lib/jamie.rb in jamie-0.1.0.alpha17 vs lib/jamie.rb in jamie-0.1.0.alpha18
- old
+ new
@@ -1,6 +1,22 @@
# -*- encoding: utf-8 -*-
+#
+# Author:: Fletcher Nichol (<fnichol@nichol.ca>)
+#
+# Copyright (C) 2012, Fletcher Nichol
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
require 'base64'
require 'delegate'
require 'digest'
require 'erb'
@@ -27,10 +43,12 @@
@source_root ||= Pathname.new(File.expand_path('../../', __FILE__))
end
# Base configuration class for Jamie. This class exposes configuration such
# as the location of the Jamie YAML file, instances, log_levels, etc.
+ #
+ # @author Fletcher Nichol <fnichol@nichol.ca>
class Config
attr_writer :yaml_file
attr_writer :platforms
attr_writer :suites
@@ -95,10 +113,12 @@
end
# Delegate class which adds the ability to find single and multiple
# objects by their #name in an Array. Hey, it's better than monkey-patching
# Array, right?
+ #
+ # @author Fletcher Nichol <fnichol@nichol.ca>
class Collection < SimpleDelegator
# Returns a single object by its name, or nil if none are found.
#
# @param name [String] name of object
@@ -139,10 +159,11 @@
Suite.new(hash.rmerge(path_hash))
end
def new_platform(hash)
mpc = merge_platform_config(hash)
+ mpc['driver_config'] ||= Hash.new
mpc['driver_config']['jamie_root'] = File.dirname(yaml_file)
mpc['driver'] = new_driver(mpc['driver_plugin'], mpc['driver_config'])
Platform.new(mpc)
end
@@ -218,10 +239,12 @@
end
end
# A Chef run_list and attribute hash that will be used in a convergence
# integration.
+ #
+ # @author Fletcher Nichol <fnichol@nichol.ca>
class Suite
# @return [String] logical name of this suite
attr_reader :name
@@ -259,18 +282,20 @@
private
def validate_options(opts)
%w(name run_list).each do |k|
- raise ArgumentError, "Attribute '#{attr}' is required." if opts[k].nil?
+ raise ArgumentError, "Attribute '#{k}' is required." if opts[k].nil?
end
end
end
# A target operating system environment in which convergence integration
# will take place. This may represent a specific operating system, version,
# and machine architecture.
+ #
+ # @author Fletcher Nichol <fnichol@nichol.ca>
class Platform
# @return [String] logical name of this platform
attr_reader :name
@@ -305,18 +330,20 @@
private
def validate_options(opts)
%w(name driver).each do |k|
- raise ArgumentError, "Attribute '#{attr}' is required." if opts[k].nil?
+ raise ArgumentError, "Attribute '#{k}' is required." if opts[k].nil?
end
end
end
# An instance of a suite running on a platform. A created instance may be a
# local virtual machine, cloud instance, container, or even a bare metal
# server, which is determined by the platform's driver.
+ #
+ # @author Fletcher Nichol <fnichol@nichol.ca>
class Instance
# @return [Suite] the test suite configuration
attr_reader :suite
@@ -329,10 +356,12 @@
# Creates a new instance, given a suite and a platform.
#
# @param suite [Suite] a suite
# @param platform [Platform] a platform
def initialize(suite, platform)
+ validate_options(suite, platform)
+
@suite = suite
@platform = platform
@jr = Jr.new(@suite.name)
end
@@ -438,10 +467,15 @@
destroy if destroy_mode == :always
end
private
+ def validate_options(suite, platform)
+ raise ArgumentError, "Attribute 'suite' is required." if suite.nil?
+ raise ArgumentError, "Attribute 'platform' is required." if platform.nil?
+ end
+
def transition_to(desired)
FSM.actions(last_action, desired).each do |transition|
send("#{transition}_action")
end
end
@@ -515,10 +549,12 @@
load_state['last_action']
end
# The simplest finite state machine pseudo-implementation needed to manage
# an Instance.
+ #
+ # @author Fletcher Nichol <fnichol@nichol.ca>
class FSM
# Returns an Array of all transitions to bring an Instance from its last
# reported transistioned state into the desired transitioned state.
#
@@ -553,10 +589,12 @@
end
# Command string generator to interface with Jamie Runner (jr). The
# commands that are generated are safe to pass to an SSH command or as an
# unix command argument (escaped in single quotes).
+ #
+ # @author Fletcher Nichol <fnichol@nichol.ca>
class Jr
# Constructs a new jr command generator, given a suite name.
#
# @param [String] suite_name name of suite on which to operate
@@ -709,10 +747,12 @@
end
end
# Mixin that wraps a command shell out invocation, providing a #run_command
# method.
+ #
+ # @author Fletcher Nichol <fnichol@nichol.ca>
module ShellOut
# Wrapped exception for any interally raised shell out commands.
class ShellCommandFailed < StandardError ; end
@@ -762,10 +802,12 @@
end
# Base class for a driver. A driver is responsible for carrying out the
# lifecycle activities of an instance, such as creating, converging, and
# destroying an instance.
+ #
+ # @author Fletcher Nichol <fnichol@nichol.ca>
class Base
include ShellOut
def initialize(config)
@@ -840,10 +882,12 @@
# Base class for a driver that uses SSH to communication with an instance.
# A subclass must implement the following methods:
# * #create(instance, state)
# * #destroy(instance, state)
+ #
+ # @author Fletcher Nichol <fnichol@nichol.ca>
class SSHBase < Base
def create(instance, state)
raise NotImplementedError, "#create must be implemented by subclass."
end
@@ -971,9 +1015,11 @@
end
end
# Uploads Chef asset files such as dna.json, data bags, and cookbooks to an
# instance over SSH.
+ #
+ # @author Fletcher Nichol <fnichol@nichol.ca>
class ChefDataUploader
include ShellOut
def initialize(instance, ssh_args, jamie_root, chef_home)