machine

[edit on GitHub]

Use the machine resource to define one (or more) machines, and then converge entire clusters of machines. This allows clusters to be maintained in a version control system and to be defined using multi-machine orchestration scenarios. For example, spinning up small test clusters and using them for continuous integration and local testing, building clusters that auto-scale, moving a set of machines in one cluster to another, building images, and so on.

Each machine is declared as a separate application topology, defined using operating system- and provisioner-independent files. Recipes (defined in cookbooks) are used to manage them. Chef Infra Client is used to converge the individual nodes (machines) within the cluster.

Warning

This functionality was available with Chef Provisioning and was packaged in the ChefDK.

Chef Provisioning was officially end-of-life on August 31, 2019 and is no longer included with ChefDK. The Chef Provisioning source code and drivers have been moved into the chef-boneyard organization. If you are a current user of Chef Provisioning, please contact your Chef Customer Success Manager or Account Representative to review your options.

Syntax

The syntax for using the machine resource in a recipe is as follows:

machine 'name' do
  attribute 'value' # see properties section below
  ...
  action :action # see actions section below
end

where

  • machine tells Chef Infra Client to use the Chef::Provider::Machine provider during a Chef Infra Client run
  • name is the name of the resource block and also the name of the machine
  • attribute is zero (or more) of the properties that are available for this resource
  • action identifies which steps Chef Infra Client will take to bring the node into the desired state

Actions

This resource has the following actions:

:allocate
Use to create a machine, return its machine identifier, and then (depending on the provider) boot the machine to an image. This reserves the machine with the provider and subsequent :allocate actions against this machine no longer need to create the machine, just update it.
:converge
Default. Use to create a machine, return its machine identifier, boot the machine to an image with the specified parameters and transport, install Chef Infra Client, and then converge the machine.
:converge_only
Use to converge a machine, but only if the machine is in a ready state.
:destroy
Use to destroy a machine.
:nothing
This resource block does not act unless notified by another resource to take action. Once notified, this resource block either runs immediately or is queued up to run at the end of a Chef Infra Client run.
:ready
Use to create a machine, return its machine identifier, and then boot the machine to an image with the specified parameters and transport. This machine is in a ready state and may be connected to (via SSH or other transport).
:setup
Use to create a machine, return its machine identifier, boot the machine to an image with the specified parameters and transport, and then install Chef Infra Client. This machine is in a ready state, has Chef Infra Client installed, and all of the configuration data required to apply the run-list to the machine.
:stop
Use to stop a machine.

In-Parallel Processing

In certain situations Chef Provisioning will run multiple machine processes in-parallel, as long as each of the individual machine resources have the same declared action. The machine_batch resource is used to run in-parallel processes.

Chef Provisioning will processes resources in-parallel automatically, unless:

  • The recipe contains complex scripts, such as when a file resource sits in-between two machine resources in a single recipe. In this situation, the resources will be run sequentially
  • The actions specified for each individual machine resource are not identical; for example, if resource A is set to :converge and resource B is set to :destroy, then they may not be processed in-parallel

To disable in-parallel processing, add the auto_machine_batch setting to the client.rb file, and then set it to false.

For example, a recipe that looks like:

machine 'a'
machine 'b'
machine 'c'

will show output similar to:

$ CHEF_DRIVER=fog:AWS chef-apply cluster.rb
...
Converging 1 resources
Recipe: @recipe_files::/Users/jkeiser/oc/environments/metal-test-local/cluster.rb
  * machine_batch[default] action converge
    - [a] creating machine a on fog:AWS:862552916454
    - [a]   key_name: "metal_default"
    - [a]   tags: {"Name"=>"a", ...}
    - [a]   name: "a"
    - [b] creating machine b on fog:AWS:862552916454
    - [b]   key_name: "metal_default"
    - [b]   tags: {"Name"=>"b", ...}
    - [b]   name: "b"
    - [c] creating machine c on fog:AWS:862552916454
    - [c]   key_name: "metal_default"
    - [c]   tags: {"Name"=>"c", ...}
    - [c]   name: "c"
    - [b] machine b created as i-eb778fb9 on fog:AWS:862552916454
    - create node b at http://localhost:8889
    -   add normal.tags = nil
    -   add normal.metal = {"location"=>{"driver_url"=>"fog:AWS:862552916454", ...}}
    - [a] machine a created as i-e9778fbb on fog:AWS:862552916454
    - create node a at http://localhost:8889
    -   add normal.tags = nil
    -   add normal.metal = {"location"=>{"driver_url"=>"fog:AWS:862552916454", ...}}
    - [c] machine c created as i-816d95d3 on fog:AWS:862552916454
    - create node c at http://localhost:8889
    -   add normal.tags = nil
    -   add normal.metal = {"location"=>{"driver_url"=>"fog:AWS:862552916454", ...}}
    - [b] waiting for b (i-eb778fb9 on fog:AWS:862552916454) to be ready ...
    - [c] waiting for c (i-816d95d3 on fog:AWS:862552916454) to be ready ...
    - [a] waiting for a (i-e9778fbb on fog:AWS:862552916454) to be ready ...
