Note: Please go to docs.rightscale.com to access the current RightScale documentation set. Also, feel free to Chat with us!
Home > Guides > Chef Cookbooks Developer Guide > End User > Getting Started > Intermediate 2 Chef Tutorial

Intermediate 2 Chef Tutorial

Prerequisites

  • RightScale account with valid AWS credentials
  • 'designer', 'actor', 'library', 'server_login', 'security_manager' user role privileges
  • Access to a GitHub account where you have read/write privileges.  If you do not have your own GitHub account, see Create a GitHub Account.
  • Completion of the Intermediate 1 Chef Tutorial

Overview

In this tutorial you will learn about the following topics:

  • Create a static Chef attribute
  • Create a dynamic Chef attribute that will appear as a user-defineable input in the RightScale platform
  • Create examples of the different types of inputs (required, recommended, and optional)


You will reuse the basic Chef development environment that you used in the Intermediate 1 tutorial, except this time, when you will launch the Chef Development Server, you will automatically download code from the cookbook repository that you set up in the previous tutorial.

diag-Chef_Dev_Environment-v2.png

Steps

Set up the Chef Development Environment

Clone the Deployment

Clone the deployment that you used in the Intermediate 1 Chef Tutorial and rename it. (e.g. Intermediate 2 Chef Tutorial)

Launch the Chef Development Server

  1. Launch the "Chef Development Server" in the new deployment.
  2. You should have inherited the required Git inputs from your previous setup. However, since you already have a cookbook repository, you are going to launch this server so that it automatically retrieves and loads the contents of your repository to the /opt/development directory. At the input confirmation page, click the "Advanced" link under the Git category and set the following inputs.
    • Git Branch - Since you are going to add new recipes to the repository, set this input to the 'master' branch. (e.g. text: master)
    • Git Repository - Enter the URL to the source repository that contains the cookbooks that you're currently developing. The specified URL must support 'read+write' access. (e.g. text:https://github.com/username/repository)
  3. Click Save and Launch button.

Launch the Chef Test Server

  1. Launch the "Chef Test Server" in the deployment. It's important that you launch the "Test" server using the editable HEAD version of the cloned Base ServerTemplate so that you can easily test the new recipes that you're going to create later in this tutorial. In a few minutes you will have a basic Chef development environment.
    screen-DeploymentServers-v1.png

Create a Static Attribute

