vmware-vra 2.7.0 → 3.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 +4 -4
- data/.gitignore +3 -1
- data/CHANGELOG.md +27 -1
- data/README.md +91 -141
- data/Rakefile +1 -12
- data/lib/vra/catalog.rb +39 -8
- data/lib/vra/catalog_base.rb +62 -0
- data/lib/vra/catalog_item.rb +29 -75
- data/lib/vra/catalog_source.rb +116 -0
- data/lib/vra/catalog_type.rb +56 -0
- data/lib/vra/client.rb +72 -53
- data/lib/vra/deployment.rb +155 -0
- data/lib/vra/deployment_request.rb +117 -0
- data/lib/vra/{resources.rb → deployments.rb} +26 -17
- data/lib/vra/exceptions.rb +2 -2
- data/lib/vra/http.rb +20 -7
- data/lib/vra/request.rb +28 -36
- data/lib/vra/request_parameters.rb +12 -10
- data/lib/vra/resource.rb +33 -203
- data/lib/vra/version.rb +2 -2
- data/lib/vra.rb +15 -12
- data/spec/catalog_item_spec.rb +64 -222
- data/spec/catalog_source_spec.rb +178 -0
- data/spec/catalog_spec.rb +112 -72
- data/spec/catalog_type_spec.rb +114 -0
- data/spec/client_spec.rb +287 -228
- data/spec/deployment_request_spec.rb +192 -0
- data/spec/deployment_spec.rb +227 -0
- data/spec/deployments_spec.rb +80 -0
- data/spec/fixtures/resource/sample_catalog_item.json +18 -0
- data/spec/fixtures/resource/sample_catalog_item_2.json +18 -0
- data/spec/fixtures/resource/sample_catalog_source.json +20 -0
- data/spec/fixtures/resource/sample_catalog_type.json +49 -0
- data/spec/fixtures/resource/sample_dep_actions.json +58 -0
- data/spec/fixtures/resource/sample_dep_request.json +19 -0
- data/spec/fixtures/resource/sample_dep_resource.json +112 -0
- data/spec/fixtures/resource/sample_deployment.json +26 -0
- data/spec/fixtures/resource/sample_entitlements.json +25 -0
- data/spec/http_spec.rb +63 -61
- data/spec/request_spec.rb +62 -68
- data/spec/resource_spec.rb +71 -390
- data/spec/spec_helper.rb +10 -4
- data/vmware-vra.gemspec +2 -4
- metadata +42 -32
- data/.travis.yml +0 -14
- data/lib/vra/catalog_request.rb +0 -127
- data/lib/vra/requests.rb +0 -41
- data/spec/catalog_request_spec.rb +0 -265
- data/spec/requests_spec.rb +0 -60
- data/spec/resources_spec.rb +0 -71
data/lib/vra/catalog_item.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
#
|
3
3
|
# Author:: Chef Partner Engineering (<partnereng@chef.io>)
|
4
|
-
# Copyright:: Copyright (c)
|
4
|
+
# Copyright:: Copyright (c) 2022 Chef Software, Inc.
|
5
5
|
# License:: Apache License, Version 2.0
|
6
6
|
#
|
7
7
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -17,114 +17,68 @@
|
|
17
17
|
# limitations under the License.
|
18
18
|
#
|
19
19
|
|
20
|
-
require "ffi_yajl"
|
20
|
+
require "ffi_yajl" unless defined?(FFI_Yajl)
|
21
21
|
require "vra/catalog"
|
22
22
|
|
23
23
|
module Vra
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
@client = client
|
28
|
-
@id = opts[:id]
|
29
|
-
@catalog_item_data = opts[:data]
|
24
|
+
# Class that represents the Catalog Item
|
25
|
+
class CatalogItem < Vra::CatalogBase
|
26
|
+
INDEX_URL = '/catalog/api/admin/items'
|
30
27
|
|
31
|
-
|
32
|
-
raise ArgumentError, "must supply an id or a catalog item data hash"
|
33
|
-
end
|
28
|
+
attr_reader :project_id
|
34
29
|
|
35
|
-
|
36
|
-
|
37
|
-
|
30
|
+
def initialize(client, opts = {})
|
31
|
+
super
|
32
|
+
@project_id = opts[:project_id]
|
33
|
+
validate!
|
38
34
|
|
39
|
-
if @
|
35
|
+
if @data.nil?
|
40
36
|
fetch_catalog_item
|
41
37
|
else
|
42
|
-
@id = @
|
38
|
+
@id = @data['id']
|
43
39
|
end
|
44
40
|
end
|
45
41
|
|
46
42
|
def fetch_catalog_item
|
47
|
-
@
|
43
|
+
@data = client.get_parsed("/catalog/api/admin/items/#{id}")
|
48
44
|
rescue Vra::Exception::HTTPNotFound
|
49
45
|
raise Vra::Exception::NotFound, "catalog ID #{id} does not exist"
|
50
46
|
end
|
51
47
|
|
52
48
|
def name
|
53
|
-
|
49
|
+
data['name']
|
54
50
|
end
|
55
51
|
|
56
52
|
def description
|
57
|
-
|
58
|
-
end
|
59
|
-
|
60
|
-
def status
|
61
|
-
@catalog_item_data["status"]
|
53
|
+
data['description']
|
62
54
|
end
|
63
55
|
|
64
|
-
def
|
65
|
-
|
66
|
-
|
67
|
-
@catalog_item_data["organization"]
|
56
|
+
def source_id
|
57
|
+
data['sourceId']
|
68
58
|
end
|
69
59
|
|
70
|
-
def
|
71
|
-
|
60
|
+
def source_name
|
61
|
+
data['sourceName']
|
72
62
|
end
|
73
63
|
|
74
|
-
def
|
75
|
-
|
64
|
+
def source
|
65
|
+
@source ||= Vra::CatalogSource.new(client, id: source_id)
|
76
66
|
end
|
77
67
|
|
78
|
-
def
|
79
|
-
|
68
|
+
def type
|
69
|
+
@type ||= Vra::CatalogType.new(client, data: data['type'])
|
80
70
|
end
|
81
71
|
|
82
|
-
def
|
83
|
-
|
72
|
+
def icon_id
|
73
|
+
data['iconId']
|
84
74
|
end
|
85
75
|
|
86
|
-
def
|
87
|
-
|
76
|
+
def entitle!(opts = {})
|
77
|
+
super(opts.merge(type: 'CatalogItemIdentifier'))
|
88
78
|
end
|
89
79
|
|
90
|
-
|
91
|
-
|
92
|
-
# @return [String] - returns a json string of the catalog template
|
93
|
-
def self.dump_template(client, id)
|
94
|
-
response = client.http_get("/catalog-service/api/consumer/entitledCatalogItems/#{id}/requests/template")
|
95
|
-
response.body
|
96
|
-
end
|
97
|
-
|
98
|
-
# @param client [Vra::Client] - a vra client object
|
99
|
-
# @param id [String] - the id of the catalog item
|
100
|
-
# @param filename [String] - the name of the file you want to output the template to
|
101
|
-
# if left blank, will default to the id of the item
|
102
|
-
# @note outputs the catalog template to a file in serialized format
|
103
|
-
def self.write_template(client, id, filename = nil)
|
104
|
-
filename ||= "#{id}.json"
|
105
|
-
begin
|
106
|
-
contents = dump_template(client, id)
|
107
|
-
data = JSON.parse(contents)
|
108
|
-
pretty_contents = JSON.pretty_generate(data)
|
109
|
-
File.write(filename, pretty_contents)
|
110
|
-
return filename
|
111
|
-
rescue Vra::Exception::HTTPError => e
|
112
|
-
raise e
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
# @param [Vra::Client] - a vra client object
|
117
|
-
# @param [String] - the directory path to write the files to
|
118
|
-
# @param [Boolean] - set to true if you wish the file name to be the id of the catalog item
|
119
|
-
# @return [Array[String]] - a array of all the files that were generated
|
120
|
-
def self.dump_templates(client, dir_name = "vra_templates", use_id = false)
|
121
|
-
FileUtils.mkdir_p(dir_name) unless File.exist?(dir_name)
|
122
|
-
client.catalog.entitled_items.map do |c|
|
123
|
-
id = use_id ? c.id : c.name.tr(" ", "_")
|
124
|
-
filename = File.join(dir_name, "#{id}.json").downcase
|
125
|
-
write_template(client, c.id, filename)
|
126
|
-
filename
|
127
|
-
end
|
80
|
+
def self.entitle!(client, id)
|
81
|
+
new(client, id: id).entitle!
|
128
82
|
end
|
129
83
|
end
|
130
84
|
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# Author:: Ashique Saidalavi (<ashique.saidalavi@progress.com>)
|
4
|
+
# Copyright:: Copyright (c) 2022 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 'ffi_yajl' unless defined?(FFI_Yajl)
|
20
|
+
|
21
|
+
module Vra
|
22
|
+
# Class that represents the Catalog Source
|
23
|
+
class CatalogSource < Vra::CatalogBase
|
24
|
+
INDEX_URL = '/catalog/api/admin/sources'
|
25
|
+
|
26
|
+
# @param client [Vra::Client] - a vra client object
|
27
|
+
# @param opts [Hash] - Contains the either id of the catalog or the data hash
|
28
|
+
# Either one of id or data hash is required, must not supply both
|
29
|
+
def initialize(client, opts)
|
30
|
+
super
|
31
|
+
validate!
|
32
|
+
fetch_data
|
33
|
+
end
|
34
|
+
|
35
|
+
def name
|
36
|
+
data['name']
|
37
|
+
end
|
38
|
+
|
39
|
+
def catalog_type_id
|
40
|
+
data['typeId']
|
41
|
+
end
|
42
|
+
|
43
|
+
def catalog_type
|
44
|
+
@catalog_type ||= Vra::CatalogType.new(client, id: catalog_type_id)
|
45
|
+
end
|
46
|
+
|
47
|
+
def config
|
48
|
+
data['config']
|
49
|
+
end
|
50
|
+
|
51
|
+
def global?
|
52
|
+
data['global'] == true
|
53
|
+
end
|
54
|
+
|
55
|
+
def project_id
|
56
|
+
config['sourceProjectId']
|
57
|
+
end
|
58
|
+
|
59
|
+
def entitle!(opts = {})
|
60
|
+
super(opts.merge(type: 'CatalogSourceIdentifier'))
|
61
|
+
end
|
62
|
+
|
63
|
+
class << self
|
64
|
+
# Method to create a catalog source
|
65
|
+
def create(client, opts)
|
66
|
+
validate_create!(opts)
|
67
|
+
|
68
|
+
response = client.http_post(
|
69
|
+
'/catalog/api/admin/sources',
|
70
|
+
FFI_Yajl::Encoder.encode(create_params(opts)),
|
71
|
+
opts[:skip_auth] || false
|
72
|
+
)
|
73
|
+
|
74
|
+
return false unless response.success?
|
75
|
+
|
76
|
+
new(client, data: FFI_Yajl::Parser.parse(response.body))
|
77
|
+
end
|
78
|
+
|
79
|
+
def entitle!(client, id)
|
80
|
+
new(client, id: id).entitle!
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def validate_create!(opts)
|
86
|
+
%i[name catalog_type_id project_id].each do |arg|
|
87
|
+
raise ArgumentError, "#{arg} param is required to perform the create action" unless opts.key?(arg)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def create_params(opts)
|
92
|
+
{
|
93
|
+
'name': opts[:name],
|
94
|
+
'typeId': opts[:catalog_type_id],
|
95
|
+
'config': {
|
96
|
+
'sourceProjectId': opts[:project_id]
|
97
|
+
}
|
98
|
+
}
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
private
|
103
|
+
|
104
|
+
def fetch_data
|
105
|
+
fetch_catalog_data && return if data.nil?
|
106
|
+
|
107
|
+
@id = data['id']
|
108
|
+
end
|
109
|
+
|
110
|
+
def fetch_catalog_data
|
111
|
+
@data = client.get_parsed("/catalog/api/admin/sources/#{id}")
|
112
|
+
rescue Vra::Exception::HTTPNotFound
|
113
|
+
raise Vra::Exception::NotFound, "catalog source ID #{id} does not exist"
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# Author:: Ashique Saidalavi (<ashique.saidalavi@progress.com>)
|
4
|
+
# Copyright:: Copyright (c) 2022 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
|
+
module Vra
|
20
|
+
# Class that represents the Catalog Type
|
21
|
+
class CatalogType < Vra::CatalogBase
|
22
|
+
INDEX_URL = '/catalog/api/types'
|
23
|
+
|
24
|
+
def initialize(client, opts = {})
|
25
|
+
super
|
26
|
+
validate!
|
27
|
+
fetch_data
|
28
|
+
end
|
29
|
+
|
30
|
+
def name
|
31
|
+
data['name']
|
32
|
+
end
|
33
|
+
|
34
|
+
def base_url
|
35
|
+
data['baseUri']
|
36
|
+
end
|
37
|
+
|
38
|
+
def config_schema
|
39
|
+
data['configSchema']
|
40
|
+
end
|
41
|
+
|
42
|
+
def icon_id
|
43
|
+
data['iconId']
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def fetch_data
|
49
|
+
@id = data['id'] and return unless data.nil?
|
50
|
+
|
51
|
+
@data = client.get_parsed("/catalog/api/types/#{id}")
|
52
|
+
rescue Vra::Exception::HTTPNotFound
|
53
|
+
raise Vra::Exception::NotFound, "catalog type ID #{id} does not exist"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/vra/client.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
#
|
3
3
|
# Author:: Chef Partner Engineering (<partnereng@chef.io>)
|
4
|
-
# Copyright:: Copyright (c)
|
4
|
+
# Copyright:: Copyright (c) 2022 Chef Software, Inc.
|
5
5
|
# License:: Apache License, Version 2.0
|
6
6
|
#
|
7
7
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -17,22 +17,27 @@
|
|
17
17
|
# limitations under the License.
|
18
18
|
#
|
19
19
|
|
20
|
-
require
|
21
|
-
require
|
22
|
-
require
|
20
|
+
require 'ffi_yajl' unless defined?(FFI_Yajl)
|
21
|
+
require 'passwordmasker'
|
22
|
+
require 'vra/http'
|
23
23
|
|
24
24
|
module Vra
|
25
25
|
class Client
|
26
|
+
REFRESH_TOKEN_URL = '/csp/gateway/am/api/login?access_token'
|
27
|
+
ACCESS_TOKEN_URL = '/iaas/api/login'
|
28
|
+
ROLES_URL = '/csp/gateway/am/api/loggedin/user/orgs'
|
29
|
+
|
26
30
|
attr_accessor :page_size
|
27
31
|
|
28
32
|
def initialize(opts)
|
29
|
-
@base_url
|
30
|
-
@username
|
31
|
-
@password
|
32
|
-
@tenant
|
33
|
-
@verify_ssl
|
34
|
-
@
|
35
|
-
@
|
33
|
+
@base_url = opts[:base_url]
|
34
|
+
@username = opts[:username]
|
35
|
+
@password = PasswordMasker.new(opts[:password])
|
36
|
+
@tenant = opts[:tenant]
|
37
|
+
@verify_ssl = opts.fetch(:verify_ssl, true)
|
38
|
+
@refresh_token = PasswordMasker.new(nil)
|
39
|
+
@access_token = PasswordMasker.new(nil)
|
40
|
+
@page_size = opts.fetch(:page_size, 20)
|
36
41
|
|
37
42
|
validate_client_options!
|
38
43
|
end
|
@@ -43,15 +48,11 @@ module Vra
|
|
43
48
|
#
|
44
49
|
|
45
50
|
def catalog
|
46
|
-
Vra::Catalog.new(self)
|
47
|
-
end
|
48
|
-
|
49
|
-
def requests(*args)
|
50
|
-
Vra::Requests.new(self, *args)
|
51
|
+
@catalog ||= Vra::Catalog.new(self)
|
51
52
|
end
|
52
53
|
|
53
|
-
def
|
54
|
-
Vra::
|
54
|
+
def deployments
|
55
|
+
@deployments ||= Vra::Deployments.new(self)
|
55
56
|
end
|
56
57
|
|
57
58
|
#########################
|
@@ -59,55 +60,73 @@ module Vra
|
|
59
60
|
# client methods
|
60
61
|
#
|
61
62
|
|
62
|
-
def
|
63
|
-
@
|
63
|
+
def access_token
|
64
|
+
@access_token.value
|
65
|
+
end
|
66
|
+
|
67
|
+
def refresh_token
|
68
|
+
@refresh_token.value
|
69
|
+
end
|
70
|
+
|
71
|
+
def access_token=(value)
|
72
|
+
@access_token.value = value
|
64
73
|
end
|
65
74
|
|
66
|
-
def
|
67
|
-
@
|
75
|
+
def refresh_token=(value)
|
76
|
+
@refresh_token.value = value
|
68
77
|
end
|
69
78
|
|
70
|
-
def
|
79
|
+
def token_params
|
71
80
|
{
|
72
|
-
|
73
|
-
|
74
|
-
|
81
|
+
'username': @username,
|
82
|
+
'password': @password.value,
|
83
|
+
'tenant': @tenant
|
75
84
|
}
|
76
85
|
end
|
77
86
|
|
78
87
|
def request_headers
|
79
|
-
headers
|
80
|
-
headers[
|
81
|
-
headers[
|
82
|
-
headers[
|
88
|
+
headers = {}
|
89
|
+
headers['Accept'] = 'application/json'
|
90
|
+
headers['Content-Type'] = 'application/json'
|
91
|
+
headers['csp-auth-token'] = @access_token.value unless @access_token.value.nil?
|
92
|
+
|
83
93
|
headers
|
84
94
|
end
|
85
95
|
|
86
96
|
def authorize!
|
87
|
-
|
97
|
+
generate_access_token unless authorized?
|
88
98
|
|
89
|
-
raise Vra::Exception::Unauthorized,
|
99
|
+
raise Vra::Exception::Unauthorized, 'Unable to authorize against vRA' unless authorized?
|
90
100
|
end
|
91
101
|
|
92
102
|
def authorized?
|
93
|
-
return false if @
|
103
|
+
return false if @access_token.value.nil?
|
94
104
|
|
95
|
-
response = http_head(
|
96
|
-
response.
|
105
|
+
response = http_head(ROLES_URL, :skip_auth)
|
106
|
+
response.success?
|
97
107
|
end
|
98
108
|
|
99
|
-
def
|
100
|
-
@
|
109
|
+
def generate_access_token
|
110
|
+
@refresh_token.value = nil
|
111
|
+
@access_token.value = nil
|
101
112
|
validate_client_options!
|
102
113
|
|
103
|
-
|
104
|
-
|
114
|
+
# VRA 8 has a two-step authentication process - This probably breaks VRA7, who knows?!?
|
115
|
+
# First step: Sending Username/Password to get a Refresh Token
|
116
|
+
refresh_response = http_post(REFRESH_TOKEN_URL,
|
117
|
+
FFI_Yajl::Encoder.encode(token_params),
|
105
118
|
:skip_auth)
|
106
|
-
unless
|
107
|
-
|
108
|
-
|
119
|
+
raise Vra::Exception::Unauthorized, "Unable to get the refresh token: #{refresh_response.body}" unless refresh_response.success_ok?
|
120
|
+
|
121
|
+
refresh_response_body = FFI_Yajl::Parser.parse(refresh_response.body)
|
122
|
+
@refresh_token.value = refresh_response_body['refresh_token']
|
109
123
|
|
110
|
-
|
124
|
+
# Second Step: Sending the refresh token to a separate endpoint to get an Access Token
|
125
|
+
access_response = http_post(ACCESS_TOKEN_URL, "{ \"refreshToken\": \"#{@refresh_token.value}\" }", :skip_auth)
|
126
|
+
raise Vra::Exception::Unauthorized, "Unable to get the access token: #{access_response.body}" unless access_response.success_ok?
|
127
|
+
|
128
|
+
access_response_body = FFI_Yajl::Parser.parse(access_response.body)
|
129
|
+
@access_token.value = access_response_body['token']
|
111
130
|
end
|
112
131
|
|
113
132
|
def full_url(path)
|
@@ -140,21 +159,26 @@ module Vra
|
|
140
159
|
response.body
|
141
160
|
end
|
142
161
|
|
162
|
+
def http_delete(path, skip_auth = nil)
|
163
|
+
http_fetch(:delete, path, skip_auth)
|
164
|
+
end
|
165
|
+
|
143
166
|
def get_parsed(path)
|
144
167
|
FFI_Yajl::Parser.parse(http_get!(path))
|
145
168
|
end
|
146
169
|
|
147
|
-
def http_get_paginated_array!(path)
|
170
|
+
def http_get_paginated_array!(path, filter = nil)
|
148
171
|
items = []
|
149
|
-
page =
|
150
|
-
base_path = path + "
|
172
|
+
page = 0
|
173
|
+
base_path = path + "?$top=#{page_size}"
|
174
|
+
base_path += "&#{filter}" if filter
|
151
175
|
|
152
176
|
loop do
|
153
|
-
response = get_parsed("#{base_path}
|
177
|
+
response = get_parsed("#{base_path}&$skip=#{page * page_size}")
|
154
178
|
items += response["content"]
|
155
179
|
|
156
|
-
break if page >= response["metadata"]["totalPages"]
|
157
180
|
page += 1
|
181
|
+
break if page >= response["totalPages"]
|
158
182
|
end
|
159
183
|
|
160
184
|
if items.uniq!
|
@@ -218,10 +242,5 @@ module Vra
|
|
218
242
|
rescue URI::InvalidURIError
|
219
243
|
false
|
220
244
|
end
|
221
|
-
|
222
|
-
def fetch_subtenant_items(tenant, subtenant_name)
|
223
|
-
http_get("/identity/api/tenants/#{tenant}/subtenants?%24filter=name+eq+'#{subtenant_name}'")
|
224
|
-
end
|
225
|
-
|
226
245
|
end
|
227
246
|
end
|
@@ -0,0 +1,155 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# Author:: Ashique Saidalavi (<ashique.saidalavi@progress.com>)
|
4
|
+
# Copyright:: Copyright (c) 2022 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
|
+
|
20
|
+
require "ffi_yajl" unless defined?(FFI_Yajl)
|
21
|
+
|
22
|
+
module Vra
|
23
|
+
# Class that represents the Deployment Object
|
24
|
+
class Deployment
|
25
|
+
INDEX_URL = '/deployment/api/deployments'
|
26
|
+
|
27
|
+
attr_reader :id
|
28
|
+
|
29
|
+
def initialize(client, opts = {})
|
30
|
+
@client = client
|
31
|
+
@id = opts[:id]
|
32
|
+
@data = opts[:data]
|
33
|
+
validate!
|
34
|
+
|
35
|
+
if @data.nil?
|
36
|
+
refresh
|
37
|
+
elsif @id.nil?
|
38
|
+
@id = @data['id']
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def name
|
43
|
+
@data['name']
|
44
|
+
end
|
45
|
+
|
46
|
+
def description
|
47
|
+
@data['description']
|
48
|
+
end
|
49
|
+
|
50
|
+
def org_id
|
51
|
+
@data['orgId']
|
52
|
+
end
|
53
|
+
|
54
|
+
def blueprint_id
|
55
|
+
@data['blueprintId']
|
56
|
+
end
|
57
|
+
|
58
|
+
def owner
|
59
|
+
@data['ownedBy']
|
60
|
+
end
|
61
|
+
|
62
|
+
def status
|
63
|
+
@data['status']
|
64
|
+
end
|
65
|
+
|
66
|
+
def successful?
|
67
|
+
status == 'CREATE_SUCCESSFUL'
|
68
|
+
end
|
69
|
+
|
70
|
+
def failed?
|
71
|
+
status == 'CREATE_FAILED'
|
72
|
+
end
|
73
|
+
|
74
|
+
def completed?
|
75
|
+
successful? || failed?
|
76
|
+
end
|
77
|
+
|
78
|
+
def actions
|
79
|
+
@actions = client.get_parsed("/deployment/api/deployments/#{id}/actions")
|
80
|
+
end
|
81
|
+
|
82
|
+
def action_id_by_name(action_name)
|
83
|
+
action = actions.find { |x| x['name'] == action_name}
|
84
|
+
return if action.nil?
|
85
|
+
|
86
|
+
action['id']
|
87
|
+
end
|
88
|
+
|
89
|
+
def resources
|
90
|
+
response = client.get_parsed("/deployment/api/deployments/#{id}/resources")
|
91
|
+
|
92
|
+
response['content'].map! { |x| Vra::Resource.new(client, id, data: x) }
|
93
|
+
end
|
94
|
+
|
95
|
+
def resource_by_id(res_id)
|
96
|
+
Vra::Resource.new(client, id, id: res_id)
|
97
|
+
end
|
98
|
+
|
99
|
+
def requests
|
100
|
+
response = client.get_parsed("/deployment/api/deployments/#{id}/requests")
|
101
|
+
|
102
|
+
response['content'].map! { |x| Vra::Request.new(client, id, id: x['id'], data: x) }
|
103
|
+
end
|
104
|
+
|
105
|
+
def refresh
|
106
|
+
@data = client.get_parsed("/deployment/api/deployments/#{id}")
|
107
|
+
rescue Vra::Exception::HTTPNotFound
|
108
|
+
raise Vra::Exception::NotFound, "deployment with ID #{id} does not exist"
|
109
|
+
end
|
110
|
+
|
111
|
+
def destroy(reason = '')
|
112
|
+
action_id = action_id_by_name('Delete')
|
113
|
+
raise Vra::Exception::NotFound, "No destroy action found for resource #{@id}" if action_id.nil?
|
114
|
+
|
115
|
+
submit_action_request(action_id, reason)
|
116
|
+
end
|
117
|
+
|
118
|
+
def power_off(reason = '')
|
119
|
+
action_id = action_id_by_name('PowerOff')
|
120
|
+
raise Vra::Exception::NotFound, "No power-off action found for resource #{@id}" if action_id.nil?
|
121
|
+
|
122
|
+
submit_action_request(action_id, reason)
|
123
|
+
end
|
124
|
+
|
125
|
+
def power_on(reason = nil)
|
126
|
+
action_id = action_id_by_name('PowerOn')
|
127
|
+
raise Vra::Exception::NotFound, "No power-on action found for resource #{@id}" if action_id.nil?
|
128
|
+
|
129
|
+
submit_action_request(action_id, reason)
|
130
|
+
end
|
131
|
+
|
132
|
+
private
|
133
|
+
|
134
|
+
attr_reader :client, :data
|
135
|
+
|
136
|
+
def validate!
|
137
|
+
raise ArgumentError, 'must supply id or data hash' if @id.nil? && @data.nil?
|
138
|
+
end
|
139
|
+
|
140
|
+
def submit_action_request(action_id, reason)
|
141
|
+
response = client.http_post!("/deployment/api/deployments/#{id}/requests",
|
142
|
+
FFI_Yajl::Encoder.encode(submit_action_payload(action_id, reason)))
|
143
|
+
|
144
|
+
Vra::Request.new(client, id, data: FFI_Yajl::Parser.parse(response))
|
145
|
+
end
|
146
|
+
|
147
|
+
def submit_action_payload(action_id, reason)
|
148
|
+
{
|
149
|
+
"actionId": action_id,
|
150
|
+
"inputs": {},
|
151
|
+
"reason": reason
|
152
|
+
}
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|