knife-cloud 1.0.0.rc.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.
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,138 @@
1
+ #
2
+ # Author:: Prabhu Das (<prabhu.das@clogeny.com>)
3
+ # Author:: Siddheshwar More (<siddheshwar.more@clogeny.com>)
4
+ # Copyright:: Copyright (c) 2013-2014 Chef Software, Inc.
5
+ # License:: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+
19
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
20
+ require 'chef/knife/cloud/fog/service'
21
+ require 'support/shared_examples_for_service'
22
+
23
+ describe Chef::Knife::Cloud::FogService do
24
+
25
+ it_behaves_like Chef::Knife::Cloud::Service, Chef::Knife::Cloud::FogService.new
26
+
27
+ let (:instance) { Chef::Knife::Cloud::FogService.new({:auth_params => {:provider => 'Any Cloud Provider'}}) }
28
+
29
+ context "connection" do
30
+ before do
31
+ allow(instance).to receive(:exit)
32
+ end
33
+
34
+ it "creates a connection to fog service with the provided auth params." do
35
+ expect(instance).to receive(:add_api_endpoint)
36
+ expect(Fog::Compute).to receive(:new).with({:provider => 'Any Cloud Provider'})
37
+ instance.connection
38
+ end
39
+ end
40
+
41
+ context "network" do
42
+ it "creates a connection to fog network with the provided auth params." do
43
+ expect(Fog::Network).to receive(:new).with({:provider => 'Any Cloud Provider'})
44
+ instance.network
45
+ end
46
+
47
+ context "connection to fog" do
48
+ before do
49
+ allow(instance).to receive(:exit)
50
+ allow(instance).to receive(:ui).and_return(Object.new)
51
+ expect(instance.ui).to receive(:fatal)
52
+ end
53
+
54
+ it "handles Unauthorized exception." do
55
+ expect(Fog::Network).to receive(:new).with({:provider => 'Any Cloud Provider'}).and_raise Excon::Errors::Unauthorized.new("Unauthorized")
56
+ expect {instance.network}.to raise_error(Chef::Knife::Cloud::CloudExceptions::ServiceConnectionError)
57
+ end
58
+
59
+ it "handles SocketError or any other connection exception." do
60
+ socket_error = Excon::Errors::SocketError.new(Exception.new "Mock Error")
61
+ expect(Fog::Network).to receive(:new).with({:provider => 'Any Cloud Provider'}).and_raise socket_error
62
+ expect {instance.network}.to raise_error(Chef::Knife::Cloud::CloudExceptions::ServiceConnectionError)
63
+ end
64
+
65
+ it "handles NetworkNotFoundError exception." do
66
+ expect(Fog::Network).to receive(:new).with({:provider => 'Any Cloud Provider'}).and_raise Fog::Errors::NotFound.new("NotFound")
67
+ expect {instance.network}.to raise_error(Chef::Knife::Cloud::CloudExceptions::NetworkNotFoundError)
68
+ end
69
+ end
70
+ end
71
+
72
+ context "add_custom_attributes" do
73
+ before(:each) do
74
+ Chef::Config[:knife][:custom_attributes] = [{"state"=>"Inactive"}]
75
+ @server_def = {:name=>"vm-1", :image_ref=>"123",:flavor_ref=>"2", :key_name=>"key"}
76
+ instance.add_custom_attributes(@server_def)
77
+ end
78
+
79
+ it "adds the custom attributes provided to server_def" do
80
+ expect(@server_def.include?(:state)).to be true
81
+ end
82
+
83
+ it "sets the provided attributes with supplied values" do
84
+ expect(@server_def[:state] == "Inactive").to be true
85
+ end
86
+ end
87
+
88
+ ["servers", "images", "networks"].each do |resource_type|
89
+ resource = case resource_type
90
+ when "networks"
91
+ :network
92
+ else
93
+ :connection
94
+ end
95
+ context "list #{resource_type}" do
96
+
97
+ it "lists #{resource_type} of the current cloud service provider account." do
98
+ allow(instance).to receive_message_chain(resource.to_sym, "#{resource_type}".to_sym, :all)
99
+ instance.method("list_#{resource_type}").call
100
+ end
101
+
102
+ it "handles Excon::Errors::BadRequest exception." do
103
+ allow(instance).to receive(:ui).and_return(Object.new)
104
+ allow(instance.ui).to receive(:fatal)
105
+ allow(instance).to receive_message_chain(resource.to_sym, "#{resource_type}".to_sym, :all).and_raise Excon::Errors::BadRequest.new("Invalid Resource")
106
+ expect {instance.method("list_#{resource_type}").call}.to raise_error(Chef::Knife::Cloud::CloudExceptions::CloudAPIException)
107
+ end
108
+ end
109
+ end
110
+
111
+ context "#delete_server" do
112
+ before(:each) do
113
+ @server = TestResource.new({:id => "test-server1"})
114
+ @server.define_singleton_method(:destroy){}
115
+ end
116
+
117
+ it "delete instance successfully" do
118
+ server_name = "test-server1"
119
+ instance.ui = double
120
+ expect(instance).to receive(:get_server).and_return(@server)
121
+ expect(instance).to receive(:get_server_name).and_return(server_name)
122
+ expect(instance).to receive(:msg_pair).with("Instance Name", server_name)
123
+ expect(instance).to receive(:msg_pair).with("Instance ID", @server.id)
124
+ expect(instance.ui).to receive(:confirm)
125
+ expect(@server).to receive(:destroy)
126
+ instance.delete_server(server_name)
127
+ end
128
+
129
+ it "raise_error on non existence server delete " do
130
+ server_name = "test-server1"
131
+ instance.ui = double
132
+ error_message = "Could not locate server '#{server_name}'."
133
+ expect(instance).to receive(:get_server).and_return(nil)
134
+ expect(instance.ui).to receive(:error).with(error_message)
135
+ expect { instance.delete_server(server_name) }.to raise_error(Chef::Knife::Cloud::CloudExceptions::ServerDeleteError, error_message)
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,136 @@
1
+ #
2
+ # Author:: Kaustubh Deorukhkar (<kaustubh@clogeny.com>)
3
+ # Author:: Prabhu Das (<prabhu.das@clogeny.com>)
4
+ # Author:: Siddheshwar More (<siddheshwar.more@clogeny.com>)
5
+ # Copyright:: Copyright (c) 2013-2014 Chef Software, Inc.
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
+ require 'spec_helper'
21
+ require 'chef/knife/cloud/list_resource_command'
22
+ require 'support/shared_examples_for_command'
23
+ require 'excon/errors'
24
+
25
+ describe Chef::Knife::Cloud::ResourceListCommand do
26
+ it_behaves_like Chef::Knife::Cloud::Command, Chef::Knife::Cloud::ResourceListCommand.new
27
+
28
+ let (:instance) {Chef::Knife::Cloud::ResourceListCommand.new}
29
+ let (:resources) {[ TestResource.new({:id => "resource-1", :os => "ubuntu"}),
30
+ TestResource.new({:id => "resource-2", :os => "windows"})]}
31
+
32
+ context "Basic tests:" do
33
+ it "raises exception to override #query_resource method" do
34
+ allow(instance).to receive(:create_service_instance).and_return(Chef::Knife::Cloud::Service.new)
35
+ expect {instance.run}.to raise_error(Chef::Exceptions::Override, "You must override query_resource in #{instance.to_s} to return resources.")
36
+ end
37
+
38
+ it "responds to #list method" do
39
+ allow(instance).to receive(:query_resource)
40
+ expect(instance).to respond_to(:list)
41
+ end
42
+
43
+ context "responds to #list method" do
44
+ let(:test_resource) { "test" }
45
+ before(:each) do
46
+ expect(instance.ui).to receive(:fatal)
47
+ end
48
+
49
+ it "handle generic exception" do
50
+ allow(test_resource).to receive(:sort_by).and_raise StandardError
51
+ expect {instance.list(test_resource)}.to raise_error(StandardError)
52
+ end
53
+
54
+ it "handle Excon::Errors::BadRequest exception." do
55
+ allow(test_resource).to receive(:sort_by).and_raise Excon::Errors::BadRequest.new("excon error message")
56
+ expect {instance.list(test_resource)}.to raise_error(Excon::Errors::BadRequest)
57
+ end
58
+ end
59
+ end
60
+
61
+ context "Without columns_with_info parameter in #list:" do
62
+ before do
63
+ allow(instance).to receive(:query_resource).and_return(resources)
64
+ allow(instance).to receive(:create_service_instance).and_return(Chef::Knife::Cloud::Service.new)
65
+ allow(instance).to receive(:puts)
66
+ end
67
+
68
+ it "lists resources in json format when columns_with_info parameter is empty" do
69
+ expect(instance).to receive(:puts).with(resources[0].to_json)
70
+ expect(instance).to receive(:puts).with(resources[1].to_json)
71
+ expect(instance).to receive(:puts).with("\n").twice
72
+ instance.run
73
+ end
74
+ end
75
+
76
+ context "With columns_with_info parameter in #list:" do
77
+ context "#value_callback not specified in columns_with_info" do
78
+ before do
79
+ class Derived < Chef::Knife::Cloud::ResourceListCommand
80
+ attr_accessor :resource_filters
81
+ def before_exec_command
82
+ @columns_with_info = [ { :key => 'id', :label => 'Instance ID' },
83
+ { :key => 'os', :label => 'Operating system' } ]
84
+ end
85
+ end
86
+
87
+ @derived_instance = Derived.new
88
+ allow(@derived_instance).to receive(:query_resource).and_return(resources)
89
+ allow(@derived_instance).to receive(:puts)
90
+ allow(@derived_instance).to receive(:create_service_instance).and_return(Chef::Knife::Cloud::Service.new)
91
+ end
92
+
93
+ it "lists all resources" do
94
+ expect(@derived_instance.ui).to receive(:list).with(["Instance ID", "Operating system", "resource-1", "ubuntu", "resource-2", "windows"], :uneven_columns_across, 2)
95
+ @derived_instance.run
96
+ end
97
+
98
+ it "excludes resource when filter is specified" do
99
+ @derived_instance.resource_filters = [{:attribute => 'id', :regex => /^resource-1$/}]
100
+ expect(@derived_instance.ui).to receive(:list).with(["Instance ID", "Operating system", "resource-2", "windows"], :uneven_columns_across, 2)
101
+ @derived_instance.run
102
+ end
103
+
104
+ it "lists all resources when disable filter" do
105
+ @derived_instance.config[:disable_filter] = true
106
+ @derived_instance.resource_filters = [{:attribute => 'id', :regex => /^resource-1$/}]
107
+ expect(@derived_instance.ui).to receive(:list).with(["Instance ID", "Operating system", "resource-1", "ubuntu", "resource-2", "windows"], :uneven_columns_across, 2)
108
+ @derived_instance.run
109
+ end
110
+ end
111
+ context "#value_callback specified in columns_with_info" do
112
+ before do
113
+ class Derived < Chef::Knife::Cloud::ResourceListCommand
114
+ attr_accessor :resource_filters
115
+ def before_exec_command
116
+ @columns_with_info = [ { :key => 'id', :label => 'Instance ID' },
117
+ { :key => 'os', :label => 'Operating system', :value_callback => method(:format_os) } ]
118
+ end
119
+ def format_os(os)
120
+ (os == 'ubuntu') ? "ubuntu - operating system with Linux kernel" : os
121
+ end
122
+ end
123
+
124
+ @derived_instance = Derived.new
125
+ allow(@derived_instance).to receive(:query_resource).and_return(resources)
126
+ allow(@derived_instance).to receive(:puts)
127
+ allow(@derived_instance).to receive(:create_service_instance).and_return(Chef::Knife::Cloud::Service.new)
128
+ end
129
+
130
+ it "lists formatted list of resources" do
131
+ expect(@derived_instance.ui).to receive(:list).with(["Instance ID", "Operating system", "resource-1", "ubuntu - operating system with Linux kernel", "resource-2", "windows"], :uneven_columns_across, 2)
132
+ @derived_instance.run
133
+ end
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,198 @@
1
+ #
2
+ # Author:: Mukta Aphale (<mukta.aphale@clogeny.com>)
3
+ # Author:: Siddheshwar More (<siddheshwar.more@clogeny.com>)
4
+ # Copyright:: Copyright (c) 2013-2014 Chef Software, Inc.
5
+ # License:: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+
19
+ require 'support/shared_examples_for_command'
20
+ require 'support/shared_examples_for_servercreatecommand'
21
+ require 'net/ssh'
22
+ require 'chef/knife/cloud/server/create_options'
23
+
24
+ describe Chef::Knife::Cloud::ServerCreateCommand do
25
+ it_behaves_like Chef::Knife::Cloud::Command, Chef::Knife::Cloud::ServerCreateCommand.new
26
+ it_behaves_like Chef::Knife::Cloud::ServerCreateCommand, Chef::Knife::Cloud::ServerCreateCommand.new
27
+
28
+ describe "#validate_params!" do
29
+ before(:each) do
30
+ @instance = Chef::Knife::Cloud::ServerCreateCommand.new
31
+ allow(@instance.ui).to receive(:error)
32
+ Chef::Config[:knife][:bootstrap_protocol] = "ssh"
33
+ Chef::Config[:knife][:identity_file] = "identity_file"
34
+ Chef::Config[:knife][:ssh_password] = "ssh_password"
35
+ Chef::Config[:knife][:chef_node_name] = "chef_node_name"
36
+ Chef::Config[:knife][:winrm_password] = "winrm_password"
37
+ end
38
+ after(:all) do
39
+ Chef::Config[:knife].delete(:bootstrap_protocol)
40
+ Chef::Config[:knife].delete(:identity_file)
41
+ Chef::Config[:knife].delete(:chef_node_name)
42
+ Chef::Config[:knife].delete(:ssh_password)
43
+ Chef::Config[:knife].delete(:winrm_password)
44
+ end
45
+
46
+ it "run sucessfully on all params exist" do
47
+ expect { @instance.validate_params! }.to_not raise_error
48
+ expect(@instance.config[:chef_node_name]).to eq(Chef::Config[:knife][:chef_node_name])
49
+ end
50
+
51
+ context "when bootstrap_protocol ssh" do
52
+ it "raise error on ssh_password and identity_file are missing" do
53
+ Chef::Config[:knife].delete(:identity_file)
54
+ Chef::Config[:knife].delete(:ssh_password)
55
+ expect { @instance.validate_params! }.to raise_error(Chef::Knife::Cloud::CloudExceptions::ValidationError, " You must provide either Identity file or SSH Password..")
56
+ end
57
+ end
58
+
59
+ context "when bootstrap_protocol winrm" do
60
+ it "raise error on winrm_password is missing" do
61
+ Chef::Config[:knife][:bootstrap_protocol] = "winrm"
62
+ Chef::Config[:knife].delete(:winrm_password)
63
+ expect { @instance.validate_params! }.to raise_error(Chef::Knife::Cloud::CloudExceptions::ValidationError, " You must provide Winrm Password..")
64
+ end
65
+ end
66
+ end
67
+
68
+ describe "#after_exec_command" do
69
+ it "calls bootstrap" do
70
+ instance = Chef::Knife::Cloud::ServerCreateCommand.new
71
+ expect(instance).to receive(:bootstrap)
72
+ instance.after_exec_command
73
+ end
74
+
75
+ it "delete server on bootstrap failure" do
76
+ instance = Chef::Knife::Cloud::ServerCreateCommand.new
77
+ instance.service = Chef::Knife::Cloud::Service.new
78
+ allow(instance).to receive(:raise)
79
+ allow(instance.ui).to receive(:fatal)
80
+ instance.config[:delete_server_on_failure] = true
81
+ allow(instance).to receive(:bootstrap).and_raise(Chef::Knife::Cloud::CloudExceptions::BootstrapError)
82
+ expect(instance.service).to receive(:delete_server_dependencies)
83
+ expect(instance.service).to receive(:delete_server_on_failure)
84
+ instance.after_exec_command
85
+ end
86
+
87
+ # Currently the RangeError is occured when image_os_type is set to linux and bootstrap-protocol is set to ssh before windows server bootstrap.
88
+ it "raise error message when bootstrap fails due to image_os_type not exist" do
89
+ instance = Chef::Knife::Cloud::ServerCreateCommand.new
90
+ instance.service = Chef::Knife::Cloud::Service.new
91
+ allow(instance.ui).to receive(:fatal)
92
+ instance.config[:delete_server_on_failure] = true
93
+ allow(instance).to receive(:bootstrap).and_raise(RangeError)
94
+ expect(instance.service).to receive(:delete_server_dependencies)
95
+ expect(instance.service).to receive(:delete_server_on_failure)
96
+ expect { instance.after_exec_command }.to raise_error(RangeError, "Check if --bootstrap-protocol and --image-os-type is correct. RangeError")
97
+ end
98
+ end
99
+
100
+ describe "#set_default_config" do
101
+ it "set valid image os type" do
102
+ instance = Chef::Knife::Cloud::ServerCreateCommand.new
103
+ instance.config[:bootstrap_protocol] = 'winrm'
104
+ instance.set_default_config
105
+ expect(instance.config[:image_os_type]).to eq('windows')
106
+ end
107
+ end
108
+
109
+ class ServerCreate < Chef::Knife::Cloud::ServerCreateCommand
110
+ include Chef::Knife::Cloud::ServerCreateOptions
111
+ end
112
+
113
+ describe "#bootstrap options" do
114
+
115
+ it "set chef config knife options" do
116
+ instance = ServerCreate.new
117
+ bootstrap_url = "bootstrap_url"
118
+ bootstrap_install_command = "bootstrap_install_command"
119
+ bootstrap_wget_options = "bootstrap_wget_options"
120
+ bootstrap_curl_options = "bootstrap_curl_options"
121
+ bootstrap_no_proxy = "bootstrap_no_proxy"
122
+
123
+ instance.options[:bootstrap_url][:proc].call bootstrap_url
124
+ expect(Chef::Config[:knife][:bootstrap_url]).to eq(bootstrap_url)
125
+
126
+ instance.options[:bootstrap_install_command][:proc].call bootstrap_install_command
127
+ expect(Chef::Config[:knife][:bootstrap_install_command]).to eq(bootstrap_install_command)
128
+
129
+ instance.options[:bootstrap_wget_options][:proc].call bootstrap_wget_options
130
+ expect(Chef::Config[:knife][:bootstrap_wget_options]).to eq(bootstrap_wget_options)
131
+
132
+ instance.options[:bootstrap_curl_options][:proc].call bootstrap_curl_options
133
+ expect(Chef::Config[:knife][:bootstrap_curl_options]).to eq(bootstrap_curl_options)
134
+
135
+ instance.options[:bootstrap_no_proxy][:proc].call bootstrap_no_proxy
136
+ expect(Chef::Config[:knife][:bootstrap_no_proxy]).to eq(bootstrap_no_proxy)
137
+
138
+ expect(instance.options[:auth_timeout][:default]).to eq(25)
139
+ end
140
+ end
141
+
142
+ describe "#before_bootstrap" do
143
+
144
+ before(:all) { @instance = ServerCreate.new }
145
+
146
+ context "bootstrap_protocol shh" do
147
+ before {@instance.config[:bootstrap_protocol] = "ssh"}
148
+
149
+ it "set ssh_user value by using -x option for ssh bootstrap protocol or linux image" do
150
+ # Currently -x option set config[:winrm_user]
151
+ # default value of config[:ssh_user] is root
152
+ @instance.config[:winrm_user] = "ubuntu"
153
+ @instance.config[:ssh_user] = "root"
154
+
155
+ @instance.before_bootstrap
156
+ expect(@instance.config[:ssh_user]).to eq("ubuntu")
157
+ end
158
+
159
+ it "set ssh_password value by using -P option for ssh bootstrap protocol or linux image" do
160
+ # Currently -P option set config[:winrm_password]
161
+ # default value of config[:ssh_password] is nil
162
+ @instance.config[:winrm_password] = "winrm_password"
163
+ @instance.config[:ssh_password] = nil
164
+
165
+ @instance.before_bootstrap
166
+ expect(@instance.config[:ssh_password]).to eq("winrm_password")
167
+ end
168
+
169
+ it "set ssh_port value by using -p option for ssh bootstrap protocol or linux image" do
170
+ # Currently -p option set config[:winrm_port]
171
+ # default value of config[:ssh_port] is 22
172
+ @instance.config[:winrm_port] = "1234"
173
+ @instance.config[:ssh_port] = "22"
174
+
175
+ @instance.before_bootstrap
176
+ expect(@instance.config[:ssh_port]).to eq("1234")
177
+ end
178
+
179
+ it "set identity_file value by using -i option for ssh bootstrap protocol or linux image" do
180
+ # Currently -i option set config[:kerberos_keytab_file]
181
+ # default value of config[:identity_file] is nil
182
+ @instance.config[:kerberos_keytab_file] = "kerberos_keytab_file"
183
+ @instance.config[:identity_file] = nil
184
+
185
+ @instance.before_bootstrap
186
+ expect(@instance.config[:identity_file]).to eq("kerberos_keytab_file")
187
+ end
188
+ end
189
+
190
+ context "bootstrap_protocol winrm" do
191
+ it "skip ssh_override_winrm" do
192
+ @instance.config[:bootstrap_protocol] = "winrm"
193
+ expect(@instance).to_not receive(:ssh_override_winrm)
194
+ @instance.before_bootstrap
195
+ end
196
+ end
197
+ end
198
+ end
@@ -0,0 +1,25 @@
1
+ #
2
+ # Author:: Kaustubh Deorukhkar (<kaustubh@clogeny.com>)
3
+ # Copyright:: Copyright (c) 2013 Chef Software, 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
+ require 'spec_helper'
19
+ require 'support/shared_examples_for_command'
20
+ require 'support/shared_examples_for_serverdeletecommand'
21
+
22
+ describe Chef::Knife::Cloud::ServerDeleteCommand do
23
+ it_behaves_like Chef::Knife::Cloud::Command, Chef::Knife::Cloud::ServerDeleteCommand.new
24
+ it_behaves_like Chef::Knife::Cloud::ServerDeleteCommand, Chef::Knife::Cloud::ServerDeleteCommand.new
25
+ end
@@ -0,0 +1,119 @@
1
+ #
2
+ # Author:: Siddheshwar More (<siddheshwar.more@clogeny.com>)
3
+ # Author:: Prabhu Das (<prabhu.das@clogeny.com>)
4
+ # Copyright:: Copyright (c) 2013-2014 Chef Software, Inc.
5
+ # License:: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+
19
+ require 'spec_helper'
20
+ require 'support/shared_examples_for_command'
21
+ require 'chef/knife/cloud/server/list_command'
22
+ require 'chef/node'
23
+
24
+ describe Chef::Knife::Cloud::ServerListCommand do
25
+ it_behaves_like Chef::Knife::Cloud::Command, Chef::Knife::Cloud::ServerListCommand.new
26
+
27
+ describe "#before_exec_command" do
28
+ it "set chef data columns info on chef data options" do
29
+ instance = Chef::Knife::Cloud::ServerListCommand.new
30
+ instance.config[:chef_data] = true
31
+ expect(Chef::Node).to receive(:list).with(true)
32
+ expect(instance.before_exec_command).to include({:label => "Chef Node Name", :key => "name"})
33
+ end
34
+
35
+ it "set chef data columns info on chef-data and chef-node-attribute options" do
36
+ chef_node_attribute = "platform_family"
37
+ instance = Chef::Knife::Cloud::ServerListCommand.new
38
+ instance.config[:chef_data] = true
39
+ instance.config[:chef_node_attribute] = chef_node_attribute
40
+ expect(Chef::Node).to receive(:list).with(true)
41
+ expect(instance.before_exec_command).to include({:label => chef_node_attribute, :key => chef_node_attribute})
42
+ end
43
+
44
+ it "not set chef data columns info if chef-data option is not set" do
45
+ instance = Chef::Knife::Cloud::ServerListCommand.new
46
+ expect(Chef::Node).to_not receive(:list).with(true)
47
+ expect(instance.before_exec_command).to be(nil)
48
+ end
49
+
50
+ it "not set chef data columns info on chef-node-attribute option set but chef-data option is not set" do
51
+ instance = Chef::Knife::Cloud::ServerListCommand.new
52
+ instance.config[:chef_node_attribute] = "platform_family"
53
+ expect(Chef::Node).to_not receive(:list).with(true)
54
+ expect(instance.before_exec_command).to be(nil)
55
+ end
56
+ end
57
+
58
+ describe "#get_resource_col_val" do
59
+ let (:resources) {[ TestResource.new({:id => "server-1", :name => "server-1", :os => "ubuntu"})]}
60
+ before do
61
+ class DerivedServerList < Chef::Knife::Cloud::ServerListCommand
62
+ attr_accessor :node
63
+ def before_exec_command
64
+ @columns_with_info = [ { :key => 'id', :label => 'Instance ID' }, {:label => 'Environment', :key => 'chef_environment'}, {:label => 'platform_family', :key => 'platform_family'} ]
65
+ @chef_data_col_info = [ {:label => 'Environment', :key => 'chef_environment'}, {:label => 'platform_family', :key => 'platform_family'} ]
66
+ @node = TestResource.new({:id => "server-1", :name => "server-1",
67
+ :chef_environment => "_default", :platform_family => "debian"})
68
+ @node.define_singleton_method(:attribute?) do |attribute|
69
+ end
70
+ @node_list = {"server-1" => @node}
71
+ end
72
+ end
73
+ @derived_instance = DerivedServerList.new
74
+ @derived_instance.config[:chef_data] = true
75
+ @derived_instance.config[:chef_node_attribute] = "platform_family"
76
+ @derived_instance.before_exec_command
77
+ @derived_instance.service = double Chef::Knife::Cloud::Service.new
78
+ allow(@derived_instance.service).to receive(:get_server_name).with(resources.first).and_return("server-1")
79
+ end
80
+
81
+ it "return columns_with_info values" do
82
+ expect(@derived_instance.node).to receive(:attribute?).with("platform_family").and_return(true)
83
+ expect(@derived_instance.get_resource_col_val(resources.first)).to eq(["server-1", "_default", "debian"])
84
+ end
85
+
86
+ it "raise error on invalide chef_node_attribute" do
87
+ allow(@derived_instance.ui).to receive(:error)
88
+ expect(@derived_instance.node).to receive(:attribute?).with("platform_family").and_return(false)
89
+ expect { @derived_instance.get_resource_col_val(resources.first) }.to raise_error(Chef::Knife::Cloud::CloudExceptions::CloudAPIException, "The Node does not have a platform_family attribute.")
90
+ end
91
+ end
92
+
93
+ describe "#format_server_state" do
94
+ before(:each) do
95
+ @instance = Chef::Knife::Cloud::ServerListCommand.new
96
+ end
97
+
98
+ %w{ shutting-down terminated stopping stopped error shutoff }.each do |state|
99
+ it "set state color red on server state is in #{state}" do
100
+ expect(@instance.ui).to receive(:color).with(state, :red)
101
+ @instance.format_server_state(state)
102
+ end
103
+ end
104
+
105
+ %w{ pending build paused suspended hard_reboot }.each do |state|
106
+ it "set state color yellow on server state is in #{state}" do
107
+ expect(@instance.ui).to receive(:color).with(state, :yellow)
108
+ @instance.format_server_state(state)
109
+ end
110
+ end
111
+
112
+ %w{ running }.each do |state|
113
+ it "set state color green on server state is #{state}" do
114
+ expect(@instance.ui).to receive(:color).with(state, :green)
115
+ @instance.format_server_state(state)
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,64 @@
1
+ #
2
+ # Author:: Siddheshwar More (<siddheshwar.more@clogeny.com>)
3
+ # Copyright:: Copyright (c) 2013-2014 Chef Software, 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
+ require 'support/shared_examples_for_command'
19
+ require 'chef/knife/cloud/server/show_command'
20
+
21
+ describe Chef::Knife::Cloud::ServerShowCommand do
22
+ it_behaves_like Chef::Knife::Cloud::Command, Chef::Knife::Cloud::ServerShowCommand.new
23
+
24
+ describe "#validate_params!" do
25
+ before(:each) do
26
+ @instance = Chef::Knife::Cloud::ServerShowCommand.new
27
+ allow(@instance.ui).to receive(:error)
28
+ Chef::Config[:knife][:instance_id] = "instance_id"
29
+ end
30
+ after(:all) do
31
+ Chef::Config[:knife].delete(:instance_id)
32
+ end
33
+
34
+ it "run sucessfully on all params exist" do
35
+ expect { @instance.validate_params! }.to_not raise_error
36
+ end
37
+
38
+ it "raise error on missing instance_id param" do
39
+ Chef::Config[:knife].delete(:instance_id)
40
+ expect { @instance.validate_params! }.to raise_error(Chef::Knife::Cloud::CloudExceptions::ValidationError, " You must provide a valid Instance Id.")
41
+ end
42
+ end
43
+
44
+ describe "#execute_command" do
45
+ it "show server summary" do
46
+ instance = Chef::Knife::Cloud::ServerShowCommand.new
47
+ instance.service = Chef::Knife::Cloud::Service.new
48
+ server = Object.new
49
+ expect(instance.service).to receive(:get_server).and_return(server)
50
+ expect(instance.service).to receive(:server_summary)
51
+ instance.execute_command
52
+ end
53
+
54
+ it "raise error on invalid instance id" do
55
+ instance = Chef::Knife::Cloud::ServerShowCommand.new
56
+ instance.service = Chef::Knife::Cloud::Service.new
57
+ Chef::Config[:knife][:instance_id] = "invalid_id"
58
+ allow(instance.ui).to receive(:error)
59
+ expect(instance.service).to receive(:get_server).and_return(nil)
60
+ expect(instance.service).to_not receive(:server_summary)
61
+ expect { instance.execute_command }.to raise_error(Chef::Knife::Cloud::CloudExceptions::ServerShowError, "Server doesn't exists for this invalid_id instance id.")
62
+ end
63
+ end
64
+ end