Search code examples
rubychef-infradevopscookbook

Organize recipes inside a Chef cookbook


I need to install java jdk 1.8 and tomcat 7 using a Chef Cookbook.

I'm trying to create a simply cookbook that install oracle java jdk 1.8 and Tomcat 1.7 con CentOS 7 using Chef supermarket java and tomcat cookbook.

I'm using Chef DK on Windows 10 and I've downloaded it from official site (ref. https://downloads.chef.io/chefdk), and using also Vagrant and Oracle Virtualbox to create my CentOS 7 target node and for to test using kitchen create and kitchen converge commands.

I try to give you some details on my cookbook configuration .....

My environment is

Chef Development Kit Version: 3.1.0
chef-client version: 14.2.0
delivery version: master (6862f27aba89109a9630f0b6c6798efec56b4efe)
berks version: 7.0.4
kitchen version: 1.22.0
inspec version: 2.1.72

In my Berksfile I've

source 'https://supermarket.chef.io'
metadata 

My Kitchen.yml is the follow

---
driver:
  name: vagrant

provisioner:
  name: chef_zero
  # You may wish to disable always updating cookbooks in CI or other testing environments.
  # For example:
  #   always_update_cookbooks: <%= !ENV['CI'] %>
  always_update_cookbooks: true

verifier:
  name: inspec

platforms:
  - name: centos-7

suites:
  - name: default
    run_list:
      - recipe[test::default]
    verifier:
      inspec_tests:
        - test/integration/default
    attributes:

My metadata.rb is the follow

name 'test'
maintainer 'The Authors'
maintainer_email '[email protected]'
license 'All Rights Reserved'
description 'Installs/Configures test'
long_description 'Installs/Configures test'
version '0.1.0'
chef_version '>= 12.14' if respond_to?(:chef_version)

depends 'java', '~> 2.2.0'
depends 'tomcat', '~> 3.0.0'

My recipes/default.rb

node.default["java"]["install_flavor"] = "oracle"
node.default["java"]["jdk_version"]    = "8"
node.default['java']['oracle']['accept_oracle_download_terms'] = true

include_recipe "java"

tomcat_install 'tomcat7' do
  version '7.0.90'
  verify_checksum false
  exclude_examples false
  exclude_docs false
end

tomcat_service 'tomcat7' do
  action :start
end

and its attributes/recipe.rb

default['java']['install_flavor'] = 'oracle'
default['java']['jdk_version'] = '8'
default['java']['oracle']['accept_oracle_download_terms'] = true

All works fine with this cookbook organization.

I'd like to try to "refactory" this structure dividing java and tomact installation: what I try do do ...

Create a recipes/inst_jdk18.rb recipe with this content ..

node.inst_jdk18["java"]["install_flavor"] = "oracle"
node.inst_jdk18["java"]["jdk_version"]    = "8"
node.inst_jdk18['java']['oracle']['accept_oracle_download_terms'] = true

include_recipe "java"

and its attributes/inst_jdk18.rb attribute file with this content

inst_jdk18['java']['install_flavor'] = 'oracle'
inst_jdk18['java']['jdk_version'] = '8'
inst_jdk18['java']['oracle']['accept_oracle_download_terms'] = true

Create a recipes/inst_tomcat7.rb recipe with this content ..

tomcat_install 'tomcat7' do
  version '7.0.90'
  verify_checksum false
  exclude_examples false
  exclude_docs false
end

tomcat_service 'tomcat7' do
  action :start
end

and then I've modified my recipes/default.rb recipe in this way

include_recipe "inst_jdk18"
include_recipe "inst_tomcat7"

Now when I try kitchen converge command I obtain the error

 ================================================================================
 Recipe Compile Error in /tmp/kitchen/cache/cookbooks/geoserver/attributes/inst_jdk18.rb
 ================================================================================

 NoMethodError
 -------------
 undefined method `inst_jdk18' for #<Chef::Node::Attribute:0x000000000383e318>

 Cookbook Trace:
 ---------------
   /tmp/kitchen/cache/cookbooks/geoserver/attributes/inst_jdk18.rb:1:in `from_file'

 Relevant File Content:
 ----------------------
 /tmp/kitchen/cache/cookbooks/geoserver/attributes/inst_jdk18.rb:

   1>> inst_jdk18['java']['install_flavor'] = 'oracle'
   2:  inst_jdk18['java']['jdk_version'] = '8'
   3:  inst_jdk18['java']['oracle']['accept_oracle_download_terms'] = true
   4: 

Any suggestion on how to structure in right way my cookbook?


Solution

  • inst_jdk18['java']['install_flavor'] = 'oracle'
    inst_jdk18['java']['jdk_version'] = '8'
    inst_jdk18['java']['oracle']['accept_oracle_download_terms'] = true
    

    inst_jdk18 is not a method of the node object, which is what default/override/etc. in attribute files are, they define the attribute level of precedence, the same is true from node.default in recipes code.

    Just replace with default and you'll be ok.

    If you define those attributes in an attribute file, don't redefine them in the recipe, do one or the other, the recommended way for wrapper cookbooks is to use node.default in the recipe before include_recipe to have a coherent place where things are defined.

    In brief you're mixing the file name (default.rb) and attribute levels (default also), what your file is named doesn't impact the attributes levels.