Ruby Doable Framework
About
This is a gem largely targeted and making the lives of DevOps / SysAdmin types easier. Whether it is installing complicated sets of software, writing maintenance scripts, or automating administrative tasks, Doable
aims to simplify these common tasks, as well as make them more reliable and robust.
The core set of values for this framework are:
- Extensibility
- Modularity
- Simplicity
- Concurrency
- Flexibility
- Reliability
- Remaining lightweight
These goals are largely achieved through a small set of core features, with nearly all functionality broken out into plugins that can be enabled as required.
Building
While it is recommended to simply install via a normal rubygems search via gem install doable
(or adding gem "doable"
to your Gemfile), you can build and install the gem yourself. This can be done like so:
#!bash
# need Mercurial to clone the repo... or download it from https://bitbucket.org/jgnagy/doable/get/tip.zip
hg clone https://bitbucket.org/jgnagy/doable
cd doable
# highly recommend using RVM here, and Ruby 2.x or above
gem build doable.gemspec
# install what you just built
gem install ./doable-*.gem
Sometimes you might get lucky and there's a semi-recent version of the pre-built gem available on bitbucket here.
Usage
Require the right gem(s):
#!ruby
require 'doable'
To create a simple job, define a plan:
#!ruby
job = Doable::Job.plan do |j|
j.before { log "Starting my awesome job" }
j.step { # do some stuff here }
j.attempt { # try to do some other stuff here }
j.after { log "Looks like we're all set" }
end
job.run # executes our job
This job is obviously pretty boring, but it shows some of the basics. Now let's continue and include some additional helpers in a new, more complex job:
#!ruby
require 'doable/helpers/password'
class JobWithPasswords < Doable::Job
include Doable::Helpers::Password
end
job2 = JobWithPasswords.plan do |j|
j.before { log "Here's a password for you..." }
j.step { puts "Password: " + generate_password(16) }
end
job2.run
After this job runs, you should see output that looks something like:
[2015/01/29 00:10:36] Here's a password for you...
Password: ZwyIVH8LjHGYYzDX
[2015/01/29 00:10:36] All Job steps completed successfully!
Let's try something more realistic. Say the goal is to:
- check to make sure we have enough space to do things
- add a user (unless they already exist)
- unpack some software
- run it as our new user
Here is an example job:
#!ruby
require 'doable/helpers/linux'
class InstallCoolSoftware < Doable::Job
include Doable::Helpers::Linux
end
job3 = InstallCoolSoftware.plan do |j|
# make sure we have 500MB of space
j.before {
@app_dir = "/opt/coolsoft/server"
check_disk_space @app_dir, (500 * 1024 * 1024)
}
j.step {
@user = "cooluser"
find_or_create_user @user, File.dirname(@app_dir)
}
j.step {
find_or_create_directory @app_dir
FileUtils.cd(@app_dir) do
tee "tar -xf /opt/media/files/coolsoft-server-1.2.3.tgz --strip=1"
end
chown @user, @user, @app_dir, :recursive => true
}.rollback {
remove(@app_dir)
}
j.step {
run_as_user @user, File.join(@app_dir, "/bin", "start.sh")
}
end
job3.run
Hopefully this demonstrates how to get access to additional helper methods. Also, you may have noticed the rollback
method added to the step for uncompressing the tarball. If things go wrong, rollbacks can be run to revert changes. To do so, just do this:
job3.rollback!
The Job
instance also has many other methods available for accessing its internals.
RubyDoc
The latest, published documentation can be seen on RubyDoc
License
Doable is distributed under the MIT License.
Contributing
I welcome pull-requests. I may or may not use your code, but I encourage the growth of others too. If this project inspires you to contribute, feel free to fork my code and submit a pull request. In most cases, I'll probably recommend you package additions in an extension gem rather than including new files, etc, directly into the core codebase.