Create a Cookbook and Recipe

  1. SSH into the running "Development" server and switch to the root user.
    1. # sudo -i
  2. Navigate to where the contents of your repository are locally stored on the instance. The scripts in the ServerTemplate checked out the "master" branch of your repository.
    • # cd /opt/development/cookbooks
  3. Use the following knife command to create a new cookbook called 'about_me' in the cookbooks directory.  Run the list command to see all of your cookbooks.
    • # knife cookbook create about_me -o /opt/development/cookbooks
      ** Creating cookbook about_me
      ** Creating README for cookbook: about_me
      ** Creating CHANGELOG for cookbook: about_me
      ** Creating metadata for cookbook: about_me
      
      # ls
      about_me  intermediate  README.md
      
  4. Go into the 'about_me' cookbook.
    • # cd about_me
      
      # ls
      attributes   files      metadata.rb  README.md  resources
      definitions  libraries  providers    recipes    templates
  5. Next, you are going to create a new attribute. Typically, you would add attributes that you want to make available to all resources (e.g. recipes) in a cookbook's 'attributes' directory. Go into the 'attributes' directory now. Create a new file called 'me.rb' with the following line of code and save the file (Ctrl + d). In this example, you are defining several Chef attributes ('first_name', 'food', 'drink', and 'water') in the 'about_me' cookbook and hard-coding a default value for each variable. If possible, create short attribute names by using hashes to help you group and categorize your inputs. (e.g. [:cookbook_name][:category1][:group1])

    Notice the different ways of defining a Chef attribute. The 'set' option is useful for defining an attribute that will never change. (e.g. your name) However, if you use the 'default' method (which replaces the old 'set_unless' method), you'll be able to easily change it into a user-definable input by modifying the metadata, which you will do as a step later in this tutorial. Most of the default attributes in RightScale's own cookbooks use the 'set_unless' method so that our users have the flexibility of converting a static attribute into a user-definable input.
    • # cd attributes
      
      # cat > me.rb
      set[:about_me][:first_name] = "<INSERT_YOUR_NAME_HERE>"
      default[:about_me][:favorite][:food] = "pizza"
      default[:about_me][:favorite][:drink] = "water"
      default[:about_me][:favorite][:hobby] = "running"
      
  6. Now you can use the defined attributes in a Chef resource such as a recipe. First, update the 'default.rb' recipe in the 'about_me' cookbook.
    1. # cd ..
      # ls
      attributes   files      metadata.json  providers  recipes    templates
      definitions  libraries  metadata.rb    README.md  resources
      
      # cd recipes
      # vi default.rb
  7. Add the following lines of code to the default recipe. In this example, declare the use of four variables ('first_name', 'food', 'drink', and 'hobby') and create a simple log statement that prints each variable.  Save the changes and exit the editor. (Esc, Shift+q, wq)
    1. rightscale_marker
      
        first_name = node[:about_me][:first_name]
        food = node[:about_me][:favorite][:food]
        drink = node[:about_me][:favorite][:drink]
        hobby = node[:about_me][:favorite][:hobby]
        
        log "Hi, my name is #{first_name} and I like #{food}, #{drink} and #{hobby}."
      
  8. The next step is to update the Chef metadata because you modified the contents of the cookbook. Edit the metadata.rb file in the 'about_me' cookbook.
    • # cd ..
      # vi metadata.rb
  9. Add the following lines of code to describe the modified default recipe. Since you hard coded a static value for the 'first_name' attribute, it does not need to be described in the metadata. Save and exit.
    • maintainer       "YOUR_COMPANY_NAME"
      maintainer_email "YOUR_EMAIL"
      license          "All rights reserved"
      description      "Installs/Configures about_me"
      long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
      version          "0.0.1"
      
      depends "rightscale"
      
      recipe "about_me::default","Prints my first name and several of my favorite things as output."
      
  10. Add and commit the changes. Then push the changes to your repository. You may need to authenticate the push to your repository by entering your Git username and password.
    • # git add /opt/development/cookbooks
      # git commit -m "Added the about_me cookbook"
      [master 4cc747d] Added the about_me cookbook
       5 files changed, 120 insertions(+)
       ​create mode 100644 cookbooks/about_me/CHANGELOG.md
       create mode 100644 cookbooks/about_me/README.md
       create mode 100644 cookbooks/about_me/attributes/me.rb
       create mode 100644 cookbooks/about_me/metadata.rb
       create mode 100644 cookbooks/about_me/recipes/default.rb
      
      # git push origin
      Username for 'https://github.com': username
      Password for 'https://username@github.com': password
      To https://github.com/username/repository
         2c16ba1..a560982  master -> master
  11. Go to your repository on GitHub to see the 'about_me' cookbook in your repository.

Refetch and Import

Now that you pushed new code to GitHub, you need to update your RightScale account so that you have access to the latest version of your cookbook in your ServerTemplate.

  1. Go to Design Repositories.
  2. Find and click on the repository that you created earlier. (e.g. Chef Tutorial)
  3. Click the Refetch and Import button, which refetches the latest code from your GitHub repository and updates the cached version in RightScale's Repose service and imports all of the cookbooks from the repository into your RightScale account.
    screen-Refetch_Import-v1.png
  4. Wait for the refreshing of the repository to be 100% complete before proceeding to the next step. You want make sure that the cached copy of the cookbook in Repose reflects your most recent change and matches the version in your source repository (e.g. GitHub). You can track the progress of the refetch action under the Events pane. 
    screen-Refetch_Event-v1.png

