Introduction
Opskelaton is an opinionated bootstrap tool for local Sandbox projects, it aims to solve the following common issues:
-
Developing Puppet/Chef modules/cookbooks on master machines which results with 'It works on my master/server' approach.
-
Large monolithic Puppet/Chef code bases, code isn’t modular or reusable.
-
Implicit/Missing dependencies including: Ruby version, OS, gems, modules/cookbooks.
-
Manual steps in setting up and maintaining such projects.
-
Non standard layout, projects missing README and LICENSE files, no clear separation between developed and dependant code.
-
Lacking development guidelines (for example extracting general modules and exporting them).
-
No continues build, linting and testing, provisioning code is second class citizen.
Opskeleton comes to solve these issues by introducing a decentralized development work flow with pre-defined layout, packaging and dependency management.
Currently Opskeleton supports Puppet and Chef, this guide is segmented to common functionality the respective separate sections for Puppet and Chef.
Usage
Installation
Perquisites (on Ubuntu):
-
Vagrant 1.8.x
-
RVM
-
Ruby >= 2.1.2
$ rvm use system
$ sudo gem install opskeleton
Autocompletion
Both zsh and bash are supported just copy the macthing file from the project autocomplete folder.
$ opsk help
Describe available commands or one spe...
bumps up version (clearing old version...
cleans up packaging products
deploy packge into bintray.com
deploy packge into s3 bucket under pat...
deploy packge using scp to host
generate an rspec ready Puppet module
generates a Chef based project
generates a Puppet based project
packages current module for celestial
print opsk version
Boxes
Opskeleton recommends the use of box-cutter in order to create Vagrant boxes in a consistent manner (as no free hosting solution currently exist):
# make sure to have latest packer
$ packer version
Packer v0.6.0
$ git clone git://github.com/box-cutter/ubuntu-vm.git
$ cd ubuntu-vm
# Edit Makefile.local
$ cat Makefile.local
# Makefile.local
CM := puppet
CM_VERSION := 3.6.1
$ make virtualbox/ubuntu1604
A useful convention for Box names:
ubuntu-{ubuntuversion}_puppet-3.6.1 ([os]-[version]_[provisioner]-[version])
Puppet
Introduction
Opskeleton supports the creation of Puppet based projects supporting dependency management (using librarian-puppet), linting and testing.
Structure
Lifecycle
Opskelaton defines a module life cycle:
-
Internal non reusable modules (usually specific to a client site) go under static-modules
-
If we create a general reusable module which is ready for prime time we pull out to a new git repository.
-
The extracted module is added (using librarian-puppet) back as a third party module under modules folder.
Life cycle scheme:
Creating new (static) modules is easy as:
$ opsk module foo
Each generated module will contain puppet-rspec with matching Rakefile.
Pushing changes
Making changes to third party modules is quite easy once librarian-puppet installed them locally (you can push only git based modules):
forge "https://forgeapi.puppetlabs.com"
mod 'puppetlabs/stdlib'
mod 'puppetlabs/apt'
mod 'strings/artifactory',
:git => 'git://github.com/pulling-strings/puppet-artifactory.git'
mod 'rip/module-data',
:git => 'git://github.com/ripienaar/puppet-module-data.git'
Its best practice to use git protocol (read only) which makes pushing changes from multiple modules a bit tedious, Opskeleton fixes that:
We can list the changes:
$ opsk uncommited
Listing changes for modules/artifactory:
changed files:
- metadata.json
added files:
untracked files:
We can commit them (providing a commit message per module or --message for all):
# We hacked a number of submodules, now we commit
$ opsk commit
Listing changes for modules/artifactory:
changed files:
- metadata.json
added files:
untracked files:
Commit the changes under modules/artifactory? (y/n) y
Commit message:
This is a nice change
For more commit options:
$ opsk help commit
Usage:
opsk commit [message]
Options:
[--message=MESSAGE] # optional commit message
[--all], [--no-all] # commit all
commit each changed puppet module under modules folder
Once commits are made we can push the changes:
$ opsk push
Push modules/artifactory? (y/n) y
pushing modules/artifactory ..
Opsk will add a remote writable repository for each submodule substituting the readonly protocol with a write enabled one, the default protocol is ssh (customizable by using --protocol).
For more options:
$ opsk help push
Usage:
opsk push
Options:
[--protocol=PROTOCOL] # remote ssh protocol (https or ssh)
# Default: ssh
[--dry], [--no-dry] # dry mode
[--all], [--no-all] # push all without asking
push each changed puppet module under modules folder
Testing
Opskelaton supports two levels of testing:
-
Static module testing that includes rspec and linting.
-
Integration testing using serverspecand Vagrant.
# linting all static modules
$ rake lint
# rspecing
$ rake modspec
# running serverspec
$ rake spec
Packaging
Opskelaton fully supports deployment and portable execution of sandboxes on non Vagrant environments:
$ opsk generate_puppet foo ubuntu-13.10
$ cd foo-sandbox
# The package version file
$ cat opsk.yaml
---
version: '0.0.1'
name: foo
# post bundle and gem install ..
$ opsk package
create pkg/foo-sandbox-0.0.1
create pkg/foo-sandbox-0.0.1/scripts
create pkg/foo-sandbox-0.0.1/scripts/lookup.rb
chmod pkg/foo-sandbox-0.0.1/scripts/lookup.rb
create pkg/foo-sandbox-0.0.1/scripts/run.sh
chmod pkg/foo-sandbox-0.0.1/scripts/run.sh
create pkg/foo-sandbox-0.0.1/manifests/site.pp
exist pkg
$ ls pkg
foo-sandbox-0.0.1 foo-sandbox-0.0.1.tar.gz
The packaging process creates a portable tar file that can be run on any machine with puppet installed via the bundled run.sh:
$ tar -xvzf foo-sandbox-0.0.1.tar.gz
$ cd foo-sandbox-0.0.1
$ sudo ./run.sh
An external node classifier based runner is also available under scripts/run.sh, this runner expects to get a <hostname>.yaml input file with the required node classes.
Updating
Keeping you box up to date with latest opsk version is easy, just re-generate it again and resolve conflicts by answering y/n:
# Moving to latest opsk
$ gem update opskeleton
# foo box already exists
$ opsk generate foo <vagrant-box>
exist foo-sandbox
conflict foo-sandbox/Vagrantfile
Overwrite /home/ronen/code/foo-sandbox/Vagrantfile? (enter "h" for help) [Ynaqdh]
Vagrant
Opskeleton generates a Vagrant file with couple of enhancements:
-
VAGRANT_BRIDGE (default eth0) for setting up public bridge on the go.
-
PUPPET_ENV (default dev) for setting puppet environment.
-
Puppet options preset to match modules and hiera folders.
Benchmarking
Tracking the speed of our provisioning code is important for keeping a consistent level of service with the produced sandboxes, enabling benchmarking:
$ opsk generate_puppet redis ubuntu-16.04 --bench-enable
# install imagemagic before bundle install
$ sudo apt-get install imagemagick libmagickwand-dev
$ rake serverspec:redis
# with each run more result lines will be recorded
$ cat benchmark.json
{"total":656,"host":"redis","revision":"5d03a41ade9fc3dd5296d4119ccb0b0ad8290b9e","time":"2014-12-17 02:57:45 +0200"}
# add it to git for tracking
$ git add benchmark.json
Now after a number of runs we could plot and view the results of a single host or of all the hosts side by side:
$ rake plot:hosts plot:per_hosts
# resulting png files
$ google-chrome plots
Deployment
The packaged tar files can be consumed using any tool and protocol (http, s3 etc), opsk has built in support for deploying public sandboxes into:
-
Bintray (make sure to configure the bintray API key):
$ opsk package
$ opsk deploy_bintray <bintray-repo>
deployed foo-sandbox-0.0.1.tar.gz to http://dl.bintray.com/narkisr/<bintray-repo>/foo-sandbox-0.0.1.tar.gz
-
S3 (Make sure to configure s3 section under ~/.configuration.rb):
$ opsk package
$ opsk deploy_s3 <bucket> <path>
deployed foo-sandbox-0.0.1.tar.gz to opsk-boxes/foo/foo-sandbox-0.0.1.tar.gz
Configuration.for('s3') {
access_key ''
secret_key ''
region ''
}
-
Scp (Make sure to configure scp section under ~/.configuration.rb):
$ opsk package
$ opsk deploy_scp bar
deployed foo-sandbox-0.0.1.tar.gz to foo@opsk-boxes:/var/boxes
Configuration.for('scp') {
bar {
host 'opsk-boxes'
user 'foo'
dest '/var/boxes'
# optional
port 2222
}
}