knife-oraclecloud 1.0.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.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.rubocop.yml +12 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +202 -0
- data/README.md +248 -0
- data/Rakefile +6 -0
- data/knife-oraclecloud.gemspec +28 -0
- data/lib/chef/knife/cloud/oraclecloud_service.rb +206 -0
- data/lib/chef/knife/cloud/oraclecloud_service_helpers.rb +48 -0
- data/lib/chef/knife/cloud/oraclecloud_service_options.rb +58 -0
- data/lib/chef/knife/oraclecloud_image_list.rb +63 -0
- data/lib/chef/knife/oraclecloud_orchestration_delete.rb +51 -0
- data/lib/chef/knife/oraclecloud_orchestration_list.rb +65 -0
- data/lib/chef/knife/oraclecloud_orchestration_show.rb +64 -0
- data/lib/chef/knife/oraclecloud_server_create.rb +105 -0
- data/lib/chef/knife/oraclecloud_server_delete.rb +48 -0
- data/lib/chef/knife/oraclecloud_server_list.rb +67 -0
- data/lib/chef/knife/oraclecloud_server_show.rb +52 -0
- data/lib/chef/knife/oraclecloud_shape_list.rb +51 -0
- data/lib/knife-oraclecloud/version.rb +21 -0
- data/spec/spec_helper.rb +17 -0
- data/spec/unit/cloud/oraclecloud_service_helpers_spec.rb +94 -0
- data/spec/unit/cloud/oraclecloud_service_spec.rb +386 -0
- data/spec/unit/oraclecloud_image_list_spec.rb +39 -0
- data/spec/unit/oraclecloud_orchestration_delete_spec.rb +59 -0
- data/spec/unit/oraclecloud_orchestration_list_spec.rb +56 -0
- data/spec/unit/oraclecloud_orchestration_show_spec.rb +96 -0
- data/spec/unit/oraclecloud_server_create_spec.rb +118 -0
- data/spec/unit/oraclecloud_server_delete_spec.rb +40 -0
- data/spec/unit/oraclecloud_server_list_spec.rb +59 -0
- data/spec/unit/oraclecloud_server_show_spec.rb +57 -0
- data/spec/unit/oraclecloud_shape_list_spec.rb +39 -0
- metadata +161 -0
data/Rakefile
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
|
5
|
+
require 'knife-oraclecloud/version'
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = 'knife-oraclecloud'
|
9
|
+
spec.version = KnifeOracleCloud::VERSION
|
10
|
+
spec.authors = ['Chef Partner Engineering']
|
11
|
+
spec.email = ['partnereng@chef.io']
|
12
|
+
spec.summary = 'Knife plugin to interact with Oracle Cloud.'
|
13
|
+
spec.description = spec.summary
|
14
|
+
spec.homepage = 'https://github.com/chef-partners/knife-oraclecloud'
|
15
|
+
spec.license = 'Apache 2.0'
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0")
|
18
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
|
+
spec.require_paths = ['lib']
|
21
|
+
|
22
|
+
spec.add_dependency 'chef', '~> 12.0'
|
23
|
+
spec.add_dependency 'knife-cloud', '~> 1.2.0'
|
24
|
+
spec.add_dependency 'oraclecloud', '~> 1.0'
|
25
|
+
|
26
|
+
spec.add_development_dependency 'bundler', '~> 1.7'
|
27
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
28
|
+
end
|
@@ -0,0 +1,206 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Chef Partner Engineering (<partnereng@chef.io>)
|
3
|
+
# Copyright:: Copyright (c) 2015 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
|
+
|
19
|
+
require 'chef/knife/cloud/exceptions'
|
20
|
+
require 'chef/knife/cloud/service'
|
21
|
+
require 'chef/knife/cloud/helpers'
|
22
|
+
require 'chef/knife/cloud/oraclecloud_service_helpers'
|
23
|
+
require 'oraclecloud'
|
24
|
+
|
25
|
+
class Chef
|
26
|
+
class Knife
|
27
|
+
class Cloud
|
28
|
+
class OraclecloudService < Service # rubocop:disable Metrics/ClassLength
|
29
|
+
include OraclecloudServiceHelpers
|
30
|
+
|
31
|
+
attr_reader :wait_time, :refresh_time
|
32
|
+
|
33
|
+
def initialize(options = {})
|
34
|
+
super(options)
|
35
|
+
|
36
|
+
@username = options[:username]
|
37
|
+
@password = options[:password]
|
38
|
+
@api_url = options[:api_url]
|
39
|
+
@identity_domain = options[:identity_domain]
|
40
|
+
@verify_ssl = options[:verify_ssl]
|
41
|
+
@wait_time = options[:wait_time]
|
42
|
+
@refresh_time = options[:refresh_time]
|
43
|
+
end
|
44
|
+
|
45
|
+
def connection
|
46
|
+
@client ||= OracleCloud::Client.new(
|
47
|
+
api_url: @api_url,
|
48
|
+
identity_domain: @identity_domain,
|
49
|
+
username: @username,
|
50
|
+
password: @password,
|
51
|
+
verify_ssl: @verify_ssl
|
52
|
+
)
|
53
|
+
end
|
54
|
+
|
55
|
+
def prepend_identity_domain(path)
|
56
|
+
"#{connection.compute_identity_domain}/#{path}"
|
57
|
+
end
|
58
|
+
|
59
|
+
def create_server(options = {})
|
60
|
+
orchestration = create_orchestration(options)
|
61
|
+
orchestration.start
|
62
|
+
ui.msg("Orchestration #{orchestration.name_with_container} started - waiting for it to complete...")
|
63
|
+
wait_for_status(orchestration, 'ready')
|
64
|
+
ui.msg("Orchestration started successfully.\n")
|
65
|
+
orchestration_summary(orchestration)
|
66
|
+
ui.msg('')
|
67
|
+
|
68
|
+
servers = orchestration.instances
|
69
|
+
raise CloudExceptions::ServerCreateError, 'The orchestration created more than one server, ' \
|
70
|
+
'but we were only expecting 1' if servers.length > 1
|
71
|
+
raise CloudExceptions::ServerCreateError, 'The orchestration did not create any servers' if servers.length == 0
|
72
|
+
|
73
|
+
servers.first
|
74
|
+
end
|
75
|
+
|
76
|
+
def delete_server(instance_id)
|
77
|
+
instance = get_server(instance_id)
|
78
|
+
server_summary(instance)
|
79
|
+
ui.msg('')
|
80
|
+
|
81
|
+
unless instance.orchestration.nil?
|
82
|
+
ui.error('Unable to delete this server. Delete the orchestration instead.')
|
83
|
+
exit(1)
|
84
|
+
end
|
85
|
+
|
86
|
+
ui.confirm('Do you really want to delete this server')
|
87
|
+
|
88
|
+
ui.msg('Deleting the instance...')
|
89
|
+
instance.delete
|
90
|
+
|
91
|
+
ui.msg('Delete request complete.')
|
92
|
+
end
|
93
|
+
|
94
|
+
def create_orchestration(options)
|
95
|
+
connection.orchestrations.create(
|
96
|
+
name: options[:name],
|
97
|
+
description: "#{options[:name]} by #{connection.username} via Knife",
|
98
|
+
instances: [ instance_request(options) ]
|
99
|
+
)
|
100
|
+
end
|
101
|
+
|
102
|
+
def delete_orchestration(orchestration_id)
|
103
|
+
orchestration = get_orchestration(orchestration_id)
|
104
|
+
orchestration_summary(orchestration)
|
105
|
+
ui.msg('')
|
106
|
+
|
107
|
+
ui.confirm('Do you really want to delete this orchestration')
|
108
|
+
|
109
|
+
ui.msg('Stopping the orchestration and any instances...')
|
110
|
+
orchestration.stop
|
111
|
+
wait_for_status(orchestration, 'stopped')
|
112
|
+
|
113
|
+
ui.msg('Deleting the orchestration and any instances...')
|
114
|
+
orchestration.delete
|
115
|
+
|
116
|
+
ui.msg('Delete request complete.')
|
117
|
+
end
|
118
|
+
|
119
|
+
def instance_request(options)
|
120
|
+
connection.instance_request(
|
121
|
+
name: options[:name],
|
122
|
+
shape: options[:shape],
|
123
|
+
imagelist: options[:image],
|
124
|
+
sshkeys: options[:sshkeys],
|
125
|
+
label: options[:label],
|
126
|
+
public_ip: options[:public_ip]
|
127
|
+
)
|
128
|
+
end
|
129
|
+
|
130
|
+
def list_servers
|
131
|
+
connection.instances.all
|
132
|
+
end
|
133
|
+
|
134
|
+
def list_orchestrations
|
135
|
+
connection.orchestrations.all
|
136
|
+
end
|
137
|
+
|
138
|
+
def list_images
|
139
|
+
connection.imagelists.all
|
140
|
+
end
|
141
|
+
|
142
|
+
def list_shapes
|
143
|
+
connection.shapes.all
|
144
|
+
end
|
145
|
+
|
146
|
+
def get_server(instance_id)
|
147
|
+
connection.instances.by_name(instance_id)
|
148
|
+
end
|
149
|
+
|
150
|
+
def get_orchestration(orchestration_id)
|
151
|
+
connection.orchestrations.by_name(orchestration_id)
|
152
|
+
end
|
153
|
+
|
154
|
+
def orchestration_summary(orchestration)
|
155
|
+
msg_pair('Orchestration ID', orchestration.name_with_container)
|
156
|
+
msg_pair('Description', orchestration.description)
|
157
|
+
msg_pair('Status', orchestration.status)
|
158
|
+
msg_pair('Instance Count', orchestration.instance_count)
|
159
|
+
end
|
160
|
+
|
161
|
+
def server_summary(server, _columns_with_info = nil)
|
162
|
+
msg_pair('Server Label', server.label)
|
163
|
+
msg_pair('Status', server.status)
|
164
|
+
msg_pair('Hostname', server.hostname)
|
165
|
+
msg_pair('IP Address', server.ip_address.nil? ? 'none' : server.ip_address)
|
166
|
+
msg_pair('Public IP Addresses', server.public_ip_addresses.empty? ? 'none' : server.public_ip_addresses.join(', '))
|
167
|
+
msg_pair('Image', server.image)
|
168
|
+
msg_pair('Shape', server.shape)
|
169
|
+
msg_pair('Orchestration', server.orchestration.nil? ? 'none' : server.orchestration)
|
170
|
+
end
|
171
|
+
|
172
|
+
def wait_for_status(item, requested_status)
|
173
|
+
last_status = ''
|
174
|
+
|
175
|
+
begin
|
176
|
+
Timeout.timeout(wait_time) do
|
177
|
+
loop do
|
178
|
+
item.refresh
|
179
|
+
current_status = item.status
|
180
|
+
|
181
|
+
if current_status == requested_status
|
182
|
+
print "\n"
|
183
|
+
break
|
184
|
+
end
|
185
|
+
|
186
|
+
if last_status == current_status
|
187
|
+
print '.'
|
188
|
+
else
|
189
|
+
last_status = current_status
|
190
|
+
print "\n"
|
191
|
+
print "Current status: #{current_status}."
|
192
|
+
end
|
193
|
+
|
194
|
+
sleep refresh_time
|
195
|
+
end
|
196
|
+
end
|
197
|
+
rescue Timeout::Error
|
198
|
+
ui.msg('')
|
199
|
+
ui.error("Request did not complete in #{wait_time} seconds. Check the Oracle Cloud Web UI for more information.")
|
200
|
+
exit 1
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Chef Partner Engineering (<partnereng@chef.io>)
|
3
|
+
# Copyright:: Copyright (c) 2015 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
|
+
|
19
|
+
class Chef
|
20
|
+
class Knife
|
21
|
+
class Cloud
|
22
|
+
module OraclecloudServiceHelpers
|
23
|
+
def create_service_instance
|
24
|
+
Chef::Knife::Cloud::OraclecloudService.new(username: locate_config_value(:oraclecloud_username),
|
25
|
+
password: locate_config_value(:oraclecloud_password),
|
26
|
+
api_url: locate_config_value(:oraclecloud_api_url),
|
27
|
+
identity_domain: locate_config_value(:oraclecloud_domain),
|
28
|
+
wait_time: locate_config_value(:wait_time),
|
29
|
+
refresh_time: locate_config_value(:request_refresh_rate),
|
30
|
+
verify_ssl: verify_ssl?)
|
31
|
+
end
|
32
|
+
|
33
|
+
def verify_ssl?
|
34
|
+
!locate_config_value(:oraclecloud_disable_ssl_verify)
|
35
|
+
end
|
36
|
+
|
37
|
+
def check_for_missing_config_values!(*keys)
|
38
|
+
missing = keys.select { |x| locate_config_value(x).nil? }
|
39
|
+
|
40
|
+
unless missing.empty? # rubocop:disable Style/GuardClause
|
41
|
+
ui.error("The following required parameters are missing: #{missing.join(', ')}")
|
42
|
+
exit(1)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Chef Partner Engineering (<partnereng@chef.io>)
|
3
|
+
# Copyright:: Copyright (c) 2015 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
|
+
|
19
|
+
class Chef
|
20
|
+
class Knife
|
21
|
+
class Cloud
|
22
|
+
# rubocop:disable Style/AlignParameters
|
23
|
+
module OraclecloudServiceOptions
|
24
|
+
def self.included(includer)
|
25
|
+
includer.class_eval do
|
26
|
+
option :oraclecloud_api_url,
|
27
|
+
long: '--oraclecloud-api-url API_URL',
|
28
|
+
description: 'URL for the oraclecloud API server'
|
29
|
+
|
30
|
+
option :oraclecloud_username,
|
31
|
+
long: '--oraclecloud-username USERNAME',
|
32
|
+
description: 'Username to use with the oraclecloud API'
|
33
|
+
|
34
|
+
option :oraclecloud_password,
|
35
|
+
long: '--oraclecloud-password PASSWORD',
|
36
|
+
description: 'Password to use with the oraclecloud API'
|
37
|
+
|
38
|
+
option :oraclecloud_domain,
|
39
|
+
long: '--oraclecloud-domain IDENTITYDOMAIN',
|
40
|
+
description: 'Identity domain to use with the oraclecloud API'
|
41
|
+
|
42
|
+
option :oraclecloud_disable_ssl_verify,
|
43
|
+
long: '--oraclecloud-disable-ssl-verify',
|
44
|
+
description: 'Skip any SSL verification for the oraclecloud API',
|
45
|
+
boolean: true,
|
46
|
+
default: false
|
47
|
+
|
48
|
+
option :request_refresh_rate,
|
49
|
+
long: '--request-refresh-rate SECS',
|
50
|
+
description: 'Number of seconds to sleep between each check of the request status, defaults to 2',
|
51
|
+
default: 2,
|
52
|
+
proc: proc { |secs| secs.to_i }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Chef Partner Engineering (<partnereng@chef.io>)
|
3
|
+
# Copyright:: Copyright (c) 2015 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
|
+
|
19
|
+
require 'chef/knife'
|
20
|
+
require 'chef/knife/cloud/list_resource_command'
|
21
|
+
require 'chef/knife/cloud/oraclecloud_service'
|
22
|
+
require 'chef/knife/cloud/oraclecloud_service_helpers'
|
23
|
+
require 'chef/knife/cloud/oraclecloud_service_options'
|
24
|
+
|
25
|
+
class Chef
|
26
|
+
class Knife
|
27
|
+
class Cloud
|
28
|
+
class OraclecloudImageList < ResourceListCommand
|
29
|
+
include OraclecloudServiceHelpers
|
30
|
+
include OraclecloudServiceOptions
|
31
|
+
|
32
|
+
banner 'knife oraclecloud image list'
|
33
|
+
|
34
|
+
def before_exec_command
|
35
|
+
@columns_with_info = [
|
36
|
+
{ label: 'Image Name', key: 'name' },
|
37
|
+
{ label: 'Description', key: 'description' }
|
38
|
+
]
|
39
|
+
|
40
|
+
@sort_by_field = 'name'
|
41
|
+
end
|
42
|
+
|
43
|
+
def query_resource
|
44
|
+
service.list_images
|
45
|
+
end
|
46
|
+
|
47
|
+
def format_status_value(status)
|
48
|
+
status = status.downcase
|
49
|
+
status_color = case status
|
50
|
+
when 'ready'
|
51
|
+
:green
|
52
|
+
when 'stopped'
|
53
|
+
:red
|
54
|
+
else
|
55
|
+
:yellow
|
56
|
+
end
|
57
|
+
|
58
|
+
ui.color(status, status_color)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Chef Partner Engineering (<partnereng@chef.io>)
|
3
|
+
# Copyright:: Copyright (c) 2015 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
|
+
|
19
|
+
require 'chef/knife'
|
20
|
+
require 'chef/knife/cloud/command'
|
21
|
+
require 'chef/knife/cloud/oraclecloud_service'
|
22
|
+
require 'chef/knife/cloud/oraclecloud_service_helpers'
|
23
|
+
require 'chef/knife/cloud/oraclecloud_service_options'
|
24
|
+
|
25
|
+
class Chef
|
26
|
+
class Knife
|
27
|
+
class Cloud
|
28
|
+
class OraclecloudOrchestrationDelete < Command
|
29
|
+
include OraclecloudServiceHelpers
|
30
|
+
include OraclecloudServiceOptions
|
31
|
+
|
32
|
+
banner 'knife oraclecloud orchestration delete ORCHESTRATION_ID [ORCHESTRATION_ID] (options)'
|
33
|
+
|
34
|
+
def validate_params!
|
35
|
+
if @name_args.empty?
|
36
|
+
ui.error('You must supply at least one Orchestration ID to delete.')
|
37
|
+
exit 1
|
38
|
+
end
|
39
|
+
|
40
|
+
super
|
41
|
+
end
|
42
|
+
|
43
|
+
def execute_command
|
44
|
+
@name_args.each do |orchestration_id|
|
45
|
+
service.delete_orchestration(orchestration_id)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|