Attach a Cookbook to the ServerTemplate

  1. Go the Scripts tab of the editable HEAD version of the "Test" ServerTemplate.
  2. Click Modify.
  3. Click Attach Cookbooks.
  4. Find and select the 'about_me' cookbook and click Attach Selected.
  5. Drag and drop the "default" Chef recipe (e.g. about_me::default) from the attached cookbook into the Operational Scripts list.
    screen-AddDefaultScript-v2.png

Test the Chef Recipe

The next step is to test the script on your "Test" server.

 

  1. Go to the current "Test" server's Scripts tab and run the "default" Chef recipe of the 'about_me' cookbook. 
  2. Go to the "Test" server's Audit Entries tab to view the output. Wait for the script to be successfully executed (e.g. completed: intermediate::default) and then click on the audit entry.
  3. Now you're going to test the script on the running "Test" server. Go to the Scripts tab of the running "Test" server (that you created with that ServerTemplate) and run the 'about_me::default' operational script. Remember, since you previously hard-coded values for the attributes in an earlier step, you will not be prompted to provide values for your first name or any of your favorite things.
    screen-RunDefaultScriptNoInput-v1.png
  4. Once the execution of the script is complete, go to the server's Audit Entries tab and view the output. In this example, you hard-coded values for attributes. In the next section you will learn how to parameterize an attribute so that it becomes a user-definable input.
    screen-AuditRunning-v3.png

Create a Dynamic Attribute (Input)

Create a Cookbook and Recipe

You can also create dynamic Chef attributes that will appear as user-definable inputs in the RightScale dashboard. If you are accustomed to using Chef with Chef Server, inputs are RightScale's version of Role Attributes.

  1. First, create a new cookbook called 'about_city' in your cookbooks directory.
    • # knife cookbook create about_city -o /opt/development/cookbooks
      ** Creating cookbook about_city
      ** Creating README for cookbook: about_city
      ** Creating CHANGELOG for cookbook: about_city
      ** Creating metadata for cookbook: about_city
      
  2. Navigate to the 'recipes' directory of the 'about_city' cookbook. Instead of modifying the existing 'default.rb' recipe, create a new recipe called 'my_city.rb' and save the file. (Ctrl + d)
    • # cd /opt/development/cookbooks
      # ls
      about_city  about_me  Chef  README.md
      # cd about_city/recipes
      # ls 
      default.rb
      # cat > my_city.rb
      
  3. Open the file in a vi editor.
    • # ls
      default.rb  my_city.rb
      
      # vi my_city.rb
      
  4. Add the following lines of code. In this example, you are going to define Chef attributes inside of a Chef recipe instead of inside the cookbook's 'attributes' directory. These attributes are also different because they are going to be dynamic attributes that will appear as user-definable inputs in the RightScale dashboard (under the Inputs tab). For this example, you're going to create three attributes to demonstrate the three different types of inputs that are supported: required, recommended, and optional. Save the changes and exit the editor. (Esc, Shift+q, wq)
    • rightscale_marker
      
        city_name = node[:about_city][:city_name]
        temperature = node[:about_city][:temperature]
        rain = node[:about_city][:rain]
        
        log "I live in #{city_name}. The current temperature is #{temperature} degrees. And if you're wondering if you need an umbrella, the answer is #{rain}."
      
  5. Before you update the metadata, you must first properly describe each input in the metadata so that the RightScale platform will know about the attributes and how to use them. Edit the 'metadata.rb' file in the 'about_city' cookbook.
    • # cd ..
      # vi metadata.rb
  6. Add the following lines of code (highlighted in green). If an attribute does not include the ':required' field, it will be treated as an 'optional' input (default). As a best practice, it's recommended that you always explicitly add a value for the ":required" field. See the last example below.(:required => "optional",)
    • name             'about_city'
      maintainer       'YOUR_COMPANY_NAME'
      maintainer_email 'YOUR_EMAIL'
      license          'All rights reserved'
      description      'Installs/Configures about_city'
      long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
      version          '0.1.0'
      
      depends "rightscale"
      
      recipe "about_city::my_city","Information about my city"
      
      # Required Input #
      attribute "about_city/city_name",
         :display_name => "City Name",
         :description => "The city where I currently live.",
         :required => "required",
         :recipes => ["about_city::my_city"]
      
      # Recommended Input #
      attribute "about_city/rain",
         :display_name => "Raining",
         :description => "Is it raining? Yes or No",
         :required => "recommended",
         :choice => ["yes", "no"],
         :default => "no",
         :recipes => ["about_city::my_city"]                                       
        
      # Optional Input #
      attribute "about_city/temperature",
         :display_name => "Temperature",
         :description => "Current temperature in the city",
         :required => "optional",
         :recipes => ["about_city::my_city"]
      
  7. Save your changes and exit the editor. (Esc, Shift+q, wq)
  8. Add all of your changes. In this example, you only added a new recipe. (about_city::my_city)
    • # git add /opt/development/cookbooks
  9. Commit your changes and push them to your repository. Enter your username and password for authentication purposes.
    • # git commit -m "Added about_city cookbook"
      [master 4b46e97] Added about_city cookbook
      5 files changed, 133 insertions(+)
      create mode 100644 cookbooks/about_city/CHANGELOG.md
      create mode 100644 cookbooks/about_city/README.md
      create mode 100644 cookbooks/about_city/metadata.rb
      create mode 100644 cookbooks/about_city/recipes/default.rb
      create mode 100644 cookbooks/about_city/recipes/my_city.rb
      
      # git push origin
  10. Go to your repository on GitHub to see the 'about_city' cookbook in your repository.

