Cover image for Customizing Chef

Book description

Take advantage of Chef’s highly customizable design to tackle specific automation issues that you can’t solve by simply using Chef’s tools, resources, and services out of the box. With this practical guide, you’ll examine the internal structure of this configuration management technology and learn where, how, and why to add custom code.

Table of Contents

  1. Dedication
  2. Preface
    1. Who This Book Is For
    2. How This Book Is Organized
    3. Conventions Used in This Book
    4. Using Code Examples
    5. Safari® Books Online
    6. How to Contact Us
    7. Acknowledgements
  3. I. Chef & Ruby 101
    1. 1. Introduction
      1. What is Configuration Management?
      2. So Why Chef?
      3. Think Critically
      4. Meet AwesomeInc.
      5. Criteria for Customization
        1. How do we find out when our Chef runs are failing and why?
        2. How do we simplify our recipes to reduce the amount of replicated code?
        3. How do we stop our developers and Ops staff treading all over each others changes?
      6. State of the Customization Nation
        1. Community Cookbooks
        2. Development Tooling
        3. Workflow Tooling
        4. Knife Plugins
        5. Handlers
        6. Recipes and Resources
      7. Chef Installation Types and Limitations
        1. Chef Solo
        2. Open Source Chef
        3. Local Mode
        4. Private Enterprise Chef
        5. Hosted Enterprise Chef
      8. Prerequisites
        1. Knife
        2. Nodes and Clients
        3. Cookbooks, Attributes, Roles, Environments and Databags
        4. Chef Search
        5. Ruby
      9. Assumptions
    2. 2. Just Enough Ruby to Customize Chef
      1. Ruby is Object Oriented
      2. Ruby is Dynamically Typed
      3. Classes
        1. Getter and Setter Methods
      4. Variable Scoping
        1. Local Variables
        2. Class Instance Variables
      5. Inheritance
      6. Modules
        1. Modules as Namespaces
        2. Modules as Mixins
      7. Using Other Classes & Modules
        1. Local Classes
        2. Rubygems
        3. Built-in Classes
      8. When Things Go Wrong
        1. Exceptions
        2. Handling Exceptions
        3. Defining Custom Exception Types
      9. Tying It All Together
        1. File Operations
        2. HTTP Requests
      10. Summary
    3. 3. Chef Internals
      1. Chef Architecture
        1. Chef Client Tools
        2. Chef Server
      2. Anatomy of a Chef Run
        1. Get Configuration Data
          1. Ohai
        2. Authenticate / Register
        3. Load and Build Node Object
        4. Synchronize Cookbooks
        5. Setup RunContext
        6. Load Cookbook Data
        7. Converge Node
        8. Finalize
      3. Dry-run and Why-run
        1. The Problem with Dry-run
        2. Why-run mode
        3. Usefulness of Why-run
      4. Using the Source
        1. Getting the Chef Source Code
        2. Chef Source Structure
      5. Tracing a Chef-client Run
        1. Execute the “chef-client” Command
        2. Run the Real “chef-client” Script
        3. The Chef::Application::Client Class
        4. Chef::Application::Client - run_chef_client Method
        5. The Chef::Client Class
        6. Chef::Client class - do_run Method
      6. Summary
  4. II. Customizing Chef Runs
    1. 4. Extending Ohai
      1. Introduction
        1. Ohai Attribute Collection
        2. The Ohai Source Code
      2. Ohai Example 1: Plugin Skeleton
      3. Testing & Running Ohai Plugins
        1. Testing Using IRB
        2. Running Using Chef
      4. Ohai Example 2: Adding More to Plugin
        1. The Mash Object
        2. Multiple
        3. Running Example 2
      5. Ohai Example 3: Multi-level Plugins
      6. Summary
    2. 5. Creating Handlers
      1. Preparing a Test Environment
        1. Create Test chef-client Configuration
        2. Create Test Cookbook
        3. Verify Test Environment Works Correctly
      2. Introduction to Handlers
      3. Runstatus Object
        1. Run Status Methods
        2. Run Information Methods
        3. Run Object Methods
      4. Handler Example 1: Start Handler
      5. Handler Example 2: Report Handler
      6. Handler Example 3: Exception Handler
      7. Handlers: Summary and Further Reading
    3. 6. Extending Chef Run Events
      1. Introduction
        1. Event Dispatcher Initialization
        2. Publish Overview
        3. Subscribe Overview
      2. Creating Formatters
        1. Formatter Example 1: Skeleton Formatter
        2. Formatter Example 2: Slightly Less Skeletal
        3. Formatter Example 3 - Custom Event Methods
        4. Setting the Default Formatter
        5. Formatters: Summary & Further Reading
      3. Creating Custom Subscribers
        1. Subscriber Example 1: Skeleton
        2. Subscriber Example 2: Registration with Start Handlers
        3. Subscriber Example 3: Custom Event Methods
        4. Custom Subscribers: Summary
      4. Revisiting AwesomeInc - Which Customization?
      5. Summary
  5. III. Customizing Recipes
    1. 7. Definitions & Libraries
      1. Cookbook Structure Revisited
      2. Creating a Test Environment
      3. Definitions
        1. What is a Definition?
        2. Definition Example 1: Skeleton
        3. Adding Parameters
        4. Definition Example 2 - Using Parameters
        5. Adding Resources
        6. Definition Example 3 - Adding Resources
      4. Libraries
        1. What is a Library?
        2. Libraries Example 1 - Modules and Mixins
        3. Libraries Example 2 - Methods in a Custom Namespace
        4. Libraries Example 3 - Extending Core Chef Classes
        5. Summary and Further Reading
    2. 8. Lightweight Resources & Providers
      1. Introduction to Resources & Providers
        1. Automatically Choosing Providers
        2. Resources and Providers - Lightweight vs Heavyweight
      2. LWRPs - Introduction
      3. LWRP Example 1 - Getting Started with LWRPs
        1. Example 1 - Creating a Resource
        2. Example 1 - Creating a Provider
        3. Example 1 - Using our LWRP in a Recipe
      4. LWRP Domain Specific Language
        1. Resource DSL
        2. Provider DSL
      5. LWRP Example 2 - Extending the Provider
      6. Provider Internals
        1. Desired Resource State
        2. Current Resource State
        3. Identifying and Executing Changes
          1. Keep it simple, keep it relevant
          2. Pick your state object sensibly
          3. Remember the criteria
        4. Informing Chef About Updates
      7. LWRP Example 3 - Native Provider
        1. Example 3: Preparing Resource and Provider
        2. Example 3: load_current_resource Method
        3. Example 3: Coding the Actions
      8. Summary and Further Reading
    3. 9. Heavyweight Resources and Providers
      1. HWRPs - Introduction
        1. Why Write HWRPs?
        2. HWRPs in Cookbooks
      2. HWRP Example 1 - Getting Started with HWRPs
        1. Example 1: Creating a Resource
        2. Example 1: Creating a Provider
        3. Example 1: Using our HWRP in a Recipe
        4. Example 1: Extending the Provider
      3. Advanced HWRP Tricks
        1. Mixing HWRPs and LWRPs
        2. Overriding Automatic Provider Resolution
        3. Implementing Multi-provider Resources
      4. HWRP Example 2 - Extending the Package Resource
        1. Example 2: Creating a Provider
        2. Example 2: Using our Provider in a Recipe
        3. Example 2: Tapping into Chef’s Provider Mapping
      5. Summary & Further Reading
  6. IV. Other Customizations
    1. 10. Customizing Knife
      1. The Knife Source Code
      2. Introduction to Knife Plugins
      3. Anatomy of a Knife Command
        1. Validate and Parse Options
        2. Load Plugins
        3. Get Subcommand Class
        4. Load Dependencies
        5. Create Subcommand Object
        6. Run Plugin
      4. Creating a Test Environment
        1. Prerequisites and Preparation
        2. Verify Test Environment Works Correctly
      5. Knife Example 1: Wrapping an Existing Plugin
      6. Presenting Presenters!
        1. Chef::Knife::Core::GenericPresenter
        2. Chef::Knife::Core::NodePresenter
      7. The UI Class
        1. User Interaction Methods
        2. Message Output Methods
        3. Other Output Methods
        4. Misc Methods
        5. Highline Methods
      8. Knife Example 2: Search Plugin
      9. Working with Chef Objects
        1. Loading Objects: Searching
        2. Loading Objects: Direct Loading
        3. Editing and Saving Objects Non-Interactively
        4. Editing and Saving Objects Interactively
        5. Creating and Updating Objects from Files
      10. Knife Example 3: Tying it all Together
      11. Revisiting AwesomeInc - Plugin Best Practices
      12. Summary & Further Reading
    2. 11. The Chef API
      1. Introduction to the Chef API
        1. So Why Use the Chef API?
        2. Authenticating to the Chef API
      2. Creating a Test Environment
      3. API Example 1: Authenticating & Making a GET Request
      4. The Chef::Rest Class
      5. API Example 2: Combining Multiple API Requests
      6. Error Handling
      7. Secrets of the Chef API
        1. The _status Endpoint
        2. Partial Search
      8. Summary and Further Reading
    3. 12. Contributing Your Customizations
      1. Documentation
      2. Supporting Your Code
      3. Managing Contributions
      4. Testing your Software
        1. Ruby & Infrastructure Testing Tools
        2. Continuous Integration Tools
        3. Chef Specific Tooling
        4. Further Reading
      5. Versioning your Software
        1. Semantic Versioning
      6. Licensing and Copyright
        1. Copyright
        2. Licensing your Code
      7. Distributing Your Customizations
        1. Sharing the Source Code
        2. Community Cookbooks
        3. Rubygems
        4. Distribution via Cookbook
      8. Summary
    4. A. Chef API Endpoints and Verbs
  7. Index
  8. About the Author
  9. Colophon
  10. Copyright