knife-cloud 1.0.0.rc.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +33 -0
  3. data/.travis.yml +7 -0
  4. data/CHANGELOG.md +11 -0
  5. data/CONTRIBUTING.md +5 -0
  6. data/Gemfile +9 -0
  7. data/LICENSE +201 -0
  8. data/README.md +420 -0
  9. data/Rakefile +35 -0
  10. data/knife-cloud.gemspec +27 -0
  11. data/lib/chef/knife/cloud/chefbootstrap/bootstrap_distribution.rb +31 -0
  12. data/lib/chef/knife/cloud/chefbootstrap/bootstrap_options.rb +191 -0
  13. data/lib/chef/knife/cloud/chefbootstrap/bootstrap_protocol.rb +69 -0
  14. data/lib/chef/knife/cloud/chefbootstrap/bootstrapper.rb +78 -0
  15. data/lib/chef/knife/cloud/chefbootstrap/ssh_bootstrap_protocol.rb +179 -0
  16. data/lib/chef/knife/cloud/chefbootstrap/unix_distribution.rb +31 -0
  17. data/lib/chef/knife/cloud/chefbootstrap/windows_distribution.rb +32 -0
  18. data/lib/chef/knife/cloud/chefbootstrap/winrm_bootstrap_protocol.rb +85 -0
  19. data/lib/chef/knife/cloud/command.rb +101 -0
  20. data/lib/chef/knife/cloud/exceptions.rb +38 -0
  21. data/lib/chef/knife/cloud/fog/options.rb +29 -0
  22. data/lib/chef/knife/cloud/fog/service.rb +200 -0
  23. data/lib/chef/knife/cloud/helpers.rb +39 -0
  24. data/lib/chef/knife/cloud/list_resource_command.rb +97 -0
  25. data/lib/chef/knife/cloud/list_resource_options.rb +21 -0
  26. data/lib/chef/knife/cloud/server/create_command.rb +165 -0
  27. data/lib/chef/knife/cloud/server/create_options.rb +80 -0
  28. data/lib/chef/knife/cloud/server/delete_command.rb +68 -0
  29. data/lib/chef/knife/cloud/server/delete_options.rb +42 -0
  30. data/lib/chef/knife/cloud/server/list_command.rb +84 -0
  31. data/lib/chef/knife/cloud/server/list_options.rb +43 -0
  32. data/lib/chef/knife/cloud/server/options.rb +39 -0
  33. data/lib/chef/knife/cloud/server/show_command.rb +55 -0
  34. data/lib/chef/knife/cloud/server/show_options.rb +36 -0
  35. data/lib/chef/knife/cloud/service.rb +91 -0
  36. data/lib/knife-cloud/version.rb +6 -0
  37. data/lib/test/fixtures/knife.rb +9 -0
  38. data/lib/test/fixtures/validation.pem +27 -0
  39. data/lib/test/knife-utils/helper.rb +39 -0
  40. data/lib/test/knife-utils/knife_test_utils.rb +40 -0
  41. data/lib/test/knife-utils/matchers.rb +29 -0
  42. data/lib/test/knife-utils/test_bed.rb +56 -0
  43. data/lib/test/templates/chef-full-chef-zero.erb +67 -0
  44. data/lib/test/templates/windows-chef-client-msi.erb +231 -0
  45. data/lib/test/templates/windows-shell.erb +77 -0
  46. data/spec/resource_spec_helper.rb +49 -0
  47. data/spec/server_command_common_spec_helper.rb +48 -0
  48. data/spec/spec_helper.rb +25 -0
  49. data/spec/support/shared_examples_for_command.rb +35 -0
  50. data/spec/support/shared_examples_for_servercreatecommand.rb +144 -0
  51. data/spec/support/shared_examples_for_serverdeletecommand.rb +77 -0
  52. data/spec/support/shared_examples_for_service.rb +85 -0
  53. data/spec/unit/bootstrap_protocol_spec.rb +70 -0
  54. data/spec/unit/bootstrapper_spec.rb +171 -0
  55. data/spec/unit/cloud_command_spec.rb +35 -0
  56. data/spec/unit/command_spec.rb +49 -0
  57. data/spec/unit/fog_service_spec.rb +138 -0
  58. data/spec/unit/list_resource_command_spec.rb +136 -0
  59. data/spec/unit/server_create_command_spec.rb +198 -0
  60. data/spec/unit/server_delete_command_spec.rb +25 -0
  61. data/spec/unit/server_list_command_spec.rb +119 -0
  62. data/spec/unit/server_show_command_spec.rb +64 -0
  63. data/spec/unit/service_spec.rb +46 -0
  64. data/spec/unit/ssh_bootstrap_protocol_spec.rb +116 -0
  65. data/spec/unit/unix_distribution_spec.rb +37 -0
  66. data/spec/unit/windows_distribution_spec.rb +37 -0
  67. data/spec/unit/winrm_bootstrap_protocol_spec.rb +106 -0
  68. metadata +248 -0
