opsmgr 0.26.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/LEGAL.txt +13 -0
- data/README.md +21 -0
- data/lib/opsmgr.rb +12 -0
- data/lib/opsmgr/api/client.rb +85 -0
- data/lib/opsmgr/api/endpoints_factory.rb +39 -0
- data/lib/opsmgr/api/http_client.rb +204 -0
- data/lib/opsmgr/api/results.rb +257 -0
- data/lib/opsmgr/api/version20/endpoints.rb +93 -0
- data/lib/opsmgr/cmd/bosh_command.rb +213 -0
- data/lib/opsmgr/cmd/ops_manager.rb +100 -0
- data/lib/opsmgr/environments.rb +77 -0
- data/lib/opsmgr/errand_runner.rb +75 -0
- data/lib/opsmgr/log.rb +70 -0
- data/lib/opsmgr/product_upload_wrapper.rb +69 -0
- data/lib/opsmgr/renderer.rb +23 -0
- data/lib/opsmgr/renderer/aws.rb +147 -0
- data/lib/opsmgr/renderer/noop.rb +21 -0
- data/lib/opsmgr/settings/microbosh/installation_settings.rb +84 -0
- data/lib/opsmgr/settings/microbosh/job.rb +54 -0
- data/lib/opsmgr/settings/microbosh/job_list.rb +27 -0
- data/lib/opsmgr/settings/microbosh/network.rb +21 -0
- data/lib/opsmgr/settings/microbosh/product.rb +88 -0
- data/lib/opsmgr/settings/microbosh/product_list.rb +27 -0
- data/lib/opsmgr/settings/microbosh/property.rb +31 -0
- data/lib/opsmgr/settings/microbosh/property_list.rb +27 -0
- data/lib/opsmgr/tasks.rb +16 -0
- data/lib/opsmgr/tasks/bosh.rake +70 -0
- data/lib/opsmgr/tasks/destroy.rake +42 -0
- data/lib/opsmgr/tasks/info.rake +19 -0
- data/lib/opsmgr/tasks/opsmgr.rake +179 -0
- data/lib/opsmgr/tasks/product.rake +53 -0
- data/lib/opsmgr/teapot.rb +51 -0
- data/lib/opsmgr/teapot/app.rb +50 -0
- data/lib/opsmgr/teapot/spec_helper.rb +33 -0
- data/lib/opsmgr/ui_helpers/add_first_user_spec.rb +25 -0
- data/lib/opsmgr/ui_helpers/config_helper.rb +151 -0
- data/lib/opsmgr/ui_helpers/delete_installation_spec.rb +41 -0
- data/lib/opsmgr/ui_helpers/delete_product_if_present_spec.rb +43 -0
- data/lib/opsmgr/ui_helpers/delete_product_spec.rb +39 -0
- data/lib/opsmgr/ui_helpers/export_installation_spec.rb +31 -0
- data/lib/opsmgr/ui_helpers/get_latest_install_log_spec.rb +29 -0
- data/lib/opsmgr/ui_helpers/import_installation_spec.rb +29 -0
- data/lib/opsmgr/ui_helpers/import_stemcell_spec.rb +30 -0
- data/lib/opsmgr/ui_helpers/microbosh/configure_microbosh_spec.rb +31 -0
- data/lib/opsmgr/ui_helpers/trigger_install_spec.rb +35 -0
- data/lib/opsmgr/ui_helpers/ui_spec_runner.rb +117 -0
- data/lib/opsmgr/ui_helpers/uncheck_errands_spec.rb +29 -0
- data/lib/opsmgr/ui_helpers/upload_and_add_product_spec.rb +27 -0
- data/lib/opsmgr/ui_helpers/upload_and_upgrade_product_spec.rb +36 -0
- data/lib/opsmgr/version.rb +11 -0
- metadata +360 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 864044e4d3a84e015296758b804e25971447ada0
|
4
|
+
data.tar.gz: b6e953028634614943d4ae23af5e8f86640b8a34
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 33132d5940ceaf71d8b3f0c2bfa4ceb9f253824cf72cbbc52ebf722665610343e464371925a1677792b3bda65467e0a860804eac37cab1ebc0d14952cc55ade9
|
7
|
+
data.tar.gz: 32fab1f041920f74a0ecaa4db3c6c8023b839b4638bba54c2583dea13dd5afde3d0997e6fe0fd57bd9ec0f7190a8231053519ff41299b714cf38f34f36da1b27
|
data/LEGAL.txt
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright (c) 2014-2015 Pivotal Software, Inc. All rights reserved.
|
2
|
+
|
3
|
+
Unauthorized use, copying or distribution of this source code via any
|
4
|
+
medium is strictly prohibited without the express written consent of
|
5
|
+
Pivotal Software, Inc.
|
6
|
+
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
8
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
9
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
10
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
11
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
12
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
13
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# opsmgr
|
2
|
+
|
3
|
+
A ruby client for opsmanager and related tools. Extracted from RelEng's [release-engineeering-automation](https://github.com/pivotal-cf/release-engineering-automation/).
|
4
|
+
|
5
|
+
## Usage
|
6
|
+
|
7
|
+
### Gemfile
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'opsmgr', git: 'git@github.com:pivotal-cf/opsmgr.git'
|
11
|
+
```
|
12
|
+
|
13
|
+
### Rakefile
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
require 'opsmgr/tasks'
|
17
|
+
```
|
18
|
+
|
19
|
+
### Teapot
|
20
|
+
|
21
|
+
TODO
|
data/lib/opsmgr.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'opsmgr/version'
|
2
|
+
|
3
|
+
module Opsmgr
|
4
|
+
end
|
5
|
+
# Copyright (c) 2014-2015 Pivotal Software, Inc.
|
6
|
+
# All rights reserved.
|
7
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
8
|
+
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
9
|
+
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
10
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
11
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
12
|
+
# USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'opsmgr/api/http_client'
|
3
|
+
require 'opsmgr/api/results'
|
4
|
+
require 'opsmgr/settings/microbosh/product_list'
|
5
|
+
|
6
|
+
module Opsmgr
|
7
|
+
module Api
|
8
|
+
class Client
|
9
|
+
attr_reader :environment_name
|
10
|
+
|
11
|
+
def initialize(environment)
|
12
|
+
@http_client = HttpClient.build(environment)
|
13
|
+
@environment_name = environment.settings.name.freeze
|
14
|
+
end
|
15
|
+
|
16
|
+
def installation_settings
|
17
|
+
response = http_client.installation_settings
|
18
|
+
if response.code == '200'
|
19
|
+
InstallationSettingsResult.new(JSON.parse(response.body))
|
20
|
+
else
|
21
|
+
Error.new('Error viewing current installation settings', response)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# .pivotal file is referred to as a "product" but the Tempest developers call it a "component"
|
26
|
+
def upload_component(path)
|
27
|
+
response = http_client.upload_component(path)
|
28
|
+
basic_success_or_error("Error uploading #{path}", response)
|
29
|
+
end
|
30
|
+
|
31
|
+
def add_product(product_name, version)
|
32
|
+
response = http_client.add_product(product_name, version)
|
33
|
+
basic_success_or_error("Error adding '#{product_name} #{version}'", response)
|
34
|
+
end
|
35
|
+
|
36
|
+
def upgrade_product(product_guid, to_version)
|
37
|
+
response = http_client.upgrade_product(product_guid, to_version)
|
38
|
+
basic_success_or_error("Error upgrading '#{product_guid}' to '#{to_version}'", response)
|
39
|
+
end
|
40
|
+
|
41
|
+
def list_products
|
42
|
+
response = http_client.list_products
|
43
|
+
if response.code == '200'
|
44
|
+
ListProductsResult.new(JSON.parse(response.body))
|
45
|
+
else
|
46
|
+
Error.new('Error listing products', response)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def installed_products
|
51
|
+
response = http_client.installed_products
|
52
|
+
if response.code == '200'
|
53
|
+
InstalledProductsResult.new(Opsmgr::Settings::Microbosh::ProductList.new(JSON.parse(response.body)))
|
54
|
+
else
|
55
|
+
Error.new('Error listing installed products', response)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def delete_unused_products
|
60
|
+
response = http_client.delete_unused_products
|
61
|
+
basic_success_or_error('There was an error deleting the unused products:', response)
|
62
|
+
end
|
63
|
+
|
64
|
+
def basic_success_or_error(message, response)
|
65
|
+
if response.code == '200'
|
66
|
+
Result.new
|
67
|
+
else
|
68
|
+
Error.new(message, response)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
attr_reader :http_client
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
# Copyright (c) 2014-2015 Pivotal Software, Inc.
|
79
|
+
# All rights reserved.
|
80
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
81
|
+
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
82
|
+
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
83
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
84
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
85
|
+
# USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'opsmgr/api/version20/endpoints'
|
3
|
+
|
4
|
+
module Opsmgr
|
5
|
+
module Api
|
6
|
+
class EndpointsFactory
|
7
|
+
def self.create(environment)
|
8
|
+
req = Net::HTTP::Get.new('/api/api_version')
|
9
|
+
uri = URI.parse(environment.settings.ops_manager.url)
|
10
|
+
req.basic_auth(environment.settings.ops_manager.username, environment.settings.ops_manager.password)
|
11
|
+
|
12
|
+
response = http(uri).request(req)
|
13
|
+
|
14
|
+
api_version = JSON.parse(response.body).fetch('version')
|
15
|
+
case api_version
|
16
|
+
when '2.0'
|
17
|
+
return Opsmgr::Api::Version20::Endpoints.new
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.http(uri)
|
22
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
23
|
+
if uri.scheme == 'https'
|
24
|
+
http.use_ssl = true
|
25
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
26
|
+
end
|
27
|
+
http
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
# Copyright (c) 2014-2015 Pivotal Software, Inc.
|
33
|
+
# All rights reserved.
|
34
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
35
|
+
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
36
|
+
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
37
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
38
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
39
|
+
# USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@@ -0,0 +1,204 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'net/http/post/multipart'
|
3
|
+
require 'json'
|
4
|
+
require 'open4'
|
5
|
+
require 'opsmgr/api/endpoints_factory'
|
6
|
+
require 'opsmgr/log'
|
7
|
+
|
8
|
+
# noinspection RubyResolve
|
9
|
+
module Opsmgr
|
10
|
+
module Api
|
11
|
+
class HttpClient
|
12
|
+
include Loggable
|
13
|
+
attr_reader :uri, :environment, :endpoints
|
14
|
+
|
15
|
+
def self.build(environment)
|
16
|
+
new(environment, Opsmgr::Api::EndpointsFactory.create(environment))
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(environment, endpoints)
|
20
|
+
@environment = environment
|
21
|
+
@uri = URI.parse(environment.settings.ops_manager.url)
|
22
|
+
@endpoints = endpoints
|
23
|
+
end
|
24
|
+
|
25
|
+
def upload_product_installation_settings(settings_file_path)
|
26
|
+
req = Net::HTTP::Post::Multipart.new(
|
27
|
+
endpoints.installation_settings_post_path,
|
28
|
+
'installation[file]' =>
|
29
|
+
UploadIO.new(
|
30
|
+
settings_file_path,
|
31
|
+
'application/octet-stream',
|
32
|
+
File.basename(settings_file_path)
|
33
|
+
)
|
34
|
+
)
|
35
|
+
|
36
|
+
req.basic_auth(web_auth_user, web_auth_password)
|
37
|
+
|
38
|
+
http.request(req)
|
39
|
+
end
|
40
|
+
|
41
|
+
def upload_component(product_path)
|
42
|
+
# We ran into a possible Net::HTTP bug where Ruby would always drop the connection while waiting for the
|
43
|
+
# uploaded zip file to unzip. Curl behaved correctly, but curb (Ruby bindings for libcurl) did not behave
|
44
|
+
# well with WebMock, so here we are.
|
45
|
+
upload_component_command =
|
46
|
+
%W(
|
47
|
+
curl -k
|
48
|
+
--silent
|
49
|
+
--fail
|
50
|
+
#{uri}#{endpoints.upload_product_path}
|
51
|
+
-F #{endpoints.upload_product_form_key}[file]=@#{product_path}
|
52
|
+
-X POST
|
53
|
+
-u #{web_auth_user}:#{web_auth_password}
|
54
|
+
)
|
55
|
+
log.info('uploading product')
|
56
|
+
|
57
|
+
error = nil
|
58
|
+
status =
|
59
|
+
Open4.popen4(*upload_component_command) do |_, _, stdout, stderr|
|
60
|
+
log.info(stdout.read)
|
61
|
+
error = stderr.read
|
62
|
+
end
|
63
|
+
|
64
|
+
if status.success?
|
65
|
+
FakeResponse.new('200', '{}')
|
66
|
+
else
|
67
|
+
error_code = (error.match(/^\< HTTP\/.* (\d+) /) || [nil, '???'])[1]
|
68
|
+
FakeResponse.new(error_code, error)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def add_product(product_name, version)
|
73
|
+
req = Net::HTTP::Post.new(endpoints.add_product_path)
|
74
|
+
req.set_form_data('name' => product_name, 'product_version' => version)
|
75
|
+
req.basic_auth(web_auth_user, web_auth_password)
|
76
|
+
|
77
|
+
http.request(req)
|
78
|
+
end
|
79
|
+
|
80
|
+
def upgrade_product(product_guid, to_version)
|
81
|
+
req = Net::HTTP::Put.new(endpoints.upgrade_product_path(product_guid))
|
82
|
+
req.set_form_data('to_version' => to_version)
|
83
|
+
req.basic_auth(web_auth_user, web_auth_password)
|
84
|
+
|
85
|
+
http.request(req)
|
86
|
+
end
|
87
|
+
|
88
|
+
def trigger_install
|
89
|
+
req = Net::HTTP::Post.new(endpoints.install_post_path)
|
90
|
+
req.body = ''
|
91
|
+
req.basic_auth(web_auth_user, web_auth_password)
|
92
|
+
|
93
|
+
http.request(req)
|
94
|
+
end
|
95
|
+
|
96
|
+
# components are both uploaded AND configured AND deployed
|
97
|
+
def list_components
|
98
|
+
get_with_basic_auth(endpoints.list_components_path)
|
99
|
+
end
|
100
|
+
|
101
|
+
# products are uploaded but not necessarily configured or deployed
|
102
|
+
def list_products
|
103
|
+
get_with_basic_auth(endpoints.list_products_path)
|
104
|
+
end
|
105
|
+
|
106
|
+
# products that have been uploaded, configured, and installed
|
107
|
+
def installed_products
|
108
|
+
get_with_basic_auth(endpoints.installed_products_path)
|
109
|
+
end
|
110
|
+
|
111
|
+
def product_manifest(product_guid)
|
112
|
+
get_with_basic_auth(endpoints.product_manifest_path(product_guid))
|
113
|
+
end
|
114
|
+
|
115
|
+
def installation_settings
|
116
|
+
get_with_basic_auth(endpoints.installation_settings_get_path)
|
117
|
+
end
|
118
|
+
|
119
|
+
def installation_delete
|
120
|
+
req = Net::HTTP::Delete.new(endpoints.installation_path)
|
121
|
+
req.basic_auth(web_auth_user, web_auth_password)
|
122
|
+
|
123
|
+
http.request(req)
|
124
|
+
end
|
125
|
+
|
126
|
+
def installation_deletion_status
|
127
|
+
get_with_basic_auth(endpoints.installation_deletion_status_path)
|
128
|
+
end
|
129
|
+
|
130
|
+
def create_the_first_user
|
131
|
+
req = Net::HTTP::Post.new(endpoints.configure_user_path)
|
132
|
+
req.set_form_data(
|
133
|
+
'user[user_name]' => web_auth_user,
|
134
|
+
'user[password]' => web_auth_password,
|
135
|
+
'user[password_confirmation]' => web_auth_password)
|
136
|
+
http.request(req)
|
137
|
+
end
|
138
|
+
|
139
|
+
def install_status(install_id)
|
140
|
+
get_with_basic_auth(endpoints.show_installation_status(install_id))
|
141
|
+
end
|
142
|
+
|
143
|
+
def install_log(install_id)
|
144
|
+
get_with_basic_auth(endpoints.installation_log_path(install_id))
|
145
|
+
end
|
146
|
+
|
147
|
+
def mark_product_for_deletion(product_guid)
|
148
|
+
req = Net::HTTP::Delete.new(endpoints.mark_for_deletion_path(product_guid))
|
149
|
+
req.basic_auth(web_auth_user, web_auth_password)
|
150
|
+
|
151
|
+
http.request(req)
|
152
|
+
end
|
153
|
+
|
154
|
+
def delete_unused_products
|
155
|
+
req = Net::HTTP::Delete.new(endpoints.list_products_path)
|
156
|
+
req.basic_auth(web_auth_user, web_auth_password)
|
157
|
+
|
158
|
+
http.request(req)
|
159
|
+
end
|
160
|
+
|
161
|
+
def version
|
162
|
+
endpoints.version
|
163
|
+
end
|
164
|
+
|
165
|
+
private
|
166
|
+
|
167
|
+
def web_auth_user
|
168
|
+
environment.settings.ops_manager.username
|
169
|
+
end
|
170
|
+
|
171
|
+
def web_auth_password
|
172
|
+
environment.settings.ops_manager.password
|
173
|
+
end
|
174
|
+
|
175
|
+
def http
|
176
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
177
|
+
if uri.scheme == 'https'
|
178
|
+
http.use_ssl = true
|
179
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
180
|
+
end
|
181
|
+
http.read_timeout = 240
|
182
|
+
http
|
183
|
+
end
|
184
|
+
|
185
|
+
def get_with_basic_auth(path)
|
186
|
+
req = Net::HTTP::Get.new(path)
|
187
|
+
req.basic_auth(web_auth_user, web_auth_password)
|
188
|
+
|
189
|
+
http.request(req)
|
190
|
+
end
|
191
|
+
|
192
|
+
class FakeResponse < Struct.new(:code, :body)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
# Copyright (c) 2014-2015 Pivotal Software, Inc.
|
198
|
+
# All rights reserved.
|
199
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
200
|
+
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
201
|
+
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
202
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
203
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
204
|
+
# USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@@ -0,0 +1,257 @@
|
|
1
|
+
require 'opsmgr/settings/microbosh/installation_settings'
|
2
|
+
require 'opsmgr/settings/microbosh/product_list'
|
3
|
+
require 'opsmgr/settings/microbosh/job_list'
|
4
|
+
require 'opsmgr/settings/microbosh/property_list'
|
5
|
+
|
6
|
+
module Opsmgr
|
7
|
+
module Api
|
8
|
+
class Result
|
9
|
+
attr_reader :message
|
10
|
+
|
11
|
+
def success?
|
12
|
+
true
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class InstallStatusResult < Result
|
17
|
+
attr_reader :status
|
18
|
+
|
19
|
+
def initialize(status_hash)
|
20
|
+
@status = status_hash['status']
|
21
|
+
status.freeze
|
22
|
+
|
23
|
+
fail(ArgumentError, "Unrecognized status: #{status}") unless %w(failed success running).include?(status)
|
24
|
+
end
|
25
|
+
|
26
|
+
def failed?
|
27
|
+
@status == 'failed'
|
28
|
+
end
|
29
|
+
|
30
|
+
def pending?
|
31
|
+
@status == 'running'
|
32
|
+
end
|
33
|
+
|
34
|
+
def finished_successfully?
|
35
|
+
@status == 'success'
|
36
|
+
end
|
37
|
+
|
38
|
+
def finished?
|
39
|
+
failed? || finished_successfully?
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class InstallationDeletionStatusResult < Result
|
44
|
+
NO_INSTALLATION = 'There is no installation.'.freeze
|
45
|
+
DELETE_IN_PROGRESS = 'Delete in progress'.freeze
|
46
|
+
|
47
|
+
attr_reader :status
|
48
|
+
|
49
|
+
def initialize(status_hash)
|
50
|
+
@status = status_hash['status']
|
51
|
+
end
|
52
|
+
|
53
|
+
def in_progress?
|
54
|
+
status == DELETE_IN_PROGRESS
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
class InstallLogResult < Result
|
59
|
+
attr_reader :log
|
60
|
+
|
61
|
+
def initialize(log_hash)
|
62
|
+
@log = log_hash['logs'].dup.freeze
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
class TriggerInstallResult < Result
|
67
|
+
attr_reader :install_id
|
68
|
+
|
69
|
+
def initialize(install_hash)
|
70
|
+
@install_id = install_hash['install']['id']
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
class ListProductsResult < Result
|
75
|
+
Product = Struct.new(:name, :product_version)
|
76
|
+
|
77
|
+
attr_reader :products
|
78
|
+
|
79
|
+
def initialize(product_hash_array)
|
80
|
+
@products = product_hash_array.map { |p| Product.new(p.fetch('name'), p.fetch('product_version')) }
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
class InstalledProductsResult < Result
|
85
|
+
def initialize(installed_products)
|
86
|
+
@installed_products = installed_products
|
87
|
+
end
|
88
|
+
|
89
|
+
def guid_for(product_type)
|
90
|
+
product_result = installed_products.find { |h| h.name == product_type }
|
91
|
+
product_result ? product_result.fetch('guid') : nil
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
attr_reader :installed_products
|
97
|
+
end
|
98
|
+
|
99
|
+
class InstallationSettingsResult < Result
|
100
|
+
def initialize(install_hash)
|
101
|
+
@install_hash = install_hash
|
102
|
+
end
|
103
|
+
|
104
|
+
def director_ip
|
105
|
+
ips = microbosh_settings.fetch('ips')
|
106
|
+
_, director_ips = ips.each_pair.find { |ip_key, _| ip_key =~ /^director-/ }
|
107
|
+
director_ips.first
|
108
|
+
end
|
109
|
+
|
110
|
+
def director_password
|
111
|
+
microbosh_jobs = microbosh_settings.fetch('jobs')
|
112
|
+
microbosh_job_list = Opsmgr::Settings::Microbosh::JobList.new(microbosh_jobs)
|
113
|
+
director_job = microbosh_job_list.find { |job| job.name == 'director' }
|
114
|
+
properties = director_job.fetch('properties')
|
115
|
+
property_list = Opsmgr::Settings::Microbosh::PropertyList.new(properties)
|
116
|
+
credential_property = property_list.find { |property| property.name == 'director_credentials' }
|
117
|
+
credential_property.fetch('value').fetch('password')
|
118
|
+
end
|
119
|
+
|
120
|
+
def uaa_admin_password
|
121
|
+
jobs = cf_settings.fetch('jobs')
|
122
|
+
job_list = Opsmgr::Settings::Microbosh::JobList.new(jobs)
|
123
|
+
uaa_job = job_list.find { |job| job.name == 'uaa' }
|
124
|
+
properties = uaa_job.fetch('properties')
|
125
|
+
property_list = Opsmgr::Settings::Microbosh::PropertyList.new(properties)
|
126
|
+
credential_property = property_list.find { |property| property.name == 'admin_credentials' }
|
127
|
+
credential_property.fetch('value').fetch('password')
|
128
|
+
end
|
129
|
+
|
130
|
+
def system_domain
|
131
|
+
properties = cc_job.fetch('properties')
|
132
|
+
property_list = Opsmgr::Settings::Microbosh::PropertyList.new(properties)
|
133
|
+
credential_property = property_list.find { |property| property.name == 'system_domain' }
|
134
|
+
credential_property.fetch('value')
|
135
|
+
end
|
136
|
+
|
137
|
+
def apps_domain
|
138
|
+
properties = cc_job.fetch('properties')
|
139
|
+
property_list = Opsmgr::Settings::Microbosh::PropertyList.new(properties)
|
140
|
+
credential_property = property_list.find { |property| property.name == 'apps_domain' }
|
141
|
+
credential_property.fetch('value')
|
142
|
+
end
|
143
|
+
|
144
|
+
def product_version(product_guid)
|
145
|
+
product = products.find { |p| p.guid == product_guid }
|
146
|
+
return nil if product.nil?
|
147
|
+
product.fetch('product_version')
|
148
|
+
end
|
149
|
+
|
150
|
+
def product_version_by_name(product_name)
|
151
|
+
product = products.find { |p| p.name == product_name }
|
152
|
+
return nil if product.nil?
|
153
|
+
product.fetch('product_version')
|
154
|
+
end
|
155
|
+
|
156
|
+
def ops_manager_installation_settings
|
157
|
+
Opsmgr::Settings::Microbosh::InstallationSettings.from_api_result(self)
|
158
|
+
end
|
159
|
+
|
160
|
+
def as_hash
|
161
|
+
install_hash
|
162
|
+
end
|
163
|
+
|
164
|
+
private
|
165
|
+
|
166
|
+
attr_reader :install_hash
|
167
|
+
|
168
|
+
def microbosh_settings
|
169
|
+
products.find { |product| product.name == 'microbosh' } || fail('microbosh not found')
|
170
|
+
end
|
171
|
+
|
172
|
+
def cf_settings
|
173
|
+
products.find { |product| product.name == 'cf' } || fail('cf not found')
|
174
|
+
end
|
175
|
+
|
176
|
+
def products
|
177
|
+
if install_hash.key?('products')
|
178
|
+
Opsmgr::Settings::Microbosh::ProductList.new(install_hash.fetch('products'))
|
179
|
+
elsif install_hash.key?('components')
|
180
|
+
Opsmgr::Settings::Microbosh::ProductList.new(install_hash.fetch('components'))
|
181
|
+
else
|
182
|
+
fail "Unable to find products in OpsManager response. Check installation schema: #{install_hash.inspect}."
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def cc_job
|
187
|
+
cf_settings.fetch('jobs')
|
188
|
+
cf_jobs = cf_settings.fetch('jobs')
|
189
|
+
cf_job_list = Opsmgr::Settings::Microbosh::JobList.new(cf_jobs)
|
190
|
+
cf_job_list.find { |job| job.name == 'cloud_controller' }
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
class ProductManifestResult < Result
|
195
|
+
Product = Struct.new(:name, :version)
|
196
|
+
Stemcell = Struct.new(:name, :version)
|
197
|
+
|
198
|
+
def initialize(manifest_hash)
|
199
|
+
@manifest_hash = manifest_hash
|
200
|
+
end
|
201
|
+
|
202
|
+
def releases
|
203
|
+
manifest_hash.fetch('releases').map { |h| Product.new(h.fetch('name'), h.fetch('version')) }
|
204
|
+
end
|
205
|
+
|
206
|
+
def stemcell
|
207
|
+
stemcell_hash = manifest_hash.fetch('resource_pools').first.fetch('stemcell')
|
208
|
+
Stemcell.new(stemcell_hash.fetch('name'), stemcell_hash.fetch('version'))
|
209
|
+
end
|
210
|
+
|
211
|
+
private
|
212
|
+
|
213
|
+
attr_reader :manifest_hash
|
214
|
+
end
|
215
|
+
|
216
|
+
class CreateFirstUserResult < Result
|
217
|
+
attr_reader :user_id
|
218
|
+
|
219
|
+
def initialize(user_hash)
|
220
|
+
@user_id = user_hash['user']['id']
|
221
|
+
end
|
222
|
+
|
223
|
+
def user_already_existed?
|
224
|
+
false
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
class Error < Result
|
229
|
+
def initialize(message, response)
|
230
|
+
@message = "#{message}:\n#{response.body}"
|
231
|
+
@response = response
|
232
|
+
end
|
233
|
+
|
234
|
+
def success?
|
235
|
+
false
|
236
|
+
end
|
237
|
+
|
238
|
+
private
|
239
|
+
|
240
|
+
attr_reader :response
|
241
|
+
end
|
242
|
+
|
243
|
+
class CreateFirstUserError < Error
|
244
|
+
def user_already_existed?
|
245
|
+
response.code == '401'
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
# Copyright (c) 2014-2015 Pivotal Software, Inc.
|
251
|
+
# All rights reserved.
|
252
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
253
|
+
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
254
|
+
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
255
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
256
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
257
|
+
# USE OR OTHER DEALINGS IN THE SOFTWARE.
|