cucumber-chef 1.0.3 → 2.0.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (108) hide show
  1. data/.gitignore +8 -35
  2. data/.rspec +1 -0
  3. data/.rvmrc.template +2 -0
  4. data/.travis.yml +22 -0
  5. data/Gemfile +2 -15
  6. data/LICENSE +202 -201
  7. data/NOTICE +9 -0
  8. data/README.md +696 -92
  9. data/Rakefile +39 -25
  10. data/TODO.md +28 -0
  11. data/bin/cc-knife +32 -0
  12. data/bin/cucumber-chef +409 -79
  13. data/chef_repo/cookbooks/cucumber-chef/LICENSE +202 -0
  14. data/chef_repo/cookbooks/cucumber-chef/README.md +69 -0
  15. data/chef_repo/cookbooks/cucumber-chef/attributes/default.rb +27 -0
  16. data/chef_repo/cookbooks/cucumber-chef/metadata.rb +13 -0
  17. data/chef_repo/cookbooks/cucumber-chef/recipes/default.rb +23 -0
  18. data/chef_repo/cookbooks/cucumber-chef/recipes/lxc.rb +315 -0
  19. data/chef_repo/cookbooks/cucumber-chef/recipes/test_lab.rb +146 -0
  20. data/chef_repo/cookbooks/cucumber-chef/templates/default/db-168-192.erb +15 -0
  21. data/chef_repo/cookbooks/cucumber-chef/templates/default/db-test-lab.erb +15 -0
  22. data/chef_repo/cookbooks/cucumber-chef/templates/default/dhcpd-conf.erb +44 -0
  23. data/chef_repo/cookbooks/cucumber-chef/templates/default/gemrc.erb +10 -0
  24. data/{cookbooks/cucumber-chef/files/default/cucumber-net → chef_repo/cookbooks/cucumber-chef/templates/default/lxc-initializer-config.erb} +1 -1
  25. data/chef_repo/cookbooks/cucumber-chef/templates/default/lxc-install-chef.erb +3 -0
  26. data/chef_repo/cookbooks/cucumber-chef/templates/default/motd.erb +10 -0
  27. data/chef_repo/cookbooks/cucumber-chef/templates/default/named-conf-local.erb +25 -0
  28. data/{cookbooks/cucumber-chef/files/default/permissive-ssh-config → chef_repo/cookbooks/cucumber-chef/templates/default/ssh-config.erb} +3 -1
  29. data/chef_repo/roles/test_lab.rb +24 -0
  30. data/cucumber-chef.gemspec +50 -123
  31. data/examples/README.md +7 -0
  32. data/examples/users_add.feature +51 -0
  33. data/examples/users_auto_remove.feature +50 -0
  34. data/features/support/env.rb +3 -2
  35. data/lib/cucumber/chef/bootstrap.rb +94 -0
  36. data/lib/cucumber/chef/command.rb +78 -0
  37. data/lib/cucumber/chef/config.rb +143 -93
  38. data/lib/cucumber/chef/helpers/chef_client.rb +87 -0
  39. data/lib/cucumber/chef/helpers/chef_server.rb +90 -0
  40. data/lib/cucumber/chef/helpers/command.rb +57 -0
  41. data/lib/cucumber/chef/helpers/container.rb +154 -0
  42. data/lib/cucumber/chef/helpers/minitest.rb +35 -0
  43. data/lib/cucumber/chef/helpers/server.rb +81 -0
  44. data/lib/cucumber/chef/helpers/test_lab.rb +46 -0
  45. data/lib/cucumber/chef/helpers/utility.rb +73 -0
  46. data/lib/cucumber/chef/helpers.rb +56 -0
  47. data/lib/cucumber/chef/logger.rb +90 -0
  48. data/lib/cucumber/chef/provisioner.rb +275 -69
  49. data/lib/cucumber/chef/ssh.rb +190 -0
  50. data/lib/cucumber/chef/steps/chef_steps.rb +32 -0
  51. data/lib/cucumber/chef/steps/minitest_steps.rb +29 -0
  52. data/lib/cucumber/chef/steps/provision_steps.rb +60 -0
  53. data/lib/cucumber/chef/steps/ssh_steps.rb +95 -0
  54. data/lib/cucumber/chef/steps.rb +27 -0
  55. data/lib/cucumber/chef/tcp_socket.rb +83 -0
  56. data/lib/cucumber/chef/template.rb +57 -0
  57. data/lib/cucumber/chef/templates/bootstrap/ubuntu-precise-test-lab.erb +99 -0
  58. data/lib/cucumber/chef/templates/cucumber/env.rb +56 -0
  59. data/lib/cucumber/chef/templates/cucumber/example_feature.erb +49 -0
  60. data/lib/cucumber/chef/templates/cucumber/example_steps.erb +11 -0
  61. data/lib/cucumber/chef/templates/cucumber/readme-data_bags.erb +1 -0
  62. data/lib/cucumber/chef/templates/cucumber/readme-keys.erb +1 -0
  63. data/lib/cucumber/chef/templates/cucumber/readme-roles.erb +1 -0
  64. data/lib/cucumber/chef/templates/cucumber/readme.erb +18 -0
  65. data/lib/cucumber/chef/templates/cucumber-chef/config-rb.erb +33 -0
  66. data/lib/cucumber/chef/templates/cucumber-chef/cucumber-yml.erb +2 -0
  67. data/lib/cucumber/chef/templates/cucumber-chef/knife-rb.erb +18 -0
  68. data/lib/cucumber/chef/test_lab.rb +308 -52
  69. data/lib/cucumber/chef/test_runner.rb +86 -15
  70. data/lib/cucumber/chef/utility.rb +128 -0
  71. data/lib/cucumber/chef/version.rb +30 -1
  72. data/lib/cucumber/chef.rb +53 -20
  73. data/lib/cucumber-chef.rb +24 -1
  74. data/spec/cucumber/chef/config_spec.rb +144 -78
  75. data/spec/cucumber/chef/provisioner_spec.rb +60 -16
  76. data/spec/cucumber/chef/test_lab_spec.rb +62 -19
  77. data/spec/spec_helper.rb +30 -26
  78. data/todo.org +17 -0
  79. metadata +267 -163
  80. data/.document +0 -5
  81. data/VERSION +0 -1
  82. data/cookbooks/cucumber-chef/README.rdoc +0 -8
  83. data/cookbooks/cucumber-chef/files/default/add-git-identity +0 -2
  84. data/cookbooks/cucumber-chef/files/default/controller-first-boot +0 -1
  85. data/cookbooks/cucumber-chef/files/default/cucumber-private-key +0 -27
  86. data/cookbooks/cucumber-chef/files/default/cucumber-run_list +0 -1
  87. data/cookbooks/cucumber-chef/files/default/git-private-key +0 -27
  88. data/cookbooks/cucumber-chef/files/default/install-chef +0 -1
  89. data/cookbooks/cucumber-chef/files/default/lxc-controller-network-config +0 -5
  90. data/cookbooks/cucumber-chef/files/default/lxc-lucid-chef +0 -378
  91. data/cookbooks/cucumber-chef/metadata.rb +0 -6
  92. data/cookbooks/cucumber-chef/recipes/controller.rb +0 -51
  93. data/cookbooks/cucumber-chef/recipes/lxc.rb +0 -35
  94. data/cookbooks/cucumber-chef/recipes/test_lab.rb +0 -23
  95. data/cookbooks/cucumber-chef/recipes/testrunner.rb +0 -46
  96. data/cookbooks/cucumber-chef/roles/controller.rb +0 -7
  97. data/cookbooks/cucumber-chef/roles/test_lab_test.rb +0 -9
  98. data/cookbooks/cucumber-chef/templates/default/controller-client.erb +0 -5
  99. data/cookbooks/cucumber-chef/templates/default/lxc-lucid-chef +0 -385
  100. data/lib/cucumber/chef/handy.rb +0 -90
  101. data/lib/cucumber/chef/templates/controller.erb +0 -35
  102. data/lib/cucumber/chef/templates/env.rb +0 -16
  103. data/lib/cucumber/chef/templates/example_feature.erb +0 -11
  104. data/lib/cucumber/chef/templates/example_step.erb +0 -19
  105. data/lib/cucumber/chef/templates/readme.erb +0 -14
  106. data/lib/cucumber/chef/templates/ubuntu10.04-gems.erb +0 -43
  107. data/lib/cucumber/ec2_server_create.rb +0 -99
  108. data/website/website.html +0 -385
