Scoped Resources A Modest Proposal
Friday, Leschi, 10:00am
John Keiser (@jkeiser)
@jkeiser, @coderanger, et. al.
Hierarchical resources! Adding (meaningful) dots to a resource name allow us to declare new specialized resources that inherit from already-loaded resources. (John is very careful not to say 'subclass' as that has specific connotations with regard to the implementation of the idea which may or may not be compatible with Chef)
This should look familiar to those who are familiar with Poise (http://poise.io).
Example given (from butcher paper):
# recipe block is inferred from simply loading the recipe, so
# that declared resources are scoped to a single recipe by default
# in this scheme.
recipe :default do
resource :file, file do
attribute :mode, :default => '0755'
end
# this will be created with mode 0755 because of the above definition.
file "/tmp/hello_world"
contents "Hi"
end
end
# if you want to override the resource for the entire cookbook
# scope, use "cookbook" instead of "recipe" above.
The goal here is to DRY up your Chef recipes without overriding global resource defaults (which can potentially break contracts with other cookbooks).
Another example:
# cookbook my_app::aws
# attribute names are examples only.
resource :small_machine, aws.machine do
ami "some-ami-image-name"
instance_type "x-small"
end
#
# cookbook my_app::application
#
small_machine "web"
small_machine "db"
# etc.
# another means of invocation:
aws.machine.small_machine "cache"
One problem raised: What happens if you override all the defaults for a cookbook-scoped resource in one recipe in the cookbook? What happens to the other resources declared earlier in scope? (Answer: This is evaluated at compile-time, so whatever happens first in compile order goes.)
Another: What about LWRPs? (Answer: They run in a different context and therefore won't be overridden.)
Q: Would there be cases where you'd then build resources that are intentionally "fuzzy" and not intended to be used directly without being scoped?
A: Hadn't thought of that, but possibly.
Q: How would you implement a library cookbook?
A: (Not answered in detail.)
Q: Is this putting a greater cognitive load on newcomers by having "library recipes?"
A: (Under debate. The bigger load may actually be on existing Chef users...)
Example goal: I want to write a cookbook for working with GitHub.
#github cookbook:
resource :github
attribute :api_token # ...
attribute :web_url # ...
resource :organization
# inherits github endpoint attributes from parent
resource :repository
# inherits organization name and other attributes
attribute :name
attribute :description
resource :issue
attribute :id
attribute :long_desc
end
end
end
end
opscode = github.organization("opscode")
opscode do
repository("chef") do
issue 1, :long_desc => "blah"
issue 2, :long_desc => "foo"
end
end
Next steps are basically for more people to take a look at this and shoot holes in the idea. It's likely that my notes aren't capturing the idea and conversation precisely.