├── README.md ├── basic-chef-fluency ├── README.md ├── basic-chef-fluency-kata-cheatsheet.md ├── basic-chef-fluency-kata.md └── basic-chef-fluency-study-sheet.md ├── deploying-cookbooks ├── README.md └── deploying-cookbooks-study-guide.md └── local-cookbook-development ├── README.md └── local-cookbook-development-study-guide.md /README.md: -------------------------------------------------------------------------------- 1 | ![](https://github.com/anniehedgpeth/anniehedgpeth.github.io/blob/master/assets/article_images/2017-06-16-basic-chef-fluency-badge/badge-basic-chef-fluency.png) 2 | 3 | So you want to get Chef Certified. Well, I'm here to help. 4 | 5 | As I, myself, study for these exams, I'm turning my study notes into study guides for you to use right here in this repo. So feel free to think of us as study partners, but that means that you have to help me out by submitting issues and pull requests if you see anything that can be improved upon! 6 | 7 | So far I've got guides for Basic Chef Fluency and Local Cookbook Development. Help yourselves. -------------------------------------------------------------------------------- /basic-chef-fluency/README.md: -------------------------------------------------------------------------------- 1 | # [BASIC CHEF FLUENCY BADGE STUDY GUIDE](https://training.chef.io/static/Basic_Chef_Fluency_Badge_Scope.pdf) 2 | 3 | > The topics for this guide are taken directly from [training.chef.io](https://training.chef.io). 4 | 5 | When studying for the [Basic Chef Fluency Badge exam](https://training.chef.io/basic-chef-fluency-badge), I recommend that you go through this guide daily until you are very comfortable going through the material. 6 | 7 | ## The files in this guide are: 8 | ### Basic Chef Fluency Study Guide 9 | - This is meant to study the concepts outlined in the [scope PDF](https://training.chef.io/static/Basic_Chef_Fluency_Badge_Scope.pdf) by Chef. 10 | ### Basic Chef Fluency Kata 11 | - This is an exercise guide meant for daily use. This guide is most effective for those that are not currently using Chef in their daily practice or are just starting in Chef. It will give you a comfort with Chef enough for navigating the topics of the exam. 12 | ### Basic Chef Fluency Kata Cheat Sheet 13 | - This is used in conjunction with the Basic Chef Fluency Kata. If you are uncertain about how to carry out an exercise, then you can consult the cheat sheet. 14 | 15 | ## IMPROVEMENTS? 16 | Do you see any errors or ways in which this guide can be improved? Please submit a [pull request](https://github.com/anniehedgpeth/basic-chef-fluency-study-guide/pulls) or [issue](https://github.com/anniehedgpeth/basic-chef-fluency-study-guide/issues)! 17 | 18 | ## Other Good Resources 19 | [Basic Chef Fluency Badge YouTube Playlist](https://www.youtube.com/playlist?list=PL_H2cfWwTC4yeHbXYOCsJOZadHyCLQ55W) 20 | 21 | [Certified Chef Developer Basic Chef Fluency Badge by Linux Academy](https://linuxacademy.com/devops/training/course/name/certified-chef-developer-basic-chef-fluency-badge) 22 | -------------------------------------------------------------------------------- /basic-chef-fluency/basic-chef-fluency-kata-cheatsheet.md: -------------------------------------------------------------------------------- 1 | # Basic Chef Fluency Kata CHEAT SHEET 2 | Please see the associated exercise kata for the Basic Chef Fluency Badge in the [basic-chef-fluency-kata.md](https://github.com/anniehedgpeth/basic-chef-fluency-study-guide/blob/master/basic-chef-fluency-kata.md) file. 3 | 4 | # Create a new repo for today's kata (or just branch the repo) 5 | - from code/chef/work create a new repo `chef generate repo chefkata<#>` 6 | - create /code/chef/work/chefkata<#>/.chef and copy the user pem inside the .chef directory 7 | - generate knife.rb "generate knife config" for that org to put in .chef folder, too 8 | 9 | # Create a new cookbook branch 10 | - from code/chef/work/chefkata<#>/cookbooks `git clone https://github.com/anniehedgpeth/chefkata.git` 11 | - from code/chef/work/chefkata<#>/cookbooks/chefkata create a branch, name it, and switch to it `git checkout -b ` 12 | 13 | # Add the second cookbook for the runlist 14 | - add the ubuntu cookbook to that cookbooks directory and make sure it converges `git clone https://github.com/anniehedgpeth/ubuntu-14-hardening.git` 15 | `berks install` 16 | `berks upload` 17 | 18 | Any time I change the cookbook, from that cookbook’s directory, I need to: 19 | - bump the version in `metadata.rb` or it won't upload the new one 20 | - (you would normally automate that in Jenkins) 21 | `berks install` 22 | `berks upload` 23 | 24 | # To bootstrap a new machine: 25 | 26 | `knife bootstrap chefkata<#>.southcentralus.cloudapp.azure.com -N chefkata<#> -r 'recipe[chefkata::default], recipe[ubuntu-14-hardening::default]' --ssh-user annie --sudo` 27 | 28 | `knife bootstrap production<#>.southcentralus.cloudapp.azure.com -N chefkata<#>prod -r 'recipe[chefkata::default], recipe[ubuntu-14-hardening::default]' -E 'prod' --ssh-user annie --sudo` 29 | 30 | # To converge on that node from here on out: 31 | 32 | run `sudo chef-client` in an ssh session 33 | 34 | # To validate with InSpec Profile 35 | First you have to add your private key to the local ssh (I don't know if it matters which directory you're in.) 36 | `ssh-add` 37 | `ssh annie@chefkata<#>.southcentralus.cloudapp.azure.com` 38 | `inspec exec https://github.com/anniehedgpeth/chefkata_inspec -t ssh://annie@chefkata<#>.southcentralus.cloudapp.azure.com` 39 | `inspec exec https://github.com/anniehedgpeth/chefkata_inspec -t ssh://annie@production<#>.southcentralus.cloudapp.azure.com` 40 | 41 | # To add run-list: 42 | 43 | `knife node run_list set chefkata<#> 'recipe[chefkata::default]'` 44 | 45 | # To edit the run-list: 46 | - `knife node show chefkata<#>` 47 | - make sure the cookbook is uploaded 48 | - make sure it has a `Berksfile` 49 | - `berks install` 50 | - `berks upload` 51 | - `knife node run_list add chefkata<#> 'ubuntu-14-hardening'` 52 | 53 | # When adding an organization to manage.chef.io 54 | - add the org 55 | - reset user key 56 | generate knife config from UI 57 | copy the user key into .chef folder 58 | create a new org key and download knife.rb 59 | see if your user needs a new key 60 | `knife node list` 61 | 62 | # Search 63 | `knife search node "platform:ubuntu"` 64 | `knife search node "builder:Annie"` 65 | 66 | # Data bags 67 | - shared data that your cookbooks can use 68 | - data_bags directory is in the chef_repo sibling to cookbooks directory 69 | - each data bag is a folder and each data_bag item is a .json file within that folder 70 | - the data_bag item is just a .json file of all of settings for that data_bag item 71 | - must include `{ "id":"" }` 72 | - upload data_bag item to chef server so that you can use it in your cookbook 73 | - first create the bag on the server 74 | - `knife data bag create website messages.json` 75 | - run this from the top of the chef repo directory `knife data bag from file BAG_NAME ITEM_NAME.json` 76 | - `knife data bag from file website messages.json` 77 | - It's the same command to update the data bag if you edit it 78 | - Verify that it's there in UI 79 | - Policy > Data Bags > name 80 | - Verify that it's there from command line 81 | - `knife data bag list` 82 | 83 | ## Using data bags in the recipe 84 | - First we access the data from that item 85 | `messages = data_bag_item('website', 'messages')` 86 | - Then we're calling the specific data element from that item 87 | `message = messages['welcomeMessage']` 88 | - Then call it in the recipe like `content message` 89 | 90 | ## Using data bags in test kitchen 91 | So kitchen can't look inside the "real" data bags directory, so you have to set up a dummy data bags directory just for test kitchen. 92 | - Create cookbooks/thiscookbook/test/integration/data_bags and copy your real data bag directory into that 93 | - Then edit the .kitchen.yml 94 | 95 | ```yaml 96 | suites: 97 | - name: default 98 | data_bags_path: "test/integration/data_bags" 99 | ``` 100 | 101 | ## Roles 102 | Roles function just like data bags in the sense that they're sibling to the cookbooks directory, you have to upload them separately to the chef server, and they have their own attributes. They also have their own run-lists. 103 | - to upload to chef server 104 | `knife role from file roles/security.json` 105 | - to check 106 | `knife role list` 107 | - to add the role to the runlist 108 | `knife node run_list add chefkata<#> 'role[security]'` 109 | 110 | ## Environments 111 | `knife environment create ENVIRONMENT_NAME -d DESCRIPTION` 112 | `knife environment from file FILE (options)` 113 | `knife environment edit ENVIRONMENT_NAME` 114 | `knife environment show ENVIRONMENT_NAME` -------------------------------------------------------------------------------- /basic-chef-fluency/basic-chef-fluency-kata.md: -------------------------------------------------------------------------------- 1 | # Basic Chef Fluency Kata 2 | Originally posted in his Github repo, [Michael Hedgpeth](https://github.com/mhedgpeth/chef-by-example/blob/master/basic-chef-fluency.md) came up with this simple exercise that one can follow daily in order to gain proficiency in Chef. 3 | 4 | We recommend that you spend one hour a day, getting as far through the kata as you can. After a while, I expect that you'll be able to get through the entire exercise in less than an hour! 5 | 6 | Here is an example of a [kata repo](https://github.com/anniehedgpeth/chefkata) that follows these exercises. Each branch is a new day's kata. 7 | 8 | ## Resources, Recipes, Cookbooks 9 | 1. Create a `chef-training` repo on GitHub and clone it locally. 10 | 11 | 1. Create a new branch using today's date in the name to track it. 12 | 1. Ensure that you have a code editor with Chef Plugins installed. I recommend Visual Studio Code. 13 | 1. Generate a cookbook into the `chef-training` repo 14 | 1. Make your cookbook only support Ubuntu. 15 | 1. Set up test kitchen to run the `default` recipe of your cookbook using Vagrant and VirtualBox. 16 | 1. Ensure that Nano is installed (in an InSpec test and recipe). Run kitchen converge and verify to ensure this works. 17 | 1. For the rest of the lab, create a Test Kitchen workflow that uses the `kitchen create`, `kitchen converge`, `kitchen verify` and `kitchen destroy` commands. Also, use `kitchen login` to manually ssh into your Ubuntu machine. 18 | 1. Create `/var/website` directory. 19 | 1. Make sure `/var/old-website` directory does not exist. 20 | 1. Write a file `/var/website/directions.txt` with text "website goes here" in it. 21 | 1. Write a file `builder.txt` to `/var/website/builder.txt` containing the text "[Your Name] built this" where `[Your Name]` is a cookbook attribute with your actual name. 22 | 1. Download the Chef logo into `/var/website`: https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSgQmQ0CYwU3cpFE6gEB82cp6TSIcBJSisax_HVvEfsgYHGBsO8kQ 23 | 1. When you run test kitchen, `builder.txt` should contain the text `Test Kitchen built this`. 24 | 1. Run the command `echo ran command > /var/website/command.txt`. 25 | 1. Don't run the command the second time chef converges (i.e. make it idempotent). 26 | 1. If the command *does* run, do a `git pull` of the architect repository into `/var/website/architect` (https://github.com/pages-themes/architect). It shouldn't pull the repository every time. 27 | 1. Refactor your command and pull into a custom resource called `chef_training_website`. 28 | 1. Make the git repo that you pull an attribute. 29 | 1. Write a `MyLogger` class with a `Log` method that prepends the message `CHEF TRAINING: ` and outputs that to the STDOUT (using puts). 30 | 31 | ## Chef Server 32 | Now that we've had some practice with basic cookbook development, let's get connected to a Chef Server. 33 | 34 | 1. Create an Ubuntu virtual machine with VirtualBox. 35 | 36 | 1. Set up an account on manage.chef.io and ensure your keys and knife.rb are available to your `knife` command on your workstation. 37 | 1. Ensure your `chef-training` cookbook is uploaded to the Chef Server 38 | 1. Bootstrap your machine running 2 recipes: `chef-training` and the `os-hardening` cookbook. You'll need to ensure the other cookbook is uploaded to the Chef Server as well. 39 | 1. Run `chef-client` on the machine again, noticing that 0 resources are converged the second time. 40 | 41 | ## Search 42 | 1. On your workstation, search for all Ubuntu nodes. 43 | 44 | 1. On your workstation, search for all nodes that match the attribute used to create the `builder.txt` file above. 45 | 1. Create a data bag `website` with item `messages`. Inside of `messages`, have a `welcomeMessage` named `Welcome to Chef Learning!` 46 | 1. In your `chef-training` cookbook, write a file `/var/website/welcome.txt` with the welcome message from the data bag. 47 | 1. Push the updated cookbook to the Chef Server and reconverge, ensuring that the file is there on your Ubuntu VM. 48 | 1. Update the data bag to `Welcome to the BEST Chef Learning EVER!` 49 | 1. Reconverge and see that the file changed. 50 | 51 | ## Advanced Administration 52 | 1. Show the node's run list with `knife` and look it up in the UI. 53 | 54 | 1. Create a role named `security` which includes the `os-hardening` cookbook. 55 | 1. Read over the README of the `os-hardening` cookbook and find some attributes to set. Set those attributes in your `security` role. 56 | 1. Change the run list on the command line to remove the `os-hardening` cookbook and add the `security` role. 57 | 1. Reconverge and ensure that the behavior is the same. 58 | 1. Create a `development` environment that will be assigned to your existing node. It should: 59 | - Always run the latest `chef-training` cookbook on the chef server 60 | - Run the `1.4.1` version of `os-hardening` cookbook 61 | - Have the `builder.txt` saying `Development Built This` 62 | 1. Assign the `development` environment through the `client.rb` on your virtual machine 63 | 1. Create another virtual machine that will be your "production" machine 64 | - Run a specific version of the `chef-training` cookbook 65 | - The `builder.txt` should say `Production Built This` 66 | - Assign the `production` environment through the `client.rb` 67 | - Update your `chef-training` cookbook to change the text of `builder.txt`. After uploading it to the Chef Server notice that only your `development` node was updated, but not your `production` node. 68 | 69 | ## Chef Automate 70 | 71 | For the first badge, you need to understand Automate itself, so this section won't be example driven but more idea driven. 72 | 73 | Watch [this video](https://www.youtube.com/watch?v=ldY7KEOxCkM&index=1&list=PL11cZfNdwNyOPa_kLgCX0wDW3O00Sjydx) to get an overview of Chef Automate. 74 | 75 | Now do this thought experiment: 76 | * How would you solidify your cookbook deployment workflow? (if you don't know workflow enough, watch [this video](https://www.youtube.com/watch?v=OdoGu31EBU0)) 77 | * How would you see what happens on your nodes? 78 | * How would you scan your nodes with inspec profiles? -------------------------------------------------------------------------------- /basic-chef-fluency/basic-chef-fluency-study-sheet.md: -------------------------------------------------------------------------------- 1 | # Study Sheet for Basic Chef Fluency 2 | 3 | > The topics for this guide are taken directly from [training.chef.io](https://training.chef.io). I copied the bulleted lists, and I filled in the study information from either my own understanding or from docs.chef.io. 4 | 5 | # [BASIC CHEF FLUENCY BADGE TOPICS](https://training.chef.io/static/Basic_Chef_Fluency_Badge_Scope.pdf) 6 | https://training.chef.io/static/Basic_Chef_Fluency_Badge_Scope.pdf 7 | 8 | **The Basic Chef Fluency badge is awarded when someone proves that they understand the core elements that underpin Chef. Candidates must show:** 9 | 10 | - An understanding of basic Chef terminology. 11 | - An understanding of Chef product offerings. 12 | - An understanding of Chef's design philosophy. 13 | - An understanding of Chef's approach to workflow and compliance. 14 | - An understanding of basic Chef coding skills. 15 | 16 | Here is a detailed breakdown of each area. 17 | 18 | # CHEF BASIC TERMINOLOGY 19 | ## RESOURCES 20 | *Candidates should understand:* 21 | 22 | ### Idempotency/convergence - test & repair model 23 | When a node is converged, chef-client first tests to see if the node is in the same state as defined by the recipe. If it is not, then it repairs the node in accordance to the recipe. 24 | 25 | ### Common resources and their actions 26 | *Default actions*
27 | - The `:nothing` action 28 | - This simply means that this resource will do nothing to the node unless told otherwise. 29 | 30 | - The `supports` directive 31 | - The `supports` directive specifies the platform that the cookbook supports. This is specified within the cookbook's `metadata.rb`. 32 | 33 | - The `not_if` and `only_if` directives 34 | - You may specify that a resource takes action only if or not if another requirement is met or not met. 35 | 36 | ### Resource extensibility 37 | 38 | ## RECIPES 39 | *Candidates should understand:* 40 | 41 | ### What a recipe is 42 | - A recipe is an ordered script within a cookbook that can be called within a chef-client run. 43 | 44 | ### Importance of the resource order 45 | - The resources of a recipe are called in the order in which they are written because some require that others exist or not before they can be called. 46 | 47 | ### How to use `include_recipe` 48 | - To include another recipe within a recipe, one must first make the cookbook dependent upon that recipe within the metadata of that cookbook. Then you may use the `include_recipe` resource within the recipe to actually execute that dependent recipe. 49 | 50 | ### What happens if a recipe is included multiple times in a run_list 51 | -If a recipe appears more than once in the run-list, the chef-client will not run it twice. 52 | 53 | ### The `notifies` and `subscribes` directives 54 | - A resource can notify another resource of its actions in order for the secondary resource to take action based upon the primary resource's actions. Conversely, a resource can subscribe to another resource to listen for its actions and take action itself based on the actions of the resource to which is it subscribed. 55 | 56 | # COOKBOOKS 57 | *Candidates should understand:* 58 | 59 | ### Cookbook contents 60 | - A cookbooks' primary contents include recipes, attributes, resources, metadata, `.kitchen.yml`, data bags, roles, environments. 61 | 62 | ### Naming conventions 63 | - Underscores should be used instead of hyphens. 64 | 65 | ### Cookbook dependencies 66 | - You can declare the dependencies of your cookbook on other cookbooks by including those cookbooks in the `metadata.rb` by using `depends '', 'versionoptional'`. If you're using dependencies that are not stored in source control or the Supermarket, you may use Berks to upload those dependencies to the Chef server from your workstation. 67 | 68 | ### The default recipe 69 | - If there is only one recipe in the cookbook, then this will be called the default recipe. The default recipe is called when the cookbook is listed without a recipe name in a run list. 70 | 71 | # CHEF SERVER 72 | *Candidates should understand:* 73 | 74 | ### How the Chef server acts as an artifact repository 75 | - The Chef server can store a number of different artifacts for use by the chef-client. These include but are not limited to: roles, environments, data bags with data bag items stored inside, attributes, cookbooks, policies, clients, organizations, node attributes / OHAI data. 76 | 77 | ### How the Chef server acts as an index of node data 78 | - The Chef server receives OHAI data, which contains all of the node data from the chef-client after it is run. 79 | 80 | ### Chef solo vs Chef server 81 | - When using Chef solo, all of the artifacts are stored on the workstation in which you are working, whereas when you are using the Chef server, those artifacts are stored on the Chef server. 82 | 83 | ### [Chef server's distributed architecture](https://docs.chef.io/install_server_ha.html) 84 | - If Chef server being a single point of failure being a huge risk for you, then you can run Chef server in high availability mode, which means it has redundancy. 85 | 86 | ### Scalability 87 | - If the chef-client is on the node being configured, then it scales more easily because a server doesn't have to do all the work. Scaling with High Availabililty (HA) is also an option. 88 | 89 | ## SEARCH 90 | *Candidates should understand:* 91 | 92 | ### What search is 93 | - `knife search` commands can be use to search the Chef server. 94 | 95 | ### How to search for node information 96 | - `knife search node ":"` may be invoked or you may search in the Chef server UI (nodes > attributes). 97 | 98 | ### [What and how many search indexes Chef server maintains](https://docs.chef.io/chef_search.html) 99 | - Node data is indexed on the Chef server. That data may be accessed through a search query in any of the following ways: 100 | 1) within the recipe 101 | 2) by using the `knife search` command 102 | 3) the search method in the Recipe DSL 103 | 4) the search box in the Chef management console 104 | 5) by using the `/search` or `/search/INDEX` endpoints in the Chef server API 105 | 106 | ### What a databag is 107 | - A databag is a directory of data that is stored on the Chef server. 108 | 109 | ### How to use search for dynamic orchestration 110 | - You would use the `knife search` command to get a list of nodes on which you need to perform actions. 111 | 112 | ### How to invoke a search from the command line 113 | - `knife search node ":"` 114 | 115 | ## CHEF CLIENT 116 | *Candidates should understand:* 117 | 118 | ### What the Chef client is 119 | - The Chef client is an agent installed on the nodes being configured. 120 | 121 | ### The function of Chef client vs the function of Chef server 122 | - While the client is installed on the nodes being configured, the server stores the necessary configuration information for the client to access. 123 | 124 | ### What 'why-run' is 125 | - The `--why-run` command is similar to Terraform's `terraform plan` command. It tells you what would happen and change if you were to converge. It does run the executable, but it doesn't actually modify the system. 126 | 127 | ### How to use '--local-mode' 128 | - `chef_zero` would be the provisioner, and you'd use local mode if you weren't using a proper Chef server. All of the data would be accessed from 129 | 130 | ### How the Chef client and the Chef server communicate 131 | - The node on which Chef client is installed has a client.rb file which contains a link and credentials to access the Chef server. The Chef server never accesses the Chef client; it merely holds the data that the client will need to access. The Chef client communicates to the Chef server over https (port 443) or http (port 80). 132 | 133 | ### The Chef client configuration 134 | - The client is configures the node that it is on based on the run-list it is given during the bootstrap or knife commands. 135 | 136 | ## NODES 137 | *Candidates should understand:* 138 | 139 | ### What a node is 140 | - A node is the machine that is being configured by the Chef client. 141 | 142 | ### What a node object is 143 | - A node object is data that is given to the Chef server to store by the Chef client after `chef-client` is run which contains OHAI data as well as attributes. 144 | 145 | ### How a node object is stored on Chef server 146 | - A node object is data that is given to the Chef server to store by the Chef client after `chef-client` is run which contains OHAI data as well as attributes. 147 | 148 | ### How to manage nodes 149 | - Nodes may be managed through the Chef server UI or through knife commands. 150 | 151 | ### How to query nodes 152 | - Nodes may be searched through using the `knife search node` command. For example `knife search node "platform:ubuntu"`. 153 | 154 | ### How to name nodes 155 | - Nodes are named either during a bootstrap or by changing the `client.rb` file on the node. 156 | 157 | ## RUN LIST 158 | *Candidates should understand:* 159 | 160 | ### What a run_list is 161 | - A run_list is added to a node either during a bootstrap or by changing the `client.rb` file on the node. It contains all of the cookbooks, recipes, and roles for the node. 162 | 163 | ### What nested run_lists are 164 | - A nested run_list simply means that when a role has a run-list and you add that role to a run-list, it becomes nested. 165 | - For example: `security` role has a run-list that includes `cloudpassage::default, hardening::centos` and then your node has a run-list that includes `role[security]` in it 166 | 167 | ### Where a run_list is stored 168 | - A run_list is stored both on the Chef server and in the node's `client.rb`. 169 | 170 | ### What does a run_list consist of 171 | - A run_list consists of all of the recipes and cookbooks to be run on the node as well as the roles assigned to it, which contain their own recipes and cookbooks. 172 | 173 | ### How to look up run_lists 174 | - You may find a node's run_list in 3 ways: 175 | 1) Look in the UI under Nodes > Details > Run List. 176 | 2) Run `knife node show ` 177 | 3) In the node, look at the `client.rb` file. 178 | 179 | ### How to set and change run_lists 180 | - You can set and change run_lists in much the same way that you can view them. 181 | 1) Look in the UI under Nodes > Details > Run List > Edit. 182 | 2) After you've insured that your desired cookbooks are uploaded to the Chef server, run `knife node run_list add 'recipe[::]'` OR `knife node run_list add chefkata7 'role[security]'` 183 | 3) In the node, look at the `client.rb` file (not best practice). 184 | 185 | ## ROLES 186 | *Candidates should understand:* 187 | 188 | ### What roles are 189 | - A role sets the patterns and processes for a node. Each node may have any amount of roles or none. A role can be thought of in two different ways: 190 | 1) the role of the machine 191 | 2) the role of the team/person setting the run lists (not best practice) 192 | 193 | ### How a role ensures code consistency across nodes 194 | - A role ensures code consistency by giving that node all of the same patterns and processes as well as attributes. 195 | 196 | ### Where roles can be stored 197 | - Roles are stored in the chefrepo sibling to cookbooks on your workstation or on the node if you're running it in local mode. Otherwise, they're stored on the Chef server. 198 | 199 | ### How roles are defined 200 | - Roles are defined in a `.json` or `.rb` file within a `roles` directory sibling to the `cookbooks` directory in a `chefrepo` which is uploaded to the Chef server. Or you may create a role within the UI of the Chef server: Policy > Roles > Create. 201 | 202 | ### What the components of a role are 203 | - The main components Roles consist of a run list and attributes (both default and override). 204 | 205 | ### Roles vs recipes vs run_lists 206 | - A role, recipe, and run_list can each call various recipes in different ways. 207 | 1) A role will be assigned to a node and may or may not have its own run_list that will be included for that node. 208 | 2) A recipe can use the `include_recipe` resource in order to run a recipe that is included in that cookbook's dependencies within the `metatdata.rb` file. 209 | 3) A run_list is assigned to a node using the `bootstrap` or `knife` command. It may contain both recipes and roles. 210 | 211 | ### How to name roles 212 | - The name of the role is defined by the name of the `.json` or `.rb` file that you create in the `roles` directory as well as the metadata within that file. This may also be done within the UI of the Chef server. The requirements for the name are that it must be: 213 | 1) unique to its organization 214 | 2) made of letters (upper and/or lower-case), numbers, underscores, and/or hyphens (no spaces allowed). 215 | 216 | ### How to apply roles to nodes 217 | - Roles are assigned to nodes through the bootstrap, knife, or UI, and they are then applied when `chef-client` is run. 218 | 219 | ## How to edit roles ENVIRONMENTS 220 | *Candidates should understand:* 221 | 222 | ### The purpose of environments 223 | - Environments are assigned to nodes to determine which phase of the release cycle that node represents. This include but are not limited to development, user acceptance testing, and production. 224 | 225 | ### How to use environments to manage cookbook release cycles 226 | - An environment is assigned to a node in order to give it the appropriate version of the cookbooks in the run_lists. The earlier in the release cycle that the environment assigned to the role is, the later versions of the recipes it will be assigned to. 227 | 228 | ### How to use environments to constrain cookbooks 229 | - Environments are assigned to nodes, and then that node data is returned to the Chef server. You can then use that data within a recipe to constrain attributes to particular environments. 230 | 231 | ### How to put nodes into an environment 232 | - Environments are assigned to nodes through: 233 | 1) the UI under Nodes > Attributes > Edit. 234 | 2) bootstrap and knife commands 235 | 3) by editing the `client.rb` file 236 | - You may also change a node's environment with a `knife exec` command. 237 | 238 | ## INFRASTRUCTURE AS CODE 239 | *Candidates should understand:* 240 | 241 | ### What the advantages are of defining infrastructure as code 242 | - If your infrastructure is code, then you know your the state of your infrastructure just by looking at the code. You can then easily alter your configuration and use version control to promote changes easily through development. 243 | 244 | ### The reasons for defining infrastructure as code 245 | - Scalability 246 | - version control 247 | - dynamic infrastructure 248 | - simplicity and flexibility for managing and provisioning infrastructure 249 | 250 | ### The difference between rolling back and rolling forward 251 | - Rolling back would be to undo the configuration changes made to your infrastructure. This is not best practice with Chef, as you're only allowed to roll back due to the nature of idempotency. You would need to first change your recipe to intentionally undo the changes to the infrastructure that you wanted to "roll back". Then you'd redefine the desired state in your recipe and instill those changes by converging again. 252 | 253 | ## DESIRED STATE CONFIGURATION 254 | *Candidates should understand:* 255 | 256 | ### The imperative vs the declarative approach to configuration management 257 | - An imperative approach to configuration management would be something like running a shell or Powershell script that consecutively executes commands on a node. Chef, however, uses a declarative approach which would declare the desired state of configuration within the Chef server and perform that configuration management through the Chef client installed on the node. 258 | 259 | ### The push vs the pull approach 260 | - A push approach would be if the node that was being configured was idle while the server pushed a policy of configuration desired state to the node. This would mean that there is nothing additional being installed on the node being configured, only what is in the policy. A pull approach is what Chef employs, which means that the Chef server is idle while the client that is installed on the node being configured pulls the necessary data from the Chef server that it needs to complete its configuration given to it through a bootstrapping process. 261 | 262 | ### What Windows DSC is 263 | - Windows Desired State Configuration is Windows' configuration management tool based on Powershell which employs declarative programming. 264 | 265 | ### What happens if you remove a resource from a recipe 266 | - If you remove a resource from a recipe that has already run on the node, then nothing will happen. Whatever that resource did the first time it ran will still be in effect unless you intentionally undo its effects. 267 | 268 | ## SUPERMARKET 269 | *Candidates should understand:* 270 | 271 | ### The Supermarket value proposition 272 | - The Supermarket is a storehouse full of FREE cookbooks available to use and maintained by Chef. They are easily depended upon in your own cookbooks. 273 | 274 | ### What you can store in Supermarket 275 | - The Supermarket can store cookbook and other tools such as InSpec profiles. 276 | 277 | ### What a private Supermarket is 278 | - A company may have their own private supermarket for use internally. These must be maintained by them and can only be accessed by them. 279 | 280 | ### When to use a private Supermarket 281 | - You would want to use a private Supermarket when you wanted to produce and promote your own cookbooks. 282 | 283 | ### If Supermarket is a free or a premium feature 284 | - The Supermarket is FREE for anyone to use. 285 | 286 | ### If the items in Supermarket are free or cost money 287 | - Everything within the Supermarket is FREE to use for anyone. 288 | 289 | ## CHEF DK 290 | *Candidates should understand:* 291 | 292 | ### The Chef DK value proposition 293 | - When the Chef DK is installed on your workstation, you're able to develop with Chef and therefor able to completely configure your infrastructure. 294 | 295 | ### Specific features of test-driven development (TDD) 296 | - Audit > Remediate > Certify - TDD allows you to develop based on red/green/refactor. You first test for the desired state, and when it fails you write the desired state in your recipe. You then test again, and it passes. 297 | 298 | ### Tools packaged in Chef DK 299 | - Chef-client and OHAI 300 | - Chef CLI 301 | - InSpec / ChefSpec / Cookstyle / Foodcritic 302 | - Chef provisioning 303 | - Knife / Berks / Spork 304 | - Test Kitchen 305 | 306 | ## TEST KITCHEN 307 | *Candidates should understand:* 308 | 309 | ### The Test Kitchen value proposition 310 | - Test Kitchen is at the heart of TDD within Chef. Being able to test your configuration before changing the state of your machine is invaluable because you can configure the state of a throw-away machine without having to change your actual infrastructure. 311 | 312 | ### What TDD is 313 | - Test Kitchen is at the heart of TDD within Chef. Being able to test your configuration before changing the state of your machine is invaluable because you can configure the state of a throw-away machine without having to change your actual infrastructure. 314 | 315 | ### The platforms supported by Test Kitchen 316 | - Linux and Windows 317 | 318 | ### How to include Test Kitchen in a pipeline 319 | - You can add `kitchen test` into your pipeline, and it will run through the entire Kitchen cycle (create, converge, verify, destroy). If it does not pass, then you can halt your build or promote if it passes. 320 | 321 | ### Basic `kitchen` commands 322 | - `kitchen create` 323 | - `kitchen converge` 324 | - `kitchen login` 325 | - `kitchen verify` 326 | - `kitchen destroy` 327 | - `kitchen test` 328 | 329 | ### Basic `kitchen` configuration 330 | - Driver- What is creating your VM? 331 | - Provisioner- What is running Chef? 332 | - Verifier- What is running the tests? (probably InSpec) 333 | - Transport- What are you using to remote to a machine? 334 | - Suites- What are the machines are you making? 335 | - Platform- What OS are you using? 336 | 337 | # DESCRIBING WHAT CHEF IS 338 | 339 | ## PRODUCTS AND FEATURES 340 | *Candidates should understand:* 341 | 342 | ### [The Chef Automate value proposition](https://www.chef.io/automate/) 343 | - "Effective cross-team collaboration" Chef Automate tracks and tests dependencies between projects and teams. Deploy safely, even in a multi-team, multi-project environment where there are complex inter-dependencies. 344 | 1) Full oversight 345 | 2) Change management 346 | 3) Governance 347 | 4) Built-in compliance 348 | 349 | ### The Chef Automate features 350 | ### What the workflow feature is and how it affects productivity 351 | - Workflow is similar to Jenkins or Team City, as it defines and automates the CI/CD pipeline. It affects productivity by promoting the next build in the previous one had passed. You're able to release code faster when the automation process is in charge of promotion. The safeguard of promoting only the builds that pass validation contributes to productivity, as well. 352 | 353 | ### What the compliance feature is and how it affects workflow 354 | - In the same way that workflow adds safeguards which contribute to productivity 355 | 356 | ### What the visibility feature is and how it affects workflow 357 | - It provides insight on how changes affect the state of Chef on the nodes. 358 | 359 | ### How a private Supermarket fits into a workflow 360 | - You create your own server, then you reference your private supermarket in your Berksfile so that Chef server grabs the cookbooks from there. 361 | 362 | ### The Chef Automate open source components 363 | - The open source components of Automate include: 364 | 1) InSpec 365 | 2) Chef 366 | 3) Habitat 367 | 368 | ### What Visibility is 369 | - Visibility is a tool within Chef Automate that allows you to see the state of infrastructure across your entire organization. 370 | 371 | ### What Habitat is 372 | - Habitat is a tool within Chef Automate for the managing and packaging of applications. 373 | 374 | ### What InSpec is 375 | - InSpec is a framework with which to automate security and compliance tests. 376 | 377 | ### What Chef Compliance is 378 | - Compliance is the tool created on top of the InSpec framework which integrates within Chef Automate. 379 | 380 | 381 | ## END-TO-END WORKFLOW 382 | *Candidates should understand:* 383 | 384 | ### How all Chef products, features, and technologies fit together 385 | - Audit (InSpec/Compliance) > Remediate (Chef/Workflow/Habitat) > Certify (Visibility) 386 | 387 | ### The workflow scope 388 | - Workflow defines and automates the CI/CD pipeline. 389 | 390 | ### The compliance scope 391 | - Compliance defines and automates compliance validation. 392 | 393 | ### The Chef Automate scope 394 | - Audit (InSpec/Compliance) > Remediate (Chef/Workflow/Habitat) > Certify (Visibility) 395 | 396 | ### How Chef Automate enhances DevOps behaviors 397 | - Audit (InSpec/Compliance) > Remediate (Chef/Workflow/Habitat) > Certify (Visibility); TDD 398 | - "Effective cross-team collaboration" Chef Automate tracks and tests dependencies between projects and teams. Deploy safely, even in a multi-team, multi-project environment where there are complex inter-dependencies. 399 | 1) Full oversight 400 | 2) Change management 401 | 3) Governance 402 | 4) Built-in compliance 403 | 404 | ### The aspects of Chef that are relevant to security and compliance teams 405 | - Cookbooks for hardening and patch management 406 | - InSpec and Compliance within Workflow for promotion of safe cookbooks 407 | - Visibility for validation of compliance 408 | 409 | ### The aspects of Chef that are relevant to development teams 410 | - Habitat for application packaging 411 | - Test Kitchen for TDD 412 | - Workflow for promotion of code through the pipeline 413 | 414 | ### The aspects of Chef that are relevant to operations teams 415 | - Compliance for health checks 416 | - Chef for infrastructure as code 417 | - Visibility for state of affairs 418 | 419 | ### The aspects of Chef that are relevant to change advisory boards 420 | - Visibility for state of affairs to assess risk of change and to verify the reliability of a version from a previous environment 421 | - Workflow for approval process 422 | 423 | ### How Chef enforces consistency across infrastructure 424 | - Chef enforces consistency across infrastructure by having roles and environments, and Workflow helps to ensure that changes are consistently applied. 425 | 426 | ## DESIGN PHILOSOPHY 427 | ## CHEF IS WRITTEN IN RUBY 428 | *Candidates should understand:* 429 | 430 | ### How Chef uses a Ruby-based DSL 431 | - Chef is a thin domain-specific-language, meaning that it was built on top of Ruby. This means that you're able to easily customize with Ruby. 432 | 433 | ### How to use raw Ruby to extend Chef 434 | - If you'd like to customize your cookbook, then you can use raw Ruby anywhere in the cookbook. 435 | 436 | ### What a library is 437 | - Ruby code can be stored in a cookbook's `libraries` directory and can be implemented / called anywhere in the cookbook's recipes or custom resources. 438 | 439 | ## EXPLICIT ACTIONS 440 | *Candidates should understand:* 441 | 442 | ### How Chef uses explicit actions and only does what you tell it to 443 | - You must state explicitly what you want Chef to do in your configuration. 444 | 445 | ### Actions for common resources such as the :nothing action 446 | - Common actions include :nothing, :create, :sync, :delete, :run, :start, :restart, :stop, :status, etc. 447 | 448 | ### What it means to roll back infrastructure 449 | - Rolling back would be to undo the configuration changes made to your infrastructure. This is not best practice with Chef, as you're only allowed to roll back due to the nature of idempotency. You would need to first change your recipe to intentionally undo the changes to the infrastructure that you wanted to "roll back". Then you'd redefine the desired state in your recipe and instill those changes by converging again. 450 | 451 | ### What happens if you reverse the order of resources in a recipe 452 | - Resources are executed in the order in which they are written. So if you were to reverse them, Chef client would test and repair them in that new order. 453 | 454 | ### [If Chef can automatically detect what patches should be applied to a system](https://blog.chef.io/2017/01/05/patch-management-system-using-chef-automate/) 455 | - Yes and no. 456 | 1) Identify which patches are required 457 | 2) Apply and evaluate the patches in a testing environment 458 | 3) Distribute the patches to the rest of the fleet 459 | 4) Confirm the patches have been applied successfully with InSpec 460 | 461 | ## PUSH VS. PULL 462 | *Candidates should understand:* 463 | 464 | ### The difference between push and pull models 465 | - A push approach would be if the node that was being configured was passive while the server pushed a policy of configuration desired state to the node. This could mean that there is nothing additional being installed on the node being configured, only what is in the policy. A pull approach is what Chef employs, which means that the Chef server is passive while the client that is installed on the node being configured pulls the necessary data from the Chef server that it needs to complete its configuration given to it through a bootstrapping process. 466 | 467 | ### The benefits of a pull model 468 | - The major benefit of a pull model is scalability. The server that houses the data needed for configuration is not strained trying to configure all of the nodes. Instead the client installed on the node does the configuration itself. 469 | 470 | ### When a push model is appropriate 471 | - When you need to run a job independently of a `chef-client` run, a push job may be appropriate. This will allow you to send a job to a node independently of the client. A push model may also be required when orchestrating changes in an order amongst different types of servers. 472 | 473 | ### What firewall rules need to be enabled for Chef client 474 | - The Chef client communicates to the Chef server over https (port 443) or http (port 80). 475 | 476 | ### The Chef client converge intervals and how to invoke immediate updates 477 | - Converge intervals are configured by the Chef client cookbook that you would include in your run list. Push jobs would be employed to invoke immediate updates. 478 | 479 | ## RECOMMENDED WORKFLOWS 480 | *Candidates should understand:* 481 | 482 | ### What wrapper cookbooks are 483 | - A wrapper cookbook is the main cookbook that you write that you include dependent cookbooks inside that don't contain all of the functionality that you need. The wrapper would extend the dependent cookbook to include the additional functionality that you need. 484 | 485 | ### How to use source control, e.g. GitHub 486 | - Storing your repos and cookbooks in source control, such as GitHub, allows you to collaborate with others on development as well as branch, fork, and promote. 487 | 488 | ### How to use the TDD approach 489 | - TDD allows you to develop based on red/green/refactor. You first test for the desired state, and when it fails you write the desired state in your recipe. You then test again, and it passes. This is done with Test Kitchen. 490 | 491 | # CHEF WORKFLOW BASICS 492 | 493 | ## CONTINUOUS DELIVERY 494 | *Candidates should understand:* 495 | 496 | ### What continuous delivery (CD) is 497 | - Continuous delivery is a software engineering approach in which teams produce software in short cycles, ensuring that the software can be reliably released at any time. It aims at building, testing, and releasing software faster and more frequently. (Wikipedia) 498 | 499 | ### What role Chef plays in CD 500 | - Chef allows for TDD with Test Kitchen, which produces reliability. And storing in source control makes it easier to develop collaboratively, leading to faster releases as the most reliable and stable branches are promoted through the environments. 501 | 502 | ### When to run tests 503 | - Tests should be run every time a change is made or the node is converged. 504 | 505 | ### Why automated configuration management is critical to CD 506 | - Uniformity through automation minimizes error. 507 | 508 | ### Why CD is *more* secure than manual processes 509 | - Removing the risk of human error, you can see your infrastructure and compliance as code, seeing its state in code before it is actually changed. 510 | 511 | ## USING COMPLIANCE TO SCAN 512 | *Candidates should understand:* 513 | 514 | ### The benefits of the agentless nature of Chef compliance 515 | - A test is more reliable if nothing is installed on the node being installed because you don't have to change the state of the node being tested; you merely have to inspect it. 516 | 517 | ### How to check for compliance on nodes that don't have the Chef client installed 518 | - You simply need to be able to have remote access into the node in order for the InSpec framework to use your profile to scan the node being inspected. 519 | 520 | ### Basic use cases for compliance 521 | - Regulatory security and compliance standards 522 | - Configuration validation 523 | - State discovery 524 | 525 | ### What language is used to express compliance requirements 526 | - InSpec 527 | 528 | ## USING CHEF DK TO TEST YOUR CHANGES 529 | *Candidates should understand:* 530 | 531 | ### The Test Kitchen value proposition 532 | - Test Kitchen is at the heart of TDD within Chef. Being able to test your configuration before changing the state of your machine is invaluable because you can configure the state of a throw-away machine without having to change your actual infrastructure. 533 | 534 | ### Basic use cases for Chef DK 535 | - cookbook development (as well as other node data such as roles and environments) 536 | - bootstrapping nodes with the Chef client 537 | - communicating with the Chef server 538 | 539 | ## PUBLISHING ARTIFACTS TO CHEF SERVER AND SUPERMARKET 540 | *Candidates should understand:* 541 | 542 | ### How to publish artifacts to Chef server 543 | - One would use a `knife` command to upload artifacts to the Chef server. 544 | 545 | ### What Berkshelf is 546 | - Berkshelf is a tool which one can use to upload artifacts such as cookbooks to the Chef server. 547 | 548 | ### If the Chef Automate workflow feature can push artifacts to things other than a Chef server or Supermarket 549 | - Yes, Chef Automate can push artifacts to places like GitHub or production servers. 550 | 551 | ### How to manage cookbook dependencies 552 | - Each cookbook that a cookbook is dependent upon must be included in that cookbook's metadata. After executing a `berks install`, 553 | 554 | ## UNDERSTANDING BASIC CHEF CODE 555 | 556 | ## APPROACHABLE CUSTOM CODE 557 | *Candidates should understand:* 558 | 559 | ### How to recognize custom code 560 | - Chef is a thin domain-specific-language, meaning that it was built on top of Ruby. This means that you're able to easily customize with Ruby. 561 | 562 | ### How to use libraries 563 | - Ruby code can be stored in a cookbook's `libraries` directory and can be implemented / called anywhere in the cookbook's recipes or custom resources. 564 | 565 | ### How to customize Chef 566 | - Chef is a thin domain-specific-language, meaning that it was built on top of Ruby. This means that you're able to easily customize with Ruby. 567 | 568 | ## APPROACHABLE CHEF CODE 569 | *Candidates should understand:* 570 | 571 | ### How to read a recipe that includes the 'package', 'file', and 'service' resources and describe its intent. 572 | - (studied in kata) 573 | -------------------------------------------------------------------------------- /deploying-cookbooks/README.md: -------------------------------------------------------------------------------- 1 | # Deploying Cookbooks 2 | 3 | You can expect this 2 part exam to be tougher than the Basic Chef Fluency badge. This particular badge provides an alternative path to becoming `Certified Chef Developer`, so if you already have `Basic Chef Fluency` and `Local Cookbook Development` badges, then if you pass this badge you will become Certified. Yay! 4 | 5 | If you're rusty, I suggest going through the [kata](https://github.com/anniehedgpeth/chef-certification-study-guides/blob/master/basic-chef-fluency/basic-chef-fluency-kata.md) in the Basic Chef Fluency study guide. 6 | 7 | Otherwise, study up on the concepts listed in the [guide](https://github.com/anniehedgpeth/chef-certification-study-guides/blob/master/deploying-cookbooks/deploying-cookbooks-study-guide.md). 8 | 9 | ## Notes from my test-taking experience 10 | 1. Not being able to use dual-screens was a nuisance during the lab. 11 | 2. The first like 7 or so questions were nothing I encounter on a regular basis - lots of chef-solo. I had no clue. It felt like a disproportionate amount of questions, not a reflection of real-life use cases (to me, at least). 12 | 3. Using docs.chef.io was super awesome - much like real life. 13 | 4. It was not clear to me that I could click on the link to go directly to the chef server UI. I thought I had to configure the connection to chef server manually via the command line, which I’ve never done, so I spent a ton of time messing with that before I realized that I could go into the UI. Hence, I ran out of time and didn’t finish. And the lab questions I did get to were rushed. 14 | 5. The lab was great once I figured that out. It was common, everyday stuff that everyone should know. If I had it my way, I would have done more of those questions and less of the first 10 multiple choice, which I feel like weren’t a reflection of my overall knowledge of Chef. 15 | 6. I would have liked to have done the lab first and then the multiple choice questions, for timing. -------------------------------------------------------------------------------- /deploying-cookbooks/deploying-cookbooks-study-guide.md: -------------------------------------------------------------------------------- 1 | # Study Sheet for DEPLOYING COOKBOOKS 2 | 3 | > The topics for this guide are taken directly from [training.chef.io](https://training.chef.io/static/Deploying_Cookbooks.pdf). I copied the bulleted lists, and I filled in the study information from either my own understanding or from docs.chef.io. 4 | 5 | The Deploying Cookbooks badge is awarded when someone proves that they understand 6 | how to use Chef server to manage nodes and ensure they're in their expected state. 7 | 8 | Candidates must show: 9 | - An understanding of the chef-client run phases. 10 | - An understanding of using Roles and Environments. 11 | - An understanding of maintaining cookbooks on the Chef server. 12 | - An understanding of using knife. 13 | - An understanding of using how bootstrapping works. 14 | - An understanding of what policy files are. 15 | - An understanding of what Chef solo is. 16 | - An understanding of using search. 17 | - An understanding of databags. 18 | 19 | Here is a detailed breakdown of each area. 20 | 21 | # ANATOMY OF A CHEF RUN 22 | 23 | ## CHEF-CLIENT OPERATION 24 | _Candidates should understand:_ 25 | - chef-client modes of operation 26 | ` -z`, `--local-mode` 27 | Run the chef-client in local mode. This allows all commands that work against the Chef server to also work against the local chef-repo. 28 | 29 | - Configuring chef-client 30 | 31 | _A sample client.rb file that contains the most simple way to connect to https://manage.chef.io:_ 32 | 33 | ``` 34 | log_level :info 35 | log_location STDOUT 36 | chef_server_url 'https://api.chef.io/organizations/' 37 | validation_client_name '-validator' 38 | validation_key '/etc/chef/validator.pem' 39 | client_key '/etc/chef/client.pem' 40 | ``` 41 | 42 | ## COMPILE VS EXECUTE 43 | _The chef-client processes recipes in two phases:_ 44 | 45 | _First, each resource in the node object is identified and a resource collection is built. All recipes are loaded in a specific order, and then the actions specified within each of them are identified. This is also referred to as the “compile phase”._ 46 | 47 | _Next, the chef-client configures the system based on the order of the resources in the resource collection. Each resource is mapped to a provider, which then examines the node and performs the necessary steps to complete the action. This is also referred to as the “execution phase”._ 48 | 49 | _Typically, actions are processed during the execution phase of the chef-client run. However, sometimes it is necessary to run an action during the compile phase. For example, a resource can be configured to install a package during the compile phase to ensure that application is available to other resources during the execution phase._ 50 | 51 | > Note: Use the chef_gem resource to install gems that are needed by the chef-client during the execution phase. 52 | 53 | _Candidates should understand:_ 54 | - What happens during the 'compile' phase? 55 | 56 | _The chef-client identifies each resource in the node object and builds the resource collection. Libraries are loaded first to ensure that all language extensions and Ruby classes are available to all resources. Next, attributes are loaded, followed by lightweight resources, and then all definitions (to ensure that any pseudo-resources within definitions are available). Finally, all recipes are loaded in the order specified by the expanded run-list. This is also referred to as the “compile phase”._ 57 | 58 | - What happens during the 'execute' phase? 59 | 60 | _The chef-client configures the system based on the information that has been collected. Each resource is executed in the order identified by the run-list, and then by the order in which each resource is listed in each recipe. Each resource in the resource collection is mapped to a provider. The provider examines the node, and then does the steps necessary to complete the action. And then the next resource is processed. Each action configures a specific part of the system. This process is also referred to as convergence. This is also referred to as the “execution phase”._ 61 | 62 | 63 | - What happens when you place some Ruby at the start of a recipe? 64 | 65 | _It is compiled during the compile phase._ 66 | 67 | - What happens when you place some Ruby at the end of a recipe? 68 | 69 | _It is compiled during the compile phase._ 70 | 71 | - When are attributes evaluated? 72 | 73 | _during the compile phase_ 74 | 75 | - What happens during a 'node.save' operation?" 76 | 77 | _It sends the node object details to the Chef server._ 78 | 79 | > per https://discourse.chef.io/t/node-save/2080/8 80 | `node.save?` _is used explicitly when information must be saved, even if the chef run fails. Otherwise, default is for the node information to be given to the Chef server after a successful chef-client run._ 81 | 82 | _A good example is when a random password (e.g. for MySQL) has been generated and applied to the database. If you don’t call node.save and the run fails, then the next run will generate a new password which doesn’t match the password in the database so access to the database will fail._ 83 | 84 | _By calling `node.save` right after generating the password but before applying it to the database, you ensure that even when the chef run fails later on, the same password will be used in subsequent chef runs._ 85 | 86 | _Chef doesn't save the node when the run fails because, by default, Chef would have no way of knowing whether that is a desirable thing to do. There may be something in your recipes that you wouldn’t want saved until the full convergence finished._ 87 | 88 | ## RUN_STATUS 89 | _Candidates should understand:_ 90 | - How can you tap into the chef-client run? 91 | 92 | https://docs.chef.io/handlers.html#run-status-object 93 | _Use a handler to identify situations that arise during a chef-client run, and then tell the chef-client how to handle these situations when they occur._ 94 | 95 | - What is ‘run_status’? 96 | 97 | _Tracks various aspects of a Chef run, including the Node and RunContext, start and end time, and any Exception that stops the run. RunStatus objects are passed to any notification or exception handlers at the completion of a Chef run._ 98 | _The run_status object is initialized by the chef-client before the report interface is run for any handler. The run_status object keeps track of the status of the chef-client run and will contain some (or all) of the following properties:_ 99 | 100 | ``` 101 | all_resources 102 | backtrace 103 | elapsed_time 104 | end_time 105 | exception 106 | failed? 107 | node 108 | run_context 109 | start_time 110 | success? 111 | updated_resources 112 | ``` 113 | 114 | - What is ‘run_state’? 115 | 116 | _The start of the chef-client run_ 117 | 118 | `node.run_state` 119 | _Use `node.run_state` to stash transient data during a `chef-client` run. This data may be passed between resources, and then evaluated during the *execution* phase. `run_state` is an empty Hash that is always discarded at the end of the `chef-client` run._ 120 | 121 | ``` 122 | package 'httpd' do 123 | action :install #installs the Apache web server 124 | end 125 | 126 | ruby_block 'randomly_choose_language' do 127 | block do 128 | if Random.rand > 0.5 #randomly choose PHP or Perl as the scripting language 129 | node.run_state['scripting_language'] = 'php' 130 | else 131 | node.run_state['scripting_language'] = 'perl' 132 | end 133 | end 134 | end 135 | 136 | package 'scripting_language' do # install that scripting language 137 | package_name lazy { node.run_state['scripting_language'] } # lazy ensures that it evaluates this during execution, not compile 138 | action :install 139 | end 140 | ``` 141 | 142 | - What is the ‘resource collection’? 143 | 144 | _During the compile phase of the `chef-client` run, when it is loading all of the cookbooks, all of the resources are compiled and set to run in order._ 145 | 146 | _ResourceCollection currently handles two tasks:_ 147 | _1) Keeps an ordered list of resources to use when converging the node_ 148 | _2) Keeps a unique list of resources (keyed as `type[name]`) used for notifications_ 149 | 150 | ## AUTHENTICATION 151 | _Candidates should understand:_ 152 | - How does the chef-client authenticate with the Chef Server? 153 | 154 | _A client is an actor that has permission to access the Chef server. A client is most often a node (on which the chef-client runs), but is also a workstation (on which knife runs), or some other machine that is configured to use the Chef server API. Each request to the Chef server that is made by a client uses a private key for authentication that must be authorized by the public key on the Chef server._ 155 | 156 | - Authentication and using NTP 157 | 158 | _In some cases, the chef-client may receive a 401 response to the authentication request and a 403 response to an authorization request. If the authentication is happening on the node, NTP may be a cause. The system clock has drifted from the actual time by more than 15 minutes. This can be fixed by syncing the clock with an Network Time Protocol (NTP) server._ 159 | 160 | ## CHEF COMPILE PHASE 161 | https://docs.chef.io/chef_client_overview.html 162 | _Candidates should understand:_ 163 | - Do all cookbooks always get downloaded? 164 | 165 | _No, they get synchronized. The chef-client asks the Chef server for a list of all cookbook files (including recipes, templates, resources, providers, attributes, libraries, and definitions) that will be required to do every action identified in the run-list for the rebuilt node object. The Chef server provides to the chef-client a list of all of those files. The chef-client compares this list to the cookbook files cached on the node (from previous chef-client runs), and then downloads a copy of every file that has changed since the previous chef-client run, along with any new files._ 166 | 167 | - What about dependencies, and their dependencies? 168 | 169 | _When a chef-client is run, it will perform all of the steps that are required to bring the node into the expected state, including synchronizing cookbooks and compiling the resource collection by loading each of the required cookbooks, including recipes, attributes, and all other dependencies._ 170 | 171 | - What order do the following get loaded - libraries, attributes, resources/providers, definitions, recipes? 172 | 173 | ``` 174 | attributes 175 | resources/providers 176 | libraries 177 | definitions 178 | recipes 179 | ``` 180 | 181 | ## CONVERGENCE 182 | _Candidates should understand:_ 183 | - What happens during the execute phase of the chef-client run? 184 | 185 | _The chef-client configures the system based on the information that has been collected. Each resource is executed in the order identified by the run-list, and then by the order in which each resource is listed in each recipe. Each resource in the resource collection is mapped to a provider. The provider examines the node, and then does the steps necessary to complete the action. And then the next resource is processed. Each action configures a specific part of the system. This process is also referred to as convergence. This is also referred to as the “execution phase”._ 186 | 187 | - The test/repair model 188 | 189 | _Chef-client "tests" the node to see if it is in the desired state as defined by the compilation of resources. If it is not, then it is "repaired" to be in that desired state._ 190 | 191 | - When do notifications get invoked? 192 | 193 | _During resource collection - A notification is a property on a resource that listens to other resources in the resource collection and then takes actions based on the notification type (notifies or subscribes)._ 194 | 195 | - What happens if there are multiple start notifications for a particular resource? 196 | 197 | _It is started the first time and is tested for being started each additional time but not restarted._ 198 | 199 | - When is node data sent to the Chef Server? 200 | 201 | _after a successful chef-client run unless explicitly told to send it sooner by using_ `node.save?` 202 | 203 | ## WHY-RUN 204 | _Candidates should understand:_ 205 | - What is the purpose of `why-run` 206 | 207 | ` -W`, `--why-run` 208 | 209 | _A type of `chef-client` run that does everything except modify the system. Use why-run mode to understand why the chef-client makes the decisions that it makes and to learn more about the current and proposed state of the system._ 210 | 211 | - How do you invoke a ‘why-run’ 212 | 213 | `chef-client -W` `chef-client --why-run` 214 | 215 | - What are limitations of doing a why run? 216 | 217 | _Because it is not modifying the system, the notifications are not accurate since certain resources don't get triggered from them._ 218 | 219 | # ENVIRONMENTS 220 | 221 | ## WHAT IS AN ENVIRONMENT/USE CASES 222 | _Candidates should understand:_ 223 | - What is the purpose of an Environments? 224 | 225 | _An environment is a way to map an organization’s real-life workflow to what can be configured and managed when using Chef server. Additional environments can be created to reflect each organization’s patterns and workflow. For example, creating production, staging, testing, and development environments. Generally, an environment is also associated with one (or more) cookbook versions._ 226 | 227 | - What is the '_default' environment? 228 | 229 | _Every organization begins with a single environment called the _default environment, which cannot be modified (or deleted)._ 230 | 231 | - What information can be specified in an Environment? 232 | 233 | _cookbook, description, name, default attributes, override attributes, cookbook versions_ 234 | 235 | - What happens if you do not specify an Environment? 236 | 237 | _It defaults to using `_default` environment._ 238 | 239 | - Creating environments in Ruby 240 | 241 | _A Ruby file for each non-default environment must exist in the environments/ subdirectory of the chef-repo. (If the chef-repo does not have this subdirectory, then it should be created.) The complete environment has the following syntax:_ 242 | ``` 243 | name 'environment_name' 244 | description 'environment_description' 245 | cookbook OR cookbook_versions 'cookbook' OR 'cookbook' => 'cookbook_version' 246 | default_attributes 'node' => { 'attribute' => [ 'value', 'value', 'etc.' ] } 247 | override_attributes 'node' => { 'attribute' => [ 'value', 'value', 'etc.' ] } 248 | ``` 249 | - Creating environments in JSON 250 | 251 | _The JSON format for environments maps directly to the domain-specific Ruby format: the same settings, attributes, and values, and a similar structure and organization, just formatted as JSON. When an environment is defined as JSON the file that contains that data must be defined as a file that ends with .json. For example:_ 252 | ``` 253 | { 254 | "name": "dev", 255 | "default_attributes": { 256 | "apache2": { 257 | "listen_ports": [ 258 | "80", 259 | "443" 260 | ] 261 | } 262 | }, 263 | "json_class": "Chef::Environment", 264 | "description": "", 265 | "cookbook_versions": { 266 | "couchdb": "= 11.0.0" 267 | }, 268 | "chef_type": "environment" 269 | } 270 | ``` 271 | _The JSON format has two additional settings:_ 272 | 273 | `chef_type` _Always set this to environment. Use this setting for any custom process that consumes environment objects outside of Ruby._ 274 | 275 | `json_class` _Always set this to Chef::Environment. The chef-client uses this setting to auto-inflate an environment object. If objects are being rebuilt outside of Ruby, ignore it._ 276 | 277 | - Using environments within a search 278 | 279 | _When searching, an environment is an attribute._ 280 | ```knife search node "chef_environment:QA AND platform:centos"``` 281 | 282 | _Or in a recipe_ 283 | ```qa_nodes = search(:node,"chef_environment:QA") 284 | qa_nodes.each do |qa_node| 285 | # Do useful work specific to qa nodes only 286 | end 287 | ``` 288 | 289 | ## ATTRIBUTE PRECEDENCE AND COOKBOOK CONSTRAINTS 290 | _Candidates should understand:_ 291 | - What attribute precedence levels are available for Environments 292 | 293 | https://docs.chef.io/roles.html#attribute-precedence 294 | 295 | _`default` and `override` 296 | 297 | - Overriding Role attributes 298 | 299 | `override` _Applying environment override attributes after role override attributes allows the same role to be used across multiple environments, yet ensuring that values can be set that are specific to each environment (when required)._ 300 | 301 | - Syntax for setting cookbook constraints. 302 | ``` 303 | "cookbook_versions": { 304 | "couchdb": "= 11.0.0" 305 | }, 306 | ``` 307 | - How would you allow only patch updates to a cookbook within an environment? 308 | ``` 309 | "cookbook_versions": { 310 | "couchdb": "~> 11.0.0" 311 | }, 312 | ``` 313 | 314 | ## SETTING AND VIEWING ENVIRONMENTS 315 | _Candidates should understand:_ 316 | - How can you list Environments? 317 | ``` 318 | $ knife environment list 319 | ``` 320 | - How can you move a node to a specific Environment? 321 | ``` 322 | $ knife node environment_set NODE_NAME ENVIRONMENT_NAME (options) 323 | ``` 324 | - Using `knife exec` to bulk change Environments. 325 | ``` 326 | knife exec -E "nodes.transform(“chef_environment:dev“) \ 327 | {|n| puts n.run_list.remove(“recipe[chef-client::upgrade]“); n.save }" 328 | ``` 329 | - Using 'chef_environment' global variable in recipes 330 | ``` 331 | if node.chef_environment == "dev" 332 | # stuff 333 | end 334 | ``` 335 | - Environment specific knife plugins, e.g. `knife flip` 336 | 337 | `knife-flip` - _A knife plugin to move a node, or all nodes in a role, to a specific environment__ 338 | 339 | `knife-bulkchangeenv` - _A plugin for Chef::Knife which lets you move all nodes in one environment into another._ 340 | 341 | `knife-env-diff` - _Adds the ability to diff the cookbook versions for two (or more) environments._ 342 | 343 | `knife-set-environment` - _Adds the ability to set a node environment._ 344 | 345 | `knife-spork` - _Adds a simple environment workflow so that teams can more easily work together on the same cookbooks and environments._ 346 | 347 | `knife-whisk` - _Adds the ability to create new servers in a team environment._ 348 | 349 | - Bootstrapping a node into a particular Environment 350 | ``` 351 | knife bootstrap --run-list 'cookbook::default' --environment 'dev' -x 'annie' -i '~/.ssh/id_rsa' -- 352 | sudo -N 'prep-node' 353 | ``` 354 | 355 | # ROLES 356 | 357 | ## USING ROLES 358 | _Candidates should understand:_ 359 | - What is the purpose of a Role? 360 | - Creating Roles 361 | - Role Ruby & JSON DSL formats 362 | - Pros and Cons of Roles 363 | Pros - one team can have some control over adding their specific run-lists. 364 | Cons - That team's run-list could mess with everyone else's stuff. 365 | 366 | - The Role cookbook pattern 367 | Wrappers 368 | 369 | - Creating Role cookbooks 370 | - Using Roles within a search 371 | `knife search role '*:*'` 372 | 373 | ## SETTING ATTRIBUTES AND ATTRIBUTE PRECEDENCE 374 | _Candidates should understand:_ 375 | - What attribute precedence levels are available for Roles 376 | 377 | https://docs.chef.io/roles.html#attribute-precedence 378 | 379 | _`default` and `override` 380 | 381 | - Setting attribute precedence 382 | 383 | _The attribute precedence order for roles and environments is reversed for `default` and `override` attributes. The precedence order for `default` attributes is environment, then role. The precedence order for `override` attributes is role, then environment. Applying environment `override` attributes after role `override` attributes allows the same role to be used across multiple environments, yet ensuring that values can be set that are specific to each environment (when required). For example, the role for an application server may exist in all environments, yet one environment may use a database server that is different from other environments._ 384 | 385 | ## BASE ROLE & NESTED ROLES 386 | _Candidates should understand:_ 387 | - What are nested roles? 388 | - Whats the purpose of a ‘base’ role? 389 | 390 | ## USING KNIFE 391 | _Candidates should understand:_ 392 | - The `knife role` command 393 | - How would you set the run_list for a node using `knife`? 394 | - Listing nodes 395 | - View role details 396 | - Using Roles within a search 397 | 398 | # UPLOADING COOKBOOKS TO CHEF SERVER 399 | 400 | ## USING BERKSHELF 401 | _Candidates should understand:_ 402 | - The Berksfile & Berksfile.lock 403 | - `berks install` and `berks upload` 404 | - Where are dependant cookbooks stored locally? 405 | - Limitations of using knife to upload cookbooks 406 | - Listing cookbooks on Chef Server using knife 407 | - What happens if you try to upload the same version of a cookbook? 408 | - How can you upload the same version of a cookbook? 409 | - Downloading cookbooks from Chef Server 410 | - Bulk uploading cookbooks using knife 411 | 412 | # USING KNIFE 413 | 414 | ## BASIC KNIFE USAGE 415 | _Candidates should understand:_ 416 | - How does knife know what Chef Server to interact with? 417 | from the chef server url in the `knife.rb` 418 | 419 | - How does knife authenticate with Chef Server 420 | with a validator key (user.pem or org.pem) 421 | 422 | - How/When would you use `knife ssh` & `knife winrm`? 423 | Use the knife ssh subcommand to invoke SSH commands (in parallel) on a subset of nodes within an organization, based on the results of a search query made to the Chef server. For example: 424 | ``` 425 | $ knife ssh "role:webserver" "sudo chef-client" 426 | ``` 427 | - Verifying ssl certificate authenticity using knife 428 | The SSL certificates that are used by the chef-client may be verified by specifying the path to the client.rb file. Use the --config option (that is available to any knife command) to specify this path: 429 | ``` 430 | $ knife ssl check --config /etc/chef/client.rb 431 | ``` 432 | Verify an external server’s SSL certificate 433 | ``` 434 | $ knife ssl check URL_or_URI 435 | ``` 436 | for example: 437 | ``` 438 | $ knife ssl check https://www.chef.io 439 | ``` 440 | - Where can/should you run the `knife` command from? 441 | from anywhere in the chef repo of your desired org 442 | 443 | ## KNIFE CONFIGURATION 444 | _Candidates should understand:_ 445 | - How/where do you configure knife? 446 | in the `.chef/knife.rb` 447 | 448 | - Common options - cookbook_path, validation_key, chef_server_url, validation_key 449 | ``` 450 | # See http://docs.chef.io/config_rb_knife.html for more information on knife configuration options 451 | 452 | current_dir = File.dirname(__FILE__) 453 | log_level :info 454 | log_location STDOUT 455 | node_name "nodename" 456 | client_key "#{current_dir}/user.pem" 457 | chef_server_url "https://api.chef.io/organizations/orgname" 458 | cookbook_path ["#{current_dir}/../cookbooks"] 459 | ``` 460 | - Setting the chef-client version to be installed during bootstrap 461 | ```$ knife bootstrap FQDN_or_IP_ADDRESS (options) 462 | ``` 463 | `--bootstrap-version VERSION` - The version of the chef-client to install. 464 | 465 | - Setting defaults for command line options in knife’s configuration file 466 | To add settings to the `knife.rb` file, use the following syntax: 467 | ``` 468 | knife[:setting_name] = value 469 | ``` 470 | where value may require quotation marks (‘ ‘) if that value is a string. For example: 471 | ``` 472 | knife[:ssh_port] = 22 473 | knife[:bootstrap_template] = 'ubuntu14.04-gems' 474 | knife[:bootstrap_version] = '' 475 | knife[:bootstrap_proxy] = '' 476 | ``` 477 | - Using environment variables and sharing knife configuration file with your team 478 | Add environment variables to the `knife.rb` and share the file among your team. For example: 479 | ``` 480 | current_dir = File.dirname(__FILE__) 481 | user = ENV['OPSCODE_USER'] || ENV['USER'] 482 | node_name user 483 | client_key "#{ENV['HOME']}/chef-repo/.chef/#{user}.pem" 484 | validation_client_name "#{ENV['ORGNAME']}-validator" 485 | validation_key "#{ENV['HOME']}/chef-repo/.chef/#{ENV['ORGNAME']}-validator.pem" 486 | chef_server_url "https://api.opscode.com/organizations/#{ENV['ORGNAME']}" 487 | syntax_check_cache_path "#{ENV['HOME']}/chef-repo/.chef/syntax_check_cache" 488 | cookbook_path ["#{current_dir}/../cookbooks"] 489 | cookbook_copyright "Your Company, Inc." 490 | cookbook_license "apachev2" 491 | cookbook_email "cookbooks@yourcompany.com" 492 | 493 | # Amazon AWS 494 | knife[:aws_access_key_id] = ENV['AWS_ACCESS_KEY_ID'] 495 | knife[:aws_secret_access_key] = ENV['AWS_SECRET_ACCESS_KEY'] 496 | ``` 497 | 498 | - Managing proxies 499 | In an environment that requires proxies to reach the Internet, many Chef commands will not work until they are configured correctly. To configure Chef to work in an environment that requires proxies, set the `http_proxy`, `https_proxy`, `ftp_proxy`, and/or `no_proxy` environment variables to specify the proxy settings using a lowercase value. 500 | 501 | ## KNIFE PLUGINS 502 | _Candidates should understand:_ 503 | - Common knife plugins 504 | 505 | _Knife functionality can be extended with plugins, which work the same as built-in subcommands (including common options). Knife plugins have been written to interact with common cloud providers, to simplify common Chef tasks, and to aid in Chef workflows._ `chef gem install PLUGIN_NAME` 506 | 507 | ``` 508 | knife-acl 509 | knife-azure 510 | knife-ec2 511 | knife-eucalyptus 512 | knife-google 513 | knife-linode 514 | knife-lpar 515 | knife-openstack 516 | knife-push 517 | knife-rackspace 518 | knife-vcenter 519 | knife-windows 520 | ``` 521 | 522 | - What is 'knife ec2' plugin 523 | 524 | _The knife ec2 subcommand is used to manage API-driven cloud servers that are hosted by Amazon EC2. ex:_ `knife ec2 server create -r 'role[webserver]' -I ami-cd0fd6be -f t2.micro --aws-access-key-id 'Your AWS Access Key ID' --aws-secret-access-key "Your AWS Secret Access Key"` 525 | 526 | - What is `knife windows` plugin 527 | 528 | _The `knife windows` subcommand is used to configure and interact with nodes that exist on server and/or desktop machines that are running Microsoft Windows. Nodes are configured using WinRM, which allows native objects—batch scripts, Windows PowerShell scripts, or scripting library variables—to be called by external applications. The `knife windows` subcommand supports NTLM and Kerberos methods of authentication. ex:_ `knife bootstrap windows winrm web1.cloudapp.net -r 'server::web' -x 'proddomain\webuser' -P 'password'` 529 | 530 | 531 | - What is ‘knife block’ plugin? 532 | 533 | https://github.com/knife-block/knife-block 534 | 535 | _The `knife block` plugin has been created to enable the use of multiple knife.rb files against multiple chef servers. The premise is that you have a "block" in which you store all your "knives" and you can choose the one best suited to the task. Knife looks for `knife.rb` in `~/.chef` - all this script does is create a symlink from the required configuration to knife.rb so that knife can act on the appropriate server. ex:_ `knife block use ` 536 | 537 | - What is ‘knife spork’ plugin? 538 | 539 | _The `knife-spork` plugin adds workflow that enables multiple developers to work on the same Chef server and repository, but without stepping on each other’s toes. This plugin is designed around the workflow at Etsy, where several people work in the same repository and Chef server simultaneously. ex:_ `knife spork bump` 540 | 541 | - Installing knife plugins 542 | ``` 543 | chef gem install PLUGIN_NAME 544 | ``` 545 | 546 | ## TROUBLESHOOTING 547 | _Candidates should understand:_ 548 | - Troubleshooting Authentication 549 | - Using `knife ssl check` command 550 | 551 | _Use the `knife ssl check` subcommand to verify the SSL configuration for the Chef server or a location specified by a URL or URI. Invalid certificates will not be used by OpenSSL. When this command is run, the certificate files (`*.crt` and/or `*.pem`) that are located in the `/.chef/trusted_certs` directory are checked to see if they have valid X.509 certificate properties. A warning is returned when certificates do not have valid X.509 certificate properties or if the `/.chef/trusted_certs` directory does not contain any certificates._ `knife ssl check (options)` 552 | 553 | - Using `knife ssl fetch` command 554 | 555 | _Run the `knife ssl fetch` to download the self-signed certificate from the Chef server to the `/.chef/trusted_certs` directory on a workstation._ 556 | 557 | - Using '-VV' flag 558 | 559 | `-V`, `--verbose` Set for more verbose outputs. Use `-VV` for maximum verbosity. 560 | 561 | - Setting log levels and log locations 562 | 563 | _Use the log resource to create log entries. The log resource behaves like any other resource: built into the resource collection during the compile phase, and then run during the execution phase. (To create a log entry that is not built into the resource collection, use `Chef::Log` instead of the log resource.)_ 564 | 565 | ``` 566 | log 'message' do 567 | message 'A message add to the log.' 568 | level :info 569 | end 570 | ``` 571 | 572 | _Log Level Syntax_ 573 | `Fatal` `Chef::Log.fatal('string')` 574 | `Error` `Chef::Log.error('string')` 575 | `Warn` `Chef::Log.warn('string')` 576 | `Info` `Chef::Log.info('string')` 577 | `Debug` `Chef::Log.debug('string')` 578 | 579 | # BOOTSTRAPPING 580 | 581 | ## USING KNIFE 582 | _Candidates should understand:_ 583 | - Common `knife bootstrap` options - UserName, Password, RunList, and Environment 584 | 585 | `-x USERNAME`, `--ssh-user USERNAME` - _The SSH user name._ 586 | 587 | `-P PASSWORD`, `--ssh-password PASSWORD` - _The SSH password. This can be used to pass the password directly on the command line. If this option is not specified (and a password is required) knife prompts for the password._ 588 | 589 | `-r RUN_LIST`, `--run-list RUN_LIST` - _A comma-separated list of roles and/or recipes to be applied._ 590 | 591 | `-E ENVIRONMENT`, `--environment ENVIRONMENT` - _The name of the environment. When this option is added to a command, the command will run only against the named environment._ 592 | 593 | - Using `winrm` & `ssh` 594 | 595 | _WINRM: Use the winrm argument to create a connection to one or more remote machines. As each connection is created, a password must be provided. This argument uses the same syntax as the search subcommand. WinRM requires that a target node be accessible via the ports configured to support access via HTTP or HTTPS._ `knife winrm SEARCH_QUERY SSH_COMMAND (options)` 596 | 597 | _SSH: Use the knife ssh subcommand to invoke SSH commands (in parallel) on a subset of nodes within an organization, based on the results of a search query made to the Chef server._ `knife ssh SEARCH_QUERY SSH_COMMAND (options)` 598 | 599 | - Using knife plugins for bootstrap - `knife ec2 ..`, `knife bootstrap windows ...` 600 | 601 | `knife ec2 server create` 602 | 603 | _Use the `bootstrap windows winrm` argument to bootstrap chef-client installations in a Microsoft Windows environment, using WinRM and the WS-Management protocol for communication. This argument requires the FQDN of the host machine to be specified. The Microsoft Installer Package (MSI) run silently during the bootstrap operation (using the /qn option). ex:_ `knife bootstrap windows winrm FQDN` 604 | 605 | 606 | ## BOOTSTRAP OPTIONS 607 | _Candidates should understand:_ 608 | - Validator' vs 'Validatorless' Bootstraps 609 | 610 | _The ORGANIZATION-validator.pem is typically added to the .chef directory on the workstation. When a node is bootstrapped from that workstation, the ORGANIZATION-validator.pem is used to authenticate the newly-created node to the Chef server during the initial chef-client run. Starting with Chef client 12.1, it is possible to bootstrap a node using the USER.pem file instead of the ORGANIZATION-validator.pem file. This is known as a “validatorless bootstrap”._ 611 | 612 | - Bootstrapping in FIPS mode, https://docs.chef.io/fips.html 613 | 614 | _If you have FIPS compliance enabled at the kernel level then chef-client will default to running in FIPS mode. Otherwise you can add `fips true` to the `/etc/chef/client.rb` or `C:\\chef\\client.rb.`_ 615 | 616 | _Bootstrap a node using FIPS_ 617 | ``` 618 | knife bootstrap 192.0.2.0 -P vanilla -x root -r 'recipe[apt],recipe[xfs],recipe[vim]' --fips 619 | ``` 620 | 621 | - What are Custom Templates 622 | 623 | https://docs.chef.io/knife_bootstrap.html#custom-templates 624 | _The default `chef-full` template uses the omnibus installer. For most bootstrap operations, regardless of the platform on which the target node is running, using the `chef-full` distribution is the best approach for installing the chef-client on a target node. In some situations, a custom template may be required._ 625 | 626 | ## UNATTENDED INSTALLS 627 | _Candidates should understand:_ 628 | - Configuring Unattended Installs 629 | 630 | _The method used to inject a user data script into a server will vary depending on the infrastructure platform being used. For example, on AWS you can pass this data in as a text file using the command line tool._ https://docs.chef.io/install_bootstrap.html#bootstrapping-with-user-data 631 | 632 | - What conditions must exists for unattended install to take place? 633 | 634 | _It is important that settings in the `client.rb` file —`chef_server_url`, `http_proxy`, and so on are used—to ensure that configuration details are built into the unattended bootstrap process._ 635 | 636 | 637 | ## FIRST CHEF-CLIENT RUN 638 | _Candidates should understand:_ 639 | - How does authentication work during the first chef-client run? (see next question) 640 | - What is ‘ORGANIZATION-validator.pem’ file and when is it used? 641 | 642 | _During the first chef-client run, the private key `/etc/chef/client.pem` does not exist. Instead, the `chef-client` will attempt to use the private key assigned to the `chef-validator`, located in `/etc/chef/validation.pem`. (If, for any reason, the `chef-validator` is unable to make an authenticated request to the Chef server, the initial `chef-client` run will fail.) During the initial `chef-client` run, the `chef-client` will register with the Chef server using the private key assigned to the `chef-validator`, after which the `chef-client` will obtain a `client.pem` private key for all future authentication requests to the Chef server._ 643 | 644 | - What is the ‘first-boot.json’ file? 645 | 646 | _Start the chef-client run:_ 647 | _On UNIX- and Linux-based machines: The second shell script executes the `chef-client` binary with a set of initial settings stored within `first-boot.json` on the node. `first-boot.json` is generated from the workstation as part of the initial `knife bootstrap` subcommand._ 648 | 649 | _On Microsoft Windows machines: The batch file that is derived from the `windows-chef-client-msi.erb` bootstrap template executes the `chef-client` binary with a set of initial settings stored within `first-boot.json` on the node. `first-boot.json` is generated from the workstation as part of the initial `knife bootstrap` subcommand._ 650 | 651 | # POLICY FILES 652 | 653 | ## BASIC KNOWLEDGE AND USAGE 654 | _Candidates should understand:_ 655 | - What are policyfiles, and what problems do they solve? 656 | 657 | _A Policyfile is an optional way to manage role, environment, and community cookbook data with a single document that is uploaded to the Chef server. The file is associated with a group of nodes, cookbooks, and settings. When these nodes perform a Chef client run, they utilize recipes specified in the Policyfile run-list._ 658 | 659 | _For some users of Chef, Policyfile will make it easier to test and promote code safely with a simpler interface. Policyfile improves the user experience and resolves real-world problems that some workflows built around Chef must deal with. The following sections discuss in more detail some of the good reasons to use Policyfile, including:_ 660 | 661 | _- Focus the workflow on the entire system_ 662 | _- Safer development workflows_ 663 | _- Less expensive computation_ 664 | _- Code visibility_ 665 | _- Role mutability_ 666 | _- Cookbook mutability_ 667 | _- Replaces Berkshelf and the environment cookbook pattern_ 668 | 669 | - Policyfile use cases? 670 | 671 | _When there is not a need for environments or roles._ 672 | 673 | - What can/not be configured in a policy file? 674 | 675 | _roles and environments_ 676 | 677 | - Policy files and Chef Workflow 678 | 679 | _Focused System Workflows: The knife command line tool maps very closely to the Chef server API and the objects defined by it: roles, environments, run-lists, cookbooks, data bags, nodes, and so on. The chef-client assembles these pieces at run-time and configures a host to do useful work._ 680 | 681 | _Policyfile focuses that workflow onto the entire system, rather than the individual components. For example, Policyfile describes whole systems, whereas each individual revision of the Policyfile.lock.json file uploaded to the Chef server describes a part of that system, inclusive of roles, environments, cookbooks, and the other Chef server objects necessary to configure that part of the system._ 682 | 683 | _Safer Workflows: Policyfile encourages safer workflows by making it easier to publish development versions of cookbooks to the Chef server without the risk of mutating the production versions and without requiring a complicated versioning scheme to work around cookbook mutability issues. Roles are mutable and those changes are applied only to the nodes specified by the policy. Policyfile does not require any changes to your normal workflows. Use the same repositories you are already using, the same cookbooks, and workflows. Policyfile will prevent an updated cookbook or role from being applied immediately to all machines._ 684 | 685 | # SEARCH 686 | 687 | ## BASIC SEARCH USAGE 688 | _Candidates should understand:_ 689 | - What information is indexed and available for search? 690 | 691 | _- client_ 692 | 693 | _- environment_ 694 | 695 | _- node_ 696 | 697 | _- role_ 698 | 699 | _- data bag_ 700 | 701 | - Search operators and query syntax 702 | 703 | _A search query is comprised of two parts: the key and the search pattern. A search query has the following syntax:_ `key:search_pattern` 704 | _where key is a field name that is found in the JSON description of an indexable object on the Chef server (a role, node, client, environment, or data bag) and search_pattern defines what will be searched for, using one of the following search patterns: exact, wildcard, range, or fuzzy matching. Both key and search_pattern are case-sensitive; key has limited support for multiple character wildcard matching using an asterisk (“*”) (and as long as it is not the first character)._ 705 | 706 | ``` 707 | knife search INDEX SEARCH_QUERY 708 | ``` 709 | _defaults to search for node_ 710 | ``` 711 | knife search '*:*' -i 712 | ``` 713 | _is the same as_ 714 | ``` 715 | $ knife search node '*:*' -i 716 | ``` 717 | 718 | - Wildcards, range and fuzzy matching 719 | 720 | _- To search for any node that contains the specified key, enter the following:_ `knife search node 'foo:*'` 721 | _- To search using an inclusive range, enter the following:_ `knife search sample "id:[bar TO foo]"` 722 | _- To use a fuzzy search pattern enter something similar to:_ `knife search client "name:boo~"` 723 | 724 | 725 | ## SEARCH USING KNIFE AND IN A RECIPE 726 | _Candidates should understand:_ 727 | - Knife command line search syntax 728 | 729 | ``` 730 | knife search INDEX SEARCH_QUERY 731 | ``` 732 | 733 | - Recipe search syntax 734 | 735 | `search(:node, "key:attribute")` 736 | 737 | 738 | ## FILTERING RESULTS 739 | _Candidates should understand:_ 740 | - How do you filter on Chef Server 741 | 742 | _Use `:filter_result` as part of a search query to filter the search output based on the pattern specified by a Hash. Only attributes in the Hash will be returned._ 743 | 744 | _The syntax for the search method that uses :filter_result is as follows:_ 745 | ``` 746 | search(:index, 'query', 747 | :filter_result => { 'foo' => [ 'abc' ], 748 | 'bar' => [ '123' ], 749 | 'baz' => [ 'sea', 'power' ] 750 | } 751 | ).each do |result| 752 | puts result['foo'] 753 | puts result['bar'] 754 | puts result['baz'] 755 | end 756 | ``` 757 | _where:_ 758 | _- `:index` is of name of the index on the Chef server against which the search query will run: `:client`, `:data_bag_name`, `:environment`, `:node`, and `:role`_ 759 | _- 'query' is a valid search query against an object on the Chef server_ 760 | _- `:filter_result` defines a Hash of values to be returned_ 761 | 762 | _For example:_ 763 | 764 | ``` 765 | search(:node, 'role:web', 766 | :filter_result => { 'name' => [ 'name' ], 767 | 'ip' => [ 'ipaddress' ], 768 | 'kernel_version' => [ 'kernel', 'version' ] 769 | } 770 | ).each do |result| 771 | puts result['name'] 772 | puts result['ip'] 773 | puts result['kernel_version'] 774 | end 775 | ``` 776 | 777 | - Selecting attributes to be returned 778 | 779 | _Use :filter\_result as part of a search query to filter the search output based on the pattern specified by a Hash. Only attributes in the Hash will be returned._ 780 | 781 | # CHEF SOLO 782 | 783 | ## WHAT CHEF SOLO IS 784 | _Candidates should understand:_ 785 | - Advantages & disadvantages of Chef-solo vs Chef Server 786 | 787 | _chef-solo is a command that executes chef-client in a way that does not require the Chef server in order to converge cookbooks. chef-solo uses chef-client’s Chef local mode, and does not support the following functionality present in chef-client / server configurations:_ 788 | 789 | _- Centralized distribution of cookbooks_ 790 | _- A centralized API that interacts with and integrates infrastructure components_ 791 | _- Authentication or authorization_ 792 | 793 | - Chef-solo executable and options 794 | ``` 795 | chef-solo OPTION VALUE OPTION VALUE ... 796 | ``` 797 | _lots of options found here https://docs.chef.io/chef\_solo.html_ 798 | 799 | - Cookbooks, nodes and attributes 800 | 801 | _chef-solo supports two locations from which cookbooks can be run: 802 | _- A local directory._ 803 | _- A URL at which a tar.gz archive is located._ 804 | 805 | _Unlike chef-client, where the node object is stored on the Chef server, chef-solo stores its node objects as JSON files on local disk. By default, chef-solo stores these files in a nodes folder in the same directory as your cookbooks directory. You can control the location of this directory via the node_path value in your configuration file._ 806 | 807 | _chef-solo does not interact with the Chef server. Consequently, node-specific attributes must be located in a JSON file on the target system, a remote location (such as Amazon Simple Storage Service (S3)), or a web server on the local network._ 808 | 809 | - Using Data Bags, Roles & Environments 810 | 811 | _chef-solo will look for data bags in /var/chef/data_bags, but this location can be modified by changing the setting in solo.rb._ `data_bag_path '/var/chef-solo/data_bags'` 812 | 813 | _chef-solo will look for roles in /var/chef/roles, but this location can be modified by changing the setting for role_path in solo.rb._ `role_path '/var/chef-solo/roles'` 814 | 815 | _chef-solo will look for environments in /var/chef/environments, but this location can be modified by changing the setting for environment_path in solo.rb._ `environment_path '/var/chef-solo/environments'` 816 | 817 | - Chef-solo run intervals 818 | 819 | ``` 820 | -i SECONDS, --interval SECONDS 821 | ``` 822 | _The frequency (in seconds) at which the chef-client runs. When the chef-client is run at intervals, `--splay` and `--interval` values are applied before the chef-client run._ 823 | 824 | - Retrieving cookbooks from remote locations 825 | 826 | ``` 827 | -r RECIPE_URL, --recipe-url RECIPE_URL 828 | ``` 829 | _The URL location from which a remote cookbook tar.gz is to be downloaded._ 830 | 831 | - Chef-solo and node object 832 | 833 | # DATA BAGS 834 | 835 | ## WHAT IS A DATA_BAG 836 | _Candidates should understand:_ 837 | - When might you use a data_bag? 838 | 839 | _A data bag is a global variable that is stored as JSON data and is accessible from a Chef server. A data bag is indexed for searching and can be loaded by a recipe or accessed during a search. It is used when different clients need to access the same information._ 840 | 841 | - Indexing data_bags 842 | 843 | _Any search for a data bag (or a data bag item) must specify the name of the data bag and then provide the search query string that will be used during the search. For example, to use knife to search within a data bag named “admin\_data” across all items, except for the “admin\_users” item, enter the following:_ 844 | ``` 845 | knife search admin_data "(NOT id:admin_users)" 846 | ``` 847 | _Or, to include the same search query in a recipe, use a code block similar to:_ 848 | ``` 849 | search(:admin_data, "NOT id:admin_users") 850 | ``` 851 | _Data bags can be accessed through the search indexes. Use this approach when more than one data bag item is required or when the contents of a data bag are looped through. The search indexes will bulk-load all of the data bag items, which will result in a lower overhead than if each data bag item were loaded by name._ 852 | 853 | _To load the secret from a file:_ 854 | ``` 855 | data_bag_item('bag', 'item', IO.read('secret_file')) 856 | ``` 857 | _To load a single data bag item named admins:_ 858 | 859 | ``` 860 | data_bag('admins') 861 | ``` 862 | _The contents of a data bag item named justin:_ 863 | ``` 864 | data_bag_item('admins', 'justin') 865 | ``` 866 | 867 | - What is a data_bag? 868 | 869 | _A data bag is a global variable that is stored as JSON data and is accessible from a Chef server. A data bag is indexed for searching and can be loaded by a recipe or accessed during a search._ 870 | 871 | - Data_bag and Chef-solo 872 | 873 | _chef-solo can load data from a data bag as long as the contents of that data bag are accessible from a directory structure that exists on the same machine as chef-solo. The location of this directory is configurable using the data_bag_path option in the solo.rb file. The name of each sub-directory corresponds to a data bag and each JSON file within a sub-directory corresponds to a data bag item. Search is not available in recipes when they are run with chef-solo; use the data_bag() and data_bag_item() functions to access data bags and data bag items._ 874 | 875 | ## DATA_BAG ENCRYPTION 876 | _Candidates should understand:_ 877 | - How do you encrypt a data_bag 878 | 879 | _A data bag item is encrypted using a knife command similar to:_ 880 | ``` 881 | knife data bag create passwords mysql --secret-file /tmp/my_data_bag_key 882 | ``` 883 | _where “passwords” is the name of the data bag, “mysql” is the name of the data bag item, and “/tmp/my_data_bag_key” is the path to the location in which the file that contains the secret-key is located. knife will ask for user credentials before the encrypted data bag item is saved._ 884 | 885 | - What is Chef Vault 886 | 887 | _chef-vault is a RubyGems package that is included in the Chef development kit. chef-vault allows the encryption of a data bag item by using the public keys of a list of nodes, allowing only those nodes to decrypt the encrypted values. chef-vault uses the knife vault subcommand._ 888 | 889 | ## USING DATA_BAGS 890 | _Candidates should understand:_ 891 | - How do you create a data_bag? 892 | 893 | _knife can be used to create data bags and data bag items when the knife data bag subcommand is run with the create argument. For example:_ 894 | 895 | ``` 896 | knife data bag create DATA_BAG_NAME (DATA_BAG_ITEM) 897 | ``` 898 | _knife can be used to update data bag items using the from file argument:_ 899 | ``` 900 | knife data bag from file BAG_NAME ITEM_NAME.json 901 | ``` 902 | _As long as a file is in the correct directory structure, knife will be able to find the data bag and data bag item with only the name of the data bag and data bag item. For example:_ 903 | 904 | ``` 905 | knife data bag from file BAG_NAME ITEM_NAME.json 906 | ``` 907 | 908 | - How can you edit a data_bag 909 | 910 | _Continuing the example above, if you are in the “admins” directory and make changes to the file charlie.json, then to upload that change to the Chef server use the following command:_ 911 | ``` 912 | knife data bag from file admins charlie.json 913 | ``` -------------------------------------------------------------------------------- /local-cookbook-development/README.md: -------------------------------------------------------------------------------- 1 | # Local Cookbook Development 2 | 3 | You can expect this 2 part exam to be tougher than the Basic Chef Fluency badge. It will be heavily focused on Test Kitchen, InSpec, and just basically creating cookbooks. 4 | 5 | If you're rusty, I suggest going through the [kata](https://github.com/anniehedgpeth/chef-certification-study-guides/blob/master/basic-chef-fluency/basic-chef-fluency-kata.md) in the Basic Chef Fluency study guide. 6 | 7 | Otherwise, study up on the concepts listed in the [guide](https://github.com/anniehedgpeth/chef-certification-study-guides/blob/master/local-cookbook-development/local-cookbook-development-study-guide.md). 8 | 9 | # Notes from Exam's Lab 10 | - How to install 'IIS-WebServerRole' Windows Feature 11 | - How to install Windows Registry Keys (recursive true) 12 | - How to create a file with content and create the recursive directories 13 | 14 | # Notes about my Exam experience 15 | - There was not a visible timer, so you have to chat with the proctor to ask how much time is left, which wastes time. 16 | - If your internet connection is interrupted (mine was 6 times), they will give you the lost time, however, this is not ideal, because it makes you frantic and you can't go to the bathroom. 17 | - You may not use the restroom or else you forfeit the remainder of your time. 18 | - The setup may take a while since they have to scan your room and workspace, so plan accordingly. 19 | - The language of the questions is unnecessarily complicated. I had to reread some of them over and over only to find out it was a simple question with very confusing wording. 20 | - The Windows lab will require that you make 10 InSpec tests pass with the recipe. The requirements are very Windows specific (see above for examples). -------------------------------------------------------------------------------- /local-cookbook-development/local-cookbook-development-study-guide.md: -------------------------------------------------------------------------------- 1 | # LOCAL COOKBOOK DEVELOPMENT BADGE TOPICS 2 | _This page is for the purpose of studying for this exam. Most of the information found on this page is taken from [docs.chef.io](https://docs.chef.io)._ 3 | 4 | The Local Cookbook Development badge is awarded when someone proves that they understand the process of developing cookbooks locally. Candidates must show: 5 | 6 | - An understanding of authoring cookbooks and setting up the local environment. 7 | - An understanding of the Chef DK tools. 8 | - An understanding of Test Kitchen configuration. 9 | - An understanding of the available testing frameworks. 10 | - An understanding of troubleshooting cookbooks. 11 | - An understanding of search and databags. 12 | 13 | _Here is a detailed breakdown of each area._ 14 | 15 | # COOKBOOK AUTHORING AND SETUP THEORY 16 | 17 | ## REPO STRUCTURE - MONOLITHIC VS SINGLE COOKBOOK 18 | _Candidates should understand:_ 19 | 20 | ### The pros and cons of a single repository per cookbook 21 | - _Cookbooks should not reside in the Chef Repo but rather be pulled in via dependency management tools like Berkshelf. Each cookbook should have its own Git repository, build process, and test suite. Cookbooks should be treated as software projects of their own. The suggested structure is to completely remove the idea of putting Cookbooks in your Chef Repo all together. Every cookbook would be contained within its own Git repository and every cookbook has its own Berksfile._ 22 | - From there they suggest creating a build job on a CI server for every cookbook. This job would test and then upload the cookbook it is managing to your Chef Server. 23 | 24 | **Pros -** 25 | - Each cookbook can be tested, uploaded, and verified by a build server 26 | - Change management is simpler 27 | - pinning versions to environments is straightforward 28 | - there can be an open source mentality toward changes to the cookbook 29 | - the run-list will only allow for one cookbook of that name per organization otherwise confusion abounds 30 | - You can use the "monolithic" chef-repo pattern as a "management console". 31 | - A different Berksfile per cookbook means that each cookbook can have different dependencies. So if cookbook A depends on apache v 2.0.0 and cookbook B depends on apache v 2.2.2, B's dependencies don't cancel out A's. 32 | 33 | **Cons -** 34 | - The cookbook is shared with other applications, so a change might cause issues. 35 | - you may or may not be the maintainer of that cookbook which means you may not have rights to change it on the master branch 36 | - you may need a wrapper cookbook to extend the functionality of that cookbook 37 | 38 | ### [The pros and cons of an application repository](https://chef.github.io/chef-rfc/rfc019-chef-workflows.html) 39 | **Pros -** 40 | - Everything needed for your application is in one place so it lessens confusion. 41 | - `chef vendor dependencies` does what berks would do to install cookbook dependencies. 42 | - You can test all your cookbooks together. 43 | 44 | **Cons -** 45 | Everything needed for your application must be the same version, creating ownership and change management issues. 46 | 47 | ### How the Chef workflow supports monolithic vs single cookbooks 48 | - Monolithic: All of your Chef related source code, including any 3rd party dependencies, are tracked in one source control repository using Git. External dependencies, and any local modifications to them, are made with built-in vendor branches, allowing you to easily track the upstream for modifications. 49 | - Single: All of the Chef cookbooks are treated as independent software projects, that can be built in isolation from any other cookbook. External dependencies are fetched as-needed, and treated as artifacts. Changes to the upstream creates a new software projects, and is tracked as such. 50 | 51 | ### How to create a repository/workspace on the workstation 52 | - You can either run `chef generate repo [name]` or download a starter kit from the Chef server for your organization. 53 | 54 | ## VERSIONING OF COOKBOOKS 55 | _Candidates should understand:_ 56 | 57 | ### Why cookbooks should be versioned 58 | - Cookbooks need versions for running different cookbooks on their different environments. 59 | 60 | ### The recommended methods of maintaining versions (e.g. knife spork) 61 | - `knife spork bump ` will automatically update the version number in your metadata if you don't manually change it in the `metadata.rb`. 62 | 63 | ### How to avoid overwriting cookbooks 64 | - by Freezing it with the `knife cookbook upload --freeze` or `berks upload` which freezes 65 | 66 | ### Where to define a cookbook version 67 | - in `metadata.rb` 68 | 69 | ### Semantic versioning 70 | - `MAJOR.MINOR.PATCH` or `BreakingChanges.BackwardsCompatibleChanges.BackwardsCompatibleBugFixes` 71 | - MAJOR version when you make incompatible API changes 72 | - MINOR version when you add functionality in a backwards-compatible manner 73 | - PATCH version when you make backwards-compatible bug fixes 74 | 75 | ### [Freezing cookbooks](https://docs.chef.io/cookbook_versions.html#freeze-versions) 76 | - A cookbook version can be frozen, which will prevent updates from being made to that version of a cookbook. (A user can always upload a new version of a cookbook.) Using cookbook versions that are frozen within environments is a reliable way to keep a production environment safe from accidental updates while testing changes that are made to a development infrastructure. 77 | 78 | ### Re-uploading and freezing cookbooks 79 | - To freeze a cookbook version using knife, enter: `knife cookbook upload redis --freeze` 80 | - Once a cookbook version is frozen, only by using the --force option can an update be made. `knife cookbook upload redis --force` 81 | 82 | ## STRUCTURING COOKBOOK CONTENT 83 | _Candidates should understand:_ 84 | 85 | ### Modular content/reusability 86 | 87 | ### Best practices around cookbooks that map 1:1 to a piece of software or functionality vs monolithic cookbooks 88 | - 1:1 cookbooks are preferred as each piece of software needs to be managed separately within its own git repo. 89 | - Versioning - you can tag specific releases 90 | - Hands in the pot - you can easily give everyone clone access, but restrict push access to select teams for certain repos 91 | - History - if you need to history for a certain cookbook, you shouldn't have to run a complex git command to parse the logs 92 | - Monolithic things are generally anti-patterns 93 | 94 | ### How to use common, core resources 95 | - (This is accomplished with the [chefkata](https://github.com/anniehedgpeth/chefkata).) 96 | - `:nothing` is the only action that can be used with any resource. 97 | - `file` `cookbook_file` `remote_file` `template` actions: 98 | - `:create` `:create_if_missing` `:delete` `:nothing` `:touch` 99 | - Properties common to every resource include: 100 | - `ignore_failure` `provider` `retries` `retry_delay` `sensitive` `supports` 101 | - [`sensitive`](https://docs.chef.io/resource_common.html#properties) Ensure that sensitive resource data is not logged by the chef-client. Default value: false. This property only applies to the `execute`, `file` and `template` resources. 102 | - `execute` actions: `:nothing` `:run` 103 | - Common `execute` properties: `command` `notifies` `creates` (Prevent a command from creating a file when that file already exists.) `path` `returns` 104 | - A notification is a property on a resource that listens to other resources in the resource collection and then takes action(s) based on the notification type (notifies or subscribes). 105 | - Timers: `:before` `:delayed` `:immediate` `:immediately` 106 | - Notifies: `notifies :action, 'resource[name]', :timer` 107 | - Subscribes: `subscribes :action, 'resource[name]', :timer` 108 | 109 | ```ruby 110 | cookbook_file '/var/www/customers/public_html/index.php' do 111 | source 'index.php' 112 | owner 'web_admin' 113 | group 'web_admin' 114 | mode '0755' 115 | action :create 116 | end 117 | ``` 118 | 119 | ## HOW METADATA IS USED 120 | _Candidates should understand:_ 121 | 122 | ### How to manage dependencies 123 | - If you're using Berks, you would add `depends 'cookbook', 'version'` in the `metadata.rb`, and in the `Berksfile` you would add the `source`, such as the supermarket at `'https://supermarket.chef.io'`. 124 | - If you're not using Berks, then you would add the dependencies to the `metadata.rb` in the same way, but you would run `knife upload `knife deps nodes/*.json` to use the output of knife deps to pass command to knife upload. 125 | 126 | ### Cookbook dependency version syntax 127 | - Inside of `metadata.rb` put `depends ''` or for a version constraint, `depends '', '> 2.0'` 128 | - The operators are `=, >=, >, <, <=, and ~>`. 129 | - That last operator `~>` will go up to the next biggest version. 130 | - `>= 2.2.0, < 3.0` == `~>2.2` 131 | 132 | ### What information to include in a cookbook - author, license, etc 133 | **Metadata settings** 134 | 135 | ```ruby 136 | name 'chefkata' 137 | maintainer 'Annie Hedgpeth' 138 | maintainer_email 'annie.hedgpeth@gmail.com' 139 | license 'all_rights' 140 | description 'Installs/Configures chefkata' 141 | long_description 'Installs/Configures chefkata' 142 | version '0.1.0' 143 | issues_url 'https://github.com//chefkata/issues' if respond_to?(:issues_url) 144 | source_url 'https://github.com//chefkata' if respond_to?(:source_url) 145 | ``` 146 | 147 | ### What 'suggests' in metadata means 148 | - Same thing as depends, but that you suggest a cookbook be there. The cookbook will still run if that dependency doesn't exist. 149 | 150 | ### What 'issues_url' in metadata means 151 | - The `issues_url` points to the location where issues for this cookbook are tracked. A `View Issues` link will be displayed on this cookbook's page when uploaded to a Supermarket. 152 | - The `source_url` points to the development repository for this cookbook. A `View Source` link will be displayed on this cookbook's page when uploaded to a Supermarket. 153 | 154 | 155 | ## WRAPPER COOKBOOK METHODS 156 | _Candidates should understand:_ 157 | 158 | ### How to consume other cookbooks in code via wrapper cookbooks 159 | - You would add those cookbooks as dependencies in the metadata and then consume them by either: 160 | - `include_recipe` in the recipe and set the attributes in the attributes file (i.e. chef-client cookbook with a lot of recipes) 161 | - use the resources provided by the cookbook (i.e. Tomcat cookbook with lots of resources and no recipes) 162 | 163 | ### How to change cookbook behavior via wrapper cookbooks 164 | - You would add those cookbooks as dependencies in the metadata and then consume them by either: 165 | - `include_recipe` in the recipe and set the attributes in the attributes file (i.e. chef-client cookbook with a lot of recipes) 166 | - use the resources provided by the cookbook (i.e. Tomcat cookbook with lots of resources and no recipes) 167 | - [MH:](https://github.com/mhedgpeth/mhedgpeth.github.io/blob/master/_drafts/local-cookbook-development-notes.md) Set the attributes of the cookbook with `node.default['attribute'] = 'overridden_value'` and use `include_recipe` 168 | 169 | ### Attribute value precedence 170 | - OHAI will trump all other attributes. Then `override` will trump other attributes in the order of role, environment, node,/recipe, attribute files. Then the default attributes in that same order. 171 | - OHAI >> Normal (R, E, N, A) >> default (R, E, N, A) 172 | - [MH:](https://github.com/mhedgpeth/mhedgpeth.github.io/blob/master/_drafts/local-cookbook-development-notes.md) [later overrides earlier](https://docs.chef.io/attributes.html): 173 | - Attribute -> Recipe -> Environment -> Role 174 | - Default -> Normal -> Override -> OHAI 175 | - declared in: 176 | - attribute: `default['attribute'] = value`, `normal['attribute'] = value`, `override['attribute'] = value` 177 | - cookbook: `node.default['attribute'] = value`, `node.normal['attribute'] = value`, `node.override['attribute'] = value` 178 | - environment: `default_attributes({ 'attribute' => 'value'})`, `override_attributes({'attribute' => 'value'})` 179 | - role: `default_attributes({ 'attribute' => 'value'})`, `override_attributes({'attribute' => 'value'})` 180 | 181 | ### How to use the `include_recipe` directive** 182 | - Add the recipe to your metadata.rb file, then use the `include_recipe` resource to run that entire recipe within the recipe in which you're including it. 183 | - [MH:](https://github.com/mhedgpeth/mhedgpeth.github.io/blob/master/_drafts/local-cookbook-development-notes.md) add `depends 'cookbook_name'` to `metadata.rb` and then add `include_recipe 'cookbook_name::recipe_name'` to a recipe in your runlist 184 | 185 | ### What happens if the same recipe is included multiple times 186 | - If the `include_recipe` method is used more than once to include a recipe, only the first inclusion is processed and any subsequent inclusions are ignored. 187 | - [MH:](https://github.com/mhedgpeth/mhedgpeth.github.io/blob/master/_drafts/local-cookbook-development-notes.md) Only the first inclusion is processed and any subsequent inclusions are ignored. 188 | 189 | ### How to use the `depends` directive 190 | - If you need a cookbook as a dependency, then you would include `depends '' ''` in the metadata of the wrapper / main cookbook. 191 | 192 | ## USING COMMUNITY COOKBOOKS 193 | _Candidates should understand:_ 194 | 195 | ### How to use a public and private Supermarket 196 | - Private Supermarket - 197 | - Create a server to serve as your private supermarket which hosts your cookbooks 198 | - add the URL of that server as your source to the private supermarket to your Berksfile so that it can look there for the dependent cookbooks and also add it to the knife.rb to upload cookbooks. 199 | - add all dependencies in the metadata.rb with `depends '' ''` 200 | - use `knife cookbook site share COOKBOOK_NAME CATEGORY (options)` to upload cookbooks to the supermarket 201 | - Public Supermarket - 202 | - add the public supermarket link as your source in the Berksfile 203 | - add all dependencies in the metadata.rb with `depends '' ''` 204 | - you may only update a cookbook in the public supermarket if you are the owner/maintainer 205 | - anyone can upload a cookbook to the public supermarket 206 | 207 | ### How to use community cookbooks 208 | - You can either use it from the Supermarket, in which you'd depend on it in metadata, or you can clone it from version control and upload it to the Chef server with berks. 209 | - The deprecated way to initialize Berkshelf is to run `berks init`, but now, when you run `chef generate cookbook` you will get a Berkshelf file in the cookbook. 210 | 211 | ### How to wrap community cookbooks 212 | - You would add those cookbooks as dependencies in the metadata and then consume them by either: 213 | - `include_recipe` in the recipe and set the attributes in the attributes file (i.e. chef-client cookbook with a lot of recipes) 214 | - use the resources provided by the cookbook (i.e. Tomcat cookbook with lots of resources and no recipes) 215 | 216 | ### How to fork community cookbooks 217 | - Fork it to your own repo in git and assume the responsibility to maintain that cookbook from your own repo 218 | 219 | ### How to use Berkshelf to download cookbooks 220 | - run `berks install` with a valid `Berksfile` containing the source for the dependencies 221 | 222 | ### How to configure a Berksfile 223 | - [MH:](https://github.com/mhedgpeth/mhedgpeth.github.io/blob/master/_drafts/local-cookbook-development-notes.md) `source` should point to a supermarket (and the first one gets precedence, so you could use a private then public supermarket) 224 | - Always include a `metadata` line to get all the `depends` attributes from the `metadata.rb`. 225 | - If your cookbook comes from another location than the supermarket, specify it, as in: `cookbook "", git: "http://github.com/username/repo'"` 226 | 227 | ### How to use a Berksfile to manage a community cookbook and a local cookbook with the same name 228 | - [MH:](https://github.com/mhedgpeth/mhedgpeth.github.io/blob/master/_drafts/local-cookbook-development-notes.md) By using a private supermarket or specifying the exact location of that cookbook on your private git server, thus making it ignore the supermarket as a default source 229 | 230 | ## USING CHEF RESOURCES VS ARBITRARY COMMANDS 231 | _Candidates should understand:_ 232 | 233 | ### [How to shell out to run commands](https://docs.chef.io/dsl_recipe.html#shell-out) 234 | - [MH:](https://github.com/mhedgpeth/mhedgpeth.github.io/blob/master/_drafts/local-cookbook-development-notes.md) Use the `shell_out` (when errors don't matter) or `shell_out!` (raises error when command fails) 235 | - The `shell_out` method can be used to run a command against the node, and then display the output to the console when the log level is set to debug. 236 | - `shell_out(command_args)` where command_args is the command that is run against the node 237 | - The `shell_out!` method can be used to run a command against the node, display the output to the console when the log level is set to debug, and then raise an error when the method returns false. 238 | - `shell_out!(command_args)` where command_args is the command that is run against the node. This method will return true or false. 239 | - The `shell_out_with_systems_locale` method can be used to run a command against the node (via the `shell_out` method), but using the LC_ALL environment variable. 240 | - `shell_out_with_systems_locale(command_args)` where command_args is the command that is run against the node. 241 | 242 | ### How to do [logging](https://docs.chef.io/resource_log.html#chef-log-entries) with Chef 243 | - Set the [sensitive property](https://docs.chef.io/resource_common.html#properties) to `true` to keep your sensitive data from being shown in the logs. 244 | 245 | ```ruby 246 | unless node['splunk']['upgrade_enabled'] 247 | Chef::Log.fatal('The chef-splunk::upgrade recipe was added to the node,') 248 | Chef::Log.fatal('but the attribute `node["splunk"]["upgrade_enabled"]` was not set.') 249 | Chef::Log.fatal('I am bailing here so this node does not upgrade.') 250 | raise 251 | end 252 | ``` 253 | 254 | ### When/not to shell out 255 | - [MH:](https://github.com/mhedgpeth/mhedgpeth.github.io/blob/master/_drafts/local-cookbook-development-notes.md) As read-only, not to change state 256 | 257 | ### How to use the `execute` resource 258 | - `execute '/usr/sbin/apachectl configtest'` 259 | 260 | ### When/not to use the `execute` resource 261 | - [MH:](https://github.com/mhedgpeth/mhedgpeth.github.io/blob/master/_drafts/local-cookbook-development-notes.md) When you are changing the state of the system 262 | 263 | ### How to ensure idempotence 264 | - by using guard clauses 265 | - [MH:](https://github.com/mhedgpeth/mhedgpeth.github.io/blob/master/_drafts/local-cookbook-development-notes.md) By using notifies or the `not_if`/`only_if` clauses 266 | 267 | # CHEF DK TOOLS 268 | 269 | ## `CHEF` COMMAND 270 | _Candidates should understand:_ 271 | 272 | ### What the `chef` command does 273 | - The `chef` command is used for generation and is like the `knife` command. You'd use it in place of `knife` when you use `policyfiles`. 274 | - `chef command [arguments...] [options...]` 275 | 276 | ``` 277 | Available Commands: 278 | exec Runs the command in context of the embedded ruby 279 | env Prints environment variables used by ChefDK 280 | gem Runs the `gem` command in context of the embedded ruby 281 | generate Generate a new app, cookbook, or component 282 | shell-init Initialize your shell to use ChefDK as your primary ruby 283 | install Install cookbooks from a Policyfile and generate a locked cookbook set 284 | update Updates a Policyfile.lock.json with latest run_list and cookbooks 285 | push Push a local policy lock to a policy group on the server 286 | push-archive Push a policy archive to a policy group on the server 287 | show-policy Show policyfile objects on your Chef Server 288 | diff Generate an itemized diff of two Policyfile lock documents 289 | provision Provision VMs and clusters via cookbook 290 | export Export a policy lock as a Chef Zero code repo 291 | clean-policy-revisions Delete unused policy revisions on the server 292 | clean-policy-cookbooks Delete unused policyfile cookbooks on the server 293 | delete-policy-group Delete a policy group on the server 294 | delete-policy Delete all revisions of a policy on the server 295 | undelete Undo a delete command 296 | verify Test the embedded ChefDK applications 297 | ``` 298 | 299 | ### What `chef generate` can create 300 | 301 | ``` 302 | Available generators: 303 | app Generate an application repo 304 | cookbook Generate a single cookbook 305 | recipe Generate a new recipe 306 | attribute Generate an attributes file 307 | template Generate a file template 308 | file Generate a cookbook file 309 | lwrp Generate a lightweight resource/provider 310 | repo Generate a Chef code repository 311 | policyfile Generate a Policyfile for use with the install/push commands 312 | generator Copy ChefDK's generator cookbook so you can customize it 313 | build-cookbook Generate a build cookbook for use with Delivery 314 | ``` 315 | 316 | ### [How to customize content using `generators`](https://blog.chef.io/2014/12/09/guest-post-creating-your-own-chef-cookbook-generator/) 317 | - `chef generate cookbook my_cookbook_name -g ~/chef/pan` 318 | - This is a way that you can templatize the way in which you create a chef repo with settings specific to your organization. 319 | 320 | ### The recommended way to create a template 321 | - `chef generate template ` 322 | 323 | ### How to add the same boilerplate text to every recipe created by a team 324 | - According to [this](https://medium.com/@echohack/creating-your-own-chef-cookbook-generator-5e998db1255b), you'd add it to the `code_generator` at `/opt/chefdk/embedded/apps/chef-dk/lib/chef-dk/skeletons/code_generator`. 325 | 326 | ### The ['chef gem'](https://docs.chef.io/ctl_chef.html#chef-gem) command 327 | - The chef gem subcommand is a wrapper around the gem command in RubyGems and is used by Chef to install RubyGems into the Chef development kit development environment. All knife plugins, drivers for Kitchen, and other Ruby applications that are not packaged within the Chef development kit will be installed to the .chefdk path in the home directory: ~/.chefdk/gem/ruby/ver.si.on/bin (where ver.si.on is the version of Ruby that is packaged within the Chef development kit). 328 | 329 | ## [FOODCRITIC](https://docs.chef.io/foodcritic.html) 330 | _Candidates should understand:_ 331 | 332 | ### What Foodcritic is 333 | - Chef-specific linting of cookbooks 334 | - Use Foodcritic to check cookbooks for common problems: 335 | - Style 336 | - Correctness 337 | - Syntax 338 | - Best practices 339 | - Common mistakes 340 | - Deprecations 341 | 342 | ### Why developers should lint their code 343 | - Consistency 344 | 345 | ### Foodcritic errors and how to fix them 346 | - [MH:](https://github.com/mhedgpeth/mhedgpeth.github.io/blob/master/_drafts/local-cookbook-development-notes.md) They all start with `FC001`; you can google that to get to the exact rule. 347 | 348 | ### Community coding rules & custom rules 349 | - Various nice people in the Chef community have also written extra rules for foodcritic that you can install and run. Or write your own! 350 | - [Custom Customink Rules](https://github.com/customink-webops/foodcritic-rules/blob/master/rules.rb) 351 | - [Custom Etsy Rules](https://github.com/etsy/foodcritic-rules) 352 | 353 | ### Foodcritic commands 354 | - `foodcritic /path/to/cookbook` 355 | - [MH:](https://github.com/mhedgpeth/mhedgpeth.github.io/blob/master/_drafts/local-cookbook-development-notes.md) Just run `foodcritic .` to do a scan from the cookbook folder. Add `--epic-fail` to make the command fail when foodcritic fails (to cause your build to fail). 356 | - A Foodcritic evaluation has the following syntax: `RULENUMBER: MESSAGE: FILEPATH:LINENUMBER` 357 | 358 | ### [Foodcritic rules](http://www.foodcritic.io/) 359 | - It comes with 60 built-in rules that identify problems ranging from simple style inconsistencies to difficult to diagnose issues that will hurt in production. 360 | 361 | ### How to exclude Foodcritic rules 362 | - `foodcritic . --tags ~RULE` 363 | - [MH:](https://github.com/mhedgpeth/mhedgpeth.github.io/blob/master/_drafts/local-cookbook-development-notes.md) For the entire cookbook, add `FC###` to the `.foodcritic` file in the root of the cookbook folder 364 | - [MH:](https://github.com/mhedgpeth/mhedgpeth.github.io/blob/master/_drafts/local-cookbook-development-notes.md) For single line of code, add the comment at the end of the line: `# ~FC003` 365 | 366 | ## BERKS 367 | _Candidates should understand:_ 368 | 369 | ### How to use berks to work with upstream dependencies 370 | - [MH:](https://github.com/mhedgpeth/mhedgpeth.github.io/blob/master/_drafts/local-cookbook-development-notes.md) by using the supermarket for dependencies, or by doing version pinning 371 | 372 | ### How to work with GitHub & Supermarket 373 | - [MH:](https://github.com/mhedgpeth/mhedgpeth.github.io/blob/master/_drafts/local-cookbook-development-notes.md) in the `Berksfile` you can state the `git:` location or have another supermarket listed as your `source:` (or even multiple ones if you want public to be a backup) 374 | 375 | ### How to work with dependent cookbooks 376 | - [MH:](https://github.com/mhedgpeth/mhedgpeth.github.io/blob/master/_drafts/local-cookbook-development-notes.md) Most of the time it works with `metadata.rb` inclusion, but you can extend it with the `cookbook` line (by including further version pinning and overriding location). 377 | 378 | ### How to troubleshoot berks issues 379 | - https://github.com/berkshelf/berkshelf/wiki/Troubleshooting 380 | - `berks test KITCHEN_COMMAND (options)` 381 | - `berks show COOKBOOK (options)` 382 | - `berks info COOKBOOK (options)` 383 | - `berks list (options)` 384 | - `berks search QUERY (options)` 385 | - `berks verify (options)` 386 | 387 | ### How to lock cookbook versions 388 | - [MH:](https://github.com/mhedgpeth/mhedgpeth.github.io/blob/master/_drafts/local-cookbook-development-notes.md) cookbooks are frozen by default with a `berks upload` 389 | 390 | ### How to manage dependencies using berks 391 | - [MH:](https://github.com/mhedgpeth/mhedgpeth.github.io/blob/master/_drafts/local-cookbook-development-notes.md) berks commands 392 | - `berks install` loads dependencies locally 393 | - `berks upload` uploads dependencies to chef server 394 | - `berks info ` will display information for that cookbook 395 | - `berks list` will list cookbooks and their dependencies 396 | - `berks apply production Berksfile.lock` will apply the settings in berksfile to the provided environment 397 | 398 | ## [RUBOCOP](https://docs.chef.io/rubocop.html) 399 | _Candidates should understand:_ 400 | 401 | ### How to use RuboCop to check Ruby styles 402 | - [MH:](https://github.com/mhedgpeth/mhedgpeth.github.io/blob/master/_drafts/local-cookbook-development-notes.md) `rubocop .` command from the cookbook folder 403 | 404 | ### RuboCop vs Foodcritic 405 | - [MH:](https://github.com/mhedgpeth/mhedgpeth.github.io/blob/master/_drafts/local-cookbook-development-notes.md) Rubocop is for ruby style, Foodcritic is for chef specifid linting 406 | - Use RuboCop to author better Ruby code: 407 | - Enforce style conventions and best practices 408 | - Evaluate the code in a cookbook against metrics like “line length” and “function size” 409 | - Help every member of a team to author similary structured code 410 | - Establish uniformity of source code 411 | - Set expectations for fellow (and future) project contributors 412 | 413 | ### RuboCop configuration & commands 414 | - [MH:](https://github.com/mhedgpeth/mhedgpeth.github.io/blob/master/_drafts/local-cookbook-development-notes.md) `--fail-fast` a good option for CI 415 | 416 | ### Auto correction 417 | - [MH:](https://github.com/mhedgpeth/mhedgpeth.github.io/blob/master/_drafts/local-cookbook-development-notes.md) `-a` or `--auto-correct` to auto-correct offenses 418 | 419 | ### How to be selective about the rules you run 420 | - Each cookbook has its own `.rubocop.yml` file, which means that each cookbook may have its own set of enabled, disabled, and custom rules. That said, it’s more common for all cookbooks to have the same set of enabled, disabled, and custom rules. When RuboCop is run against a cookbook, the full set of enabled and disabled rules (as defined in the `enabled.yml` and `disabled.yml` files in RuboCop itself) are loaded first and are then compared against the settings in the cookbook’s `.rubocop.yml` file. 421 | 422 | ```ruby 423 | NAME_OF_RULE: 424 | Description: 'a description of a rule' 425 | Enabled : (true or false) 426 | KEY: VALUE 427 | ``` 428 | - Use a `.rubocop_todo.yml` file to capture the current state of all evaluations, and then write them to a file. This allows evaluations to reviewed one at a time. Disable any evaluations that are unhelpful, and then address the ones that are. 429 | - To generate the `.rubocop_todo.yml` file, run the following command: `rubocop --auto-gen-config` 430 | - Rename this file to `.rubocop.yml` to adopt this evaluation state as the standard. 431 | - Include this file in the `.rubocop.yml` file by adding `inherit_from: .rubocop_todo.yml` to the top of the `.rubocop.yml` file. 432 | 433 | 434 | ## TEST KITCHEN 435 | _Candidates should understand:_ 436 | 437 | ### Writing tests to verify intent 438 | - One should use InSpec to write tests that verify that the desired state was achieved, not necessarily that all of the resources simply converged but that they're functioning in the desired state. 439 | 440 | ### How to focus tests on critical outcomes 441 | - One should use InSpec to write tests that verify that the desired state was achieved, not necessarily that all of the resources simply converged but that they're functioning in the desired state. 442 | 443 | ### How to test each resource component vs how to test for desired outcomes 444 | - One should use InSpec to write tests that verify that the desired state was achieved, not necessarily that all of the resources simply converged but that they're functioning in the desired state. 445 | 446 | ### Regression testing 447 | - Running `kitchen converge` twice will ensure your policy applies without error to existing instances 448 | - Running `kitchen test` will ensure your policy applies without error to any new instances 449 | 450 | # TEST KITCHEN 451 | - The basic structure of a `.kitchen.yml` file is as follows: 452 | 453 | ```yaml 454 | driver: 455 | name: driver_name 456 | 457 | provisioner: 458 | name: provisioner_name 459 | 460 | verifier: 461 | name: verifier_name 462 | 463 | transport: 464 | name: transport_name 465 | 466 | platforms: 467 | - name: platform-version 468 | driver: 469 | name: driver_name 470 | - name: platform-version 471 | 472 | suites: 473 | - name: suite_name 474 | run_list: 475 | - recipe[cookbook_name::recipe_name] 476 | attributes: { foo: "bar" } 477 | excludes: 478 | - platform-version 479 | - name: suite_name 480 | driver: 481 | name: driver_name 482 | run_list: 483 | - recipe[cookbook_name::recipe_name] 484 | attributes: { foo: "bar" } 485 | includes: 486 | - platform-version 487 | ``` 488 | 489 | ## DRIVERS 490 | _Candidates should understand:_ 491 | 492 | ### Test Kitchen provider & platform support 493 | - `platforms:` contains a list of all the platforms that Kitchen will test against when executed. This should be a list of all the platforms that you want your cookbook to support. 494 | 495 | ### How to use .kitchen.yml to set up complex testing matrices 496 | - In the `.kitchen.yml` file we define two fields that create a test matrix; the number of **platforms** we want to support multiplied by the number of test **suites** that we defined. 497 | 498 | ### How to test a cookbook on multiple deployment scenarios 499 | - In the `.kitchen.yml` file we define two fields that create a test matrix; the number of **platforms** we want to support multiplied by the number of test **suites** that we defined. 500 | 501 | ### How to configure drivers 502 | - Kitchen uses a driver plugin architecture to enable Kitchen to simulate testing on cloud providers, such as Amazon EC2, OpenStack, and Rackspace, and also on non-cloud platforms, such as Microsoft Windows. Each driver is responsible for managing a virtual instance of that platform so that it may be used by Kitchen during cookbook testing. 503 | - Most drivers have driver-specific configuration settings that must be added to the `.kitchen.yml` file before Kitchen will be able to use that platform during cookbook testing. For information about these driver-specific settings, refer to the driver-specific documentation. 504 | - Common drivers include: 505 | - `kitchen-all` A driver for everything, or “all the drivers in a single Ruby gem”. 506 | - `kitchen-bluebox` A driver for Blue Box. 507 | - `kitchen-cloudstack` A driver for CloudStack. 508 | - `kitchen-digitalocean` A driver for DigitalOcean. 509 | - `kitchen-docker` A driver for Docker. 510 | - `kitchen-dsc` A driver for Windows PowerShell Desired State Configuration (DSC). 511 | - `kitchen-ec2` A driver for Amazon EC2. 512 | - `kitchen-fog` A driver for Fog, a Ruby gem for interacting with various cloud providers. 513 | - `kitchen-google` A driver for Google Compute Engine. 514 | - `kitchen-hyperv` A driver for Hyper-V Server. 515 | - `kitchen-joyent` A driver for Joyent. 516 | - `kitchen-linode` A driver for Linode. 517 | - `kitchen-opennebula` A driver for OpenNebula. 518 | - `kitchen-openstack` A driver for OpenStack. 519 | - `kitchen-pester` A driver for Pester, a testing framework for Microsoft Windows. 520 | - `kitchen-rackspace` A driver for Rackspace. 521 | - `kitchen-vagrant` A driver for Vagrant. The default driver packaged with the Chef development kit. 522 | - How to customize a driver: 523 | 524 | ```yaml 525 | --- 526 | driver: 527 | customize: 528 | memory: 1024 529 | cpuexecutioncap: 50 530 | ``` 531 | 532 | ```yaml 533 | driver: 534 | customize: 535 | createhd: 536 | filename: /tmp/disk1.vmdk 537 | size: 1024 538 | storageattach: 539 | storagectl: SATA Controller 540 | port: 1 541 | device: 0 542 | type: hdd 543 | medium: /tmp/disk1.vmdk 544 | ``` 545 | 546 | ```yaml 547 | --- 548 | driver: 549 | network: 550 | - ["forwarded_port", {guest: 80, host: 8080}] 551 | - ["private_network", {ip: "192.168.33.33"}] 552 | ``` 553 | 554 | ## PROVISIONER 555 | _Candidates should understand:_ 556 | 557 | ### The available provisioners 558 | - `chef_zero` and `chef_solo` are the most common provisioners used for testing cookbooks. 559 | 560 | ### How to configure provisioners 561 | 562 | ```yaml 563 | provisioner: 564 | name: chef_zero 565 | http_proxy: http://10.0.0.1 566 | ``` 567 | 568 | - The environment variables `http_proxy`, `https_proxy`, and `ftp_proxy` are honored by Kitchen for proxies. The `client.rb` file is read to look for proxy configuration settings. If `http_proxy`, `https_proxy`, and `ftp_proxy` are specified in the `client.rb` file, the `chef-client` will configure the ENV variable based on these (and related) settings. 569 | 570 | ```ruby 571 | http_proxy 'http://proxy.example.org:8080' 572 | http_proxy_user 'myself' 573 | http_proxy_pass 'Password1' 574 | ``` 575 | 576 | - `ENV['http_proxy'] = 'http://myself:Password1@proxy.example.org:8080'` 577 | - Kitchen also supports `http_proxy` and `https_proxy` in the `.kitchen.yml` file: 578 | 579 | ### When to use `chef-client` vs. `chef-solo` vs. `Chef` 580 | - `chef-client` to converge the node when it is bootstrapped to the Chef server. 581 | - `chef-solo` as the provisioner for Test Kitchen when you run a light-weight version of Chef on the VM being tested 582 | - `Chef` when you interact with the Chef server 583 | 584 | ### How to use the [shell provisioner](https://www.morethanseven.net/2014/01/12/shell-provisioner-for-test-kitchen/) 585 | - to run a command during a converge 586 | - `provisioner: shell` 587 | - The shell provisioner is going to look for a file called `bootstrap.sh` by default. 588 | - In this case our script is completely self contained but if it needed some additional files we could put them in a directory called data and they would be copied to the newly created virtual machine under `/tmp/kitchen`. 589 | 590 | ## SUITES 591 | _Candidates should understand:_ 592 | 593 | ### What a suite is 594 | - a scenario that you want to run that consists of set of names for each of the platforms specified 595 | 596 | ```yaml 597 | - name: suite_name 598 | driver: 599 | name: driver_name 600 | run_list: 601 | - recipe[cookbook_name::recipe_name] 602 | attributes: { foo: "bar" } 603 | includes: 604 | - platform-version 605 | ``` 606 | 607 | - including or excluding platforms is available 608 | 609 | ```yaml 610 | driver: 611 | name: vagrant 612 | 613 | provisioner: 614 | name: chef_zero 615 | 616 | platforms: 617 | - name: ubuntu-12.04 618 | - name: centos-6.4 619 | - name: debian-7.1.0 620 | 621 | suites: 622 | - name: default 623 | run_list: 624 | - recipe[apache::httpd] 625 | excludes: 626 | - debian-7.1.0 627 | ``` 628 | 629 | ### How to use suites to test different recipes in different environments 630 | - Each suite is given a runlist. (see above) 631 | - Attributes are given for each suite. 632 | 633 | ### Testing directory for InSpec 634 | - The InSpec tests are to be stored in `/test//` 635 | - If your path is different, then you must specify as such in the `.kitchen.yml`. 636 | 637 | ```yaml 638 | verifier: 639 | inspec_tests: 640 | - test/foo/bar 641 | ``` 642 | 643 | ### How to configure suites 644 | - Answered above 645 | - 1) edit their run lists, and 2) define a platform for the suite in the `platforms` setting 646 | 647 | ## PLATFORMS 648 | _Candidates should understand:_ 649 | 650 | ### How to specify platforms 651 | - Within the `suites:` you may include or exclude platforms that are listed in your `platforms:` section. 652 | 653 | ```yaml 654 | includes: 655 | - platform-version 656 | ``` 657 | 658 | ### Common platforms 659 | - ubuntu, debian, windows, centos, rhel 660 | 661 | ### How to locate base images 662 | - [Bento](https://github.com/chef/bento) is a project that contains a set of base images that are used by Chef for internal testing and to provide a comprehensive set of base images for use with Kitchen. By default, Kitchen uses the base images provided by Bento. (Custom images may also be built using Packer.) 663 | - If you are using a vagrant image, you can go to the Atlas site to see the available [Bento boxes](https://atlas.hashicorp.com/boxes/search?utf8=%E2%9C%93&sort=&provider=&q=bento). 664 | 665 | ### Common images and custom images 666 | - The common images are from [Bento](https://atlas.hashicorp.com/boxes/search?utf8=%E2%9C%93&sort=&provider=&q=bento). 667 | - If you want to make a custom image, then you would build it with [Packer](https://www.packer.io/intro/getting-started/build-image.html), then upload those files to Atlas. 668 | - You may also use images built by the community on the Atlas site. 669 | 670 | ## KITCHEN COMMANDS 671 | _Candidates should understand:_ 672 | 673 | ### The basic Test Kitchen workflow 674 | - `kitchen create` to create the vm instance 675 | - `kitchen converge` to compile and converge the cookbooks on the vm instance 676 | - `kitchen verify` to run the InSpec tests on the instance 677 | - `kitchen destroy` to destroy the instance 678 | 679 | ### 'kitchen' commands 680 | - `kitchen create` to create the vm instance 681 | - `kitchen converge` to compile and converge the cookbooks on the vm instance 682 | - `kitchen verify` to run the InSpec tests on the instance 683 | - `kitchen destroy` to destroy the instance 684 | - `kitchen test` to destroy the instance if one exits followed by running through all of the above tests and finishing with another destroy 685 | - `kitchen login` to log into the vm instance 686 | - `kitchen init` to initialize a new `.kitchen.yml` 687 | 688 | ### When tests get run 689 | - when you run `kitchen verify` 690 | 691 | ### How to install [bussers](https://docs.chef.io/kitchen.html#busser) 692 | - Busser is a test setup and execution framework that is designed to work on remote nodes upon whose system dependencies cannot be relied. 693 | - Kitchen uses Busser to run post-convergence tests via a plugin architecture that supports different test frameworks. Busser is installed automatically as part of Kitchen. 694 | - InSpec is the busser that is being used, but you could choose a different busser (but why would you?). 695 | 696 | ### What 'kitchen init' does 697 | - `kitchen init` to initialize a new `.kitchen.yml` 698 | 699 | # COOKBOOK COMPONENTS 700 | 701 | ## DIRECTORY STRUCTURE OF A COOKBOOK 702 | _Candidates should understand:_ 703 | 704 | ### What the components of a cookbook are 705 | - Directories are: 706 | - recipes 707 | - files 708 | - attributes 709 | - test 710 | - spec 711 | - libraries 712 | - templates 713 | - definitions (don't want to use it, but you should be aware of it) 714 | - resources 715 | - providers (only if the cookbook employs lwrp or hwrp) 716 | - Files are: 717 | - .kitchen.yml 718 | - Berksfile 719 | - metadata.rb 720 | - README.md 721 | - chefignore 722 | 723 | ### What siblings of cookbooks in a repository are 724 | - data_bags 725 | - roles 726 | - environments 727 | 728 | ### The default recipe & attributes files 729 | - The default recipe is the only one that is run when a cookbook called without a recipe specified. 730 | - An [attribute file](https://docs.chef.io/attributes.html) is located in the attributes/ sub-directory for a cookbook. 731 | - When a cookbook is run against a node, the attributes contained in all attribute files are evaluated in the context of the node object. 732 | - Node methods (when present) are used to set attribute values on a node. 733 | 734 | ### Why there is a 'default' subdirectory under 'templates’ 735 | - [MH:](https://github.com/mhedgpeth/mhedgpeth.github.io/blob/master/_drafts/local-cookbook-development-notes.md) It is the fallback of where to go for templates. Templates can also be platform specific, where the platform would be the directory. Or you can specify the group in the recipe code, which would be configurable 736 | 737 | ### Where tests are stored 738 | - inspec: `tests/integration/default` 739 | - serverspec: `spec` directory 740 | 741 | ## ATTRIBUTES AND HOW THEY WORK 742 | _Candidates should understand:_ 743 | 744 | ### What attributes are 745 | - [MH:](https://github.com/mhedgpeth/mhedgpeth.github.io/blob/master/_drafts/local-cookbook-development-notes.md) values defined in a file within the attributes directory 746 | 747 | ### Attributes as a nested hash 748 | - The following two blocks say the same thing. The second displays the attributes in a nested hash. 749 | 750 | ```ruby 751 | default['cookbook_name']['category_name']['key1'] = 'value1' 752 | default['cookbook_name']['category_name']['key2'] = 'value2' 753 | default['cookbook_name']['different_category'] = 'other_value' 754 | ``` 755 | 756 | ```ruby 757 | default['cookbook_name'] = { 758 | category_name: { 759 | value1: 'value1', 760 | value2: 'value2' 761 | }, 762 | different_category: 'other_value' 763 | } 764 | ``` 765 | 766 | ### How attributes are defined 767 | - Attributes are defined by: 768 | - Attributes file (can be `.json` or `.rb`) 769 | 770 | ```ruby 771 | default['cookbook_name']['category_name']['key1'] = 'value1' 772 | default['cookbook_name']['category_name']['key2'] = 'value2' 773 | normal['cookbook_name']['different_category'] = 'other_value' # normal overrides the default value 774 | ``` 775 | - In recipes - 776 | 777 | ```ruby 778 | node.default['cookbook_name']['category_name']['key1'] = 'recipe_value' 779 | node.normal['cookbook_name']['category_name']['key2'] = 'recipe_value2' 780 | ``` 781 | 782 | - Roles & Environments 783 | 784 | ```ruby 785 | override_attributes({ 786 | category_name: { 787 | value1: 'new_value1', 788 | value2: 'new_value2' 789 | } 790 | }) 791 | default_attributes({ 792 | category_name: { 793 | value1: 'new_value1-a', 794 | value2: 'new_value2-b' 795 | } 796 | }) 797 | ``` 798 | 799 | ### How attributes are named 800 | - in a nested tree 801 | 802 | ### How attributes are referenced 803 | - `node[key:value]` 804 | 805 | ### Attribute precedence levels 806 | - OHAI >> Normal/Override (Role, Env, Node/recipe, Attribute) >> default (Role, Env, Node/recipe, Attribute) 807 | 808 | ### What [Ohai](https://docs.chef.io/ohai.html) is 809 | - Ohai is a tool that is used to detect attributes on a node, and then provide these attributes to the chef-client at the start of every chef-client run. Ohai is required by the chef-client and must be present on a node. (Ohai is installed on a node as part of the chef-client install process.) 810 | - Attributes that are collected by Ohai are automatic level attributes, in that these attributes are used by the chef-client to ensure that these attributes remain unchanged after the chef-client is done configuring the node. 811 | 812 | ### What the 'platform' attribute is 813 | - [Ohai](https://docs.chef.io/ohai.html) collects data for many platforms, including AIX, Darwin, Linux, FreeBSD, OpenBSD, NetBSD, Solaris, and any Microsoft Windows operating system based off the Windows_NT kernel and has access to win32 or win64 sub-systems. 814 | 815 | ### How to use the 'platform' attribute in [recipes](https://docs.chef.io/dsl_recipe.html) 816 | 817 | ```ruby 818 | if node['platform'] == 'ubuntu' 819 | # do ubuntu things 820 | end 821 | ``` 822 | 823 | ## FILES AND TEMPLATES - DIFFERENCE AND HOW THEY WORK, WHEN TO USE EACH 824 | _Candidates should understand:_ 825 | 826 | ### How to instantiate [files](https://docs.chef.io/files.html) on nodes 827 | - Use the `cookbook_file` resource to manage files that are added to nodes based on files that are located in the /files directory in a cookbook. 828 | - Use the `file` resource to manage files directly on a node. 829 | - Use the `remote_file` resource to transfer files to nodes from remote locations. 830 | - Use the `template` resource to manage files that are added to nodes based on files that are located in the /templates directory in a cookbook. 831 | 832 | ### The difference between `file`, `cookbook_file`, `remote_file`, and `template` 833 | - `file` - Use this when you want to create a simple file. You'll use the `content` property to add the content. 834 | - `cookbook_file` - Use this when you want to store a file in the cookbook to be copied directly onto the node. 835 | - `source` - Use this when you have a remote source on which the file is stored that you want put on the node. 836 | - `template` - Use this when you want to create a file out of a template based on environment variables. 837 | 838 | ### How two teams can manage the same file 839 | - [MH:](https://github.com/mhedgpeth/mhedgpeth.github.io/blob/master/_drafts/local-cookbook-development-notes.md) If they can share the same cookbok, then by overriding attributes on the same cookbook. Otherwise use partial templates (see below). 840 | 841 | ### How to write templates 842 | - You would use the `template` resource in the recipe: 843 | 844 | ```ruby 845 | template '/etc/motd' do 846 | source 'motd.erb' 847 | owner 'root' 848 | group 'root' 849 | mode '0755' 850 | variables({ 851 | key: 'value' 852 | }) 853 | end 854 | ``` 855 | - And the actual template would be the file name with its extension and an `.erb` extension. The file would look like: 856 | 857 | ``` 858 | message = <%= message %> 859 | ``` 860 | 861 | ### What ['partial templates'](https://docs.chef.io/resource_template.html#partial-templates) are 862 | - A template can be built in a way that allows it to contain references to one (or more) smaller template files. 863 | - These smaller template files are also referred to as partials. 864 | - A partial can be referenced from a template file in one of the following ways: 865 | - By using the render method in the template file 866 | - `<%= render "simple.txt.erb", :variables => {:user => Etc.getlogin }, :local => true %>` 867 | - By using the template resource and the variables property 868 | 869 | ### Common file-related resource actions and properties 870 | - `file` `cookbook_file` `remote_file` `template` actions: 871 | - `:create` `:create_if_missing` `:delete` `:nothing` `:touch` 872 | - Properties common to every resource include: 873 | - `ignore_failure` `provider` `retries` `retry_delay` `sensitive` `supports` 874 | - Common file-related resource properties: 875 | - `notifies` `mode` `group` `content` `owner` `subscribes` 876 | 877 | ### [ERB syntax](https://docs.puppet.com/puppet/4.9/lang_template_erb.html) 878 | - Each ERB tag has a beginning tag and a matched ending tag. `<% code %>` 879 | - This executes the ruby code within the brackets and does not display the result. `<% if (50 + 50) == 100 %>` 880 | - We use `<%= code %>` when we want to show the value stored in a variable or the result of some calculation. 881 | - For example: `<%= node['hostname'] %>` 882 | 883 | ## CUSTOM RESOURCES - HOW THEY ARE STRUCTURED AND WHERE THEY GO 884 | _Candidates should understand:_ 885 | 886 | ### What custom resources are 887 | - A custom resource can either be a hwrp, lwrp, a definition, or a custom resource. 888 | 889 | ### How to consume resources specified in another cookbook 890 | - depend on cookbook, and then use them 891 | 892 | ### Naming conventions 893 | - If you do not explicitly name the custom resource then it will be named like `_` 894 | 895 | ### How to test custom resources 896 | - [MH:](https://github.com/mhedgpeth/mhedgpeth.github.io/blob/master/_drafts/local-cookbook-development-notes.md) by using a wrapper cookbook embedded inside of the cookbook (I usually put it in `test/cookbooks` and then included in the runlist) 897 | 898 | 899 | ## [LIBRARIES](https://docs.chef.io/libraries.html) 900 | _Candidates should understand:_ 901 | 902 | ### What libraries are and when to use them 903 | - In the same way that the `resources` directory is where you'd store custom resources, you will store ruby code that you want to reuse in the `libraries` directory. 904 | - Use a library to: 905 | - Create a custom class or module; for example, create a subclass of Chef::Recipe 906 | - Connect to a database 907 | - Talk to an LDAP provider 908 | - Do anything that can be done with Ruby 909 | 910 | ### Where libraries are stored 911 | - A library file is a Ruby file that is located within a cookbook’s `/libraries` directory. 912 | 913 | # AVAILALABLE TESTING FRAMEWORKS 914 | 915 | ## INSPEC 916 | _Candidates should understand:_ 917 | 918 | ### How to test common resources with InSpec 919 | - see below 920 | 921 | ### InSpec syntax 922 | 923 | ```ruby 924 | describe bash('command') do 925 | it { should exist } 926 | its('matcher') { should eq 'output' } 927 | end 928 | 929 | describe file('path') do 930 | it { should MATCHER 'value' } 931 | end 932 | 933 | describe http('url', auth: {user: 'user', pass: 'test'}, params: {params}, method: 'method', headers: {headers}, body: body) do 934 | its('status') { should eq number } 935 | its('body') { should eq 'body' } 936 | its('headers.name') { should eq 'header' } 937 | end 938 | 939 | describe os[:family] do 940 | it { should eq 'platform_name' } 941 | end 942 | ``` 943 | 944 | ### How to write InSpec tests 945 | - see above 946 | 947 | ### How to run InSpec tests 948 | - `inspec exec path/to/test` 949 | - After running the tests, you will receive feedback about what was retuned in regard to what was expected. 950 | 951 | ```ruby 952 | describe some_resource('/proc/cpuinfo') do 953 | its('mode') { should cmp '0345' } 954 | end 955 | 956 | expected: 0345 957 | got: 0444 958 | ``` 959 | 960 | ### [Where InSpec tests are stored](http://www.anniehedgie.com/inspec-basics-6) 961 | - locally 962 | - Supermarket 963 | - git 964 | - Chef Compliance Server 965 | 966 | ## CHEFSPEC 967 | Candidates should understand: 968 | 969 | ### What ChefSpec is 970 | - ChefSpec is a framework that tests resources and recipes as part of a simulated chef-client run. 971 | 972 | ### The ChefSpec value proposition 973 | - The benefit of writing tests focused around the Resource Collection will allow us to gain feedback quickly and build a better development workflow. 974 | 975 | ### What happens when you run ChefSpec 976 | - it tests the resources compiled, not running those resources 977 | 978 | ### ChefSpec syntax 979 | 980 | ```ruby 981 | describe 'scenario' 982 | context 'when something happens' do 983 | let :chef_run do 984 | runner = ChefSpec::SoloRunner.new(platform: 'windows', version: '2012R2') 985 | runner.converge(described_recipe) 986 | end 987 | 988 | it 'converges successfully' do 989 | expect { chef_run }.to_not raise_error 990 | end 991 | end 992 | ``` 993 | 994 | ### How to write [ChefSpec tests](https://docs.chef.io/chefspec.html) 995 | 996 | ```ruby 997 | # Recipe - file resource 998 | 999 | file '/tmp/explicit_action' do 1000 | action :delete 1001 | end 1002 | 1003 | file '/tmp/with_attributes' do 1004 | user 'user' 1005 | group 'group' 1006 | backup false 1007 | action :delete 1008 | end 1009 | 1010 | file 'specifying the identity attribute' do 1011 | path '/tmp/identity_attribute' 1012 | action :delete 1013 | end 1014 | ``` 1015 | 1016 | ```ruby 1017 | # Unit Test 1018 | require 'chefspec' 1019 | 1020 | describe 'file::delete' do 1021 | let(:chef_run) { ChefSpec::SoloRunner.new(platform: 'ubuntu', version: '16.04').converge(described_recipe) } 1022 | 1023 | it 'deletes a file with an explicit action' do 1024 | expect(chef_run).to delete_file('/tmp/explicit_action') 1025 | expect(chef_run).to_not delete_file('/tmp/not_explicit_action') 1026 | end 1027 | 1028 | it 'deletes a file with attributes' do 1029 | expect(chef_run).to delete_file('/tmp/with_attributes').with(backup: false) 1030 | expect(chef_run).to_not delete_file('/tmp/with_attributes').with(backup: true) 1031 | end 1032 | 1033 | it 'deletes a file when specifying the identity attribute' do 1034 | expect(chef_run).to delete_file('/tmp/identity_attribute') 1035 | end 1036 | end 1037 | ``` 1038 | ### How to run ChefSpec tests 1039 | - `rspec` or `chef exec rspec` 1040 | 1041 | ### Where ChefSpec tests are stored 1042 | - `spec/unit/recipes` 1043 | 1044 | ## GENERIC TESTING TOPICS 1045 | _Candidates should understand:_ 1046 | 1047 | ### The test-driven development (TDD) workflow 1048 | - Define a test set for the unit first 1049 | - Then implement the unit 1050 | - Finally verify that the implementation of the unit makes the tests succeed. 1051 | - Refactor 1052 | 1053 | ### Where tests are stored 1054 | - Inspec: `/test//` 1055 | - ChefSpec: `/spec/unit/recipes` 1056 | 1057 | ### How tests are organized in a cookbook 1058 | - by suites 1059 | 1060 | ### Naming conventions - how Test Kitchen finds tests 1061 | - The InSpec tests are to be stored in `/test//` 1062 | - If your path is different, then you must specify as such in the .kitchen.yml. 1063 | 1064 | ```yaml 1065 | verifier: 1066 | inspec_tests: 1067 | - test/foo/bar 1068 | ``` 1069 | 1070 | ### Tools to test code "at rest" 1071 | - Foodcritic and Rubocop 1072 | 1073 | ### Integration testing tools 1074 | - InSpec 1075 | 1076 | ### Tools to run code and test the output 1077 | - InSpec 1078 | 1079 | ### When to use ChefSpec in the workflow 1080 | - after linting and before Kitchen 1081 | 1082 | ### When to use Test Kitchen in the workflow 1083 | - after ChefSpec and before promotion to the Chef server or Supermarket 1084 | 1085 | ### Testing intent 1086 | - One should use InSpec to write tests that verify that the desired state was achieved, not necessarily that all of the resources simply converged but that they're functioning in the desired state. 1087 | 1088 | ### Functional vs unit testing 1089 | - Functional is basically integration testing which you'd do with InSpec. 1090 | - Unit testing would be done with ChefSpec. 1091 | 1092 | 1093 | # TROUBLESHOOTING 1094 | 1095 | ## READING TEST-KITCHEN OUTPUT 1096 | _Candidates should understand:_ 1097 | 1098 | ### Test Kitchen phases and associated output 1099 | - `kitchen create` to create the vm instance 1100 | - `kitchen converge` to compile and converge the cookbooks on the vm instance 1101 | - `kitchen verify` to run the InSpec tests on the instance 1102 | - `kitchen destroy` to destroy the instance 1103 | - `kitchen test` to destroy the instance if one exits followed by running through all of the above tests and finishing with another destroy 1104 | - `kitchen login` to log into the vm instance 1105 | - `kitchen init` to initialize a new `.kitchen.yml` 1106 | 1107 | ## COMPILE VS. CONVERGE 1108 | _Candidates should understand:_ 1109 | 1110 | ### What happens during the compile phase of a chef-client run 1111 | - All of the code is run in order to get the resources ready for consumption. 1112 | 1113 | ### What happens during the converge phase of a chef-client run 1114 | - All of the resources are executed on the node. 1115 | 1116 | ### When pure Ruby gets executed 1117 | - This happens in the compile phase. 1118 | 1119 | ### When Chef code gets executed 1120 | - This happens during the converge phase. 1121 | 1122 | 1123 | # SEARCH AND DATABAGS 1124 | 1125 | ## [DATA BAGS](https://docs.chef.io/data_bags.html) 1126 | _Candidates should understand:_ 1127 | 1128 | ### What databags are 1129 | - A data bag is a global variable that is stored as JSON data and is accessible from a Chef server. 1130 | - A data bag is indexed for searching and can be loaded by a recipe or accessed during a search. 1131 | - A data bag is a container of related data bag items, where each individual data bag item is a JSON file. 1132 | - `knife` can load a data bag item by specifying the name of the data bag to which the item belongs and then the filename of the data bag item. 1133 | - The only structural requirement of a data bag item is that it must have an id: 1134 | 1135 | ```json 1136 | { 1137 | /* This is a supported comment style */ 1138 | // This style is also supported 1139 | "id": "ITEM_NAME", 1140 | "key": "value" 1141 | } 1142 | ``` 1143 | 1144 | ### Where databags are stored 1145 | - A `data_bags` directory is sibling to the `cookbooks` directory in the `chef-repo`. Individual databags are stored `data_bags/BAG_NAME/ITEM_NAME.json` 1146 | - When the chef-repo is cloned from GitHub, the following occurs: 1147 | - A directory named data_bags is created. 1148 | - For each data bag, a sub-directory is created that has the same name as the data bag. 1149 | - For each data bag item, a JSON file is created and placed in the appropriate sub-directory. 1150 | 1151 | ``` 1152 | - data_bags 1153 | - admins 1154 | - charlie.json 1155 | - bob.json 1156 | - tom.json 1157 | - db_users 1158 | - charlie.json 1159 | - bob.json 1160 | - sarah.json 1161 | - db_config 1162 | - small.json 1163 | - medium.json 1164 | - large.json 1165 | ``` 1166 | 1167 | ### When to use [databags](https://docs.chef.io/data_bags.html#use-data-bags) 1168 | - when you want data to be accessed by multiple cookbooks within your Chef server 1169 | - Values that are stored in a data bag are global to the organization and are available to any environment. 1170 | 1171 | ### How to use [databags](https://docs.chef.io/data_bags.html#use-data-bags) 1172 | - Data bags can be accessed in the following ways: 1173 | - with **Search** 1174 | - using knife `knife search admin_data "(NOT id:admin_users)"` 1175 | - in a recipe `search(:admins, "id:charlie")` 1176 | 1177 | - with **Environments** 1178 | - data bag that is storing a top-level key for an environment might look something like this: 1179 | 1180 | ```json 1181 | { 1182 | "id": "some_data_bag_item", 1183 | "production" : { 1184 | # Hash with all your data here 1185 | }, 1186 | "testing" : { 1187 | # Hash with all your data here 1188 | } 1189 | } 1190 | ``` 1191 | - When using the data bag in a recipe, that data can be accessed from a recipe using code similar to: 1192 | 1193 | ```ruby 1194 | bag_item[node.chef_environment]['some_other_key'] 1195 | ``` 1196 | - with **Recipes** 1197 | - Loaded by name when using the Recipe DSL. Use this approach when a only single, known data bag item is required. 1198 | - `data_bag(bag)`, where `bag` is the name of the data bag. 1199 | - For example, the contents of a data bag item named justin: `data_bag_item('admins', 'justin')` will return something similar to: `# => {'comment'=>'Justin Currie', 'gid'=>1005, 'id'=>'justin', 'uid'=>1005, 'shell'=>'/bin/zsh'}` 1200 | - `data_bag_item('bag_name', 'item', 'secret')`, where `bag` is the name of the data bag and item is the name of the data bag item. If `'secret'` is not specified, the `chef-client` will look for a secret at the path specified by the `encrypted_data_bag_secret` setting in the `client.rb` file. 1201 | - Accessed through the search indexes. Use this approach when more than one data bag item is required or when the contents of a data bag are looped through. The search indexes will bulk-load all of the data bag items, which will result in a lower overhead than if each data bag item were loaded by name. 1202 | 1203 | - with **Chef Solo** 1204 | - chef-solo can load data from a data bag as long as the contents of that data bag are accessible from a directory structure that exists on the same machine as chef-solo. The location of this directory is configurable using the data_bag_path option in the solo.rb file. 1205 | 1206 | ### How to create a databag 1207 | - A data bag can be created in two ways: using `knife` or manually. In general, using knife to create data bags is recommended, but as long as the data bag folders and data bag item JSON files are created correctly, either method is safe and effective. 1208 | - `knife data bag create DATA_BAG_NAME (DATA_BAG_ITEM)` 1209 | - `knife data bag from file BAG_NAME ITEM_NAME.json` 1210 | - This will load the following file: `data_bags/BAG_NAME/ITEM_NAME.json` 1211 | 1212 | ### How to update a databag 1213 | - A data bag can be edited in two ways: 1214 | - using `knife` 1215 | - `knife data bag edit BAG_NAME ITEM_NAME` will open the $EDITOR 1216 | - Once opened, you can update the data before saving it to the Chef server. 1217 | - (You can also just edit it in your own editor, then `knife data bag from file BAG_NAME ITEM_NAME.json` again.) 1218 | - using the Chef management console (the Chef server UI on manage.chef.io) 1219 | - Click Policy. 1220 | - Click Data Bags. 1221 | - Select a data bag. 1222 | - Select the Items tab. 1223 | - Select a data bag. 1224 | - Click Edit. 1225 | 1226 | ### How to search databags 1227 | - A data bag is a global variable that is stored as JSON data and is accessible from a Chef server. 1228 | - A data bag is indexed for searching and can be loaded by a recipe or accessed during a search. 1229 | 1230 | ```ruby 1231 | search(:admins, "*:*") 1232 | ``` 1233 | 1234 | ```ruby 1235 | search(:admins, "id:charlie") 1236 | ``` 1237 | 1238 | ```ruby 1239 | search(:admins, "id:c*") 1240 | ``` 1241 | 1242 | ```ruby 1243 | admins = data_bag('admins') 1244 | 1245 | admins.each do |login| 1246 | admin = data_bag_item('admins', login) 1247 | home = "/home/#{login}" 1248 | 1249 | user(login) do 1250 | uid admin['uid'] 1251 | gid admin['gid'] 1252 | shell admin['shell'] 1253 | comment admin['comment'] 1254 | home home 1255 | manage_home true 1256 | end 1257 | 1258 | end 1259 | ``` 1260 | 1261 | ### [Chef Vault](https://docs.chef.io/chef_vault.html) 1262 | - Chef Vault is similar to encryped databags except that it provides two layers of encryption instead of just one. 1263 | - chef-vault allows the encryption of a data bag item by using the public keys of a list of nodes, allowing only those nodes to decrypt the encrypted values. `chef-vault` adds the `knife vault` subcommand. 1264 | - The chef-vault cookbook is maintained by Chef. Use it along with chef-vault itself. This cookbook adds the `chef_vault_item` helper method to the Recipe DSL and the `chef_vault_secret` resource. Use them both in recipes to work with data bag secrets. 1265 | 1266 | ### The difference between databags and attributes 1267 | - Databags have no precedence and are cookbook independent. 1268 | 1269 | ### What `knife` commands to use to CRUD databags 1270 | - create: `knife data bag create myproduct` 1271 | - read: `knife data bag show myproduct values` 1272 | - update: either `knife data bag edit myproduct values` or `knife data bag from file myproduct values.json` (preferred) 1273 | - delete: `knife data bag delete myproduct` 1274 | 1275 | 1276 | ## [SEARCH](https://docs.chef.io/chef_search.html) 1277 | _Candidates should understand:_ 1278 | 1279 | ### What data is indexed and searchable 1280 | - Search indexes allow queries to be made for any type of data that is indexed by the Chef server, including data bags (and data bag items), environments, nodes, and roles. 1281 | 1282 | ### Why you would search in a recipe 1283 | - There is a lot of information that `chef-client` will not have until it is run, like what kind of node it is on, which environment it is in, what role it has, etc. We can invoke a search to fill in the proper attributes and values to be consumed by the recipe as needed. 1284 | 1285 | ### Search criteria syntax 1286 | - A search query is comprised of two parts: the key and the search pattern. A search query has the following syntax: `key:search_pattern` where `key` is a field name that is found in the JSON description of an indexable object on the Chef server (a role, node, client, environment, or data bag) and `search_pattern` defines what will be searched for, using one of the following search patterns: exact, wildcard, range, or fuzzy matching. 1287 | - Both `key` and `search_pattern` are case-sensitive; `key` has limited support for multiple character wildcard matching using an asterisk (“*”) (and as long as it is not the first character). 1288 | 1289 | ### How to invoke a search from the command line 1290 | - `knife search` commands can be use to search the Chef server. 1291 | - `knife search node 'network_interfaces__addresses:192.168*'` 1292 | - `knife search admins 'id:charlie'` 1293 | - `knife search node 'foo:*'` 1294 | - Use the `AND`, `NOT`, or `OR` [boolean operators](https://docs.chef.io/chef_search.html#and) 1295 | - `knife search node 'platform:windows AND roles:jenkins'` 1296 | - `knife search sample "(NOT id:foo)"` 1297 | - `knife search sample "id:foo OR id:abc"` 1298 | 1299 | ### How to invoke a search from within a recipe 1300 | - `search(:node, "key:attribute")` 1301 | - `search(:node, 'roles:load_balancer')` 1302 | 1303 | ```ruby 1304 | # search node 1305 | search(:node, "*:*").each do |matching_node| 1306 | puts matching_node.to_s 1307 | end 1308 | ``` 1309 | 1310 | ```ruby 1311 | search(:node, 'platform:ubuntu AND name:CHEF*').each |matching_node| 1312 | puts matching_node['ipaddress'] 1313 | puts matching_node['name'] 1314 | end 1315 | ``` 1316 | 1317 | ```ruby 1318 | # search environments 1319 | qa_nodes = search(:node,"chef_environment:QA") 1320 | qa_nodes.each do |qa_node| 1321 | # Do useful work specific to qa nodes only 1322 | end 1323 | ``` 1324 | 1325 | ```ruby 1326 | # search data bags (see above for more) 1327 | search(:admin_data, "NOT id:admin_users") 1328 | ``` --------------------------------------------------------------------------------