@@ -0,0 +1,94 @@
1
+ ################################################################################
2
+ #
3
+ # Author: Stephen Nelson-Smith <stephen@atalanta-systems.com>
4
+ # Author: Zachary Patten <zachary@jovelabs.com>
5
+ # Copyright: Copyright (c) 2011-2012 Atalanta Systems Ltd
6
+ # License: Apache License, Version 2.0
7
+ #
8
+ # Licensed under the Apache License, Version 2.0 (the "License");
9
+ # you may not use this file except in compliance with the License.
10
+ # You may obtain a copy of the License at
11
+ #
12
+ # http://www.apache.org/licenses/LICENSE-2.0
13
+ #
14
+ # Unless required by applicable law or agreed to in writing, software
15
+ # distributed under the License is distributed on an "AS IS" BASIS,
16
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ # See the License for the specific language governing permissions and
18
+ # limitations under the License.
19
+ #
20
+ ################################################################################
21
+
22
+ module Cucumber
23
+ module Chef
24
+
25
+ class BootstrapError < Error; end
26
+
27
+ class Bootstrap
28
+ attr_accessor :stdout, :stderr, :stdin, :config
29
+
30
+ ################################################################################
31
+
32
+ def initialize(stdout=STDOUT, stderr=STDERR, stdin=STDIN)
33
+ @stdout, @stderr, @stdin = stdout, stderr, stdin
34
+ @stdout.sync = true if @stdout.respond_to?(:sync=)
35
+
36
+ @ssh = Cucumber::Chef::SSH.new(@stdout, @stderr, @stdin)
37
+ @config = Hash.new(nil)
38
+ @config[:context] = Hash.new(nil)
39
+ end
40
+
41
+ ################################################################################
42
+
43
+ def run
44
+ $logger.debug { "config(#{@config.inspect})" }
45
+
46
+ if !@config[:template_file]
47
+ message = "You must supply a 'template_file' option."
48
+ $logger.fatal { message }
49
+ raise BootstrapError, message
50
+ end
51
+
52
+ if !@config[:host]
53
+ message = "You must supply a 'host' option."
54
+ $logger.fatal { message }
55
+ raise BootstrapError, message
56
+ end
57
+
58
+ if !@config[:ssh_user]
59
+ message = "You must supply a 'ssh_user' option."
60
+ $logger.fatal { message }
61
+ raise BootstrapError, message
62
+ end
63
+
64
+ if (!@config[:ssh_password] && !@config[:identity_file])
65
+ message = "You must supply a 'ssh_password' or 'identity_file' option."
66
+ $logger.fatal { message }
67
+ raise BootstrapError, message
68
+ end
69
+
70
+ $logger.debug { "prepare(#{@config[:host]})" }
71
+
72
+ @ssh.config[:host] = @config[:host]
73
+ @ssh.config[:ssh_user] = @config[:ssh_user]
74
+ @ssh.config[:ssh_password] = @config[:ssh_password]
75
+ @ssh.config[:identity_file] = @config[:identity_file]
76
+ @ssh.config[:timeout] = 5
77
+
78
+ $logger.debug { "template_file(#{@config[:template_file]})" }
79
+ command = Cucumber::Chef::Template.render(@config[:template_file], @config[:context])
80
+ command = "sudo #{command}" if @config[:use_sudo]
81
+
82
+ $logger.debug { "begin(#{@config[:host]})" }
83
+ @ssh.exec(command, :silence => true)
84
+ $logger.debug { "end(#{@config[:host]})" }
85
+ end
86
+
87
+ ################################################################################
88
+
89
+ end
90
+
91
+ end
92
+ end
93
+
94
+ ################################################################################
@@ -0,0 +1,78 @@
1
+ ################################################################################
2
+ #
3
+ # Author: Stephen Nelson-Smith <stephen@atalanta-systems.com>
4
+ # Author: Zachary Patten <zachary@jovelabs.com>
5
+ # Copyright: Copyright (c) 2011-2012 Atalanta Systems Ltd
6
+ # License: Apache License, Version 2.0
7
+ #
8
+ # Licensed under the Apache License, Version 2.0 (the "License");
9
+ # you may not use this file except in compliance with the License.
10
+ # You may obtain a copy of the License at
11
+ #
12
+ # http://www.apache.org/licenses/LICENSE-2.0
13
+ #
14
+ # Unless required by applicable law or agreed to in writing, software
15
+ # distributed under the License is distributed on an "AS IS" BASIS,
16
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ # See the License for the specific language governing permissions and
18
+ # limitations under the License.
19
+ #
20
+ ################################################################################
21
+
22
+ module Cucumber
23
+ module Chef
24
+
25
+ class CommandError < Error; end
26
+
27
+ class Command
28
+ attr_accessor :stdout, :stderr, :stdin
29
+
30
+ ################################################################################
31
+
32
+ def initialize(stdout=STDOUT, stderr=STDERR, stdin=STDIN)
33
+ @stdout, @stderr, @stdin = stdout, stderr, stdin
34
+ @stdout.sync = true if @stdout.respond_to?(:sync=)
35
+
36
+ @knife = (Cucumber::Chef.locate(:file, "bin", "knife") rescue nil)
37
+ @knife = "/usr/bin/env knife" unless @knife
38
+ end
39
+
40
+ ################################################################################
41
+
42
+ def run(command, options={})
43
+ options = { :exit_code => 0, :silence => false }.merge(options)
44
+ exit_code = options[:exit_code]
45
+ silence = options[:silence]
46
+ $logger.debug { "options(#{options.inspect})" }
47
+
48
+ command = "#{command} 2>&1"
49
+ $logger.debug { "command(#{command})" }
50
+ output = %x( #{command} )
51
+ $logger.debug { "exit_code(#{$?})" }
52
+
53
+ $logger.debug { "--------------------------------------------------------------------------------" }
54
+ $logger.debug { output }
55
+ $logger.debug { "--------------------------------------------------------------------------------" }
56
+
57
+ @stdout.puts(output) if !silence
58
+
59
+ raise CommandError, "run(#{command}) failed! [#{$?}]" if ($? != exit_code)
60
+
61
+ output
62
+ end
63
+
64
+ ################################################################################
65
+
66
+ def knife(command, options={})
67
+ knife_rb = File.expand_path(File.join(Dir.pwd, ".cucumber-chef", "knife.rb"))
68
+ run("#{@knife} #{command.flatten.compact.join(" ")} -c #{knife_rb} --color -n", options)
69
+ end
70
+
71
+ ################################################################################
72
+
73
+ end
74
+
75
+ end
76
+ end
77
+
78
+ ################################################################################
@@ -1,129 +1,179 @@
1
+ ################################################################################
2
+ #
3
+ # Author: Stephen Nelson-Smith <stephen@atalanta-systems.com>
4
+ # Author: Zachary Patten <zachary@jovelabs.com>
5
+ # Copyright: Copyright (c) 2011-2012 Atalanta Systems Ltd
6
+ # License: Apache License, Version 2.0
7
+ #
8
+ # Licensed under the Apache License, Version 2.0 (the "License");
9
+ # you may not use this file except in compliance with the License.
10
+ # You may obtain a copy of the License at
11
+ #
12
+ # http://www.apache.org/licenses/LICENSE-2.0
13
+ #
14
+ # Unless required by applicable law or agreed to in writing, software
15
+ # distributed under the License is distributed on an "AS IS" BASIS,
16
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ # See the License for the specific language governing permissions and
18
+ # limitations under the License.
19
+ #
20
+ ################################################################################
21
+
1
22
  module Cucumber
2
23
  module Chef
3
- class ConfigError < Error ; end
24
+
25
+ class ConfigError < Error; end
4
26
 
5
27
  class Config
6
- KEYS = %w[mode node_name chef_server_url client_key validation_key validation_client_name]
7
- KNIFE_KEYS = %w[aws_access_key_id aws_secret_access_key region aws_image_id availability_zone aws_ssh_key_id identity_file]
28
+ extend(Mixlib::Config)
8
29
 
9
- def initialize
10
- config[:mode] = "user"
11
- end
30
+ KEYS = %w( mode provider ).map(&:to_sym) unless const_defined?(:KEYS)
31
+ MODES = %w( user test ).map(&:to_sym) unless const_defined?(:MODES)
32
+ PROVIDERS = %w( aws vagrant ).map(&:to_sym) unless const_defined?(:PROVIDERS)
12
33
 
13
- def self.mode
14
- config.test_mode? ? 'test' : 'user'
15
- end
34
+ PROVIDER_AWS_KEYS = %w( aws_access_key_id aws_secret_access_key region availability_zone aws_ssh_key_id identity_file ).map(&:to_sym) unless const_defined?(:PROVIDER_AWS_KEYS)
16
35
 
17
- def [](key)
18
- config[key]
19
- end
36
+ ################################################################################
20
37
 
21
- def []=(key, value)
22
- config[key] = value
38
+ def self.inspect
39
+ configuration.inspect
23
40
  end
24
41
 
25
- def config
26
- unless @config
27
- full_path = Dir.pwd.split(File::SEPARATOR)
28
- (full_path.length - 1).downto(0) do |i|
29
- knife_file = File.join(full_path[0..i] + [".chef", "knife.rb"])
30
- if File.exist?(knife_file)
31
- ::Chef::Config.from_file(knife_file)
32
- @config = ::Chef::Config
33
- return @config
34
- end
35
- end
36
- raise ConfigError.new("Couldn't find knife.rb")
42
+ ################################################################################
43
+
44
+ def self.duplicate(input)
45
+ output = Hash.new
46
+ input.each do |key, value|
47
+ output[key] = (value.is_a?(Hash) ? self.duplicate(input[key]) : value.to_s.dup)
37
48
  end
38
- @config
49
+ output
39
50
  end
40
51
 
41
- def self.test_config
42
- config = self.new
43
- config[:mode] = "test"
44
- config
45
- end
52
+ def self.load
53
+ config_rb = Cucumber::Chef.locate(:file, ".cucumber-chef", "config.rb")
54
+ $logger.info { "Attempting to load cucumber-chef configuration from '%s'." % config_rb }
55
+ self.from_file(config_rb)
56
+ self.verify
57
+ $logger.info { "Successfully loaded cucumber-chef configuration from '%s'." % config_rb }
46
58
 
47
- def test_mode?
48
- config[:mode] == "test"
49
- end
59
+ log_dump = self.duplicate(self.configuration)
60
+ log_dump[:aws].merge!(:aws_access_key_id => "[REDACTED]", :aws_secret_access_key => "[REDACTED]")
61
+ $logger.debug { log_dump.inspect }
50
62
 
51
- def list
52
- values = []
53
- KEYS.each do |key|
54
- value = config[key]
55
- values << "#{key}: #{value}"
56
- end
57
- KNIFE_KEYS.each do |key|
58
- value = config[:knife][key.to_sym]
59
- values << "knife[:#{key}]: #{value}"
60
- end
61
- values
63
+ self
64
+ rescue Errno::ENOENT, UtilityError
65
+ raise ConfigError, "Could not find your cucumber-chef configuration file; did you run 'cucumber-chef init'?"
62
66
  end
63
67
 
64
- def verify
65
- @errors = []
66
- verify_orgname
67
- verify_opscode_user
68
- verify_keys
69
- verify_opscode_platform_credentials
70
- verify_aws_credentials
71
- if @errors.size > 0
72
- raise ConfigError.new(@errors.join("\n"))
73
- end
68
+ def self.test
69
+ self.load
70
+ self[:mode] = :test
71
+ self
74
72
  end
75
73
 
76
- private
77
-
78
- def verify_orgname
79
- if !ENV["ORGNAME"] || ENV["ORGNAME"] == ""
80
- @errors << "Your organisation must be set using the environment variable ORGNAME."
81
- end
82
- end
74
+ ################################################################################
83
75
 
84
- def verify_opscode_user
85
- if !ENV["OPSCODE_USER"] || ENV["OPSCODE_USER"] == ""
86
- @errors << "Your Opscode platform username must be set using the environment variable OPSCODE_USER."
87
- end
76
+ def self.verify
77
+ self.verify_keys
78
+ self.verify_provider_keys
79
+ eval("self.verify_provider_#{self[:provider].to_s.downcase}")
80
+ $logger.debug { "Configuration verified successfully" }
88
81
  end
89
82
 
90
- def verify_keys
91
- missing_keys = []
92
- KEYS.each do |key|
93
- value = config[key]
94
- missing_keys << key unless value && value != ""
95
- end
96
- KNIFE_KEYS.each do |key|
97
- missing_keys << "knife[:#{key}]" unless value = config[:knife][key.to_sym]
83
+ ################################################################################
84
+
85
+ def self.verify_keys
86
+ $logger.debug { "Checking for missing configuration keys" }
87
+ missing_keys = KEYS.select{ |key| !self[key.to_sym] }
88
+ if missing_keys.count > 0
89
+ message = "Configuration incomplete, missing configuration keys: #{missing_keys.join(", ")}"
90
+ $logger.fatal { message }
91
+ raise ConfigError, message
98
92
  end
99
- if missing_keys.size > 0
100
- @errors << "Incomplete config file, please specify: #{missing_keys.join(", ")}."
93
+
94
+ $logger.debug { "Checking for invalid configuration keys" }
95
+ invalid_keys = KEYS.select{ |key| !eval("#{key.to_s.upcase}S").include?(self[key]) }
96
+ if invalid_keys.count > 0
97
+ message = "Configuration incomplete, invalid configuration keys: #{invalid_keys.join(", ")}"
98
+ $logger.fatal { message }
99
+ raise ConfigError, message
101
100
  end
102
101
  end
103
102
 
104
- def verify_opscode_platform_credentials
105
- username = config['node_name']
106
- if username
107
- req = Net::HTTP.new('community.opscode.com', 80)
108
- code = req.request_head("/users/#{username}").code
109
- end
110
- if username == "" || code != "200"
111
- @errors << "Invalid Opscode platform credentials. Please check."
103
+ ################################################################################
104
+
105
+ def self.verify_provider_keys
106
+ $logger.debug { "Checking for missing provider keys" }
107
+ missing_keys = eval("PROVIDER_#{self[:provider].to_s.upcase}_KEYS").select{ |key| !self[self[:provider]].key?(key) }
108
+ if missing_keys.count > 0
109
+ message = "Configuration incomplete, missing provider configuration keys: #{missing_keys.join(", ")}"
110
+ $logger.fatal { message }
111
+ raise ConfigError, message
112
112
  end
113
113
  end
114
-
115
- def verify_aws_credentials
116
- if config[:knife][:aws_access_key_id] && config[:knife][:aws_secret_access_key]
114
+
115
+ ################################################################################
116
+
117
+ def self.verify_provider_aws
118
+ if self[:aws][:aws_access_key_id] && self[:aws][:aws_secret_access_key]
117
119
  compute = Fog::Compute.new(:provider => 'AWS',
118
- :aws_access_key_id => config[:knife][:aws_access_key_id],
119
- :aws_secret_access_key => config[:knife][:aws_secret_access_key])
120
+ :aws_access_key_id => self[:aws][:aws_access_key_id],
121
+ :aws_secret_access_key => self[:aws][:aws_secret_access_key])
120
122
  compute.describe_availability_zones