Refetch and Import

Now that you pushed new code to GitHub, you need to update your RightScale account so that you have access to the latest version of your cookbook in your ServerTemplate.

  1. Go to Design > Repositories.
  2. Find and click on the repository that you created earlier. (e.g. Chef Tutorial)
  3. Click the Refetch and Import button to update Repose with the most recent changes to your source repository.

Attach a Cookbook to the ServerTemplate

  1. Go the Scripts tab of the editable HEAD version of the "Test" ServerTemplate.
  2. Click Modify.
  3. Click Attach Cookbooks.
  4. Find and select the 'about_city' cookbook and click Attach Selected.
  5. Drag and drop the "default" Chef recipe (e.g. about_city::default) from the attached cookbook into the Operational Scripts list.

Test the Chef Recipe

The next step is to test the new 'my_city' script on your "Test" server.

  1. Go to the current "Test" server's Scripts tab and run the "default" Chef recipe of the 'about_city' cookbook.
  2. Now you're going to test the script on the running "Test" server. Go to the Scripts tab of the running "Test" server (that you created with that ServerTemplate) and run the 'about_city::default' operational script. Remember, since you previously hard-coded values for the attributes in an earlier step, you will not be prompted to provide values for your first name or any of your favorite things.
  3. Go to the Scripts tab of the running "Test" server (that you created with that ServerTemplate) and run the 'about_city::my_city' script.
    screen-RunMyCityScript-v1.png
  4. Since the new script uses inputs for variable substitution, you will need to provide values for the missing inputs and click Continue to run the script.
    screen-SetInputs-v1.png
    This particular script shows an example of each type of input.
    • required - ('city_name') An input that requires a value to be specified in order to successfully run the script. You cannot specify a default value for a required input. Any required inputs that do not have a value specified will be highlighted in red.
      • Example: Text:Santa Barbara
    • recommended -  ('rain') An input that requires a value to be specified, however it's predefined with an acceptable default value that you can safely use or change as necessary. In this example, there is a dropdown menu because you predefined two choices (yes, no) with "no" as the default value. Note: Since input inheritance is only applied at boot time when a server is launched, the running server will not have "no" pre-selected as the default value even though it's defined as such in the metadata. Select a value for the input.
      • Example: Text:yes
    • optional - ('temperature') An input that does not require a value to be specified in order for the script to run successfully. Optional inputs can be left blank/unset. By default, optional inputs will be hidden under the "Advanced" section. You will need to click the "Show advanced inputs" text link to view all optional inputs.
      • Example: Text:68
  5. Once the execution of the script is complete, go to the server's Audit Entries tab and view the output.
    screen-AuditDynamicAttribute-v4.png
     
  6. (Optional) Relaunch the server and re-run the 'about_city::my_city' script again to see the default value of "no" pre-selected for the recommended ('rain') input because it will take effect at launch time as a result of the input inheritance rules.

