vagrant-recipe 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.
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ # We depend on Vagrant for development, but we don't add it as a
7
+ # gem dependency because we expect to be installed within the
8
+ # Vagrant environment itself using `vagrant plugin`.
9
+ gem 'vagrant', git: 'git://github.com/mitchellh/vagrant.git'
10
+ end
data/LICENSE.md ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2013-2013 Raul Simiciuc
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,87 @@
1
+ vagrant-recipe [![Gem Version](https://badge.fury.io/rb/vagrant-exec.png)](http://badge.fury.io/rb/vagrant-exec)
2
+ ===============
3
+
4
+ Vagrant plugin to execute chef recipes.
5
+
6
+ Description
7
+ -----------
8
+
9
+ Use this plugin to run your recipes at any time.
10
+
11
+ Example
12
+ -------
13
+
14
+ ```shell
15
+ ➜ vagrant run-recipe SystemSetup::default
16
+ ```
17
+
18
+ Installation
19
+ ------------
20
+
21
+ ```shell
22
+ ➜ vagrant plugin install vagrant-recipe
23
+ ```
24
+
25
+ Configuration
26
+ -------------
27
+
28
+ ### Chef exec file and chef json config file
29
+
30
+ The root directory can be configured using Vagrantfile.
31
+
32
+ ```ruby
33
+ Vagrant.configure('2') do |config|
34
+ config.vm.box = 'precise32'
35
+ # set this value if your solo exec file is different from /tmp/vagrant-chef-1/solo.rb
36
+ config.recipe.chef = '/tmp/vagrant-chef-1/solo.rb'
37
+
38
+ # set this value if your json confi file is different from /tmp/vagrant-chef-1/dna.json
39
+ config.recipe.json = '/tmp/vagrant-chef-1/dna.json'
40
+ end
41
+ ```
42
+
43
+ ```shell
44
+ ➜ vagrant run-recipe SystemSetup
45
+ # is the same as
46
+ ➜ vagrant ssh -c "sudo chef-solo -c /tmp/vagrant-chef-1/solo.rb -j /tmp/vagrant-chef-1/dna.json --override-runlist \"recipe[SystemSetup::default]\""
47
+ ```
48
+
49
+ ### Bundler
50
+
51
+ You can enable bundler to prepend each command with `bundle exec`. Note that it won't be done for commands starting with `bundle` (e.g. `bundle install`).
52
+
53
+ ```ruby
54
+ Vagrant.configure('2') do |config|
55
+ config.vm.box = 'precise32'
56
+ config.recipe.bundler = true
57
+ end
58
+ ```
59
+
60
+ ```shell
61
+ ➜ vagrant recipe SystemSetup
62
+ # is the same as
63
+ ➜ vagrant ssh -c "cd /vagrant && bundle exec sudo chef-solo -c /tmp/vagrant-chef-1/solo.rb -j /tmp/vagrant-chef-1/dna.json --override-runlist \"recipe[SystemSetup::default]\""
64
+ ```
65
+
66
+ ### Environment variables
67
+
68
+ You can add environment variables to be exported before.
69
+
70
+ ```ruby
71
+ Vagrant.configure('2') do |config|
72
+ config.vm.box = 'precise32'
73
+ config.recipe.env['RAILS_ENV'] = 'test'
74
+ config.recipe.env['RAILS_ROOT'] = '/vagrant'
75
+ end
76
+ ```
77
+
78
+ ```shell
79
+ ➜ vagrant exec SystemSetup
80
+ # is the same as
81
+ ➜ vagrant ssh -c "export RAILS_ENV=test && export RAILS_ROOT=/vagrant && sudo chef-solo -c /tmp/vagrant-chef-1/solo.rb -j /tmp/vagrant-chef-1/dna.json --override-runlist \"recipe[SystemSetup::default]\""
82
+ ```
83
+
84
+ Copyright
85
+ ---------
86
+
87
+ Copyright (c) 2013-2013 Raul Simiciuc. See LICENSE.md for details.
data/Rakefile ADDED
@@ -0,0 +1,20 @@
1
+ require 'bundler'
2
+ require 'cucumber/rake/task'
3
+ Bundler::GemHelper.install_tasks
4
+
5
+ namespace :features do
6
+ desc 'Downloads and adds vagrant box for testing.'
7
+ task(:bootstrap) do
8
+ system('bundle exec vagrant box add vagrant_recipe http://cloud-images.ubuntu.com/vagrant/precise/current/precise-server-cloudimg-amd64-vagrant-disk1.box')
9
+ end
10
+
11
+ Cucumber::Rake::Task.new(:run) do |t|
12
+ t.cucumber_opts = %w(--format pretty)
13
+ end
14
+
15
+ desc 'Removes testing vagrant box .'
16
+ task(:cleanup) do
17
+ system('bundle exec vagrant destroy -f')
18
+ system('bundle exec vagrant box remove vagrant_recipe virtualbox')
19
+ end
20
+ end
@@ -0,0 +1,49 @@
1
+ Given(/^I have default Vagrantfile$/) do
2
+ vagrantfile = <<-RUBY
3
+ Vagrant.require_plugin 'vagrant-exec'
4
+
5
+ Vagrant.configure('2') do |config|
6
+ config.vm.box = 'vagrant_exec'
7
+ end
8
+ RUBY
9
+ step 'a file named "Vagrantfile" with:', vagrantfile
10
+ end
11
+
12
+
13
+ Given(/^I set vagrant-exec folder to (.+)$/) do |folder|
14
+ config = <<-RUBY
15
+
16
+ Vagrant.configure('2') do |config|
17
+ config.exec.folder = #{folder}
18
+ end
19
+ RUBY
20
+ step 'I append to "Vagrantfile" with:', config
21
+ end
22
+
23
+
24
+ Given(/^I set vagrant-exec bundler to (.+)$/) do |bundler|
25
+ config = <<-RUBY
26
+
27
+ Vagrant.configure('2') do |config|
28
+ config.exec.bundler = #{bundler}
29
+ end
30
+ RUBY
31
+ step 'I append to "Vagrantfile" with:', config
32
+ end
33
+
34
+
35
+ Given(/^I set vagrant-exec env with the following values:$/) do |table|
36
+ data = table.hashes
37
+ config = data.map do |hash|
38
+ key, value = "#{hash['key']}", "#{hash['value']}"
39
+ %(config.exec.env['#{key}'] = '#{value}')
40
+ end
41
+
42
+ config = <<-RUBY
43
+
44
+ Vagrant.configure('2') do |config|
45
+ #{config.join("\n\s\s")}
46
+ end
47
+ RUBY
48
+ step 'I append to "Vagrantfile" with:', config
49
+ end
@@ -0,0 +1,12 @@
1
+ require 'aruba/cucumber'
2
+ ENV['VAGRANT_LOG'] = 'info'
3
+
4
+ Before do
5
+ # VM start takes a long time
6
+ @aruba_timeout_seconds = 60
7
+ end
8
+
9
+ After do
10
+ # halt VM
11
+ system "cd tmp/aruba; bundle exec vagrant halt &> /dev/null"
12
+ end
@@ -0,0 +1,91 @@
1
+ @no-clobber
2
+ Feature: vagrant-exec
3
+ In order to execute commands in Vagrant box
4
+ Within context of root synced folder
5
+ As a developer using vagrant-exec plugin
6
+ I want to use "vagrant exec" command
7
+ And be able to customize folder
8
+ And prepend commands with "bundle exec"
9
+ And set exported environmental variables
10
+ Using Vagrantfile configuration
11
+
12
+ Background:
13
+ Given I have default Vagrantfile
14
+
15
+ Scenario: uses /vagrant as default folder
16
+ Given I run `bundle exec vagrant up`
17
+ When I run `bundle exec vagrant exec pwd`
18
+ Then the exit status should be 0
19
+ And the output should contain "Executing single command on remote machine: cd /vagrant && pwd"
20
+
21
+ Scenario: can use custom folder
22
+ Given I set vagrant-exec folder to "/tmp"
23
+ And I run `bundle exec vagrant up`
24
+ When I run `bundle exec vagrant exec pwd`
25
+ Then the exit status should be 0
26
+ And the output should contain "Executing single command on remote machine: cd /tmp && pwd"
27
+
28
+ Scenario: raises error if folder is improperly set
29
+ Given I set vagrant-exec folder to true
30
+ And I run `bundle exec vagrant up`
31
+ Then the exit status should not be 0
32
+ And the output should contain "folder should be a string"
33
+
34
+ Scenario: does not use bundler by default
35
+ Given I run `bundle exec vagrant up`
36
+ When I run `bundle exec vagrant exec pwd`
37
+ Then the output should not contain "bundle exec"
38
+
39
+ # we don't have bundler in box
40
+ Scenario: can use bundler
41
+ Given I set vagrant-exec bundler to true
42
+ And I run `bundle exec vagrant up`
43
+ When I run `bundle exec vagrant exec pwd`
44
+ Then the exit status should not be 0
45
+ And the output should contain "Executing single command on remote machine: cd /vagrant && bundle exec pwd"
46
+
47
+ Scenario: does not use bundler for bundle commands
48
+ Given I set vagrant-exec bundler to true
49
+ And I run `bundle exec vagrant up`
50
+ When I run `bundle exec vagrant exec bundle install`
51
+ Then the output should contain "Executing single command on remote machine: cd /vagrant && bundle install"
52
+
53
+ Scenario: raises error if bundler is improperly set
54
+ Given I set vagrant-exec bundler to "true"
55
+ When I run `bundle exec vagrant up`
56
+ Then the exit status should not be 0
57
+ And the output should contain "bundler should be boolean"
58
+
59
+ Scenario: can export environment variables
60
+ Given I set vagrant-exec env with the following values:
61
+ | key | value |
62
+ | TEST1 | true |
63
+ | TEST2 | false |
64
+ And I run `bundle exec vagrant up`
65
+ When I run `bundle exec vagrant exec pwd`
66
+ Then the exit status should be 0
67
+ And the output should contain "Executing single command on remote machine: cd /vagrant && export TEST1=true && export TEST2=false && pwd"
68
+
69
+ Scenario Outline: shows help correctly
70
+ Given I run `bundle exec vagrant up`
71
+ When I run `bundle exec vagrant exec <args>`
72
+ Then the output should contain "Usage: vagrant exec [options] <command>"
73
+ Examples:
74
+ | args |
75
+ | |
76
+ | -h |
77
+ | --help |
78
+ | -h pwd |
79
+ | --help pwd -h |
80
+
81
+ Scenario Outline: passes command arguments correctly
82
+ Given I run `bundle exec vagrant up`
83
+ When I run `bundle exec vagrant exec <cmd>`
84
+ Then the output should contain "Executing single command on remote machine: cd /vagrant && <cmd>"
85
+ Examples:
86
+ | cmd |
87
+ | cwd . |
88
+ | cwd ~ |
89
+ | cwd -h |
90
+ | cwd --blah |
91
+ | cwd -h blah -v blah |
@@ -0,0 +1,72 @@
1
+ module VagrantPlugins
2
+ module Recipe
3
+ class Command < Vagrant.plugin(2, :command)
4
+
5
+ def execute
6
+ cmd, cmd_args = parse_args
7
+ cmd && cmd_args or return nil
8
+
9
+ # Execute the actual SSH
10
+ with_target_vms(nil, single_target: true) do |vm|
11
+ vm.config.recipe.finalize! # TODO: do we have to call it explicitly?
12
+
13
+ plain = "sudo chef-solo -c #{vm.config.recipe.chef} -j #{vm.config.recipe.json} --override-runlist \"recipe[#{cmd}]\""
14
+ command = ""
15
+
16
+ command << add_env(vm.config.exec.env)
17
+ command << add_bundler(vm.config.exec.bundler, plain)
18
+ command << plain
19
+
20
+ @logger.info("Executing recipe on remote machine: #{command}")
21
+ env = vm.action(:ssh_run, ssh_run_command: command)
22
+
23
+ status = env[:ssh_run_exit_status] || 0
24
+ return status
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def parse_args
31
+ opts = OptionParser.new do |o|
32
+ o.banner = 'Usage: vagrant run-recipe <recipe-name>'
33
+ o.separator ''
34
+
35
+ o.on('-h', '--help', 'Print this help') do
36
+ safe_puts(opts.help)
37
+ end
38
+ end
39
+
40
+ argv = split_main_and_subcommand(@argv.dup)
41
+ exec_args, cmd, cmd_args = argv[0], argv[1], argv[2]
42
+
43
+ # show help
44
+ if !cmd || exec_args.any? { |a| a == '-h' || a == '--help' }
45
+ safe_puts(opts.help)
46
+ return nil
47
+ end
48
+
49
+ return cmd, cmd_args
50
+ end
51
+
52
+ def add_env(env)
53
+ ''.tap do |command|
54
+ if env.any?
55
+ env.each do |key, value|
56
+ command << "export #{key}=#{value} && "
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ def add_bundler(bundler, plain_command)
63
+ ''.tap do |command|
64
+ if bundler && plain_command !~ /^bundle /
65
+ command << 'bundle exec '
66
+ end
67
+ end
68
+ end
69
+
70
+ end # Command
71
+ end # Recipe
72
+ end # VagrantPlugins
@@ -0,0 +1,33 @@
1
+ module VagrantPlugins
2
+ module Recipe
3
+ class Config < Vagrant.plugin(2, :config)
4
+
5
+ attr_reader :env
6
+ attr_accessor :bundler
7
+ attr_accessor :chef
8
+ attr_accessor :json
9
+
10
+ def initialize
11
+ @env = {}
12
+ @bundler = UNSET_VALUE
13
+ @chef = UNSET_VALUE
14
+ @json = UNSET_VALUE
15
+ end
16
+
17
+ def validate(_)
18
+ return { 'exec' => ['bundler should be boolean'] } unless [true, false].include?(@bundler)
19
+ return { 'exec' => ['chef should be a string'] } unless @chef.is_a?(String)
20
+ return { 'exec' => ['json should be a string'] } unless @json.is_a?(String)
21
+
22
+ {}
23
+ end
24
+
25
+ def finalize!
26
+ @chef = '/tmp/vagrant-chef-1/solo.rb' if @chef == UNSET_VALUE
27
+ @json = '/tmp/vagrant-chef-1/dna.json' if @json == UNSET_VALUE
28
+ @bundler = false if @bundler == UNSET_VALUE
29
+ end
30
+
31
+ end # Config
32
+ end # Recipe
33
+ end # VagrantPlugins
@@ -0,0 +1,20 @@
1
+ module VagrantPlugins
2
+ module Recipe
3
+ class Plugin < Vagrant.plugin(2)
4
+
5
+ name 'Vagrant Recipe'
6
+ description 'Plugin allows to execute a chef recipe.'
7
+
8
+ config :run-recipe do
9
+ require_relative 'config'
10
+ Config
11
+ end
12
+
13
+ command :run-recipe do
14
+ require_relative 'command'
15
+ Command
16
+ end
17
+
18
+ end # Plugin
19
+ end # Recipe
20
+ end # VagrantPlugins
@@ -0,0 +1,7 @@
1
+ module VagrantPlugins
2
+ module Recipe
3
+
4
+ VERSION = '0.1.0'
5
+
6
+ end # Recipe
7
+ end # VagrantPlugins
@@ -0,0 +1,4 @@
1
+ require 'vagrant'
2
+
3
+ require 'vagrant-recipe/plugin'
4
+ require 'vagrant-recipe/version'
@@ -0,0 +1,21 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+ require 'vagrant-recipe/version'
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'vagrant-recipe'
6
+ s.version = VagrantPlugins::Recipe::VERSION
7
+ s.platform = Gem::Platform::RUBY
8
+ s.author = 'Raul Simiciuc'
9
+ s.email = 'byraul@gmail.com'
10
+ s.homepage = 'http://github.com/rsimiciuc/vagrant-recipe'
11
+ s.summary = 'Execute chef recipes'
12
+ s.description = 'Vagrant plugin to execute chef recipes'
13
+
14
+ s.files = `git ls-files`.split("\n")
15
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
+ s.require_paths = %w(lib)
18
+
19
+ s.add_development_dependency 'aruba'
20
+ s.add_development_dependency 'rake'
21
+ end
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: vagrant-recipe
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Raul Simiciuc
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-10-20 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: aruba
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
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: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
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
+ description: Vagrant plugin to execute chef recipes
47
+ email: byraul@gmail.com
48
+ executables: []
49
+ extensions: []
50
+ extra_rdoc_files: []
51
+ files:
52
+ - Gemfile
53
+ - LICENSE.md
54
+ - README.md
55
+ - Rakefile
56
+ - features/step_definitions/steps.rb
57
+ - features/support/env.rb
58
+ - features/vagrant-recipe.feature
59
+ - lib/vagrant-recipe.rb
60
+ - lib/vagrant-recipe/command.rb
61
+ - lib/vagrant-recipe/config.rb
62
+ - lib/vagrant-recipe/plugin.rb
63
+ - lib/vagrant-recipe/version.rb
64
+ - vagrant-recipe.gemspec
65
+ homepage: http://github.com/rsimiciuc/vagrant-recipe
66
+ licenses: []
67
+ post_install_message:
68
+ rdoc_options: []
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ none: false
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ requirements: []
84
+ rubyforge_project:
85
+ rubygems_version: 1.8.23
86
+ signing_key:
87
+ specification_version: 3
88
+ summary: Execute chef recipes
89
+ test_files: []