121
- else
122
- @errors << "Invalid AWS credentials. Please check."
123
123
  end
124
124
  rescue Fog::Service::Error => err
125
- @errors << "Invalid AWS credentials. Please check."
125
+ message = "Invalid AWS credentials. Please check your configuration."
126
+ $logger.fatal { message }
127
+ raise ConfigError, message
128
+ end
129
+
130
+ def self.verify_provider_vagrant
131
+ message = "Not yet implemented."
132
+ $logger.fatal { message }
133
+ raise ConfigError, message
134
+ end
135
+
136
+ ################################################################################
137
+
138
+ def self.aws_image_id
139
+ if self[:aws][:aws_image_id]
140
+ return self[:aws][:aws_image_id]
141
+ elsif (self[:aws][:ubuntu_release] && self[:aws][:region])
142
+ ami = Ubuntu.release(self[:aws][:ubuntu_release]).amis.find do |ami|
143
+ ami.arch == (self[:aws][:aws_instance_arch] || "i386") &&
144
+ ami.root_store == (self[:aws][:aws_instance_disk_store] || "instance-store") &&
145
+ ami.region == self[:aws][:region]
146
+ end
147
+ return ami.name if ami
148
+ end
149
+ message = "Could not find a valid AMI image ID. Please check your configuration."
150
+ $logger.fatal { message }
151
+ raise ConfigError, message
126
152
  end
