We have recipe which use node attribute:
python_pip 'request_proxy' do
virtualenv '/opt/proxy/.env'
version node.default['request-proxy']['version']
Chef::Log.info('Auth request proxy #{version}')
action :install
end
Attribute is set on node level and everything is OK, but for test purposes i want to override it in my local (kitchen/vagrant) node. As first step i add attribute to my .kitchen.yml:
suites:
- name: default
run_list:
- recipe[proxy_install]
attributes: {request-proxy: {'version': '1.0.8'}}
Unfortunately node still use the "default" version. Everything works fine, without any error and completly ignores my attributes.
Later i tried add this to parameter file (chef-client -j params.json) on production node, result was the same.
What I missed? What am I doing wrong?
P.S. Chef::Log.info('Auth request proxy #{version}') is also completely ignored ??
Can you try using YAML? kitchen.yml is not a JSON file, so I'm not sure that your JSON embedded inside it would work.
attributes:
request-proxy:
version: '1.0.8'
Also, you probably should not be using node.default, unless you want to pick up the default value only (and never any overrides). If you want to use the attribute precedence (default, normal, override, force) in Chef, you should be doing:
node['request-proxy']['version']
Finally, you also have a single-quoted string with a variable. This will never work like you expect in Ruby (are you running rubocop? It would have caught this). Try it with double quotes, and remove it from the middle of your resource:
Chef::Log.info("Auth request proxy #{version}")
Related
In addition to disabling the warning, why does it happen?
use serde_json::from_str;
use serde_json::error::Result;
#[derive(Deserialize)]
pub struct Config {
#[serde(rename="cudaBlasDylibPath")]
pub cuda_blas_dylib_path: String,
}
impl Config {
pub fn new() -> Result<Config> {
from_str("{}")
}
}
src/config.rs:4:10: 4:21 warning: unused attribute, #[warn(unused_attributes)] on by default
src/config.rs:4 #[derive(Deserialize)]
Adding #[allow(unused_attributes)] doesn't help.
Here's the full output from the compiler:
src/main.rs:10:10: 10:21 warning: unused attribute, #[warn(unused_attributes)] on by default
src/main.rs:10 #[derive(Deserialize)]
^~~~~~~~~~~
src/main.rs:10:10: 10:21 note: in this expansion of #[derive_Deserialize] (defined in src/main.rs)
What this means is that the warning is within the code for the impl generated by the #[derive] attribute. However, it's hard to understand what's going on without seeing the code!
Fortunately, we can ask the compiler to show us the generated code. We need to pass additional parameters to rustc, specifically -Z unstable-options --pretty=expanded. If you're using Cargo, delete the compiled crate or run cargo clean (Cargo does nothing if the target is up to date), then run this command:
$ cargo rustc -- -Z unstable-options --pretty=expanded > src/main-expanded.rs
We can then try to compile src/main-expanded.rs with rustc. If you're using Cargo, use the command Cargo prints when you run cargo build --verbose (when the target is not up to date), but replace the name of the root source file with the new file we just generated – or you can just swap your main.rs or lib.rs with the expanded source. It might not always work, but when it does, it can provide some valuable insight.
We now get a clearer picture of the situation:
src/main-expanded.rs:17:5: 17:43 warning: unused attribute, #[warn(unused_attributes)] on by default
src/main-expanded.rs:17 #[serde(rename = "cudaBlasDylibPath")]
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/main-expanded.rs:20:1: 20:25 warning: unused attribute, #[warn(unused_attributes)] on by default
src/main-expanded.rs:20 #[automatically_derived]
^~~~~~~~~~~~~~~~~~~~~~~~
Here, the warning on the #[serde] attribute is probably caused by the fact that the struct no longer has the #[derive(Deserialize)] attribute, which is what processes the attribute. Also, it's not part of the expansion of the #[derive(Deserialize)] attribute, so that's not the attribute the original warning complained about.
It looks like the #[automatically_derived] attribute is the culprit here. This attribute appears to be used mainly by rustdoc (the documentation generation tool), but it has no meaning when compiling.
The implementation of #[derive] for derivable traits known to rustc emits the attribute like this:
let attr = cx.attribute(
self.span,
cx.meta_word(self.span,
InternedString::new("automatically_derived")));
// Just mark it now since we know that it'll end up used downstream
attr::mark_used(&attr);
My guess is that serde doesn't call the mark_used function, which is what causes the warning. The only occurrences of "automatically_derived" in serde's source code are in invocations of the quote_item! macro, which probably doesn't emit a call to mark_used (and it should probably not do it either).
Just getting started with using chef recently. I gather that attributes are stored in one large monolithic hash named node that's available for use in your recipes and templates.
There seem to be multiple ways of defining attributes
Directly in the recipe itself
Under an attributes file - e.g. attributes/default.rb
In a JSON object that's passed to the chef-solo call. e.g. chef-solo -j web.json
Given the above 3, I'm curious
Are those all the ways attributes can be defined?
What's the order of precedence here? I'm assuming one of these methods supercedes the others
Is #3 (the JSON method) only valid for chef-solo ?
I see both node and default hashes defined. What's the difference? My best guess is that the default hash defined in attributes/default.rb gets merged into the node hash?
Thanks!
Your last question is probably the easiest to answer. In an attributes file you don't have to type 'node' so that this in attributes/default.rb:
default['foo']['bar']['baz'] = 'qux'
Is exactly the same as this in recipes/whatever.rb:
node.default['foo']['bar']['baz'] = 'qux'
In retrospect having different syntaxes for recipes and attributes is confusing, but this design choice dates back to extremely old versions of Chef.
The -j option is available to chef-client or chef-solo and will both set attributes. Note that these will be 'normal' attributes which are persistent in the node object and are generally not recommended to use. However, the 'run_list', 'chef_environment' and 'tags' on servers are implemented this way. It is generally not recommended to use other 'normal' attributes and to avoid node.normal['foo'] = 'bar' or node.set['foo'] = 'bar' in recipe (or attribute) files. The difference is that if you delete the node.normal line from the recipe the old setting on a node will persist, while if you delete a node.default setting out of a recipe then when your run chef-client on the node that setting will get deleted.
What happens in a chef-client run to make this happen is that at the start of the run the client issues a GET to get its old node document from the server. It then wipes the default, override and automatic(ohai) attributes while keeping the 'normal' attributes. The behavior of the default, override and automatic attributes makes the most sense -- you start over at the start of the run and then construct all the state, if its not in the recipe then you don't see a value there. However, normally the run_list is set on the node and nodes do not (often) manage their own run_list. In order to make the run_list persist it is a normal attribute.
The choice of the word 'normal' is unfortunate, as is the choice of 'node.set' setting 'normal' attributes. While those look like obvious choices to use to set attributes users should avoid using those. Again the problem is that they came first and were and are necessary and required for the run_list. Generally stick with default and override attributes only. And typically you can get most of your work done with default attributes, those should be preferred.
There's a big precedence level picture here:
https://docs.chef.io/attributes.html#attribute-precedence
That's the ultimate source of truth for attribute precedence.
That graph describes all the different ways that attributes can be defined.
The problem with Chef Attributes is that they've grown organically and sprouted many options to try to help out users who painted themselves into a corner. In general you should never need to touch automatic, normal, force_default or force_override levels of attributes. You should also avoid setting attributes in recipe code. You should move setting attributes in recipes to attribute files. What this leaves is these places to set attributes:
in the initial -j argument (sets normal attributes, you should limit using this to setting the run_state, over using this is generally smell)
in the role file as default or override precedence levels (careful with this one though because roles are not versioned and if you touch these attributes a lot you will cause production issues)
in the cookbook attributes file as default or override precedence levels (this is where you should set most of your attributes)
in environment files as default or override precedence levels (can be useful for settings like DNS servers in a datacenter, although you can use roles and/or cookbooks for this as well)
You also can set attributes in recipes, but when you do that you invariably wind up getting your next lesson in the two-phase compile-converge parser that runs through the Chef Recipes. If you have recipes that need to communicate with each other its better to use the node.run_state which is just a hash that doesn't get written as node attributes. You can drop node.run_state[:foo] = 'bar' in one recipe and read it in another. You probably will see recipes that set attributes though so you should be aware of that.
Hope That Helps.
When writing a cookbook, I visualize three levels of attributes:
Default values to converge successfully -- attributes/default.rb
Local testing override values -- JSON or .kitchen.yml (have you tried chef_zero using ChefDK and Kitchen?)
Environment/role override values -- link listed in lamont's answer: https://docs.chef.io/attributes.html#attribute-precedence
I've got a executable target called Foobar, a static library holding some common code called FoobarCommon, and a test target specifically for the common code called FoobarCommonSpecs.
Unsurprisingly, I have made both Foobar and FoobarCommonSpecs depend on the FoobarCommon library.
The Podfile looks something like the below:
target 'FoobarCommon' do
pod 'ReactiveCocoa'
...
end
target 'Foobar' do # links against to FoobarCommon in Xcode
...
end
target 'FoobarCommonSpecs' do # links against to FoobarCommon in Xcode
pod 'LLReactiveMatchers', :git => 'https://github.com/lawrencelomax/LLReactiveMatchers.git'
end
LLReactiveMatchers is a Pod that depends on ReactiveCocoa.
Note that in this situation, ReactiveCocoa is prsent in both FoobarCommon and also in FoobarCommonSpecs
The Problem
Whenever I run FoobarCommonSpecs, I get many duplicate symbol errors for ReactiveCocoa.
I want to say to Cocoapods that it should just IGNORE LLReactiveMatcher's dependency on ReactiveCocoa. It should just let Xcode do its job and it should link with the copy of ReactiveCocoa found in FoobarCommon. How do I do that?
Does the link_with directive have anything to do with anything?
In my code I use Registry pattern like that:
$data = Registry::get('classA')->methodOfClassA($param1, param2);
Registry class stores instances of some classes in internal array, so in any place of my code I can call class methods for handy functions like in line above.
But, the problem is that PHP-storm does not autocomplete when I type:
Registry::get('classA')->
And, that is worse, it does not go to declaration of the method "methodOfClassA" when I hover mouse cursor holding mac-button (analogue of control-button on windows)
I suppose, that IDE AI is not so good to recognise cases like that, but maybe there is some tricks to do that in a hard way? hardcoding classes+method names in some file and so on...
At least, I want it to understand to go to method declaration when I click method name...
Any advices?
http://confluence.jetbrains.com/display/PhpStorm/PhpStorm+Advanced+Metadata
This link describes it all -- it is already used by multiple projects/frameworks/code-generation helpers, like Magento, for example (some other can be found mentioned in the comments of the actual ticket).
For other situations you may want to check out DynamicReturnTypePlugin plugin (Settings | Plugins | Browse repositories...) -- have not tried myself and therefore cannot comment how good/fast/laggy it is.
You can always indicate the variable type in two steps:
/** #var $foo MyClass */
$foo = $this->get('MyClass');
$foo->bar(); // autocomplete works
FIREBREATH 1.6 -- VC2010 --
No logging with FBLOG_TRACE("StaticInitialize()", "INIT-trace");
settings
outMethods.push_back(std::make_pair(FB::Log::LogMethod_File, "U:/logs/PT.log"));
...
FB::Log::LogLevel getLogLevel(){
return FB::Log::LogLevel_Trace;
...
changing "FBLOG_TRACE" to "FBLOG_INFO" logging to Logfile works. I don´t understand the reason.
function not inserted in its respective area
FB::Log::LogLevel getLogLevel(){
return FB::Log::LogLevel_Trace; // Now Trace and above is logged.
}
Discription Logging here.
Enabling logging
...
regenerate your project using the prep* scripts
open up Factory.cpp in your project. You need to define the following function inside the class definition for PluginFactory:
...
About log levels
...
If you want to change the log level, you need to define the following in your Factory.cpp:
Referring to the above that means somewhere in "Factory.cpp". that´s incorrect. The description should say -->
If you want to change the log level, you need to define the following function inside the class definition for PluginFactory:
I drag it from bottom of "Factory.cpp" to inside Class PluginFactory.
Now it works as expected !!!
The entire purpose of having different log levels (FBLOG_FATAL, FBLOG_ERROR, FBLOG_WARN, FBLOG_INFO, FBLOG_DEBUG, FBLOG_TRACE) is so that you can configure which level to use and anything below that level is hidden. The default log level in FireBreath is FB::Log::LogLevel_Info, which means that nothing below INFO (such as DEBUG or TRACE) will be visible.
You can change this by overriding FB::FactoryBase::getLogLevel() in your Factory class to return FB::Log::LogLevel_Trace.
The method you'd be overriding is: https://github.com/firebreath/FireBreath/blob/master/src/PluginCore/FactoryBase.cpp#L78
The definition of the LogLevel enum:
https://github.com/firebreath/FireBreath/blob/master/src/ScriptingCore/logging.h#L69
There was a version of FireBreath in which this didn't work; I think it was fixed by 1.6.0, but I don't remember for certain. If that doesn't work try updating to the latest on the 1.6 branch (which is currently 1.6.1 as of the time of this writing but I haven't found time to release yet)