Chef error on attributes- string not matched - ruby

I cannot seem to get around a chef error that deals with similarly named attributes in my attributes/default.rb file.
I have 2 attributes:
default['test']['webservice']['https']['keyManagerPwd'] = 'password'
...
...
default['test']['webservice']['https']['keyManagerPwd']['type'] = 'encrypted'
Notice that, up until the last bracket (['type']), the names are identical.
I am referencing these attributes in a template and in a template block in the recipe. When I go to run it, I receive this error:
==================================================[0m
I, [2015-01-28T13:36:43.668692 #7920] INFO -- core-14-2-centos-65:
[31mRecipe Compile Error
in /tmp/kitchen/cache/cookbooks/avx/attributes/default.rb[0m
I, [2015-01-28T13:36:43.669192 #7920] INFO -- core-14-2-centos-65:
=================================================================[0m
I, [2015-01-28T13:36:43.669192 #7920] INFO -- core-14-2-centos-65:
I, [2015-01-28T13:36:43.669692 #7920] INFO -- core-14-2-centos-65:
[0mIndexError[0m
I, [2015-01-28T13:36:43.669692 #7920] INFO -- core-14-2-centos-65: -------
--[0m
I, [2015-01-28T13:36:43.669692 #7920] INFO -- core-14-2-centos-65: string not matched[0m
I, [2015-01-28T13:36:43.670192 #7920] INFO -- core-14-2-centos-65:
I, [2015-01-28T13:36:43.670192 #7920] INFO -- core-14-2-centos-65:
[0mCookbook Trace:[0m
I, [2015-01-28T13:36:43.670692 #7920] INFO -- core-14-2-centos-65: --------[0m
I, [2015-01-28T13:46:05.101875 #8332] INFO -- core-14-2-centos-65:
[0m113>> default['webservice']['https']['keyManagerPwd']['type'] =
'encrypted'
It seems as if Chef cannot distinguish between 2 attributes when the only differentiation is the ending.
If I modify the same attributes by placing some unique text at the front of the name, there is not issue with the recipe at all:
default['test']['1']['webservice']['https']['keyManagerPwd'] = 'password'
...
...
default['test']['2']['webservice']['https']['keyManagerPwd']['type'] = 'encrypted'
By putting the ['1'] and ['2'] there, it solves the problem.
I am fairly new to Chef so I'm thinking its just something simple I'm overlooking. Does anyone have any ideas or suggestions? Thanks.

Simple answer: You cannot do this. That's not a Chef problem, nor a ruby problem - it's a general problem of like most programming languages.
Let's use foo as a variable instead of the lengthy default['test']['webservice']['https']['keyManagerPwd'].
What you effectively do is
1: foo = "password"
2: foo['type'] = "encrypted"
In line 1, foo is a string. In line 2, it is treated as hash (called array in some other languages). The second line automatically overwrites your foo = "password" assignment. It's effectively the same as
1: foo = "password"
2: foo = {}
3: foo['type'] = "encrypted"
The alternative would be to use
foo['something'] = "password"
foo['type'] = "encrypted"
Or translated to your code:
default['test']['webservice']['https']['keyManagerPwd']['something'] = 'password'
default['test']['webservice']['https']['keyManagerPwd']['type'] = 'encrypted'
This should work.

Related

The "error_marshaling_enabled" setting seems to be always enabled

When I run this code:
$client->evaluate('
box.session.settings.error_marshaling_enabled = false
box.error{code = 42, reason = "Foobar", type = "MyError"}
');
regardless of the value of error_marshaling_enabled I always get a response with a new (extended) error format:
[
49 => 'Foobar',
82 => [
0 => [
0 => [
0 => 'CustomError',
2 => 3,
1 => 'eval',
3 => 'Foobar',
4 => 0,
5 => 42,
6 => [
'custom_type' => 'MyError',
],
],
],
],
],
Why is that?
Short answer.
error_marshaling_enabled option affects only how error objects are encoded in response body (48, IPROTO_DATA). It does not affect how they are returned as exceptions, in the response header (82, IPROTO_ERROR).
Long answer.
In Tarantool an error object can be returned in 2 ways: as an exception and as an object. For example, this is how to throw an error as exception:
function throw_error()
box.error({code = 1000, reason = "Error message"})
-- Or
error('Some error string')
end
This is how to return it as an object:
function return_error()
return box.error.new({code = 1000, reason = "Error message"})
end
If the function was called remotely, using IPROTO protocol via a connector like netbox, or PHP connector, or any other one, the error return way affects how it is encoded into MessagePack response packet. When the function throws, and the error reaches the top stack frame without being caught, it is encoded as IPROTO_ERROR (82) and IPROTO_ERROR_24 (49).
When the error object is returned as a regular value, not as an exception, it is encoded also as a regular value, inside IPROTO_DATA (48). Just like a string, a number, a tuple, etc.
With encoding as IPROTO_ERROR/IPROTO_ERROR_24 there is no much of a configuration space. Format of these values can't be changed. IPROTO_ERROR is always returned as a MessagePack map, with a stack of errors in it. IPROTO_ERROR_24 is always an error message. The IPROTO_ERROR_24 field is kept for compatibility with connectors to Tarantool versions < 2.4.1.
With encoding as a part of IPROTO_DATA you can choose serialization way using error_marshaling_enabled option. When it is true, errors are encoded as MessagePack extension type MP_EXT, and contain the whole error stack, encoded exactly like IPROTO_ERROR value. When the option is false (default behaviour in 2.4.1), the error is encoded as a string, MP_STR, which is the error's message. If there is a stack of errors, only the newest error is encoded.
error_marshaling_enabled option exists for backward compatibility, in case your application on Tarantool wants to be compatible with old connectors, which don't support MP_EXT encoded errors.
In Tarantool < 2.4.1 errors were encoded into result MessagePack as a string with error message, and error stacks didn't exist at all. So when the new format and the error stacks feature were introduced, making the new format default would be a too radical change breaking the old connectors.
Consider these examples of how error marshaling affects results. I use Tarantool 2.4.1 console here, and built-in netbox connector. The code below can be copy pasted into the console.
First instance:
box.cfg{listen = 3313}
box.schema.user.grant('guest', 'super')
function throw_error()
box.error({code = 1000, reason = "Error message"})
end
function return_error()
return box.error.new({code = 1000, reason = "Error message"})
end
Second instance:
netbox = require('net.box')
c = netbox.connect(3313)
Now I try to call the function on the second instance:
tarantool> c:call('throw_error')
---
- error: Error message
...
The c:call('throw_error') threw an exception. If I catch it using pcall() Lua function, I will see the error object.
tarantool> ok, err = pcall(c.call, c, 'throw_error')
tarantool> err:unpack()
---
- code: 1000
base_type: ClientError
type: ClientError
message: Error message
trace:
- file: '[string "function throw_error()..."]'
line: 2
...
As you can see, I didn't set error_marshaling_enabled, but got the full error. Now I will call the other function, without exceptions. But the error object won't be full.
tarantool> err = c:call('return_error')
tarantool> err
---
- Error message
...
tarantool> err:unpack()
---
- error: '[string "return err:unpack()"]:1: attempt to call method ''unpack'' (a nil
value)'
...
The error was returned as a mere string, error message. Not as an error object. Now I will turn on the marshaling:
tarantool> c:eval('box.session.settings.error_marshaling_enabled = true')
---
...
tarantool> err = c:call('return_error')
---
...
tarantool> err:unpack()
---
- code: 1000
base_type: ClientError
type: ClientError
message: Error message
trace:
- file: '[C]'
line: 4294967295
...
Now the same function returned the error in the new format, more featured.
On the summary: error_marshaling_enabled affects only returned errors. Not thrown errors.

YML syntax error

I want to have a multi-line bit of markdown java in a yam file. I tried many things but I guess I don't quite get the quoting rules of Yaml.
{
title: Museum,
body: |
"```java
code code code
java2",
answers: [
"`museum`",
"`museum.getFloor(3)`",
"`museum.getFloor(3).getExhibit(5)`",
"`museum.getFloor(3).getExhibit(5).getCurator()`",
"`museum.getFloor(3).getExhibit(5).getCurator().name`",
"`museum.getFloor(3).getExhibit(5).getCurator().name.toUpper()`"
]
}
Produces:
/Users/pitosalas/.rbenv/versions/2.3.1/lib/ruby/2.3.0/psych.rb:377:in `parse': (generator/test.yml): found character that cannot start any token while scanning for the next token at line 3 column 9 (Psych::SyntaxError)
YAML has two styles: the JSON like flow style and the much better human readable block style.
Roughly speaking you can have nested structures each style nested within itself and can have flow style nested within block style, but block style nested within flow style is not allowed.
Your to level { and } are flow style but you try to introduce, with |, a literal block style scalar within that flow style. Replace the flow style with block style upwards from that scalar:
title: Museum
body: |
"```java
code code code
java2"
answers: [
"`museum`",
"`museum.getFloor(3)`",
"`museum.getFloor(3).getExhibit(5)`",
"`museum.getFloor(3).getExhibit(5).getCurator()`",
"`museum.getFloor(3).getExhibit(5).getCurator().name`",
"`museum.getFloor(3).getExhibit(5).getCurator().name.toUpper()`"
]
and your YAML is fine. Note that the double quotes "around" the value for the key body are not going to be stripped when loading, maybe that is not what you intended.
You should IMO not leave out the trailing , after the last value in the (flow style) sequence that is the value for answers. This will certainly lead to errors when you extend the list and forget to put in the trailing comma on the line above.
I would personally go for block style all the way:
title: Museum
body: |
"```java
code code code
java2"
answers:
- "`museum`"
- "`museum.getFloor(3)`"
- "`museum.getFloor(3).getExhibit(5)`"
- "`museum.getFloor(3).getExhibit(5).getCurator()`"
- "`museum.getFloor(3).getExhibit(5).getCurator().name`"
- "`museum.getFloor(3).getExhibit(5).getCurator().name.toUpper()`"
When dealing with YAML file generation that is convoluted or complex, or when it's not working as I expect, I revert to letting Ruby show me the way:
require 'yaml'
body = <<EOT
"```java
code code code
java2
"
EOT
answers = %w(
`museum`
`museum.getFloor(3)`
`museum.getFloor(3).getExhibit(5)`
`museum.getFloor(3).getExhibit(5).getCurator()`
`museum.getFloor(3).getExhibit(5).getCurator().name`
`museum.getFloor(3).getExhibit(5).getCurator().name.toUpper()`
)
obj = {
"title" => "Museum",
"body" => body,
"answers" => answers
}
puts obj.to_yaml
Which, in this case, outputs:
---
title: Museum
body: |
"```java
code code code
java2
"
answers:
- "`museum`"
- "`museum.getFloor(3)`"
- "`museum.getFloor(3).getExhibit(5)`"
- "`museum.getFloor(3).getExhibit(5).getCurator()`"
- "`museum.getFloor(3).getExhibit(5).getCurator().name`"
- "`museum.getFloor(3).getExhibit(5).getCurator().name.toUpper()`"
If you then pass that YAML back into the parser, you should get the original data structure back:
YAML.load(obj.to_yaml)
# => {"title"=>"Museum",
# "body"=>"\"```java\n" +
# "code code code\n" +
# "java2\n" +
# "\"\n",
# "answers"=>
# ["`museum`",
# "`museum.getFloor(3)`",
# "`museum.getFloor(3).getExhibit(5)`",
# "`museum.getFloor(3).getExhibit(5).getCurator()`",
# "`museum.getFloor(3).getExhibit(5).getCurator().name`",
# "`museum.getFloor(3).getExhibit(5).getCurator().name.toUpper()`"]}

Elastic Beanstalk and Rails – initializing multiple times?

When I deploy my RoR (4.2.6) application to ElasticBeanstalk, it appears that the initialization process is getting run four times. This is impacting the way I rely on a singleton instance of a job Scheduler object (using Rufus Scheduler).
In a couple of initializer files and in application.rb, I added a few log statements:
Here:
# /config/initializers/scheduler.rb
require 'rufus-scheduler'
::Rufus_lockfile = "/tmp/.rufus-scheduler.lock"
::Scheduler = Rufus::Scheduler.singleton(
:lockfile => Rufus_lockfile
)
Rails.logger.info "1: started Scheduler #{Scheduler.object_id}"
And here:
# /config/initializers/cookies_serializer.rb
Rails.logger.info "2: some other initializer"
And here:
# /config/application.rb
require File.expand_path('../boot', __FILE__)
require 'rails/all'
Bundler.require(*Rails.groups)
module MyApp
class Application < Rails::Application
...
config.after_initialize do
Rails.logger.info "3: after app is initialized"
end
end
end
After I run eb deploy and it completes, this is what I see at the top of app/log/production.log:
I, [2016-05-31T10:31:08.756302 #18753] INFO -- : 2: some other initializer
I, [2016-05-31T10:31:08.757252 #18753] INFO -- : 1: started Scheduler 47235057343600
I, [2016-05-31T10:31:08.896353 #18753] INFO -- : 3: after app is initialized
I, [2016-05-31T10:31:23.669517 #18817] INFO -- : 2: some other initializer
I, [2016-05-31T10:31:23.670380 #18817] INFO -- : 1: started Scheduler 46989489069800
I, [2016-05-31T10:31:23.806154 #18817] INFO -- : 3: after app is initialized
D, [2016-05-31T10:31:23.969103 #18817] DEBUG -- : ^[[1m^[[36mActiveRecord::SchemaMigration Load (1.3ms)^[[0m ^[[1mSELECT "schema_migrations".* FROM "schema_migrations"^[[0m
I, [2016-05-31T10:31:33.108449 #18897] INFO -- : 2: some other initializer
I, [2016-05-31T10:31:33.109513 #18897] INFO -- : 1: started Scheduler 47156425207060
I, [2016-05-31T10:31:33.116500 #18901] INFO -- : 2: some other initializer
I, [2016-05-31T10:31:33.117374 #18901] INFO -- : 1: started Scheduler 47156425216940
I, [2016-05-31T10:31:33.790266 #18901] INFO -- : 3: after app is initialized
I, [2016-05-31T10:31:33.844517 #18897] INFO -- : 3: after app is initialized
So it looks like the initializer files and even the code in my after_initializer block are getting run four times... and I can't figure out why.
Question got asked on rufus-scheduler issue system, answered there: https://github.com/jmettraux/rufus-scheduler/issues/208

Checking if a key exists in a Hbase table affects subsequent get call

I'm sure am overlooking something in the snippet below, but I can't figure out what. As indicated, if I include a call to 'exists' to quickly check if the key exists in table, the subsequent 'get' ends up returning nothing; commenting out the 'exists' call, however, makes the code work. But, now I have to do additional checks before parsing the result fetched from Hbase to make sure it is not empty/null.
...
final Get g = new Get(someKey);
g.setCacheBlocks(true);
g.setMaxVersions(1);
g.addColumn(colFamily, colName);
/* --- THIS DOES NOT WORK --- */
if (this.someHbaseTab.exists(g)) {
final Result res = this.someHbaseTab.get(g);
// res is empty!!!
}
// --- --- ---
/* --- THIS WORKS --- */
// No call to 'exists'
final Result res = this.someHbaseTab.get(g);
// Valid result
// --- --- ---
...
I'm running Cloudera CDH5.
You do not have to call exists. Just check res.isEmpty() after the get() call

Calling Sinatra from Sinatra produces results different from external request

Following my question here.
So I am trying to do a smart redirect using this:
get "/category/:id/merge" do
#... setting #catalog_id and category
call env.merge("PATH_INFO" => "/catalog/#{#catalog_id}/category/#{category.id}", "REQUEST_METHOD"=>"PATCH","QUERY_STRING"=>"merge=1")
status 200
end
But when I look in logs, I see something that is not only frustrating but also completely absurd:
# this one is from internal call
I, [2013-03-21T15:55:54.382153 #29569] INFO -- : Processing GET /catalog/1/category/2686/merge
I, [2013-03-21T15:55:54.382239 #29569] INFO -- : Parameters: {}
...
I, [2013-03-21T15:55:54.394992 #29569] INFO -- : Processing PATCH /catalog/1/category/2686
I, [2013-03-21T15:55:54.395041 #29569] INFO -- : Parameters: {"merge"=>"1"}
I, [2013-03-21T15:55:54.395560 #29569] INFO -- : Processed PATCH /catalog/1/category/2686?merge=1 with status code 404
I, [2013-03-21T15:55:54.395669 #29569] INFO -- : Processed GET /catalog/1/category/2686/merge with status code 200
# this one is a direct request
I, [2013-03-21T15:56:36.246535 #29588] INFO -- : Processing PATCH /catalog/1/category/2686
I, [2013-03-21T15:56:36.246629 #29588] INFO -- : Parameters: {"merge"=>"1"}
...
I, [2013-03-21T15:56:36.286216 #29588] INFO -- : Processed PATCH /catalog/1/category/2686?merge=1 with status code 204
And the body of internal 404 request is just Sinatra's standard 404 error page. How the hell can he tell me straight in the eye that he doesn't know this route if I caught him serving exactly the same URL with acceptable 204?
UPDATE
It gets even more exciting when I change REQUEST_METHOD to GET - works like a charm.
I, [2013-03-21T17:09:37.718756 #3141] INFO -- : Processing GET /catalog/1/category/2686/merge
I, [2013-03-21T17:09:37.718838 #3141] INFO -- : Parameters: {}
...
I, [2013-03-21T17:09:37.735632 #3141] INFO -- : Processing GET /catalog/1/category/2686
I, [2013-03-21T17:09:37.735678 #3141] INFO -- : Parameters: {"merge"=>"1"}
...
I, [2013-03-21T17:09:37.773033 #3141] INFO -- : Processed GET /catalog/1/category/2686?merge=1 with status code 200
I, [2013-03-21T17:09:37.773143 #3141] INFO -- : Processed GET /catalog/1/category/2686/merge with status code 200

Resources