knife-octo 0.0.1
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/Gemfile +3 -0
- data/README.md +2 -0
- data/knife-octo.gemspec +19 -0
- data/lib/chef/knife/octo.rb +1139 -0
- data/lib/knife-octo/version.rb +6 -0
- metadata +62 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: cd7bc1743508087e6be632056bceebb3b1d69a6f2a1d899283a9ec094ecd0db8
|
4
|
+
data.tar.gz: 81265673f87d32b4dd03725fbb62dd696a79922ee7094bc9b0b44e48d205357c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4696cecd5c395c10bbf7a0e58ead23413184096991644d5f54015ec0e65d16bb38fcc1036ba3b3d01cbd10f6fab52919786a491b825239d5d770aab3a6de66f4
|
7
|
+
data.tar.gz: 771c36c3e295aea4325dfba8bbb252ab9a7e2e101e70f5e5a7652a16ffff49ca645155793d34ecdf961a462bff8351994ef3264c720d96cb28076e36aad0c221
|
data/Gemfile
ADDED
data/README.md
ADDED
data/knife-octo.gemspec
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
$LOAD_PATH.push File.expand_path("lib", __dir__)
|
2
|
+
require "knife-octo/version"
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "knife-octo"
|
6
|
+
s.version = Knife::Octo::VERSION
|
7
|
+
s.platform = Gem::Platform::RUBY
|
8
|
+
s.authors = "Vishal Basra"
|
9
|
+
s.email = "vishalbasra@live.com"
|
10
|
+
s.homepage = "https://github.com/vishalbasra/knife-octo"
|
11
|
+
s.summary = "Chef Knife plugin to help see stuff in Octopus Deploy"
|
12
|
+
s.description = "A knife plugin to things much faster in Octopus Deploy server."
|
13
|
+
s.date = '2018-10-16'
|
14
|
+
s.license = "Apache-2.0"
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.require_paths = ["lib"]
|
17
|
+
s.add_development_dependency "colorize", "~> 0.7.7"
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,1139 @@
|
|
1
|
+
# chef gem install colorize
|
2
|
+
module Octo
|
3
|
+
class OctoHelperMethods < Chef::Knife
|
4
|
+
require 'json'
|
5
|
+
require 'uri'
|
6
|
+
require 'net/http'
|
7
|
+
require 'openssl'
|
8
|
+
require 'colorize'
|
9
|
+
|
10
|
+
|
11
|
+
def initialize(apikey, instance)
|
12
|
+
@apikey = apikey
|
13
|
+
@instance = instance
|
14
|
+
end
|
15
|
+
|
16
|
+
## generic helper methods
|
17
|
+
|
18
|
+
def generic_call(method, resource, params)
|
19
|
+
instance = @instance
|
20
|
+
apikey = @apikey
|
21
|
+
output = {
|
22
|
+
'response' => 'error',
|
23
|
+
'message' => false
|
24
|
+
}
|
25
|
+
# Format URI object
|
26
|
+
uri = "https://#{instance}/api/#{resource}"
|
27
|
+
if params
|
28
|
+
# logic to do params here for a PUSH / POST, currently not supported
|
29
|
+
end
|
30
|
+
uri = URI.parse(uri)
|
31
|
+
|
32
|
+
# Format HTTPS request object
|
33
|
+
header = { 'X-Octopus-ApiKey' => apikey }
|
34
|
+
# Create HTTP object
|
35
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
36
|
+
http.use_ssl = true
|
37
|
+
if method == 'GET'
|
38
|
+
# put try catch here
|
39
|
+
req = Net::HTTP::Get.new(uri.request_uri, header)
|
40
|
+
else
|
41
|
+
# put try catch here
|
42
|
+
req = Net::HTTP::Post.new(uri.request_uri, header)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Execute HTTP request
|
46
|
+
begin
|
47
|
+
result = http.request(req)
|
48
|
+
rescue => exception
|
49
|
+
print "#{'ERROR'.red} : Could not send request to #{'https://'.red}#{instance.red} - #{exception}\n"
|
50
|
+
exit
|
51
|
+
else
|
52
|
+
"" # had an older colorize block here
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
## Validate result
|
57
|
+
case result
|
58
|
+
when Net::HTTPOK
|
59
|
+
output['response'] = 'ok'
|
60
|
+
result_hash = {}
|
61
|
+
begin
|
62
|
+
result_hash = JSON.parse("#{result.body.force_encoding('UTF-8')}")
|
63
|
+
rescue
|
64
|
+
result_hash = {
|
65
|
+
'HTTP success type' => "#{result.class.name}"
|
66
|
+
}
|
67
|
+
if result.body
|
68
|
+
result_hash['body'] = "#{result.body}"
|
69
|
+
end
|
70
|
+
if result.message
|
71
|
+
result_hash['message'] = "#{result.message}"
|
72
|
+
end
|
73
|
+
if result['location']
|
74
|
+
result_hash['location'] = "#{result['location']}"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
output['message'] = result_hash
|
78
|
+
else
|
79
|
+
output['response'] = 'notok'
|
80
|
+
output['message'] = "#{'ERROR - '.red} HTTP Response: #{result.class.name}"
|
81
|
+
if result.message
|
82
|
+
output['message'] += " - Message: #{result.message}"
|
83
|
+
end
|
84
|
+
if result.body
|
85
|
+
output['message'] += "\nCaused by: #{JSON.parse(result.body)['ErrorMessage'].red}\n"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
return output
|
89
|
+
end
|
90
|
+
|
91
|
+
def envname_from_id(env_id)
|
92
|
+
output = {
|
93
|
+
'response' => 'error',
|
94
|
+
'message' => false
|
95
|
+
}
|
96
|
+
request = generic_call('GET', "environments/#{env_id}", false)
|
97
|
+
if request['response'] == 'ok'
|
98
|
+
output['response'] = 'ok'
|
99
|
+
output['message'] = request['message']['Name']
|
100
|
+
else
|
101
|
+
output['response'] = request['response']
|
102
|
+
output ['message'] = request['message']
|
103
|
+
end
|
104
|
+
return output
|
105
|
+
end
|
106
|
+
|
107
|
+
def eid_from_name(env_name)
|
108
|
+
output = {
|
109
|
+
'response' => 'error',
|
110
|
+
'message' => false
|
111
|
+
}
|
112
|
+
request = generic_call('GET', 'environments/all', false)
|
113
|
+
if request['response'] == 'ok'
|
114
|
+
parsed_list = parse_env_list(request['message'],true)
|
115
|
+
JSON.parse(parsed_list).each do |some_env|
|
116
|
+
if some_env['name'] == env_name
|
117
|
+
output['response'] = 'ok'
|
118
|
+
output ['message'] = some_env['properties']['id']
|
119
|
+
end
|
120
|
+
end
|
121
|
+
if output['message'].class.to_s == 'FalseClass'
|
122
|
+
output['response'] = 'notok'
|
123
|
+
output ['message'] = 'Environment name not found'
|
124
|
+
end
|
125
|
+
else
|
126
|
+
output['response'] = request['response']
|
127
|
+
output ['message'] = request['message']
|
128
|
+
end
|
129
|
+
return output
|
130
|
+
end
|
131
|
+
|
132
|
+
def mid_from_mname(m_name)
|
133
|
+
output = {
|
134
|
+
'response' => 'error',
|
135
|
+
'message' => false
|
136
|
+
}
|
137
|
+
request = generic_call('GET', 'machines/all', false)
|
138
|
+
if request['response'] == 'ok'
|
139
|
+
parsed_list = parse_machine_list(request['message'],true)
|
140
|
+
JSON.parse(parsed_list).each do |some_machine|
|
141
|
+
if some_machine['name'] == m_name
|
142
|
+
output['response'] = 'ok'
|
143
|
+
output ['message'] = some_machine['properties']['id']
|
144
|
+
end
|
145
|
+
end
|
146
|
+
if output['message'].class.to_s == 'FalseClass'
|
147
|
+
output['response'] = 'notok'
|
148
|
+
output ['message'] = 'Machine name not found'
|
149
|
+
end
|
150
|
+
else
|
151
|
+
output['response'] = request['response']
|
152
|
+
output ['message'] = request['message']
|
153
|
+
end
|
154
|
+
return output
|
155
|
+
end
|
156
|
+
|
157
|
+
def create_local_file_by_id(thing)
|
158
|
+
tmp_location = "/tmp/ajnfieneom"
|
159
|
+
request = generic_call('GET', "#{thing}/all", false)
|
160
|
+
things = []
|
161
|
+
request['message'].each do |single|
|
162
|
+
things << {
|
163
|
+
"#{single['Id']}" => "#{single['Name']}"
|
164
|
+
}
|
165
|
+
end
|
166
|
+
if request['response'] == 'ok'
|
167
|
+
file = File.open("#{tmp_location}",'w+')
|
168
|
+
file.write(JSON.pretty_generate(things))
|
169
|
+
end
|
170
|
+
file.read
|
171
|
+
end
|
172
|
+
|
173
|
+
def create_local_file_by_name(thing)
|
174
|
+
tmp_location = "/tmp/ajnfieneoma"
|
175
|
+
request = generic_call('GET', "#{thing}/all", false)
|
176
|
+
things = []
|
177
|
+
request['message'].each do |single|
|
178
|
+
things << {
|
179
|
+
"#{single['Name']}" => "#{single['Id']}"
|
180
|
+
}
|
181
|
+
end
|
182
|
+
if request['response'] == 'ok'
|
183
|
+
file = File.open("#{tmp_location}",'w+')
|
184
|
+
file.write(JSON.pretty_generate(things))
|
185
|
+
file.close
|
186
|
+
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def local_file_by_id(e_id,e_name) # couple with create_local_file_by_id ; e_name will be used in a future release
|
191
|
+
tmp_location = "/tmp/ajnfieneom"
|
192
|
+
file = File.read("#{tmp_location}")
|
193
|
+
json_envs = JSON.parse(file)
|
194
|
+
json_envs.each do |json_env|
|
195
|
+
unless json_env["#{e_id}"].nil?
|
196
|
+
return json_env["#{e_id}"]
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
def local_file_by_key(key,value) # couple with create_local_file_by_name ; e_name will be used in a future release
|
202
|
+
tmp_location = "/tmp/ajnfieneoma"
|
203
|
+
file = File.read("#{tmp_location}")
|
204
|
+
json_things = JSON.parse(file)
|
205
|
+
json_things.each do |json_thing|
|
206
|
+
unless json_thing["#{key}"].nil?
|
207
|
+
return json_thing["#{key}"]
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
def delete_local_file
|
213
|
+
tmp_location = "/tmp/ajnfieneom"
|
214
|
+
tmp_location_another = "/tmp/ajnfieneoma"
|
215
|
+
if File.file?(tmp_location)
|
216
|
+
File.delete(tmp_location)
|
217
|
+
end
|
218
|
+
if File.file?(tmp_location_another)
|
219
|
+
File.delete(tmp_location_another)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
|
224
|
+
## specific helper methods
|
225
|
+
|
226
|
+
def parse_variable_list (var_list_object,islong)
|
227
|
+
instance = @instance
|
228
|
+
variable_sets = []
|
229
|
+
var_list_object.each do |item|
|
230
|
+
if item['ContentType'] == 'Variables'
|
231
|
+
if islong.class.to_s == 'TrueClass'
|
232
|
+
variable_sets << {
|
233
|
+
name: item['Name'],
|
234
|
+
properties: {
|
235
|
+
description: item['Description'],
|
236
|
+
id: item['Id'],
|
237
|
+
link: "http://#{instance}/app#/library/variables/#{item['Id']}"
|
238
|
+
}
|
239
|
+
}
|
240
|
+
else
|
241
|
+
variable_sets << item['Name']
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
return JSON.pretty_generate(variable_sets)
|
246
|
+
end
|
247
|
+
|
248
|
+
def parse_variable_sets_helper (var_obj,islong)
|
249
|
+
variable_sets = []
|
250
|
+
var_obj['Variables'].each do |item|
|
251
|
+
if islong.class.to_s == 'TrueClass' # long
|
252
|
+
variable_sets << {
|
253
|
+
'name' => item['Name'],
|
254
|
+
'value' => item['Value'],
|
255
|
+
'isencrypted' => item['IsSensitive'],
|
256
|
+
'type' => item['Type'],
|
257
|
+
'iseditable' => item['IsEditable'],
|
258
|
+
'scope' => item['Scope']['Environment'] # alter this here if we ever use Roles
|
259
|
+
}
|
260
|
+
else # short
|
261
|
+
variable_sets.push(item['Name'])
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
##
|
266
|
+
#DO env things here
|
267
|
+
if islong.class.to_s == 'TrueClass' # long substitue
|
268
|
+
# NEW CREATE ENV FILE
|
269
|
+
create_local_file_by_id('environments')
|
270
|
+
variable_sets.each do |single_var|
|
271
|
+
new_envs = []
|
272
|
+
unless single_var['scope'].nil?
|
273
|
+
single_var['scope'].each do |env_id|
|
274
|
+
new_envs.push(local_file_by_id(env_id,false))
|
275
|
+
end
|
276
|
+
end
|
277
|
+
# SECRET
|
278
|
+
single_var['scope'] = new_envs
|
279
|
+
if single_var['isencrypted'].class.to_s == 'TrueClass'
|
280
|
+
single_var['value'] = '************'
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
return JSON.pretty_generate(variable_sets)
|
286
|
+
end
|
287
|
+
|
288
|
+
def parse_variable_sets (var_name,islong)
|
289
|
+
output = {
|
290
|
+
'response' => 'error',
|
291
|
+
'message' => false
|
292
|
+
}
|
293
|
+
create_local_file_by_name('libraryvariablesets')
|
294
|
+
unless local_file_by_key(var_name,false).nil?
|
295
|
+
var_id = local_file_by_key(var_name,false)
|
296
|
+
case var_id
|
297
|
+
when String
|
298
|
+
""
|
299
|
+
else
|
300
|
+
output['response'] = 'notok'
|
301
|
+
output['message'] = "Incorrect Variable Set provided"
|
302
|
+
return output
|
303
|
+
end
|
304
|
+
|
305
|
+
request = generic_call('GET', "/variables/variableset-#{var_id}", false)
|
306
|
+
if request['response'] == 'ok'
|
307
|
+
output['response'] = 'ok'
|
308
|
+
output['message'] = parse_variable_sets_helper(request['message'],islong)
|
309
|
+
else
|
310
|
+
output['response'] = 'notok'
|
311
|
+
output['message'] = request['message']
|
312
|
+
end
|
313
|
+
end
|
314
|
+
#end
|
315
|
+
if output['response'].class.to_s == 'FalseClass'
|
316
|
+
output['response'] = 'notok'
|
317
|
+
output['message'] = "Incorrect Variable Set provided"
|
318
|
+
end
|
319
|
+
delete_local_file
|
320
|
+
return output
|
321
|
+
|
322
|
+
|
323
|
+
|
324
|
+
end
|
325
|
+
|
326
|
+
def parse_env_list (env_list_object,islong)
|
327
|
+
variable_sets = []
|
328
|
+
env_list_object.each do |item|
|
329
|
+
if islong.class.to_s == 'TrueClass'
|
330
|
+
variable_sets << {
|
331
|
+
'name' => item['Name'],
|
332
|
+
'properties' => {
|
333
|
+
'description'=> item['Description'],
|
334
|
+
'id'=> item['Id']
|
335
|
+
}
|
336
|
+
}
|
337
|
+
else
|
338
|
+
variable_sets << item['Name']
|
339
|
+
end
|
340
|
+
end
|
341
|
+
return JSON.pretty_generate(variable_sets)
|
342
|
+
end
|
343
|
+
|
344
|
+
def parse_env_deets(env_object,islong)
|
345
|
+
output = {
|
346
|
+
'response' => 'error',
|
347
|
+
'message' => false
|
348
|
+
}
|
349
|
+
variable_sets = []
|
350
|
+
env_object['Items'].each do |item|
|
351
|
+
if islong.class.to_s == 'TrueClass'
|
352
|
+
variable_sets << {
|
353
|
+
'name' => item['Name'],
|
354
|
+
'properties' => {
|
355
|
+
'description' => item['Description'],
|
356
|
+
'id' => item['Id'],
|
357
|
+
'uri' => item['Endpoint']['Uri'],
|
358
|
+
'thumbprint' => item['Thumbprint'],
|
359
|
+
'isdisabled' => item['IsDisabled'],
|
360
|
+
'health' => item['HealthStatus'],
|
361
|
+
'status' => item['Status'],
|
362
|
+
'summary' => item['StatusSummary'],
|
363
|
+
'isinprocess' => item['IsInProcess'],
|
364
|
+
'roles' => item['Roles'],
|
365
|
+
'environments' => item['EnvironmentIds']
|
366
|
+
}
|
367
|
+
}
|
368
|
+
else
|
369
|
+
variable_sets << item['Name']
|
370
|
+
end
|
371
|
+
end
|
372
|
+
if islong.class.to_s == 'TrueClass'
|
373
|
+
# TRANSPOSE ENVS
|
374
|
+
variable_sets.each do |single_var|
|
375
|
+
new_envs = []
|
376
|
+
unless single_var['properties']['environments'].nil?
|
377
|
+
single_var['properties']['environments'].each do |env_id|
|
378
|
+
new_envs.push(local_file_by_id(env_id,false))
|
379
|
+
end
|
380
|
+
end
|
381
|
+
single_var['properties']['environments'] = new_envs
|
382
|
+
end
|
383
|
+
# END OF ENV TRANSPOSING
|
384
|
+
end
|
385
|
+
JSON.pretty_generate(variable_sets)
|
386
|
+
end
|
387
|
+
|
388
|
+
def parse_machine_list (m_list_object,islong)
|
389
|
+
variable_sets = []
|
390
|
+
m_list_object.each do |item|
|
391
|
+
if islong.class.to_s == 'TrueClass'
|
392
|
+
variable_sets << {
|
393
|
+
'name' => item['Name'],
|
394
|
+
'properties' => {
|
395
|
+
'health'=> item['HealthStatus'],
|
396
|
+
'id'=> item['Id']
|
397
|
+
}
|
398
|
+
}
|
399
|
+
else
|
400
|
+
variable_sets << item['Name']
|
401
|
+
end
|
402
|
+
end
|
403
|
+
return JSON.pretty_generate(variable_sets)
|
404
|
+
end
|
405
|
+
|
406
|
+
def parse_machine_deets (m_object,islong)
|
407
|
+
output = {
|
408
|
+
'response' => 'error',
|
409
|
+
'message' => false
|
410
|
+
}
|
411
|
+
variable_sets = []
|
412
|
+
if islong.class.to_s == 'TrueClass'
|
413
|
+
variable_sets << {
|
414
|
+
'name' => m_object['Name'],
|
415
|
+
'properties' => {
|
416
|
+
'id' => m_object['Id'],
|
417
|
+
'uri' => m_object['Endpoint']['Uri'],
|
418
|
+
'thumbprint' => m_object['Thumbprint'],
|
419
|
+
'isdisabled' => m_object['IsDisabled'],
|
420
|
+
'health' => m_object['HealthStatus'],
|
421
|
+
'status' => m_object['Status'],
|
422
|
+
'summary' => m_object['StatusSummary'],
|
423
|
+
'isinprocess' => m_object['IsInProcess'],
|
424
|
+
'roles' => m_object['Roles'],
|
425
|
+
'environments' => m_object['EnvironmentIds']
|
426
|
+
}
|
427
|
+
}
|
428
|
+
else
|
429
|
+
variable_sets << {
|
430
|
+
'name' => m_object['Name'],
|
431
|
+
'uri' => m_object['Endpoint']['Uri'],
|
432
|
+
}
|
433
|
+
end
|
434
|
+
if islong.class.to_s == 'TrueClass'
|
435
|
+
variable_sets.each do |single_hash|
|
436
|
+
new_environments = []
|
437
|
+
single_hash['properties']['environments'].each do |env_id|
|
438
|
+
request = envname_from_id(env_id)
|
439
|
+
if request['response'] == 'ok'
|
440
|
+
new_environments.push(request['message'])
|
441
|
+
end
|
442
|
+
end
|
443
|
+
single_hash['properties']['environments'] = new_environments
|
444
|
+
end
|
445
|
+
end
|
446
|
+
JSON.pretty_generate(variable_sets)
|
447
|
+
end
|
448
|
+
|
449
|
+
def parse_project_list (p_list_object,islong,manyitems)
|
450
|
+
output = {
|
451
|
+
'response' => 'error',
|
452
|
+
'message' => false
|
453
|
+
}
|
454
|
+
instance = @instance
|
455
|
+
variable_sets = []
|
456
|
+
if manyitems.class.to_s == 'TrueClass' # it's a list
|
457
|
+
p_list_object.each do |item|
|
458
|
+
if islong.class.to_s == 'TrueClass'
|
459
|
+
variable_sets << {
|
460
|
+
'name' => item['Name'],
|
461
|
+
'properties' => {
|
462
|
+
'id'=> item['Id'],
|
463
|
+
'deploymentid'=> item['DeploymentProcessId'],
|
464
|
+
'variableid'=> item['VariableSetId'],
|
465
|
+
'variablesets'=> item['IncludedLibraryVariableSetIds'],
|
466
|
+
'url' => "http://#{instance}#{item['Links']['Web']}"
|
467
|
+
}
|
468
|
+
}
|
469
|
+
else
|
470
|
+
variable_sets << {
|
471
|
+
'name' => item['Name'],
|
472
|
+
'url' => "http://#{instance}#{item['Links']['Web']}"
|
473
|
+
}
|
474
|
+
end
|
475
|
+
end
|
476
|
+
else # it is not a list and is a single item
|
477
|
+
if islong.class.to_s == 'TrueClass'
|
478
|
+
## steps
|
479
|
+
steps = generic_call('GET', "deploymentprocesses/#{p_list_object['DeploymentProcessId']}", false)
|
480
|
+
if steps['response'] == 'ok'
|
481
|
+
process = []
|
482
|
+
steps['message']['Steps'].each do |step|
|
483
|
+
new_envs = []
|
484
|
+
step['Actions'][0]['Environments'].each do |envy_id|
|
485
|
+
new_envs.push(local_file_by_id(envy_id,false))
|
486
|
+
end
|
487
|
+
|
488
|
+
excl_envs = []
|
489
|
+
step['Actions'][0]['ExcludedEnvironments'].each do |excl_env_id|
|
490
|
+
excl_envs.push(local_file_by_id(excl_env_id,false))
|
491
|
+
end
|
492
|
+
|
493
|
+
process << { # not using Id here but it can be used
|
494
|
+
"name" => step['Name'],
|
495
|
+
"packages_required" => step['RequiresPackagesToBeAcquired'],
|
496
|
+
"roles" => step['Properties']['Octopus.Action.TargetRoles'],
|
497
|
+
"condition" => step['Condition'],
|
498
|
+
"start_trigger" => step['StartTrigger'],
|
499
|
+
"environments" => new_envs,
|
500
|
+
"excluded_environments" => excl_envs,
|
501
|
+
"isdisabled" => step['Actions'][0]['IsDisabled'],
|
502
|
+
"details" => step['Actions'][0]['Properties'],
|
503
|
+
}
|
504
|
+
end
|
505
|
+
end
|
506
|
+
## steps end
|
507
|
+
|
508
|
+
variable_sets << {
|
509
|
+
'name' => p_list_object['Name'],
|
510
|
+
'properties' => {
|
511
|
+
'id'=> p_list_object['Id'],
|
512
|
+
'deploymentid'=> p_list_object['DeploymentProcessId'],
|
513
|
+
'variableid'=> p_list_object['VariableSetId'],
|
514
|
+
'variablesets'=> p_list_object['IncludedLibraryVariableSetIds'],
|
515
|
+
'url' => "http://#{instance}#{p_list_object['Links']['Web']}",
|
516
|
+
},
|
517
|
+
'releases' => [],
|
518
|
+
'process' => process
|
519
|
+
|
520
|
+
}
|
521
|
+
else
|
522
|
+
## steps
|
523
|
+
steps = generic_call('GET', "deploymentprocesses/#{p_list_object['DeploymentProcessId']}", false)
|
524
|
+
if steps['response'] == 'ok'
|
525
|
+
process = []
|
526
|
+
steps['message']['Steps'].each do |step|
|
527
|
+
process.push(step['Name'])
|
528
|
+
end
|
529
|
+
end
|
530
|
+
## steps end
|
531
|
+
variable_sets << {
|
532
|
+
'name' => p_list_object['Name'],
|
533
|
+
'id' => p_list_object['Id'],
|
534
|
+
'url' => "http://#{instance}#{p_list_object['Links']['Web']}",
|
535
|
+
'process' => process
|
536
|
+
}
|
537
|
+
end
|
538
|
+
end
|
539
|
+
if islong.class.to_s == 'TrueClass'
|
540
|
+
# logic for transforming library variables will go here
|
541
|
+
|
542
|
+
create_local_file_by_id('libraryvariablesets')
|
543
|
+
variable_sets.each do |single_var|
|
544
|
+
new_vars = []
|
545
|
+
unless single_var['properties']['variablesets'].nil?
|
546
|
+
single_var['properties']['variablesets'].each do |var_id|
|
547
|
+
new_vars.push(local_file_by_id(var_id,false))
|
548
|
+
end
|
549
|
+
end
|
550
|
+
single_var['properties']['variablesets'] = new_vars
|
551
|
+
end
|
552
|
+
# end of logic for transforming library variables
|
553
|
+
case variable_sets
|
554
|
+
when Array # single item or manyitems is FALSE
|
555
|
+
p_id = variable_sets[0]['properties']['id']
|
556
|
+
release_obj = generic_call('GET', "projects/#{p_id}/releases", false)
|
557
|
+
if release_obj['response'] = 'ok'
|
558
|
+
releases = []
|
559
|
+
release_obj['message']['Items'].each do |item|
|
560
|
+
releases << {
|
561
|
+
'version' => item['Version'],
|
562
|
+
'properties' => {
|
563
|
+
'url' => "https://#{instance}#{item['Links']['Web']}",
|
564
|
+
'id' => item['Id'],
|
565
|
+
}
|
566
|
+
}
|
567
|
+
end
|
568
|
+
variable_sets[0]['releases'] = releases
|
569
|
+
else
|
570
|
+
output['response'] = 'notok'
|
571
|
+
output ['message'] = release_obj['message']
|
572
|
+
end
|
573
|
+
print "\n"
|
574
|
+
|
575
|
+
output['response'] = 'ok'
|
576
|
+
output['message'] = JSON.pretty_generate(variable_sets)
|
577
|
+
|
578
|
+
when Hash # many items or manyitems is TRUE
|
579
|
+
output['response'] = 'ok'
|
580
|
+
output['message'] = JSON.pretty_generate(variable_sets)
|
581
|
+
|
582
|
+
else
|
583
|
+
output['response'] = 'notok'
|
584
|
+
output['message'] = 'Could not parse data appropriately.'
|
585
|
+
return output
|
586
|
+
end
|
587
|
+
else
|
588
|
+
output['response'] = 'ok'
|
589
|
+
output['message'] = JSON.pretty_generate(variable_sets)
|
590
|
+
end
|
591
|
+
if output['message'].class.to_s == 'FalseClass'
|
592
|
+
output['response'] = 'notok'
|
593
|
+
output ['message'] = 'Could not parse data appropriately.'
|
594
|
+
end
|
595
|
+
return output
|
596
|
+
end
|
597
|
+
|
598
|
+
def parse_project_release(r_object)
|
599
|
+
output = {
|
600
|
+
'response' => 'error',
|
601
|
+
'message' => false
|
602
|
+
}
|
603
|
+
instance = @instance
|
604
|
+
variable_sets = []
|
605
|
+
begin
|
606
|
+
package_steps = []
|
607
|
+
r_object['SelectedPackages'].each do |package|
|
608
|
+
package_steps.push(package['StepName'])
|
609
|
+
end
|
610
|
+
variable_sets << {
|
611
|
+
'Assembled' => r_object['Assembled'],
|
612
|
+
'url' => "http://#{instance}#{r_object['Links']['Web']}",
|
613
|
+
'package-steps' => package_steps,
|
614
|
+
'id' => r_object['Id']
|
615
|
+
|
616
|
+
}
|
617
|
+
output['response'] = 'ok'
|
618
|
+
output['message'] = JSON.pretty_generate(variable_sets)
|
619
|
+
rescue
|
620
|
+
output['response'] = 'notok'
|
621
|
+
output ['message'] = 'Could not parse data appropriately.'
|
622
|
+
end
|
623
|
+
return output
|
624
|
+
end
|
625
|
+
|
626
|
+
def parse_deployment(d_object,islong)
|
627
|
+
output = {
|
628
|
+
'response' => 'error',
|
629
|
+
'message' => false
|
630
|
+
}
|
631
|
+
variable_sets = []
|
632
|
+
if islong.class.to_s == 'TrueClass' # long result
|
633
|
+
begin
|
634
|
+
steps = []
|
635
|
+
d_object['StepsToExecute'].each do |item|
|
636
|
+
steps << {
|
637
|
+
'name' => item['ActionName'],
|
638
|
+
'properties' => {
|
639
|
+
'num' => item['ActionNumber'],
|
640
|
+
'roles' => item['Roles'],
|
641
|
+
'targets' => item['MachineNames'],
|
642
|
+
'excluded_machines' => item['ExcludedMachines'],
|
643
|
+
}
|
644
|
+
}
|
645
|
+
end
|
646
|
+
variable_sets << {
|
647
|
+
'steps' => steps
|
648
|
+
}
|
649
|
+
output['response'] = 'ok'
|
650
|
+
output ['message'] = JSON.pretty_generate(variable_sets)
|
651
|
+
rescue
|
652
|
+
output['response'] = 'notok'
|
653
|
+
output ['message'] = 'Could not parse data appropriately.'
|
654
|
+
end
|
655
|
+
return output
|
656
|
+
else # not long
|
657
|
+
begin
|
658
|
+
steps = []
|
659
|
+
d_object['StepsToExecute'].each do |item|
|
660
|
+
steps.push("#{item['ActionNumber']} : #{item['ActionName']}")
|
661
|
+
end
|
662
|
+
variable_sets << {
|
663
|
+
'steps' => steps
|
664
|
+
}
|
665
|
+
output['response'] = 'ok'
|
666
|
+
output ['message'] = JSON.pretty_generate(variable_sets)
|
667
|
+
rescue
|
668
|
+
output['response'] = 'notok'
|
669
|
+
output ['message'] = 'Could not parse data appropriately.'
|
670
|
+
ensure
|
671
|
+
return output
|
672
|
+
end # ends
|
673
|
+
end
|
674
|
+
end
|
675
|
+
|
676
|
+
|
677
|
+
end
|
678
|
+
|
679
|
+
class Octo < Chef::Knife
|
680
|
+
|
681
|
+
def run
|
682
|
+
puts <<-EOH
|
683
|
+
** OCTO COMMANDS **
|
684
|
+
You may use these flags
|
685
|
+
--long or -l
|
686
|
+
The long flag helps with more information
|
687
|
+
|
688
|
+
knife octo variables list
|
689
|
+
knife octo variables show 'name'
|
690
|
+
knife octo env list
|
691
|
+
knife octo env show 'name'
|
692
|
+
knife octo machine list
|
693
|
+
knife octo machine show 'name'
|
694
|
+
|
695
|
+
knife octo project list -- The long option for the said command will display the last 30 releases created for the said project with other details.
|
696
|
+
|
697
|
+
** project show **
|
698
|
+
Supports two additional flags in addition to --long
|
699
|
+
--release or -r
|
700
|
+
--env or -e
|
701
|
+
knife octo project show 'name'
|
702
|
+
knife octo project show 'name' -r 'release number'
|
703
|
+
knife octo project show 'name' -r 'release number' -e 'environment' -- The said command will display the outcome of the process if a deployment were to be triggered on the said environment and release.
|
704
|
+
|
705
|
+
|
706
|
+
EOH
|
707
|
+
end
|
708
|
+
end
|
709
|
+
|
710
|
+
class OctoVariablesList < Chef::Knife
|
711
|
+
banner "** knife octo variables list ** \n knife octo variables list \n knife octo variables list --long \n knife octo variables list -l"
|
712
|
+
option :long,
|
713
|
+
:short => '-l',
|
714
|
+
:long => '--long',
|
715
|
+
:boolean => true,
|
716
|
+
:description => "Select to use long i.e detailed results"
|
717
|
+
def run
|
718
|
+
if Chef::Config[:knife][:octo_instance].nil?
|
719
|
+
ui.error("Please specify your Octopus Deploy instance in your knife config as -\nknife[:octo_instance] = 'MYOCTO.MYDOMAIN'")
|
720
|
+
exit
|
721
|
+
end
|
722
|
+
if Chef::Config[:knife][:octo_apikey].nil?
|
723
|
+
ui.error("Please specify your Octopus API key in your knife config as -\nknife[:octo_apikey] = 'MYKEY'\nSee Also : https://octopus.com/docs/api-and-integration/api/how-to-create-an-api-key")
|
724
|
+
exit
|
725
|
+
end
|
726
|
+
unless name_args.size == 0
|
727
|
+
ui.error("This command does not take any arguments")
|
728
|
+
return
|
729
|
+
end
|
730
|
+
octo_methods = OctoHelperMethods.new(Chef::Config[:knife][:octo_apikey],Chef::Config[:knife][:octo_instance])
|
731
|
+
request = octo_methods.generic_call('GET', 'libraryvariablesets/all/', false)
|
732
|
+
if request['response'] == 'ok'
|
733
|
+
if config[:long]
|
734
|
+
print octo_methods.parse_variable_list(request['message'],true)
|
735
|
+
else
|
736
|
+
print octo_methods.parse_variable_list(request['message'],false)
|
737
|
+
end
|
738
|
+
print "\n"
|
739
|
+
else
|
740
|
+
print request['message']
|
741
|
+
end
|
742
|
+
end
|
743
|
+
end
|
744
|
+
|
745
|
+
class OctoVariablesShow < Chef::Knife
|
746
|
+
banner "** knife octo variables show 'name' ** \n knife octo variables 'name' -l \n knife octo variables show 'name' --long \n"
|
747
|
+
option :long,
|
748
|
+
:short => '-l',
|
749
|
+
:long => '--long',
|
750
|
+
:boolean => true,
|
751
|
+
:description => "Select to use long i.e detailed results"
|
752
|
+
|
753
|
+
def run
|
754
|
+
if Chef::Config[:knife][:octo_instance].nil?
|
755
|
+
ui.error("Please specify your Octopus Deploy instance in your knife config as -\nknife[:octo_instance] = 'MYOCTO.MYDOMAIN'")
|
756
|
+
exit
|
757
|
+
end
|
758
|
+
if Chef::Config[:knife][:octo_apikey].nil?
|
759
|
+
ui.error("Please specify your Octopus API key in your knife config as -\nknife[:octo_apikey] = 'MYKEY'\nSee Also : https://octopus.com/docs/api-and-integration/api/how-to-create-an-api-key")
|
760
|
+
exit
|
761
|
+
end
|
762
|
+
if name_args.size == 0
|
763
|
+
ui.error('Specify a variable list!')
|
764
|
+
return
|
765
|
+
end
|
766
|
+
if name_args.size > 1
|
767
|
+
ui.error ("You specified two variables!\n Try giving the variable name in quotes.")
|
768
|
+
return
|
769
|
+
end
|
770
|
+
octo_methods = OctoHelperMethods.new(Chef::Config[:knife][:octo_apikey],Chef::Config[:knife][:octo_instance])
|
771
|
+
|
772
|
+
if config[:long]
|
773
|
+
if octo_methods.parse_variable_sets(name_args[0],true)['response'] == 'ok'
|
774
|
+
octo_methods.create_local_file_by_id('environments')
|
775
|
+
print octo_methods.parse_variable_sets(name_args[0],true)['message']
|
776
|
+
#delete_local_file
|
777
|
+
else
|
778
|
+
ui.error(octo_methods.parse_variable_sets(name_args[0],true)['message'])
|
779
|
+
exit
|
780
|
+
end
|
781
|
+
else
|
782
|
+
if octo_methods.parse_variable_sets(name_args[0],false)['response'] == 'ok'
|
783
|
+
print octo_methods.parse_variable_sets(name_args[0],false)['message']
|
784
|
+
else
|
785
|
+
ui.error(octo_methods.parse_variable_sets(name_args[0],false)['message'])
|
786
|
+
exit
|
787
|
+
end
|
788
|
+
|
789
|
+
end
|
790
|
+
print "\n"
|
791
|
+
|
792
|
+
|
793
|
+
end
|
794
|
+
end
|
795
|
+
|
796
|
+
class OctoEnvList < Chef::Knife
|
797
|
+
banner "** knife octo env list ** \n knife octo env list\n knife octo env list --long \n knife octo env list -l\n"
|
798
|
+
option :long,
|
799
|
+
:short => '-l',
|
800
|
+
:long => '--long',
|
801
|
+
:boolean => true,
|
802
|
+
:description => "Select to use long i.e detailed results"
|
803
|
+
def run
|
804
|
+
if Chef::Config[:knife][:octo_instance].nil?
|
805
|
+
ui.error("Please specify your Octopus Deploy instance in your knife config as -\nknife[:octo_instance] = 'MYOCTO.MYDOMAIN'")
|
806
|
+
exit
|
807
|
+
end
|
808
|
+
if Chef::Config[:knife][:octo_apikey].nil?
|
809
|
+
ui.error("Please specify your Octopus API key in your knife config as -\nknife[:octo_apikey] = 'MYKEY'\nSee Also : https://octopus.com/docs/api-and-integration/api/how-to-create-an-api-key")
|
810
|
+
exit
|
811
|
+
end
|
812
|
+
unless name_args.size == 0
|
813
|
+
ui.error('This command does not take any arguments')
|
814
|
+
return
|
815
|
+
end
|
816
|
+
octo_methods = OctoHelperMethods.new(Chef::Config[:knife][:octo_apikey],Chef::Config[:knife][:octo_instance])
|
817
|
+
request = octo_methods.generic_call('GET', 'environments/all', false)
|
818
|
+
if request['response'] == 'ok'
|
819
|
+
if config[:long]
|
820
|
+
print octo_methods.parse_env_list(request['message'],true)
|
821
|
+
else
|
822
|
+
print octo_methods.parse_env_list(request['message'],false)
|
823
|
+
end
|
824
|
+
print "\n"
|
825
|
+
else
|
826
|
+
print request['message']
|
827
|
+
end
|
828
|
+
end
|
829
|
+
end
|
830
|
+
|
831
|
+
class OctoEnvShow < Chef::Knife
|
832
|
+
|
833
|
+
banner "** knife octo env show ** \n knife octo env show\n knife octo env show --long \n knife octo env show -l"
|
834
|
+
option :long,
|
835
|
+
:short => '-l',
|
836
|
+
:long => '--long',
|
837
|
+
:boolean => true,
|
838
|
+
:description => "Select to use long i.e detailed results"
|
839
|
+
def run
|
840
|
+
if Chef::Config[:knife][:octo_instance].nil?
|
841
|
+
ui.error("Please specify your Octopus Deploy instance in your knife config as -\nknife[:octo_instance] = 'MYOCTO.MYDOMAIN'")
|
842
|
+
exit
|
843
|
+
end
|
844
|
+
if Chef::Config[:knife][:octo_apikey].nil?
|
845
|
+
ui.error("Please specify your Octopus API key in your knife config as -\nknife[:octo_apikey] = 'MYKEY'\nSee Also : https://octopus.com/docs/api-and-integration/api/how-to-create-an-api-key")
|
846
|
+
exit
|
847
|
+
end
|
848
|
+
if name_args.size > 1
|
849
|
+
ui.error("You provided two environments\nSupply only one environemnt or try quotes.")
|
850
|
+
return
|
851
|
+
end
|
852
|
+
|
853
|
+
unless name_args.size == 1
|
854
|
+
ui.error('Provide the env name!')
|
855
|
+
return
|
856
|
+
end
|
857
|
+
|
858
|
+
octo_methods = OctoHelperMethods.new(Chef::Config[:knife][:octo_apikey],Chef::Config[:knife][:octo_instance])
|
859
|
+
env_id = octo_methods.eid_from_name("#{name_args[0]}")
|
860
|
+
if env_id['response'] == 'ok'
|
861
|
+
|
862
|
+
request = octo_methods.generic_call('GET', "environments/#{env_id['message']}/machines", false)
|
863
|
+
if config[:long]
|
864
|
+
octo_methods.create_local_file_by_id('environments')
|
865
|
+
print octo_methods.parse_env_deets(request['message'],true)
|
866
|
+
print "\n"
|
867
|
+
octo_methods.delete_local_file
|
868
|
+
else
|
869
|
+
print octo_methods.parse_env_deets(request['message'],false)
|
870
|
+
print "\n"
|
871
|
+
end
|
872
|
+
else
|
873
|
+
ui.error(env_id['message'])
|
874
|
+
end
|
875
|
+
end
|
876
|
+
end
|
877
|
+
|
878
|
+
class OctoMachineList < Chef::Knife
|
879
|
+
|
880
|
+
banner "** knife octo machine list ** \n knife octo machine list \n knife octo machine list --long \n knife octo machine list -l\n"
|
881
|
+
option :long,
|
882
|
+
:short => '-l',
|
883
|
+
:long => '--long',
|
884
|
+
:boolean => true,
|
885
|
+
:description => "Select to use long i.e detailed results"
|
886
|
+
def run
|
887
|
+
if Chef::Config[:knife][:octo_instance].nil?
|
888
|
+
ui.error("Please specify your Octopus Deploy instance in your knife config as -\nknife[:octo_instance] = 'MYOCTO.MYDOMAIN'")
|
889
|
+
exit
|
890
|
+
end
|
891
|
+
if Chef::Config[:knife][:octo_apikey].nil?
|
892
|
+
ui.error("Please specify your Octopus API key in your knife config as -\nknife[:octo_apikey] = 'MYKEY'\nSee Also : https://octopus.com/docs/api-and-integration/api/how-to-create-an-api-key")
|
893
|
+
exit
|
894
|
+
end
|
895
|
+
unless name_args.size == 0
|
896
|
+
ui.error('This command does not take any arguments')
|
897
|
+
return
|
898
|
+
end
|
899
|
+
octo_methods = OctoHelperMethods.new(Chef::Config[:knife][:octo_apikey],Chef::Config[:knife][:octo_instance])
|
900
|
+
request = octo_methods.generic_call('GET', 'machines/all', false)
|
901
|
+
if request['response'] == 'ok'
|
902
|
+
if config[:long]
|
903
|
+
print octo_methods.parse_machine_list(request['message'],true)
|
904
|
+
print "\n"
|
905
|
+
else
|
906
|
+
print octo_methods.parse_machine_list(request['message'],false)
|
907
|
+
print "\n"
|
908
|
+
end
|
909
|
+
else
|
910
|
+
ui.error(response['message'])
|
911
|
+
print "\n"
|
912
|
+
end
|
913
|
+
end
|
914
|
+
|
915
|
+
end
|
916
|
+
|
917
|
+
class OctoMachineShow < Chef::Knife
|
918
|
+
banner "** knife octo machine show 'name' ** \n knife octo machine show 'name' \n knife octo machine show 'name' --long \n knife octo machine show 'name' -l"
|
919
|
+
option :long,
|
920
|
+
:short => '-l',
|
921
|
+
:long => '--long',
|
922
|
+
:boolean => true,
|
923
|
+
:description => "Select to use long i.e detailed results"
|
924
|
+
|
925
|
+
def run
|
926
|
+
if Chef::Config[:knife][:octo_instance].nil?
|
927
|
+
ui.error("Please specify your Octopus Deploy instance in your knife config as -\nknife[:octo_instance] = 'MYOCTO.MYDOMAIN'")
|
928
|
+
exit
|
929
|
+
end
|
930
|
+
if Chef::Config[:knife][:octo_apikey].nil?
|
931
|
+
ui.error("Please specify your Octopus API key in your knife config as -\nknife[:octo_apikey] = 'MYKEY'\nSee Also : https://octopus.com/docs/api-and-integration/api/how-to-create-an-api-key")
|
932
|
+
exit
|
933
|
+
end
|
934
|
+
if name_args.size > 1
|
935
|
+
ui.error("You provided two machines.\nSupply only one machine name or try quotes.")
|
936
|
+
return
|
937
|
+
end
|
938
|
+
|
939
|
+
unless name_args.size == 1
|
940
|
+
ui.error("#{'Provide the machine name!'.red}")
|
941
|
+
return
|
942
|
+
end
|
943
|
+
octo_methods = OctoHelperMethods.new(Chef::Config[:knife][:octo_apikey],Chef::Config[:knife][:octo_instance])
|
944
|
+
m_id = octo_methods.mid_from_mname("#{name_args[0]}")
|
945
|
+
if m_id['response'] == 'ok'
|
946
|
+
request = octo_methods.generic_call('GET', "machines/#{m_id['message']}", false)
|
947
|
+
if config[:long]
|
948
|
+
print octo_methods.parse_machine_deets(request['message'],true)
|
949
|
+
print "\n"
|
950
|
+
else
|
951
|
+
print octo_methods.parse_machine_deets(request['message'],false)
|
952
|
+
print "\n"
|
953
|
+
end
|
954
|
+
else
|
955
|
+
ui.error(m_id['message'])
|
956
|
+
end
|
957
|
+
end
|
958
|
+
end
|
959
|
+
|
960
|
+
class OctoProjectList < Chef::Knife
|
961
|
+
banner "** knife octo project list ** \n knife octo project list \n knife octo project list --long \n knife octo project list -l\n"
|
962
|
+
option :long,
|
963
|
+
:short => '-l',
|
964
|
+
:long => '--long',
|
965
|
+
:boolean => true,
|
966
|
+
:description => "Select to use long i.e detailed results"
|
967
|
+
def run
|
968
|
+
if Chef::Config[:knife][:octo_instance].nil?
|
969
|
+
ui.error("Please specify your Octopus Deploy instance in your knife config as -\nknife[:octo_instance] = 'MYOCTO.MYDOMAIN'")
|
970
|
+
exit
|
971
|
+
end
|
972
|
+
if Chef::Config[:knife][:octo_apikey].nil?
|
973
|
+
ui.error("Please specify your Octopus API key in your knife config as -\nknife[:octo_apikey] = 'MYKEY'\nSee Also : https://octopus.com/docs/api-and-integration/api/how-to-create-an-api-key")
|
974
|
+
exit
|
975
|
+
end
|
976
|
+
unless name_args.size == 0
|
977
|
+
ui.error('This command does not take any arguments')
|
978
|
+
return
|
979
|
+
end
|
980
|
+
|
981
|
+
octo_methods = OctoHelperMethods.new(Chef::Config[:knife][:octo_apikey],Chef::Config[:knife][:octo_instance])
|
982
|
+
request = octo_methods.generic_call('GET', 'projects/all', false)
|
983
|
+
if request['response'] == 'ok'
|
984
|
+
if config[:long]
|
985
|
+
octo_methods.create_local_file_by_id('libraryvariablesets')
|
986
|
+
parser = octo_methods.parse_project_list(request['message'],true,true)
|
987
|
+
octo_methods.delete_local_file
|
988
|
+
else
|
989
|
+
parser = octo_methods.parse_project_list(request['message'],false,true)
|
990
|
+
end
|
991
|
+
if parser['response'] == 'ok'
|
992
|
+
print parser['message']
|
993
|
+
else
|
994
|
+
ui.error(parser['message'])
|
995
|
+
end
|
996
|
+
print "\n"
|
997
|
+
else
|
998
|
+
print request['message']
|
999
|
+
end
|
1000
|
+
end
|
1001
|
+
|
1002
|
+
end
|
1003
|
+
|
1004
|
+
class OctoProjectShow < Chef::Knife
|
1005
|
+
banner "** knife octo project show 'name' ** \n knife octo project show 'name' \n knife octo project show 'name' --long \n knife octo project show 'name' -l\n knife octo project show 'name' -r 'release number'\n knife octo project show 'name' -r 'release number' -e 'environment'\n \nknife octo project show 'name' --release 'release number'\n knife octo project show 'name' --release 'release number' --env 'environment'\n\n"
|
1006
|
+
option :long,
|
1007
|
+
:short => '-l',
|
1008
|
+
:long => '--long',
|
1009
|
+
:boolean => true,
|
1010
|
+
:description => "Select to use long i.e detailed results"
|
1011
|
+
|
1012
|
+
option :release,
|
1013
|
+
:short => '-r',
|
1014
|
+
:long => '--release',
|
1015
|
+
:boolean => true,
|
1016
|
+
:description => "Select to specify a release number"
|
1017
|
+
|
1018
|
+
option :env,
|
1019
|
+
:short => '-e',
|
1020
|
+
:long => '--env',
|
1021
|
+
:boolean => true,
|
1022
|
+
:description => "Select to specify an environment"
|
1023
|
+
|
1024
|
+
|
1025
|
+
def run
|
1026
|
+
if Chef::Config[:knife][:octo_instance].nil?
|
1027
|
+
ui.error("Please specify your Octopus Deploy instance in your knife config as -\nknife[:octo_instance] = 'MYOCTO.MYDOMAIN'")
|
1028
|
+
exit
|
1029
|
+
end
|
1030
|
+
if Chef::Config[:knife][:octo_apikey].nil?
|
1031
|
+
ui.error("Please specify your Octopus API key in your knife config as -\nknife[:octo_apikey] = 'MYKEY'\nSee Also : https://octopus.com/docs/api-and-integration/api/how-to-create-an-api-key")
|
1032
|
+
exit
|
1033
|
+
end
|
1034
|
+
|
1035
|
+
if name_args.size == 0
|
1036
|
+
ui.error("#{'Provide the project name!'.red}")
|
1037
|
+
return
|
1038
|
+
end
|
1039
|
+
if (config[:env] && !config[:release])
|
1040
|
+
ui.error('You cannot specify just an environment, specify a release and an environment.')
|
1041
|
+
exit
|
1042
|
+
end
|
1043
|
+
octo_methods = OctoHelperMethods.new(Chef::Config[:knife][:octo_apikey],Chef::Config[:knife][:octo_instance])
|
1044
|
+
request = octo_methods.generic_call('GET', "projects/#{name_args[0]}", false)
|
1045
|
+
case name_args.size
|
1046
|
+
when 1
|
1047
|
+
if config[:release]
|
1048
|
+
ui.error('You specified the release flag but did not provide a release number.')
|
1049
|
+
exit
|
1050
|
+
end
|
1051
|
+
if config[:env]
|
1052
|
+
ui.error('You cannot specify just an environment, specify a release and an environment.')
|
1053
|
+
exit
|
1054
|
+
end
|
1055
|
+
if request['response'] == 'ok'
|
1056
|
+
octo_methods.create_local_file_by_id('environments')
|
1057
|
+
if config[:long]
|
1058
|
+
parser = octo_methods.parse_project_list(request['message'],true,false)
|
1059
|
+
octo_methods.delete_local_file
|
1060
|
+
else
|
1061
|
+
parser = octo_methods.parse_project_list(request['message'],false,false)
|
1062
|
+
end
|
1063
|
+
if parser['response'] == 'ok'
|
1064
|
+
print parser['message']
|
1065
|
+
else
|
1066
|
+
ui.error(parser['message'])
|
1067
|
+
end
|
1068
|
+
else
|
1069
|
+
ui.error(request['message'])
|
1070
|
+
end
|
1071
|
+
octo_methods.delete_local_file
|
1072
|
+
when 2
|
1073
|
+
if config[:release]
|
1074
|
+
if request['response'] == 'ok'
|
1075
|
+
second_request = octo_methods.generic_call('GET', "projects/#{request['message']['Id']}/releases/#{name_args[1]}", false)
|
1076
|
+
if second_request['response'] == 'ok'
|
1077
|
+
release_result = octo_methods.parse_project_release(second_request['message'])
|
1078
|
+
if release_result['response'] == 'ok'
|
1079
|
+
print release_result['message']
|
1080
|
+
else
|
1081
|
+
ui.error(release_result['message'])
|
1082
|
+
end
|
1083
|
+
|
1084
|
+
else
|
1085
|
+
ui.error(second_request['message'])
|
1086
|
+
end
|
1087
|
+
else
|
1088
|
+
ui.error(request['message'])
|
1089
|
+
end
|
1090
|
+
end
|
1091
|
+
|
1092
|
+
when 3
|
1093
|
+
# if config env
|
1094
|
+
if (config[:release] && config[:env])
|
1095
|
+
if request['response'] == 'ok'
|
1096
|
+
second_request = octo_methods.generic_call('GET', "projects/#{request['message']['Id']}/releases/#{name_args[1]}", false)
|
1097
|
+
if second_request['response'] == 'ok'
|
1098
|
+
r_id = second_request['message']['Id']
|
1099
|
+
env = octo_methods.eid_from_name(name_args[2])
|
1100
|
+
if env['response'] == 'ok'
|
1101
|
+
third_request = octo_methods.generic_call('GET', "releases/#{r_id}/deployments/preview/#{env['message']}", false)
|
1102
|
+
if third_request['response'] == 'ok'
|
1103
|
+
if config[:long]
|
1104
|
+
d_deets = octo_methods.parse_deployment(third_request['message'],true)
|
1105
|
+
else
|
1106
|
+
d_deets = octo_methods.parse_deployment(third_request['message'],false)
|
1107
|
+
end
|
1108
|
+
if d_deets['response'] == 'ok'
|
1109
|
+
print d_deets['message']
|
1110
|
+
else
|
1111
|
+
ui.error(d_deets['message'])
|
1112
|
+
exit
|
1113
|
+
end
|
1114
|
+
else
|
1115
|
+
ui.error(third_request['message'])
|
1116
|
+
exit
|
1117
|
+
end
|
1118
|
+
else
|
1119
|
+
ui.error(env['message'])
|
1120
|
+
end
|
1121
|
+
else
|
1122
|
+
ui.error(second_request['message'])
|
1123
|
+
exit
|
1124
|
+
end
|
1125
|
+
else
|
1126
|
+
ui.error(request['message'])
|
1127
|
+
end
|
1128
|
+
|
1129
|
+
end
|
1130
|
+
# end env
|
1131
|
+
else
|
1132
|
+
ui.error('You can only specify two options')
|
1133
|
+
end
|
1134
|
+
print "\n"
|
1135
|
+
end
|
1136
|
+
end
|
1137
|
+
|
1138
|
+
# EOF
|
1139
|
+
end
|
metadata
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: knife-octo
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Vishal Basra
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-10-16 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: colorize
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.7.7
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.7.7
|
27
|
+
description: A knife plugin to things much faster in Octopus Deploy server.
|
28
|
+
email: vishalbasra@live.com
|
29
|
+
executables: []
|
30
|
+
extensions: []
|
31
|
+
extra_rdoc_files: []
|
32
|
+
files:
|
33
|
+
- Gemfile
|
34
|
+
- README.md
|
35
|
+
- knife-octo.gemspec
|
36
|
+
- lib/chef/knife/octo.rb
|
37
|
+
- lib/knife-octo/version.rb
|
38
|
+
homepage: https://github.com/vishalbasra/knife-octo
|
39
|
+
licenses:
|
40
|
+
- Apache-2.0
|
41
|
+
metadata: {}
|
42
|
+
post_install_message:
|
43
|
+
rdoc_options: []
|
44
|
+
require_paths:
|
45
|
+
- lib
|
46
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '0'
|
51
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
requirements: []
|
57
|
+
rubyforge_project:
|
58
|
+
rubygems_version: 2.7.6
|
59
|
+
signing_key:
|
60
|
+
specification_version: 4
|
61
|
+
summary: Chef Knife plugin to help see stuff in Octopus Deploy
|
62
|
+
test_files: []
|