jamie 0.1.0.alpha1

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 ADDED
@@ -0,0 +1,20 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .rvmrc
19
+ .rbenv-version
20
+ .ruby-version
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ Author:: Fletcher Nichol (<fnichol@nichol.ca>)
2
+
3
+ Copyright 2012 Fletcher Nichol
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License");
6
+ you may not use this file except in compliance with the License.
7
+ You may obtain a copy of the License at
8
+
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software
12
+ distributed under the License is distributed on an "AS IS" BASIS,
13
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ See the License for the specific language governing permissions and
15
+ limitations under the License.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # Jamie
2
+
3
+ A Chef convergence integration test harness.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'jamie'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install jamie
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/jamie.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'jamie/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "jamie"
8
+ gem.version = Jamie::VERSION
9
+ gem.authors = ["Fletcher Nichol"]
10
+ gem.email = ["fnichol@nichol.ca"]
11
+ gem.description = %q{A Chef convergence integration test harness}
12
+ gem.summary = gem.description
13
+ gem.homepage = ""
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_dependency 'hashie'
21
+ gem.add_dependency 'mixlib-shellout'
22
+ gem.add_dependency 'vagrant', '~> 1.0.5'
23
+ end
@@ -0,0 +1,52 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'rake'
4
+ require 'rake/tasklib'
5
+
6
+ require 'jamie'
7
+
8
+ module Jamie
9
+ module Rake
10
+ class Tasks < ::Rake::TaskLib
11
+ attr_accessor :name
12
+
13
+ def initialize(name = :jamie)
14
+ @name = name
15
+ yield self if block_given?
16
+ define
17
+ end
18
+
19
+ def define
20
+ config = Jamie::Config.new
21
+
22
+ namespace(name) do
23
+ config.instances.each do |instance_name|
24
+ desc "Run #{instance_name} integration"
25
+ task(instance_name) do
26
+ puts "-----> Cleaning up any prior instances of #{instance_name}"
27
+ config.backend.destroy(instance_name)
28
+ puts "-----> Bringing up instance #{instance_name}"
29
+ config.backend.up(instance_name)
30
+ puts "-----> Instance #{instance_name} completed."
31
+ end
32
+
33
+ namespace(instance_name) do
34
+ desc "Destroy #{instance_name} instance"
35
+ task :destroy do
36
+ puts "-----> Destroying any prior instances of #{instance_name}"
37
+ config.backend.destroy(instance_name)
38
+ puts "-----> Instance #{instance_name} destruction complete."
39
+ end
40
+ end
41
+ end
42
+
43
+ desc "Destroy all instances"
44
+ task :destroy => config.instances.map { |i| "#{i}:destroy" }
45
+ end
46
+
47
+ desc "Run Jamie integration"
48
+ task name => config.instances
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,70 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'forwardable'
4
+ require 'vagrant'
5
+
6
+ require 'jamie'
7
+
8
+ module Jamie
9
+ module Vagrant
10
+ class Config < ::Vagrant::Config::Base
11
+ extend Forwardable
12
+
13
+ def_delegators :@config, :yaml, :yaml=, :platforms, :platforms=,
14
+ :suites, :suites=, :log_level, :log_level=,
15
+ :data_bags_base_path, :data_bags_base_path=, :yaml_data
16
+
17
+ def initialize
18
+ @config = Jamie::Config.new
19
+ end
20
+ end
21
+
22
+ def self.init!
23
+ ::Vagrant.config_keys.register(:jamie) { Jamie::Vagrant::Config }
24
+ end
25
+
26
+ def self.define_vms(config)
27
+ config.jamie.suites.each do |suite|
28
+ config.jamie.platforms.each do |platform|
29
+ define_vagrant_vm(config, suite, platform)
30
+ end
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def self.define_vagrant_vm(config, suite, platform)
37
+ name = "#{suite.name}-#{platform.name}".gsub(/_/, '-').gsub(/\./, '')
38
+
39
+ config.vm.define name do |c|
40
+ c.vm.box = platform.vagrant_box
41
+ c.vm.box_url = platform.vagrant_box_url if platform.vagrant_box_url
42
+ c.vm.host_name = "#{name}.vagrantup.com"
43
+ c.vm.customize ["modifyvm", :id, "--memory", "256"]
44
+
45
+ c.vm.provision :chef_solo do |chef|
46
+ chef.log_level = config.jamie.log_level
47
+ chef.run_list = platform.base_run_list + Array(suite.run_list)
48
+ chef.json = suite.json
49
+ chef.data_bags_path = calculate_data_bags_path(config, name)
50
+ end
51
+ end
52
+ end
53
+
54
+ def self.calculate_data_bags_path(config, instance_name)
55
+ base_path = config.jamie.data_bags_base_path
56
+ instance_data_bags_path = File.join(base_path, instance_name, "data_bags")
57
+ common_data_bags_path = File.join(base_path, "data_bags")
58
+
59
+ if File.directory?(instance_data_bags_path)
60
+ instance_data_bags_path
61
+ elsif File.directory?(common_data_bags_path)
62
+ common_data_bags_path
63
+ else
64
+ nil
65
+ end
66
+ end
67
+ end
68
+ end
69
+
70
+ Jamie::Vagrant.init!
@@ -0,0 +1,3 @@
1
+ module Jamie
2
+ VERSION = "0.1.0.alpha1"
3
+ end
data/lib/jamie.rb ADDED
@@ -0,0 +1,112 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'hashie/dash'
4
+ require 'mixlib/shellout'
5
+ require 'yaml'
6
+
7
+ require "jamie/version"
8
+
9
+ module Jamie
10
+ class Platform < Hashie::Dash
11
+ property :name, :required => true
12
+ property :vagrant_box
13
+ property :vagrant_box_url
14
+ property :base_run_list, :default => []
15
+ end
16
+
17
+ class Suite < Hashie::Dash
18
+ property :name, :required => true
19
+ property :run_list, :required => true
20
+ property :json, :default => Hash.new
21
+ end
22
+
23
+ class Config
24
+ attr_writer :yaml
25
+ attr_writer :platforms
26
+ attr_writer :suites
27
+ attr_writer :backend
28
+ attr_writer :log_level
29
+ attr_writer :data_bags_base_path
30
+
31
+ def yaml
32
+ @yaml ||= File.join(Dir.pwd, '.jamie.yml')
33
+ end
34
+
35
+ def platforms
36
+ @platforms ||=
37
+ Array(yaml_data["platforms"]).map { |hash| Platform.new(hash) }
38
+ end
39
+
40
+ def suites
41
+ @suites ||=
42
+ Array(yaml_data["suites"]).map { |hash| Suite.new(hash) }
43
+ end
44
+
45
+ def backend
46
+ @backend ||= backend_for(yaml_data["backend"] || "vagrant")
47
+ end
48
+
49
+ def log_level
50
+ @log_level ||= :info
51
+ end
52
+
53
+ def data_bags_base_path
54
+ default_path = File.join(Dir.pwd, 'test/integration')
55
+
56
+ @data_bags_path ||= File.directory?(default_path) ? default_path : nil
57
+ end
58
+
59
+ def instances
60
+ result = []
61
+ suites.each do |suite|
62
+ platforms.each do |platform|
63
+ result << instance_name(suite, platform)
64
+ end
65
+ end
66
+ result
67
+ end
68
+
69
+ private
70
+
71
+ def yaml_data
72
+ @yaml_data ||= YAML.load_file(yaml)
73
+ end
74
+
75
+ def instance_name(suite, platform)
76
+ "#{suite.name}-#{platform.name}".gsub(/_/, '-').gsub(/\./, '')
77
+ end
78
+
79
+ def backend_for(backend)
80
+ klass = Jamie::Backend.const_get(backend.capitalize)
81
+ klass.new
82
+ end
83
+ end
84
+
85
+ module Backend
86
+ class CommandFailed < StandardError ; end
87
+
88
+ class Vagrant
89
+ def up(instance)
90
+ exec! "vagrant up #{instance}"
91
+ rescue Mixlib::ShellOut::ShellCommandFailed => ex
92
+ raise CommandFailed, ex.message
93
+ end
94
+
95
+ def destroy(instance)
96
+ exec! "vagrant destroy #{instance} -f"
97
+ rescue Mixlib::ShellOut::ShellCommandFailed => ex
98
+ raise CommandFailed, ex.message
99
+ end
100
+
101
+ def exec!(cmd)
102
+ puts "-----> [vagrant command] #{cmd}"
103
+ shellout = Mixlib::ShellOut.new(
104
+ cmd, :live_stream => STDOUT, :timeout => 60000
105
+ )
106
+ shellout.run_command
107
+ puts "-----> Command '#{cmd}' ran in #{shellout.execution_time} seconds."
108
+ shellout.error!
109
+ end
110
+ end
111
+ end
112
+ end
metadata ADDED
@@ -0,0 +1,103 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jamie
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0.alpha1
5
+ prerelease: 6
6
+ platform: ruby
7
+ authors:
8
+ - Fletcher Nichol
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-12-01 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: hashie
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '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: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: mixlib-shellout
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
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: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: vagrant
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 1.0.5
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: 1.0.5
62
+ description: A Chef convergence integration test harness
63
+ email:
64
+ - fnichol@nichol.ca
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - .gitignore
70
+ - Gemfile
71
+ - LICENSE
72
+ - README.md
73
+ - Rakefile
74
+ - jamie.gemspec
75
+ - lib/jamie.rb
76
+ - lib/jamie/rake_task.rb
77
+ - lib/jamie/vagrant.rb
78
+ - lib/jamie/version.rb
79
+ homepage: ''
80
+ licenses: []
81
+ post_install_message:
82
+ rdoc_options: []
83
+ require_paths:
84
+ - lib
85
+ required_ruby_version: !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ! '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ required_rubygems_version: !ruby/object:Gem::Requirement
92
+ none: false
93
+ requirements:
94
+ - - ! '>'
95
+ - !ruby/object:Gem::Version
96
+ version: 1.3.1
97
+ requirements: []
98
+ rubyforge_project:
99
+ rubygems_version: 1.8.24
100
+ signing_key:
101
+ specification_version: 3
102
+ summary: A Chef convergence integration test harness
103
+ test_files: []