knife-softlayer 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,124 @@
1
+ #
2
+ # Author:: Matt Eldridge (<matt.eldridge@us.ibm.com>)
3
+ # © Copyright IBM Corporation 2014.
4
+ #
5
+ # LICENSE: Apache 2.0 (http://www.apache.org/licenses/)
6
+ #
7
+
8
+ require 'chef/knife/softlayer_base'
9
+ require 'chef/search/query'
10
+ require 'chef/api_client'
11
+
12
+ class Chef
13
+ class Knife
14
+ class SoftlayerServerDestroy < Knife
15
+
16
+ attr_accessor :node
17
+ attr_accessor :cci
18
+
19
+ include Knife::SoftlayerBase
20
+
21
+ banner 'knife softlayer server destroy (options)'
22
+
23
+ option :chef_node_name,
24
+ :short => "-N NAME",
25
+ :long => "--node-name NAME",
26
+ :description => "The Chef node name for your new node"
27
+
28
+ option :ip_address,
29
+ :long => "--ip-address ADDRESS",
30
+ :short => "-I",
31
+ :description => "Find the CCI and node to destroy by its public IP address."
32
+
33
+ ##
34
+ # Run the procedure to destroy a SoftLayer VM and clean up its Chef node and client.
35
+ # @return [nil]
36
+ def run
37
+
38
+ $stdout.sync = true
39
+
40
+ puts ui.color("Decommissioning SoftLayer CCI, this may take a few minutes.", :green)
41
+
42
+ @chef = Chef::Search::Query.new
43
+
44
+ if config[:chef_node_name]
45
+ @chef.search('node', "name:#{config[:chef_node_name]}") do |node|
46
+ config[:ip_address] = node.ipaddress
47
+ @node = node
48
+ end
49
+ elsif config[:ip_address]
50
+ @chef.search('node', "ipaddress:#{config[:ip_address]}") do |node|
51
+ @node = node
52
+ end
53
+ else
54
+ raise "#{ui.color("FATAL: Please supply the node name or IP address.", :red)}"
55
+ end
56
+
57
+ @cci = connection.findByIpAddress(config[:ip_address])
58
+
59
+
60
+ @node.nil? and raise "#{ui.color('Chef node not found!', :red)}"
61
+ @cci.nil? and raise "#{ui.color('CCI instance with IP: ' + config[:ip_address] +' not found!', :red)}"
62
+
63
+
64
+ begin
65
+ begin
66
+ destroy_item(Chef::Node, @node.name, "node")
67
+ puts ui.color("Chef node successfully deleted.", :green)
68
+ rescue Exception => e
69
+ err_msg ui.color("ERROR DELETING CHEF NODE", :red)
70
+ err_msg ui.color(e.message, :yellow)
71
+ err_msg ui.color(e.backtrace, :yellow)
72
+ end
73
+
74
+ begin
75
+ destroy_item(Chef::ApiClient, @node.name, "client")
76
+ puts ui.color("Chef client successfully deleted.", :green)
77
+ rescue Exception => e
78
+ err_msg ui.color("ERROR DELETING CHEF CLIENT", :red)
79
+ err_msg ui.color(e.message, :yellow)
80
+ err_msg ui.color(e.backtrace, :yellow)
81
+ end
82
+
83
+ begin
84
+ connection.object_with_id(@cci['id']).deleteObject
85
+ puts ui.color("SoftLayer CCI successfully deleted. You are no longer being billed for this instance.", :green)
86
+ rescue Exception => e
87
+ err_msg ui.color("ERROR DELETING SOFTLAYER CCI. IT'S POSSIBLE YOU ARE STILL BEING BILLED FOR THIS INSTANCE. PLEASE CONTACT SUPPORT FOR FURTHER ASSISTANCE", :red)
88
+ err_msg ui.color(e.message, :yellow)
89
+ err_msg ui.color(e.backtrace, :yellow)
90
+ end
91
+ ensure
92
+ unless err_msg.empty?
93
+ err_msg.each do |msg|
94
+ puts msg
95
+ end
96
+ end
97
+ end
98
+
99
+ end
100
+
101
+ # @param [Chef::*] klass
102
+ # @param [String] name
103
+ # @param [String] type_name
104
+ # @return [nil]
105
+ def destroy_item(klass, name, type_name)
106
+ begin
107
+ object = klass.load(name)
108
+ object.destroy
109
+ ui.warn("Deleted #{type_name} #{name}")
110
+ rescue Net::HTTPServerException
111
+ ui.warn("Could not find a #{type_name} named #{name} to delete!")
112
+ end
113
+ end
114
+
115
+ def err_msg(msg=nil)
116
+ @msgs ||= []
117
+ @msgs.push(msg).compact
118
+ end
119
+
120
+ end
121
+ end
122
+ end
123
+
124
+
@@ -0,0 +1,12 @@
1
+ #
2
+ # Author:: Matt Eldridge (<matt.eldridge@us.ibm.com>)
3
+ # © Copyright IBM Corporation 2014.
4
+ #
5
+ # LICENSE: Apache 2.0 (http://www.apache.org/licenses/)
6
+ #
7
+
8
+ module Knife
9
+ module Softlayer
10
+ VERSION = "0.0.2"
11
+ end
12
+ end
@@ -0,0 +1,21 @@
1
+ #
2
+ # Author:: Matt Eldridge (<matt.eldridge@us.ibm.com>)
3
+ # © Copyright IBM Corporation 2014.
4
+ #
5
+ # LICENSE: Apache 2.0 (http://www.apache.org/licenses/)
6
+ #
7
+
8
+ $:.unshift File.expand_path('../../lib', __FILE__)
9
+ require 'chef'
10
+ require 'chef/knife/winrm_base'
11
+ require 'chef/knife/softlayer_server_create'
12
+ require 'chef/knife/softlayer_server_destroy'
13
+
14
+ # Clear config between each example
15
+ # to avoid dependencies between examples
16
+ RSpec.configure do |c|
17
+ c.before(:each) do
18
+ Chef::Config.reset
19
+ Chef::Config[:knife] ={}
20
+ end
21
+ end
@@ -0,0 +1,136 @@
1
+ #
2
+ # Author:: Matt Eldridge (<matt.eldridge@us.ibm.com>)
3
+ # © Copyright IBM Corporation 2014.
4
+ #
5
+ # LICENSE: Apache 2.0 (http://www.apache.org/licenses/)
6
+ #
7
+
8
+ require File.expand_path('../../spec_helper', __FILE__)
9
+ require 'chef/knife/bootstrap'
10
+ require 'softlayer_api'
11
+
12
+
13
+ describe Chef::Knife::SoftlayerServerCreate do
14
+ before(:each) do
15
+ @knife_softlayer_create = Chef::Knife::SoftlayerServerCreate.new
16
+ @knife_softlayer_create.stub(:tcp_test_ssh).and_return(true)
17
+
18
+ @softlayer_connection = double("connection", :createObject => {
19
+ 'accountId' => 000001,
20
+ 'createDate' => '2014-03-24T18:03:27-04:00',
21
+ 'dedicatedAccountHostOnlyFlag' => false,
22
+ 'domain' => 'example.com',
23
+ 'fullyQualifiedDomainName' => 'test',
24
+ 'hostname' =>"test",
25
+ 'id' => 0000001,
26
+ 'lastPowerStateId' => nil,
27
+ 'lastVerifiedDate' => nil,
28
+ 'maxCpu' => 4,
29
+ 'maxCpuUnits' => 'CORE',
30
+ 'maxMemory' => 4096,
31
+ 'metricPollDate' => nil,
32
+ 'modifyDate' => nil,
33
+ 'startCpus' => 4,
34
+ 'statusId' => 1001,
35
+ 'globalIdentifier' => '93f3bfb6-3f48-4e9c-82ab-25e8b5dd14ce'
36
+ })
37
+
38
+ @softlayer_servers = double("servers")
39
+ @cci = double("cci")
40
+
41
+ @softlayer_server_attribs = { :id => '1234567',
42
+ :public_ip_address => '33.33.33.33',
43
+ :private_dns_name => 'example.com',
44
+ :private_ip_address => '10.10.10.10',
45
+ }
46
+
47
+ @softlayer_server_attribs.each_pair do |attrib, value|
48
+ @cci.stub(attrib).and_return(value)
49
+ end
50
+ end
51
+
52
+ describe "go-wrong cases for .run" do
53
+ it "should raise an exception if we try to create/bootstrap a windows instance" do
54
+ @knife_softlayer_create.config[:os_code] = 'WIN_2012-STD_64'
55
+ expect { @knife_softlayer_create.run }.to raise_exception(Chef::Knife::SoftlayerServerCreateError)
56
+ end
57
+ end
58
+
59
+ describe "go-right cases for .run" do
60
+ before do
61
+ @softlayer_connection.should_receive(:object_mask).with('mask.operatingSystem.passwords.password').and_return(@softlayer_servers)
62
+ @softlayer_servers.should_receive(:object_with_id).with(1).and_return(@softlayer_servers)
63
+ @softlayer_servers.should_receive(:getObject).and_return(@cci)
64
+ @cci.should_receive(:[]).exactly(3).times.with('operatingSystem').and_return({'passwords' => ['foobar']})
65
+ @cci.should_receive(:[]).with('primaryIpAddress').and_return('33.33.33.33')
66
+
67
+ @public_ip = "33.33.33.33"
68
+ SoftLayer::Service.should_receive(:new).twice.and_return(@softlayer_connection)
69
+
70
+
71
+ @knife_softlayer_create.stub(:puts)
72
+ @knife_softlayer_create.stub(:print)
73
+ {
74
+ :domain => 'example.com',
75
+ :hostname => 'test',
76
+ :flavor => 'medium',
77
+ :chef_node_name => 'test.example.com',
78
+ }.each do |key, value|
79
+ @knife_softlayer_create.config[key] = value
80
+ end
81
+
82
+ @bootstrap = Chef::Knife::Bootstrap.new
83
+ Chef::Knife::Bootstrap.stub(:new).and_return(@bootstrap)
84
+ @bootstrap.should_receive(:run)
85
+ end
86
+
87
+ it "defaults to a distro of 'chef-full' for a linux instance" do
88
+ @knife_softlayer_create.config[:distro] = @knife_softlayer_create.options[:distro][:default]
89
+ @knife_softlayer_create.run
90
+ @bootstrap.config[:distro].should == 'chef-full'
91
+ end
92
+
93
+ it "creates an CCI instance and bootstraps it" do
94
+ @knife_softlayer_create.run
95
+ @knife_softlayer_create.cci.should_not == nil
96
+ end
97
+
98
+ it "set ssh_user value by using -x option" do
99
+ # default value of config[:ssh_user] is root
100
+ @knife_softlayer_create.config[:ssh_user] = "tim-eah!"
101
+
102
+ @knife_softlayer_create.run
103
+ @knife_softlayer_create.config[:ssh_user].should == "tim-eah!"
104
+ @knife_softlayer_create.cci.should_not == nil
105
+ end
106
+
107
+ it "set ssh_password value by using -P option" do
108
+ # default value of config[:ssh_password] is nil
109
+ @knife_softlayer_create.config[:ssh_password] = "passw0rd"
110
+
111
+ @knife_softlayer_create.run
112
+ @knife_softlayer_create.config[:ssh_password].should == "passw0rd"
113
+ @knife_softlayer_create.cci.should_not == nil
114
+ end
115
+
116
+ it "set ssh_port value by using -p option" do
117
+ # default value of config[:ssh_port] is 22
118
+ @knife_softlayer_create.config[:ssh_port] = "86"
119
+
120
+ @knife_softlayer_create.run
121
+ @knife_softlayer_create.config[:ssh_port].should == "86"
122
+ @knife_softlayer_create.cci.should_not == nil
123
+ end
124
+
125
+ it "set identity_file value by using -i option for ssh bootstrap protocol or linux image" do
126
+ # default value of config[:identity_file] is nil
127
+ @knife_softlayer_create.config[:identity_file] = "~/.ssh/mah_key_file.pem"
128
+
129
+ @knife_softlayer_create.run
130
+ @knife_softlayer_create.config[:identity_file].should == "~/.ssh/mah_key_file.pem"
131
+ @knife_softlayer_create.cci.should_not == nil
132
+ end
133
+
134
+ end
135
+
136
+ end
@@ -0,0 +1,71 @@
1
+ #
2
+ # Author:: Matt Eldridge (<matt.eldridge@us.ibm.com>)
3
+ # © Copyright IBM Corporation 2014.
4
+ #
5
+ # LICENSE: Apache 2.0 (http://www.apache.org/licenses/)
6
+ #
7
+
8
+ require File.expand_path('../../spec_helper', __FILE__)
9
+ require 'chef/knife/bootstrap'
10
+ require 'softlayer_api'
11
+
12
+
13
+
14
+ describe Chef::Knife::SoftlayerServerDestroy do
15
+ before do
16
+ end
17
+
18
+ describe "run" do
19
+ before(:each) do
20
+ Chef::Config[:client_key] = nil
21
+ @cci_attributes = {
22
+ :id => '1000001',
23
+ :flavor_id => 'medium',
24
+ :fqdn => 'test.example.com',
25
+ :public_ip_address => '33.33.33.33',
26
+ :private_ip_address => '10.10.10.10'
27
+ }
28
+
29
+ @knife_softlayer_destroy = Chef::Knife::SoftlayerServerDestroy.new
30
+ @knife_softlayer_destroy.stub(:destroy_item).and_return(true)
31
+ @softlayer_servers = double()
32
+ @knife_softlayer_destroy.ui.stub(:confirm)
33
+ @knife_softlayer_destroy.stub(:msg_pair)
34
+ @cci = double(@cci_attributes)
35
+ @softlayer_connection = double("connection", :createObject => {
36
+ 'accountId' => 000001,
37
+ 'createDate' => '2014-03-24T18:03:27-04:00',
38
+ 'dedicatedAccountHostOnlyFlag' => false,
39
+ 'domain' => 'example.com',
40
+ 'fullyQualifiedDomainName' => 'test',
41
+ 'hostname' =>"test",
42
+ 'id' => 0000001,
43
+ 'lastPowerStateId' => nil,
44
+ 'lastVerifiedDate' => nil,
45
+ 'maxCpu' => 4,
46
+ 'maxCpuUnits' => 'CORE',
47
+ 'maxMemory' => 4096,
48
+ 'metricPollDate' => nil,
49
+ 'modifyDate' => nil,
50
+ 'startCpus' => 4,
51
+ 'statusId' => 1001,
52
+ 'globalIdentifier' => '93f3bfb6-3f48-4e9c-82ab-25e8b5dd14ce'
53
+ })
54
+ @softlayer_connection.stub(:findByIpAddress).and_return({ 'id' => 100001 })
55
+ @softlayer_connection.stub(:object_with_id).and_return(@softlayer_connection)
56
+ @softlayer_connection.stub(:deleteObject).and_return(true)
57
+ @knife_softlayer_destroy.ui.stub(:warn)
58
+ @knife_softlayer_destroy.node = double("node", :name => 'foo')
59
+ SoftLayer::Service.should_receive(:new).twice.and_return(@softlayer_connection)
60
+ end
61
+
62
+ it "should be talking to the softlayer api and the chef server" do
63
+ Chef::Search::Query.stub(:new).and_return(double("query", :search => {}))
64
+ @knife_softlayer_destroy.config[:ip_address] = '33.33.33.33'
65
+ @softlayer_connection.should_receive(:findByIpAddress).with('33.33.33.33')
66
+ @softlayer_connection.should_receive(:deleteObject)
67
+ @knife_softlayer_destroy.run
68
+ end
69
+
70
+ end
71
+ end
metadata ADDED
@@ -0,0 +1,232 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: knife-softlayer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Matt Eldridge
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-04-08 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: softlayer_api
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '1.0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '1.0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: knife-windows
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 0.5.12
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 0.5.12
46
+ - !ruby/object:Gem::Dependency
47
+ name: net-ssh
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 2.8.0
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 2.8.0
62
+ - !ruby/object:Gem::Dependency
63
+ name: mixlib-config
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: '2.0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: '2.0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: chef
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: 0.10.10
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: 0.10.10
94
+ - !ruby/object:Gem::Dependency
95
+ name: rspec
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ~>
100
+ - !ruby/object:Gem::Version
101
+ version: '2.14'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ~>
108
+ - !ruby/object:Gem::Version
109
+ version: '2.14'
110
+ - !ruby/object:Gem::Dependency
111
+ name: rake
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ~>
116
+ - !ruby/object:Gem::Version
117
+ version: '10.1'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ~>
124
+ - !ruby/object:Gem::Version
125
+ version: '10.1'
126
+ - !ruby/object:Gem::Dependency
127
+ name: sdoc
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ~>
132
+ - !ruby/object:Gem::Version
133
+ version: '0.3'
134
+ type: :development
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ~>
140
+ - !ruby/object:Gem::Version
141
+ version: '0.3'
142
+ - !ruby/object:Gem::Dependency
143
+ name: bundler
144
+ requirement: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ~>
148
+ - !ruby/object:Gem::Version
149
+ version: '1.5'
150
+ type: :development
151
+ prerelease: false
152
+ version_requirements: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ~>
156
+ - !ruby/object:Gem::Version
157
+ version: '1.5'
158
+ - !ruby/object:Gem::Dependency
159
+ name: rake
160
+ requirement: !ruby/object:Gem::Requirement
161
+ none: false
162
+ requirements:
163
+ - - ! '>='
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ type: :development
167
+ prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ none: false
170
+ requirements:
171
+ - - ! '>='
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ description: SoftLayer CCI support for Chef's knife utility.
175
+ email:
176
+ - matt.eldridge@us.ibm.com
177
+ executables: []
178
+ extensions: []
179
+ extra_rdoc_files: []
180
+ files:
181
+ - .gitignore
182
+ - CHANGELOG.md
183
+ - CONTRIBUTING.md
184
+ - Gemfile
185
+ - LICENSE.txt
186
+ - README.md
187
+ - Rakefile
188
+ - docs/cla-corporate.md
189
+ - docs/cla-individual.md
190
+ - knife-softlayer.gemspec
191
+ - knife-softlayer.html
192
+ - lib/chef/knife/flavor/base.rb
193
+ - lib/chef/knife/softlayer.rb
194
+ - lib/chef/knife/softlayer_base.rb
195
+ - lib/chef/knife/softlayer_delete.rb
196
+ - lib/chef/knife/softlayer_flavor_list.rb
197
+ - lib/chef/knife/softlayer_list.rb
198
+ - lib/chef/knife/softlayer_server_create.rb
199
+ - lib/chef/knife/softlayer_server_destroy.rb
200
+ - lib/knife-softlayer/version.rb
201
+ - spec/spec_helper.rb
202
+ - spec/unit/softlayer_server_create_spec.rb
203
+ - spec/unit/softlayer_server_destroy_spec.rb
204
+ homepage: https://github.com/SoftLayer/knife-softlayer
205
+ licenses:
206
+ - Apache 2.0
207
+ post_install_message:
208
+ rdoc_options: []
209
+ require_paths:
210
+ - lib
211
+ required_ruby_version: !ruby/object:Gem::Requirement
212
+ none: false
213
+ requirements:
214
+ - - ! '>='
215
+ - !ruby/object:Gem::Version
216
+ version: '0'
217
+ required_rubygems_version: !ruby/object:Gem::Requirement
218
+ none: false
219
+ requirements:
220
+ - - ! '>='
221
+ - !ruby/object:Gem::Version
222
+ version: '0'
223
+ requirements: []
224
+ rubyforge_project:
225
+ rubygems_version: 1.8.23
226
+ signing_key:
227
+ specification_version: 3
228
+ summary: SoftLayer CCI support for Chef's knife utility.
229
+ test_files:
230
+ - spec/spec_helper.rb
231
+ - spec/unit/softlayer_server_create_spec.rb
232
+ - spec/unit/softlayer_server_destroy_spec.rb