Project

rouster

0.05
No commit activity in last 3 years
No release in over 3 years
Rouster allows you to programmatically control and interact with your existing Vagrant virtual machines
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

>= 0
~> 2.0

Runtime

>= 0
~> 1.1.9
>= 0
 Project Readme

Rouster

build status Gem Version

Rouster.is_a?('abstraction layer for controlling Vagrant virtual machines')
=> true

Rouster was conceived as the missing piece needed to functionally test Puppet manifests: while RSpec is nice (and much faster), compiling a catalog and applying it are 2 distinct operations.

app = Rouster.new(:name => 'app' )
app.up()

p app.run('/sbin/service puppet once -t', 2)
# or p app.run_puppet('master', { :expected_exitcode => 2}), if you've required 'rouster/puppet'

app.destroy()

The first implementation of Rouster was in Perl, called Salesforce::Vagrant. Salesforce::Vagrant is functional, but new functionality may or may not be ported back.

Requirements

  • Ruby, version 2.1+
  • Vagrant, version 1.0.5+
  • Gems
    • json
    • log4r
    • net-scp
    • net-ssh
    • fog (only if using AWS or OpenStack)

Note: Rouster should work exactly the same on Windows as it does on *nix and OSX (minus rouster/deltas.rb functionality, at least currently), but no real testing has been done to confirm this. Please file issues as appropriate.

From-source local usage (latest)

git clone https://github.com/chorankates/rouster.git
cd rouster
bundle install # use :aws to pull in fog
...
irb(main):001:0> require './path_helper.rb'
=> true
irb(main):002:0> require 'rouster'
=> true

From-source installation (latest)

git clone https://github.com/chorankates/rouster.git
cd rouster
rake buildgem
gem install rouster-<version>.gem
...
irb(main):001:0> require 'rouster'
=> true

pre-built gem installation (stable)

gem install rouster

Using Rouster

Rouster supports many of the vagrant faces:

  • destroy()
  • suspend()
  • status()
  • up()

All Rouster workers also support:

  • get()
  • put()
  • rebuild()
  • restart()
  • run()

And depending on which pieces of rouster you 'require':

  • rouster/deltas

    • get_groups()
    • get_packages()
    • get_ports()
    • get_services()
    • get_users()
  • rouster/puppet

    • facter()
    • get_catalog()
    • get_puppet_errors()
    • get_puppet_notices()
    • parse_catalog()
    • remove_existing_certs()
    • run_puppet()
  • rouster/testing

    • validate_file()
    • validate_group()
    • validate_package()
    • validate_service()
    • validate_user()
  • rouster/tests

    • is_dir?()
    • is_executable?()
    • is_file?()
    • is_group?()
    • is_in_file?()
    • is_in_path?()
    • is_package?()
    • is_port_active?()
    • is_port_open?()
    • is_process_running?())
    • is_readable?()
    • is_service?()
    • is_service_running?()
    • is_user?()
    • is_user_in_group?()
    • is_writeable?()

These additional methods are added to the Rouster object via class extension.

basic instantiation and usage

require 'rouster'

# the value for the 'name' attribute should be a name shown when you execute `vagrant status`
app = Rouster.new(:name => 'app')

# equivalent to `vagrant up app`
app.up()

# STD(OUT|ERR) of this is available in app.get_output()
app.run('cat /etc/hosts')
app.put('new-foo', '/tmp/foo')
app.get('/tmp/foo')

app.destroy()

advanced instantiation (passthroughs!)

detailed options in examples/passthrough.rb, examples/aws.rb and examples/openstack.rb

since Rouster only requires an SSH connection to control a machine, why stop at Vagrant?

require 'rouster'
require 'rouster/plugins/aws'
require 'rouster/plugins/openstack'

# control the machine rouster itself is running on
local = Rouster.new(:name => 'local', :passthrough => { :type => :local } }

# control a remote machine
remote = Rouster.new(
  :name => 'remote',
  :passthrough => {
    :type => :remote,
    :host => 'foo.bar.com',
    :user => 'keanu',
    :key  => '/path/to/private/key',
  }

  :sudo => true, # false by default, enabling requires that sshd is not enforcing 'requiretty'
)

# control a running EC2 instance
aws_already_running = Rouster.new(
  :name => 'cloudy',
  :passthrough => {
    :type     => :aws,
    :instance => 'your-instance-id',
    :keypair  => 'your-keypair-name',
  }
)

# start and control an EC2 instance
aws_start_me_up = Rouster.new(
  :name        => 'bgates',
  :passthrough => {
    :type            => :aws,
    :ami             => 'your-ami-id',
    :security_groups => 'your-security-groups',
    :key_id          => 'your-aws-key-id',     # defaults to ${AWS_ACCESS_KEY_ID}
    :secret_key      => 'your-aws-secret-key', # defaults to ${AWS_SECRET_ACCESS_KEY}
  }
)