Convert a Static Attribute into an Input

At the beginning of this tutorial you hard-coded a few inputs. Next, you are going to convert one of them into a user-definable input and use the input in a recipe located in a different cookbook.

Update the Metadata

  1. As a reminder, view the file in the 'attributes' directory of the 'about_me' cookbook where you hard-coded several attributes. Although you were able to define values for these variables using the 'set' and 'default' methods, the benefit of using the 'default' method is that you can easily convert the attribute into a user-definable input by simply updating the cookbook's metadata. For this reason, RightScale prefers to use the 'default' (previously 'set_unless') method in our own cookbooks. After viewing the original file, exit out of view mode.
    • # view /opt/development/cookbooks/about_me/attributes/me.rb
      
      set[:about_me][:first_name] = "<INSERT_YOUR_NAME_HERE>"
      default[:about_me][:favorite][:food] = "pizza"
      default[:about_me][:favorite][:drink] = "water"
      default[:about_me][:favorite][:hobby] = "running"
  2. Next, you are going to convert the 'hobby' attribute into an input. Update the metadata for the 'about_me' cookbook.
    • # vi /opt/development/cookbooks/about_me/metadata.rb
  3. Add the following lines of code to the 'metadata.rb' file (highlighted in green) and save the changes. (Esc, Shift+q, wq)
    • maintainer       "YOUR_COMPANY_NAME"
      maintainer_email "YOUR_EMAIL"
      license          "All rights reserved"
      description      "Installs/Configures about_me"
      long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
      version          "0.0.1"
      
      depends "rightscale"
      
      recipe "about_me::default","Prints my first name and several of my favorite things as output."
      
      # Required #
      attribute "about_me/favorite/hobby",
         :display_name => "Hobby",
         :description => "My favorite hobby.",
         :required => "required",
         :recipes => ["about_me::default"]
  4. Add, commit, and push the changes to your repository.
    • # cd /opt/development/cookbooks/about_me/
      # git commit -am "Converted the hobby attribute into an input"
      # git push origin

Refetch and Import

Now that you pushed new code to GitHub, you need to update your RightScale account so that you have access to the latest version of your cookbook in your ServerTemplate.

  1. Go to Design Repositories.
  2. Find and click on the repository that you created earlier. (e.g. Chef Tutorial)
  3. Click the Refetch and Import button to update Repose with the most recent changes to your source repository.

Test the Script

  1. Go to the Scripts tab of the current "Test" server and run the 'about_me::default' script. Notice that the script has a missing "hobby" input.
    screen-RunDefaultScriptInput-v1.png
     

  2. Since you converted the 'hobby' attribute into a required input, you will need to provide a value for the input before the script can be executed. After entering a value (e.g. text:hiking), click Continue.
    screen-SetInputHiking-v2.png
     

  3. Check the server's latest Audit Entry to verify that the output is correct. 

    screen-AuditHiking-v3.png

Terminate the Servers

You can now safely terminate the servers.

In summary, you learned about the following concepts in this tutorial.

  • Static attributes
  • Dynamic attributes which get displayed as user-definable inputs in the dashboard
  • Different types of inputs: required, recommended, and optional
  • Converting a static attribute into a user-definable input

Things to Consider

Although you can technically use an attribute that's defined in a different cookbook, it's strongly recommended that attributes only be defined and used within the context of the same cookbook in order to prevent accidental input overrides.

You must to post a comment.
Last modified
14:40, 10 Oct 2013

Tags

Classifications

This page has no classifications.

Announcements

None


© 2006-2014 RightScale, Inc. All rights reserved.
RightScale is a registered trademark of RightScale, Inc. All other products and services may be trademarks or servicemarks of their respective owners.