kitchen-vagrant 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,16 @@
1
+ ## 0.7.0 / 2013-03-22
2
+
3
+ ### New features
4
+
5
+ * Pull request [#7][]: [Breaking] Support Vagrant 1.1+ and remove vagrant gem dependency. ([@fnichol][])
6
+ * Pull request [#8][]: Add dependency checks for Vagrant and berkshelf-vagrant plugin (if necessary). ([@fnichol][])
7
+
8
+
9
+ ## 0.6.0 / 2013-03-02
10
+
11
+ The initial release.
12
+
13
+ <!--- The following link definition list is generated by PimpMyChangelog --->
14
+ [#7]: https://github.com/opscode/kitchen/issues/7
15
+ [#8]: https://github.com/opscode/kitchen/issues/8
16
+ [@fnichol]: https://github.com/fnichol
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Kitchen::Vagrant
2
2
 
3
- [![Build Status](https://secure.travis-ci.org/jamie-ci/kitchen-vagrant.png)](https://travis-ci.org/jamie-ci/kitchen-vagrant)
4
- [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/jamie-ci/kitchen-vagrant)
3
+ [![Build Status](https://travis-ci.org/opscode/kitchen-vagrant.png)](https://travis-ci.org/opscode/kitchen-vagrant)
4
+ [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/opscode/kitchen-vagrant)
5
5
 
6
6
  This gem provides `kitchen-vagrant`, a driver for `test-kitchen` to provision systems to test under Vagrant.
7
7
 
data/Rakefile CHANGED
@@ -3,11 +3,7 @@ require 'cane/rake_task'
3
3
  require 'tailor/rake_task'
4
4
 
5
5
  desc "Run cane to check quality metrics"
6
- Cane::RakeTask.new do |cane|
7
- cane.abc_exclude = %w(
8
- Kitchen::Vagrant.define_vagrant_vm
9
- )
10
- end
6
+ Cane::RakeTask.new
11
7
 
12
8
  Tailor::RakeTask.new
13
9
 
@@ -18,7 +18,6 @@ Gem::Specification.new do |gem|
18
18
  gem.require_paths = ["lib"]
19
19
 
20
20
  gem.add_dependency 'test-kitchen', '~> 1.0.0.alpha.0'
21
- gem.add_dependency 'vagrant', '~> 1.0'
22
21
 
23
22
  gem.add_development_dependency 'cane'
24
23
  gem.add_development_dependency 'tailor'
@@ -16,7 +16,11 @@
16
16
  # See the License for the specific language governing permissions and
17
17
  # limitations under the License.
18
18
 
19
+ require 'fileutils'
20
+ require 'rubygems/version'
21
+
19
22
  require 'kitchen'
23
+ require 'kitchen/vagrant/vagrantfile_creator'
20
24
 
21
25
  module Kitchen
22
26
 
@@ -25,6 +29,9 @@ module Kitchen
25
29
  # Vagrant driver for Kitchen. It communicates to Vagrant via the CLI.
26
30
  #
27
31
  # @author Fletcher Nichol <fnichol@nichol.ca>
32
+ #
33
+ # @todo Vagrant installation check and version will be placed into any
34
+ # dependency hook checks when feature is released
28
35
  class Vagrant < Kitchen::Driver::SSHBase
29
36
 
30
37
  default_config :customize, {:memory => '256'}
@@ -32,60 +39,113 @@ module Kitchen
32
39
  no_parallel_for :create, :destroy
33
40
 
34
41
  def create(state)
35
- # @todo Vagrantfile setup will be placed in any dependency hook
36
- # checks when feature is released
37
- vagrantfile = File.join(config[:kitchen_root], "Vagrantfile")
38
- create_vagrantfile(vagrantfile) unless File.exists?(vagrantfile)
39
-
40
42
  state[:hostname] = instance.name
41
- run "vagrant up #{state[:hostname]} --no-provision"
43
+ create_vagrantfile(state)
44
+ run "vagrant up --no-provision"
42
45
  info("Vagrant instance <#{state[:hostname]}> created.")
43
46
  end
44
47
 
45
48
  def converge(state)
49
+ create_vagrantfile(state)
46
50
  ssh_args = build_ssh_args(state)
47
51
  install_omnibus(ssh_args) if config[:require_chef_omnibus]
48
- run "vagrant provision #{state[:hostname]}"
52
+ run "vagrant provision"
53
+ end
54
+
55
+ def setup(state)
56
+ create_vagrantfile(state)
57
+ super
58
+ end
59
+
60
+ def verify(state)
61
+ create_vagrantfile(state)
62
+ super
49
63
  end
50
64
 
51
65
  def destroy(state)
52
66
  return if state[:hostname].nil?
53
67
 
54
- run "vagrant destroy #{state[:hostname]} -f"
68
+ create_vagrantfile(state)
69
+ run "vagrant destroy -f"
70
+ FileUtils.rm_rf(vagrant_root)
55
71
  info("Vagrant instance <#{state[:hostname]}> destroyed.")
56
72
  state.delete(:hostname)
57
73
  end
58
74
 
59
75
  def login_command(state)
60
- %W{vagrant ssh #{state[:hostname]}}
76
+ create_vagrantfile(state)
77
+ LoginCommand.new(%W{vagrant ssh}, :chdir => vagrant_root)
78
+ end
79
+
80
+ def verify_dependencies
81
+ check_vagrant_version
82
+ check_berkshelf_plugin
61
83
  end
62
84
 
63
85
  protected
64
86
 
87
+ WEBSITE = "http://downloads.vagrantup.com/"
88
+ MIN_VER = "1.1.0"
89
+
65
90
  def ssh(ssh_args, cmd)
66
- run %{vagrant ssh #{ssh_args.first} --command '#{cmd}'}
91
+ run %{vagrant ssh --command '#{cmd}'}
67
92
  end
68
93
 
69
- def run(cmd)
94
+ def run(cmd, options = {})
70
95
  cmd = "echo #{cmd}" if config[:dry_run]
71
- run_command(cmd)
96
+ run_command(cmd, { :cwd => vagrant_root }.merge(options))
97
+ end
98
+
99
+ def silently_run(cmd)
100
+ run_command(cmd,
101
+ :live_stream => nil, :quiet => logger.debug? ? false : true)
102
+ end
103
+
104
+ def vagrant_root
105
+ @vagrant_root ||= File.join(
106
+ config[:kitchen_root], %w{.kitchen kitchen-vagrant}, instance.name
107
+ )
108
+ end
109
+
110
+ def create_vagrantfile(state)
111
+ return if @vagrantfile_created
112
+
113
+ vagrantfile = File.join(vagrant_root, "Vagrantfile")
114
+ debug("Creating Vagrantfile for <#{state[:hostname]}> (#{vagrantfile})")
115
+ FileUtils.mkdir_p(vagrant_root)
116
+ File.open(vagrantfile, "wb") { |f| f.write(creator.render) }
117
+ @vagrantfile_created = true
72
118
  end
73
119
 
74
- def create_vagrantfile(vagrantfile)
75
- File.open(vagrantfile, "wb") { |f| f.write(vagrantfile_contents) }
120
+ def creator
121
+ Kitchen::Vagrant::VagrantfileCreator.new(instance, config)
122
+ end
123
+
124
+ def vagrant_version
125
+ version_string = silently_run("vagrant --version")
126
+ version_string = version_string.chomp.split(" ").last
127
+ rescue Errno::ENOENT
128
+ raise UserError, "Vagrant #{MIN_VER} or higher is not installed." +
129
+ " Please download a package from #{WEBSITE}."
130
+ end
131
+
132
+ def check_vagrant_version
133
+ version = vagrant_version
134
+ if Gem::Version.new(version) < Gem::Version.new(MIN_VER)
135
+ raise UserError, "Detected an old version of Vagrant (#{version})." +
136
+ " Please upgrade to version #{MIN_VER} or higher from #{WEBSITE}."
137
+ end
76
138
  end
77
139
 
78
- def vagrantfile_contents
79
- arr = []
80
- arr << %{require 'kitchen/vagrant'}
140
+ def check_berkshelf_plugin
81
141
  if File.exists?(File.join(config[:kitchen_root], "Berksfile"))
82
- arr << %{require 'berkshelf/vagrant'}
142
+ plugins = silently_run("vagrant plugin list").split("\n")
143
+ if ! plugins.find { |p| p =~ /^berkshelf-vagrant\b/ }
144
+ raise UserError, "Detected a Berksfile but the berksfile-vagrant" +
145
+ " plugin was not found in Vagrant. Please run:" +
146
+ " `vagrant plugin install berkshelf-vagrant' and retry."
147
+ end
83
148
  end
84
- arr << %{}
85
- arr << %{Vagrant::Config.run do |config|}
86
- arr << %{ Kitchen::Vagrant.define_vms(config)}
87
- arr << %{end\n}
88
- arr.join("\n")
89
149
  end
90
150
  end
91
151
  end
@@ -21,6 +21,6 @@ module Kitchen
21
21
  module Driver
22
22
 
23
23
  # Version string for Vagrant Kitchen driver
24
- VAGRANT_VERSION = "0.6.0"
24
+ VAGRANT_VERSION = "0.7.0"
25
25
  end
26
26
  end
@@ -0,0 +1,110 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
4
+ #
5
+ # Copyright (C) 2013, Fletcher Nichol
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+
19
+ module Kitchen
20
+
21
+ module Vagrant
22
+
23
+ # Class to render Vagrantfiles to be used by the Kitchen Vagrant driver.
24
+ #
25
+ # @author Fletcher Nichol <fnichol@nichol.ca>
26
+ class VagrantfileCreator
27
+
28
+ def initialize(instance, config)
29
+ @instance = instance
30
+ @config = config
31
+ end
32
+
33
+ def render
34
+ arr = []
35
+ arr << %{Vagrant.configure("2") do |c|}
36
+ common_block(arr)
37
+ network_block(arr)
38
+ provider_block(arr)
39
+ chef_block(arr)
40
+ berkshelf_block(arr)
41
+ arr << %{end}
42
+ arr.join("\n")
43
+ end
44
+
45
+ private
46
+
47
+ attr_reader :instance, :config
48
+
49
+ def common_block(arr)
50
+ arr << %{ c.vm.box = "#{config[:box]}"}
51
+ arr << %{ c.vm.box_url = "#{config[:box_url]}"} if config[:box_url]
52
+ arr << %{ c.vm.hostname = "#{instance.name}.vagrantup.com"}
53
+ end
54
+
55
+ def network_block(arr)
56
+ Array(config[:network]).each do |network_options|
57
+ options = Array(network_options.dup)
58
+ type = options.shift
59
+ arr << %{ c.vm.network(:#{type}, #{options.join(", ")})}
60
+ end
61
+ end
62
+
63
+ def provider_block(arr)
64
+ arr << %{ c.vm.provider :virtualbox do |p|}
65
+ config[:customize].each do |key, value|
66
+ arr << %{ p.customize ["modifyvm", :id, "--#{key}", #{value}]}
67
+ end
68
+ arr << %{ end}
69
+ end
70
+
71
+ def chef_block(arr)
72
+ arr << %{ c.vm.provision :chef_solo do |chef|}
73
+ arr << %{ chef.log_level = #{vagrant_logger_level}}
74
+ arr << %{ chef.run_list = #{instance.run_list.inspect}}
75
+ arr << %{ chef.json = #{instance.attributes.to_s}}
76
+ if instance.suite.data_bags_path
77
+ arr << %{ chef.data_bags_path = #{instance.suite.data_bags_path}}
78
+ end
79
+ if instance.suite.roles_path
80
+ arr << %{ chef.roles_path = #{instance.suite.roles_path}}
81
+ end
82
+ arr << %{ end}
83
+ end
84
+
85
+ def berkshelf_block(arr)
86
+ if File.exists?(berksfile)
87
+ arr << %{ c.berkshelf.berksfile_path = "#{berksfile}"}
88
+ end
89
+ end
90
+
91
+ def vagrant_logger_level
92
+ if instance.logger.debug?
93
+ ":debug"
94
+ elsif instance.logger.info?
95
+ ":info"
96
+ elsif instance.logger.error?
97
+ ":error"
98
+ elsif instance.logger.fatal?
99
+ ":fatal"
100
+ else
101
+ ":info"
102
+ end
103
+ end
104
+
105
+ def berksfile
106
+ File.join(config[:kitchen_root], "Berksfile")
107
+ end
108
+ end
109
+ end
110
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kitchen-vagrant
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-03-02 00:00:00.000000000 Z
12
+ date: 2013-03-23 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: test-kitchen
@@ -27,22 +27,6 @@ dependencies:
27
27
  - - ~>
28
28
  - !ruby/object:Gem::Version
29
29
  version: 1.0.0.alpha.0
30
- - !ruby/object:Gem::Dependency
31
- name: vagrant
32
- requirement: !ruby/object:Gem::Requirement
33
- none: false
34
- requirements:
35
- - - ~>
36
- - !ruby/object:Gem::Version
37
- version: '1.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: '1.0'
46
30
  - !ruby/object:Gem::Dependency
47
31
  name: cane
48
32
  requirement: !ruby/object:Gem::Requirement
@@ -100,6 +84,7 @@ extra_rdoc_files: []
100
84
  files:
101
85
  - .gitignore
102
86
  - .travis.yml
87
+ - CHANGELOG.md
103
88
  - Gemfile
104
89
  - LICENSE
105
90
  - README.md
@@ -107,7 +92,7 @@ files:
107
92
  - kitchen-vagrant.gemspec
108
93
  - lib/kitchen/driver/vagrant.rb
109
94
  - lib/kitchen/driver/vagrant_version.rb
110
- - lib/kitchen/vagrant.rb
95
+ - lib/kitchen/vagrant/vagrantfile_creator.rb
111
96
  homepage: https://github.com/opscode/kitchen-vagrant/
112
97
  licenses: []
113
98
  post_install_message:
@@ -122,7 +107,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
122
107
  version: '0'
123
108
  segments:
124
109
  - 0
125
- hash: -433240395816256093
110
+ hash: 2904040541379656438
126
111
  required_rubygems_version: !ruby/object:Gem::Requirement
127
112
  none: false
128
113
  requirements:
@@ -131,7 +116,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
131
116
  version: '0'
132
117
  segments:
133
118
  - 0
134
- hash: -433240395816256093
119
+ hash: 2904040541379656438
135
120
  requirements: []
136
121
  rubyforge_project:
137
122
  rubygems_version: 1.8.24
@@ -1,101 +0,0 @@
1
- # -*- encoding: utf-8 -*-
2
- #
3
- # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
4
- #
5
- # Copyright (C) 2012, Fletcher Nichol
6
- #
7
- # Licensed under the Apache License, Version 2.0 (the "License");
8
- # you may not use this file except in compliance with the License.
9
- # You may obtain a copy of the License at
10
- #
11
- # http://www.apache.org/licenses/LICENSE-2.0
12
- #
13
- # Unless required by applicable law or agreed to in writing, software
14
- # distributed under the License is distributed on an "AS IS" BASIS,
15
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
- # See the License for the specific language governing permissions and
17
- # limitations under the License.
18
-
19
- require 'forwardable'
20
- require 'vagrant'
21
-
22
- require 'kitchen'
23
-
24
- module Kitchen
25
-
26
- module Vagrant
27
-
28
- # A Vagrant confiuration class which wraps a Kitchen::Config instance.
29
- #
30
- # @author Fletcher Nichol <fnichol@nichol.ca>
31
- class Config < ::Vagrant::Config::Base
32
- extend Forwardable
33
-
34
- def_delegators :@config, :suites, :suites=, :platforms, :platforms=,
35
- :instances, :yaml_file, :yaml_file=, :log_level, :log_level=,
36
- :test_base_path, :test_base_path=, :yaml_data
37
-
38
- def initialize
39
- @config = Kitchen::Config.new
40
- @config.yaml_file = ENV['KITCHEN_YAML'] if ENV['KITCHEN_YAML']
41
- end
42
-
43
- # Override default implementation to prevent serializing the config
44
- # instance variable, which may contain circular references.
45
- #
46
- # @return [Hash] an empty Hash
47
- def instance_variables_hash
48
- {}
49
- end
50
- end
51
-
52
- # Defines all Vagrant virtual machines, one for each instance.
53
- #
54
- # @param config [Vagrant::Config::Top] Vagrant top level config object
55
- def self.define_vms(config)
56
- config.kitchen.instances.each do |instance|
57
- define_vagrant_vm(config, instance)
58
- end
59
- end
60
-
61
- private
62
-
63
- def self.define_vagrant_vm(config, instance)
64
- driver = instance.driver
65
-
66
- config.vm.define instance.name do |c|
67
- c.vm.box = driver[:box]
68
- c.vm.box_url = driver[:box_url] if driver[:box_url]
69
- c.vm.host_name = "#{instance.name}.vagrantup.com"
70
-
71
- Array(driver[:forward_port]).each do |ports|
72
- if ports.length != 2
73
- raise ArgumentError,
74
- "Vagrant config.vm.forward_port only accepts two arguments"
75
- end
76
- c.vm.forward_port(*ports)
77
- end
78
-
79
- Array(driver[:network]).each do |network_options|
80
- options = Array(network_options)
81
- type = options.shift
82
- c.vm.network(type.to_sym, *options)
83
- end
84
-
85
- driver[:customize].each do |key, value|
86
- c.vm.customize ["modifyvm", :id, "--#{key}", value]
87
- end
88
-
89
- c.vm.provision :chef_solo do |chef|
90
- chef.log_level = config.kitchen.log_level
91
- chef.run_list = instance.run_list
92
- chef.json = instance.attributes
93
- chef.data_bags_path = instance.suite.data_bags_path
94
- chef.roles_path = instance.suite.roles_path
95
- end
96
- end
97
- end
98
- end
99
- end
100
-
101
- Vagrant.config_keys.register(:kitchen) { Kitchen::Vagrant::Config }