...
        Running handlers:
        Running handlers complete

        Chef Client finished, 0/0 resources updated in 4.053363945 seconds
    - [c] run 'chef-client -l auto' on c

Running handlers:
Running handlers complete
Chef Client finished, 1/1 resources updated in 59.64014 seconds

At the end, it shows 1/1 resources updated. The three machine resources are replaced with a single machine_batch resource, which then runs each of the individual machine processes in-parallel.

Properties

This resource has the following properties:

admin

Ruby Type: true, false

Use to specify whether Chef Infra Client is an API client.

allow_overwrite_keys

Ruby Type: true, false

Use to overwrite the key on a machine when it is different from the key specified by source_key.

attribute

Use to specify an attribute, and then modify that attribute with the specified value. The following patterns may be used to specify the value.

attribute <name>, <value>
attribute [<path>], <value>

The following example will set attribute a to b:

attribute 'a', 'b'

The following example will set attribute node['a']['b']['c'] to d and will ignore attributes a.b.x, a.b.y, etc.:

attribute %w[a b c], 'd'

The following example is similar to %w[a b c], 'd':

attribute 'a', { 'b' => { 'c' => 'd' } }

Each modified attribute should be specified individually. This attribute should not be used in the same recipe as attributes.

attributes
Use to specify a Hash that contains all of the normal attributes to be applied to a machine. This attribute should not be used in the same recipe as attribute.
chef_config

Ruby Type: String

Use to specify a string that contains extra configuration settings for a machine.

chef_environment
The name of the environment.
chef_server

Ruby Type: Hash

The URL for the Chef Infra Server.

complete

Use to specify if all of the normal attributes specified by this resource represent a complete specification of normal attributes for a machine. When true, any attributes not specified will be reset to their default values. For example, if a machine resource is empty and sets complete to true, all existing attributes will be reset:

machine "foo" do
  complete "true"
end
converge

Ruby Type: true, false

Use to manage convergence when used with the :create action. Set to false to prevent convergence. Set to true to force convergence. When nil, the machine will converge only if something changes.

driver

Ruby Type: Chef::Provisioning::Driver

Use to specify the URL for the driver to be used for provisioning.

files

Ruby Type: Hash

A list of files to upload. Syntax: REMOTE_PATH => LOCAL_PATH_OR_HASH.

For example:

files '/remote/path.txt' => '/local/path.txt'

or:

files '/remote/path.txt' => {
  :local_path => '/local/path.txt'
}

or:

files '/remote/path.txt' => { :content => 'foo' }
from_image

Ruby Type: String

Use to specify an image created by the machine_image resource.

machine_options

Ruby Type: Hash

A Hash that is specifies driver options.

name

Ruby Type: String

The name of the machine.

ohai_hints

Ruby Type: Hash

An Ohai hint to be set on the target node. For example: 'ec2' => { 'a' => 'b' } creates file ec2.json with json contents { 'a': 'b' }.

private_key_options

Ruby Type: Hash

Use to generate a private key of the desired size, type, and so on.

public_key_format

Ruby Type: String | Default Value: pem

Use to specify the format of a public key. Possible values: pem and der.

public_key_path

Ruby Type: String

The path to a public key.

raw_json

The machine as JSON data. For example:

{
  "name": "node1",
  "chef_environment": "_default",
  "json_class": "Chef::Node",
  "automatic": {
    "languages": {
      "ruby": {
        ...
      },
    ...
  ...
}
recipe

Use to add a recipe to the run-list for a machine. Use this property multiple times to add multiple recipes to a run-list. Use this property along with role to define a run-list. The order in which the recipe and role properties are specified will determine the order in which they are added to the run-list. This property should not be used in the same recipe as run_list. For example:

recipe 'foo'
role 'bar'
recipe 'baz'
remove_recipe
Use to remove a recipe from the run-list for the machine.
remove_role
Use to remove a role from the run-list for the machine.
remove_tag
Use to remove a tag.
role

Use to add a role to the run-list for the machine. Use this property multiple times to add multiple roles to a run-list. Use this property along with recipe to define a run-list. The order in which the recipe and role properties are specified will determine the order in which they are added to the run-list. This property should not be used in the same recipe as run_list. For example:

recipe 'foo'
role 'bar'
recipe 'baz'
run_list

An array of strings that specifies the run-list to apply to a machine. This property should not be used in the same recipe as recipe and role. For example:

[ 'recipe[COOKBOOK::RECIPE]','COOKBOOK::RECIPE','role[NAME]' ]
source_key
Use to copy a private key, but apply a different format and password. Use in conjunction with source_key_pass_phrase` and source_key_path.
source_key_pass_phrase

Ruby Type: String

The pass phrase for the private key. Use in conjunction with source_key` and source_key_path.

source_key_path

Ruby Type: String

The path to the private key. Use in conjunction with source_key` and source_key_pass_phrase.

tag
Use to add a tag.
tags
Use to add one (or more) tags. This will remove any tag currently associated with the machine. For example: tags :a, :b, :c.
validator

Ruby Type: true, false

Use to specify if Chef Infra Client is a chef-validator.

Examples

The following examples demonstrate various approaches for using resources in recipes:

Build machines dynamically

machine 'mario' do
  recipe 'postgresql'
  recipe 'mydb'
  tag 'mydb_master'
end

num_webservers = 1

1.upto(num_webservers) do |i|
  machine "luigi#{i}" do
    recipe 'apache'
    recipe 'mywebapp'
  end
end

Get a remote file onto a new machine

A deployment process requires more than just setting up machines. For example, files may need to be copied to machines from remote locations. The following example shows how to use the remote_file resource to grab a tarball from a URL, create a machine, copy that tarball to the machine, and then get that machine running by using a recipe that installs and configures that tarball on the machine:

remote_file 'mytarball.tgz' do
  url 'https://myserver.com/mytarball.tgz'
end

machine 'x'
  action :allocate
end

machine_file '/tmp/mytarball.tgz' do
  machine 'x'
  local_path 'mytarball.tgz'
  action :upload
end

machine 'x' do
  recipe 'untarthatthing'
  action :converge
end

Build machines that depend on each other

The following example shows how to create two identical machines, both of which cannot exist without the other. The first machine resource block creates the first machine by omitting the recipe that requires the other machine to be defined. The second resource block creates the second machine; because the first machine exists, both recipes can be run. The third resource block applies the second recipe to the first machine:

machine 'server_a' do
  recipe 'base_recipes'
end

machine 'server_b' do
  recipe 'base_recipes'
  recipe 'theserver'
end

machine 'server_a' do
  recipe 'theserver'
end

Use a loop to build many machines

1.upto(10) do |i|
  machine "hadoop#{i}" do
    recipe 'hadoop'
  end
end

Converge multiple machine types, in-parallel

The machine_batch resource can be used to converge multiple machine types, in-parallel, even if each machine type has different drivers. For example:

machine_batch do
  machine 'db' do
    recipe 'mysql'
  end
  1.upto(50) do |i|
    machine "#{web}#{i}" do
      recipe 'apache'
    end
  end
end

Define machine_options for a driver

require 'chef/provisioning_driver'

machine 'wario' do
  recipe 'apache'

  machine_options :driver_options => {
   :base_image => {
     :name => 'ubuntu',
     :repository => 'ubuntu',
     :tag => '14.04'
     },

   :command => '/usr/sbin/httpd'
  }

end

where provisioning_driver and :driver_options specify the actual driver that is being used to build the machine.

Build a machine from a machine image

machine_image 'web_image' do
  recipe 'apache2'
end

machine 'web_machine' do
 from_image 'web_image'
end

Set up a VPC, route table, key pair, and machine for Amazon AWS

require 'chef/provisioning/aws_driver'

with_driver 'aws::eu-west-1'

aws_vpc 'test-vpc' do
  cidr_block '10.0.0.0/24'
  internet_gateway true
end

aws_route_table 'ref-public1' do
  vpc 'test-vpc'
  routes '0.0.0.0/0' => :internet_gateway
end

aws_key_pair 'ref-key-pair'

m = machine 'test' do
  machine_options bootstrap_options: { key_name: 'ref-key-pair' }
end