153
+
154
+ ################################################################################
155
+
156
+ mode :user
157
+ prerelease true
158
+
159
+ provider :aws
160
+ librarian_chef false
161
+
162
+ user ( ENV['OPSCODE_USER'] || ENV['USER'] )
163
+
164
+ aws Hash[ :ubuntu_release => "precise",
165
+ :aws_instance_arch => "i386",
166
+ :aws_instance_disk_store => "ebs",
167
+ :aws_instance_type => "m1.small",
168
+ :aws_security_group => "cucumber-chef" ]
169
+
170
+ vagrant Hash.new
171
+
172
+ ################################################################################
173
+
127
174
  end
175
+
128
176
  end
129
177
  end
178
+
179
+ ################################################################################
@@ -0,0 +1,87 @@
1
+ ################################################################################
2
+ #
3
+ # Author: Stephen Nelson-Smith <stephen@atalanta-systems.com>
4
+ # Author: Zachary Patten <zachary@jovelabs.com>
5
+ # Copyright: Copyright (c) 2011-2012 Atalanta Systems Ltd
6
+ # License: Apache License, Version 2.0
7
+ #
8
+ # Licensed under the Apache License, Version 2.0 (the "License");
9
+ # you may not use this file except in compliance with the License.
10
+ # You may obtain a copy of the License at
11
+ #
12
+ # http://www.apache.org/licenses/LICENSE-2.0
13
+ #
14
+ # Unless required by applicable law or agreed to in writing, software
15
+ # distributed under the License is distributed on an "AS IS" BASIS,
16
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ # See the License for the specific language governing permissions and
18
+ # limitations under the License.
19
+ #
20
+ ################################################################################
21
+
22
+ module Cucumber::Chef::Helpers::ChefClient
23
+
24
+ ################################################################################
25
+
26
+ # call this in a Before hook
27
+ def chef_set_client_config(config={})
28
+ @chef_client_config = { :log_level => :debug,
29
+ :log_location => "/var/log/chef/client.log",
30
+ :chef_server_url => "https://api.opscode.com/organizations/#{config[:orgname]}",
31
+ :validation_client_name => "#{config[:orgname]}-validator" }.merge(config)
32
+ end
33
+
34
+ ################################################################################
35
+
36
+ # call this before chef_run_client
37
+ def chef_set_client_attributes(name, attributes={})
38
+ @chef_client_attributes = (@chef_client_attributes || {}).merge(attributes) { |k,o,n| (k = (o + n)) }
39
+ end
40
+
41
+ ################################################################################
42
+
43
+ def chef_run_client(name,*args)
44
+ chef_config_client(name)
45
+ output = command_run_remote(name, ["/usr/bin/chef-client -j /etc/chef/attributes.json -N #{name}", args].join(" "))
46
+ log("chef-client", "ran on node '#{name}'")
47
+ output
48
+ end
49
+
50
+ ################################################################################
51
+
52
+ def chef_config_client(name)
53
+ # make sure our configuration location is there
54
+ client_rb = File.join("/", container_root(name), "etc/chef/client.rb")
55
+ FileUtils.mkdir_p(File.dirname(client_rb))
56
+
57
+ File.open(client_rb, 'w') do |f|
58
+ f.puts(Cucumber::Chef.generate_do_not_edit_warning("Chef Client Configuration"))
59
+ f.puts
60
+ f.puts("log_level :#{@chef_client_config[:log_level]}")
61
+ f.puts("log_location \"#{@chef_client_config[:log_location]}\"")
62
+ f.puts("chef_server_url \"#{@chef_client_config[:chef_server_url]}\"")
63
+ f.puts("ssl_verify_mode :verify_none")
64
+ f.puts("validation_client_name \"#{@chef_client_config[:validation_client_name]}\"")
65
+ f.puts("node_name \"#{name}\"")
66
+ f.puts
67
+ f.puts("Mixlib::Log::Formatter.show_time = true")
68
+ end
69
+
70
+ attributes_json = File.join("/", container_root(name), "etc", "chef", "attributes.json")
71
+ FileUtils.mkdir_p(File.dirname(attributes_json))
72
+ File.open(attributes_json, 'w') do |f|
73
+ f.puts((@chef_client_attributes || {}).to_json)
74
+ end
75
+
76
+ # make sure our log location is there
77
+ log_location = File.join("/", container_root(name), @chef_client_config[:log_location])
78
+ FileUtils.mkdir_p(File.dirname(log_location))
79
+
80
+ command_run_local("cp /etc/chef/validation.pem #{container_root(name)}/etc/chef/ 2>&1")
81
+ end
82
+
83
+ ################################################################################
84
+
85
+ end
86
+
87
+ ################################################################################
@@ -0,0 +1,90 @@
1
+ ################################################################################
2
+ #
3
+ # Author: Stephen Nelson-Smith <stephen@atalanta-systems.com>
4
+ # Author: Zachary Patten <zachary@jovelabs.com>
5
+ # Copyright: Copyright (c) 2011-2012 Atalanta Systems Ltd
6
+ # License: Apache License, Version 2.0
7
+ #
8
+ # Licensed under the Apache License, Version 2.0 (the "License");
9
+ # you may not use this file except in compliance with the License.
10
+ # You may obtain a copy of the License at
11
+ #
12
+ # http://www.apache.org/licenses/LICENSE-2.0
13
+ #
14
+ # Unless required by applicable law or agreed to in writing, software
15
+ # distributed under the License is distributed on an "AS IS" BASIS,
16
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ # See the License for the specific language governing permissions and
18
+ # limitations under the License.
19
+ #
20
+ ################################################################################
21
+
22
+ module Cucumber::Chef::Helpers::ChefServer
23
+
24
+ ################################################################################
25
+
26
+ def chef_server_node_destroy(name)
27
+ (::Chef::Node.load(name).destroy rescue nil)
28
+ log("chef-server", "destroyed node '#{name}'")
29
+ end
30
+
31
+ ################################################################################
32
+
33
+ def chef_server_client_destroy(name)
34
+ (::Chef::ApiClient.load(name).destroy rescue nil)
35
+ log("chef-server", "destroyed client '#{name}'")
36
+ end
37
+
38
+ ################################################################################
39
+
40
+ def load_role(role, role_path)
41
+ if !File.exists?(File.expand_path(role_path))
42
+ raise "Role path does not exist!"
43
+ end
44
+ ::Chef::Config[:role_path] = role_path
45
+ role = ::Chef::Role.from_disk(role)
46
+ role.save
47
+ log("chef-server", "updated role '#{role}' from file '#{role_path}'")
48
+ end
49
+
50
+ ################################################################################
51
+
52
+ def create_databag(databag)
53
+ @rest ||= ::Chef::REST.new(Chef::Config[:chef_server_url])
54
+ @rest.post_rest("data", { "name" => databag })
55
+ rescue Net::HTTPServerException => e
56
+ raise unless e.to_s =~ /^409/
57
+ end
58
+
59
+ def load_databag_item(databag_item_path)
60
+ ::Yajl::Parser.parse(IO.read(databag_item_path))
61
+ end
62
+
63
+ def load_databag(databag, databag_path)
64
+ create_databag(databag)
65
+ items = Dir.glob(File.expand_path(File.join(databag_path, "*.{json,rb}")))
66
+ items.each do |item|
67
+ next if File.directory?(item)
68
+
69
+ item_path = File.basename(item)
70
+ databag_item_path = File.expand_path(File.join(databag_path, item_path))
71
+
72
+ data_bag_item = ::Chef::DataBagItem.new
73
+ data_bag_item.data_bag(databag)
74
+ data_bag_item.raw_data = load_databag_item(databag_item_path)
75
+ data_bag_item.save
76
+ log("chef-server", "updated data bag item '#{databag}/#{item_path}' from file '#{databag_path}'")
77
+ end
78
+
79
+ # TODO fix ghetto sleep
80
+ # databags don't always update right away; ghetto fix with a sleep
81
+ # for now. likely needs to loop reading the databag back until it updates
82
+ # then return
83
+ sleep(3)
84
+ end
85
+
86
+ ################################################################################
87
+
88
+ end
89
+
90
+ ################################################################################