jamie 0.1.0.alpha1

Sign up to get free protection for your applications and to get access to all the features.
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: []