@@ -0,0 +1,80 @@
1
+ #
2
+ # Copyright:: Copyright (c) 2013 Opscode, Inc.
3
+ # License:: Apache License, Version 2.0
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.
16
+ #
17
+
18
+ require 'chef/knife/cloud/chefbootstrap/bootstrap_options'
19
+ require 'chef/knife/cloud/server/options'
20
+
21
+ class Chef
22
+ class Knife
23
+ class Cloud
24
+ module ServerCreateOptions
25
+
26
+ def self.included(includer)
27
+ includer.class_eval do
28
+ include ServerOptions
29
+ include BootstrapOptions
30
+ option :image,
31
+ :short => "-I IMAGE",
32
+ :long => "--image IMAGE",
33
+ :description => "A regexp matching an image name or an image ID for the server",
34
+ :proc => Proc.new { |i| Chef::Config[:knife][:image] = i }
35
+
36
+ option :image_os_type,
37
+ :short => "-T IMAGE_OS_TYPE",
38
+ :long => "--image-os-type IMAGE_OS_TYPE",
39
+ :description => "The image os type. options [windows/linux]. Only required when cloud does not provide a way to identify image os",
40
+ :default => "linux",
41
+ :proc => Proc.new { |i| Chef::Config[:knife][:image_os_type] = i }
42
+
43
+ option :flavor,
44
+ :short => "-f FLAVOR_ID",
45
+ :long => "--flavor FLAVOR_ID",
46
+ :description => "The flavor name or ID of server",
47
+ :proc => Proc.new { |f| Chef::Config[:knife][:flavor] = f }
48
+
49
+ option :bootstrap_protocol,
50
+ :long => "--bootstrap-protocol protocol",
51
+ :description => "Protocol to bootstrap servers. options: winrm/ssh. For linux servers always use ssh.",
52
+ :default => 'ssh',
53
+ :proc => Proc.new { |b| Chef::Config[:knife][:bootstrap_protocol] = b}
54
+
55
+ option :server_create_timeout,
56
+ :long => "--server-create-timeout timeout",
57
+ :description => "How long to wait until the server is ready; default is 600 seconds",
58
+ :default => 600,
59
+ :proc => Proc.new { |v| Chef::Config[:knife][:server_create_timeout] = v}
60
+
61
+ option :delete_server_on_failure,
62
+ :long => "--delete-server-on-failure",
63
+ :boolean => true,
64
+ :default => false,
65
+ :description => "Destroy corresponding server in case of failure"
66
+
67
+ option :chef_node_name_prefix,
68
+ :long => "--chef-node-name-prefix PREFIX_FOR_NODE_NAME",
69
+ :description => "The prefix for chef node name",
70
+ :default => includer.snake_case_name.split('_').first,
71
+ :proc => Proc.new { |key| Chef::Config[:knife][:chef_node_name_prefix] = key }
72
+
73
+ end
74
+ end
75
+
76
+ end # module end
77
+ end
78
+ end
79
+ end
80
+
@@ -0,0 +1,68 @@
1
+ #
2
+ # Author:: Kaustubh Deorukhkar (<kaustubh@clogeny.com>)
3
+ # Copyright:: Copyright (c) 2013 Opscode, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'chef/knife/cloud/command'
20
+ # These two are needed for the '--purge' deletion case
21
+ require 'chef/node'
22
+ require 'chef/api_client'
23
+
24
+ class Chef
25
+ class Knife
26
+ class Cloud
27
+ class ServerDeleteCommand < Command
28
+
29
+ def execute_command
30
+ @name_args.each do |server_name|
31
+ service.delete_server(server_name)
32
+ delete_from_chef(server_name)
33
+ end
34
+ end
35
+
36
+ def delete_from_chef(server_name)
37
+ # delete the node from Chef if purge requested.
38
+ if config[:purge]
39
+ thing_to_delete = config[:chef_node_name] || server_name
40
+ destroy_item(Chef::Node, thing_to_delete, "node")
41
+ destroy_item(Chef::ApiClient, thing_to_delete, "client")
42
+ else
43
+ ui.warn("Corresponding node and client for the #{server_name} server were not deleted and remain registered with the Chef Server")
44
+ end
45
+ end
46
+
47
+ # Extracted from Chef::Knife.delete_object, because it has a
48
+ # confirmation step built in... By specifying the '--purge'
49
+ # flag (and also explicitly confirming the server destruction!)
50
+ # the user is already making their intent known. It is not
51
+ # necessary to make them confirm two more times.
52
+ def destroy_item(klass, name, type_name)
53
+ begin
54
+ object = klass.load(name)
55
+ object.destroy
56
+ ui.warn("Deleted #{type_name} #{name}")
57
+ rescue Net::HTTPServerException => e
58
+ error_message = "#{e.message}. Could not find a #{type_name} named #{name} to delete!"
59
+ ui.warn(error_message)
60
+ raise CloudExceptions::ServerDeleteError, error_message
61
+ end
62
+ end
63
+
64
+ end # class ServerDeleteCommand
65
+ end
66
+ end
67
+ end
68
+
@@ -0,0 +1,42 @@
1
+ #
2
+ # Author:: Kaustubh Deorukhkar (<kaustubh@clogeny.com>)
3
+ # Copyright:: Copyright (c) 2013 Opscode, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'chef/knife/cloud/server/options'
20
+
21
+ class Chef
22
+ class Knife
23
+ class Cloud
24
+ module ServerDeleteOptions
25
+ def self.included(includer)
26
+ includer.class_eval do
27
+ include ServerOptions
28
+
29
+ option :purge,
30
+ :short => "-P",
31
+ :long => "--purge",
32
+ :boolean => true,
33
+ :default => false,
34
+ :description => "Destroy corresponding node and client on the Chef Server, in addition to destroying the Cloud node itself. Assumes node and client have the same name as the server (if not, add the '--node-name' option)."
35
+
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+
@@ -0,0 +1,84 @@
1
+ require 'chef/knife/cloud/list_resource_command'
2
+ require 'chef/knife/cloud/exceptions'
3
+
4
+ class Chef
5
+ class Knife
6
+ class Cloud
7
+ class ServerListCommand < ResourceListCommand
8
+
9
+ def before_exec_command
10
+ if config[:chef_data]
11
+ begin
12
+ # Chef::Node.list(inflate = true) to use Solr search.
13
+ @node_list = Chef::Node.list(true)
14
+ rescue Errno::ECONNREFUSED => e
15
+ error_message = "Connection error with Chef server. #{e}"
16
+ ui.warn(error_message)
17
+ raise CloudExceptions::ChefServerError, error_message
18
+ end
19
+
20
+ @chef_data_col_info = [
21
+ {:label => 'Chef Node Name', :key => 'name'},
22
+ {:label => 'Environment', :key => 'chef_environment'},
23
+ {:label => 'FQDN', :key => 'fqdn'},
24
+ {:label => 'Runlist', :key => 'run_list'},
25
+ {:label => 'Tags', :key => 'tags'},
26
+ {:label => 'Platform', :key => 'platform'},
27
+ ]
28
+
29
+ if config[:chef_node_attribute]
30
+ @chef_data_col_info << {:label => "#{config[:chef_node_attribute]}", :key => "#{config[:chef_node_attribute]}"}
31
+ end
32
+ @columns_with_info.concat(@chef_data_col_info)
33
+ end
34
+ end
35
+
36
+ # Override from base to display chef node data along with server list display.
37
+ def get_resource_col_val(server)
38
+ list = []
39
+ @columns_with_info.each do |col_info|
40
+ if config[:chef_data] && @chef_data_col_info.include?(col_info)
41
+ server_name = service.get_server_name(server)
42
+ if @node_list.include?(server_name)
43
+ node = @node_list[server_name]
44
+ # Raise serverlisting error on invalid chef_node_attribute.
45
+ if col_info[:key] == config[:chef_node_attribute] && ! node.attribute?(col_info[:key])
46
+ error_message = "The Node does not have a #{col_info[:key]} attribute."
47
+ ui.error(error_message)
48
+ raise CloudExceptions::CloudAPIException, error_message
49
+ else
50
+ value = (col_info[:value_callback].nil? ? node.send(col_info[:key]).to_s : col_info[:value_callback].call(node.send(col_info[:key])))
51
+ end
52
+ else
53
+ # Set chef data value for those server which is not part chef server.
54
+ value = ""
55
+ end
56
+ else
57
+ value = (col_info[:value_callback].nil? ? server.send(col_info[:key]).to_s : col_info[:value_callback].call(server.send(col_info[:key])))
58
+ end
59
+ list << value
60
+ end
61
+ list
62
+ end
63
+
64
+ def query_resource
65
+ @service.list_servers
66
+ end
67
+
68
+ def format_server_state(state)
69
+ state = state.to_s.downcase
70
+ state_color = case state
71
+ when 'shutting-down','terminated','stopping','stopped','error','shutoff'
72
+ :red
73
+ when 'pending','build','paused','suspended','hard_reboot'
74
+ :yellow
75
+ else
76
+ :green
77
+ end
78
+ ui.color(state, state_color)
79
+ end
80
+
81
+ end # class ServerListCommand
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,43 @@
1
+ #
2
+ # Author:: Siddheshwar More (<siddheshwar.more@clogeny.com>)
3
+ # Copyright:: Copyright (c) 2013 Opscode, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ class Chef
20
+ class Knife
21
+ class Cloud
22
+ module ServerListOptions
23
+ def self.included(includer)
24
+ includer.class_eval do
25
+
26
+ option :chef_data,
27
+ :long => "--chef-data",
28
+ :boolean => true,
29
+ :default => false,
30
+ :description => "Display chef node data which include chef node name, environment name, fqdn, platform, runlist and tags."
31
+
32
+ option :chef_node_attribute,
33
+ :long => "--chef-node-attribute CHEF_NODE_ATTRIBUTE_NAME",
34
+ :description => "Used with --chef-data option. It display node attributes details by adding new column in server list display.",
35
+ :proc => Proc.new { |i| Chef::Config[:knife][:chef_node_attribute] = i }
36
+
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+
@@ -0,0 +1,39 @@
1
+ #
2
+ # Author:: Kaustubh Deorukhkar (<kaustubh@clogeny.com>)
3
+ # Copyright:: Copyright (c) 2013 Opscode, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ class Chef
20
+ class Knife
21
+ class Cloud
22
+ module ServerOptions
23
+ def self.included(includer)
24
+ includer.class_eval do
25
+ option :chef_node_name,
26
+ :short => "-N NAME",
27
+ :long => "--node-name NAME",
28
+ :description => "The name of the node and client to delete, if it differs from the server name. Only has meaning when used with the '--purge' option."
29
+
30
+ option :custom_attributes,
31
+ :long => "--custom-attributes CUSTOM_ATTRIBUTES",
32
+ :description => "Custom attributes to be passed to Fog.",
33
+ :proc => Proc.new {|args| Chef::Config[:knife][:custom_attributes] = args.split(';').map{|keys| keys.split('=')}.map{|j| Hash[*j.map{|k| k.strip}]}}
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,55 @@
1
+ #
2
+ # Copyright:: Copyright (c) 2013 Opscode, Inc.
3
+ # License:: Apache License, Version 2.0
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.
16
+ #
17
+
18
+ require 'chef/knife/cloud/command'
19
+ require 'chef/knife/cloud/exceptions'
20
+
21
+ class Chef
22
+ class Knife
23
+ class Cloud
24
+ class ServerShowCommand < Command
25
+
26
+ def initialize(argv=[])
27
+ super argv
28
+ # columns_with_info is array of hash with label, key and attribute extraction callback, ex [{:label => "Label text", :key => 'key', value_callback => callback_method to extract/format the required value}, ...]
29
+ @columns_with_info = []
30
+ end
31
+
32
+ def validate_params!
33
+ errors = []
34
+ config[:instance_id] = @name_args.first
35
+ if locate_config_value(:instance_id).nil?
36
+ errors << "You must provide a valid Instance Id"
37
+ end
38
+ error_message = ""
39
+ raise CloudExceptions::ValidationError, error_message if errors.each{|e| ui.error(e); error_message = "#{error_message} #{e}."}.any?
40
+ end
41
+
42
+ def execute_command
43
+ server = service.get_server(locate_config_value(:instance_id))
44
+ if server.nil?
45
+ error_message = "Server doesn't exists for this #{locate_config_value(:instance_id)} instance id."
46
+ ui.error(error_message)
47
+ raise CloudExceptions::ServerShowError, error_message
48
+ else
49
+ service.server_summary(server, @columns_with_info)
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,36 @@
1
+ #
2
+ # Copyright:: Copyright (c) 2013 Opscode, Inc.
3
+ # License:: Apache License, Version 2.0
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.
16
+ #
17
+
18
+ class Chef
19
+ class Knife
20
+ class Cloud
21
+ module ServerShowOptions
22
+ def self.included(includer)
23
+ includer.class_eval do
24
+
25
+ option :instance_id,
26
+ :long => "--instance-id INSTANCE_ID",
27
+ :description => "Required. Instance Id of Server",
28
+ :proc => Proc.new { |i| Chef::Config[:knife][:instance_id] = i }
29
+
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+
@@ -0,0 +1,91 @@
1
+ #
2
+ # Author:: Kaustubh Deorukhkar (<kaustubh@clogeny.com>)
3
+ # Copyright:: Copyright (c) 2013 Opscode, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'chef/knife/cloud/exceptions'
20
+ require "chef/knife/cloud/helpers"
21
+
22
+ class Chef
23
+ class Knife
24
+ class Cloud
25
+ class Service
26
+ include Cloud::Helpers
27
+ attr_accessor :ui
28
+
29
+ def initialize(options = {})
30
+ @auth_params = options[:auth_params]
31
+ end
32
+
33
+ def connection
34
+ # Fog or cloud specific connection object must be created in derived.
35
+ raise Chef::Exceptions::Override, "You must override connection in #{self.to_s}"
36
+ end
37
+
38
+ # override in cloud specific derived classes
39
+ def list_resource_allocations
40
+ end
41
+
42
+ # Do nothing or override in cloud specific derived classes for pre-vm-creation setup steps
43
+ def create_server_dependencies
44
+ end
45
+
46
+ # Do nothing or override in cloud specific derived classes for pre-vm-creation setup steps
47
+ def delete_server_dependencies
48
+ end
49
+
50
+ def delete_server_on_failure(server = nil)
51
+ raise Chef::Exceptions::Override, "You must override delete_server_on_failure in #{self.to_s} to delete server"
52
+ end
53
+
54
+ # cloud server specific implementation methods for commands.
55
+ def create_server(options = {})
56
+ raise Chef::Exceptions::Override, "You must override create_server in #{self.to_s}"
57
+ end
58
+
59
+ def delete_server(server_name)
60
+ raise Chef::Exceptions::Override, "You must override delete_server in #{self.to_s}"
61
+ end
62
+
63
+ def list_servers
64
+ raise Chef::Exceptions::Override, "You must override list_servers in #{self.to_s}"
65
+ end
66
+
67
+ def list_images(image_filters)
68
+ raise Chef::Exceptions::Override, "You must override list_images in #{self.to_s}"
69
+ end
70
+
71
+ def list_resource_configurations
72
+ raise Chef::Exceptions::Override, "You must override list_resource_configurations in #{self.to_s}"
73
+ end
74
+
75
+ def get_server(server_name)
76
+ raise Chef::Exceptions::Override, "You must override get_server in #{self.to_s}"
77
+ end
78
+
79
+ def server_summary(server, columns_with_info = [])
80
+ raise Chef::Exceptions::Override, "You must override server_summary in #{self.to_s}"
81
+ end
82
+
83
+ def add_custom_attributes(server_def)
84
+ Chef::Config[:knife][:custom_attributes].map{|args| args.map{|k,v| server_def.merge!(k.to_sym => v)}} unless Chef::Config[:knife][:custom_attributes].nil?
85
+ end
86
+
87
+ end # class service
88
+ end
89
+ end
90
+ end
91
+
@@ -0,0 +1,6 @@
1
+ module Knife
2
+ module Cloud
3
+ VERSION = "1.0.0.rc.0"
4
+ MAJOR, MINOR, TINY = VERSION.split('.')
5
+ end
6
+ end
@@ -0,0 +1,9 @@
1
+ current_dir = File.dirname(__FILE__)
2
+ node_name "chef0"
3
+ client_key "#{current_dir}/validation.pem"
4
+ validation_client_name "validation"
5
+ validation_key "#{current_dir}/validation.pem"
6
+ chef_server_url "http://localhost:8889"
7
+ cache_type 'BasicFile'
8
+ cache_options( :path => "#{ENV['HOME']}/.chef/checksums" )
9
+ cookbook_path ["#{current_dir}/chef-repo/cookbooks"]
@@ -0,0 +1,27 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ MIIEogIBAAKCAQEA7TfhToresZudM5gaBfzM/eHrGuJtN8uMaG51fLk9rNVwOxIw
3
+ eb9AmWJSQgftRj4AJSnt8Jv+QyAafjg79rEmCpd2K+toN1fXiVsf/ld/VdMI5vCd
4
+ usJc8aC4OFIVrLetm9eq+joXiCSLfEYP1w4d1gc9wqr54rnGVgQdWv31NhqXX7Tl
5
+ 2bHRoEsfIFM7Vr5zC9Rv6XEtrwezSpzQ+ru707UOCOHNnH1TDxNDz+L71xJnGXD6
6
+ uh596hVm2GiXJ8lyCVJTs/RZ+HKtRuxYOJztdCQAXbd6DDjTBax/cCEzzoxK/LMc
7
+ 1K/zWCKN8yM/XpiFqNuBB0yrqS5Y4zlROY0ssQIDAQABAoIBAQDmC1HYvD1YGePq
8
+ O+/IrK8S6jr4WGq4OBIS2EPhTzbrXBU5g9s0xe7ckIfa9xr4CnpTkATqWCzMZd6r
9
+ Vtd31bVhgh6cWu829F3WG2O8YJfg4AX7B46+pWxC+qyMGbZhR8L5pb1ualWVtnL6
10
+ cms8D7mJbH5NQUeRwrz/f4AEVNGuw165PhglXnRq3zxs97jdNH6av0na1VLAmUeR
11
+ vmYToLoIsK5yLeNzMfRRrQkq4ndUvad2ahqsz+p/xUjfYneBz4uujE/PcCgi423Q
12
+ FMH1NtPpzmuZuABU53wUMW4BXsSGv+34UMhRTazcBPRBYjKT6l6F7Tt9wPFxrtVn
13
+ KYI9dI0tAoGBAPzBwLsUuyEJtSd2zW63f7EhhG/2rSBm1g9Bcs1sHZtXIX3JN51X
14
+ hd+ckXQcLgQYn8syGW1+WcuaHGyp7v3G0yr6b38FWwEnmD85Mq5da1dyio2udBdK
15
+ Xm8MfY94yP8qSH3bUDKEl+cV9X5rtzbQAorMXb/Qkc4vErWfABVBKeLPAoGBAPBD
16
+ FjGxER9YU4hFV2vn5qElfxa799Vl0uSvao0lSkTpA/sHFxAkRQc/mo1PBClaH0ba
17
+ Hqr141o5pGUDgLqpO3kEY5vYBOaFXLFdFCcL+1YUR6t0bX+WCHuq21Cs6Gu4+qNA
18
+ D4dpsSPDXfatyXWM5PF2d4FwO2XnL25Yt+rg6dh/AoGAbEfk9UCQWjr6bImswH3E
19
+ KnIddonK6VKk6aw0LmTe2imdo3GMbc+M/prohUF9RSv3aOlxk0LJ3TuMadDzHa0L
20
+ 0iGvmk8FCZ2Yz50FZUWIMtJTIRdXjJLDmfdT4x7vnMDUhXZrCPlcyhbSMPKcbtL2
21
+ A9hBYWdMz3PDJCOVuYVNGGkCgYEAhSxKUwTYfs1Qj8oPqOoDdfL4vLs3pfsoqEVr
22
+ BA1VW1jlMfE+IV5ZPKlOm2De56TijT09nnloqYwlyS/l3JENPAjoxWs5XCUzucPj
23
+ 9bi4eYAIMcr5Hq0kypdrtQ4CTiNcGbzaXq6A11fk72RotFWCWSzXFNIGuncoXTuj
24
+ xfcg5zUCf3TQrwpcBB1Hf9hm6lUVpptvUZJAQtkWoaWXUPRY0CjcVdDc5ak4xqL2
25
+ FcAuJwV95b3qLyPESJ8zUBLOg3DcT1X9mrvRuKgC/Ie6k4R+oxU/nXi4vsPXlvg4
26
+ yap6MUYSjPOa7eCrhg2zFZiqO6VLEogPc1nsjb9Zl2UWLLYyCVz=
27
+ -----END RSA PRIVATE KEY-----
@@ -0,0 +1,39 @@
1
+ require "securerandom"
2
+ require 'tmpdir'
3
+ require 'fileutils'
4
+ require File.expand_path(File.dirname(__FILE__) + '/knife_test_utils')
5
+ require File.expand_path(File.dirname(__FILE__) + '/matchers')
6
+
7
+ module KnifeTestHelper
8
+ extend RSpec::KnifeTestUtils
9
+ def temp_dir
10
+ @_temp_dir ||= Dir.mktmpdir
11
+ end
12
+
13
+ def match_status(test_run_expect)
14
+ if "#{test_run_expect}" == "should fail"
15
+ should_not have_outcome :status => 0
16
+ elsif "#{test_run_expect}" == "should succeed"
17
+ should have_outcome :status => 0
18
+ elsif "#{test_run_expect}" == "should return empty list"
19
+ should have_outcome :status => 0
20
+ else
21
+ should have_outcome :status => 0
22
+ end
23
+ end
24
+
25
+ def match_stdout(test_run_expect)
26
+ should have_outcome :stdout => test_run_expect
27
+ end
28
+
29
+ def create_file(file_dir, file_name, data_to_write_file_path)
30
+ puts "Creating: #{file_name}"
31
+ begin
32
+ data_to_write = File.read(File.expand_path("#{data_to_write_file_path}", __FILE__))
33
+ File.open("#{file_dir}/#{file_name}", 'w') {|f| f.write(data_to_write)}
34
+ rescue
35
+ puts "Error while creating file - #{file_name}"
36
+ end
37
+ end
38
+
39
+ end
@@ -0,0 +1,40 @@
1
+ require 'mixlib/shellout'
2
+
3
+ module RSpec
4
+ module KnifeTestUtils
5
+
6
+ def self.included(base)
7
+ base.class_eval do
8
+ subject { knife_run }
9
+ let(:knife_run) { run command }
10
+ let(:command) { fail 'Define let(:command) in the spec' }
11
+ let(:cmd_output) { @op }
12
+ end
13
+ end
14
+
15
+ # Convenience method for actually running a knife command in our
16
+ # testing repository. Returns the Mixlib::Shellout object ready for
17
+ # inspection.
18
+ def run(command_line)
19
+ shell_out = Mixlib::ShellOut.new("#{command_line}")
20
+ shell_out.timeout = 3000
21
+ shell_out.tap(&:run_command)
22
+ @op = shell_out.exitstatus == 1 ? shell_out.stderr : shell_out.stdout
23
+ return shell_out
24
+ end
25
+
26
+ def knife(knife_command)
27
+ run "knife #{knife_command}"
28
+ end
29
+
30
+ # Convenience function for grabbing a hash of several important
31
+ # Mixlib::Shellout command configuration parameters.
32
+ def self.command_setting(shellout_command)
33
+ keys = [:cwd, :user, :group, :umask, :timeout, :valid_exit_codes, :environment]
34
+ keys.inject({}) do |hash, attr|
35
+ hash[attr] = shellout_command.send(attr)
36
+ hash
37
+ end
38
+ end
39
+ end
40
+ end