Mischa Taylor's Coding Blog
Time 2022-08-22 09:48:14Web Name: Mischa Taylor's Coding Blog
WebSite: http://www.misheska.com
ID:289010
Keywords:
Taylor,Mischa,Blog,CodingDescription:
Mischa Taylor's Coding Blog
On the edge of time and reason
Chef Server 12
The source code for this article can be found at https://github.com/learningchef/learningchef-code/tree/master/chefserver12.
Make sure you install the latest Chef Development Kit 0.3.5 (or higher) and/orChef Client 11.18 (or higher) before trying to run knife
commands againstChef Server 12. It appears that some changes were made to the clients foradministrators to work with Chef Server 12, so these newer versions (at thetime of this writing) are required that came out since the Learning Chef bookwas published.
Introduction
In the Learning Chef book we cover Chef Server 11 in Chapters 9 and 10, as that was the version ofChef Server available when we were writing the book. Since then, Chef Server12 has been released. This blog post covers how the material presentedin Chapter 9 can be adapted for Chef Server 12. No changes are needed inChapter 10 for Chef Server 12.
Chef Server 12 merges the code bases for what were three separate flavors ofChef Server:
Open Source Chef Server On-Premises Enterprise Chef Hosted Enterprised ChefAlso the pricing for Chef Server has changed as well to match. Formore information on the changes, refer to Chef plans and pricing.
From a technical standpoint, the great thing about Chef Server 12 is that isnow shares the same core, whether or not you choose to use what used to be theopen source option or you pay for a subscription to take advantage of ChefServer’s Premium features.
Installing Chef Server 12 Manually
To install Chef Server, go to https://downloads.getchef.com/ and click on the “Get It” button, as shown in the following screenshot:
From there, you are presented with a download link page where you can chooseto download Chef Server 12. Chef Server 12 currently provides install packagesfor both the Red Hat Enterprise Linux and Ubuntu Linux platforms (sorry, noWindows support for the server piece, only for Windows clients):
To manually replicate a basic Chef Server install in a cookbook, we first needto download the Chef Server 12 install package for Red Hat Enterprise Linux 6,as we’ll be installing on CentOS 6.5. To match what is being written in thisarticle, use version 12.0.0. Use the Copy Link Addressoption on the download link to copy the full download URl to your clipboard.
Here’s the rest of the steps necessary to install Chef Server:
Install thechef-server
package. Run sudo chef-server-ctl reconfigure
.NOTE: The name of the command line application to configure Chef Server haschanged from private-chef-ctl
to chef-server-ctl
with version 12.
Install Chef Server 12
Assuming you have sufficient resources to install Chef Server 12 locally alongwith a test node, let’s create a chef-server
cookbook that will installChef Server 12. To maintain consistency with Hosted Enterprise Chef, createthe directory chef-repo/cookbooks
and create the chef-server
cookbook inthat directory. Having a top-level chef-repo
directory will help you handlethe additional files necessary to manage Chef Server 12 beyond the cookbooksthemselves. You’ll definitely be using more than one cookbook in yourorganization, so we suggest putting them in a chef-repo/coobkooks
subdirectory.
Create the chef-repo/cookbooks
directory and make it the current workingdirectory.
Linux/Mac OS X:
$ mkdir -p chef-repo/cookbooks$ cd chef-repo/cookbooks
Windows:
> mkdir chef-repo\cookbooks> cd chef-repo\cookbooks
Then generate the chef-server
cookbook with chef generate cookbook
orknife cookbook create
, dependening on whether you are using the ChefDevelopment Kit or Chef Client. We’re going to go through the cookbookcreation steps quickly in this article. If you need a refresher on what eachof these commands mean and the expected output, refer to Chapter 7 of theLearning Chef book.
Chef Development Kit:
$ chef generate cookbook chef-server$ cd chef-server
Chef Client:
$ knife cookbook create chef-server --cookbook-path .$ cd chef-server$ kitchen init --create-gemfile$ bundle install
As shown in the code example below, edit the .kitchen.yml
file to use theCentOS 6.5 basebox we prepared specifically for the Learning Chef book. Alsoassign a private network address like we did in Chapter 7 of Learning Chef.This time we’re going to use the IP address 192.168.38.34
. If this conflictswith an address already being used on your local network. change it to anonconflicting one. We also need more memory than the default 512 MB allocated,so add a customize:
block with a memory:
statement to increase the memoryto 1.5 GB (memory is specified in megabytes only).
NOTE: We also changed the suite name to server
as we’ll be logging into the virtual machine with Chef Server 12. This makes it more clearthat the examples should be run on the Chef Server machine.
Generate a default attributes file in attributes/default.rb
.
Chef Development Kit:
$ chef generate attribute default
Chef Client:
$ touch attributes/default.rb
Add an attribute specifying the download URL for the Chef Server packagethat you obtained from the download link page. We recommend using the 12.0.0version URL as shown below, as we wrote the exampels for this article usingthis Version of Chef Server.
From here, we’re just going to skip ahead to the final bit of code in the“Introducing Idempotence” section of Chapter 9 in Learning Chef, as everythingremains the same for Chef Server 12. The only difference is the commandline app for configuring Chef Server is now called chef-server-ctl
insteadof private-server-ctl
. Refer to Chapter 9 in Learning Chef for moreexplanation on what this code does.
Try running kitchen converge
against this recipe, and note that it reports 0/2 resources updated
, which is the result we are looking for; no resourcesare updated after running kitchen converge for the second time:
$ kitchen converge-----> Starting Kitchen (v1.2.1)-----> Converging <default-centos65>......Converging 3 resources Recipe: chef-server::default * remote_file[/tmp/kitchen/cache/chef-server-core-12.0.0-1.el6.x86_64.rpm] action create[2014-11-26T01:27:20+00:00] INFO: Processing remote_file[/tmp/kitchen/cache/chef-server-core-12.0.0-1.el6.x86_64.rpm] action create (chef-server::default line 11) (up to date) * package[chef-server-core-12.0.0-1.el6.x86_64.rpm] action install[2014-11-26T01:27:27+00:00] INFO: Processing package[chef-server-core-12.0.0-1.el6.x86_64.rpm] action install (chef-server::default line 15) (up to date) * execute[reconfigure-chef-server] action nothing[2014-11-26T01:27:28+00:00] INFO: Processing execute[reconfigure-chef-server] action nothing (chef-server::default line 22) (skipped due to action :nothing) [2014-11-26T01:27:28+00:00] INFO: Chef Run complete in 7.811144016 seconds Running handlers: [2014-11-26T01:27:28+00:00] INFO: Running report handlers Running handlers complete [2014-11-26T01:27:28+00:00] INFO: Report handlers complete Chef Client finished, 0/2 resources updated in 10.600168629 seconds Finished converging <default-centos65> (0m12.49s).-----> Kitchen is finished. (0m13.51s)
Always check your recipes to see if they are idempotent before deploying themto production. If we had deployed the first version of this recipe inproduction, given that the chef-client usually runs on a periodic timerperforming Chef runs, all our nodes would have been reinstalling the ChefServer package and reconfiguring the server every 30 minutes!
Configure Chef Server
The configuration of Chef Server has changed considerably with Chef Server 12.Now, the server does not enable a web UI by default, and you are expected toconfigure the Chef Server primarily through the command line.
You need to perform two actions in order to configure Chef Server 12:
Create an admin user Create an organizationBoth of these actions are now chef-server-ctl
subcommands: user-create
and org-create
respectively.
NOTE: You may be tempted to skip ahead and install the management UI and tryto configure an admin user/organization in the web UI, just like you did withChef Server 11. Unfortunately this approach does not work with version 12.0.0.You must create one admin user and an initial organization on the command linefirst, then you can create the rest in the web UI.
The chef-server-ctl user-create
command is used to create a user Thehelp for the command usage follows. As of this writing the help mistakenlydisplays usage for the legacy knife opc user create
command, but it isreally now supposed to be chef-server-ctl user-create
:
USAGE: knife opc user create USERNAME FIRST_NAME [MIDDLE_NAME] LAST_NAME EMAIL PASSWORD-f, --filename FILENAME Write private key to FILENAME rather than STDOUT
The chef-server-ctl org-create
command is used to create an organization. Thehelp for the command usage follows. It currently has a similar issue with thehelp referencing the legacy command, similar to user-create
:
USAGE: knife opc org create ORG_SHORT_NAME ORG_FULL_NAME (options)-f, --filename FILENAME Write validator private key to FILENAME rather than STDOUT
In both cases, use the --filename
parameter to write the *.pem
filescontaining the user and organization keys. By default, they are just echoedto STDOUT.
Login to the server-centos65
instance to create the first admin user and thefirst organization. I created an admin user for myself, just like I did inChapter 9 of Learning Chef. Here’s the results of the commands I ran:
$ kitchen login server-centos65Last login: Wed Nov 26 01:59:12 2014 from 10.0.2.2Welcome to your Packer-built virtual machine.[vagrant@server-centos65 ~]$ sudo chef-server-ctl user-create misheska Mischa Taylor mischa@misheska.com chefrocks --filename misheska.pem...[vagrant@server-centos65 ~]$ sudo chef-server-ctl org-create learningchef "Learning Chef" --association misheska --filename learningchef-validator.pem...[vagrant@server-centos65 ~]$ ls *.pemlearningchef-validator.pem misheska.pem[vagrant@server-centos65 ~]$ exitlogoutConnection to 127.0.0.1 closed.
NOTE: You’ll need sudo
or root
access to run the user-create
andorg-create
commands, because they need access to the default superuser keyowned by root
. This key is located in /etc/opscode/pivotal.pem
.
After you have created the <username>.pem and <organization>-validator.pemfiles to the chef-repo/.chef
directory on your host. One way to do this isto use the scp
command to copy the files. Here’s what I did to create thesefiles on my host after making chef-repo
the current working directory:
$ mkdir .chef$ scp -o stricthostkeychecking=no vagrant@192.168.38.34:/home/vagrant/misheska.pem .chef/misheska.pemvagrant@192.168.38.34's password: vagrant$ scp -o stricthostkeychecking=no vagrant@192.168.38.34:/home/vagrant/learningchef-validator.pem .chef/learningchef-validator.pemvagrant@192.168.38.34's password: vagrant
For the initial organization, you’ll need to create your own knife.rb
fileby hand. Here’s the knife.rb
file I used:
The chef_server_url
field in the knife.rb
uses a fake DNS hostname ofserver-centos65.vagrantup.com
because that’s the hostname vagrant set up.If you try to visit the URL https://server-centos65.vagrantup.com/organization/learningchef, you will discover that it is not valid.
Chef Server requires that hosts have valid fully qualified domain names set upin your local domain name service (DNS). In production, you would have yourChef Server hosntame configured in your Domain Name System (DNS) server beforeinstalling Chef Server. Let’s add a temporary host entry forserver-centos65.vagrantup.com
in your local host database in lieu of makinga DNS change, as we are just doing a book exercose.
Run one of the following commands to add a host entry. Following are thecommands I ran on my machine. If you used an IP address other than192.168.38.34
, make sure it matches when you run the command.
Linux/Mac OS X:
$ sudo sh -c "echo '192.168.38.34 server-centos65.vagrantup.com' >> /etc/hosts"
Windows Command Prompt:
> echo 192.168.38.34 server-centos65.vagrantup.com >> %WINDIR%\System32\Drivers\Etc\Hosts
Windows PowerSHell:
PS> ac -Encoding UTF8 $env:windor\system32\drivers\etc\hosts "192.168.38.34 server-centos65.vagrantup.com"
Now if you try to visit https://default-centos65.vagrantup.com in your webbrowser, your local host should think that this is a valid hostname.
Testing the Connection
You should run the following commands from inside the Chef repository. Openyour termianl or command prompt, and make chef-repo
the current workingdirectory. If you placed your chef-repo
in a different location, use thatinstead:
$ cd ~/chef-repo
Now you can use knife
, the command-line tool for Chef Server, to test yourconnection and authentication against Chef Server. At the time of this writing,Chef does not provide a “connection test” command. However, asking ChefServer to list the clients will very
Issue the knife client list
command on your terminal. You should see thefollowing:
$ knife client listlearningchef-validator
If you get an error, checking the following:
You can access https://server-centos65.vagrantup.com:443 from a web browser. You are running commands from inside the chef-repo directory. The .chef directory contains two .pem files and a knife.rb. Your authentication fiels have the correct file permissions (they should be only user-readable). You are using the Chef Development Kit 0.3.5 and/or chef-client 11.18.0 (or higher). These tools needed some updates to work properly with Chef Server 12.If you have confirmed the preceding steps and are still unable to connectto Chef Server, please consult the Chef online documentation.
From this point forward, the steps for bootstrapping a node are the same aswith Chef Server 11. Refer to the “Bootstrapping a Node” section in Chapter 9of Learning Chef for more information.
Installing the web UI
The web UI is now a premium feature of Chef Server. It is not installed bydefault. To install the web UI on your Chef Server, run the followingcommands to install the opscode-manage
plugin and reconfigure both theweb UI configuration and the Chef Server configuration to use the web UI:
$ cd cookbooks/chef-server$ kitchen loginLast login: Wed Nov 26 04:09:56 2014 from 10.0.2.2Welcome to your Packer-built virtual machine.[vagrant@server-centos65 ~]$ sudo chef-server-ctl install opscode-manage...[vagrant@server-centos65 ~]$ sudo opscode-manage-ctl reconfigure...[vagrant@server-centos65 ~]$ sudo chef-server-ctl reconfigure...[vagrant@server-centos65 ~]$ exitlogoutConnection to 127.0.0.1 closed.
Once you have configured Chef Server to use the web UI, vist https://server-centos65.vagrantup.com. You should see something resemblingthe following screenshot. Since you already created an admin account,click on the Click here to sign in link:
Clicking on the link will take you to https://server-centos65.vagrantup.com/login where you can sign in with your administrator account, as shown in the following:
From there, you can access the management UI for Chef Server 12!
Conclusion
This blog post covered all the relevant changes needed to adapt the materialpresented in Chapter 9 of the Learning Chef book for Chef Server 12.Thankfully, besides the server configuration steps, not much changed.
In addition to the material presented in this article, you might want toconsider automating the creation of the admin user and organization in yourChef cookbook. To see how this might be done, take a look at the Chefcookbook I use to demo Chef Server 12 for clients athttps://github.com/misheska-cookbooks/chef-server12.
Survey of Test Kitchen Providers
Update November 10, 2014* Update for DigitalOcean 0.8x provider using API V2
Introduction
Test Kitchen supports a wide variety of different providers via Test Kitchen drivers besides the default kitchen-vagrant
driver. In this post, we’ll cover several popular alternatives.
Test Kitchen drivers are gem libraries available for download from http://rubygems.org . Use the kitchen driver discover
command to list all the Test Kitchen gems currently available. Here is a list of all the Test Kitchen drivers as of this writing:
$ kitchen driver discover Gem Name Latest Stable Release kitchen-all 0.2.0 kitchen-ansible 0.0.1 kitchen-azure 0.1.0 kitchen-bluebox 0.6.2 kitchen-cabinet 3.0.0 kitchen-cloudstack 0.10.0 kitchen-digital_ocean 0.3.0 kitchen-digitalocean 0.8.0 kitchen-docker 1.5.0 kitchen-docker-api 0.4.0 kitchen-driver-vagrant_provision 1.0.0 kitchen-ec2 0.8.0 kitchen-fifo 0.1.0 kitchen-fog 0.7.3 kitchen-gce 0.2.0 kitchen-goiardi 0.1.1 kitchen-inspector 1.3.0 kitchen-joyent 0.1.1 kitchen-libvirtlxc 0.4.0 kitchen-local 0.0.1 kitchen-lxc 0.0.1 kitchen-openstack 1.6.0 kitchen-puppet 0.0.13 kitchen-rackspace 0.12.0 kitchen-rightscale 0.1.0 kitchen-salt 0.0.19 kitchen-scribe 0.3.1 kitchen-sharedtests 0.2.0 kitchen-ssh 0.0.4 kitchen-sshgzip 0.0.3 kitchen-sync 1.0.1 kitchen-vagrant 0.15.0 kitchen-vagrant_sandbox 0.1.1 kitchen-vagrant_winrm 0.1.1 kitchen-zcloudjp 0.5.0 test-kitchen-provisioners 0.1
By default, Test Kitchen defaults to using the kitchen-vagrant
driver. When you run the kitchen init
command to add Test Kitchen support to a project, you can add the --driver=<gem_name>
option to have Test Kitchen generate configuration files using another driver of your choice. For example, the following command would use the kitchen-azure
driver:
kitchen init --create-gemfile --driver=kitchen-azure
As shown in the following diagram the environments supported by Chef-releated drivers fall into four different categories: desktop virtual machines, public/private cloud providers, Linux containers and physical machines. We’ll cover representative examples from each category in this appendix.
Desktop Virtualization
Test Kitchen uses the kitchen-vagrant
driver to work with desktop virtualization providers, like VirtualBox, VMWare Fusion, VMWare Workstation and Hyper-V. Since the kitchen-vagrant
driver is just a shim on top of Vagrant for Test Kitchen, any provider that Vagrant supports should be supported by the kitchen-vagrant
driver.
It is important to clarify that as of this writing, the kitchen-vagrant
driver assumes that the virtualization provider is installed locally on the host machine. As shown in the following diagram, using the kitchen-vagrant
driver, Test Kitchen creates a sandbox environment virtual machine locally on your host:
kitchen-vagrant
driver to create a virtual machine instance. In the case of the kitchen-vagrant
driver, Vagrant itself contains all the logic to work with different types of virtualization software. The kitchen-vagrant
is just a small shim to allow Test Kitchen to use Vagrant to work with virtual machine instances. In this example, Vagrant uses the VirtualBox API to spin up a virtual machine instance for our sandbox environment. Once the sandbox environment is running, Test Kitchen links the instance for communication.Test Kitchen treats the data center versions of VMware, like vCenter/vSphere/ESXi as a cloud provider. To Test Kitchen the data center editions are handled as if there were cloud instances, as vCenter/vSphere/ESXi merely a private cloud on a local LAN or corporate WAN instead of a public cloud over the Internet. As of this writing, the kitchen-openstack
and kitchen-ssh
drivers support vSphere data center virtualization with Test Kitchen.
kitchen-vagrant with VMware Fusion/VMware Workstation desktop virtualization
You can use VMware desktop virutalization with kitchen-varant
instead of Oracle VM VirtualBox. It requires the purchase of the Vagrant VMware plugin from https://www.vagrantup.com/vmware which, at the time of this writing, costs USD $79 per seat. The VMware plugin works with VMware Workstation 9 and 10 on Windows/Linux and VMware Fusion 5, 6 and 7 on Mac OS X.
On Mac OS X/Linux, you may have multiple virtualization solutions installed alongside VMware. On these platforms, you can use both VMware and VirtualBox baseboxes at the same time, for example, if you have enough system resources. On Windows, you must make a choice, as only one virtualization solution can be installed at a time.
Once you have purchased the VMware plugin and received a license file, you can install the Vagrant plugin and license with the following:
For VMware Workstation (on Windows/Linux):
$ vagrant plugin install vagrant-vmware-workstation$ vagrant plugin license vagrant-vmware-workstation license.lic
For VMware Fusion (on Mac OS X):
$ vagrant plugin install vagrant-vmware-fusion$ vagrant plugin license vagrant-vmware-fusion license.lic
After you install the VMware plugin and license file and want to use VMware, you’ll need to get VMware baseboxes. Currently VirtualBox and VMware baseboxes are not interchangeable.
Once the VMware plugin and license has been installed, you’ll need to change your .kitchen.yml
files slightly for VMware. You can specify the VMware provider name in the platforms
section of your .kitchen.yml
file.
Modify the .kitchen.yml
file, adding a provider:
line to the platforms
driver
section. If you are using VMware Workstation, use the vmware_workstation
provider name. For VMware Fusion, the provider name should be vmware_fusion
. You’ll also need to change the box_url
line to point at a box file which has Vmware Tools installed, as box files are not guest tool agnostic. For this book, box files have been provided for both VMware and VirtualBox via VagrantCloud, so you can use the same box_url
line.
Synced folders work the same as with VirtualBox. Just add a synced_folders:
block to the driver:
section with a list of folders to map between the guest and the host. Each entry in the list contains an array with two parameters. The first parameter is a path to the directory on the host machine. If the path is relative, it is relative to the .kitchen.yml
file. The second parameter is an absolute path specifying where the folder is shared on the guest machine. The .kitchen.yml
examples that follow map the current working directory on the host to the directory /vagrant
on the guest, like so:
... synced_folders: - [".", "/vagrant"]...
VMware Workstation .kitchen.yml
example:
VMware Fusion .kitchen.yml
example:
Once you modify the .kitchen.yml
file appropriately the kitchen create
, kitchen converge
, etc. commands will use VMware instead of VirtualBox:
$ kitchen create default-centos65-----> Starting Kitchen (v1.2.2.dev)-----> Creating <default-centos65>... Bringing machine 'default' up with 'vmware_fusion' provider... ==> default: Cloning VMware VM: 'learningchef/centos65'. This can take some time... ==> default: Checking if box 'learningchef/centos65' is up to date... ==> default: Verifying vmnet devices are healthy... ==> default: Preparing network adapters... ==> default: Fixed port collision for 22 => 2222. Now on port 2200. ==> default: Starting the VMware VM... ==> default: Waiting for the VM to finish booting... ==> default: The machine is booted and ready! ==> default: Forwarding ports... default: -- 22 => 2200 ==> default: Setting hostname... ==> default: Configuring network adapters within the VM... ==> default: Waiting for HGFS kernel module to load... ==> default: Enabling and configuring shared folders... default: -- /Users/misheska/github/learningchef/learningchef-code/chapa01/vmware/fusion: /vagrant ==> default: Machine not provisioning because `--no-provision` is specified. Vagrant instance <default-centos65> created. Finished creating <default-centos65> (0m39.42s).-----> Kitchen is finished. (0m39.66s)
Test Kitchen Cloud Drivers
The following diagram shows how the Test Kitchen cloud drivers create a sandbox environment. The main difference between using a cloud provider and desktop virtualization is that the sandbox environment lives remotely on another machine. Test Kitchen communicates with the sandbox environment remotely over SSH, usually on the Internet.
Test Kitchen invokes the specified driver (likekitchen-ec2
) to create an instance on the cloud provider. Cloud provider drivers communicate with the cloud provider using the appropiate cloud API. Normally this is an HTTP API. The cloud provider spins up an instance to serve as our sandbox environment. Once the sandbox environment is running, Test Kitchen links the instance to your local development workstation for remote communication, usually over SSH. All Test Kitchen commands work with the remote sandbox environment transparently. As far as the user experience with Test Kitchen goes, it behaves as if it were a local desktop virtualization environment.As of this writing, all of the Test Kitchen Cloud drivers do not support synchronized folders. All kitchen
commands automatically copy your project files to the sandbox environment, as Test Kitchen uses scp
to transfer files from your host to the remote cloud instance. For any other file sharing beyond what is supported by Test Kitchen, you’ll need to use a Cloud Provider-specific mechanism, such as Amazon Elastic Block Store (EBS).
DigitalOcean Cloud Provider (kitchen-digitalocean)
kitchen-digitalocean Setup
Go to https://cloud.digitalocean.com/settings/applications and click on theGenerate new token
button to generate a new Personal Access Token usingthe v2.0 API. Make sure you check the optional Write
scope when yougenerate the token. Write scope is necessary for the DigitalOcean Cloudprovider to function correctly.
Record the personal access token that is generated when you click on theGenerate new token
button, as shown below:
Add the new access token to your ~/.bash_profile
(or equivalent for yourplatform) as the environment variable DIGITALOCEAN_ACCESS_TOKEN
:
export DIGITALOCEAN_ACCESS_TOKEN="1234567890abcdefg"
Collect SSH public keys from the computers which need access to your sandboxinstances. Visit https://cloud.digitalocean.com/ssh_keys and add the SSH keys.Once you’ve added the SSH keys(s), use the following curl
command to get theDigitalOcean SSH Key IDs:
curl -X GET https://api.digitalocean.com/v2/account/keys -H "Authorization: Bearer $DIGITALOCEAN_ACCESS_TOKEN"
Record the id
field for each of your SSH keys. Add the list of SSH Key IDsto the environment variable DIGITALOCEAN_SSH_KEY_IDS
. If you have more thanone SSH key ID, separate each ID by a comma followed by a space:
export DIGITALOCEAN_SSH_KEY_IDS="12345, 67890"
Run the following kitchen init
command to add Test Kitchen support to your project using the kitchen-digitalocean
driver:
$ kitchen init --driver=kitchen-digitalocean --create-gemfile create .kitchen.yml create test/integration/default create Gemfile append Gemfile append GemfileYou must run `bundle install' to fetch any new gems.
Run bundle install
to download and install any required gems.
kitchen-digitalocean .kitchen.yml Example
As of the 0.8.x release, the kitchen-digitalocean
provider automatically looks for the access token in the DIGITAL_ACCESS_TOKEN
and the ssh keyIDs in the DIGITALOCEAN_SSH_KEY_IDS
environment variables. Since theaccess token and SSH key IDs are sensitive information, it is recommendedthat you store them in these environment variables instead of directly inyour .kitchen.yml
file. This way, you can share your .kitchen.yml
filewith others and store it in source control.
Here is an example kitchen.yml
which spins up a CentOS 6.5 sandbox environment, loading the Access Token and SSH Key IDs from corresponding environment variables:
Before running any Test Kitchen commands, make sure you set the appropriate environment variables as shown below (with your own values):
Linux and Mac OS X:
export DIGITALOCEAN_ACCESS_TOKEN="01234567890abcdef01234567890abcdef"export DIGITALOCEAN_SSH_KEY_IDS="12345, 67890"
Windows Command Prompt:
set DIGITALOCEAN_ACCESS_TOKEN=01234567890abcdef01234567890abcdefset DIGITALOCEAN_SSH_KEY_IDS=12345, 67890
Windows Powershell:
$env:DIGITALOCEAN_ACCESS_TOKEN="01234567890abcdef01234567890abcdef"$env:DIGITALOCEAN_SSH_KEY_IDS="12345, 67890"
The output of kitchen list
should resemble the following:
$ kitchen listInstance Driver Provisioner Last Actiondefault-centos65 Digitalocean ChefZero <Not Created>
Spin up the node with kitchen create
:
$ kitchen create default-centos65-----> Starting Kitchen (v1.2.1)-----> Creating <default-centos65>... Digital Ocean instance <3129943> created. Waiting for 192.241.185.202:22... Waiting for 192.241.185.202:22... (ssh ready) Finished creating <default-centos65> (2m42.61s).-----> Kitchen is finished. (2m42.82s)
Install Chef Client with kitchen setup
. kitchen destroy
will delete your Droplet on DigitalOcean.
Refer to the kitchen-digitalocean
driver documentation on https://github.com/test-kitchen/kitchen-digitalocean for more information on additional .kitchen.yml
settings.
Amazon EC2 Cloud Provider (kitchen-ec2)
kitchen-ec2 Setup
In order to use the kitchen-ec2
driver, you’ll need to create an Amazon Web Services access key, consisting of an access key ID plus a secret key. You can create a new access key ID and secret _key or retrieve an existing access key ID on the AWS Identity and Access Management (IAM) page in the AWS Console. Once you select a user, click on the Manage Access Keys button as shown in the following:
In the Manage Access keys dialog, click on the Create Access Key button to create a new access key ID and secret _key as shown in the following:
AWS will create your access key. You can click on Show User Security Credentials to display the Access Key ID and the Secret Access Key. Make note of these as this is the last time they will be displayed. You can also click on the Download Credentials button to download the credentials as a .csv
file as shown below:
Create a key pair to use when you launch instances. Amazon EC2 supports a variety of ways to work with key pairs. Refer to http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html for more information.
Make sure you set permissions on the key pair. Otherwise kitchen-ec2
will ignore the file.
chmod 400 my-key-pair.pem
Run the following kitchen init
command to add Test Kitchen support to your project using the kitchen-ec2
driver:
$ kitchen init --driver=kitchen-ec2 --create-gemfile create .kitchen.yml create test/integration/default create Gemfile append Gemfile append GemfileYou must run `bundle install' to fetch any new gems.
Run bundle install
to fetch any new gems.
kitchen-ec2 .kitchen.yml Example
Since the Access Key ID, Secret Access Key and SSH Key ID contain sensitive information, it is recommended that you store these values in environment variables instead of directly in your .kitchen.yml
file. This way, you can share your .kitchen.yml
file with others and store it in source control. You can use embedded Ruby templates in a .kitchen.yml
file to load values from the environment. Here is an example kitchen.yml
which spins up a CentOS 6.5 sandbox environment, loading the Access Key ID, Secret Acces Key and SSH Key ID from corresponding environment variables:
Before running any Test Kitchen commands, make sure you set the appropriate environment variables as shown below (with your own values):
Linux and Mac OS X:
export AWS_ACCESS_KEY_ID="ABCDEFGHI123JKLMNOPQ"export AWS_SECRET_ACCESS_KEY="abcdefghijklmnopqrstuvwyz"export AWS_SSH_KEY_ID="keyid1234"export AWS_SSH_KEY="$HOME/ec2/$AWS_SSH_KEY_ID.pem"
Windows Command Prompt:
set AWS_ACCESS_KEY_ID=ABCDEFGHI123JKLMNOPQset AWS_SECRET_ACCESS_KEY=abcdefghijklmnopqrstuvwyzset AWS_SSH_KEY_ID=keyid1234set AWS_SSH_KEY=%USERPROFILE%/ec2/%AWS_SSH_KEY_ID%.pem
Windows Powershell:
$env:AWS_ACCESS_KEY_ID="ABCDEFGHI123JKLMNOPQ"$env:AWS_SECRET_ACCESS_KEY="abcdefghijklmnopqrstuvwyz"$env:AWS_SSH_KEY_ID="keyid1234"$env:AWS_SSH_KEY="$env:userprofile/ec2/$env:aws_ssh_key_id.pem"
The output of kitchen list
should resemble the following:
$ kitchen listInstance Driver Provisioner Last Actiondefault-centos65 Ec2 ChefSolo <Not Created>
Spin up the node with kitchen create
:
$ kitchen create default-centos65-----> Starting Kitchen (v1.2.2.dev)-----> Creating <default-centos65>... EC2 instance <i-5b6f2b70> created............ (server ready) Waiting for ec2-54-197-34-184.compute-1.amazonaws.com:22... Waiting for ec2-54-197-34-184.compute-1.amazonaws.com:22... Waiting for ec2-54-197-34-184.compute-1.amazonaws.com:22... Waiting for ec2-54-197-34-184.compute-1.amazonaws.com:22... (ssh ready)\n Finished creating <default-centos65> (3m2.97s).-----> Kitchen is finished. (3m3.40s)
NOTE:
You may be prompted to opt in and accept the terms and subscribe to using the AWS Marketplace CentOS image the first time you spin up an image. The kitchen-ec2
driver will provide you with a link to the opt in URL.
NOTE:
You might not be able to create CentOS images in all availability zones. The kitchen-ec2
driver will advice you of your availability zone options if there is an issue with your availability zone choice.
Install Chef Client with kitchen setup
. kitchen destroy
will delete your EC2 instance.
Refer to the kitchen-ec2
driver documentation on https://github.com/test-kitchen/kitchen-ec2 for more information additional .kitchen.yml
settings.
Google Compute Engine Cloud Provider (kitchen-gce)
kitchen-gce Setup
Create a Google Compute Engine project in the Google Developers Console at https://console.developers.google.com. Create a Service Account Key by navigating to APIs & auth > Credentials. Under OAuth start the process by clicking on the CREATE NEW CLIENT ID button as shown here:
On the Create Client ID dialog, choose Service account then click on Create Client ID as shown below. This will generate a private key file along with a password. Record this information, as it is the only time it will be displayed.
Make note of the Email address field for the Service Account (not to be confused with the project owner’s Email Address at the top of the page) as shown in the following. You’ll be recording this in the google_client_email
field in the .kitchen.yml
.
If you do not already have an SSH key pair to login, create them using ssh-keygen
or an equivalent tool. Register the public key in the Google Developer Console. The default file name for a public key is $HOME/.ssh/id_rsa.pub
. Navigate to Compute > Compute Engine > Metadata on the Google Developers Console. Make sure the SSH_keys is selected in the panel on the right, then click on the Add SSH key button as shown in the following:
Copy the public key id_rsa.pub
file contents to the clipboard and paste it into the Enter entire key data field. Click on the Done button to save.
Run the following kitchen init
command to add Test Kitchen support to your project using the kitchen-gce
driver:
$ kitchen init --driver=kitchen-gce --create-gemfile create .kitchen.yml create test/integration/default create Gemfile append Gemfile append GemfileYou must run `bundle install' to fetch any new gems.
Run bundle install
to fetch any new gems.
kitchen-gce .kitchen.yml Example
Since the project, client e-mail and key location are sensitive information and differ between users, it is recommended that you store them in environment variables instead of directly in your .kitchen.yml
file. This way, you can share your .kitchen.yml
file with others and store it in source control. You can use an embedded Ruby template in a .kitchen.yml
file to load values from the environment. Here is an example kitchen.yml
which spins up a CentOS 6.5 sandbox environment, loading the project and client e-mail from corresponding environment variables:
Before running any Test Kitchen commands, make sure you set the appropriate environment variables as shown below (with your own values):
Linux and Mac OS X:
export GOOGLE_PROJECT="alpha-bravo-123"export GOOGLE_CLIENT_EMAIL="123456789012@developer.gserviceaccount.com"export GOOGLE_KEY_LOCATION="$HOME/gce/1234567890abcdef1234567890abcdef12345678-privatekey.p12"
Windows Command Prompt:
set GOOGLE_PROJECT=alpha-bravo-123set GOOGLE_CLIENT_EMAIL=123456789012@developer.gserviceaccount.comset GOOGLE_KEY_LOCATION=%USERPROFILE%/gce/1234567890abcdef1234567890abcdef12345678-privatekey.p12
Windows Powershell:
$env:GOOGLE_PROJECT="alpha-bravo-123"$env:GOOGLE_CLIENT_EMAIL="123456789012@developer.gserviceaccount.com"$env:GOOGLE_KEY_LOCATION="$env:userprofile/gce/1234567890abcdef1234567890abcdef12345678-privatekey.p12"
The output of kitchen list
should resemble the following:
$ kitchen listInstance Driver Provisioner Last Actiondefault-centos65 Gce ChefSolo <Not Created>
Spin up the node with kitchen create
:
$ kitchen create default-centos65-----> Starting Kitchen (v1.2.2.dev)-----> Creating <default-centos65>... GCE instance <default-centos65-31681aab-e6a2-494b-99cb-9b920a1f6284> created... (server ready) (ssh ready) Finished creating <default-centos65> (1m26.70s).-----> Kitchen is finished. (1m28.18s)
Install Chef Client with kitchen setup
. kitchen destroy
will delete your Google Compute Engine instance.
Refer to the kitchen-gce
driver documentation on https://github.com/anl/kitchen-gce for more information on additional .kitchen.yml
settings.
Rackspace Cloud Provider (kitchen-rackspace)
kitchen-rackspace Setup
Login to the Cloud Sites Control Panel at https://manage.rackspacecloud.com/pages/Login.jsp Navigate to Your Account > API Access to display your username and API key as shown in below:
Run the following kitchen init
command to add Test Kitchen support to your project using the kitchen-rackspace
driver:
$ kitchen init --driver=kitchen-rackspace --create-gemfile create .kitchen.yml create test/integration/default create Gemfile append Gemfile append GemfileYou must run `bundle install' to fetch any new gems.
Run bundle install
to fetch any new gems.
kitchen-rackspace .kitchen.yml Example
Since the username and API Key are sensitive information and differ between users, it is recommended that you store them in environment variables instead of directly in your .kitchen.yml
file. This way, you can share your .kitchen.yml
file with others and store it in source control. You can use an embedded Ruby template in a .kitchen.yml
file to load values from the environment. Here is an example kitchen.yml
which spins up a CentOS 6.5 sandbox environment, loading the project and client e-mail from corresponding environment variables:
Before running any Test Kitchen commands, make sure you set the appropriate environment variables as shown below (with your own values):
Linux and Mac OS X:
export RACKSPACE_USERNAME="alice"export RACKSPACE_API_KEY="abcdef0123456789abcdef0123456789"export RACKSPACE_PUBLIC_KEY_PATH="$HOME/.ssh/id_rsa.pub"
Windows Command Prompt:
set RACKSPACE_USERNAME=aliceset RACKSPACE_API_KEY=abcdef0123456789abcdef0123456789set RACKSPACE_PUBLIC_KEY_PATH=%USERPROFILE%/.ssh/id_rsa.pub
Windows Powershell:
$env:RACKSPACE_USERNAME="alice"$env:RACKSPACE_API_KEY="abcdef0123456789abcdef0123456789"$env:RACKSPACE_PUBLIC_KEY_PATH="$env:userprofile/.ssh/id_rsa.pub"
The output of kitchen list
should resemble the following:
$ kitchen listInstance Driver Provisioner Last Actiondefault-centos65 Rackspace ChefSolo <Not Created>
Spin up the node with kitchen create
:
$ kitchen create default-centos65-----> Starting Kitchen (v1.2.2.dev)-----> Creating <default-centos65>... Rackspace instance <9456b985-3a41-4cb0-a3cf-7536cc15baf7> created. (server ready) (ssh ready) Finished creating <default-centos65> (0m37.77s).-----> Kitchen is finished. (0m38.21s)
Then install Chef Client with kitchen setup
. kitchen destroy
will delete your instance on Rackspace.
Refer to the kitchen-gce
driver documentation on https://github.com/test-kitchen/kitchen-rackspace for more information on additional .kitchen.yml
settings.
Linux Container Drivers
You can regard Linux Containers to be a resource-efficient variant of virtual machines. As shown in the following diagram, Linux containers trade off the flexibility (and overhead) of being able to run different operating systems in each guest to minimize resource consumption by having all guests share the same OS kernel. In container environments, guests are isolated like virtual machines using more lightweight mechanisms around Linux processes instead.
This idea has its origins in attempts to provide better process isolation to chroot jails. chroot is a Unix command that facilitates creating a separate virtualized copy of the operating system by changing the apparent root directory (/) to processes running within this copy of the operating system. Other variants of Unix have added extensions to this chroot mechanism to provide better isolation of the guest process, such as FreeBSD jails and Solaris Containers. Linux Containers bring this process-based isolation mechanism to the standard Linux kernel via a recently added kernel feature called control groups.
As of this writing, there are no container-like Test Kitchen drivers for Windows. Microsoft is working on adding similar lightweight virtualization technology to Windows via its Drawbridge virtalization technology[http://research.microsoft.com/en-us/projects/drawbridge/]. The only equivalent to Linux Containers in Windows at this moment is Microsoft Applications Virtualization (App-V), which has been around for quite some time, but it has a major drawback in requiring modification of target applications in order to work with the system, so it is not widely used.
The following diagram shows the steps in the sandbox environment creation process for containers. It is identical to the host-based model presented previously, just using lightweight, isolated container processes instead of full-blown virtual machines.
Test Kitchen invokes the container driver (kitchen-docker
or kitchen-lxc
) to create a container instance. The Test Kitchen driver uses the operating system APIs for Linux Containers to create a new instance for our sandbox environment. Once the sandbox environment is running, Test Kitchen links the instance for communication.As of this writing, Test Kitchen drivers for Linux Containers do not support functionality equivalent to synchronized folders. All Test Kitchen commands use scp
to transfer files from your host to the container instance. For any other file sharing beyond what is supported by Test Kitchen, you’ll need to make direct use of the file sharing mechanisms provided by the container driver being used. This is where Docker shines, as it supports data volume containers which bypass container image layering. Data volume containers are an ideal way to share data between containers. It is also possible to mount host directories in a container, but that has more limited use cases. Refer to the documentation on your container provider for more information.
You can combine together virtual machines with Linux containers to use containers on platforms that do not have native container support, like Mac OS X and Windows. The following diagram presents an overview of the setup. With virtual machines, it is usually not possible to nest virtualization software instances. Running virtualization software inside guest OS instances is either prohibited or painfully slow. However, it’s perfectly fine to run Linux Containers within a virtual machine. To the outer virtualization software, the container instances are merely Linux processes.
In the next section on Docker, we’ll show you how to use this technique for readers running Mac OS X or Windows. Neither platform supports Linux containers natively on the host. Chef Software uses a Docker-based VM in training classes, so that students with laptops running Mac OS X or Windows can use the same setup as the students using Linux. This approach also saves money, as Chef Software uses cloud providers for training, and these providers charge based the number of instances and resources used. The lightweight Docker instances consume fewer resources and only require one running instance on the cloud provider - all the other instances are just lightweight container instances, which cloud providers (currently) do not charge extra. You may want to consider using Linux Containers in a similar fashion to save money if you make heavy use of third-party virtualization or cloud providers, like we do.
Docker Driver (kitchen-docker)
If you are using Linux, refer to the Docker installation guide for instructions on how to install and configure Docker in your environment: http://www.docker.com/.
Chef Training Environment Setup
Skip ahead to the next secion if you are using Linux and already have Docker installed. Otherwise, you’ll need to spin up a virtual machine with Docker installed in order to play around with a container environment.
We’ve created a Chef training environment that has Docker and the Chef Development Kit used in this book preinstalled on a Linux virtual machine. We use this same instance in official Chef training. It’s also a handy environment for playing around with containers using Test Kitchen.
First, make sure you install Vagrant and VirtualBox or Vagrant and VMware.
Create a directory for the Chef training environment project called chef
and make it the current directory.
$ mkdir chef$ cd chef
Add Test Kitchen support to the project using the default kitchen-vagrant
driver by running kitchen init
. Then run bundle install
to install the necessary gems for the Test Kitchen driver.
$ kitchen init --create-gemfile create .kitchen.yml create test/integration/default create Gemfile append Gemfile append GemfileYou must run `bundle install' to fetch any new gems.$ bundle installFetching gem metadata from https://rubygems.org/..........Fetching additional metadata from https://rubygems.org/..Resolving dependencies...Using mixlib-shellout (1.4.0)Using net-ssh (2.9.1)Using net-scp (1.2.1)Using safe_yaml (1.0.3)Using thor (0.19.1)Using test-kitchen (1.2.1)Using kitchen-vagrant (0.15.0)Using bundler (1.5.2)Your bundle is complete!Use `bundle show [gemname]` to see where a bundled gem is installed.
Modify the .kitchen.yml
file to use the Chef training image as shown in the following .kitchen.yml
:
Run kitchen create
to spin up the image:
$ kitchen create-----> Starting Kitchen (v1.2.2.dev)-----> Creating <default-learningchef>... Bringing machine 'default' up with 'virtualbox' provider... ==> default: Importing base box 'learningchef/chefdk-box'... ==> default: Matching MAC address for NAT networking... ==> default: Checking if box 'learningchef/chefdk-box' is up to date... ==> default: Setting the name of the VM: default-learningchef_default_1404728110875_23069 ==> default: Fixed port collision for 22 => 2222. Now on port 2200. ==> default: Clearing any previously set network interfaces... ==> default: Preparing network interfaces based on configuration... default: Adapter 1: nat ==> default: Forwarding ports... default: 22 => 2200 (adapter 1) ==> default: Booting VM... ==> default: Waiting for machine to boot. This may take a few minutes... default: SSH address: 127.0.0.1:2200 default: SSH username: vagrant default: SSH auth method: private key default: Warning: Remote connection disconnect. Retrying... ==> default: Machine booted and ready! ==> default: Checking for guest additions in VM... ==> default: Setting hostname... ==> default: Machine not provisioning because `--no-provision` is specified. Vagrant instance <default-learningchef> created. Finished creating <default-learningchef> (0m36.99s).-----> Kitchen is finished. (0m37.44s)
Then run kitchen login
to use Docker! Note that the image also has the latest Chef Development Kit installed (as of this writing). You will be running the Test Kitchen Docker driver inside this virtual machine. It has been pre-populated with all the necessary files to spin up the CentOS 6.5 images used in the exercises for this book:
$ kitchen loginWelcome to Ubuntu 14.04 LTS (GNU/Linux 3.13.0-24-generic x86_64) * Documentation: https://help.ubuntu.com/Welcome to the Learning Chef training environmentLast login: Fri May 23 13:49:31 2014 from 10.0.2.2vagrant@default-learningchef:~$ docker --versionDocker version 0.11.1, build fb99f99vagrant@default-learningchef:~$ kitchen --versionTest Kitchen version 1.2.2.devvagrant@default-learningchef:~$
NOTE:
Sharp-eyed readers might notice that this is an Ubuntu image. It is perfectly OK to spin up CentOS images on Ubuntu, as long as you use a version that shares the same kernel!
TIP:
At first, the multiple layers of instances might be a little confusing. Refer back to the Docker diagram shown previously so that you can keep the big picture of this setup in mind. Also, modifying the command prompts so they clearly indicate which environment is the VM and which environment is a container instance is strongly recommended.
kitchen-docker Setup
Run the following kitchen init
command to add Test Kitchen support to your project using the kitchen-docker
driver:
$ kitchen init --driver=kitchen-docker --create-gemfile create .kitchen.yml create test/integration/default create Gemfile append Gemfile append GemfileYou must run `bundle install' to fetch any new gems.
Run bundle install
to download and install any required gems.
kitchen-docker .kitchen.yml Example
The following .kitchen.yml
presents an example which spins up a CentOS 6.5 sandbox environment:
The output of kitchen list
should resemble the following:
$ kitchen listInstance Driver Provisioner Last Actiondefault-centos65 Docker ChefSolo <Not Created>
Spin up the node with kitchen create
:
$ kitchen create-----> Starting Kitchen (v1.2.2.dev)-----> Creating <default-centos65>... Step 0 : FROM centos:latest Pulling repository centos ---> 0c752394b855... Waiting for localhost:49153... Waiting for localhost:49153... Finished creating <default-centos65> (1m19.28s).-----> Kitchen is finished. (1m19.34s)
At the time of this writing, due to some issues with kitchen-docker
, you may be prompted for kitchen@localhost's password
. The password is kitchen
$ kitchen loginkitchen@localhost's password: kitchenLast login: Mon Jul 7 11:37:14 2014 from 172.17.42.1[kitchen@55f29336b435 ~]$ cat /etc/redhat-releaseCentOS release 6.5 (Final)[kitchen@55f29336b435 ~]$ exitlogoutConnection to localhost closed.
Install Chef Client with kitchen setup
. kitchen destroy
will delete container instance.
Refer to the kitchen-docker
driver documentation on https://github.com/portertech/kitchen-docker for more information on additional .kitchen.yml
settings.
Physical Machine Drivers
As of this writing, Test Kitchen does not currently support chef-metal
. It is currently planned to provide robust support for managing sandbox environments running on physical machines using chef-metal
(though plans sometimes change).
Until Test Kitchen supports chef-metal
, the only way to use Test Kitchen with physical machines currently (other than your local host) is to use the kitchen-ssh
driver. This is actually a generic way to integrate any kind of machine with Test Kitchen, not just physical machines. As long as the machine accepts ssh
connections, it will work.
The following diagram shows an overview of the Test Kitchen instance creation process using kitchen-ssh
. It is similar to the creation process used for cloud instances with the Test Kitchen environment being run on a remote machine, but there is only one step because an isolated sandbox instance is not created. The kitchen-ssh
driver merely links up an SSH communication channel with Test Kitchen in the remote machine’s host environment.
It is assumed that you are using some other method outside of Test Kitchen to be able to easily reset the environment. Also, since it does not spin up a new instance, you will need to make sure the machine that you are linking to has CentOS 6 installed to match the exercises in this book.
Driver for any server with an SSH address (kitchen-ssh)
Run the following kitchen init
command to add Test Kitchen support to your project using the kitchen-ssh
driver:
$ kitchen init --driver=kitchen-ssh --create-gemfile create .kitchen.yml create test/integration/default create Gemfile append Gemfile append GemfileYou must run `bundle install' to fetch any new gems.
Run bundle install
to fetch any required gems.
kitchen-ssh .kitchen.yml Example
The following .kitchen.yml
assumes that you are connecting to an existing CentOS 6.5 environment with an SSH server running. Change the hostname:
, username:
and password:
fields accordingly to match your remote machine’s settings:
The output of kitchen list
should resemble the following:
Instance Driver Provisioner Last Actiondefault-centos65 Ssh ChefSolo Created
Initiate a connection to the node with kitchen create
. You could also run kitchen login
without needing to run kitchen create
in this case, as kitchen create
does nothing:
$ kitchen create-----> Starting Kitchen (v1.2.2.dev)-----> Creating <default-centos65>... Kitchen-ssh does not start your server '192.168.33.33' but will look for an ssh connection with user 'alice'--- Kitchen-ssh found ssh ready on host '192.168.33.33' with user 'alice' Finished creating <default-centos65> (0m0.01s).-----> Kitchen is finished. (0m0.02s)
Install Chef Client with kitchen setup
. For this driver, kitchen destroy
does nothing, just like kitchen create
, besides updating the status in Test Kitchen.
Refer to the kitchen-ssh
driver documentation on https://github.com/neillturner/kitchen-ssh/blob/master/lib/kitchen/driver/ssh.rb for more information on additional .kitchen.yml
settings.
Set Up a Sane Ruby Cookbook Authoring Environment for Chef on Mac OS X, Linux and Windows
subl
command line launch link - Mac OS X Install Sublime Text 3 Package Control (Optional) - Mac OS X Install Sublime Chef (Optional) - Mac OS X Linux Install Prerequisite Packages - Linux Ubuntu prerequisites: RHEL/CentOS prerequisites: Install Chruby and Ruby-Build - Linux Compile Ruby 1.9.x from source - Linux Install Bundler - Linux Install Sublime Text 3 (Optional) - Linux subl
command line launch link - Linux Install Sublime Text 3 Package Control (Optional) - Linux Install Sublime Chef (Optional) - Linux Windows Install Ruby 1.9.x - Windows Install Ruby DevKit - Windows Enhance Rubies to use the DevKit - Windows Install Bundler - Windows Install Git - Windows Install Sublime Text 3 (Optional) - Windows Install Sublime Text 3 Package Control (Optional) - Windows Install Sublime Chef (Optional) - Windows Updated January 3, 2014
Added instructions to createsubl
launching commandletUpdated January 2, 2014
Per Seth Vargo switched from rbenv to chruby Switched from SublimeText 2 to SublimeText 3 - it works with SublimeChefYou will need to set up a sane Ruby 1.9.x development to support yourChef cookbook authoring activity on Mac OS X, Linux or Windows. In thisRuby environment, you will manage all the required Ruby Gem librariesnecessary to support Chef cookbook authoring. TheLearnChefsite recommends that you piggyback the Chef client’s omnibus Rubyenvironment to start learning how to write Chef cookbooks. Thisarticle assumes that you want to go beyond the basics, where you’ll needa Ruby environment dedicated for Chef cookbook development.
There are many different ways to set up a sane Ruby environment. Thisarticle covers how to set up a sane Ruby environment for Chef usingChruby for Mac OS X/Linux andRubyInstaller for Windows. The setupcovered in this article should work for most people wanting to writeChef cookbooks. If you are more experienced with Ruby development, youmay want to roll your own Ruby environment in another fashion. The onlyrequirement is that Ruby 1.9.x must be used, the Chef client currentlydoes not support Ruby 2.x.
Mac OS X
Out of the box, Ruby does not provide a mechanism to support multipleinstalled versions. Chrubymakes it easy to manage multiple versions of Ruby. It’s a great way to set upa dedicated Ruby 1.9.x environment with all the required Gem libraries forChef cookbook development.
NOTE: Before trying to installChrubyverify that you do not have another popular Ruby virtualization managerinstalled - RVM. If you try to run the following rvm
command, it should say command not found
:
$ rvm --version-bash: rvm: command not found
If you want to switch to Chruby (which is recommended), make sure that youcompletely remove RVM first(as Chruby and RVM cannot coexist because RVM overrides the gem
command witha function specific to RVM).
Install the Xcode Command Line Tools - Mac OS X
First you’ll need to install a C compiler and the Xcode Command Line toolsto build Ruby from source. If you are using the latest version of Mac OS XMavericks 10.9, it has support for downloading the Xcode command line toolsdirectly from a Terminal window. Run the following on a command line:
$ xcode-select --install
You will be prompted to either click on Install
to just install the commandline developer tools or click on Get Xcode
to install both Xcode and thecommand line developer tools. It can be handy to have Xcode as well, butit is a rather large multi-gigabyte download and not really necessary forRuby development. So if you want to get going quickly, just click on theInstall
button:
If xcode-select
installed the Xcode Command Line Tools, you should havegit
installed (among other things). Verify this with the followingcommand:
$ git --versiongit version 1.8.3.4 (Apple Git-47)
Install the Homebrew Package Manager - Mac OS X
Next, you’ll need to install the Homebrew package managerto get all the dependencies needed to compile Ruby from source. While youcould manage these dependencies by hand, using a package manager is a betteridea, as package managers know how to uninstall what they install.
First verify that you DO NOT currently have homebrew installed.brew --version
should report command not found
.
$ brew --version-bash: brew: command not found
If you already have Homebrew installed, justUpdate Homebrew and Rbenvand skip to the next section.
NOTE: Before trying to install Homebrew verify thatyou do not have another popular package manager installed - MacPorts.If you try to run the following port
command, it should saycommand not found
:
$ port --version-bash: port: command not found
If MacPorts is already installed, make sure that youcompletely remove MacPorts from your systembefore trying to install Homebrew.
Run the following command to install Homebrew:
$ ruby -e "$(curl -fsSL https://raw.github.com/Homebrew/homebrew/go/install)"
Run brew doctor
and address any issues it discovers. Whenall is well, you should see:
$ brew doctorYour system is raring to brew.
Install Apple GCC 4.2 - Mac OS X
Next, install the additional dependencies to compile Ruby from source:
# For update-systembrew update# Add the system duplicate formulaebrew tap homebrew/dupes# Install legacy C compiler for building Rubybrew install apple-gcc42
Install Chruby and Ruby-Build via Homebrew - Mac OS X
Now install chruby
and ruby-install
via Homebrew:
$ brew update$ brew install chruby$ brew install ruby-build
Add chruby.sh
to your shell to enable chruby:
$ echo 'source /usr/local/share/chruby/chruby.sh' >> $HOME/.bash_profile
Add auto.sh
to your shell to enble auto-switching of Rubies specified by`.ruby-version files:
$ echo 'source /usr/local/share/chruby/auto.sh' >> $HOME/.bash_profile
Compile Ruby 1.9.x from source - Mac OS X
Install the latest version of ruby 1.9.x (at the time of this writing 1.9.3-p484)
$ ruby-build 1.9.3-p484 --install-dir ~/.rubies/ruby-1.9.3-p484
Reload .bashrc
with these new settings:
$ source $HOME/.bash_profile
To switch to the Ruby required for Chef:
$ chruby ruby-1.9
To make this version the default version of Ruby, simply add this commandto your $HOME/.bash_profile
$ echo 'chruby ruby-1.9' >> $HOME/.bash_profile
Verify the ruby install. If everything was installed correctly, the ruby -v
command should report that version 1.9.3p484 is installed.
$ ruby -vruby 1.9.3p484 (2013-11-22 revision 43786) [x86_64-darwin13.0.0]
Install Bundler - Mac OS X
You’ll need to use Bundler to manage gems. Installinga gem is also a good way to ensure that you’ve installed most of the Rubyprerequisites.
First, make sure you update to the latest version of Rubygems:
$ gem update --systemUpdating rubygems-updateFetching: rubygems-update-2.2.0.gem (100%)Successfully installed rubygems-update-2.2.0Installing RubyGems 2.2.0RubyGems 2.2.0 installed...
Then install the bundler
gem. If the gem install
command reportsSuccessfully installed
you’re good to go:
$ gem install bundlerSuccessfully installed bundler-1.5.1Parsing documentation for bundler-1.5.11 gem installed
Install Sublime Text 3 (Optional) - Mac OS X
Miguel Cabeça has written an excellent plugin for the Sublime Text editorcalled SublimeChef, which is theclosest thing to an Integrated Development Environment (IDE) that existsfor Chef. Sublime Text costs $70 for a license, but has no restrictionon the length of a trial period, so feel free try out Sublime Text to seeif it works for you.
Download and install SublimeText 3 for your platform viahttp://www.sublimetext.com/3
Create subl
command line launch link - Mac OS X
It is very handy to be able to launch Sublime Text from the command lineas you’ll find yourself going back and forth between the two in developingyour cookbooks. Create a short-named link to the Sublime Text executablewith the following commands:
$ sudo mkdir -p /usr/local/bin$ sudo chown -R $(whoami) /usr/local/bin$ ln -s /Applications/Sublime\ Text.app/Contents/SharedSupport/bin/subl /usr/local/bin/subl
Since /usr/local/bin
should already bin your path, typing in the following command should launch Sublime Text:
$ subl
You can pass in a filename parameter as well, such as:
$ subl default.rb
Install Sublime Text 3 Package Control (Optional) - Mac OS X
In order to install the SublimeChef plugin, first you need to installSublime Text Package Control.
Download Package Control.sublime-package
Choose Preferences > Browse Packages...
from the Sublime Text 3 menu
Browse up a folder, then navigate into Installed Packages/
Copy Package Control.sublime-package
file you downloaded into thisSublime Text 3\Installed Packages
directory
Restart Sublime Text 3 to enable Package Control
Once Package Control is installed successfully, you should be able todisplay the Command Palette by pressing COMMAND+SHIFT+P
:
Install Sublime Chef (Optional) - Mac OS X
After pressing CTRL+SHIFT+P
to display the Command Palette, start typinginstall
to select Package Control: Install Package
:
Then type chef
to display the SublimeChef entry - click to install:
Miguel created the followingdemo videoto show how SublimeChef can be used.
Linux
Install Prerequisite Packages - Linux
Make sure the prerequisite packages are installed.
Ubuntu prerequisites:
$ sudo apt-get update$ sudo apt-get install -y build-essential git$ sudo apt-get install -y libxml2-dev libxslt-dev libssl-dev
RHEL/CentOS prerequisites:
$ sudo yum update$ sudo yum install -y git$ sudo yum install -y gcc-c++ patch readline readline-devel zlib zlib-devel$ sudo yum install -y libyaml-devel libffi-devel openssl-devel make bzip2$ sudo yum install -y autoconf automake libtool bison$ sudo yum install -y libxml2-devel libxslt-devel
Install Chruby and Ruby-Build - Linux
Download the chruby source distribution:
$ wget -O chruby-0.3.8.tar.gz https://github.com/postmodern/chruby/archive/v0.3.8.tar.gz
Extract chruby and install:
$ tar xzvf chruby-0.3.8.tar.gz$ cd chruby-0.3.8/$ sudo make install
Feel free to remove the chruby source dir after installing:
$ cd ..$ rm chruby-0.3.8.tar.gz$ rm -rf chruby-0.3.8
Install ruby-build:
$ git clone https://github.com/sstephenson/ruby-build.git$ cd ruby-build$ sudo ./install.sh
Feel free to remove the ruby-build source dir after installing:
$ cd ..$ rm -rf ruby-build
Add chruby.sh
to your shell to enable chruby:
$ echo 'source /usr/local/share/chruby/chruby.sh' >> $HOME/.bashrc
Add auto.sh
to your shell to enble auto-switching of Rubies specified by`.ruby-version files:
$ echo 'source /usr/local/share/chruby/auto.sh' >> $HOME/.bashrc
Compile Ruby 1.9.x from source - Linux
Install the latest version of ruby 1.9.x (at the time of this writing 1.9.3-p484)
$ ruby-build 1.9.3-p484 --install-dir ~/.rubies/ruby-1.9.3-p484
Reload .bashrc
with these new settings:
$ source $HOME/.bashrc
To switch to the Ruby required for Chef:
$ chruby ruby-1.9
To make this version the default version of Ruby, simply add this commandto your $HOME/.bashrc
$ echo 'chruby ruby-1.9' >> $HOME/.bashrc
Verify the ruby install. If everything was installed correctly, the ruby -v
command should report that version 1.9.3p484 is installed.
$ ruby -vruby 1.9.3p484 (2013-11-22 revision 43786) [x86_64-darwin13.0.0]
Install Bundler - Linux
You’ll need to use Bundler to manage gems.Installing a gem is also a good way to ensure that you’ve installed mostof the Ruby prerequisites.
First, make sure you update to the latest version of Rubygems:
$ gem update --systemUpdating rubygems-updateFetching: rubygems-update-2.2.0.gem (100%)Successfully installed rubygems-update-2.2.0Installing RubyGems 2.2.0RubyGems 2.2.0 installed...
Then install the bundler
gem. If the gem install
command reportsSuccessfully installed
you’re good to go:
$ gem install bundlerSuccessfully installed bundler-1.5.0Parsing documentation for bundler-1.5.01 gem installed
Install Sublime Text 3 (Optional) - Linux
Miguel Cabeça has written an excellent plugin for the Sublime Text editorcalled SublimeChef, which is theclosest thing to an Integrated Development Environment (IDE) that existsfor Chef. Sublime Text costs $70 for a license, but has no restrictionon the length of a trial period, so feel free try out Sublime Text to seeif it works for you.
Download and install SublimeText 3 for your platform viahttp://www.sublimetext.com/3
subl
command line launch link - Linux
Unlike with Mac OS X, the Linux installer should have created acommand line launch link for Sublime Text in /usr/bin/subl
.Typing in the following command should launch Sublime Text:
$ subl
You can pass in a filename parameter as well, such as:
$ subl default.rb
Install Sublime Text 3 Package Control (Optional) - Linux
In order to install the SublimeChef plugin, first you need to installSublime Text Package Control.
Download Package Control.sublime-package
Choose Preferences > Browse Packages...
from the Sublime Text 3 menu
Browse up a folder, then navigate into Installed Packages/
Copy Package Control.sublime-package
file you downloaded into thisSublime Text 3/Installed Packages
directory
Restart Sublime Text 3 to enable Package Control
Once Package Control is installed successfully, you should be able todisplay the Command Pallete by pressing CTRL+SHIFT+P
:
Install Sublime Chef (Optional) - Linux
After pressing CTRL+SHIFT+P
to display the Command Pallette, start typinginstall
to select Package Control: Install Package
:
Then type chef
to display the SublimeChef entry - click to install:
Miguel created the followingdemo videoto show how SublimeChef can be used.
Windows
There is no need to install a Ruby version manager on Windows, like thereis for Mac OS X or Linux. In fact, the chruby version manager does notwork on Windows. Instead, you’ll use the RubyInstaller for Windows whichcan install different versions of Ruby on the same machine.
Install Ruby 1.9.x - Windows
Download and install the latest Windows RubyInstaller for Ruby 1.9.x fromhttp://rubyinstaller.org/downloads(version 1.9.3-p484 as of this writing):
Verify that Ruby was installed correctly by running the following from aCommand Prompt:
> ruby -vruby 1.9.3p484 (2013-11-22) [i386-mingw32]
Install Ruby DevKit - Windows
Download and install the Ruby Development Kit for use with Ruby 1.8.7 and1.9.3.
Extract the archive to C:\Ruby\DevKit
:
Enhance Rubies to use the DevKit - Windows
Run dk.rb init
to generate a config.yml
which includes all the installedRubies to be enhanced to use the DevKit:
> cd /d c:\Ruby\DevKit> ruby dk.rb init
If you want to review the list of Rubies before installing, rundk.rb review
:
> cd /d c:\Ruby\DevKit> ruby dk.rb review
Then run dk.rb
to DevKit enhance your installed Rubies:
> cd /d c:\Ruby\DevKit> ruby dk.rb install
Finally run devkitvars
to add the DevKit tools to your command shell’sPATH and try to get the version of gcc
to verify that the toolsinstalled properly:
> c:\Ruby\DevKit\devkitvars.batAdding the DevKit to PATH...> gcc --versiongcc (tdm-1) 4.5.2Copyright (C) 2010 Free Software Foundation, Inc.This is free software; see the source for copying conditions. There is NOwarranty; not even for MERCHANTABILITY or FITNESS OR A PARTICULAR PURPOSE.
Install Bundler - Windows
You’ll need to use Bundler to manage gems. Installinga gem is also a good way to ensure that you’ve installed most of the Rubyprerequisites.
First, make sure you update to the latest version of Rubygems:
> c:\Ruby\DevKit\devkitvars.batAdding the DevKit to Path...> gem update --systemFetching: rubygems-update-2.2.0.gem (100%)Successfully installed ruygems-update-2.2.0Installing RubyGems 2.2.0RubyGems 2.2.0 installed...
Then install the bundler
gem. If the gem install
command reportsSuccessfully installed
you’re good to go:
> gem install bundlerSuccessfully installed bundler-1.5.0Parsing documentation for bundler-1.5.01 gem installed
Install Git - Windows
While using source control is a recommended best practice, Chef does notrequire Git. If you use some other source control system besides Git,feel free to install it instead of Git. Use of Git source control justhappens to be more common than others with Chef.
Download the latest stable release of the Git for Windows install fromhttp://git-scm.com/downloads
Run the Git Windows install accepting the default choices, except on thePATH setup dialog. You’ll need to include the Unix tools on your Windowscommand prompt for some Chef commands to work:
Verify that Git installed correcting by running the following on a commandprompt:
> git --versiongit version 1.8.4.msysgit.0
Install Sublime Text 3 (Optional) - Windows
Miguel Cabeça has written an excellent plugin for the Sublime Text editorcalled SublimeChef, which is theclosest thing to an Integrated Development Environment (IDE) that existsfor Chef. Sublime Text costs $70 for a license, but has no restrictionon the length of a trial period, so feel free try out Sublime Text to seeif it works for you.
Download and install SublimeText 3 for your platform viahttp://www.sublimetext.com/3
Install Sublime Text 3 Package Control (Optional) - Windows
In order to install the SublimeChef plugin, first you need to installSublime Text Package Control.
Download Package Control.sublime-package
Choose Preferences > Browse Packages...
from the Sublime Text 3 menu
Browse up a folder, then navigate into Installed Packages/
Copy Package Control.sublime-package
file you downloaded into thisSublime Text 3\Installed Packages
directory
Restart Sublime Text 3 to enable Package Control
Once Package Control is installed successfully, you should be able todisplay the Command Pallete by pressing CTRL+SHIFT+P
:
Install Sublime Chef (Optional) - Windows
After pressing CTRL+SHIFT+P
to display the Command Pallette, start typinginstall
to select Package Control: Install Package
:
Then type chef
to display the SublimeChef entry - click to install:
Miguel created the followingdemo videoto show how SublimeChef can be used.
Getting Started Writing Chef Cookbooks the Berkshelf Way, Part 3
Update January 7, 2014* Note about Michel Goetz’s blog series on ChefSpec
Updated December 29, 2013
Bumped Test Kitchen from 1.0.0.beta.3 to 1.1.1 Bumped CentOS to version 6.5 Per Kelly Setzer, updated os check with recent RSpec updatesUpdated September 10, 2013
Bumped VirtualBox images from version 4.2.16 to 4.2.18 Bumped Vagrant from version 1.2.7 to 1.3.1Updated September 1, 2013
Bumped Test Kitchen from 1.0.0.beta.2 to 1.0.0.beta.3This is the third article in a series on writing Opscode Chef cookbooks theBerkshelf Way. Here’s a link to Part 1 andPart 2. The source code examples covered in thisarticle can be found on Github: https://github.com/misheska/myface
In this installment, we’re going to learn how to use Test Kitchen to automate all the verification steps we did by hand for each iteration inPart 1 andPart 2. If not anything else, it’s worth learningTest Kitchen because OpsCode, the company that makes Chef, has encouraged theuse of Test Kitchen to verify community cookbooks.
Test Kitchen is built on top of vagrant and supplements the Vagrantfile
fileyou have been using so far in this series to do local automated testing. Themain benefit to Test Kitchen is that it makes it easy to run tests on multipleplatforms in parallel, which is more difficult to do with just a Vagrantfile
.We’ll be showcasing this aspect of Test Kitchen by ensuring that Myface workson both the CentOS 6.4 and Ubuntu 12.04 Linux distributions.
Iteration #13 - Install Test Kitchen
Edit myface/Gemfile
and add the following lines to load theTest Kitchen gems:
gem 'test-kitchen'gem 'kitchen-vagrant'
Depending on when you went through this article series, your Gemfile
may already have these additions. After editing, your myface/Gemfile
should look like the following after editing:
After you have updated the Gemfile
run bundle install
to download thetest-kitchen gem and all its dependencies:
$ bundle installFetching gem metadata from https://rubygems.org/........Fetching gem metadata from https://rubygems.org/..Resolving dependencies...Using i18n (0.6.9)Using multi_json (1.8.2)Using activesupport (3.2.16)...Installing test-kitchen (1.1.1)Using bundler (1.5.1)Your bundle is complete!Use `bundle show [gemname]` to see where a bundled gem is installed.
Testing Iteration #13 - Show the Test Kitchen version
If everything worked properly you should be able to run the kitchen --version
command to see your installed Test Kitchen’s version information
$ kitchen --versionTest Kitchen version 1.1.1
Iteration #14 - Create a Kitchen YAML file
In order to use Test Kitchen on a cookbook, first you need to add a few moredependencies and create a template Kitchen YAML file. Test Kitchen makes thiseasy by providing the kitchen init
command to perform all theseinitialization steps automatically
$ kitchen init create .kitchen.yml append Thorfile create test/integration/default append .gitignore append .gitignore append Gemfile append GemfileYou must run 'bundle install' to fetch any new gems.
Since kitchen init
modified your Gemfile, you need to re-run bundle install
(as suggested above) to pick up the new gem dependencies:
$ bundle installFetching gem metadata from https://rubygems.org/........Fetching additional metadata from https://rubygems.org/..Resolving dependencies...Using i18n (0.6.9)Using multi_json (1.8.2)Using activesupport (3.2.16)...Using safe_yaml (0.9.7)Using test-kitchen (1.1.1)Installing kitchen-vagrant (0.14.0)Using bundler (1.5.1)Your bundle is complete!Use `bundle show [gemname]` to see where a bundled gem is installed.
Most importantly, this new bundle install
pass installed thekitchen-vagrant
vagrant driver for Test Kitchen.
Now that you have created a .kitchen.yml
Kitchen YAML file and loaded allthe necessary gems, let’s customize the file so that we’ll use to verify that the Myface cookbook works on CentOS 6.4, like we were doing inthe previous installments with the Vagrantfile
.
Everything in the YAML file should be straightforward to understand, exceptperhaps the attributes
item in the suites
stanza. These values came from the Vagrantfile
we used in the previous installments of thisseries. Here’s an excerpt from the Vagrantfile
- at the end are somevalues that Berkshelf initialzed (which we used inPart 2).
... config.vm.provision :chef_solo do |chef| chef.json = { :mysql => { :server_root_password => 'rootpass', :server_debian_password => 'debpass', :server_repl_password => 'replpass' } } chef.run_list = [ "recipe[myface::default]" ] endend
Those Vagrantfile
attributes were just converted into a format that theTest Kitchen YAML file format finds acceptable.
You can add even more Vagrantfile customizations to your kitchen.yml
fileif you like. For example, you can assign a host-only network IP so you canlook at the MyFace website with a browser on your host. Add the followingnetwork:
block to a platform’s driver_config:
:
...driver_config: network: - ["private_network", {ip: "33.33.33.10"}]...
After adding this block your .kitchen.yml
should look like this:
For more information on the kitchen-vagrant
settings, refer to theREADME.md file for kitchen-vagrant
at https://github.com/opscode/kitchen-vagrant/blob/master/README.md
Testing Iteration #14 - Provision with Test Kitchen
You can do nearly everything that you were doing with vagrant just using TestKitchen. The Test Kitchen equivalent of the vagrant up
command is kitchen converge
. Try running the kitchen converge
command now to verifythat your .kitchen.yml
file is valid. When you run kitchen converge
it willspin up a CentOS 6.5 vagrant test node instance and use Chef Solo to provisionthe MyFace cookbook on the test node:
$ kitchen converge -----> Starting Kitchen (v1.1.1)-----> Creating <default-centos65>... Bringing machine 'default' up with 'virtualbox' provider... [default] Importing base box 'centos65'... [default] Matching MAC address for NAT networking... [default] Setting the name of the VM... [default] Clearing any previously set forwarded ports... [Berkshelf] Skipping Berkshelf with --no-provision [default] Fixed port collision for 22 => 2222. Now on port 2200. [default] Clearing any previously set network interfaces... [default] Preparing network interfaces based on configuration... [default] Forwarding ports... [default] -- 22 => 2200 (adapter 1) [default] Running 'pre-boot' VM customizations... [default] Booting VM... [default] Waiting for machine to boot. This may take a few minutes... [default] Machine booted and ready! [default] Setting hostname... Vagrant instance <default-centos65> created. Finished creating <default-centos65> (0m51.76s).-----> Converging <default-centos65>... Preparing files for transfer Resolving cookbook dependencies with Berkshelf... Removing non-cookbook files before transfer-----> Installing Chef Omnibus (true) downloading https://www.opscode.com/chef/install.sh to file /tmp/install.sh trying wget... Downloading Chef for el... downloading https://www.opscode.com/chef/metadata?v=&prerelease=false&p=el&pv=6&m=x86_64 to file /tmp/install.sh.2158/metadata.txt trying wget... urlhttps://opscode-omnibus-packages.s3.amazonaws.com/el/6/x86_64/chef-11.8.2-1.el6.x86_64.rpm md510f3d0da82efa973fe91cc24a6a74549 sha256044558f38d25bbf75dbd5790ccce892a38e5e9f2a091ed55367ab914fbd1cfed downloaded metadata file looks valid... downloading https://opscode-omnibus-packages.s3.amazonaws.com/el/6/x86_64/chef-11.8.2-1.el6.x86_64.rpm to file /tmp/install.sh.2158/chef-.x86_64.rpm trying wget... Checksum compare with sha256sum succeeded. Installing Chef installing with rpm... warning: /tmp/install.sh.2158/chef-.x86_64.rpm: Header V4 DSA/SHA1 Signature, key ID 83ef826a: NOKEYPreparing... ##### ########################################### [100%] 1:chef ########################################### [100%] Thank you for installing Chef! Transfering files to <default-centos65> [2013-12-29T11:44:52-08:00] INFO: Forking chef instance to converge... Starting Chef Client, version 11.8.2 [2013-12-29T11:44:52-08:00] INFO: *** Chef 11.8.2 *** [2013-12-29T11:44:52-08:00] INFO: Chef-client pid: 2257 [2013-12-29T11:44:53-08:00] INFO: Setting the run_list to ["recipe[myface::default]"] from JSON [2013-12-29T11:44:53-08:00] INFO: Run List is [recipe[myface::default]] ... Recipe: apache2::default * service[apache2] action restart[2013-12-29T11:47:41-08:00] INFO: Processing service[apache2] action restart (apache2::default line 210) [2013-12-29T11:47:43-08:00] INFO: service[apache2] restarted - restart service service[apache2] [2013-12-29T11:47:43-08:00] INFO: Chef Run complete in 170.575449983 seconds [2013-12-29T11:47:43-08:00] INFO: Running report handlers [2013-12-29T11:47:43-08:00] INFO: Report handlers complete Chef Client finished, 100 resources updated Finished converging <default-centos65> (3m43.06s).-----> Kitchen is finished. (4m35.40s)
To display the results of the Chef Run, type in the kitchen list
command:
$ kitchen listInstance Driver Provisioner Last Actiondefault-centos65 Vagrant Chef Solo Converged
If the run succeeded, it should display Converged
in the Last Action
field.
The Test Kitchen equivalent of the vagrant ssh
command is kitchen login
.Since Test Kitchen supports multiple instances, you will need to pass inthe instance name for which you wish to login as a parameter (which you canget from the kitchen list
output). We want to login to the CentOS 6.5instance (the only instance for now), so type in the commandkitchen login default-centos65
to login:
$ kitchen login default-centos65Last login: Sun Dec 29 13:16:33 2013 from 10.0.2.2Welcome to your Packer-built virtual machine.[vagrant@default-centos65 ~]$
Now you can poke around in the image the same way you did with vagrant ssh
,for example, verifying that the httpd server is running:
[vagrant@default-centos65 ~]$ sudo /sbin/service httpd statushttpd (pid 4410) is running...
After you are done working in the test instance, make sure to run theexit
command to log out so that you return back to your host prompt:
[vagrant@default-centos65 ~]$ exitlogoutConnection to 127.0.0.1 closed.
Should you need it, the Test Kitchen equivalent of vagrant destroy
iskitchen destroy
. If you make a change to the chef cookbook andwant to re-deploy, the Test Kitchen equivalent of vagrant provision
iskitchen converge
.
Since you added a private IP for you instance, you can also view theMyFace website on your host with your favorite web browser:
http://33.33.33.10
Iteration #15 - Provisioning Ubuntu
We haven’t really made use of any unique Test Kitchen features yet, let’sstart now. We’ll also deploy our cookbook locally to Ubuntu 12.04 fortesting, in addition to CentOS 6.5.
Edit .kitchen.yml
and add a reference to a Ubuntu 12.04 basebox alongsidethe existing CentOS 6.5 basebox in the platforms
stanza:
- name: ubuntu1204 driver_config: box: ubuntu1204 box_url: https://s3-us-west-2.amazonaws.com/misheska/vagrant/virtualbox4.3.6/ubuntu1204.box network: - ["private_network", {ip: "33.33.33.11"}]
After editing, your .kitchen.yml
file should resemble the following:
Before we run kitchen converge
to do a Chef run, we need to fix our cookbookso it will run successfully on Ubuntu 12.04. If you tried to deploy now youwould notice that the MyFace cookbook would fail to deploy to Ubuntu 12.04successfully due to a reference to the php-mysql
package in myface/receipes/webserver.rb
.
... include_recipe 'apache2'include_recipe 'apache2::mod_php5'package 'php-mysql' do action :install notifies :restart, 'service[apache2]'end...
On Ubuntu the package name should be php5-mysql
instead of php-mysql
.
As with most issues in the Chef world, there’s a cookbook for that!The Opscode php
cookbook has conditionals to reference the correct namefor the php-mysql
package on a number of platforms.
Edit myface/metadata.rb
and add a reference to the latest version of thephp
cookbook (currently 1.3.10):
In myface/recipes/webserver.rb
replace the package "php-mysql" do ... end
block with the following reference:
include_recipe 'php::module_mysql'
After editing, myface/recipes/webserver.rb
should look like this:
Testing Iteration #15 - Deploy locally to Ubuntu 12.04
Now that we’ve fixed up our cookbook to work on Ubuntu 12.04, let’s test itout! Run kitchen list
to display the list of Test Kitchen instances:
Instance Driver Provisioner Last Actiondefault-centos65 Vagrant Chef Solo Convergeddefault-ubuntu1204 Vagrant Chef Solo <Not Created>
Notice that after editing the .kitchen.yml
we now have an Ubuntu 12.04instance called default-ubuntu1204
and it is in the <Not Created>
state.
Go ahead setup the Ubuntu 12.04 instance by running kitchen converge
again:
$ kitchen converge default-ubuntu1204
Note that this time we added an optional instance parameter so that TestKitchen only performs the action against the specified instance. If you donot specify this parameter, it defaults to all
, running the command againstall instances. After about 5-10 minutes or so, you should observe that TestKitchen downloaded an Ubuntu 12.04 basebox, booted a VM with the basebox, andsuccessfully deployed our chef cookbook.
Run the kitchen list
command again to verify that the Ubuntu 12.04 instanceis now in the Set Up
state as well, showing that there were no errors:
Instance Driver Provisioner Last Actiondefault-centos65 Vagrant Chef Solo Convergeddefault-ubuntu1204 Vagrant Chef Solo Converged
You just fixed an error with the MyFace cookbook that prevented deployment toUbuntu 12.04, and verified that the cookbook correctly deploys to both Ubuntu 12.04 and Centos 6.5.
Use the kitchen login
command to ssh into each instance and poke aroundif you like. You now have two local vagrant VMs instantiated to play with!
$ kitchen login default-ubuntu1204Welcome to Ubuntu 12.04.3 LTS (GNU/Linux 3.8.0-29-generic x86_64) * Documentation: https://help.ubuntu.com/Last login: Sun Dec 29 13:30:36 2013 from 10.0.2.2$ [...poke around, run some commands...]$ exitConnection to 127.0.0.1 closed.$ kitchen login default-centos65Last login: Sun Dec 29 13:21:10 2013 from 10.0.2.2Welcome to your Packer-built virtual machine.[vagrant@default-centos65 ~]$ [...poke around, run some commands...][vagrant@default-centos65 ~]$ exitlogoutConnection to 127.0.0.1 closed.
You can view the websites for each instance by viewing the appropriateprivate IP
CentOS 6.5: http://33.33.33.10Ubuntu 12.04: http://33.33.33.11
Iteration #16 - Writing your first Serverspec test
While it’s really helpful to know now that the Myface cookbook will converge onboth a CentOS 6.5 and Ubuntu 12.04 setup, we haven’t written any tests yet.Let’s do that.
It’s helpful to know that Test Kitchen was designed as a framework forpost-convergence system testing. You are supposed to set up a bunch of testinstances, perform a Chef run to apply your cookbook’s changes to them, thenwhen this is process is complete your tests can inspect the state of eachtest instance after the Chef run is finished. This is how we tested ournodes by hand in Part 1and Part 2. Now we are going to automate the process.
NOTE: It is a testing anti-pattern to rely too much on system tests, even if they are automatedso make sure you are judicious in your use of system tests. It can bedifficult to maintain a lot of system tests over time and keep them relevant.The tests you performed by hand in Part 1and Part 2to verify MyFace are at just the right level of detail for a system test.Do just enough to verify that the system works correctly after it wasconfigured. In a future post, I’ll cover unit tests in more detail usingChefspec andGuard. For now, let’s focus on system tests.
Test Kitchen finds tests by following a directory naming convention. Whenyou installed Test Kitchen, it created the test/integration/default
subdirectory underneath your main cookbook. It looks for test code in thefollowing directory underneath test/integration
:
<COOKBOOOK-PATH>/test/integration/<TEST-SUITE-NAME>/<PLUGIN-NAME>
A collection of tests is called a test suite. Following Test Kitchen install’s lead, we’ll just call our firstsuite of tests default
. Test Kitchen has a number of plugins which willinstall and setup any components necessary for running tests. We’ll be usingthe severspec
plugin for our tests. So you will be placing your test filesin the following directory:
myface/test/integration/default/serverspec
Create the myface/test/integration/default/serverspec
subdirectory now.
To start, we need to add a Ruby helper script which loads our Test Kitchenplugin. We’ll call itmyface/test/integration/default/serverspec/spec_helper.rb
:
This code is modeled after the examples provided on theserverspec website.
Create a subdirectory underneath myface/test/integration/default/serverspec
called localhost
:
myface/test/integration/default/serverspec/localhost
It is a serverspec convention to put tests (a.k.a. “specs”) underneathspec_helper.rb
in a subdirectory denoting the host name to be tested.Serverspec supports testing via SSH access to remote hosts. We won’tbe using this capability as we will be testing local images, so we’ll justuse localhost
for the host name.
Now, let’s write our first test! If you recall in Testing Iteration #1, we ranthe following command to verify that the myface user was created:
$ getent password myfacemyface:x:497:503::/home/myface:/bin/bash
Create the a file named myface/test/integration/default/serverspec/localhost/webserver_spec.rb
that contains a serverspec test to perform the same action:
Serverspec provides extensions to Rspec to help you more easily test servers.If you’re not familiar with Rspec syntax, Code School has an excellenttutorial on Testing with Rspec. Even if youdon’t know Rspec, you should still be able to follow along withprovided examples.
You can find a list of serverspec resources at the following link:http://serverspec.org/resource_types.html. We’re using the command
resource to run the command getent password myface
and match theresultant output with a Ruby regular expression (because the uid and gidfield could be any number between 100-999, because myface is a systemaccount).
Testing Iteration #16 - Running your first Serverspec test
OK, let’s run our first test!
To start you need to run kitchen setup
so that Test Kitchen loads andconfigures all the required plugins. In keeping with the restaurant theme,the component that manages Test Kitchen plugins is calledBusser.
$ kitchen setup-----> Starting Kitchen (v1.1.1)-----> Setting up <default-centos65>...Fetching: thor-0.18.1.gem (100%)Fetching: busser-0.6.0.gem (100%) Successfully installed thor-0.18.1 Successfully installed busser-0.6.0 2 gems installed-----> Setting up Busser Creating BUSSER_ROOT in /tmp/busser Creating busser binstub Plugin serverspec installed (version 0.2.5)-----> Running postinstall for serverspec plugin Finished setting up <default-centos65> (0m52.12s).-----> Setting up <default-ubuntu1204>...Fetching: thor-0.18.1.gem (100%)Fetching: busser-0.6.0.gem (100%)Successfully installed thor-0.18.1Successfully installed busser-0.6.02 gems installed-----> Setting up Busser Creating BUSSER_ROOT in /tmp/busser Creating busser binstub Plugin serverspec installed (version 0.2.5)-----> Running postinstall for serverspec plugin Finished setting up <default-ubuntu1204> (0m15.36s).-----> Kitchen is finished. (1m7.77s)
After running kitchen setup
, next run kitchen verify
to run your testsuite.
$ kitchen verify-----> Starting Kitchen (v1.1.1)-----> Verifying <default-centos65>... Suite path directory /tmp/busser/suites does not exist, skipping. Uploading /tmp/busser/suites/serverspec/localhost/webserver_spec.rb (mode=0644) Uploading /tmp/busser/suites/serverspec/spec_helper.rb (mode=0644)-----> Running serverspec test suite /opt/chef/embedded/bin/ruby -I/tmp/busser/suites/serverspec -S /opt/chef/embedded/bin/rspec /tmp/busser/suites/serverspec/localhost/webserver_spec.rb --color --format documentation MyFace webserver should have a myface user Finished in 0.04293 seconds 1 example, 0 failures Finished verifying <default-centos65> (0m1.61s).-----> Verifying <default-ubuntu1204>... Suite path directory /tmp/busser/suites does not exist, skipping.Uploading /tmp/busser/suites/serverspec/localhost/webserver_spec.rb (mode=0644)Uploading /tmp/busser/suites/serverspec/spec_helper.rb (mode=0644)-----> Running serverspec test suite /opt/chef/embedded/bin/ruby -I/tmp/busser/suites/serverspec -S /opt/chef/embedded/bin/rspec /tmp/busser/suites/serverspec/localhost/webserver_spec.rb --color --format documentationMyFace webserver should have a myface userFinished in 0.11307 seconds1 example, 0 failures Finished verifying <default-ubuntu1204> (0m1.66s).-----> Kitchen is finished. (0m3.80s)
Finally run kitchen list
to display the results of your test run.
$ kitchen listInstance Driver Provisioner Last Actiondefault-centos-64 Vagrant Chef Solo Verifieddefault-ubuntu-1204 Vagrant Chef Solo Verified
If Test Kitchen displays the Last Action
as Verified
, all the tests passed.
Iteration #17 - Completing the webserver test suite
Now let’s dive in and encode all the rest of the tests fromPart 1.
While we used the command
resource to encode our first test, this isn’tthe optimal way to encode this test as a serverspec. We can make use of the user
resource to encode a test more succinctly:
it 'should have a myface user' do expect(user 'myface').to existend
The myface/test/integration/default/serverspec/localhost/webserver_spec.rb
file should resemble the following:
Run kitchen verify
and kitchen list
to re-run your test. You should seethe same result as before - 1 example, 0 failures
:
$ kitchen verify$ kitchen list
Only use the command
resource as a method of last resort. First check tosee if serverspec has a better resource to perform a test.
Let’s move on to the next command fromTesting Iteration #3:
$ vagrant ssh -c "sudo /sbin/service httpd status"httpd (pid 4831) is running.
Use the servspec service
resource to perform a test to ensure that thehttpd service is running and it automatically starts on bootup:
it 'should be running the httpd server' do expect(service 'httpd').to be_running expect(service 'httpd').to be_enabledend
Add this statement to your webserver_spec
file:
Run kitchen verify
and kitchen list
again to run this new test:
$ kitchen verify-----> Starting Kitchen (v1.1.1)-----> Verifying <default-centos65>...... MyFace webserver should have a myface user should be running the httpd server Finished in 0.04706 seconds 2 examples, 0 failures Finished verifying <default-centos65> (0m1.61s).-----> Verifying <default-ubuntu1204>... Removing /tmp/busser/suites/serverspecUploading /tmp/busser/suites/serverspec/localhost/webserver_spec.rb (mode=0644)Uploading /tmp/busser/suites/serverspec/spec_helper.rb (mode=0644)-----> Running serverspec test suite/opt/chef/embedded/bin/ruby -I/tmp/busser/suites/serverspec -S /opt/chef/embedded/bin/rspec /tmp/busser/suites/serverspec/localhost/webserver_spec.rb --color --format documentationMyFace webserver should have a myface userhttpd: unrecognized service should be running the httpd server (FAILED - 1)Failures: 1) MyFace webserver should be running the httpd server Failure/Error: expect(service 'httpd').to be_running ps aux | grep -w -- httpd | grep -qv grep expected Service "httpd" to be running # /tmp/busser/suites/serverspec/localhost/webserver_spec.rb:10:in `block (2 levels) in <top (required)>'Finished in 0.05906 seconds2 examples, 1 failureFailed examples:rspec /tmp/busser/suites/serverspec/localhost/webserver_spec.rb:9 # MyFace webserver should be running the httpd server/opt/chef/embedded/bin/ruby -I/tmp/busser/suites/serverspec -S /opt/chef/embedded/bin/rspec /tmp/busser/suites/serverspec/localhost/webserver_spec.rb --color --format documentation failedRuby Script[/tmp/busser/gems/gems/busser-serverspec-0.2.5/lib/busser/runner_plugin/../serverspec/runner.rb /tmp/busser/suites/serverspec] exit code was 1>>>>>> Verify failed on instance <default-ubuntu1204>.>>>>>> Please see .kitchen/logs/default-ubuntu1204.log for more details>>>>>> ------Exception------->>>>>> Class: Kitchen::ActionFailed>>>>>> Message: SSH exited (1) for command: [sh -c 'BUSSER_ROOT="/tmp/busser" GEM_HOME="/tmp/busser/gems" GEM_PATH="/tmp/busser/gems" GEM_CACHE="/tmp/busser/gems/cache" ; export BUSSER_ROOT GEM_HOME GEM_PATH GEM_CACHE; sudo -E /tmp/busser/bin/busser test']>>>>>> ----------------------...$ kitchen listInstance Driver Provisioner Last Actiondefault-centos65 Vagrant ChefSolo Verifieddefault-ubuntu1204 Vagrant ChefSolo Verified
Uh oh! That’s not what we expected! The tests failed on our Ubuntu 12.04instance - and yet it still says that it is Verified
, but the tests passedon CentOS 6.5. The Last Action
field is literally the last action. It doesnot report success or failure state, so you’ll want to pay attention to theoutput of kitchen verify
and note whether or not all the tests passed.
In this case, the reason for the failure is that on Ubuntu, the name of theApache httpd service is apache2
not httpd
. Let’s address this by adding a conditional that checks the os
custom configuration setting that is set in spec_helper.rb
.
I didn’t explain what this did before, but it runs a serverspec helpermethod to check the os type before each spec/test run. When running underUbuntu (or Debian), the value of RSpec.configuation.os
will be Debian
,otherwise the value will be RedHat
if it is running under any RHEL variant,including CentOS. So the following conditional should do the trick:
it 'should be running the httpd server' do case RSpec.configuration.os when "Debian" expect(service 'apache2').to be_running expect(service 'apache2').to be_enabled else expect(service 'httpd').to be_running expect(service 'httpd').to be_enabled endend
After this change, your webserver_spec.rb
file should resemble the following:
Run kitchen verify
and kitchen list
again - all the tests should pass:
$ kitchen verify-----> Starting Kitchen (v1.1.1)-----> Verifying <default-centos65>... Removing /tmp/busser/suites/serverspec Uploading /tmp/busser/suites/serverspec/localhost/webserver_spec.rb (mode=0644) Uploading /tmp/busser/suites/serverspec/spec_helper.rb (mode=0644)-----> Running serverspec test suite /opt/chef/embedded/bin/ruby -I/tmp/busser/suites/serverspec -S /opt/chef/embedded/bin/rspec /tmp/busser/suites/serverspec/localhost/webserver_spec.rb --color --format documentation MyFace webserver should have a myface user should be running the httpd server Finished in 0.04858 seconds 2 examples, 0 failures Finished verifying <default-centos65> (0m1.58s).-----> Verifying <default-ubuntu1204>... Removing /tmp/busser/suites/serverspecUploading /tmp/busser/suites/serverspec/localhost/webserver_spec.rb (mode=0644)Uploading /tmp/busser/suites/serverspec/spec_helper.rb (mode=0644)-----> Running serverspec test suite/opt/chef/embedded/bin/ruby -I/tmp/busser/suites/serverspec -S /opt/chef/embedded/bin/rspec /tmp/busser/suites/serverspec/localhost/webserver_spec.rb --color --format documentationMyFace webserver should have a myface user should be running the httpd serverFinished in 0.06551 seconds2 examples, 0 failures Finished verifying <default-ubuntu1204> (0m1.59s).-----> Kitchen is finished. (0m3.46s)$ kitchen listInstance Driver Provisioner Last Actiondefault-centos65 Vagrant Chef Solo Verifieddefault-ubuntu1204 Vagrant Chef Solo Verified
The final test that is used for the rest of the Test Iterations inPart 1basically amounts to visiting http://33.33.33.10 with a web browserand eyeballing the results. That would be difficult to automate withserverspec, and one would probably want to use a web automation frameworklike Selenium to do this. However, you canat least use serverspec to verify that the Apache Server is serving upcontent on port 80 (the default http port).
We can check that the server is listening on port 80 with the port
resource:
it 'should be listening on port 80' do expect(port 80).to be_listeningend
We’ll resort to using the command
resource to check to see if the serveraccepts an HTTP connections and returns something that looks reasonable, asthere doesn’t seem to be an obvious higher-level resource to perform thisaction:
it 'should respond to an HTTP request' do expect(command 'curl localhost').to return_stdout /.*<title>MyFace Users<\/title>.*/end
After adding these two checks, this is what your webserver_spec.rb
file shouldlook like:
Now we have an automated script that performs some basic tests to verifythat our cookbook enabled the web server properly. Let the robots do someof the grunge work!
Testing Iteration #17 - Running the suite
Do a final kitchen verify
and kitchen list
. Everything should look good:
$ kitchen verify-----> Starting Kitchen (v1.1.1)-----> Verifying <default-centos65>... Removing /tmp/busser/suites/serverspec Uploading /tmp/busser/suites/serverspec/localhost/webserver_spec.rb (mode=0644) Uploading /tmp/busser/suites/serverspec/spec_helper.rb (mode=0644)-----> Running serverspec test suite /opt/chef/embedded/bin/ruby -I/tmp/busser/suites/serverspec -S /opt/chef/embedded/bin/rspec /tmp/busser/suites/serverspec/localhost/webserver_spec.rb --color --format documentation MyFace webserver should have a myface user should be running the httpd server should respond to an HTTP request Finished in 0.05525 seconds 3 examples, 0 failures Finished verifying <default-centos65> (0m1.53s).-----> Verifying <default-ubuntu1204>... Removing /tmp/busser/suites/serverspecUploading /tmp/busser/suites/serverspec/localhost/webserver_spec.rb (mode=0644)Uploading /tmp/busser/suites/serverspec/spec_helper.rb (mode=0644)-----> Running serverspec test suite/opt/chef/embedded/bin/ruby -I/tmp/busser/suites/serverspec -S /opt/chef/embedded/bin/rspec /tmp/busser/suites/serverspec/localhost/webserver_spec.rb --color --format documentationMyFace webserver should have a myface user should be running the httpd server should respond to an HTTP requestFinished in 0.15965 seconds3 examples, 0 failures Finished verifying <default-ubuntu1204> (0m1.68s).-----> Kitchen is finished. (0m3.53s)$ kitchen listInstance Driver Provisioner Last Actiondefault-centos65 Vagrant Chef Solo Verifieddefault-ubuntu1204 Vagrant Chef Solo Verified
Iteration #18 - Completing the database test suite
Let’s wrap this up by finishing off the tests for the database portion inPart 2Create a new file called myface/test/integration/default/serverspec/localhost/database_spec.rb
to contain the database tests.
In Testing Iteration #7we checked to see if the mysqld
service was running with the followingcommand:
$ sudo /sbin/service mysqld status
There is a similar name difference between the Ubuntu and CentOS services asthere was with the Apache web server. For Ubuntu, the name of theMySQL service is mysql
. For CentOS, the name of the service is mysqld
.
This should be a piece of cake to write a serverspec test for now:
it 'should be running the database server' do case RSpec.configuration.os[:family] when "Ubuntu" expect(service 'mysql').to be_running expect(service 'mysql').to be_enabled else expect(service 'mysqld').to be_running expect(service 'mysqld').to be_enabled endend
In Testing Iteration #8we ran the following command to verify that the myface database was created:
$ mysqlshow -uroot -prootpass
That’s a simple command
resource regular expression:
it 'should have created the myface database' do expect(command 'mysqlshow -uroot -prootpass').to return_stdout /.*myface.*/end
In Testing Iteration #9we created a myface-app MySQL database user and to check to see if themyface_app user only has rights to the myface database with the followingcommands:
$ mysql -uroot -prootpass -e "select user,host from mysql.user;"$ mysql -uroot -prootpass -e "show grants for 'myface_app'@'localhost';"
Again, these are just more serverspec command
s (\s
indicates “anywhitespace character”):
it 'should have created the myface_app user' do expect(command 'mysql -uroot -prootpass -e "select user,host from mysql.user;"').to return_stdout /.*myface_app\s+localhost.*/endit 'should have given the myface_app database user rights to myface' do expect(command 'mysql -uroot -prootpass -e "show grants for \'myface_app\'@\'localhost\';"').to return_stdout /.*GRANT ALL PRIVILEGES ON `myface`.\* TO \'myface_app\'@\'localhost\'.*/end
In Testing Itegration #10we dumped the contents of the users
table to verify it got created:
$ mysql -hlocalhost -umyface_app -psupersecret -Dmyface -e "select id,user_name from users;"'
You guessed it, yet another command
:
it 'should have created the users table' do expect(command 'mysql -hlocalhost -umyface_app -psupersecret -Dmyface -e "select id,user_name from users;"').to return_stdout /.*mbower.*/end
In Testing Iteration #11 we checkedto see if the php5_module was successfully installed:
$ sudo /usr/sbin/httpd -M | grep php5
Note that there is a php_config
serverspec resource for checkingPHP config settings, but that’s not helpful for checking the existenceof PHP, so another command will do (just remember the service name isdifferent between the two different OSes):
it 'should have installed the Apache php5_module' do case RSpec.configuration.os[:family] when "Ubuntu" expect(command 'sudo /usr/sbin/apache2 -M | grep php5').to return_stdout /.*php5_module.*/ else expect(command 'sudo /usr/sbin/httpd -M | grep php5').to return_stdout /.*php5_module.*/ endend
And there you have it! Your final database_spec.rb
file should resemble thefollowing:
Testing Iteration #19 - kitchen test
Perform a final kitchen verify
and kitchen list
to check that there areno syntax errors. 9 tests succeeded!
In addition to the kitchen
commands that you have used so far, there’s oneother command that it quite useful - kitchen test
. It runs all the commandsin the Test Kitchen test lifecycle in order:
kitchen create
- Creates a vagrant instance.
kitchen converge
- Provision the vagrant instance with Chef, using the run list specified in the .kitchen.yml
file.
kitchen setup
- Install and configure any necessary Test Kitchen plugins needed to run tests.
kitchen verify
- Run tests.
kitchen destroy
- Destroy the vagrant instance, removing it from memory & disk.
When you are in the midst of writing tests, using the above commandsinteractively can save time (like only running kitchen verify
after addinga new test). But once the tests are written, normally you will runkitchen test
to run everything in one shot, preferably running as a “latch”triggered when your cookbook changes are committed to source control. Thiswill ensure that your tests are run often.
Conclusion
So hopefully now you understand how to use Test Kitchen and what it’s usefulfor. In the next article in this series, we’ll cover writing tests that canrun before deployment, providing feedback more quickly than withTest Kitchen (albeit in more limited circumstances), using Chefspec and Guard.(In the meantime check out Michael Geotz’sexcellent article series on ChefSpec with Guardas I’m currently coauthoring upcoming O’Reilly Media book on Chef withSeth Vargoand probably won’t have time to do further installments in this seriesanytime soon until I help finish the d*mn book!)
Now you should be able to test everything but the kitchen sink! Wait…actually Test Kitchen has got that covered as well:
$ kitchen sink ___ ' _ '. / /` `\ \ | | [__] | | \{\{ | | \}\} _ | | _ \{\{ ___________<_>_| |_<_>\}\}________ .=======^=(___)=^=\{\{====. / .----------------\}\}---. \ / / \{\{ \ \ / / \}\} \ \ ( '=========================' ) '-----------------------------'
Windows Server 2012 Automated Install Settings
Updated March 19, 2014
Updated ADK link from version 8 to 8.1 Updated link to Autounattend.xml Added note about using KMS keysI just recently revised all my automated install XML files for the WindowsSystem Preparation Tool (Sysprep) that I use for my Windows developmenttestbed. For this go around, I’m documenting the XML answer file settingsfor each version of Microsoft Windows. This article covers the XML answerfiles settings needed to automate a Windows Server 2012 (64-bit) baseOS install.
You’ll need to use the Windows System Image Manager tool to edit SysprepXML answer files. The Windows System Image Manager is packaged with theWindows Assessment and Deployment Kittool suite. Download and install the Windows Assessment and Deployment Kitto install the Windows System Image Manager (WSIM).
Link to Autounattend.xml with all the settings in this article. NOTE: Right-click and choose “Download Linked File As…” in your web browser, as many web browsers will try to interpret the Xml.
Disabling the language settings dialog
In the Windows Image pane, select the component amd64_Microsoft-Windows-International-Core-WinPE_6.2.9200.16384_neutral,right-click and choose Add Setting to Pass 1 windowsPE. Using theAnswer File Properties and Settings panes, configure the following settings:
InputLocale = en-US SystemLocale = en-US UILanguage = en-US UserLocale = en-USIn the Windows Image pane, select the component amd64_Microsoft-Windows-Setup_6.2.9200.16384_neutral,right-click on UserData/ProductKey and choose Add Setting to Pass 1 windowsPE. Using theAnswer File Properties and Settings panes, configure the following settings:
Key = YOUR_PRODUCT_KEY WillShowUI = OnErrorThe official Microsoft KMS keys are listed here and make a good starting point to test installs.
Disabling the Select Operating System dialog
In the Windows Image pane, select the componentamd64_Microsoft-Windows-Setup_6.2.9200.16384_neutral,right-click on ImageInstall/OSImage/InstallFrom/Metadata and chooseAdd Setting to Pass 1 windowsPE. Using the Answer File Properties andSettings panes, configure the following settings:
Key = /IMAGE/NAME Value = Windows Server 2012 SERVERDATACENTERNOTE: Make sure the /IMAGE/NAME
value matches the Windows Server 2012Image flavor you selected. Possible values are:
Disabling the EULA dialog
In the Windows Image pane, select the componentamd64_Microsoft-Windows-Setup_6.2.9200.16384_neutral,right-click on UserData and chooseAdd Setting to Pass 1 windowsPE. Using the Answer File Properties andSettings panes, configure the following settings:
AcceptEula = trueDisabling the Disk Allocation dialog
In the Windows Image pane, select the componentamd64_Microsoft-Windows-Setup_6.2.9200.16384_neutral,right-click on DiskConfiguration and chooseAdd setting to Pass 1 windowsPE. Using the Answer File Properties andSettings panes, configure the following settings:
WillShowUI = OnErrorIn the Windows Image pane, select the componentamd64_Microsoft-Windows-Setup_6.2.9200.16384_neutral,right-click on DiskConfiguration/Disk and chooseAdd setting to Pass 1 windowsPE. Using the Answer File Properties andSettings panes, configure the following settings:
DiskID = 0 WillWipDisk = trueIn the Windows Image pane, select the componentamd64_Microsoft-Windows-Setup_6.2.9200.16384_neutral,right-click on DiskConfiguration/Disk/CreatePartitions/CreatePartition and choose Add setting to Pass 1 windowsPE. Using the Answer File Propertiesand Settings panes, configure the following settings:
Extend = false Order = 1 Size = 10000 Type = PrimaryNOTE: Don’t worry about getting the size exact - just set it to areasonable minimum. In the next setting, we will extend the partitionto fill all remaining disk space on the drive.
In the Windows Image pane, select the componentamd64_Microsoft-Windows-Setup_6.2.9200.16384_neutral,right-click on DiskConfiguration/Disk/ModifyPartitions/ModifyPartition and choose Add setting to Pass 1 windowsPE. Using the Answer File Propertiesand Settings panes, configure the following settings:
Active = true Extend = true Format = NTFS Letter = C Order = 1 PartitionID = 1In the Windows Image pane, select the componentamd64_Microsoft-Windows-Setup_6.1.7600.16385_neutral,right-click on ImageInstall/OSImage/InstallTo and choose Add setting to Pass 1 windowsPE. Using the Answer File Propertiesand Settings panes, configure the following settings:
DiskID = 0 PartitionID = 1Disabling the Administrator password prompt
In the Windows Image pane, select the componentamd64_Microsoft-Windows-Shell-Setup_6.2.9200.16384_neutral,right-click on UserAccounts/AdministratorPassword and chooseAdd Setting to Pass 7 oobeSystem. Using the Answer File Properties andSettings panes, configure the following settings:
Value = vagrantSet up vagrant autologin
In the Windows Image pane, select the componentamd64_Microsoft-Windows-Shell-Setup_6.2.9200.16384_neutral,right-click on UserAccounts/LocalAccounts/LocalAccount and chooseAdd Setting to Pass 7 oobeSystem. Using the Answer File Properties andSettings panes, configure the following settings:
Description = Vagrant User DisplayName = vagrant Group = Administrators Name = vagrantIn the Windows Image pane, select the componentamd64_Microsoft-Windows-Shell-Setup_6.2.9200.16384_neutral,right-click on UserAccounts/LocalAccounts/LocalAccount/Password and chooseAdd Setting to Pass 7 oobeSystem. Using the Answer File Properties andSettings panes, configure the following settings:
Value = vagrantIn the Windows Image pane, select the componentamd64_Microsoft-Windows-Shell-Setup_6.1.9200.16384_neutral,right-click on AutoLogon and chooseAdd Setting to Pass 7 oobeSystem. Using the Answer File Properties andSettings panes, configure the following settings:
Enabled = true Username = vagrantIn the Windows Image pane, select the componentamd64_Microsoft-Windows-Shell-Setup_6.2.9200.16384_neutral,right-click on AutoLogon/Password and chooseAdd Setting to Pass 7 oobeSystem. Using the Answer File Properties andSettings panes, configure the following settings:
Value = vagrantDo not show Server Manager at logon
In the Windows Image pane, select the componentamd64_Microsoft-Windows-ServerManager-SvrMgrNc_6.2.9200.16384_neutral,right-click and choose Add Setting to Pass 4 specialize. Using the Answer File Properties and Settings panes, configure the followingsettings:
DoNotOpenServerManagerAtLogon = trueDisable User Account Control (UAC)
In the Windows Image pane, select the componentamd64_Microsoft-Windows-LUA-Settings_6.2.9200.16384_neutral,right-click and choose Add Setting to Pass 2 offlineServicing. Using the Answer File Properties and Settings panes, configure the followingsettings:
EnableLUA = falseDisable Internet Explorer Enhanced Security Configuration
In the Windows Image pane, select the componentamd64_Microsoft-Windows-IE-ESC_10.0.9200.16384_neutral,right-click and choose Add Setting to Pass 4 specialize. Using the Answer File Properties and Settings panes, configure the followingsettings:
IEHardenAdmin = false IEHardenUser = falseDisable Internet Explorer First Run Wizard
In the Windows Image pane, select the componentamd64_Microsoft-Windows-IE-InternetExplorer_10.0.9200.16384_neutral,right-click and choose Add Setting to Pass 4 specialize. Using the Answer File Properties and Settings panes, configure the followingsettings:
DisableAccelerators = true DisableFirstRunWizard = true Home_Page = about:blankIn the Windows Image pane, select the componentwow64_Microsoft-Windows-IE-InternetExplorer_10.0.9200.16384_neutral,right-click and choose Add Setting to Pass 4 specialize. Using the Answer File Properties and Settings panes, configure the followingsettings:
DisableAccelerators = true DisableFirstRunWizard = true Home_Page = about:blankReplace Internet Explorer Bing search with Google
In the Windows Image pane, select the componentamd64_Microsoft-Windows-IE-InternetExplorer_10.0.9200.16384_neutral,right-click on SearchScopes/Scope and chooseAdd Setting to Pass 4 specialize. Using the Answer File Propertiesand Settings panes, configure the following settings:
ScopeDefault = true ScopeDisplayName = Google ScopeKey = Google ScopeUrl = http://www.google.com/search?q={searchTerms} ShowSearchSuggestions = trueIn the Windows Image pane, select the componentwow64_Microsoft-Windows-IE-InternetExplorer_10.0.9200.16384_neutral,right-click on SearchScopes/Scope and chooseAdd Setting to Pass 4 specialize. Using the Answer File Propertiesand Settings panes, configure the following settings:
ScopeDefault = true ScopeDisplayName = Google ScopeKey = Google ScopeUrl = http://www.google.com/search?q={searchTerms} ShowSearchSuggestions = **trueEnable Remote Desktop
In the Windows Image pane, select the componentamd64_Microsoft-Windows-TerminalServices-LocalSessionManager_6.2.9200.16384_neutral,right-click and chooseAdd Setting to Pass 4 specialize. Using the Answer File Propertiesand Settings panes, configure the following settings:
fDenyTSConnections = falseIn the Windows Image pane, select the componentamd64_Networking-MPSSVC-Svc_6.2.9200.16384_neutral,right-click on FirewallGroups/FirewallGroup and chooseAdd Setting to Pass 4 specialize. Using the Answer File Propertiesand Settings panes, configure the following settings:
Active = true Group = Remote Desktop Key = RemoteDesktop Profile = allIn the Windows Image pane, select the componentamd64_Microsoft-Windows-TerminalServices-RDP-WinStationExtensions_6.2.9200.16384_neutral,right-click and chooseAdd Setting to Pass 4 specialize. Using the Answer File Propertiesand Settings panes, configure the following settings:
SecurityLayer = 1 UserAuthentication = 0Turn off computer password
Prevent the image from changing its computer account password,so you can restore old snapshots without being dropped from a domain
REG ADD "HKLM\System\CurrentControlSet\Services\Netlogon\Parameters" /v DisablePasswordChange /t REG_DWORD /d 1 /f
In the Windows Image pane, select the componentamd64_Microsoft-Windows-Shell-Setup_6.2.9200.16384_neutral,right-click FirstLogonCommands/SynchronousCommand” and choose_Add Setting to Pass 7 oobeSystem. Using the Answer File Propertiesand Settings panes, configure the following settings:
CommandLine = REG ADD “HKLM\System\CurrentControlSet\Services\Netlogon\Parameters” /v DisablePasswordChange /t REG_DWORD /d 2 /f Description = Disable computer password change Order = 1 RequiresUserInput trueTurn off all power saving and timeouts
In the Windows Image pane, select the componentamd64_Microsoft-Windows-Shell-Setup_6.2.9200.16384_neutral,right-click FirstLogonCommands/SynchronousCommand” and choose_Add Setting to Pass 7 oobeSystem. Using the Answer File Propertiesand Settings panes, configure the following settings:
CommandLine = cmd.exe /c a:set-power-config.bat Description = Turn off all power saving and timeouts Order = 2 RequiresUserInput = trueWindows 8 Automated Install Settings
Updated April 03, 2014
Updated link to Autounattend.xmlI just recently revised all my automated install XML files for the WindowsSystem Preparation Tool (Sysprep) that I use for my Windows developmenttestbed. For this go around, I’m documenting the XML answer file settingsfor each version of Microsoft Windows. This article covers the XML answerfiles settings needed to automate a Windows 8 (64-bit) baseOS install.
You’ll need to use the Windows System Image Manager tool to edit SysprepXML answer files. The Windows System Image Manager is packaged with theWindows Assessment and Deployment Kittool suite. Download and install the Windows Assessment and Deployment Kitto install the Windows System Image Manager (WSIM).
Link to Autounattend.xmlwith all the settings in this article. NOTE: Right-click and choose “Download Linked File As…” in your web browser, as many web browsers will try to interpret the Xml.
Disabling the language settings dialog
In the Windows Image pane, select the component amd64_Microsoft-Windows-International-Core-WinPE_6.2.9200.16384_neutral,right-click and choose Add Setting to Pass 1 windowsPE. Using theAnswer File Properties and Settings panes, configure the following settings:
InputLocale = en-US SystemLocale = en-US UILanguage = en-US UserLocale = en-USDisabling the Select Operating System dialog
In the Windows Image pane, select the componentamd64_Microsoft-Windows-Setup_6.2.9200.16384_neutral,right-click on ImageInstall/OSImage/InstallFrom/Metadata and chooseAdd Setting to Pass 1 windowsPE. Using the Answer File Properties andSettings panes, configure the following settings:
Key = /IMAGE/NAME Value = Windows 8 EnterpriseDisabling the EULA dialog
In the Windows Image pane, select the componentamd64_Microsoft-Windows-Setup_6.2.9200.16384_neutral,right-click on UserData and chooseAdd Setting to Pass 1 windowsPE. Using the Answer File Properties andSettings panes, configure the following settings:
AcceptEula = trueDisabling the Disk Allocation dialog
In the Windows Image pane, select the componentamd64_Microsoft-Windows-Setup_6.2.9200.16384_neutral,right-click on DiskConfiguration and chooseAdd setting to Pass 1 windowsPE. Using the Answer File Properties andSettings panes, configure the following settings:
WillShowUI = OnErrorIn the Windows Image pane, select the componentamd64_Microsoft-Windows-Setup_6.2.9200.16384_neutral,right-click on DiskConfiguration/Disk and chooseAdd setting to Pass 1 windowsPE. Using the Answer File Properties andSettings panes, configure the following settings:
DiskID = 0 WillWipDisk = trueIn the Windows Image pane, select the componentamd64_Microsoft-Windows-Setup_6.2.9200.16384_neutral,right-click on DiskConfiguration/Disk/CreatePartitions/CreatePartition and choose Add setting to Pass 1 windowsPE. Using the Answer File Propertiesand Settings panes, configure the following settings:
Extend = false Order = 1 Size = 10000 Type = PrimaryNOTE: Don’t worry about getting the size exact - just set it to areasonable minimum. In the next setting, we will extend the partitionto fill all remaining disk space on the drive.
In the Windows Image pane, select the componentamd64_Microsoft-Windows-Setup_6.2.9200.16384_neutral,right-click on DiskConfiguration/Disk/ModifyPartitions/ModifyPartition and choose Add setting to Pass 1 windowsPE. Using the Answer File Propertiesand Settings panes, configure the following settings:
Active = true Extend = true Format = NTFS Letter = C Order = 1 PartitionID = 1In the Windows Image pane, select the componentamd64_Microsoft-Windows-Setup_6.1.7600.16385_neutral,right-click on ImageInstall/OSImage/InstallTo and choose Add setting to Pass 1 windowsPE. Using the Answer File Propertiesand Settings panes, configure the following settings:
DiskID = 0 PartitionID = 1Disable PC name dialog
In the Windows Image pane, select the componentamd64_Microsoft-Windows-Shell-Setup_6.2.9200.16384_neutral,right-click and chooseAdd Setting to Pass 4 specialize. Using the Answer File Properties andSettings panes, configure the following settings:
Value - vagrant-win7 TimeZone = Pacific Standard TimeDisable Settings dialog
In the Windows Image pane, select the componentamd64_Microsoft-Windows-Shell-Setup_6.2.9200.16384_neutral,right-click on OOBE and chooseAdd Setting to Pass 7 oobeSystem. Using the Answer File Properties andSettings panes, configure the following settings:
NetworkLocation = Work ProtectYourPC = 3Disabling the Sign in to your PC dialog
In the Windows Image pane, select the componentamd64_Microsoft-Windows-Shell-Setup_6.2.9200.16384_neutral,right-click on UserAccounts/LocalAccounts/LocalAccount and chooseAdd Setting to Pass 7 oobeSystem. Using the Answer File Properties andSettings panes, configure the following settings:
Description = Vagrant User DisplayName = vagrant Group = Administrators Name = vagrantIn the Windows Image pane, select the componentamd64_Microsoft-Windows-Shell-Setup_6.2.9200.16384_neutral,right-click on UserAccounts/LocalAccounts/LocalAccount/Password and chooseAdd Setting to Pass 7 oobeSystem. Using the Answer File Properties andSettings panes, configure the following settings:
Value = vagrantIn the Windows Image pane, select the componentamd64_Microsoft-Windows-Shell-Setup_6.2.9200.16384_neutral,right-click on AutoLogon and chooseAdd Setting to Pass 7 oobeSystem. Using the Answer File Properties andSettings panes, configure the following settings:
Enabled = true Username = vagrantIn the Windows Image pane, select the componentamd64_Microsoft-Windows-Shell-Setup_6.1.7601.17514_neutral,right-click on AutoLogon/Password and chooseAdd Setting to Pass 7 oobeSystem. Using the Answer File Properties andSettings panes, configure the following settings:
Value = vagrantDisable User Account Control (UAC)
In the Windows Image pane, select the componentamd64_Microsoft-Windows-LUA-Settings_6.2.9200.16384_neutral,right-click and choose Add Setting to Pass 2 offlineServicing. Using the Answer File Properties and Settings panes, configure the followingsettings:
EnableLUA = falseDisable Internet Explorer First Run Wizard
In the Windows Image pane, select the componentamd64_Microsoft-Windows-IE-InternetExplorer_10.0.9200.16384_neutral,right-click and choose Add Setting to Pass 4 specialize. Using the Answer File Properties and Settings panes, configure the followingsettings:
DisableAccelerators = true DisableFirstRunWizard = true Home_Page = about:blankIn the Windows Image pane, select the componentwow64_Microsoft-Windows-IE-InternetExplorer_10.0.9200.16384_neutral,right-click and choose Add Setting to Pass 4 specialize. Using the Answer File Properties and Settings panes, configure the followingsettings:
DisableAccelerators = true DisableFirstRunWizard = true Home_Page = about:blankReplace Internet Explorer Bing search with Google
In the Windows Image pane, select the componentamd64_Microsoft-Windows-IE-InternetExplorer_10.0.9200.16384_neutral,right-click on SearchScopes/Scope and chooseAdd Setting to Pass 4 specialize. Using the Answer File Propertiesand Settings panes, configure the following settings:
ScopeDefault = true ScopeDisplayName = Google ScopeKey = Google ScopeUrl = http://www.google.com/search?q={searchTerms} ShowSearchSuggestions = trueIn the Windows Image pane, select the componentwow64_Microsoft-Windows-IE-InternetExplorer_10.0.9200.16384_neutral,right-click on SearchScopes/Scope and chooseAdd Setting to Pass 4 specialize. Using the Answer File Propertiesand Settings panes, configure the following settings:
ScopeDefault = true ScopeDisplayName = Google ScopeKey = Google ScopeUrl = http://www.google.com/search?q={searchTerms} ShowSearchSuggestions = **trueEnable Remote Desktop
In the Windows Image pane, select the componentamd64_Microsoft-Windows-TerminalServices-LocalSessionManager_6.2.9200.16384_neutral,right-click and chooseAdd Setting to Pass 4 specialize. Using the Answer File Propertiesand Settings panes, configure the following settings:
fDenyTSConnections = falseIn the Windows Image pane, select the componentamd64_Networking-MPSSVC-Svc_6.2.9200.16384_neutral,right-click on FirewallGroups/FirewallGroup and chooseAdd Setting to Pass 4 specialize. Using the Answer File Propertiesand Settings panes, configure the following settings:
Active = true Group = Remote Desktop Key = RemoteDesktop Profile = allIn the Windows Image pane, select the componentamd64_Microsoft-Windows-TerminalServices-RDP-WinStationExtensions_6.1.7601.17514_neutral,right-click and chooseAdd Setting to Pass 4 specialize. Using the Answer File Propertiesand Settings panes, configure the following settings:
SecurityLayer = 1 UserAuthentication = 0Turn off computer password
Prevent the image from changing its computer account password,so you can restore old snapshots without being dropped from a domain
REG ADD "HKLM\System\CurrentControlSet\Services\Netlogon\Parameters" /v DisablePasswordChange /t REG_DWORD /d 1 /f
In the Windows Image pane, select the componentamd64_Microsoft-Windows-Shell-Setup_6.2.9200.16384_neutral,right-click FirstLogonCommands/SynchronousCommand” and choose_Add Setting to Pass 7 oobeSystem. Using the Answer File Propertiesand Settings panes, configure the following settings:
CommandLine = REG ADD “HKLM\System\CurrentControlSet\Services\Netlogon\Parameters” /v DisablePasswordChange /t REG_DWORD /d 2 /f Description = Disable computer password change Order = 1 RequiresUserInput trueTurn off all power saving and timeouts
In the Windows Image pane, select the componentamd64_Microsoft-Windows-Shell-Setup_6.2.9200.16384_neutral,right-click FirstLogonCommands/SynchronousCommand” and choose_Add Setting to Pass 7 oobeSystem. Using the Answer File Propertiesand Settings panes, configure the following settings:
CommandLine = cmd.exe /c a:set-power-config.bat Description = Turn off all power saving and timeouts Order = 2 RequiresUserInput = trueWindows 7 Automated Install Settings
Updated April 03, 2014
Updated link to Autounattend.xmlI just recently revised all my automated install XML files for the WindowsSystem Preparation Tool (Sysprep) that I use for my Windows developmenttestbed. For this go around, I’m documenting the XML answer file settingsfor each version of Microsoft Windows. This article covers the XML answerfiles settings needed to automate a Windows 7 (64-bit) baseOS install.
You’ll need to use the Windows System Image Manager tool to edit SysprepXML answer files. The Windows System Image Manager is packaged with theWindows Assessment and Deployment Kittool suite. Download and install the Windows Assessment and Deployment Kitto install the Windows System Image Manager (WSIM).
Settings to Use for an Unattended Installation
Automate Windows Welcome
Link to Autounattend.xmlwith all the settings in this article. NOTE: Right-click and choose “Download Linked File As…” in your web browser, as many web browsers will try to interpret the Xml.
Disabling the language settings dialog
In the Windows Image pane, select the component amd64_Microsoft-Windows-International-Core-WinPE_6.1.7600.16385_neutral,right-click and choose Add Setting to Pass 1 windowsPE. Using theAnswer File Properties and Settings panes, configure the following settings:
InputLocale = en-US SystemLocale = en-US UILanguage = en-US UserLocale = en-USDisabling the Select Operating System dialog
In the Windows Image pane, select the componentamd64_Microsoft-Windows-Setup_6.1.7600.16385_neutral,right-click on ImageInstall/OSImage/InstallFrom/Metadata and chooseAdd Setting to Pass 1 windowsPE. Using the Answer File Properties andSettings panes, configure the following settings:
For Windows 7 Enterprise:
Key = /IMAGE/NAME Value = Windows 7 ENTERPRISEFor Windows 7 Professional:
Key = /IMAGE/NAME Value = Windows 7 PROFESSIONALDisabling the EULA dialog
In the Windows Image pane, select the componentamd64_Microsoft-Windows-Setup_6.1.7600.16385_neutral,right-click on UserData and chooseAdd Setting to Pass 1 windowsPE. Using the Answer File Properties andSettings panes, configure the following settings:
AcceptEula = trueDisabling the Disk Allocation dialog
In the Windows Image pane, select the componentamd64_Microsoft-Windows-Setup_6.1.7600.16385_neutral,right-click on DiskConfiguration and chooseAdd setting to Pass 1 windowsPE. Using the Answer File Properties andSettings panes, configure the following settings:
WillShowUI = OnErrorIn the Windows Image pane, select the componentamd64_Microsoft-Windows-Setup_6.1.7600.16385_neutral,right-click on DiskConfiguration/Disk and chooseAdd setting to Pass 1 windowsPE. Using the Answer File Properties andSettings panes, configure the following settings:
DiskID = 0 WillWipDisk = trueIn the Windows Image pane, select the componentamd64_Microsoft-Windows-Setup_6.1.7600.16385_neutral,right-click on DiskConfiguration/Disk/CreatePartitions/CreatePartition and choose Add setting to Pass 1 windowsPE. Using the Answer File Propertiesand Settings panes, configure the following settings:
Extend = false Order = 1 Size = 10000 Type = PrimaryNOTE: Don’t worry about getting the size exact - just set it to areasonable minimum. In the next setting, we will extend the partitionto fill all remaining disk space on the drive.
In the Windows Image pane, select the componentamd64_Microsoft-Windows-Setup_6.1.7600.16385_neutral,right-click on DiskConfiguration/Disk/ModifyPartitions/ModifyPartition and choose Add setting to Pass 1 windowsPE. Using the Answer File Propertiesand Settings panes, configure the following settings:
Active = true Extend = true Format = NTFS Letter = C Order = 1 PartitionID = 1In the Windows Image pane, select the componentamd64_Microsoft-Windows-Setup_6.1.7600.16385_neutral,right-click on ImageInstall/OSImage/InstallTo and choose Add setting to Pass 1 windowsPE. Using the Answer File Propertiesand Settings panes, configure the following settings:
DiskID = 0 PartitionID = 1Disabling the account and computer name dialog
In the Windows Image pane, select the componentamd64_Microsoft-Windows-Shell-Setup_6.1.7601.17514_neutral,right-click on UserAccounts/LocalAccounts/LocalAccount and chooseAdd Setting to Pass 7 oobeSystem. Using the Answer File Properties andSettings panes, configure the following settings:
Description = Vagrant User DisplayName = vagrant Group = Administrators Name = vagrantIn the Windows Image pane, select the componentamd64_Microsoft-Windows-Shell-Setup_6.1.7601.17514_neutral,right-click on UserAccounts/LocalAccounts/LocalAccount/Password and chooseAdd Setting to Pass 7 oobeSystem. Using the Answer File Properties andSettings panes, configure the following settings:
Value = vagrantIn the Windows Image pane, select the componentamd64_Microsoft-Windows-Shell-Setup_6.1.7601.17514_neutral,right-click on AutoLogon and chooseAdd Setting to Pass 7 oobeSystem. Using the Answer File Properties andSettings panes, configure the following settings:
Enabled = true Username = vagrantIn the Windows Image pane, select the componentamd64_Microsoft-Windows-Shell-Setup_6.1.7601.17514_neutral,right-click on AutoLogon/Password and chooseAdd Setting to Pass 7 oobeSystem. Using the Answer File Properties andSettings panes, configure the following settings:
Value = vagrantDisable Computer Name dialog
In the Windows Image pane, select the componentamd64_Microsoft-Windows-Shell-Setup_6.1.7601.17514_neutral,right-click and chooseAdd Setting to Pass 4 specialize. Using the Answer File Properties andSettings panes, configure the following settings:
Value - vagrant-win7 TimeZone = Pacific Standard TimeDisable Protect Computer dialog
In the Windows Image pane, select the componentamd64_Microsoft-Windows-Shell-Setup_6.1.7601.17514_neutral,right-click on OOBE and chooseAdd Setting to Pass 7 oobeSystem. Using the Answer File Properties andSettings panes, configure the following settings:
NetworkLocation = Work ProtectYourPC = 3Disable User Account Control (UAC)
In the Windows Image pane, select the componentamd64_Microsoft-Windows-LUA-Settings_6.1.7600.16385_neutral,right-click and choose Add Setting to Pass 2 offlineServicing. Using the Answer File Properties and Settings panes, configure the followingsettings:
EnableLUA = falseDisable Internet Explorer First Run Wizard
In the Windows Image pane, select the componentamd64_Microsoft-Windows-IE-InternetExplorer_8.0.7600.16385_neutral,right-click and choose Add Setting to Pass 4 specialize. Using the Answer File Properties and Settings panes, configure the followingsettings:
DisableAccelerators = true DisableFirstRunWizard = true Home_Page = about:blankIn the Windows Image pane, select the componentwow64_Microsoft-Windows-IE-InternetExplorer_8.0.7601.17514_neutral,right-click and choose Add Setting to Pass 4 specialize. Using the Answer File Properties and Settings panes, configure the followingsettings:
DisableAccelerators = true DisableFirstRunWizard = true Home_Page = about:blankReplace Internet Explorer Bing search with Google
In the Windows Image pane, select the componentamd64_Microsoft-Windows-IE-InternetExplorer_8.0.7600.16385_neutral,right-click on SearchScopes/Scope and chooseAdd Setting to Pass 4 specialize. Using the Answer File Propertiesand Settings panes, configure the following settings:
ScopeDefault = true ScopeDisplayName = Google ScopeKey = Google ScopeUrl = http://www.google.com/search?q={searchTerms} ShowSearchSuggestions = trueIn the Windows Image pane, select the componentwow64_Microsoft-Windows-IE-InternetExplorer_8.0.7601.17514_neutral,right-click on SearchScopes/Scope and chooseAdd Setting to Pass 4 specialize. Using the Answer File Propertiesand Settings panes, configure the following settings:
ScopeDefault = true ScopeDisplayName = Google ScopeKey = Google ScopeUrl = http://www.google.com/search?q={searchTerms} ShowSearchSuggestions = trueEnable Remote Desktop
In the Windows Image pane, select the componentamd64_Microsoft-Windows-TerminalServices-LocalSessionManager_6.1.7601.17514_neutral,right-click and chooseAdd Setting to Pass 4 specialize. Using the Answer File Propertiesand Settings panes, configure the following settings:
fDenyTSConnections = falseIn the Windows Image pane, select the componentamd64_Networking-MPSSVC-Svc_6.1.7601.175414_neutral,right-click on FirewallGroups/FirewallGroup and chooseAdd Setting to Pass 4 specialize. Using the Answer File Propertiesand Settings panes, configure the following settings:
Active = true Group = Remote Desktop Key = RemoteDesktop Profile = allIn the Windows Image pane, select the componentamd64_Microsoft-Windows-TerminalServices-RDP-WinStationExtensions_6.1.7601.17514_neutral,right-click and chooseAdd Setting to Pass 4 specialize. Using the Answer File Propertiesand Settings panes, configure the following settings:
SecurityLayer = 1 UserAuthentication = 0(Really) Disable Set Network Location Prompt
REG ADD "HKLM\System\CurrentControlSet\Control\Network\NewNetworkWindowOff"
In the Windows Image pane, select the componentamd64_Microsoft-Windows-Shell-Setup_6.1.7601.17514_neutral,right-click FirstLogonCommands/SynchronousCommand and chooseAdd Setting to Pass 7 oobeSystem. Using the Answer File Propertiesand Settings panes, configure the following settings:
CommandLine = REG ADD “HKLM\System\CurrentControlSet\Control\Network\NewNetworkWindowOff” Description = Disable Set Network Location Prompt Order = 1 RequiresUserInput trueTurn off computer password
Prevent the image from changing its computer account password,so you can restore old snapshots without being dropped from a domain
REG ADD "HKLM\System\CurrentControlSet\Services\Netlogon\Parameters" /v DisablePasswordChange /t REG_DWORD /d 1 /f
In the Windows Image pane, select the componentamd64_Microsoft-Windows-Shell-Setup_6.1.7601.17514_neutral,right-click FirstLogonCommands/SynchronousCommand” and choose_Add Setting to Pass 7 oobeSystem. Using the Answer File Propertiesand Settings panes, configure the following settings:
CommandLine = REG ADD “HKLM\System\CurrentControlSet\Services\Netlogon\Parameters” /v DisablePasswordChange /t REG_DWORD /d 2 /f Description = Disable computer password change Order = 2 RequiresUserInput trueTurn off all power saving and timeouts
In the Windows Image pane, select the componentamd64_Microsoft-Windows-Shell-Setup_6.1.7601.17514_neutral,right-click FirstLogonCommands/SynchronousCommand” and choose_Add Setting to Pass 7 oobeSystem. Using the Answer File Propertiesand Settings panes, configure the following settings:
CommandLine = cmd.exe /c a:set-power-config.bat Description = Turn off all power saving and timeouts Order = 3 RequiresUserInput = trueWindows Server 2008 R2 Automated Install Settings
Updated April 03, 2014
Updated link to Autounattend.xmlI just recently revised all my automated install XML files for the WindowsSystem Preparation Tool (Sysprep) that I use for my Windows developmenttestbed. For this go around, I’m documenting the XML answer file settingsfor each version of Microsoft Windows. This article covers the XML answerfiles settings needed to automate a Windows Server 2008 R2 (64-bit) baseOS install.
You’ll need to use the Windows System Image Manager tool to edit SysprepXML answer files. The Windows System Image Manager is packaged with theWindows Assessment and Deployment Kittool suite. Download and install the Windows Assessment and Deployment Kitto install the Windows System Image Manager (WSIM).
Link to Autounattend.xmlwith all the settings in this article. NOTE: Right-click and choose “Download Linked File As…” in your web browser, as many web browsers will try to interpret the Xml.
Disabling the language settings dialog
In the Windows Image pane, select the component amd64_Microsoft-Windows-International-Core-WinPE_6.1.7600.16385_neutral,right-click and choose Add Setting to Pass 1 windowsPE. Using theAnswer File Properties and Settings panes, configure the following settings:
InputLocale = en-US SystemLocale = en-US UILanguage = en-US UserLocale = en-USDisabling the Select Operating System dialog
In the Windows Image pane, select the componentamd64_Microsoft-Windows-Setup_6.1.7600.16385_neutral,right-click on ImageInstall/OSImage/InstallFrom/Metadata and chooseAdd Setting to Pass 1 windowsPE. Using the Answer File Properties andSettings panes, configure the following settings:
Key = /IMAGE/NAME Value = Windows Server 2008 R2 SERVERDATACENTERNOTE: Make sure the /IMAGE/NAME
value matches the Windows 2008R2Image flavor you selected. Possible values are:
Disabling the EULA dialog
In the Windows Image pane, select the componentamd64_Microsoft-Windows-Setup_6.1.7600.16385_neutral,right-click on UserData and chooseAdd Setting to Pass 1 windowsPE. Using the Answer File Properties andSettings panes, configure the following settings:
AcceptEula = trueDisabling the Disk Allocation dialog
In the Windows Image pane, select the componentamd64_Microsoft-Windows-Setup_6.1.7600.16385_neutral,right-click on DiskConfiguration and chooseAdd setting to Pass 1 windowsPE. Using the Answer File Properties andSettings panes, configure the following settings:
WillShowUI = OnErrorIn the Windows Image pane, select the componentamd64_Microsoft-Windows-Setup_6.1.7600.16385_neutral,right-click on DiskConfiguration/Disk and chooseAdd setting to Pass 1 windowsPE. Using the Answer File Properties andSettings panes, configure the following settings:
DiskID = 0 WillWipDisk = trueIn the Windows Image pane, select the componentamd64_Microsoft-Windows-Setup_6.1.7600.16385_neutral,right-click on DiskConfiguration/Disk/CreatePartitions/CreatePartition and choose Add setting to Pass 1 windowsPE. Using the Answer File Propertiesand Settings panes, configure the following settings:
Extend = false Order = 1 Size = 10000 Type = PrimaryNOTE: Don’t worry about getting the size exact - just set it to areasonable minimum. In the next setting, we will extend the partitionto fill all remaining disk space on the drive.
In the Windows Image pane, select the componentamd64_Microsoft-Windows-Setup_6.1.7600.16385_neutral,right-click on DiskConfiguration/Disk/ModifyPartitions/ModifyPartition and choose Add setting to Pass 1 windowsPE. Using the Answer File Propertiesand Settings panes, configure the following settings:
Active = true Extend = true Format = NTFS Letter = C Order = 1 PartitionID = 1In the Windows Image pane, select the componentamd64_Microsoft-Windows-Setup_6.1.7600.16385_neutral,right-click on ImageInstall/OSImage/InstallTo and choose Add setting to Pass 1 windowsPE. Using the Answer File Propertiesand Settings panes, configure the following settings:
DiskID = 0 PartitionID = 1Disabling the Administrator password prompt
In the Windows Image pane, select the componentamd64_Microsoft-Windows-Shell-Setup_6.1.7601.17514_neutral,right-click on UserAccounts/AdministratorPassword and chooseAdd Setting to Pass 7 oobeSystem. Using the Answer File Properties andSettings panes, configure the following settings:
Value = vagrantSet up vagrant autologin
In the Windows Image pane, select the componentamd64_Microsoft-Windows-Shell-Setup_6.1.7601.17514_neutral,right-click on UserAccounts/LocalAccounts/LocalAccount and chooseAdd Setting to Pass 7 oobeSystem. Using the Answer File Properties andSettings panes, configure the following settings:
Description = Vagrant User DisplayName = vagrant Group = Administrators Name = vagrantIn the Windows Image pane, select the componentamd64_Microsoft-Windows-Shell-Setup_6.1.7601.17514_neutral,right-click on UserAccounts/LocalAccounts/LocalAccount/Password and chooseAdd Setting to Pass 7 oobeSystem. Using the Answer File Properties andSettings panes, configure the following settings:
Value = vagrantIn the Windows Image pane, select the componentamd64_Microsoft-Windows-Shell-Setup_6.1.7601.17514_neutral,right-click on AutoLogon and chooseAdd Setting to Pass 7 oobeSystem. Using the Answer File Properties andSettings panes, configure the following settings:
Enabled = true Username = vagrantIn the Windows Image pane, select the componentamd64_Microsoft-Windows-Shell-Setup_6.1.7601.17514_neutral,right-click on AutoLogon/Password and chooseAdd Setting to Pass 7 oobeSystem. Using the Answer File Properties andSettings panes, configure the following settings:
Value = vagrantDisable Initial Configuration Dialog
In the Windows Image pane, select the componentamd64_Microsoft-Windows-OutOfBoxExperience_6.1.7600.16385_neutral,right-click and choose Add Setting to Pass 4 specialize. Using the Answer File Properties and Settings panes, configure the followingsettings:
DoNotOpenInitialConfigurationTasksAtLogon = trueDo not show Server Manager at logon
In the Windows Image pane, select the componentamd64_Microsoft-Windows-ServerManager-SvrMgrNc_6.1.7600.16385_neutral,right-click and choose Add Setting to Pass 4 specialize. Using the Answer File Properties and Settings panes, configure the followingsettings:
DoNotOpenServerManagerAtLogon = trueDisable User Account Control (UAC)
In the Windows Image pane, select the componentamd64_Microsoft-Windows-LUA-Settings_6.1.7600.16385_neutral,right-click and choose Add Setting to Pass 2 offlineServicing. Using the Answer File Properties and Settings panes, configure the followingsettings:
EnableLUA = falseDisable Internet Explorer Enhanced Security Configuration
In the Windows Image pane, select the componentamd64_Microsoft-Windows-IE-ESC_8.0.7601.17514_neutral,right-click and choose Add Setting to Pass 4 specialize. Using the Answer File Properties and Settings panes, configure the followingsettings:
IEHardenAdmin = false IEHardenUser = falseDisable Internet Explorer First Run Wizard
In the Windows Image pane, select the componentamd64_Microsoft-Windows-IE-InternetExplorer_8.0.7600.16385_neutral,right-click and choose Add Setting to Pass 4 specialize. Using the Answer File Properties and Settings panes, configure the followingsettings:
DisableAccelerators = true DisableFirstRunWizard = true Home_Page = about:blankIn the Windows Image pane, select the componentwow64_Microsoft-Windows-IE-InternetExplorer_8.0.7601.17514_neutral,right-click and choose Add Setting to Pass 4 specialize. Using the Answer File Properties and Settings panes, configure the followingsettings:
DisableAccelerators = true DisableFirstRunWizard = true Home_Page = about:blankReplace Internet Explorer Bing search with Google
In the Windows Image pane, select the componentamd64_Microsoft-Windows-IE-InternetExplorer_8.0.7600.16385_neutral,right-click on SearchScopes/Scope and chooseAdd Setting to Pass 4 specialize. Using the Answer File Propertiesand Settings panes, configure the following settings:
ScopeDefault = true ScopeDisplayName = Google ScopeKey = Google ScopeUrl = http://www.google.com/search?q={searchTerms} ShowSearchSuggestions = trueIn the Windows Image pane, select the componentwow64_Microsoft-Windows-IE-InternetExplorer_8.0.7601.17514_neutral,right-click on SearchScopes/Scope and chooseAdd Setting to Pass 4 specialize. Using the Answer File Propertiesand Settings panes, configure the following settings:
ScopeDefault = true ScopeDisplayName = Google ScopeKey = Google ScopeUrl = http://www.google.com/search?q={searchTerms} ShowSearchSuggestions = trueEnable Remote Desktop
In the Windows Image pane, select the componentamd64_Microsoft-Windows-TerminalServices-LocalSessionManager_6.1.7601.17514_neutral,right-click and chooseAdd Setting to Pass 4 specialize. Using the Answer File Propertiesand Settings panes, configure the following settings:
fDenyTSConnections = falseIn the Windows Image pane, select the componentamd64_Networking-MPSSVC-Svc_6.1.7601.175414_neutral,right-click on FirewallGroups/FirewallGroup and chooseAdd Setting to Pass 4 specialize. Using the Answer File Propertiesand Settings panes, configure the following settings:
Active = true Group = Remote Desktop Key = RemoteDesktop Profile = allIn the Windows Image pane, select the componentamd64_Microsoft-Windows-TerminalServices-RDP-WinStationExtensions_6.1.7601.17514_neutral,right-click and chooseAdd Setting to Pass 4 specialize. Using the Answer File Propertiesand Settings panes, configure the following settings:
SecurityLayer = 1 UserAuthentication = 0Turn off computer password
Prevent the image from changing its computer account password,so you can restore old VM snapshots without being dropped from a domain
REG ADD "HKLM\System\CurrentControlSet\Services\Netlogon\Parameters" /v DisablePasswordChange /t REG_DWORD /d 1 /f
In the Windows Image pane, select the componentamd64_Microsoft-Windows-Shell-Setup_6.1.7601.17514_neutral,right-click FirstLogonCommands/SynchronousCommand” and choose_Add Setting to Pass 7 oobeSystem. Using the Answer File Propertiesand Settings panes, configure the following settings:
CommandLine = REG ADD “HKLM\System\CurrentControlSet\Services\Netlogon\Parameters” /v DisablePasswordChange /t REG_DWORD /d 1 /f Description = Disable computer password change Order = 1 RequiresUserInput trueTurn off all power saving and timeouts
In the Windows Image pane, select the componentamd64_Microsoft-Windows-Shell-Setup_6.1.7601.17514_neutral,right-click FirstLogonCommands/SynchronousCommand” and choose_Add Setting to Pass 7 oobeSystem. Using the Answer File Propertiesand Settings panes, configure the following settings:
CommandLine = cmd.exe /c a:set-power-config.bat Description = Turn off all power saving and timeouts Order = 2 RequiresUserInput = trueGetting Started Writing Chef Cookbooks the Berkshelf Way, Part 2
Updated December 29, 2013
Bumped apache2 cookbook reference from 1.7.x to 1.8.x Bumped database cookbook reference from 1.4.x to 1.6.x Per Nicholas Johns removed php 5.5 deprecated mysql* functions_ Replaced symbol references with strings to match part 1 changes Added Windows instructionsUpdated September 1, 2013
Bumped apache2 cookbook reference from 1.6.x to 1.7.x Bumped database cookbook reference from 1.3.x to 1.4.xUpdated August 7, 2013
Fixed error in Iteration #10 test per Jeff ThomasUpdated July 23rd, 2013
Referenced Sean OMeara’s & Charles Johnson’s latest myface example appThis is a second article in a series on writing Opscode Chef cookbooks theBerkshelf Way. Here’s a link to Part 1. The source codeexamples covered in this article can be found on Github:https://github.com/misheska/myface
In this installment, Part 2, we’re going to create a new database
recipe. In Part1MyFace is just a web application serving up a static page. Now we’re going toenhance MyFace so that it stores account information in a persistent MySQL database.
Thanks go out to the Opscode Advanced Chef Cookbook Authoring class and specifically Sean OMeara and Charles Johnson for the database and PHP code used in this article.
Iteration #7 - Install MySQL
Edit metadata.rb
and add a reference to the mysql
cookbook. Alsobump the version to 2.0.0 because we know that there will be incompatible APIchanges, moving to MySQL, per Semantic Versioning:
Create a new recipe called recipes/database.rb
which includes the MySQLcookbook’s server recipe (this is a similar abstraction to what you created inPart 1with recipes/webserver.rb
):
Wire the database
recipe into the MyFace cookbook by adding aninclude_recipe
reference to recipes/default.rb
:
Run vagrant provision
to converge your changes.
$ vagrant provision[Berkshelf] This version of the Berkshelf plugin has not been fully tested on this version of Vagrant.[Berkshelf] You should check for a newer version of vagrant-berkshelf.[Berkshelf] If you encounter any errors with this version, please report them at https://github.com/RiotGames/vagrant-berkshelf/issues[Berkshelf] You can also join the discussion in #berkshelf on Freenode.[Berkshelf] Updating Vagrant's berkshelf: '/Users/misheska/.berkshelf/default/vagrant/berkshelf-20131228-44581-4bhc9d-default'[Berkshelf] Using myface (2.0.0)[Berkshelf] Using apache2 (1.8.14)[Berkshelf] Installing mysql (4.0.14) from site: 'http://cookbooks.opscode.com/api/v1/cookbooks'[Berkshelf] Installing openssl (1.1.0) from site: 'http://cookbooks.opscode.com/api/v1/cookbooks'[Berkshelf] Installing build-essential (1.4.2) from site: 'http://cookbooks.opscode.com/api/v1/cookbooks'[default] Chef 11.8.2 Omnibus package is already installed.[default] Running provisioner: chef_solo...Generating chef JSON and uploading...Running chef-solo...[2013-12-28T23:45:15-08:00] INFO: Forking chef instance to converge...[2013-12-28T23:45:15-08:00] INFO: *** Chef 11.8.2 ***[2013-12-28T23:45:15-08:00] INFO: Chef-client pid: 28502[2013-12-28T23:45:16-08:00] INFO: Setting the run_list to ["recipe[myface::default]"] from JSON[2013-12-28T23:45:16-08:00] INFO: Run List is [recipe[myface::default]][2013-12-28T23:45:16-08:00] INFO: Run List expands to [myface::default][2013-12-28T23:45:16-08:00] INFO: Starting Chef Run for myface-berkshelf[2013-12-28T23:45:16-08:00] INFO: Running start handlers[2013-12-28T23:45:16-08:00] INFO: Start handlers complete.[2013-12-28T23:45:16-08:00] WARN: Cloning resource attributes for directory[/var/lib/mysql] from prior resource (CHEF-3694)[2013-12-28T23:45:16-08:00] WARN: Previous directory[/var/lib/mysql]: /tmp/vagrant-chef-1/chef-solo-1/cookbooks/mysql/recipes/_server_rhel.rb:11:in `block in from_file'[2013-12-28T23:45:16-08:00] WARN: Current directory[/var/lib/mysql]: /tmp/vagrant-chef-1/chef-solo-1/cookbooks/mysql/recipes/_server_rhel.rb:20:in `from_file'[2013-12-28T23:45:16-08:00] WARN: Cloning resource attributes for service[apache2] from prior resource (CHEF-3694)[2013-12-28T23:45:16-08:00] WARN: Previous service[apache2]: /tmp/vagrant-chef-1/chef-solo-1/cookbooks/apache2/recipes/default.rb:24:in `from_file'[2013-12-28T23:45:16-08:00] WARN: Current service[apache2]: /tmp/vagrant-chef-1/chef-solo-1/cookbooks/apache2/recipes/default.rb:210:in `from_file'[2013-12-28T23:45:33-08:00] INFO: package[mysql-server] installing mysql-server-5.1.71-1.el6 from base repository[2013-12-28T23:45:43-08:00] INFO: directory[/var/log/mysql] created directory /var/log/mysql[2013-12-28T23:45:43-08:00] INFO: directory[/var/log/mysql] owner changed to 27[2013-12-28T23:45:43-08:00] INFO: directory[/var/log/mysql] group changed to 27[2013-12-28T23:45:43-08:00] INFO: directory[/var/log/mysql] mode changed to 755[2013-12-28T23:45:43-08:00] INFO: directory[/etc/mysql/conf.d] created directory /etc/mysql/conf.d[2013-12-28T23:45:43-08:00] INFO: directory[/etc/mysql/conf.d] owner changed to 27[2013-12-28T23:45:43-08:00] INFO: directory[/etc/mysql/conf.d] group changed to 27[2013-12-28T23:45:43-08:00] INFO: directory[/etc/mysql/conf.d] mode changed to 755[2013-12-28T23:45:43-08:00] INFO: template[initial-my.cnf] backed up to /var/chef/backup/etc/my.cnf.chef-20131228234543.651750[2013-12-28T23:45:43-08:00] INFO: template[initial-my.cnf] updated file contents /etc/my.cnf[2013-12-28T23:45:43-08:00] INFO: template[initial-my.cnf] sending start action to service[mysql-start] (immediate)[2013-12-28T23:45:45-08:00] INFO: service[mysql-start] started[2013-12-28T23:45:45-08:00] INFO: execute[assign-root-password] ran successfully[2013-12-28T23:45:45-08:00] INFO: template[/etc/mysql_grants.sql] created file /etc/mysql_grants.sql[2013-12-28T23:45:45-08:00] INFO: template[/etc/mysql_grants.sql] updated file contents /etc/mysql_grants.sql[2013-12-28T23:45:45-08:00] INFO: template[/etc/mysql_grants.sql] owner changed to 0[2013-12-28T23:45:45-08:00] INFO: template[/etc/mysql_grants.sql] group changed to 0[2013-12-28T23:45:45-08:00] INFO: template[/etc/mysql_grants.sql] mode changed to 600[2013-12-28T23:45:45-08:00] INFO: template[/etc/mysql_grants.sql] sending run action to execute[install-grants] (immediate)[2013-12-28T23:45:45-08:00] INFO: execute[install-grants] ran successfully[2013-12-28T23:45:45-08:00] INFO: execute[install-grants] sending restart action to service[mysql] (immediate)[2013-12-28T23:45:50-08:00] INFO: service[mysql] restarted[2013-12-28T23:45:50-08:00] INFO: service[mysql] enabled[2013-12-28T23:45:52-08:00] INFO: Chef Run complete in 35.813790999 seconds[2013-12-28T23:45:52-08:00] INFO: Running report handlers[2013-12-28T23:45:52-08:00] INFO: Report handlers complete[2013-12-28T23:45:15-08:00] INFO: Forking chef instance to converge...
Testing Iteration #7
Verify that the mysqld
service is running on your vagrant guest byrunning the following command on Mac OS X/Linux:
$ vagrant ssh -c "sudo /sbin/service mysqld status"mysqld (pid 8525) is running...
And on Windows:
> vagrant ssh -c "sudo /sbin/service mysqld status" -- -n -Tmysqld (pid 8525) is running...
Also check that MySQL is enabled to start on boot on Mac OS X/Linux:
$ vagrant ssh -c "sudo /sbin/chkconfig --list | grep mysqld"mysqld 0:off1:off2:on3:on4:on5:on6:off
And on Windows:
> vagrant ssh -c "sudo /sbin/chkconfig --list | grep mysqld" -- -n -Tmysqld 0:off1:off2:on3:on4:on5:on6:off
If the service is set to be activated at runlevels 3 and 5, then MySQL isenabled to run under full multi-user text mode and full multi-user graphicalmode, which is exactly the desired behavior.
Iteration #8 - Create the MyFace Database
We’ve installed MySQL, but we don’t have a database yet. Now we’re goingto create a database to store information about our users with anothercookbook, the database
cookbook.
Add the database
cookbook as a dependency in the metadata.rb
file:
Berkshelf automatically populates MySQL passwords for you. They wereconfigured in the Vagrantfile
when you ran berks cookbook
inPart 1:
...config.vm.provision :chef_solo do |chef| chef.json = { :mysql => { :server_root_password => 'rootpass', :server_debian_password => 'debpass', :server_repl_password => "replpass' } } ...end...
You can reference these passwords as variables in your Chef recipes, which wewill do when we add some data attributes. Add the following attributes toattributes/default.rb
so it looks like so:
Describe the database to be created for MyFace in recipes/database.rb
:
Converge the changes with vagrant provision
:
$ vagrant provision[Berkshelf] This version of the Berkshelf plugin has not been fully tested on this version of Vagrant.[Berkshelf] You should check for a newer version of vagrant-berkshelf.[Berkshelf] If you encounter any errors with this version, please report them at https://github.com/RiotGames/vagrant-berkshelf/issues[Berkshelf] You can also join the discussion in #berkshelf on Freenode.[Berkshelf] Updating Vagrant's berkshelf: '/Users/misheska/.berkshelf/default/vagrant/berkshelf-20131229-47158-1y8wp6-default'[Berkshelf] Using myface (2.0.0)[Berkshelf] Using apache2 (1.8.14)[Berkshelf] Using mysql (4.0.14)[Berkshelf] Using openssl (1.1.0)[Berkshelf] Using build-essential (1.4.2)[Berkshelf] Using database (1.6.0)[Berkshelf] Using postgresql (3.3.4)[Berkshelf] Using apt (2.3.4)[Berkshelf] Using aws (1.0.0)[Berkshelf] Using xfs (1.1.0)[default] Chef 11.8.2 Omnibus package is already installed.[default] Running provisioner: chef_solo...Generating chef JSON and uploading...Running chef-solo...[2013-12-29T00:40:09-08:00] INFO: Forking chef instance to converge...[2013-12-29T00:40:09-08:00] INFO: *** Chef 11.8.2 ***[2013-12-29T00:40:09-08:00] INFO: Chef-client pid: 5081[2013-12-29T00:40:10-08:00] INFO: Setting the run_list to ["recipe[myface::default]"] from JSON[2013-12-29T00:40:10-08:00] INFO: Run List is [recipe[myface::default]][2013-12-29T00:40:10-08:00] INFO: Run List expands to [myface::default][2013-12-29T00:40:10-08:00] INFO: Starting Chef Run for myface-berkshelf[2013-12-29T00:40:10-08:00] INFO: Running start handlers[2013-12-29T00:40:10-08:00] INFO: Start handlers complete.[2013-12-29T00:40:10-08:00] WARN: Cloning resource attributes for directory[/var/lib/mysql] from prior resource (CHEF-3694)[2013-12-29T00:40:10-08:00] WARN: Previous directory[/var/lib/mysql]: /tmp/vagrant-chef-1/chef-solo-1/cookbooks/mysql/recipes/_server_rhel.rb:11:in `block in from_file'[2013-12-29T00:40:10-08:00] WARN: Current directory[/var/lib/mysql]: /tmp/vagrant-chef-1/chef-solo-1/cookbooks/mysql/recipes/_server_rhel.rb:20:in `from_file'[2013-12-29T00:40:11-08:00] INFO: package[autoconf] installing autoconf-2.63-5.1.el6 from base repository[2013-12-29T00:40:18-08:00] INFO: package[bison] installing bison-2.4.1-5.el6 from base repository[2013-12-29T00:40:25-08:00] INFO: package[flex] installing flex-2.5.35-8.el6 from base repository[2013-12-29T00:40:31-08:00] INFO: package[gcc-c++] installing gcc-c++-4.4.7-4.el6 from base repository[2013-12-29T00:40:41-08:00] INFO: package[mysql-devel] installing mysql-devel-5.1.71-1.el6 from base repository[2013-12-29T00:41:17-08:00] WARN: Cloning resource attributes for service[apache2] from prior resource (CHEF-3694)[2013-12-29T00:41:17-08:00] WARN: Previous service[apache2]: /tmp/vagrant-chef-1/chef-solo-1/cookbooks/apache2/recipes/default.rb:24:in `from_file'[2013-12-29T00:41:17-08:00] WARN: Current service[apache2]: /tmp/vagrant-chef-1/chef-solo-1/cookbooks/apache2/recipes/default.rb:210:in `from_file'[2013-12-29T00:41:19-08:00] INFO: Chef Run complete in 69.220896743 seconds[2013-12-29T00:41:19-08:00] INFO: Running report handlers[2013-12-29T00:41:19-08:00] INFO: Report handlers complete[2013-12-29T00:40:09-08:00] INFO: Forking chef instance to converge...
Testing Iteration #8
Run mysqlshow
on your vagrant guest to display database information, verifyingthat the myface
database was created on Mac OS X/Linux:
$ vagrant ssh -c "mysqlshow -uroot -prootpass"+--------------------+| Databases |+--------------------+| information_schema || myface || mysql || test |+--------------------+
And on Windows:
> vagrant ssh -c "mysqlshow -uroot -prootpass" -- -n -T
Note that myface
is listed as a database name - success!
Iteration #9 - Create a MySQL user
It’s a good idea to create a user in MySQL for each one of your applicationsthat has the ability to only manipulate the application’s database and has no MySQL administrative privileges.
Add some attributes to attributes/default.rb
for your app user:
default['myface']['database']['app']['username'] = 'myface_app'default['myface']['database']['app']['password'] = 'supersecret'
attributes/default.rb
should look like so:
Edit recipes/database.rb
and describe the MySQL database user:
... ) action :createendmysql_database_user node['myface']['database']['app']['username'] do connection( :host => node['myface']['database']['host'], :username => node['myface']['database']['username'], :password => node['myface']['database']['password'] ) password node['myface']['database']['app']['password'] database_name node['myface']['database']['dbname'] host node['myface']['database']['host'] action [:create, :grant]end
After editing recipes/database.rb
should look like the following:
Converge the node to apply the changes:
$ vagrant provision
Testing Iteration #9
Check to see if the myface-app
user is enabled as a local user by running thefollowing mysql command on Mac OS X/Linux:
$ vagrant ssh -c 'mysql -uroot -prootpass -e "select user,host from mysql.user;"'+------------+------------------+| user | host |+------------+------------------+| repl | % || root | 127.0.0.1 || | localhost || myface_app | localhost || root | localhost || | myface-berkshelf |+------------+------------------+Connection to 127.0.0.1 closed.
And on Windows:
> vagrant ssh -c "mysql -uroot -prootpass -e 'select user,host from mysql.user;'" -- -n -T
As you can see above, the myface_app@localhost
user exists, so our cookbookdid what was expected.
Also check to see that the myface_app
user only has rights on the myface databse on Mac OS X/Linux:
$ vagrant ssh -c 'mysql -uroot -prootpass -e "show grants for 'myface_app'@'localhost';"'Grants for myface_app@localhostGRANT USAGE ON *.* TO 'myface_app'@'localhost' IDENTIFIED BY PASSWORD '*90BA3AC0BFDE07AE334CA523CB27167AE33825B9'GRANT ALL PRIVILEGES ON `myface`.* TO 'myface_app'@'localhost'
And on Windows:
> vagrant ssh -c "mysql -uroot -prootpass -e 'show grants for "myface_app"@"localhost";'" -- -n -T
Iteration #10 - Create a table for users
Let’s create a SQL script to create a table modeling MyFace users andpopulate it with some initial data. Create a file files/default/myface-create.sql
with the following content:
Add an attribute for the temporary location used for the SQL script we justcreated:
default['myface']['database']['seed_file'] = '/tmp/myface-create.sql'
The resultant attributes/default.rb
should resemble the following:
Modify recipes/database.rb
so that the cookbook transfers the SQL scriptto the guest node and so that the SQL script executes. As you learned inPart 1, recipes should be idempotent,so you will need to add a not_if
statement which ensures that the commandis only executed when necessary.
... host 'localhost' action [:create, :grant]end# Write schema seed file to filesystemcookbook_file node['myface']['database']['seed_file'] do source 'myface-create.sql' owner 'root' group 'root' mode '0600'end# Seed database with test dataexecute 'initialize myface database' do command "mysql -h #{node['myface']['database']['host']} -u #{node['myface']['database']['app']['username']} -p#{node['myface']['database']['app']['password']} -D #{node['myface']['database']['dbname']} < #{node['myface']['database']['seed_file']}" not_if "mysql -h #{node['myface']['database']['host']} -u #{node['myface']['database']['app']['username']} -p#{node['myface']['database']['app']['password']} -D #{node['myface']['database']['dbname']} -e 'describe users;'"end
Once you have made these changes, recipes/database.rb
should look like so:
Run vagrant provision
to converge your changes:
$ vagrant provision
Testing Iteration #10
Run the following mysql command to dump the contents of the users
table onMac OS X/Linux:
$ vagrant ssh -c 'mysql -hlocalhost -umyface_app -psupersecret -Dmyface -e "select id,user_name from users;"'id user_name216e03c2-ffe4-11e2-b1ad-080027c8jtimberman216e0890-ffe4-11e2-b1ad-080027c8someara216e0bce-ffe4-11e2-b1ad-080027c8jwinsor216e0eda-ffe4-11e2-b1ad-080027c8cjohnson216e11e6-ffe4-11e2-b1ad-080027c8mbower
And on Windows:
> vagrant ssh -c "mysql -hlocalhost -umyface_app -psupersecret -Dmyface -e 'select id,user_name from users;'" -- -n -T
The output should look similar to what you see above - the data from theINSERT INTO
statemens in the SQL script.
Iteration #11 - Install PHP
Let’s add some PHP scripting sizzle to sell the steak of the database wejust created. We’re going to install Apache 2 mod_php5
module and thephp-mysql
package to support our PHP script.
Edit recipes/webserver.rb
and add the following:
...include_recipe 'apache2'include_recipe 'apache2::mod_php5'package 'php-mysql' do action :install notifies :restart, 'service[apache2]'end
This will use the apache2 cookbook’s mod_php5
module to install PHP5and install the php-mysql
support package. After editing,recipes/webserver.rb
should look like this:
Run vagrant provision
to converge your changes:
$ vagrant provision
Test Iteration #11
Run the following command to verify that the php5_module was successfullyinstalled on Mac OS X/Linux:
$ vagrant ssh -c "sudo /usr/sbin/httpd -M | grep php5"httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1 for ServerName[Wed Aug 07 21:42:03 2013] [warn] NameVirtualHost *:80 has no VirtualHostsSyntax OK php5_module (shared)
And on Windows:
> vagrant ssh -c "sudo /usr/sbin/httpd -M | grep php5" -- -n -T
Iteration #12 - Add PHP Sizzle
It’s the last iteration, get ready to see the PHP sizzle! First modifytemplates/default/apache2.conf.erb
as follows:
Next delete files/default/index.html
with the following command:
$ rm files/default/index.html
You’ll be replacing it with the following parametized PHP script astemplates/default/index.php.erb
:
Finally modify recipes/webserver.rb
to use index.php.erb
template to generate a new index.php
document root:
Since we changed the document root and our recipe contains no statements toremove the old index.html
document root, we’ll need to destroy our vagranttest node and do a full vagrant up
again, otherwise if we visithttp://33.33.33.10 again, we’ll just see the old document root:
$ vagrant destroy -f$ vagrant up
Testing Iteration #12
Visit http://33.33.33.10 Now you should see the lovely new PHP version ofMyface.
More to Come!
In Part 3, we’ll introduce a new tool test-kitchen
and show you how toautomate all the tests you’ve been doing manually to test each iteration.
If you want to see the full source for MyFace, check out the followingGitHub link: https://github.com/misheska/myface
Getting Started Writing Chef Cookbooks the Berkshelf Way, Part 1
Updated Jan 29th, 2014
Per Seth Vargo, Note about the future of vagrant-berkshelfUpdated December 27th, 2013
Being more prescriptive about the necessary Ruby 1.9.x environment Bumped VirtualBox from version 4.3.4 to 4.3.6 Bumped vagrant-berkshelf plugin from version 1.3.6 to 1.3.7 Bumped vagrant-omnibus plugin from version 1.1.2 to 1.2.1 Added alternate command lines for Windows, as necessary Debate on symbols vs strings is an unnecessary distraction, removed this section Per Dan Patrick introducing the concept ofcookbook_file
before template
, as this was confusingUpdated December 15th, 2013
Bumped CentOS basebox version from 6.4 to 6.5 Added note about issue with Vagrant 1.4.0 Bumped VirtualBox from version 4.2.18 to 4.3.4 Bumped Vagrant from version 1.3.1 to 1.3.5 Bumped vagrant-berkshelf plugin from version 1.3.3 to 1.3.6 Bumped vagrant-omnibus plugin from version 1.1.1 to 1.1.2Updated September 9th, 2013
Bumped VirtualBox from version 4.2.16 to 4.2.18 Bumped berkshelf from version 2.0.9 to 2.0.10 Bumped vagrant from version 1.2.7 to 1.3.1 Bumped vagrant-omnibus plugin from version 1.1.0 to 1.1.1NOTE: As of Tuesday, January 28th the Berkshelf core team announced the future deprecation and retirement of the vagrant-berkshelf pluginIt is recommended that new users get started with the Berkshelf Way by using Test Kitchen and its .kitchen.yml
covered in Part 3of this series.
Jamie Winsor hasn’t yet updated his guide to authoring cookbooks the Berkshelf wayto match recent changes related to Vagrant 1.x and Chef 11This post is an attempt to update these instructions, walking through Jamie’sand Sean O’Meara’s example app - MyFace.For more information on Berkshelf, check out his recenttalkand slidesfrom ChefConf 2013.
NOTE: The source code examples covered in this article can be found onGitHub: https://github.com/misheska/myface
Getting Started
You can write Chef Cookbooks with Berkshelf on Mac OS X, Linux or Windows.To set up your cookbook-writing environment, make sure you have the followinginstalled:
Install VirtualBox 4.x. VirtualBox 4.3.6 was testedfor this post.
Install Vagrant 1.4.1 (or higher). Vagrant 1.4.1 was tested for this post.
Set up a sane Ruby 1.9.x environment for Chef cookbook authoring
Install Berkshelf
Upgrade from Berkshelf 1.x
NOTE: If you had a previous 1.x version of the berkshelf plugin installed,when it was named berkshelf-vagrant
, which you can verify by runningthe following command:
$ vagrant plugin listberkshelf-vagrant (1.1.3)
Make sure you fully uninstall the old berkshelf-vagrant
plugin beforeinstalling the new vagrant-berkshelf
plugin, as vagrant will get confusedby the name change:
$ vagrant plugin uninstall berkshelf-vagrantUninstalling the 'berkshelf-vagrant' plugin...$ vagrant plugin install vagrant-berkshelfInstalling the 'vagrant-berkshelf' plugin. This can take a few minutes...
Create the MyFace Application Cookbook
Key to the Berkshelf way is the use of the Application Cookbook Pattern. Anapplication cookbook contains the list of recipes needed to build yourapplication or service. As an example, this blog post will walk you throughthe creation of an example service - MyFace - the next killer social web app.
First create a new cookbook for the MyFace application using theberks cookbook myface
command:
$ berks cookbook myface create myface/files/default create myface/templates/default create myface/attributes create myface/definitions create myface/libraries create myface/providers create myface/recipes create myface/resources create myface/recipes/default.rb create myface/metadata.rb create myface/LICENSE create myface/README.md create myface/Berksfile create myface/Thorfile create myface/chefignore create myface/.gitignore run git init from "./myface" create myface/Gemfile create .kitchen.yml append Thorfile create test/integration/default append .gitignore append .gitignore append Gemfile append GemfileYou must run `bundle install' to fetch any new gems. create myface/Vagrantfile
Run bundle install
in the newly created cookbook directory to install thenecessary Gem dependencies:
$ cd myface$ bundle installFetching gem metadata from https://rubygems.org/.......Fetching additional metadata from https://rubygems.org/..Resolving dependencies...Using i18n (0.6.9)Using multi_json (1.8.2)Using activesupport (3.2.16). . .Using berkshelf (2.0.10)Using mixlib-shellout (1.3.0)Using net-scp (1.1.2)Using safe_yaml (0.9.7)Using test-kitchen (1.1.1)Using kitchen-vagrant (0.14.0)Using bundler (1.5.0)Your bundle is complete!Use `bundle show [gemname]` to see where a bundled gem is installed.
Prepare a virtual machine for testing
It’s a good idea to develop your cookbook incrementally, testing in short iterations. Berkshelf integrates with Vagrant to deployyour cookbook changes to a virtual machine for testing.
Ensure that the vagrant-omnibus
plugin is installed correctly.
$ vagrant plugin list...vagrant-omnibus (1.2.1)...
The vagrant-omnibus
plugin hooks into Vagrant and allows you to specifythe version of the Chef Omnibus package you want installed using theomnibus.chef_version
key
Edit the Vagrantfile generated by the berks cookbook
command to usea VirtualBox template that does not have a version of Chef provisioned.Then, specify that you want your image to always use the latest versionof Chef via the config.omnibus.chef_version
config option and replace thelegacy config.ssh.max_tries
and config.ssh.timeout
settings with config.vm.boot_timeout
.
NOTE: Vagrant 1.3.0 deprecated the config.ssh.max_tries
and config.ssh.timeout
settings that are inserted in the Vagrantfile byBerkshelf. Until Berkshelf is updated for these changes to vagrant, you’llneed to remove these settings from the Vagrantfile
and replace them withconfig.vm.boot_timeout
as above. If you are using vagrant 1.2.x, keep theconfig.ssh.max_tries
and config.ssh.timeout
settings, as the newconfig.vm.boot_timeout
setting is not valid in the older version of vagrant.
Run vagrant up
to start up the virtual machine and to test the stub MyFacecookbook you just created:
$ vagrant upBringing machine 'default' up with 'virtualbox' provider...[default] Box 'centos65' was not found. Fetching box from specified URL forthe provider 'virtualbox'. Note that if the URL does not havea box for this provider, you should interrupt Vagrant now and addthe box yourself. Otherwise Vagrant will attempt to download thefull box prior to discovering this error.Downloading box from URL: https://s3-us-west-2.amazonaws.com/misheska/vagrant/virtualbox4.3.6/centos65.boxExtracting box...te: 6881k/s, Estimated time remaining: 0:00:01)Successfully added box 'centos65' with provider 'virtualbox'![default] Importing base box 'centos65'...[default] Matching MAC address for NAT networking...[default] Setting the name of the VM...[default] Clearing any previously set forwarded ports...[Berkshelf] This version of the Berkshelf plugin has not been fully tested on this version of Vagrant.[Berkshelf] You should check for a newer version of vagrant-berkshelf.[Berkshelf] If you encounter any errors with this version, please report them at https://github.com/RiotGames/vagrant-berkshelf/issues[Berkshelf] You can also join the discussion in #berkshelf on Freenode.[Berkshelf] Updating Vagrant's berkshelf: '/Users/misheska/.berkshelf/default/vagrant/berkshelf-20131228-44316-176rdqc-default'[Berkshelf] Using myface (0.1.0)[default] Clearing any previously set network interfaces...[default] Preparing network interfaces based on configuration...[default] Forwarding ports...[default] -- 22 => 2222 (adapter 1)[default] Booting VM...[default] Waiting for machine to boot. This may take a few minutes...[default] Machine booted and ready![default] Setting hostname...[default] Configuring and enabling network interfaces...[default] Mounting shared folders...[default] -- /vagrant[default] -- /tmp/vagrant-chef-1/chef-solo-1/cookbooks[default] Installing Chef 11.8.2 Omnibus package...[default] Downloading Chef 11.8.2 for el...[default] downloading https://www.opscode.com/chef/metadata?v=11.8.2&prerelease=false&p=el&pv=6&m=x86_64 to file /tmp/install.sh.2993/metadata.txttrying wget...[default] urlhttps://opscode-omnibus-packages.s3.amazonaws.com/el/6/x86_64/chef-11.8.2-1.el6.x86_64.rpmmd510f3d0da82efa973fe91cc24a6a74549sha256044558f38d25bbf75dbd5790ccce892a38e5e9f2a091ed55367ab914fbd1cfed[default] downloaded metadata file looks valid...[default] downloading https://opscode-omnibus-packages.s3.amazonaws.com/el/6/x86_64/chef-11.8.2-1.el6.x86_64.rpm to file /tmp/install.sh.2993/chef-11.8.2.x86_64.rpmtrying wget...[default] Checksum compare with sha256sum succeeded.[default] Installing Chef 11.8.2installing with rpm...[default] warning:[default] /tmp/install.sh.2993/chef-11.8.2.x86_64.rpm: Header V4 DSA/SHA1 Signature, key ID 83ef826a: NOKEY[default] Preparing...[default] ##################################################[default][default] chef[default] #[default][default] Thank you for installing Chef![default] Running provisioner: chef_solo...Generating chef JSON and uploading...Running chef-solo...[2013-12-28T13:42:49-08:00] INFO: Forking chef instance to converge...[2013-12-28T13:42:49-08:00] INFO: *** Chef 11.8.2 ***[2013-12-28T13:42:49-08:00] INFO: Chef-client pid: 3368[2013-12-28T13:42:50-08:00] INFO: Setting the run_list to ["recipe[myface::default]"] from JSON[2013-12-28T13:42:50-08:00] INFO: Run List is [recipe[myface::default]][2013-12-28T13:42:50-08:00] INFO: Run List expands to [myface::default][2013-12-28T13:42:50-08:00] INFO: Starting Chef Run for myface-berkshelf[2013-12-28T13:42:50-08:00] INFO: Running start handlers[2013-12-28T13:42:50-08:00] INFO: Start handlers complete.[2013-12-28T13:42:50-08:00] INFO: Chef Run complete in 0.023677599 seconds[2013-12-28T13:42:50-08:00] INFO: Running report handlers[2013-12-28T13:42:50-08:00] INFO: Report handlers complete[2013-12-28T13:42:49-08:00] INFO: Forking chef instance to converge...
If all goes well, you should see Chef Run complete
with no errors.
NOTE: The basebox URL comes from my current collection of baseboxes. Thefollowing link points to a README file which provides links to all thevagrant baseboxes I use (which I normally update frequently):https://github.com/misheska/basebox-packer
If you would ever like to delete your test virtual machine and start over,you can destroy your test virtual machine with the vagrant destroy
command:
$ vagrant destroyAre you sure you want to destroy the 'default' VM? [y/N] y[default] Forcing shutdown of VM...[default] Destroying VM and associated drives...[Berkshelf] Cleaning Vagrant's berkshelf[default] Running cleanup tasks for 'chef_solo' provisioner...
Run vagrant up
to recreate the test virtual machine.
NOTE: If you just ran vagrant destroy
make sure you run vagrant up
before proceeding to the next section.
Iteration #1: Create an application user
For our first short iteration, let’s create a myface
user under whichwe’ll run our application. One best practice is to avoid runningapplications as root and create a user/group under which the application runsinstead who has just enough rights that the app needs.
Edit myface/recipes/default.rb
defining a new Group Resourceand User Resource for myface,so it looks like the following:
Save recipes/default.rb
and re-run vagrant provision
to create themyface user on your test virtual machine:
$ vagrant provision[Berkshelf] This version of the Berkshelf plugin has not been fully tested on this version of Vagrant.[Berkshelf] You should check for a newer version of vagrant-berkshelf.[Berkshelf] If you encounter any errors with this version, please report them at https://github.com/RiotGames/vagrant-berkshelf/issues[Berkshelf] You can also join the discussion in #berkshelf on Freenode.[Berkshelf] Updating Vagrant's berkshelf: '/Users/misheska/.berkshelf/default/vagrant/berkshelf-20131228-44581-4bhc9d-default'[Berkshelf] Using myface (0.1.0)[default] Chef 11.8.2 Omnibus package is already installed.[default] Running provisioner: chef_solo...Generating chef JSON and uploading...Running chef-solo...[2013-12-28T13:57:59-08:00] INFO: Forking chef instance to converge...[2013-12-28T13:57:59-08:00] INFO: *** Chef 11.8.2 ***[2013-12-28T13:57:59-08:00] INFO: Chef-client pid: 3845[2013-12-28T13:57:59-08:00] INFO: Setting the run_list to ["recipe[myface::default]"] from JSON[2013-12-28T13:57:59-08:00] INFO: Run List is [recipe[myface::default]][2013-12-28T13:57:59-08:00] INFO: Run List expands to [myface::default][2013-12-28T13:57:59-08:00] INFO: Starting Chef Run for myface-berkshelf[2013-12-28T13:57:59-08:00] INFO: Running start handlers[2013-12-28T13:57:59-08:00] INFO: Start handlers complete.[2013-12-28T13:57:59-08:00] INFO: group[myface] created[2013-12-28T13:57:59-08:00] INFO: user[myface] created[2013-12-28T13:57:59-08:00] INFO: Chef Run complete in 0.157055758 seconds[2013-12-28T13:57:59-08:00] INFO: Running report handlers[2013-12-28T13:57:59-08:00] INFO: Report handlers complete[2013-12-28T13:57:59-08:00] INFO: Forking chef instance to converge...
You should expect to see the Chef run complete with no errors. Noticethat it also creates group[myface]
and user[myface]
.
Testing Iteration #1
Verify that Chef actually created the myface user on our test virtualmachine by running the following on Mac OS X/Linux:
$ vagrant ssh -c "getent passwd myface"myface:x:497:501::/home/myface:/bin/bash
On Windows, add two extra parameters to the ssh invocation to squelch someerror messages:
> vagrant ssh -c "getent passwd myface" -- -n -Tmyface:x:497:501::/home/myface:/bin/bash
The extra -n
and -T
parameters for Windows are additional ssh parametersto prevent trying to read from stdin and to suppress an error messagethat a pseudo terminal can’t be allocated, respectively. On Windows,vagrant runs as a service, and windows services do not have consolesessions attached which ssh assumes, so you’ll see some errors on Windowsif you don’t use these extra parameters.
We use vagrant ssh -c
to run a command on our test virtual machine. Thegetent
command can be used to query all user databases. In thiscase we’re looking for myface
, and it exists!
Because we are using well-defined resources that are completelyidempotent, you should noticethat if you run vagrant provision
again, the Chef run executes more quicklyand it does not try to re-create the user/group it already created.
$ vagrant provision[Berkshelf] This version of the Berkshelf plugin has not been fully tested on this version of Vagrant.[Berkshelf] You should check for a newer version of vagrant-berkshelf.[Berkshelf] If you encounter any errors with this version, please report them at https://github.com/RiotGames/vagrant-berkshelf/issues[Berkshelf] You can also join the discussion in #berkshelf on Freenode.[Berkshelf] Updating Vagrant's berkshelf: '/Users/misheska/.berkshelf/default/vagrant/berkshelf-20131228-44581-4bhc9d-default'[Berkshelf] Using myface (0.1.0)[default] Chef 11.8.2 Omnibus package is already installed.[default] Running provisioner: chef_solo...Generating chef JSON and uploading...Running chef-solo...[2013-12-28T14:01:18-08:00] INFO: Forking chef instance to converge...[2013-12-28T14:01:18-08:00] INFO: *** Chef 11.8.2 ***[2013-12-28T14:01:18-08:00] INFO: Chef-client pid: 4378[2013-12-28T14:01:18-08:00] INFO: Setting the run_list to ["recipe[myface::default]"] from JSON[2013-12-28T14:01:18-08:00] INFO: Run List is [recipe[myface::default]][2013-12-28T14:01:18-08:00] INFO: Run List expands to [myface::default][2013-12-28T14:01:18-08:00] INFO: Starting Chef Run for myface-berkshelf[2013-12-28T14:01:18-08:00] INFO: Running start handlers[2013-12-28T14:01:18-08:00] INFO: Start handlers complete.[2013-12-28T14:01:18-08:00] INFO: Chef Run complete in 0.023349135 seconds[2013-12-28T14:01:18-08:00] INFO: Running report handlers[2013-12-28T14:01:18-08:00] INFO: Report handlers complete[2013-12-28T14:01:18-08:00] INFO: Forking chef instance to converge...
Iteration #2 - Refactor to attributes
What if at some point you wanted to change the name of the myface
user/groupyou just created to something else? At the moment, you would need to editmyface/recipes/default.rb
in three places.
Let’s create a new file called myface/attributes/default.rb
whichinitializes Chef attributesdefining the user name and group name under which our application will run sothat you don’t repeat yourself.
In Chef, attributes are a hash of a hash used to override the default settingson a node. The first hash is the cookbook name - in ourcase we’ve named our cookbook 'myface'
. The second hash is the name ofour attribute - in this case, we’re defining two new attributes: 'user'
and'group'
.
default
implies the use of the node objectnode.default
and is a Chef attribute file shorthand. The following areequivalent definitions to the ones above:
node.default['myface']['user'] = 'myface'node.default['myface']['group'] = 'myface'
Note that the hash names are defined as strings enclosed by quotes.In this case, it doesn’t matter if you use single or double quotes. InChef source files, double quotes indicate thatstring interpolationshould be performed, replacing special tokens in a string with theirvalues. If single quotes are used, no string interpolation is performed.We’ll see more examples of when string interpolation is necessary laterin this artile.
Now that you’ve created your attribute definitions, editmyface/recipes/default.rb
and replace all references to the ‘myface’ user namewith node['myface']['user']
and all references to the ‘myface’ group withnode['myface']['group']
. myface/recipes/default.rb
should now look likethis:
Re-provision with vagrant provision
to see how the refactor went:
$ vagrant provision
As long as you didn’t create any syntax errors in your refactoring file edits,there should be no net change on the virtual machine test node (as you’ve onlyjust moved some strings into a node attribute).
Testing Iteration #2
Running getent
on the test virtual machine should also produce the sameresult as when you validated Iteration #1 on Mac OS X/Linux:
$ vagrant ssh -c "getent passwd myface"myface:x:497:501::/home/myface:/bin/bash
And on Windows:
> vagrant ssh -c "getent passwd myface" -- -n -Tmyface:x:497:501::/home/myface:/bin/bash
Iteration #3 - Install the Apache2 Web Server
Our hot new social networking application, myface, is a web app, so we needto install a web server. Let’s install the Apache2 web server.
Modify myface/recipes/default.rb
to include the apache2 cookbook’s defaultrecipe:
include_recipe 'apache2'
The resultant myface/recipes/default.rb
file should look like so:
Since you are loading Apache2 from another cookbook, you need to configure thedependency in your metadata. Edit myface/metadata.rb
and add the apache2
dependency at the bottom:
depends 'apache2', '~> 1.8.0'
This tells Chef that the myface cookbook depends on the apache2 cookbook.We’ve also specified a version constraint using the optimistic operator~>
to tell our Chef that we want the latest version of the apache2 cookbookthat is greater than 1.8.0 but not 1.9.0 or higher.
It is recommended that Chef cookbooks follow aSemantic Versioning scheme. So if you write yourcookbook to use the latest apache2 1.8.x cookbook, if the apache2 cookbook isever bumped to a 1.9.x version (or 2.x), it has some public API functionalitythat has at least been deprecated. So you’ll want to review the changes andtest before automatically using an apache2 cookbook version 1.9.x or higher.However, automatic use of any new 1.8.x is perfectly fine, because noonly backwards-compatible bug fixes has been introduced. Semantic Versioningguarantees there are no changes in the public APIs.
Your myface/metadata.rb
file should look like this:
Now when you re-run vagrant provision
it will install apache2 on yourtest virtual machine:
$ vagrant provision[Berkshelf] This version of the Berkshelf plugin has not been fully tested on this version of Vagrant.[Berkshelf] You should check for a newer version of vagrant-berkshelf.[Berkshelf] If you encounter any errors with this version, please report them at https://github.com/RiotGames/vagrant-berkshelf/issues[Berkshelf] You can also join the discussion in #berkshelf on Freenode.[Berkshelf] Updating Vagrant's berkshelf: '/Users/misheska/.berkshelf/default/vagrant/berkshelf-20131228-44581-4bhc9d-default'[Berkshelf] Using myface (0.1.0)[Berkshelf] Installing apache2 (1.8.14) from site: 'http://cookbooks.opscode.com/api/v1/cookbooks'[default] Chef 11.8.2 Omnibus package is already installed.[default] Running provisioner: chef_solo...Generating chef JSON and uploading...Running chef-solo......[2013-12-28T14:10:49-08:00] INFO: service[apache2] started[2013-12-28T14:10:49-08:00] INFO: template[/etc/httpd/mods-available/deflate.conf] sending restart action to service[apache2] (delayed)[2013-12-28T14:10:51-08:00] INFO: service[apache2] restarted[2013-12-28T14:10:51-08:00] INFO: Chef Run complete in 38.225601754 seconds[2013-12-28T14:10:51-08:00] INFO: Running report handlers[2013-12-28T14:10:51-08:00] INFO: Report handlers complete[2013-12-28T14:10:12-08:00] INFO: Forking chef instance to converge...
Testing Iteration #3
You can verify that the apache2 httpd
service is running on your berkshelfvirtual machine with the following command on Mac OS X/Linux:
$ vagrant ssh -c "sudo /sbin/service httpd status"httpd (pid 5758) is running.
And on Windows:
> vagrant ssh -c "sudo /sbin/service httpd status" -- -n -Thttpd (pid 5758) is running.
Since this is a web server, so you can also check it out in your favorite webbrowser. The host-only private network address for the virtual machinethat Berkshelf created is in the Vagrantfile
. Display the IP address withthe following command:
$ grep ip: Vagrantfileconfig.vm.network :private_network, ip: "33.33.33.10"
Check it out with your favorite web browser:
http://33.33.33.10
While you will get a 404 Not Found
error because we haven’t added anycontent to our web site yet, the important part is that Apache Serverat 33.33.33.10 Port 80
sent the response:
Wait a second, though. You never downloaded the apache2
cookbook!That’s the magic of the Berkshelf Vagrant plugin you installed earlier. TheBerkshelf Vagrant plugin will make sure that any changes you make to yourcookbook and all of your cookbook’s dependencies are made available to yourvirtual machine. Berkshelf automatically loads all your cookbook dependenciesmuch like Bundler automatically loads all your gem dependencies.
Where does the Berkshelf put the cookbooks it downloads? You can find themin ~/.berkshelf/default/cookbooks
(or%USERPROFILE%\.berkshelf\default\cookbooks
on Windows)
Users/misheska/.berkshelf/default/cookbooks└── apache2-1.8.14 ├── attributes ├── definitions ├── files │ └── default │ └── tests │ └── minitest │ └── support ├── recipes └── templates └── default └── mods
~/.berkshelf
(or %USERPROFILE%\.berkshelf
on Windows) is just the defaultlocation where Berkshelf stores data on your local disk. This location can bealtered by setting the environment variable BERKSHELF_PATH
.
Iteration #4 - Add Content
Let’s add some content to make that 404 go away. Editmyface/recipes/default.rb
as follows:
If you’re familiar with Chef and configuring a web app via apache2, nothinghere should be too surprising. But if not, spend some time reading up onthe resource references at http://docs.opscode.com
Note our first use of string interpolationon line 26:
template "#{node['apache']['dir']}/sites-available/myface.conf" do
We need to enclose the template string in double-quotes because we’reusing the Ruby #{}
operator to indicate that we want to perform stringinterpolation and evaluate the value of node['apache']['dir']
inserting theevaluated value in the string.
Create a file to contain our web site content asmyface/files/default/index.html
.
Chef looks for files in the files
subtree by default. A subdirectorylevel underneath files
is used to specify platform-specific files.Files in files/default
are used with every platform. During the Chefrun this file is copied to the target node in the locationspecified in the cookbook_fileresource (see line 38 of myface/recipes/default.rb
).
With Chef, you can also create config files from templates usingERB, aRuby templating system. When the template .erb
file is processed by Chef,it will replace any token bracketed by a <%=
%>
tag with the valueof the Ruby expression inside the token (like node[:hostname]
). (Unlikewith a cookbook_file
whose content is static and is never manipulatedby Chef).
Chef expects ERB template files to be in the templates
subirectory of acookbook. A subdirectory level underneath templates
is used to specifyplatorm-specific files. Files in the templates/default
subdirectory areused with every platform.
Create a new template file calledmyface/templates/default/apache2.conf.erb
which will become thefile .../sites-available/myface.conf
on our test virtual machine(refer to myface/recipes/default.rb
above):
After you have created these three files, run vagrant provision
to deployyour changes:
$ vagrant provision
Testing Iteration #4
If the Chef run completed successfully, if you point your web browser at yourmyface web site again:
http://33.33.33.10
You’ll see some lovely content!
Also, note the difference between a cookbook_file
and a template
. Run thiscommand on Mac OS X/Linux to print out index.html
that was copied to the node during the Chef run.
$ vagrant ssh -c "cat /srv/apache/myface/index.html"Welcome to MyFace!Connection to 127.0.0.1 closed.
And on Windows:
> vagrant ssh -c "cat /srv/apache/myface/index.html" -- -n -TWelcome to MyFace!Connection to 127.0.0.1 closed.
Note that index.html
is copied verbatim with no changes to the file.
By comparison, in a template
any ERB tokens are replaced when they arecopied to the node. Look at the resultant myface.conf
on the nodewith the following command on Mac OS X/Linux:
$ vagrant ssh -c "cat /etc/httpd/sites-available/myface.conf"# Managed by Chef for myface-berkshelfAlias / /srv/apache/myface/<Directory /srv/apache/myface> Options FollowSymLinks +Indexes Allow from All</Directory>Connection to 127.0.0.1 closed.
and with the following command on Windows:
> vagrant ssh -c "cat /etc/httpd/sites-available/myface.conf" -- -n -T
The ERB token <%= node['hostname'] %>
was replaced by the evaluated stringmyface-berkshelf
during the Chef run.
Iteration #5 - Refactoring webserver
myface/recipes/default.rb
is getting rather large and we’ve got a lot moreto add to our cookbook. Let’s go through another refactoring pass.
Let’s move all the webserver-related resources to their own filemyface/recipes/webserver.rb
. Rename myface/recipes/default.rb
tomyface/recipes/webserver.rb
.
Now myface/recipes/webserver.rb
should look like this:
Create a new myface/recipes/default.rb
file which references webserver.rb
.
Converge your node again to make sure there are no syntax errors:
$ vagrant provision
Let’s eliminate some more of the duplication that crept in while we wereworking on things. Edit myface/attributes/default.rb
NOTE: With Chef 11, it is now possible to nest attributes, like so:
node.default['app']['name'] = 'my_app'node.default['app']['document_root'] = "/srv/apache/#{node['app']['name']}"
This approach is overkill for MyFace (and is frankly overkill for mostChef recipes). Even though nesting is an option now with Chef 11, you shouldtry to keep your attribute files as simple and straightforward to follow aspossible.
In myface/recipes/webserver.rb
replace the corresponding hardcoded referencesto attribute references:
Converge your node to make sure there are no syntax errors:
$ vagrant provision
Add tokens to the templates/default/apache2.conf.erb
ERB templatefile so they will be replaced with the value of thenode['myface']['document_root']
attribute during the Chef run.
Converge your node one last time to make sure there are no syntax errors:
$ vagrant provision
Testing Iteration #5
Visiting http://33.33.33.10 should produce the same result as before as youhave made no net changes, just shuffled things around a bit.
Iteration #6 - Version Bump and Production Deploy
Now that we have tested our cookbook locally and everything seems to work,we’re ready to finalize the cookbook and deploy it to production.
Version Bump to 1.0.0
First you need to “bump” the cookbook version in the metadata.rb
file toits final version 1.0.0. As mentioned in Iteration #3, cookbooks (even theones you write), should follow theSemantic Versioning scheme. Since this is the firstpublic version of our cookbook, it’s version 1.0.0.
myface/metadata.rb
should look like this:
Configure Berkshelf
In order to deploy to your production server (instead of just locally withvagrant), you’ll need to add a section to your Berkshelf config file withyour production Chef settings. Run the following command to create a defaultBerkshelf configuration file:
$ berks configure
It will prompt you for a bunch of server settings. Since I’m using hosted Chefto manage my servers, my settings are as follows (yours will be slightly different):
$ berks configureEnter value for chef.chef_server_url (default: 'http://localhost:4000'): https://api.opscode.com/organizations/misheskaEnter value for chef.node_name (default: 'Ruby.local'): misheskaEnter value for chef.client_key (default: '/etc/chef/client.pem'): /Users/misheska/.chef/misheska.pemEnter value for chef.validation_client_name (default: 'chef-validator'): misheska-validatorEnter value for chef.validation_key_path (default: '/etc/chef/validation.pem'): /Users/misheska/.chef/misheska-validator.pemEnter value for vagrant.vm.box (default: 'Berkshelf-CentOS-6.3-x86_64-minimal'): centos65Enter value for vagrant.vm.box_url (default: 'https://dl.dropbox.com/u/31081437/Berkshelf-CentOS-6.3-x86_64-minimal.box'): https://s3-us-west-2.amazonaws.com/misheska/vagrant/virtualbox4.3.6/centos65.boxConfig written to: '/Users/misheska/.berkshelf/config.json'
The config file is located in $HOME/.berkshelf/config.json
(or inx%USERPROFILE%/.berkshelf/config.json
on Windows).
Here’s what my $HOME/.berkshelf/config.json
file looks like:
{ "chef":{ "chef_server_url":"https://api.opscode.com/organizations/misheska", "validation_client_name":"misheska-validator", "validation_key_path":"/Users/misheska/.chef/misheska-validator.pem", "client_key":"/Users/misheska/.chef/misheska.pem", "node_name":"misheska" }, "cookbook":{ "copyright":"Mischa Taylor", "email":"mischa@misheska.com", "license":"Apache 2.0" }, "allowed_licenses":[], "raise_license_exception":false, "vagrant":{ "vm":{ "box":"centos65", "box_url":"https://s3-us-west-2.amazonaws.com/misheska/vagrant/virtualbox4.3.6/centos65.box", "forward_port":{}, "network":{"bridged":false,"hostonly":"33.33.33.10"}, "provision":"chef_solo"} }, "ssl":{ "verify":false }}{ "chef":{ "chef_server_url": "https://api.opscode.com/organizations/misheska", "validation_client_name": "misheska-validator", "validation_key_path": "/Users/mischa/.chef/misheska-validator.pem", "client_key": "/Users/mischa/.chef/misheska.pem", "node_name":"misheska" }, "vagrant":{ "vm":{ "box": "centos65", "box_url":"https://s3-us-west-2.amazonaws.com/misheska/vagrant/virtualbox4.3.6/centos65.box", "forward_port": { }, "network":{ "bridged": false, "hostonly": "33.33.33.10" }, "provision": "chef_solo" } }, "ssl": { "verify":false }}
I assume you have your own production Chef setup either running Hosted Chef,Private Chef, orOpen Source Chef Server. If you need more help getting your .pem file values, refer tothe QuickStart Guide on LearnChef.
Upload cookbooks
Edit your $HOME/.berkshelf/config.json
file similarly with your .pem filevalues. Then run berks upload
to upload your cookbooks to the chef server:
$ berks uploadUsing myface (1.0.0)Using apache2 (1.8.14)Uploading myface (1.0.0) to: 'https://api.opscode.com:443/organizations/misheska'Uploading apache2 (1.8.14) to: 'https://api.opscode.com:443/organizations/misheska'
Similarly to when you ran vagrant up
, Berkshelf automatically uploaded allthe cookbook dependencies.
Converge node
Add the default myface
cookbook recipe to your node’s run list. For example,I used the following command to add myface
to mine:
$ knife node run_list add mischa-ubuntu 'recipe[myface]'mischa-ubuntu: run_list: recipe[myface]
Converge the node by running chef-client
(if you don’t already have itsetup to run chef-client automatically). For example, here’s the commandI used to run chef-client
on my production node:
$ knife ssh name:mischa-ubuntu "sudo chef-client" -x misheskaStarting Chef Client, version 11.8.2resolving cookbooks for run list: ["myface"]Synchronizing Cookbooks: - myface - apache2...Chef Client finished, 20 resources updated
Testing Iteration #6
Browsing your production node’s URL should produce the same result as whenyou tested Iteration #4. For example, I visited http://mischa-ubuntu
More to Come!
This is just part one of a multi-part series. So far you’ve gone throughseveral short iteration loops as you evolve the myface cookbook webapplication. In Part 2,we’ll wire up a database to the myface application and explore the use ofthe mysql
and database
cookbooks.
If you want to see the full source for myface, check out the followingGitHub link: https://github.com/misheska/myface
← Older Blog ArchivesRecent Posts
Chef Server 12 Survey of Test Kitchen providers Set up a Sane Ruby Cookbook Authoring Environment for Chef on Mac OS X, Linux and Windows Getting Started Writing Chef Cookbooks the Berkshelf Way, Part 3 Windows Server 2012 Automated Install SettingsGitHub Repos
Status updating… @misheska on GitHubTAGS:Taylor Mischa Blog Coding
<<< Thank you for your visit >>>
Websites to related : Artwork and Friends - Grafik- &
artwork-and-friends | Grafik-GalerieSuchenPrimäres MenüZum Inhalt springenHomeFoto- & Grafik-AlbumGeo-MapTagsKontaktImpressumSitemapHomeWillkom
Taylor Leigh | Squarespace Web D0 Skip to Content
Inicio - Blog y LanaSaltar al contenido Sobre míServiciosPodCastBlogComienza aquí MenúSobre míServiciosPodCastBlogComienza aquí Sobre míServiciosPodCastBlog
owl and bear - a san diego musicowl and bearSearchPrimary MenuSkip to contentfeaturesart/books/filmcomedycontestslisteninterviewsmusic newsphotospodcastreviewssan diegovideowilco arc
The Burning Ear – The musiFEATURESTRACKSBest ofSolid AlbumsINFOVINYL MOONSearch Menu TwitterFacebook
Gimnasio, Piscinas, EntrenamientFitnessNutrición#WellLivingEnCasaNataciónFisioterapiaEstéticaSoyO2Selecciona Tu CentroGIRONA – Parc del MigdíaMADRID – BoutiqueMADRID
Digital Bounds | Internet CulturCategoriesPodcastTwitterFacebookInstagramSnapchatYouTubeNewsletterApps Editorial Gadgets Internet Lifestyle Mobile Reviews Social Media CategoriesPodc
BLOG HOME | Peras de Rincón deSOMOS LA PERAUN BOSQUE DE PERASESTA PERA RECUPERALA PERA QUE INNOVARECETASSeguirSeguirSeguirSeguirSeguirPeras de Rincón de Sotoiniciamos CAMPAÑA el
Alfattah Parenting Blog KeluargaLompat ke konten Lompat ke sidebar Lompat ke footer Alfattah Parenting Blog Keluarga AlfattahMari Berbagi Bersama
Warung BloggerTentangKontakSyarat & KebijakanDisclaimerWarung Blogger<i class="fa fa-bullhorn"></i> #InfoWB<i class="fa fa-book"></i> Blog-mbig/urun%20artikel<i cla
adsHot Websites