daptiv-chef-ci 0.0.15 → 0.1.0

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.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/daptiv-chef-ci.gemspec +21 -20
  3. data/lib/daptiv-chef-ci/clone_environment_task.rb +69 -0
  4. data/lib/daptiv-chef-ci/logger.rb +9 -10
  5. data/lib/daptiv-chef-ci/raketask_helper.rb +5 -6
  6. data/lib/daptiv-chef-ci/shell.rb +50 -28
  7. data/lib/daptiv-chef-ci/upload_cookbook_task.rb +62 -0
  8. data/lib/daptiv-chef-ci/vagrant_destroy_task.rb +11 -12
  9. data/lib/daptiv-chef-ci/vagrant_driver.rb +47 -56
  10. data/lib/daptiv-chef-ci/vagrant_provision_task.rb +12 -15
  11. data/lib/daptiv-chef-ci/vagrant_task.rb +34 -57
  12. data/lib/daptiv-chef-ci/vagrant_up_task.rb +14 -16
  13. data/lib/daptiv-chef-ci/version_cookbook_task.rb +69 -0
  14. data/lib/daptiv-chef-ci/virtualbox_driver.rb +11 -12
  15. data/spec/daptiv-chef-ci/logger_spec.rb +11 -15
  16. data/spec/daptiv-chef-ci/shell_spec.rb +23 -27
  17. data/spec/daptiv-chef-ci/vagrant_destroy_task_spec.rb +5 -7
  18. data/spec/daptiv-chef-ci/vagrant_driver_spec.rb +34 -72
  19. data/spec/daptiv-chef-ci/vagrant_provision_task_spec.rb +9 -13
  20. data/spec/daptiv-chef-ci/vagrant_task_spec.rb +29 -21
  21. data/spec/daptiv-chef-ci/vagrant_up_task_spec.rb +9 -12
  22. data/spec/daptiv-chef-ci/virtualbox_driver_spec.rb +21 -16
  23. data/spec/shared_contexts/rake.rb +7 -7
  24. metadata +21 -14
  25. data/lib/daptiv-chef-ci/basebox_builder_factory.rb +0 -19
  26. data/lib/daptiv-chef-ci/virtualbox_basebox_builder.rb +0 -33
  27. data/lib/daptiv-chef-ci/vmware_basebox_builder.rb +0 -103
  28. data/spec/daptiv-chef-ci/basebox_builder_factory_spec.rb +0 -25
  29. data/spec/daptiv-chef-ci/virtualbox_basebox_builder_spec.rb +0 -20
  30. data/spec/daptiv-chef-ci/vmware_basebox_builder_spec.rb +0 -20
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 829ea781a4a70546ff1b3ec4b548c30567bb6344
4
- data.tar.gz: 56e8f9b1dda7737427467d842b06e9b6543eea85
3
+ metadata.gz: cfeeac6ae1094f6d486f92af9fca0fc1a1915ec9
4
+ data.tar.gz: 489147267747924a25c9e1f6e350881f01996a35
5
5
  SHA512:
6
- metadata.gz: 7e2b012c9f7dacb4e49165af23db194dd201ed1c50e89e37cdb0dac6955f80cdb28f476d9c7af7d66b78cf5a696046ae901ab5a14f97a07b12ced9ab0f1656d7
7
- data.tar.gz: 5f72fd850b5d95a72184d84f1904d2605a6456c1a38763fffda62683b29adb2eb695801c1399f8a84258199dd22a56b5feaaea834cdfcf892940fed085581287
6
+ metadata.gz: 5707f54b532a6299e7f446add8ceaef337840207d337190cd8a7c9772e7e87362cbf922ee7f92342506d015459fa9d30f9601def5dee61ba93d1d8450eb5374b
7
+ data.tar.gz: 41db757953a4c6ce7100eff2217719354d71667763367b4969acb1d87e344f904c56ac0e7bd98759f1358c514df8d146ac37bb8d5e6f82be7ab213089f5b4b0f
@@ -1,11 +1,11 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
 
3
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 = ""
4
+ gem.authors = ['Shawn Neal']
5
+ gem.email = ['sneal@daptiv.com']
6
+ gem.description = 'Vagrant automation for CI'
7
+ gem.summary = 'A small gem to reduce Rake duplication'
8
+ gem.homepage = ''
9
9
 
