remy 0.0.1

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/lib/remy/remy.rb ADDED
@@ -0,0 +1,140 @@
1
+ #--
2
+ # Copyright (c) 2011 Gregory S. Woodward
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ module Remy
25
+ class Configuration
26
+ attr_accessor :yml_files, :cookbook_path, :spec_path, :remote_chef_dir, :node_attributes, :roles_path
27
+
28
+ def initialize
29
+ @yml_files = []
30
+ @node_attributes = {}
31
+ end
32
+ end
33
+
34
+ class << self
35
+ include ::Remy::Shell
36
+ include FileUtils
37
+
38
+ def configure
39
+ @config_instance = Configuration.new
40
+ yield @config_instance
41
+ @configuration = Hashie::Mash.new({:yml_files => [@config_instance.yml_files].compact.flatten,
42
+ :remote_chef_dir => (@config_instance.remote_chef_dir || '/var/chef'),
43
+ :roles_path => [@config_instance.roles_path].compact.flatten,
44
+ :spec_path => [@config_instance.spec_path].compact.flatten,
45
+ :cookbook_path => [@config_instance.cookbook_path].compact.flatten}.merge!(@config_instance.node_attributes))
46
+
47
+ @config_instance.yml_files.each do |filename|
48
+ begin
49
+ configuration.deep_merge!(YAML.load(ERB.new(File.read(filename)).result) || {})
50
+ rescue SystemCallError, IOError
51
+ warn "WARN: #{filename} could not be found!"
52
+ end
53
+ end
54
+ end
55
+
56
+ def configuration
57
+ @configuration ? @configuration : Hashie::Mash.new
58
+ end
59
+
60
+ def to_json
61
+ configuration.to_json
62
+ end
63
+
64
+ def servers
65
+ configuration.servers
66
+ end
67
+
68
+ def find_servers(options = {})
69
+ return nil unless configuration.servers
70
+ Hashie::Mash.new(configuration.servers.inject({}) do |hash, (server_name, server_config)|
71
+ found = options.all? { |(key, value)| server_config[key] == value }
72
+ hash[server_name] = server_config if found
73
+ hash
74
+ end)
75
+ end
76
+
77
+ def find_server(options = {})
78
+ return nil unless configuration.servers
79
+ server_name, server_config = configuration.servers.detect do |(server_name, server_config)|
80
+ options.all? { |(key, value)| server_config[key] == value }
81
+ end
82
+ {server_name => server_config.nil? ? nil : server_config.dup}
83
+ end
84
+
85
+ def find_server_config(options = {})
86
+ find_server(options).try(:values).try(:first)
87
+ end
88
+
89
+ def find_server_config_by_name(name)
90
+ return nil unless configuration.servers
91
+ configuration.servers.find {|(server_name, _)| server_name == name}.try(:last)
92
+ end
93
+
94
+ def cloud_configuration
95
+ configuration && configuration.cloud_configuration
96
+ end
97
+
98
+ def bootstrap
99
+ configuration && configuration.bootstrap
100
+ end
101
+
102
+ def determine_ip_addresses_for_remy_run(rake_args)
103
+ ip_addresses = []
104
+ if options_hash = convert_properties_to_hash(rake_args)
105
+ servers = find_servers(options_hash)
106
+ if !servers.empty?
107
+ ip_addresses = servers.collect {|server_name, chef_option| chef_option.ip_address }
108
+ else
109
+ ip_addresses = [options_hash[:ip_address]]
110
+ end
111
+ else
112
+ names_or_ip_addresses = rake_args.split(' ').collect {|name| name.strip }
113
+ names_or_ip_addresses.each do |name_or_ip_address|
114
+ # From: http://www.regular-expressions.info/examples.html
115
+ ip_address_regex = '\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b'
116
+ if name_or_ip_address.match(ip_address_regex)
117
+ ip_addresses << name_or_ip_address
118
+ elsif server_config = find_server_config_by_name(name_or_ip_address)
119
+ ip_addresses << server_config.ip_address
120
+ end
121
+ end
122
+ ip_addresses << configuration.ip_address
123
+ end
124
+ ip_addresses.compact
125
+ end
126
+
127
+ # Converts "foo:bar baz:blech" to {:foo => 'bar', :baz => 'blech'}
128
+ def convert_properties_to_hash(properties)
129
+ if properties =~ /:/
130
+ properties.split(' ').inject({}) do |result, pair|
131
+ key, value = pair.split(':')
132
+ result[key] = value
133
+ result
134
+ end.symbolize_keys
135
+ else
136
+ nil
137
+ end
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,71 @@
1
+ class Remy::Server
2
+ attr_reader :server_name, :cloud_api_key, :cloud_username, :cloud_provider, :flavor_id, :image_id, :server
3
+
4
+ def initialize(options = {})
5
+ options = {
6
+ :flavor_id => 4, # 2GB
7
+ :image_id => 49, # Ubuntu 10.04 LTS (lucid)
8
+ :quiet => false
9
+ }.merge(Remy.cloud_configuration || {}).merge(options || {}).symbolize_keys
10
+
11
+ @server_name = options[:server_name]
12
+ @cloud_api_key = options[:cloud_api_key]
13
+ @cloud_username = options[:cloud_username]
14
+ @cloud_provider = options[:cloud_provider]
15
+ @flavor_id = options[:flavor_id]
16
+ @image_id = options[:image_id]
17
+ @quiet = options[:quiet]
18
+ @raise_exception = options[:raise_exception]
19
+ @server = nil
20
+ end
21
+
22
+ def create
23
+ compute = Fog::Compute.new(
24
+ :provider => cloud_provider,
25
+ :rackspace_api_key => cloud_api_key,
26
+ :rackspace_username => cloud_username
27
+ )
28
+
29
+ @server = compute.servers.create(:flavor_id => flavor_id.to_i, :image_id => image_id.to_i, :name => server_name)
30
+ server.wait_for do
31
+ print '.'
32
+ STDOUT.flush
33
+ ready?
34
+ end
35
+ print server_info
36
+ {:ip_address => server.public_ip_address, :password => server.password}
37
+ rescue Exception => e
38
+ puts 'Failed!'
39
+ p e
40
+ raise e if raise_exception?
41
+ {}
42
+ end
43
+
44
+ private
45
+ def server_info
46
+ <<-SERVER_INFO
47
+
48
+
49
+ Server name: #{server.name}
50
+ root password: #{server.password}
51
+ RAM: #{server.flavor.ram} MB
52
+ Image: #{server.image.name}
53
+ IP address: #{server.public_ip_address}
54
+ Private IP address: #{server.addresses['private'][0]}
55
+
56
+ SERVER_INFO
57
+
58
+ end
59
+
60
+ def print *args
61
+ Kernel.print(*args) unless quiet?
62
+ end
63
+
64
+ def quiet?
65
+ @quiet
66
+ end
67
+
68
+ def raise_exception?
69
+ @raise_exception
70
+ end
71
+ end
data/lib/remy/shell.rb ADDED
@@ -0,0 +1,26 @@
1
+ module Remy
2
+ module Shell
3
+ def execute(command)
4
+ if quiet?
5
+ `#{command} 2>&1`
6
+ $?.success?
7
+ else
8
+ puts "Running command: #{command}"
9
+ system command
10
+ end
11
+ end
12
+
13
+ def remote_execute(cmd)
14
+ raise ArgumentError.new unless ip_address
15
+ execute "ssh -T #{user}@#{ip_address} '#{cmd.strip}'"
16
+ end
17
+
18
+ def user
19
+ 'root'
20
+ end
21
+
22
+ def quiet?
23
+ false
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,3 @@
1
+ module Remy
2
+ VERSION = "0.0.1"
3
+ end
data/lib/remy.rb ADDED
@@ -0,0 +1,56 @@
1
+ #--
2
+ # Copyright (c) 2011 Gregory S. Woodward
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ begin
25
+ require 'active_support/core_ext/object/to_json'
26
+ rescue LoadError
27
+ require 'active_support/json/encoders/object'
28
+ end
29
+
30
+ begin
31
+ require 'active_support/core_ext/object/try'
32
+ rescue LoadError
33
+ require 'active_support/core_ext/try'
34
+ end
35
+
36
+ require 'active_support/core_ext/hash'
37
+ require 'fog'
38
+ require 'erb'
39
+ require 'json'
40
+ require 'hashie'
41
+ require 'tmpdir'
42
+ require 'remy/shell'
43
+ require 'yaml'
44
+ dir = File.dirname(__FILE__)
45
+ Dir[File.join(File.dirname(__FILE__), 'remy', '**', '*.rb')].each {|f| require f.gsub(dir, '')[1, f.length] }
46
+
47
+ module Remy
48
+ begin
49
+ class Railtie < ::Rails::Railtie
50
+ rake_tasks do
51
+ load 'tasks/remy.rake'
52
+ end
53
+ end
54
+ rescue LoadError, NameError
55
+ end
56
+ end
@@ -0,0 +1,51 @@
1
+ require 'remy'
2
+
3
+ namespace :remy do
4
+ task :environment do
5
+ begin
6
+ Rake::Task[:environment].invoke
7
+ rescue RuntimeError
8
+ end
9
+ end
10
+
11
+ desc 'ssh to a named box'
12
+ task :ssh, :rake_args do |task, options|
13
+ Rake::Task[:'remy:environment'].invoke
14
+ user = Remy.configuration.user || 'root'
15
+ if ip_address = Remy.determine_ip_addresses_for_remy_run(options[:rake_args]).try(:first)
16
+ exec "ssh #{user}@#{ip_address}"
17
+ end
18
+ end
19
+
20
+ namespace :chef do
21
+ desc 'run chef solo'
22
+ task :run, :rake_args do |task, options|
23
+ Rake::Task[:'remy:environment'].invoke
24
+ Remy::Chef.rake_run(options[:rake_args])
25
+ end
26
+ end
27
+
28
+ namespace :server do
29
+ desc 'create a server'
30
+ task :create, :server_name, :flavor_id, :cloud_api_key, :cloud_username, :cloud_provider, :image_id do |task, options|
31
+ Rake::Task[:'remy:environment'].invoke
32
+ Remy::Server.new(options).create
33
+ end
34
+
35
+ desc 'bootstrap chef'
36
+ task :bootstrap, :ip_address, :password do |task, options|
37
+ Rake::Task[:'remy:environment'].invoke
38
+ Remy::Bootstrap.new(options).run
39
+ end
40
+
41
+ desc 'create a server and bootstrap chef'
42
+ task :create_and_bootstrap, :server_name, :flavor_id, :cloud_api_key, :cloud_username, :cloud_provider, :image_id do |task, options|
43
+ Rake::Task[:'remy:environment'].invoke
44
+ begin
45
+ result = Remy::Server.new({:raise_exception => true}.merge(options)).create
46
+ Rake::Task[:'remy:server:bootstrap'].invoke(result[:ip_address], result[:password])
47
+ rescue Exception => e
48
+ end
49
+ end
50
+ end
51
+ end
data/remy.gemspec ADDED
@@ -0,0 +1,31 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path('../lib', __FILE__)
3
+ require 'remy/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'remy'
7
+ s.version = Remy::VERSION
8
+ s.authors = ['Greg Woodward & Ryan Dy']
9
+ s.email = ['pair+gwoodward+rdy@pivotallabs.com']
10
+ s.homepage = 'http://sharespost.com'
11
+ s.summary = %q{Remy gem}
12
+ s.description = %q{Easy chef deployment}
13
+
14
+ s.rubyforge_project = 'remy'
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ['lib']
20
+
21
+ # specify any dependencies here; for example:
22
+ s.add_development_dependency 'bourne'
23
+ s.add_development_dependency 'mocha'
24
+ s.add_development_dependency 'i18n'
25
+ s.add_development_dependency 'json'
26
+ s.add_development_dependency 'rspec', '~> 2.7.0'
27
+ s.add_runtime_dependency 'activesupport', '>= 2'
28
+ s.add_runtime_dependency 'chef'
29
+ s.add_runtime_dependency 'fog'
30
+ s.add_runtime_dependency 'hashie'
31
+ end
@@ -0,0 +1,7 @@
1
+ baz:
2
+ baz
3
+ another_node_attribute:
4
+ hot
5
+ colors:
6
+ blue: 'blue'
7
+ green: 'green'
@@ -0,0 +1,44 @@
1
+ app_server: &APP
2
+ recipes:
3
+ - recipe[hello_world]
4
+ database_server: &DB
5
+ adapter: mysql2
6
+ encoding: utf8
7
+
8
+ rails_env: bogus_and_should_be_overridden_by_value_in_servers_section
9
+
10
+ servers:
11
+ web.sharespost.com:
12
+ <<: *APP
13
+ ip_address: <%= IP_ADDRESS %>
14
+ rails_env: demo
15
+ color: blue
16
+
17
+ db.sharespost.com:
18
+ <<: *DB
19
+ ip_address: 51.51.51.51
20
+ rails_env: production
21
+ color: yellow
22
+
23
+ demo.sharespost.com:
24
+ <<: *DB
25
+ <<: *APP
26
+ ip_address: 52.52.52.52
27
+ rails_env: demo
28
+ color: green
29
+
30
+ cloud_configuration:
31
+ cloud_provider: Rackspace
32
+ cloud_username: sharespost
33
+ cloud_api_key: abcdefg12345
34
+ flavor_id: 4
35
+ image_id: 49
36
+ server_name: new-server.somedomain.com
37
+
38
+ bootstrap:
39
+ ruby_version: 1.9.2
40
+ gems:
41
+ bundler: 1.0.21
42
+ chef: 0.10.4
43
+ rspec: 2.7.0
44
+
@@ -0,0 +1,5 @@
1
+ blah:
2
+ bar
3
+ colors:
4
+ red: 'red'
5
+ green: 'green'
@@ -0,0 +1,8 @@
1
+ ip_address: <%= IP_ADDRESS %>
2
+ color: blue
3
+ recipes:
4
+ - recipe[hello_world]
5
+ other_data:
6
+ - red
7
+ - yellow
8
+ - blue
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+
3
+ describe Remy::Bootstrap do
4
+ def ruby_version(bootstrap)
5
+ bootstrap.instance_variable_get(:@ruby_version)
6
+ end
7
+
8
+ def gem(bootstrap)
9
+ bootstrap.instance_variable_get(:@gems)
10
+ end
11
+
12
+ def ip_address(bootstrap)
13
+ bootstrap.instance_variable_get(:@ip_address)
14
+ end
15
+
16
+ describe "ruby_version" do
17
+ it 'should default to 1.8.7 if there is no Ruby version specified in the yml files' do
18
+ Remy.configure { |config| config.yml_files = File.join(File.dirname(__FILE__), '../fixtures/hello_world_chef.yml') }
19
+ bootstrap = Remy::Bootstrap.new
20
+ ruby_version(bootstrap).should == '1.8.7'
21
+ end
22
+
23
+ it 'should get the Ruby version if specified in the yml files' do
24
+ Remy.configure { |config| config.yml_files = File.join(File.dirname(__FILE__), '../fixtures/chef.yml') }
25
+ bootstrap = Remy::Bootstrap.new
26
+ ruby_version(bootstrap).should == '1.9.2'
27
+ end
28
+
29
+ it 'should use the version passed in as an option, even if it exists in the yml files' do
30
+ Remy.configure { |config| config.yml_files = File.join(File.dirname(__FILE__), '../fixtures/chef.yml') }
31
+ bootstrap = Remy::Bootstrap.new(:ruby_version => '1.9.1')
32
+ ruby_version(bootstrap).should == '1.9.1'
33
+ end
34
+ end
35
+
36
+ describe "gems" do
37
+ it 'should default to nil if not specified in the yml files' do
38
+ Remy.configure { |config| config.yml_files = File.join(File.dirname(__FILE__), '../fixtures/hello_world_chef.yml') }
39
+ bootstrap = Remy::Bootstrap.new
40
+ gem(bootstrap)[:chef].should be_nil
41
+ gem(bootstrap)[:bundler].should be_nil
42
+ gem(bootstrap)[:rspec].should be_nil
43
+ end
44
+
45
+ it 'should get gem version if it has been specified in the yml files' do
46
+ Remy.configure { |config| config.yml_files = File.join(File.dirname(__FILE__), '../fixtures/chef.yml') }
47
+ bootstrap = Remy::Bootstrap.new
48
+ gem(bootstrap)[:chef].should == '0.10.4'
49
+ gem(bootstrap)[:bundler].should == '1.0.21'
50
+ gem(bootstrap)[:rspec].should == '2.7.0'
51
+ end
52
+ end
53
+
54
+ describe "ip_address" do
55
+ it 'should use the value from the options' do
56
+ Remy.configure { |config| config.yml_files = File.join(File.dirname(__FILE__), '../fixtures/hello_world_chef.yml') }
57
+ bootstrap = Remy::Bootstrap.new(:ip_address => '1.2.3.4', :password => 'abcdef')
58
+ ip_address(bootstrap).should == '1.2.3.4'
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,82 @@
1
+ require 'spec_helper'
2
+
3
+ describe Remy::Chef do
4
+ def node_configuration(chef)
5
+ chef.instance_variable_get(:@node_configuration)
6
+ end
7
+
8
+ describe "#initialize and the node configuration" do
9
+ it 'should use the top-level IP address in the yml files, if one is present, and an ip address is not passed in as an argument' do
10
+ Remy.configure { |config| config.yml_files = File.join(File.dirname(__FILE__), '../fixtures/hello_world_chef.yml') }
11
+ chef = Remy::Chef.new
12
+ node_configuration(chef).ip_address.should == IP_ADDRESS
13
+ node_configuration(chef).color.should == 'blue'
14
+ node_configuration(chef).recipes.should == ['recipe[hello_world]']
15
+ end
16
+
17
+ it 'should allow the top-level values in the yml files (including the ip address) to be overridden' do
18
+ Remy.configure { |config| config.yml_files = File.join(File.dirname(__FILE__), '../fixtures/hello_world_chef.yml') }
19
+ chef = Remy::Chef.new(:ip_address => '1.2.3.4', :color => 'green')
20
+ node_configuration(chef).ip_address.should == '1.2.3.4'
21
+ node_configuration(chef).color.should == 'green'
22
+ node_configuration(chef).recipes.should == ['recipe[hello_world]']
23
+ end
24
+
25
+ it 'should return properties from the :servers section of the yml file if the ip address is found in there' do
26
+ Remy.configure { |config| config.yml_files = File.join(File.dirname(__FILE__), '../fixtures/chef.yml') }
27
+ chef = Remy::Chef.new(:ip_address => '51.51.51.51')
28
+ node_configuration(chef).ip_address.should == '51.51.51.51'
29
+ node_configuration(chef).rails_env.should == 'production'
30
+ node_configuration(chef).color.should == 'yellow'
31
+ node_configuration(chef).adapter.should == 'mysql2'
32
+ node_configuration(chef).encoding.should == 'utf8'
33
+ end
34
+
35
+ it 'should allow properties from the servers section of the yml file to be overridden plus additional options added' do
36
+ Remy.configure { |config| config.yml_files = File.join(File.dirname(__FILE__), '../fixtures/chef.yml') }
37
+ chef = Remy::Chef.new(:ip_address => '51.51.51.51', :color => 'purple', :temperature => 'warm')
38
+ node_configuration(chef).color.should == 'purple' # Overrides 'yellow' from the yml files
39
+ node_configuration(chef).temperature.should == 'warm' # A new node attribute which is not present in the yml files
40
+ end
41
+
42
+ it 'should allow the chef args to be specified (and not merge this chef_args value into the node configuration)' do
43
+ Remy.configure { |config| config.yml_files = File.join(File.dirname(__FILE__), '../fixtures/chef.yml') }
44
+ chef = Remy::Chef.new(:chef_args => '-l debug')
45
+ node_configuration(chef).chef_args.should be_nil
46
+ chef.instance_variable_get(:@chef_args).should == '-l debug'
47
+ end
48
+
49
+ it 'should allow the quiet option to be specified (and not merge this option into the node configuration)' do
50
+ Remy.configure { |config| config.yml_files = File.join(File.dirname(__FILE__), '../fixtures/chef.yml') }
51
+ chef = Remy::Chef.new(:quiet => true)
52
+ node_configuration(chef).quiet.should be_nil
53
+ chef.instance_variable_get(:@quiet).should be_true
54
+ end
55
+
56
+ it 'should not modify the global Remy configuration, but rather only the node configuration for this particular Chef node' do
57
+ Remy.configure { |config| config.yml_files = File.join(File.dirname(__FILE__), '../fixtures/bar.yml') }
58
+ Remy.configuration.another_node_attribute.should == 'hot'
59
+ chef = Remy::Chef.new(:another_node_attribute => 'cold')
60
+ node_configuration(chef).another_node_attribute.should == 'cold'
61
+ Remy.configuration.another_node_attribute.should == 'hot' # Unchanged from its original value # do some checks
62
+ end
63
+ end
64
+
65
+ describe '#run' do
66
+ before do
67
+ Remy.configure { |config| config.yml_files = File.join(File.dirname(__FILE__), '../fixtures/chef.yml') }
68
+ end
69
+
70
+ it 'should work with a hash as its argument' do
71
+ chef = Remy::Chef.new(:ip_address => IP_ADDRESS)
72
+ node_configuration(chef).ip_address.should == IP_ADDRESS
73
+ node_configuration(chef).recipes.should == ['recipe[hello_world]']
74
+ end
75
+
76
+ it 'should work with JSON as its argument' do
77
+ chef = Remy::Chef.new("{\"ip_address\":\"#{IP_ADDRESS}\"}")
78
+ node_configuration(chef).ip_address.should == IP_ADDRESS
79
+ node_configuration(chef).recipes.should == ['recipe[hello_world]']
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe Remy::Chef do
4
+ before do
5
+ Remy.configure do |config|
6
+ config.yml_files = ['../../fixtures/foo.yml', '../../fixtures/bar.yml', '../../fixtures/chef.yml'].map { |f| File.join(File.dirname(__FILE__), f) }
7
+ config.cookbook_path = ["../../../chef/cookbooks"].map { |f| File.join(File.dirname(__FILE__), f) }
8
+ config.spec_path = ["../../../chef/spec"].map { |f| File.join(File.dirname(__FILE__), f) }
9
+ end
10
+ end
11
+
12
+ describe '#run' do
13
+ def clean_up_remote_chef_test_files(chef)
14
+ chef.remote_execute "rm -rf /tmp/hello_world.txt #{Remy.configuration.remote_chef_dir}" if Remy.configuration.remote_chef_dir && Remy.configuration.remote_chef_dir.size > 2
15
+ end
16
+
17
+ def verify_contents_of_hello_world(chef)
18
+ chef.remote_execute(%Q{cat /tmp/hello_world.txt | grep "I am feeling blue"}).should be_true
19
+ end
20
+
21
+ def run_chef(options = {})
22
+ chef = Remy::Chef.new(options)
23
+ clean_up_remote_chef_test_files(chef)
24
+ chef.run
25
+ yield chef
26
+ clean_up_remote_chef_test_files(chef)
27
+ end
28
+
29
+ it 'should work with a hash as its argument' do
30
+ run_chef(:ip_address => IP_ADDRESS) do |chef|
31
+ verify_contents_of_hello_world(chef)
32
+ end
33
+ end
34
+
35
+ it 'should work with JSON as its argument' do
36
+ run_chef("{\"ip_address\":\"#{IP_ADDRESS}\"}") do |chef|
37
+ verify_contents_of_hello_world(chef)
38
+ end
39
+ end
40
+ end
41
+ end