Jisota
Jisota is a simple provisioning tool meant for smaller projects.
Provisioning, in this context, is the act of turning an empty server into a working machine tailored to your needs.
Installation
Add this line to your application's Gemfile:
gem 'jisota', require: false
And then execute:
$ bundle
Or install it yourself as:
$ gem install jisota
Introduction
A simple example of a Jisota script:
# config/provision.rb (Or whatever you want to call this file)
require 'jisota'
config = Jisota.config do
role :app do
ruby version: "2.1.1"
nginx config_file: "path/to/nginx.conf"
end
server "mydomain.com", user: "john_doe", roles: :app
end
Jisota.run(config)
Run the script with the ruby executable:
$ ruby config/provision.rb
Defining a package
Inside a Jisota.config
block, use the package
method to define a package.
Example:
Jisota.config do
package :essentials do
description "Installs important stuff"
run do
apt :curl, :vim, :git
end
end
end
In this simple example we define a package with the name :essentials
. It has
a description and runs another package, :apt
, that it calls with the arguments
:curl, :vim, :git
The DSL you can use inside a package include:
description
: Will provide a description for the package.param
: Specify one or more named parameters for the package. See more in the params section below.run(&block)
: This block will be called when the package is executed.verify(&block)
: If this block exits with code 0, the run block will not be executed
Inside a run-block, packages can be called by their name, somewhat like a Ruby
method. See the apt
example above.
Defining packages to be used in more than one project
Defining packages with Jisota.config
as above will only add the package to
the current configuration. To make packages global they need to be in the
global package manager. Simply use the Jisota.global_config
instead:
Jisota.global_config do
package :ruby do
description "Installs ruby from source"
...
end
end
This will make the package accessable from all configurations. If a local package has the same name, the local package is used.
All build-in packages are defined this way.
Defining params for a package
Params for a package are defined with the param
DSL method inside a
package
-block. Params are named:
package :my_package do
param :foo
param :bar
...
end
This package can be called either with named parameters or with sorted parameters. The following calls are all equivalent:
my_package 42, "Baz"
my_package 42, bar: "Baz"
my_package foo: 42, bar: "Baz"
my_package bar: "Baz", foo: 42
Param options
Params can have the following options:
default
: Sets a default value, if no value is passed to that parameterrequired
: Validates that the parameter will have a valuesplat
: Will assign all the following unnamed arguments to this parameter as an array
Example:
package :apt do
param :packages, splat: true
param :command, default: "sudo apt-get install :package"
run do
cmd command.gsub(/:package/, packages.join(' '))
end
end
# And then call params inside another script block:
run do
apt :vim, :git
apt :vim, :git, command: "sudo apt-get install -y :package"
end
Atomic script operations
All packages will eventually boil down to these few atomic operations, which can be called inside a script block:
cmd
Will run a script on the server. Example:
cmd "apt-get install foo"
upload
Uploads the file to the server. Example:
upload from: "path/to/nginx.conf", to: "/etc/nginx.conf"
Complete list of build-in packages
ruby
description "Installs ruby from source"
param :version, required: true
param :tmp_dir, default: "~/tmp"
apt
description "Installs packages with apt-get"
param :packages, required: true, splat: true
More packages?
Jisota is a young gem. Please contribute with any packages that you think others could benifit from.
To DSL or not to DSL
The DSL provided by Jisota is just a layer of abstraction. The entire library can easily be used without the DSL. This could be useful if you need to e.g. dynamically build a configuration.
Example:
my_package = Jisota::Package.new(:stuff)
my_package.params << Jisota::Param.new(:foo, default: 42)
config = Jisota::Configuration.new
config.packages << my_package
is equivalent to:
config = Jisota.config do
package :stuff do
param :foo, default: 42
end
end
Full example
An example using most of the features of Jisota:
require 'jisota'
config = Jisota.config do
package :essentials do
description "Install essentials"
param :extra_packages, splat: true
run do
packages = %w[git vim curl]
packages += extra_packages
cmd "sudo apt-get install #{packages.join(" ")}"
end
end
package :postgres do
description "Installs postgres"
run do
cmd "some command sequence to install postgres"
end
end
package :nginx do
description "Install nginx"
param :config_file, required: true
run do
cmd "sudo apt get install nginx"
upload from: config_file, to: /etc/nginx.conf
end
end
role :app do
essentials "libfoo"
ruby version: "2.1.1"
nginx
end
role :db do
essentials
postgres
end
server "myapp.com", user: "deploy", roles: :app
server "staging.myapp.com", user: "deploy", roles: :app
server "db.myapp.com", user: "deploy", roles: :db
server "standby.myapp.com", user: "deploy", roles: [:app, :db]
end
Jisota.run(config)
Contributing
Any pull requests, suggestions, bug reports and feedback are most welcome :)
- Fork it ( http://github.com/lasseebert/jisota/fork )
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request