10
10
  # The following block of code determines the files that should be included
11
11
  # in the gem. It does this by reading all the files in the directory where
@@ -13,9 +13,9 @@ Gem::Specification.new do |gem|
13
13
  # Note that the entire gitignore(5) syntax is not supported, specifically
14
14
  # the "!" syntax, but it should mostly work correctly.
15
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")
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
19
  gitignore = File.readlines(gitignore_path)
20
20
  gitignore.map! { |line| line.chomp.strip }
21
21
  gitignore.reject! { |line| line.empty? || line =~ /^(#|!)/ }
@@ -34,22 +34,23 @@ Gem::Specification.new do |gem|
34
34
  #
35
35
  gitignore.any? do |ignore|
36
36
  File.fnmatch(ignore, file, File::FNM_PATHNAME) ||
37
- File.fnmatch(ignore, File.basename(file), File::FNM_PATHNAME)
37
+ File.fnmatch(ignore, File.basename(file), File::FNM_PATHNAME)
38
38
  end
39
39
  end
40
40
 
41
41
  gem.files = unignored_files
42
- gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
42
+ gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
43
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.15'
47
-
48
- gem.add_runtime_dependency "log4r", "~> 1.1.10"
49
- gem.add_runtime_dependency "mixlib-shellout", "~> 1.6.0"
44
+ gem.name = 'daptiv-chef-ci'
45
+ gem.require_paths = ['lib']
46
+ gem.version = '0.1.0'
50
47
 
51
- gem.add_development_dependency "rake"
52
- gem.add_development_dependency "rspec-core", "~> 2.12.2"
53
- gem.add_development_dependency "rspec-expectations", "~> 2.12.1"
54
- gem.add_development_dependency "rspec-mocks", "~> 2.12.1"
48
+ gem.add_runtime_dependency 'log4r', '~> 1.1.10'
49
+ gem.add_runtime_dependency 'mixlib-shellout', '~> 1.2'
50
+ gem.add_runtime_dependency 'versionomy', '~> 0.4.4'
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'
55
56
  end
@@ -0,0 +1,69 @@
1
+ require 'rake'
2
+ require 'rake/tasklib'
3
+ require 'rake/dsl_definition'
4
+ require 'json'
5
+ require 'tempfile'
6
+ require_relative 'raketask_helper'
7
+ require_relative 'shell'
8
+
9
+ class CloneEnvironment
10
+ # Example usage, copies a Chef environment definition to another
11
+ # environment.
12
+ #
13
+ # CloneEnvironment::RakeTask.new do |t|
14
+ # t.src_env = 'dev'
15
+ # t.dest_env = "vagrant-#{ENV['LOGNAME']}-dotnetframework"
16
+ # end
17
+ #
18
+ # This class lets you define Rake tasks to clone Chef environments.
19
+ class RakeTask < ::Rake::TaskLib
20
+ include ::Rake::DSL if defined? ::Rake::DSL
21
+ include DaptivChefCI::RakeTaskHelpers
22
+
23
+ attr_accessor :src_env
24
+ attr_accessor :dest_env
25
+
26
+ # @param [String] name The task name.
27
+ # @param [String] desc Description of the task.
28
+ def initialize(name = 'clone_environment', desc = 'Clone environment task')
29
+ @logger = Log4r::Logger.new('daptiv_chef_ci::clone_environment_task')
30
+ @shell = DaptivChefCI::Shell.new
31
+ @name, @desc = name, desc
32
+ yield self if block_given?
33
+ define_task
34
+ end
35
+
36
+ private
37
+
38
+ def define_task
39
+ desc @desc
40
+ task @name do
41
+ execute do
42
+ fail 'src_env must be specified' unless @src_env
43
+ fail 'dest_env must be specified' unless @dest_env
44
+ clone_environment
45
+ end
46
+ end
47
+ end
48
+
49
+ def clone_environment
50
+ out = @shell.exec_cmd_in_context(
51
+ "knife environment show #{@src_env} -F json").join(' ')
52
+
53
+ env = JSON.parse(out)
54
+ env['name'] = @dest_env
55
+ env['description'] = "The #{dest_env} environment"
56
+
57
+ env_file = Tempfile.new([@dest_env, '.json'])
58
+ begin
59
+ IO.write(env_file.path, JSON.pretty_generate(env))
60
+
61
+ @shell.exec_cmd_in_context(
62
+ "knife environment from file '#{env_file.path}'")
63
+ ensure
64
+ env_file.close
65
+ env_file.unlink
66
+ end
67
+ end
68
+ end
69
+ end
@@ -1,35 +1,34 @@
1
1
  module DaptivChefCI
2
+ # Chef CI logger class
2
3
  class Logger
3
-
4
4
  # Initializes and enables logging to the given environments level
5
5
  # By default logging only occurs at ERROR level or higher.
6
6
  # Set CHEF_CI_LOG env var to change logging levels
7
- def self.init()
7
+ def self.init
8
8
  require 'log4r'
9
-
9
+
10
10
  # Set the logging level on all "chef-ci" namespaced
11
11
  # logs as long as we have a valid level.
12
- logger = Log4r::Logger.new("daptiv_chef_ci")
12
+ logger = Log4r::Logger.new('daptiv_chef_ci')
13
13
  logger.outputters = Log4r::Outputter.stderr
14
- logger.level = log_level()
14
+ logger.level = log_level
15
15
  logger = nil
16
16
  end
17
-
17
+
18
18
  # LogLevels = ['DEBUG', 'INFO', 'WARN', 'ERROR', 'FATAL']
19
19
  # DEBUG = 1
20
20
  # INFO = 2
21
21
  # WARN = 3
22
22
  # ERROR = 4
23
23
  # FATAL = 5
24
- def self.log_level()
25
- level = ENV['CHEF_CI_LOG'].upcase().to_s()
24
+ def self.log_level
25
+ level = ENV['CHEF_CI_LOG'].upcase.to_s
26
26
  level_i = Log4r::Log4rConfig::LogLevels.index(level)
27
27
  level_i + 1
28
28
  rescue
29
29
  return 2 # info
30
30
  end
31
-
32
31
  end
33
32
  end
34
33
 
35
- DaptivChefCI::Logger.init()
34
+ DaptivChefCI::Logger.init
@@ -1,17 +1,17 @@
1
1
  module DaptivChefCI
2
2
  module RakeTaskHelpers
3
3
  extend self
4
-
4
+
5
5
  @@exit_on_failure = true
6
-
6
+
7
7
  def exit_on_failure
8
8
  @@exit_on_failure
9
9
  end
10
-
10
+
11
11
  def exit_on_failure=(exit_on_failure)
12
12
  @@exit_on_failure = exit_on_failure
13
13
  end
14
-
14
+
15
15
  def execute(&block)
16
16
  begin
17
17
  block.call()
@@ -31,6 +31,5 @@ module DaptivChefCI
31
31
  end
32
32
  end
33
33
  end
34
-
35
34
  end
36
- end
35
+ end
@@ -3,61 +3,83 @@ require 'bundler'
3
3
  require 'mixlib/shellout'
4
4
 
5
5
  module DaptivChefCI
6
+ # Command shell wrapper
6
7
  class Shell
7
-
8
- def initialize()
9
- @logger = Log4r::Logger.new("daptiv_chef_ci::shell")
8
+ def initialize
9
+ @logger = Log4r::Logger.new('daptiv_chef_ci::shell')
10
10
  end
11
-
11
+
12
12
  # Executes the specified shell command and returns the stdout.
13
13
  #
14
14
  # This method ensure that any invoked command use the same PATH environment
15
15
  # that the user has outside Ruby/Bundler.
16
16
  #
17
17
  # @param [String] The command line to execute
18
- # @param [Int] The number of seconds to wait for the command to finish, defaults to 600
19
- # @param [Hash] Key value pairs of environment variables to pass to the command's environment.
18
+ # @param [Int] The number of seconds to wait for the command to finish,
19
+ # defaults to 600
20
+ # @param [Hash] Key value pairs of environment variables to pass to the
21
+ # command's environment.
20
22
  # @return [Array] Each entry represents a line from the stdout
21
- def exec_cmd(command, timeout = nil, environment = {})
23
+ def exec_cmd_in_context(command, timeout = nil, environment = {})
22
24
  timeout ||= 600
23
25
  environment = Hash[ environment.map{ |k, v| [k.to_s, v.to_s] } ]
24
- environment['LC_ALL'] = ENV['LC_ALL'] if !environment.has_key?('LC_ALL')
26
+ environment['LC_ALL'] = ENV['LC_ALL'] unless environment.key?('LC_ALL')
27
+
28
+ @logger.info("Executing: '#{command}'")
29
+ @logger.debug("\n\ttimeout: #{timeout}\n\tenvironment: #{environment}")
30
+
31
+ shell_out = Mixlib::ShellOut.new(
32
+ command, timeout: timeout, environment: environment)
33
+ shell_out.live_stream = STDOUT
34
+
35
+ shell_out.run_command
36
+ shell_out.invalid! if shell_out.exitstatus != 0
37
+ @logger.info(shell_out.stdout)
38
+ shell_out.stdout.split("\n")
39
+ end
40
+
41
+ # Executes the specified shell command and returns the stdout.
42
+ #
43
+ # This method ensure that any invoked command use the same PATH environment
44
+ # that the user has outside Ruby/Bundler.
45
+ #
46
+ # @param [String] The command line to execute
47
+ # @param [Int] The number of seconds to wait for the command to finish,
48
+ # defaults to 600
49
+ # @param [Hash] Key value pairs of environment variables to pass to the
50
+ # command's environment.
51
+ # @return [Array] Each entry represents a line from the stdout
52
+ def exec_cmd(command, timeout = nil, environment = {})
25
53
  path_at_start = ENV['PATH']
26
54
  begin
27
- ENV['PATH'] = path_without_gem_dir()
28
- @logger.debug("Temporarily setting PATH: #{ENV['PATH']}")
29
-
30
- @logger.info("Executing: '#{command}'\n\ttimeout: #{timeout}\n\tenvironment: #{environment}")
31
- shell_out = Mixlib::ShellOut.new(command, :timeout => timeout, :environment => environment)
32
- shell_out.run_command()
33
- shell_out.invalid! if shell_out.exitstatus != 0
34
-
35
- @logger.info(shell_out.stdout)
36
- shell_out.stdout.split("\n")
55
+ ENV['PATH'] = path_without_gem_dir
56
+ @logger.debug("Setting PATH: #{ENV['PATH']}")
57
+ exec_cmd_in_context(command, timeout, environment)
37
58
  ensure
38
59
  @logger.debug("Resetting PATH: #{path_at_start}")
39
60
  ENV['PATH'] = path_at_start
40
61
  end
41
62
  end
42
-
63
+
43
64
  # Returns the PATH environment variable as it was before Bundler prepended
44
65
  # the system gem directory to it.
45
66
  #
46
- # This can happen if the user has invoked "require 'bundler/setup'" somewhere,
47
- # like in this gems Rakefile.
67
+ # This can happen if the user has invoked "require 'bundler/setup'"
68
+ # somewhere, like in this gems Rakefile.
48
69
  #
49
- # This is needed because sometimes a user will have the Vagrant gem installed
50
- # on their system and we don't want to use it, we should use the one that's in
51
- # their PATH as if they invoked vagrant themselves (i.e. the installed version)
70
+ # This is needed because sometimes a user will have the Vagrant gem
71
+ # installed on their system and we don't want to use it, we should use the
72
+ # one that's in their PATH as if they invoked vagrant themselves
73
+ # (i.e. the installed version)
52
74
  #
53
- # @return [String] The ENV['PATH] without the Bundler system gem dir prepended
75
+ # @return [String] The ENV['PATH] without the Bundler system gem dir
76
+ # prepended
54
77
  def path_without_gem_dir
55
78
  paths = ENV['PATH'].split(':')
56
79
  system_gem_dir = "#{Bundler.bundle_path}/bin"
57
80
  @logger.debug("System gem dir: #{system_gem_dir}")
58
- paths.delete_if { |p| p.downcase() == system_gem_dir.downcase() }
81
+ paths.delete_if { |p| p.downcase == system_gem_dir.downcase }
59
82
  paths.join(':')
60
83
  end
61
-
62
84
  end
63
- end
85
+ end
@@ -0,0 +1,62 @@
1
+ require 'rake'
2
+ require 'rake/tasklib'
3
+ require 'rake/dsl_definition'
4
+ require_relative 'raketask_helper'
5
+ require_relative 'shell'
6
+
7
+ class UploadCookbook
8
+ # Example usage, uploads the current cookbook to the Chef server freezing
9
+ # it to the Canary environment.
10
+ #
11
+ # UploadCookbook::RakeTask.new do |t|
12
+ # t.environment = 'canary'
13
+ # t.freeze = true
14
+ # end
15
+ #
16
+ # This class lets you define Rake tasks to upload cookbooks to Chef.
17
+ class RakeTask < ::Rake::TaskLib
18
+ include ::Rake::DSL if defined? ::Rake::DSL
19
+ include DaptivChefCI::RakeTaskHelpers
20
+
21
+ attr_accessor :environment
22
+ attr_accessor :freeze
23
+
24
+ # @param [String] name The task name.
25
+ # @param [String] desc Description of the task.
26
+ def initialize(name = 'upload_cookbook', desc = 'Upload cookbook task')
27
+ @logger = Log4r::Logger.new('daptiv_chef_ci::upload_cookbook_task')
28
+ @shell = DaptivChefCI::Shell.new
29
+ @name, @desc = name, desc
30
+ @freeze = false
31
+ yield self if block_given?
32
+ define_task
33
+ end
34
+
35
+ private
36
+
37
+ def define_task
38
+ desc @desc
39
+ task @name do
40
+ execute do
41
+ upload_cookbook
42
+ end
43
+ end
44
+ end
45
+
46
+ def upload_cookbook
47
+ cmd = "knife cookbook upload #{cookbook_name} -o ../"
48
+ cmd << " -E #{environment}" if @environment
49
+ @shell.exec_cmd_in_context(cmd)
50
+ end
51
+
52
+ def cookbook_name
53
+ unless @cookbook_name
54
+ metadata = IO.read(File.join(Dir.pwd, 'metadata.rb'))
55
+ @cookbook_name = /name\s+['|"](\w+)/.match(metadata)[1]
56
+ fail 'Cannot find cookbook name in metadata.rb' unless @cookbook_name
57
+ @logger.debug("found cookbook name: #{@cookbook_name}")
58
+ end
59
+ @cookbook_name
60
+ end
61
+ end
62
+ end
@@ -6,7 +6,6 @@ require_relative 'raketask_helper'
6
6
  require_relative 'logger'
7
7
 
8
8
  class VagrantDestroy
9
-
10
9
  # Example usage, destroys a Vagrant box.
11
10
  #
12
11
  # VagrantUp::RakeTask.new 'up' do |t|
@@ -17,11 +16,11 @@ class VagrantDestroy
17
16
  class RakeTask < ::Rake::TaskLib
18
17
  include ::Rake::DSL if defined? ::Rake::DSL
19
18
  include DaptivChefCI::RakeTaskHelpers
20
-
19
+
21
20
  attr_accessor :vagrant_driver
22
21
  attr_accessor :destroy_timeout_in_seconds
23
22
  attr_accessor :environment
24
-
23
+
25
24
  # @param [String] name The task name.
26
25
  # @param [String] desc Description of the task.
27
26
  def initialize(name = 'vagrant_destroy', desc = 'Vagrant destroy task')
@@ -31,22 +30,22 @@ class VagrantDestroy
31
30
  yield self if block_given?
32
31
  define_task
33
32
  end
34
-
33
+
35
34
  private
36
35
 
37
36
  def define_task
38
37
  desc @desc
39
38
  task @name do
40
- execute { vagrant_driver.destroy({
41
- :cmd_timeout_in_seconds => @destroy_timeout_in_seconds,
42
- :environment => @environment }) }
39
+ execute do
40
+ vagrant_driver.destroy(
41
+ cmd_timeout_in_seconds: @destroy_timeout_in_seconds,
42
+ environment: @environment)
43
+ end
43
44
  end
44
45
  end
45
-
46
- def vagrant_driver()
47
- @vagrant_driver ||= DaptivChefCI::VagrantDriver.new()
48
- end
49
46
 
47
+ def vagrant_driver
48
+ @vagrant_driver ||= DaptivChefCI::VagrantDriver.new
49
+ end
50
50
  end
51
51
  end
52
-