daptiv-chef-ci 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +2 -0
- data/Gemfile +8 -0
- data/README.md +2 -0
- data/Rakefile +25 -0
- data/daptiv-chef-ci.gemspec +58 -0
- data/lib/daptiv-chef-ci/logger.rb +33 -0
- data/lib/daptiv-chef-ci/shell.rb +54 -0
- data/lib/daptiv-chef-ci/templates/Vagrantfile.erb +41 -0
- data/lib/daptiv-chef-ci/vagrant_driver.rb +95 -0
- data/lib/daptiv-chef-ci/vagrant_task.rb +115 -0
- data/lib/daptiv-chef-ci/virtualbox_driver.rb +48 -0
- data/spec/daptiv-chef-ci/logger_spec.rb +41 -0
- data/spec/daptiv-chef-ci/shell_spec.rb +36 -0
- data/spec/daptiv-chef-ci/vagrant_driver_spec.rb +93 -0
- data/spec/daptiv-chef-ci/virtualbox_driver_spec.rb +32 -0
- metadata +215 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
require 'rspec/core/rake_task'
|
4
|
+
|
5
|
+
# Change to the directory of this file.
|
6
|
+
Dir.chdir(File.expand_path("../", __FILE__))
|
7
|
+
|
8
|
+
# For gem creation and bundling
|
9
|
+
require "bundler/gem_tasks"
|
10
|
+
|
11
|
+
# Run the unit test suite
|
12
|
+
RSpec::Core::RakeTask.new do |task|
|
13
|
+
task.pattern = "spec/**/*_spec.rb"
|
14
|
+
task.rspec_opts = [ '--color', '-f documentation' ]
|
15
|
+
task.rspec_opts << '-tunit'
|
16
|
+
end
|
17
|
+
|
18
|
+
# Default task is to run tests
|
19
|
+
task :default => "spec"
|
20
|
+
|
21
|
+
desc 'Run foodcritic with default rule set.'
|
22
|
+
task :path do
|
23
|
+
puts ENV['PATH']
|
24
|
+
end
|
25
|
+
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |gem|
|
4
|
+
gem.authors = ["Shawn Neal"]
|
5
|
+
gem.email = ["sneal@daptiv.com"]
|
6
|
+
gem.description = %q{Vagrant automation for CI}
|
7
|
+
gem.summary = %q{A small gem to reduce Rake duplication}
|
8
|
+
gem.homepage = ""
|
9
|
+
|
10
|
+
# The following block of code determines the files that should be included
|
11
|
+
# in the gem. It does this by reading all the files in the directory where
|
12
|
+
# this gemspec is, and parsing out the ignored files from the gitignore.
|
13
|
+
# Note that the entire gitignore(5) syntax is not supported, specifically
|
14
|
+
# the "!" syntax, but it should mostly work correctly.
|
15
|
+
root_path = File.dirname(__FILE__)
|
16
|
+
all_files = Dir.chdir(root_path) { Dir.glob("**/{*,.*}") }
|
17
|
+
all_files.reject! { |file| [".", ".."].include?(File.basename(file)) }
|
18
|
+
gitignore_path = File.join(root_path, ".gitignore")
|
19
|
+
gitignore = File.readlines(gitignore_path)
|
20
|
+
gitignore.map! { |line| line.chomp.strip }
|
21
|
+
gitignore.reject! { |line| line.empty? || line =~ /^(#|!)/ }
|
22
|
+
|
23
|
+
unignored_files = all_files.reject do |file|
|
24
|
+
# Ignore any directories, the gemspec only cares about files
|
25
|
+
next true if File.directory?(file)
|
26
|
+
|
27
|
+
# Ignore any paths that match anything in the gitignore. We do
|
28
|
+
# two tests here:
|
29
|
+
#
|
30
|
+
# - First, test to see if the entire path matches the gitignore.
|
31
|
+
# - Second, match if the basename does, this makes it so that things
|
32
|
+
# like '.DS_Store' will match sub-directories too (same behavior
|
33
|
+
# as git).
|
34
|
+
#
|
35
|
+
gitignore.any? do |ignore|
|
36
|
+
File.fnmatch(ignore, file, File::FNM_PATHNAME) ||
|
37
|
+
File.fnmatch(ignore, File.basename(file), File::FNM_PATHNAME)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
gem.files = unignored_files
|
42
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
43
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
44
|
+
gem.name = "daptiv-chef-ci"
|
45
|
+
gem.require_paths = ["lib"]
|
46
|
+
gem.version = '0.0.1'
|
47
|
+
|
48
|
+
gem.add_runtime_dependency "mixlib-shellout", "~> 1.2.0"
|
49
|
+
gem.add_runtime_dependency "log4r", "~> 1.1.10"
|
50
|
+
gem.add_runtime_dependency "erubis", "~> 2.7.0"
|
51
|
+
|
52
|
+
gem.add_development_dependency "rake"
|
53
|
+
gem.add_development_dependency "rspec-core", "~> 2.12.2"
|
54
|
+
gem.add_development_dependency "rspec-expectations", "~> 2.12.1"
|
55
|
+
gem.add_development_dependency "rspec-mocks", "~> 2.12.1"
|
56
|
+
gem.add_development_dependency "simplecov"
|
57
|
+
gem.add_development_dependency "mocha", "~> 0.14.0"
|
58
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module DaptivChefCI
|
2
|
+
class Logger
|
3
|
+
|
4
|
+
# Initializes and enables logging to the given environments level
|
5
|
+
# By default logging only occurs at ERROR level or higher.
|
6
|
+
# Set CHEF_CI_LOG env var to change logging levels
|
7
|
+
def self.init()
|
8
|
+
require 'log4r'
|
9
|
+
|
10
|
+
# Set the logging level on all "chef-ci" namespaced
|
11
|
+
# logs as long as we have a valid level.
|
12
|
+
logger = Log4r::Logger.new("daptiv_chef_ci")
|
13
|
+
logger.outputters = Log4r::Outputter.stderr
|
14
|
+
logger.level = log_level()
|
15
|
+
logger = nil
|
16
|
+
end
|
17
|
+
|
18
|
+
# LogLevels = ['DEBUG', 'INFO', 'WARN', 'ERROR', 'FATAL']
|
19
|
+
# DEBUG = 1
|
20
|
+
# INFO = 2
|
21
|
+
# WARN = 3
|
22
|
+
# ERROR = 4
|
23
|
+
# FATAL = 5
|
24
|
+
def self.log_level()
|
25
|
+
level = ENV['CHEF_CI_LOG'].upcase().to_s()
|
26
|
+
level_i = Log4r::Log4rConfig::LogLevels.index(level)
|
27
|
+
level_i + 1
|
28
|
+
rescue
|
29
|
+
return 4 # error
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'log4r'
|
2
|
+
require 'mixlib/shellout'
|
3
|
+
require 'bundler'
|
4
|
+
|
5
|
+
module DaptivChefCI
|
6
|
+
class Shell
|
7
|
+
|
8
|
+
def initialize()
|
9
|
+
@logger = Log4r::Logger.new("daptiv_chef_ci::shell")
|
10
|
+
end
|
11
|
+
|
12
|
+
# Executes the specified shell command and returns the stdout.
|
13
|
+
#
|
14
|
+
# This method ensure that any invoked command use the same PATH environment
|
15
|
+
# that the user has outside Ruby/Bundler.
|
16
|
+
#
|
17
|
+
# @param [String] The command line to execute
|
18
|
+
# @return [Array] Each entry represents a line from the stdout
|
19
|
+
def exec_cmd(command)
|
20
|
+
@logger.info("Calling command [#{command}]")
|
21
|
+
path_at_start = ENV['PATH']
|
22
|
+
begin
|
23
|
+
ENV['PATH'] = path_without_gem_dir()
|
24
|
+
@logger.debug("Temporarily setting PATH: #{ENV['PATH']}")
|
25
|
+
out = `#{command}`
|
26
|
+
@logger.debug(out)
|
27
|
+
out.split("\n")
|
28
|
+
ensure
|
29
|
+
@logger.debug("Resetting PATH: #{path_at_start}")
|
30
|
+
ENV['PATH'] = path_at_start
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Returns the PATH environment variable as it was before Bundler prepended
|
35
|
+
# the system gem directory to it.
|
36
|
+
#
|
37
|
+
# This can happen if the user has invoked "require 'bundler/setup'" somewhere,
|
38
|
+
# like in this gems Rakefile.
|
39
|
+
#
|
40
|
+
# This is needed because sometimes a user will have the Vagrant gem installed
|
41
|
+
# on their system and we don't want to use it, we should use the one that's in
|
42
|
+
# their PATH as if they invoked vagrant themselves (i.e. the installed version)
|
43
|
+
#
|
44
|
+
# @return [String] The ENV['PATH] without the Bundler system gem dir prepended
|
45
|
+
def path_without_gem_dir
|
46
|
+
paths = ENV['PATH'].split(':')
|
47
|
+
system_gem_dir = "#{Bundler.bundle_path}/bin"
|
48
|
+
@logger.debug("System gem dir: #{system_gem_dir}")
|
49
|
+
paths.delete_if { |p| p.downcase() == system_gem_dir.downcase() }
|
50
|
+
paths.join(':')
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# -*- mode: ruby -*-
|
2
|
+
# vi: set ft=ruby :
|
3
|
+
|
4
|
+
Vagrant.configure("2") do |config|
|
5
|
+
chef_repo_dir = '<%= chef_repo_dir %>'
|
6
|
+
|
7
|
+
config.berkshelf.enabled = true
|
8
|
+
|
9
|
+
config.vm.box = '<%= box_name %>'
|
10
|
+
<% if !box_url.nil? %>
|
11
|
+
config.vm.box_url = '<%= box_url %>'
|
12
|
+
<% end %>
|
13
|
+
|
14
|
+
<% if guest_os == :windows %>
|
15
|
+
config.vm.guest = :windows
|
16
|
+
|
17
|
+
config.windows.halt_timeout = 15
|
18
|
+
config.winrm.username = "vagrant"
|
19
|
+
config.winrm.password = "vagrant"
|
20
|
+
|
21
|
+
config.vm.network :forwarded_port, guest: 3389, host: 3389
|
22
|
+
config.vm.network :forwarded_port, guest: 5985, host: 5985
|
23
|
+
<% end %>
|
24
|
+
|
25
|
+
config.vm.provision :chef_solo do |chef|
|
26
|
+
chef.node_name = '<%= node_name %>'
|
27
|
+
chef.log_level = :info
|
28
|
+
chef.roles_path = File.join(chef_repo_dir, 'roles')
|
29
|
+
chef.data_bags_path = File.join(chef_repo_dir, 'data_bags')
|
30
|
+
chef.encrypted_data_bag_secret_key_path = '/etc/chef/encrypted_data_bag_secret'
|
31
|
+
chef.add_recipe 'minitest-handler'
|
32
|
+
<% run_list.each do |recipe| %>
|
33
|
+
chef.add_recipe '<%= recipe %>'
|
34
|
+
<% end %>
|
35
|
+
<% if !chef_json.nil? %>
|
36
|
+
chef.json = {
|
37
|
+
<%= chef_json %>
|
38
|
+
}
|
39
|
+
<% end %>
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'log4r'
|
2
|
+
require 'socket'
|
3
|
+
require 'erubis'
|
4
|
+
require_relative 'shell'
|
5
|
+
|
6
|
+
module DaptivChefCI
|
7
|
+
class VagrantDriver
|
8
|
+
|
9
|
+
# Constructs a new Vagrant management instance
|
10
|
+
#
|
11
|
+
# @param [Shell] The CLI
|
12
|
+
# @param [Hash] The options to pass to the Vagrantfile
|
13
|
+
#
|
14
|
+
# options[:guest_os] - defaults to :linux
|
15
|
+
# options[:chef_repo_dir] - The chef-repo root directory, defaults to ~/src/chef-repo
|
16
|
+
# options[:box_name] - defaults to 'Vagrant-hostname'
|
17
|
+
# options[:node_name] - The chef node name, defaults to 'Vagrant-hostname'
|
18
|
+
# options[:box_url] - URL to the box download location, this is optional.
|
19
|
+
# options[:run_list] - The Chef run list, defaults to empty.
|
20
|
+
# options[:chef_json] - Any additional Chef attributes in json format.
|
21
|
+
def initialize(shell, options)
|
22
|
+
@logger = Log4r::Logger.new("daptiv_chef_ci::vagrant")
|
23
|
+
@shell = shell
|
24
|
+
|
25
|
+
options[:guest_os] ||= :linux
|
26
|
+
options[:box_name] ||= "Vagrant-#{Socket.gethostname}"
|
27
|
+
options[:box_url] ||= nil
|
28
|
+
options[:node_name] ||= options[:box_name]
|
29
|
+
options[:run_list] ||= []
|
30
|
+
options[:chef_repo_dir] = "#{ENV['HOME']}/src/chef-repo"
|
31
|
+
options[:chef_json] ||= nil
|
32
|
+
@options = options
|
33
|
+
end
|
34
|
+
|
35
|
+
def create_vagrantfile()
|
36
|
+
@logger.debug('Creating Vagrantfile')
|
37
|
+
File.open('Vagrantfile', 'w') do |f|
|
38
|
+
f.write render_vagrantfile()
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def render_vagrantfile()
|
43
|
+
Erubis::Eruby.new(vagrantfile_erb()).result(@options)
|
44
|
+
end
|
45
|
+
|
46
|
+
def destroy()
|
47
|
+
@shell.exec_cmd('vagrant destroy -f')
|
48
|
+
end
|
49
|
+
|
50
|
+
def halt()
|
51
|
+
@shell.exec_cmd('vagrant halt')
|
52
|
+
end
|
53
|
+
|
54
|
+
def up()
|
55
|
+
@shell.exec_cmd('vagrant up')
|
56
|
+
end
|
57
|
+
|
58
|
+
def provision()
|
59
|
+
@shell.exec_cmd('vagrant provision')
|
60
|
+
end
|
61
|
+
|
62
|
+
def reload()
|
63
|
+
@shell.exec_cmd('vagrant reload')
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def vagrantfile_erb()
|
70
|
+
path = vagrantfile_erb_path()
|
71
|
+
@logger.info("Using #{path} to render Vangrantfile")
|
72
|
+
File.read(vagrantfile_erb_path())
|
73
|
+
end
|
74
|
+
|
75
|
+
def vagrantfile_erb_path()
|
76
|
+
erbs = [
|
77
|
+
File.join(Dir.pwd, 'Vagrantfile.erb'),
|
78
|
+
File.join(Dir.pwd, 'build/Vagrantfile.erb'),
|
79
|
+
File.expand_path('Vagrantfile.erb', template_dir())
|
80
|
+
]
|
81
|
+
|
82
|
+
erbs.each do |erb|
|
83
|
+
@logger.debug("Searching for #{erb}")
|
84
|
+
return erb if File.exists?(erb)
|
85
|
+
end
|
86
|
+
# This should never happen
|
87
|
+
raise 'Couldn\'t find a Vagrantfile.erb!'
|
88
|
+
end
|
89
|
+
|
90
|
+
def template_dir()
|
91
|
+
File.join(File.expand_path(File.dirname(__FILE__)), 'templates')
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/tasklib'
|
3
|
+
require_relative 'vagrant_driver'
|
4
|
+
require_relative 'virtualbox_driver'
|
5
|
+
require_relative 'shell'
|
6
|
+
require_relative 'logger'
|
7
|
+
|
8
|
+
begin
|
9
|
+
# Support Rake > 0.8.7
|
10
|
+
require 'rake/dsl_definition'
|
11
|
+
rescue LoadError
|
12
|
+
end
|
13
|
+
|
14
|
+
DaptivChefCI::Logger.init()
|
15
|
+
|
16
|
+
class Vagrant
|
17
|
+
|
18
|
+
# This class lets you define Rake tasks to drive Vagrant.
|
19
|
+
#
|
20
|
+
# @example Run the Python and NGinx cookbooks on a Linux guest
|
21
|
+
# Vagrant::RakeTask.new do |task|
|
22
|
+
# task.box_name = 'vagrant-FreeBSD'
|
23
|
+
# task.run_list = [ 'python', 'nginx' ]
|
24
|
+
# task.chef_repo_dir = '/Users/me/chef-repo'
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# @example Run the Python and NGinx cookbooks on a Windows guest
|
28
|
+
# Vagrant::RakeTask.new do |task|
|
29
|
+
# task.guest_os = :windows
|
30
|
+
# task.box_name = 'vagrant-windows-server-r2'
|
31
|
+
# task.box_url = 'http://example.com/boxes/vagrant-windows-server-r2.box'
|
32
|
+
# task.run_list = [ 'python', 'nginx' ]
|
33
|
+
# task.chef_repo_dir = '/Users/me/chef-repo'
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
class RakeTask < ::Rake::TaskLib
|
37
|
+
include ::Rake::DSL if defined? ::Rake::DSL
|
38
|
+
|
39
|
+
attr_accessor :guest_os
|
40
|
+
attr_accessor :box_url
|
41
|
+
attr_accessor :box_name
|
42
|
+
attr_accessor :run_list
|
43
|
+
attr_accessor :node_name
|
44
|
+
attr_accessor :chef_repo_dir
|
45
|
+
attr_accessor :chef_json
|
46
|
+
|
47
|
+
# @param [String] name The task name.
|
48
|
+
# @param [String] desc Description of the task.
|
49
|
+
def initialize(name = 'vagrant', desc = 'Daptiv Vagrant Tasks')
|
50
|
+
@name, @desc = name, desc
|
51
|
+
@guest_os = nil
|
52
|
+
@box_url = nil
|
53
|
+
@box_name = nil
|
54
|
+
@run_list = []
|
55
|
+
@node_name = nil
|
56
|
+
@chef_repo_dir = nil
|
57
|
+
@chef_json = nil
|
58
|
+
|
59
|
+
yield self if block_given?
|
60
|
+
|
61
|
+
define_task
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def define_task
|
68
|
+
desc @desc
|
69
|
+
task @name do
|
70
|
+
|
71
|
+
options = {
|
72
|
+
:guest_os => @guest_os,
|
73
|
+
:box_url => @box_url,
|
74
|
+
:box_name => @box_name,
|
75
|
+
:run_list => @run_list,
|
76
|
+
:node_name => @node_name,
|
77
|
+
:chef_repo_dir => @chef_repo_dir,
|
78
|
+
:chef_json => @chef_json }
|
79
|
+
|
80
|
+
shell = DaptivChefCI::Shell.new()
|
81
|
+
vagrant = DaptivChefCI::VagrantDriver.new(shell, options)
|
82
|
+
|
83
|
+
vagrant.create_vagrantfile()
|
84
|
+
|
85
|
+
begin
|
86
|
+
vagrant.destroy()
|
87
|
+
rescue SystemExit => ex
|
88
|
+
exit(ex.status)
|
89
|
+
rescue Exception => ex
|
90
|
+
print_err(ex)
|
91
|
+
end
|
92
|
+
|
93
|
+
begin
|
94
|
+
vagrant.up()
|
95
|
+
rescue SystemExit => ex
|
96
|
+
exit(ex.status)
|
97
|
+
rescue Exception => ex
|
98
|
+
print_err(ex)
|
99
|
+
exit(1)
|
100
|
+
ensure
|
101
|
+
vagrant.halt()
|
102
|
+
vagrant.destroy()
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def print_err(ex)
|
109
|
+
STDERR.puts("#{ex.message} (#{ex.class})")
|
110
|
+
STDERR.puts(ex.backtrace.join("\n"))
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'log4r'
|
2
|
+
require_relative 'shell'
|
3
|
+
|
4
|
+
module DaptivChefCI
|
5
|
+
class VirtualBoxDriver
|
6
|
+
|
7
|
+
def initialize(shell)
|
8
|
+
@logger = Log4r::Logger.new("daptiv_chef_ci::virtual_box")
|
9
|
+
@shell = shell
|
10
|
+
end
|
11
|
+
|
12
|
+
# Remove any running vms that have the same name as this box
|
13
|
+
def cleanup_vms(box_name)
|
14
|
+
list_all_running_vms().each do |vm|
|
15
|
+
if vm.include?(box_name)
|
16
|
+
machine_name = vm.split[0]
|
17
|
+
@logger.debug("Found matching VBox #{machine_name} - Running")
|
18
|
+
poweroff(machine_name)
|
19
|
+
unregister(machine_name)
|
20
|
+
else
|
21
|
+
@logger.debug("Found no matching VBox #{machine_name}")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
# Power off the named virtual box
|
30
|
+
def poweroff(machine_name)
|
31
|
+
@logger.info("Powering off VM: #{machine_name}")
|
32
|
+
@shell.exec_cmd("vboxmanage controlvm #{machine_name} poweroff")
|
33
|
+
end
|
34
|
+
|
35
|
+
# Unregister the virtual box. Must be powered off first.
|
36
|
+
def unregister(machine_name)
|
37
|
+
@logger.info("Unregistering VM: #{machine_name}")
|
38
|
+
@shell.exec_cmd("vboxmanage unregistervm #{machine_name}")
|
39
|
+
end
|
40
|
+
|
41
|
+
# Get a list of running vms
|
42
|
+
def list_all_running_vms()
|
43
|
+
@logger.info("List running VMs")
|
44
|
+
@shell.exec_cmd('vboxmanage list runningvms') || ''
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'mocha/api'
|
2
|
+
require 'daptiv-chef-ci/logger'
|
3
|
+
require 'log4r'
|
4
|
+
|
5
|
+
describe DaptivChefCI::Logger, :unit => true do
|
6
|
+
|
7
|
+
describe 'init' do
|
8
|
+
|
9
|
+
# get logging level before running any of these tests
|
10
|
+
before(:all) do
|
11
|
+
@chef_ci_log = ENV['CHEF_CI_LOG']
|
12
|
+
end
|
13
|
+
|
14
|
+
# reset logging back to starting state before this fixture
|
15
|
+
after(:all) do
|
16
|
+
ENV['CHEF_CI_LOG'] = @chef_ci_log
|
17
|
+
DaptivChefCI::Logger.init()
|
18
|
+
end
|
19
|
+
|
20
|
+
# reset logging back to default state before every test
|
21
|
+
before(:each) do
|
22
|
+
ENV['CHEF_CI_LOG'] = ''
|
23
|
+
DaptivChefCI::Logger.init()
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should initialize logging to error by default' do
|
27
|
+
DaptivChefCI::Logger.init()
|
28
|
+
logger = Log4r::Logger.new("daptiv_chef_ci::logger_spec")
|
29
|
+
expect(logger.level).to eq(4)
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should initialize logging to the specified level' do
|
33
|
+
ENV['CHEF_CI_LOG'] = 'DEBUG'
|
34
|
+
DaptivChefCI::Logger.init()
|
35
|
+
logger = Log4r::Logger.new("daptiv_chef_ci::logger_spec")
|
36
|
+
expect(logger.level).to eq(1)
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'mocha/api'
|
2
|
+
require 'daptiv-chef-ci/virtualbox_driver'
|
3
|
+
require 'daptiv-chef-ci/logger'
|
4
|
+
require 'bundler'
|
5
|
+
|
6
|
+
describe DaptivChefCI::Shell, :unit => true do
|
7
|
+
|
8
|
+
describe 'exec_cmd' do
|
9
|
+
|
10
|
+
it 'should split output by line' do
|
11
|
+
shell = DaptivChefCI::Shell.new()
|
12
|
+
out = shell.exec_cmd('ls -l')
|
13
|
+
expect(out.count).to be > 1
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should revert path when method returns' do
|
17
|
+
path_before = ENV['PATH']
|
18
|
+
shell = DaptivChefCI::Shell.new()
|
19
|
+
shell.exec_cmd('ls -l')
|
20
|
+
expect(ENV['PATH']).to eq(path_before)
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
describe 'path_without_gem_dir' do
|
26
|
+
|
27
|
+
it 'should not be prefixed by the system gem dir' do
|
28
|
+
shell = DaptivChefCI::Shell.new()
|
29
|
+
path = shell.path_without_gem_dir()
|
30
|
+
expect(path).not_to include(Bundler.bundle_path.to_s())
|
31
|
+
expect(ENV['PATH']).to include(path)
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'mocha/api'
|
2
|
+
require 'daptiv-chef-ci/vagrant_driver'
|
3
|
+
require 'daptiv-chef-ci/logger'
|
4
|
+
|
5
|
+
describe DaptivChefCI::VagrantDriver, :unit => true do
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
@shell = mock()
|
9
|
+
@options = {}
|
10
|
+
@vagrant = DaptivChefCI::VagrantDriver.new(@shell, @options)
|
11
|
+
end
|
12
|
+
|
13
|
+
describe 'render_vagrantfile' do
|
14
|
+
it 'should default chef-repo dir to ~/src/chef-repo' do
|
15
|
+
vagrantfile = @vagrant.render_vagrantfile()
|
16
|
+
expect(vagrantfile).to include("chef_repo_dir = '#{ENV['HOME']}/src/chef-repo'")
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should not include box url when not set' do
|
20
|
+
vagrantfile = @vagrant.render_vagrantfile()
|
21
|
+
expect(vagrantfile).not_to include("config.vm.box_url")
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should include box url when set' do
|
25
|
+
@options[:box_url] = 'http://example.com/boxes/freebsd.box'
|
26
|
+
vagrantfile = @vagrant.render_vagrantfile()
|
27
|
+
expect(vagrantfile).to include("config.vm.box_url = 'http://example.com/boxes/freebsd.box'")
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should include windows section when guest is set to windows' do
|
31
|
+
@options[:guest_os] = :windows
|
32
|
+
vagrantfile = @vagrant.render_vagrantfile()
|
33
|
+
expect(vagrantfile).to include('config.vm.guest = :windows')
|
34
|
+
expect(vagrantfile).to include('config.windows.halt_timeout = 15')
|
35
|
+
expect(vagrantfile).to include('config.winrm.username = "vagrant"')
|
36
|
+
expect(vagrantfile).to include('config.winrm.password = "vagrant"')
|
37
|
+
expect(vagrantfile).to include('config.vm.network :forwarded_port, guest: 5985, host: 5985')
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should expand runlist' do
|
41
|
+
@options[:run_list] = ['python', 'nginx']
|
42
|
+
vagrantfile = @vagrant.render_vagrantfile()
|
43
|
+
expect(vagrantfile).to include("chef.add_recipe 'python'")
|
44
|
+
expect(vagrantfile).to include("chef.add_recipe 'nginx'")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe 'destroy' do
|
49
|
+
it 'should force shutdown vagrant' do
|
50
|
+
@shell.expects(:exec_cmd).with do |cmd|
|
51
|
+
expect(cmd).to eq('vagrant destroy -f')
|
52
|
+
end
|
53
|
+
@vagrant.destroy()
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe 'halt' do
|
58
|
+
it 'should halt vagrant' do
|
59
|
+
@shell.expects(:exec_cmd).with do |cmd|
|
60
|
+
expect(cmd).to eq('vagrant halt')
|
61
|
+
end
|
62
|
+
@vagrant.halt()
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe 'up' do
|
67
|
+
it 'should up vagrant' do
|
68
|
+
@shell.expects(:exec_cmd).with do |cmd|
|
69
|
+
expect(cmd).to eq('vagrant up')
|
70
|
+
end
|
71
|
+
@vagrant.up()
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe 'provision' do
|
76
|
+
it 'should provision vagrant' do
|
77
|
+
@shell.expects(:exec_cmd).with do |cmd|
|
78
|
+
expect(cmd).to eq('vagrant provision')
|
79
|
+
end
|
80
|
+
@vagrant.provision()
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe 'reload' do
|
85
|
+
it 'should reload vagrant' do
|
86
|
+
@shell.expects(:exec_cmd).with do |cmd|
|
87
|
+
expect(cmd).to eq('vagrant reload')
|
88
|
+
end
|
89
|
+
@vagrant.reload()
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'mocha/api'
|
2
|
+
require 'daptiv-chef-ci/virtualbox_driver'
|
3
|
+
require 'daptiv-chef-ci/logger'
|
4
|
+
|
5
|
+
describe DaptivChefCI::VirtualBoxDriver, :unit => true do
|
6
|
+
|
7
|
+
describe 'cleanup_vms' do
|
8
|
+
it 'should poweroff and unregister all machines with a matching name' do
|
9
|
+
boxes = [
|
10
|
+
'"aspnet_1372120179" {b1937a1c-c6c4-4777-88d0-dfa9066fb126}',
|
11
|
+
'"aspnet_1379346156" {7bb1bbce-c6cc-47a2-9c51-57ede42e02b5}',
|
12
|
+
'"python_1372120178" {c1937a1c-c6c4-4777-88d0-dfa9066fb156}'
|
13
|
+
]
|
14
|
+
@shell = mock()
|
15
|
+
@vbox = DaptivChefCI::VirtualBoxDriver.new(@shell)
|
16
|
+
|
17
|
+
@shell.expects(:exec_cmd).with('vboxmanage list runningvms').returns(boxes)
|
18
|
+
|
19
|
+
@shell.expects(:exec_cmd).with('vboxmanage controlvm "aspnet_1372120179" poweroff').once()
|
20
|
+
@shell.expects(:exec_cmd).with('vboxmanage unregistervm "aspnet_1372120179"').once()
|
21
|
+
|
22
|
+
@shell.expects(:exec_cmd).with('vboxmanage controlvm "aspnet_1379346156" poweroff').once()
|
23
|
+
@shell.expects(:exec_cmd).with('vboxmanage unregistervm "aspnet_1379346156"').once()
|
24
|
+
|
25
|
+
@shell.expects(:exec_cmd).with('vboxmanage controlvm "python_1372120178" poweroff').never()
|
26
|
+
@shell.expects(:exec_cmd).with('vboxmanage unregistervm "python_1372120178"').never()
|
27
|
+
|
28
|
+
@vbox.cleanup_vms('aspnet')
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
metadata
ADDED
@@ -0,0 +1,215 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: daptiv-chef-ci
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Shawn Neal
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-10-21 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: mixlib-shellout
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.2.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 1.2.0
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: log4r
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 1.1.10
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 1.1.10
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: erubis
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 2.7.0
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 2.7.0
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rake
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: rspec-core
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ~>
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: 2.12.2
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 2.12.2
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: rspec-expectations
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ~>
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: 2.12.1
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 2.12.1
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: rspec-mocks
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ~>
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 2.12.1
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ~>
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: 2.12.1
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: simplecov
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ! '>='
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
type: :development
|
135
|
+
prerelease: false
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - ! '>='
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0'
|
142
|
+
- !ruby/object:Gem::Dependency
|
143
|
+
name: mocha
|
144
|
+
requirement: !ruby/object:Gem::Requirement
|
145
|
+
none: false
|
146
|
+
requirements:
|
147
|
+
- - ~>
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: 0.14.0
|
150
|
+
type: :development
|
151
|
+
prerelease: false
|
152
|
+
version_requirements: !ruby/object:Gem::Requirement
|
153
|
+
none: false
|
154
|
+
requirements:
|
155
|
+
- - ~>
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: 0.14.0
|
158
|
+
description: Vagrant automation for CI
|
159
|
+
email:
|
160
|
+
- sneal@daptiv.com
|
161
|
+
executables: []
|
162
|
+
extensions: []
|
163
|
+
extra_rdoc_files: []
|
164
|
+
files:
|
165
|
+
- daptiv-chef-ci.gemspec
|
166
|
+
- Gemfile
|
167
|
+
- lib/daptiv-chef-ci/logger.rb
|
168
|
+
- lib/daptiv-chef-ci/shell.rb
|
169
|
+
- lib/daptiv-chef-ci/templates/Vagrantfile.erb
|
170
|
+
- lib/daptiv-chef-ci/vagrant_driver.rb
|
171
|
+
- lib/daptiv-chef-ci/vagrant_task.rb
|
172
|
+
- lib/daptiv-chef-ci/virtualbox_driver.rb
|
173
|
+
- pkg/daptiv-chef-ci-0.0.1.gem
|
174
|
+
- Rakefile
|
175
|
+
- README.md
|
176
|
+
- spec/daptiv-chef-ci/logger_spec.rb
|
177
|
+
- spec/daptiv-chef-ci/shell_spec.rb
|
178
|
+
- spec/daptiv-chef-ci/vagrant_driver_spec.rb
|
179
|
+
- spec/daptiv-chef-ci/virtualbox_driver_spec.rb
|
180
|
+
- .gitignore
|
181
|
+
homepage: ''
|
182
|
+
licenses: []
|
183
|
+
post_install_message:
|
184
|
+
rdoc_options: []
|
185
|
+
require_paths:
|
186
|
+
- lib
|
187
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
188
|
+
none: false
|
189
|
+
requirements:
|
190
|
+
- - ! '>='
|
191
|
+
- !ruby/object:Gem::Version
|
192
|
+
version: '0'
|
193
|
+
segments:
|
194
|
+
- 0
|
195
|
+
hash: -2620113271490867274
|
196
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
197
|
+
none: false
|
198
|
+
requirements:
|
199
|
+
- - ! '>='
|
200
|
+
- !ruby/object:Gem::Version
|
201
|
+
version: '0'
|
202
|
+
segments:
|
203
|
+
- 0
|
204
|
+
hash: -2620113271490867274
|
205
|
+
requirements: []
|
206
|
+
rubyforge_project:
|
207
|
+
rubygems_version: 1.8.23
|
208
|
+
signing_key:
|
209
|
+
specification_version: 3
|
210
|
+
summary: A small gem to reduce Rake duplication
|
211
|
+
test_files:
|
212
|
+
- spec/daptiv-chef-ci/logger_spec.rb
|
213
|
+
- spec/daptiv-chef-ci/shell_spec.rb
|
214
|
+
- spec/daptiv-chef-ci/vagrant_driver_spec.rb
|
215
|
+
- spec/daptiv-chef-ci/virtualbox_driver_spec.rb
|