Hazetug

Cloud provisioner and bootstrapper for DigitalOcean and Linode. Hazetug uses fog cloud library to be able to easily append other cloud computes and tugs (bootstraps) hosts using:

  • Knife bootstrap for chef-client.
  • Knife bootstrap for chef-solo.

Options

Cloud Computes specific options

Option Description
name Name of a host to provision. Random names are possible using %rand(x)% macro.
location Location in the cloud compute, namely data center.
flavor Flavor of a provisioned host. Flavors are recognized by memory, use: 512mb, 4gb, etc to choose the proper one.
image Distribution or image which is used for provisioning. Examples: ubuntu-12.04-x32, arch-linux-2014.14. If OS architecture is not specified then x64 is assumed.

SSH Specific

Option Description Default value
ssh_user User used to during provisioning and for connecting via ssh. root
ssh_password Password for a provisioned node. Evaluated randomly for some computes.
ssh_port Port used for ssh connection. 22
host_key_verify Verifies host key, set to true to enable verification. false

Knife tug

Option Description Default value
chef_validation_key Validation key used to authenticate new nodes in the Chef Server. validation.pem
chef_environment Chef Environment used during bootstrap
chef_server_url URL of the Chef Serer.

Solo tug

Option Description Default value
attributes Hash of attributes prepared for chef-solo run. (It's merged with the run_list). {}
berksfile Path to Berksfile.

Installation

Add this line to your application's Gemfile:

gem 'hazetug'

And then execute:

$ bundle

Or install it yourself as:

$ gem install hazetug

Usage

Configuration file

Create ~/.hazetug configuration file, with the content like:

default:
  linode_api_key: YOUR_LINODE_API_KEY
  linode_ssh_keys:
    - ~/.ssh/linode.pem (Change with your path, it also might be missing)
  digitalocean_api_key: DIGITALOCEAN_API_KEY
  digitalocean_client_id: DIGITALOCEAN_CLIENT_ID
  digitalocean_ssh_keys:
    - ~/.ssh/digitalocean.pem (Change with your path)

Tasks

Hazetug bootstrap task file is yaml file as well, it consists of two sections global and bootstrap. Global section sets default variables used by hazetug, each bootstraped host from bootstrap list sets variables specific to it thus redefining global defaults. Let's have a look at a sample task file:

chef_server_url: 'https://mychefserver.uri'
chef_environment: staging
chef_version: 11.14.6
ruby_version: ruby-2.1.2
ssh_password: my-password-on-api-nodes
bootstrap:
  - name: api-testbox-%rand(6)%
    number:   2
    location: london
    flavor:   2gb
    image:    ubuntu-14.04-x64
    run_list: ["role[api]"]

From the example above we can see various variables used by hazetug they are common for all bootstrapped nodes, that's why it's reasonable to locate them in the global. However each variable has three layer hierarchy more details look into the Variables Priority section.

Variables priority

Hazetug uses 3-level priority for flexible variable choosing. Priority in the ascending order is the following: variable from the global section -> variable set via command option -> variable in the bootstrap list entity. All variables are merged using this 3-level priority.

Command Line and Invocation

Bootstrap using knife

Help for the linode compute is given bellow:

NAME
    knife - Bootstraps server using Knife

SYNOPSIS
    hazetug.rb [global options] linode bootstrap knife [command options] task.yaml

COMMAND OPTIONS
    -v, --variables=arg   - Set variable or comma-seperated list of variables (var1_1=hello) (default: none)
    -n, --number=arg      - Set number of created nodes, value from yaml is honored (default: 1)
    -c, --concurrency=arg - Set concurrency value, i.e. number of hosts bootstraped simultaneously (default: 1)
    -b, --bootstrap=arg   - Set path to knife bootstrap.erb file (default: bootstrap.erb)

All variables are passed to the bootstrap template and are available using the hazetug hash like - hazetug[:variable_name]. Amongst variables described here in the options sections, hazetug also passes useful variables such as compute_name, public_ip_address, private_ip_address if those are available.

Client and Solo modes

It's possible to use chef-client or chef-solo to bootstrap a node. The solo mode is almost identical with the client mode, but with the only difference that it uses berkshelf to assist during the bootstrap process. Cookbooks are packaged and uploaded to the remote node and can be used by chef

You can initiate bootstrap in the solo mode, like the following:


hazetug digitalocean bootstrap solo -b bootstrap.erb solo-task.yaml

Solo bootstrap also uses bootstrap.erb, but there's no need to start client or use any data like validation_key or start_chef helper.

When defining a task, there additional options berksfile and attributes

...
...
bootstrap:
  - name: solo-box
    location: london
    flavor:   1gb
    image:    ubuntu-14.04-x64
    run_list: ["role[api]"]
    attributes: {
      "mycookbook": {
        "settings": {}
      }
    }

Merged attributes with the run_list form the input data for running chef-solo they are available inside bootstrap.erb as hazetug[:attributes_json]. Berksfile can be set specifically in the bootstrap task list or if it's not set local Berksfile is tried by default.

Another important option which is also available in the bootstrap.erb file is hazetug[:cookbooks_path] which is path to an archive of cookbooks packaged by Berkshelf.

Examples

  • Provisioning and bootstrapping 5 nodes, each 3 of them will be processed simultaneously:

hazetug digitalocean bootstrap knife -n 5 -c 3 -b api.erb api-task.yaml

  • Redefining validation_key and chef_version:

hazetug digitalocean bootstrap knife -v validation_key=/tmp/validation.pem,chef_version=11.12.4 api.erb api-task.yaml

Contributing

  1. Fork it ( http://github.com/dennybaa/hazetug/fork )
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request