Search code examples
rubychef-infrachef-recipecookbooklwrp

What are attribute methods of a Chef LWRP and what can I pass them?


I have the following attribute in a chef resource:

attribute :attribName, kind_of: String, name_attribute: true, default: 'big string sldkjslkdflksdksdlkff'

I want to break this up so it looks nice, so I did this:

attribute [
  :attribName,
  kind_of: String,
  name_attribute: true,
  default: 'big string sldkjslkdflksdksdlkff'
]

But I get an error when converging:

   NoMethodError
   -------------
   undefined method `to_sym' for #<Array:0x00000004a63b60>
   Did you mean?  to_s
           to_yaml
           to_set

   Platform:
   ---------
   x64-mingw32    

   Running handlers:
   [2016-10-01T19:07:39-07:00] ERROR: Running exception handlers
   Running handlers complete
   [2016-10-01T19:07:39-07:00] ERROR: Exception handlers complete
   Chef Client failed. 0 resources updated in 11 seconds
   [2016-10-01T19:07:39-07:00] FATAL: Stacktrace dumped to C:/Users/ADMINI~1/AppData/Local/Temp/kitchen/cache/chef-stacktrace.out
   [2016-10-01T19:07:39-07:00] FATAL: Please provide the contents of the stacktrace.out file if you file a bug report
   [2016-10-01T19:07:39-07:00] FATAL: NoMethodError: undefined method `to_sym' for #<Array:0x00000004a63b60>
   Did you mean?  to_s
           to_yaml
           to_set

So I thought attributes in resource files were just methods that accepted an array of arguments and passing [..args..] to it was the same thing. Why doesn't this work? I think I'm confused about what type of ruby object attributes are in this context and what their behavior is.


Solution

  • The attribute method is trying to symbolize the first argument, which is the name of the attribute. The second argument seems like a hash of options, so the method signature should look something like this: def attribute(name, options={}). You sent an Array as the first argument when you wrapped everything inside brackets.

    Try reformatting it like this:

    attribute :attribName,
      kind_of: String,
      name_attribute: true,
      default: 'big string sldkjslkdflksdksdlkff'
    

    If you really don't that first argument in the same like, you can use splat(I don't like this at all):

    attribute *[
      :attribName,
      {
        kind_of: String,
        name_attribute: true,
        default: 'big string sldkjslkdflksdksdlkff'
      }
    ]
    

    That will turn the array elements into arguments.