# create a remote OpenStack instance
ostack = Rouster.new(
  :name      => 'ostack-testing',
  :passthrough => {
    :type                => :openstack,
    :openstack_auth_url  => 'http://hostname.domain.com:5000/v2.0/tokens',
    :openstack_username  => 'some_console_user',
    :openstack_tenant    => 'tenant_id',
    :user                => 'some_ssh_userid', 
    :keypair             => 'keypair_name',
    :image_ref           => 'c0340afb-577d-4db6-1234-aebdd6d1838f',
    :flavor_ref          => '547d9af5-096c-44a3-1234-7d23162556b8',
    :openstack_api_key   => 'some_api_key',
    :key                 => '/path/to/private/key.pem',
  },
  :sudo => true, # false by default, enabling requires that sshd is not enforcing 'requiretty'
)

# control a running OpenStack instance
openstack_already_running = Rouster.new(
  :name      => 'ostack-copy',
  :passthrough => {
    :type                => :openstack,
    :openstack_auth_url  => 'http://hostname.domain.com:5000/v2.0/tokens',
    :openstack_username  => 'some_console_user',
    :openstack_tenant    => 'tenant_id',
    :user                => 'ssh_user',
    :keypair             => 'keypair_name',
    :instance            => 'your-instance-id',
  },
)

functional puppet test

require 'rouster'
require 'rouster/puppet'
require 'test/unit'

class TestPuppetRun < Test::Unit::TestCase

  def setup
    @ppm = Rouster.new(:name => 'ppm', :verbose => 4)
    @app = Rouster.new(:name => 'app')
  end

  def test_it

    workers = [@ppm, @app]

    workers.each do |w|
      # tear them down and build back up for clean run
      w.destroy()
      w.up()

      #res = w.run('puppet agent -t --environment development', 2)
      assert_raises_nothing do
        res = w.run_puppet('master', { :expected_exitcode => 2 })
      end
      assert_match(/Finished catalog/, res, "output contains 'Finished catalog'")
    end
  end

  def teardown
    @ppm.destroy()
    @app.destroy()
  end

end

Base Methods

irb(main):001:0> require './path_helper.rb'
=> true
irb(main):002:0> require 'rouster'
=> true
irb(main):003:0> pp (Rouster.new(:name => 'app').methods - Object.methods).sort
=> [
[:_run,
 :cache,
 :cache_timeout,
 :check_key_permissions,
 :connect_ssh_tunnel,
 :deltas,
 :destroy,
 :dir,
 :dirs,
 :disconnect_ssh_tunnel,
 :exitcode,
 :facts,
 :facts=,
 :file,
 :files,
 :generate_unique_mac,
 :get,
 :get_crontab,
 :get_groups,
 :get_output,
 :get_packages,
 :get_ports,
 :get_services,
 :get_ssh_info,
 :get_users,
 :halt,
 :is_available_via_ssh?,
 :is_dir?,
 :is_executable?,
 :is_file?,
 :is_group?,
 :is_in_file?,
 :is_in_path?,
 :is_package?,
 :is_passthrough?,
 :is_port_active?,
 :is_port_open?,
 :is_process_running?,
 :is_readable?,
 :is_service?,
 :is_service_running?,
 :is_symlink?,
 :is_user?,
 :is_user_in_group?,
 :is_vagrant_running?,
 :is_writeable?,
 :logger,
 :os_type,
 :output,
 :package,
 :parse_ls_string,
 :passthrough,
 :put,
 :rebuild,
 :restart,
 :retries,
 :run,
 :sandbox_available?,
 :sandbox_commit,
 :sandbox_off,
 :sandbox_on,
 :sandbox_rollback,
 :sshkey,
 :status,
 :suspend,
 :traverse_up,
 :unittest,
 :up,
 :uses_sudo?,
 :vagrant,
 :vagrantbinary,
 :vagrantfile]
]

AWS methods

irb(main):001:0> require './path_helper.rb'
=> true
irb(main):002:0> require 'rouster'
=> true
irb(main):003:0> require 'rouster/plugins/aws'
=> true
irb(main):004:0> pp (Rouster.new(:name => 'aws', :passthrough => { :type => :aws }).methods - Object.methods).sort
=> [
...
 :aws_bootstrap,
 :aws_connect,
 :aws_connect_to_elb,
 :aws_describe_instance,
 :aws_destroy,
 :aws_get_ami,
 :aws_get_hostname,
 :aws_get_instance,
 :aws_get_ip,
 :aws_get_metadata,
 :aws_get_url,
 :aws_get_userdata,
 :aws_status,
 :ec2,
 :elb,
 :elb_connect,
 :find_ssh_elb,
 :instance_data,
...
]

Openstack methods

[
  :ostack_connect,
  :ostack_describe_instance,
  :ostack_destroy,
  :ostack_get_instance_id,
  :ostack_get_ip,
  :ostack_status,
  :ostack_up
]