opsmgr-cgfrost 0.35.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LEGAL.txt +13 -0
- data/README.md +123 -0
- data/lib/opsmgr.rb +12 -0
- data/lib/opsmgr/api/client.rb +116 -0
- data/lib/opsmgr/api/http_client.rb +399 -0
- data/lib/opsmgr/api/results.rb +280 -0
- data/lib/opsmgr/api/version20/endpoints.rb +121 -0
- data/lib/opsmgr/bosh_command_runner.rb +84 -0
- data/lib/opsmgr/cmd/bosh_command.rb +189 -0
- data/lib/opsmgr/cmd/ops_manager.rb +142 -0
- data/lib/opsmgr/environments.rb +106 -0
- data/lib/opsmgr/errand_runner.rb +62 -0
- data/lib/opsmgr/log.rb +70 -0
- data/lib/opsmgr/product_upload_wrapper.rb +71 -0
- data/lib/opsmgr/renderer.rb +23 -0
- data/lib/opsmgr/renderer/aws.rb +148 -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 +56 -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 +90 -0
- data/lib/opsmgr/settings/microbosh/product_list.rb +27 -0
- data/lib/opsmgr/settings/microbosh/property.rb +33 -0
- data/lib/opsmgr/settings/microbosh/property_list.rb +27 -0
- data/lib/opsmgr/tasks.rb +16 -0
- data/lib/opsmgr/tasks/bosh.rake +104 -0
- data/lib/opsmgr/tasks/destroy.rake +42 -0
- data/lib/opsmgr/tasks/info.rake +19 -0
- data/lib/opsmgr/tasks/opsmgr.rake +205 -0
- data/lib/opsmgr/tasks/product.rake +82 -0
- data/lib/opsmgr/ui_helpers/add_first_user_spec.rb +25 -0
- data/lib/opsmgr/ui_helpers/config_helper.rb +38 -0
- data/lib/opsmgr/ui_helpers/delete_installation_spec.rb +41 -0
- data/lib/opsmgr/ui_helpers/delete_product_if_present_spec.rb +37 -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_stemcell_spec.rb +30 -0
- data/lib/opsmgr/ui_helpers/microbosh/configure_microbosh_spec.rb +32 -0
- data/lib/opsmgr/ui_helpers/post_import_configuration_spec.rb +31 -0
- data/lib/opsmgr/ui_helpers/revert_staged_changes_spec.rb +39 -0
- data/lib/opsmgr/ui_helpers/settings_helper.rb +132 -0
- data/lib/opsmgr/ui_helpers/trigger_install_spec.rb +35 -0
- data/lib/opsmgr/ui_helpers/ui_spec_runner.rb +122 -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
- data/sample_env_files/aws.yml +95 -0
- data/sample_env_files/vsphere.yml +87 -0
- metadata +392 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5f5da0a81ed7e7d3eeaa3c69f09af30df22a25a6
|
4
|
+
data.tar.gz: 474e43c4c2f42546df8537d11bb8d4d3f44f7381
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bd2269a6edd6809c4b143c1877902d06106186ad01174b5f75a3a2ac110408c07eb53b8045aaafdb43cedbe8df7b48a5fb1c4e6abb77e4eb80b00fe2a4e9de38
|
7
|
+
data.tar.gz: d873d303f5bc961eb1fd7867ea2aa20953c9c9ac567e32f4144316741aa43ace02629018404d47342040e9ad108180b69afa957b1598ddc4c27454c79a5babc8
|
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,123 @@
|
|
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
|
+
## Prerequisites
|
6
|
+
|
7
|
+
### Ruby
|
8
|
+
Install ruby on your machine. Two popular ways to install ruby and manage your ruby installations are:
|
9
|
+
|
10
|
+
- ruby-install (https://github.com/postmodern/ruby-install) / chruby (https://github.com/postmodern/chruby)
|
11
|
+
- rbenv (https://github.com/rbenv/rbenv)
|
12
|
+
|
13
|
+
The rest of these instructions assume you have already installed the correct ruby version and are familiar with its use.
|
14
|
+
|
15
|
+
## Setup
|
16
|
+
|
17
|
+
### Command-Line
|
18
|
+
Run:
|
19
|
+
```shell
|
20
|
+
gem install opsmgr
|
21
|
+
```
|
22
|
+
|
23
|
+
This will install the opsmgr Gem and all dependencies.
|
24
|
+
|
25
|
+
### Within Ruby Code
|
26
|
+
To install, add this line to your Gemfile and run bundle install:
|
27
|
+
```ruby
|
28
|
+
gem 'opsmgr'
|
29
|
+
```
|
30
|
+
|
31
|
+
## Usage
|
32
|
+
|
33
|
+
### From the Command-Line
|
34
|
+
To see a list of all available rake tasks:
|
35
|
+
|
36
|
+
1. Create a Rakefile:
|
37
|
+
```ruby
|
38
|
+
require 'opsmgr/tasks'
|
39
|
+
```
|
40
|
+
|
41
|
+
1. Run:
|
42
|
+
```shell
|
43
|
+
rake -T
|
44
|
+
```
|
45
|
+
|
46
|
+
### Within Ruby Code
|
47
|
+
Require the appropriate part of the opsmgr library. See below for the required files for each task.
|
48
|
+
|
49
|
+
## Environment Configuration File
|
50
|
+
The expected location of the environment configuration file is `../environment/metadata`. If you need to specify an alternative location, you can use either the `ENV_CONFIG_FILE` or `ENV_DIRECTORY` environment variables. If you use the `ENV_DIRECTORY` environment variable to point to a directory of configuration files, the files inside that directory must be named according to the name of the environment, with the extension `.yml`.
|
51
|
+
|
52
|
+
Example AWS and vSphere environment files are included in the gem.
|
53
|
+
|
54
|
+
## Basic Deployment of Ops Manager with Rake Tasks
|
55
|
+
|
56
|
+
### Clean existing environment
|
57
|
+
If you want to start fresh, you can clear out your environment completely:
|
58
|
+
|
59
|
+
**WARNING: this destroys all VMs in the environment, including but not limited to Ops Manager, µBOSH and Runtime**
|
60
|
+
|
61
|
+
Note: If you used the old version of opsmgr tasks to create this environment, then you need to use that version to clean it. The new version does not correctly clean out deployments from the old version.
|
62
|
+
|
63
|
+
```
|
64
|
+
bundle exec rake opsmgr:destroy[environment]
|
65
|
+
```
|
66
|
+
|
67
|
+
### Download an Ops Manager Image
|
68
|
+
Obtain the Ops Manager Image you need from [Pivotal Network](https://network.pivotal.io). If you need a newer version than is available there, consult the Ops Manager team.
|
69
|
+
|
70
|
+
### Prepare The Environment (AWS-only)
|
71
|
+
This will spin up a cloudformation stack; because it provisions an RDS instance, it can take around half an hour.
|
72
|
+
|
73
|
+
```
|
74
|
+
bundle exec rake opsmgr:prepare[environment]
|
75
|
+
```
|
76
|
+
|
77
|
+
### Deploy the Ops Manager
|
78
|
+
You need to specify the path to the Ops Manager image you want to use/have just downloaded.
|
79
|
+
|
80
|
+
```
|
81
|
+
bundle exec rake opsmgr:install[environment,path_to_ops_manager_image]
|
82
|
+
```
|
83
|
+
|
84
|
+
### Configure and Deploy Microbosh
|
85
|
+
You need to specify the major and minor version of Ops Manager in these commands.
|
86
|
+
|
87
|
+
`<OM version>` is the Ops Manager version. Opsmgr supports Ops Manager `1.4`, `1.5`, and `1.6`.
|
88
|
+
|
89
|
+
`<wait time>` is number of minutes to wait for install, recommended wait time is `45`
|
90
|
+
|
91
|
+
```
|
92
|
+
bundle exec rake opsmgr:add_first_user[environment,<OM version>]
|
93
|
+
bundle exec rake opsmgr:microbosh:configure[environment,<OM version>]
|
94
|
+
bundle exec rake opsmgr:trigger_install[environment,<OM version>,<wait time>]
|
95
|
+
```
|
96
|
+
|
97
|
+
## Advanced Tasks
|
98
|
+
|
99
|
+
### Export the installation from Ops Manager
|
100
|
+
`<OM version>` is the Ops Manager version. Opsmgr supports Ops Manager `1.4`, `1.5`, and `1.6`.
|
101
|
+
|
102
|
+
`<file name>` local file name to save the exported installation file
|
103
|
+
|
104
|
+
```
|
105
|
+
bundle exec rake opsmgr:export_installation[environment,<OM version>,<file name>]
|
106
|
+
```
|
107
|
+
|
108
|
+
### Import an installation to Ops Manager
|
109
|
+
`<OM version>` is the Ops Manager version. Opsmgr supports Ops Manager `1.4`, `1.5`, and `1.6`.
|
110
|
+
|
111
|
+
`<file name>` local file name of the installation file to import
|
112
|
+
|
113
|
+
```
|
114
|
+
bundle exec rake opsmgr:import_installation[environment,<OM version>,<file name>]
|
115
|
+
```
|
116
|
+
|
117
|
+
### Destroy only the Ops Manager VM
|
118
|
+
|
119
|
+
Commonly done when testing export/import scenarios
|
120
|
+
|
121
|
+
```
|
122
|
+
bundle exec rake opsmgr:destroy:opsmgr[environment]
|
123
|
+
```
|
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,116 @@
|
|
1
|
+
require 'backport_refinements'
|
2
|
+
using OpsManagerUiDrivers::BackportRefinements
|
3
|
+
|
4
|
+
require 'json'
|
5
|
+
require 'opsmgr/api/http_client'
|
6
|
+
require 'opsmgr/api/results'
|
7
|
+
require 'opsmgr/settings/microbosh/product_list'
|
8
|
+
|
9
|
+
module Opsmgr
|
10
|
+
module Api
|
11
|
+
class Client
|
12
|
+
attr_reader :environment_name
|
13
|
+
|
14
|
+
def initialize(environment, om_version)
|
15
|
+
@http_client = HttpClient.build(environment, om_version)
|
16
|
+
@environment_name = environment.settings.dig('name').freeze
|
17
|
+
end
|
18
|
+
|
19
|
+
def installation_settings
|
20
|
+
response = http_client.installation_settings
|
21
|
+
if response.code == '200'
|
22
|
+
InstallationSettingsResult.new(JSON.parse(response.body))
|
23
|
+
else
|
24
|
+
Error.new('Error viewing current installation settings', response)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# .pivotal file is referred to as a "product" but the Tempest developers call it a "component"
|
29
|
+
def upload_component(path)
|
30
|
+
response = http_client.upload_component(path)
|
31
|
+
basic_success_or_error("Error uploading #{path}", response)
|
32
|
+
end
|
33
|
+
|
34
|
+
def add_product(product_name, version)
|
35
|
+
response = http_client.add_product(product_name, version)
|
36
|
+
basic_success_or_error("Error adding '#{product_name} #{version}'", response)
|
37
|
+
end
|
38
|
+
|
39
|
+
def root_ca_certificate
|
40
|
+
response = http_client.root_ca_certificate
|
41
|
+
if response.code == '200'
|
42
|
+
JSON.parse(response.body)['root_ca_certificate_pem']
|
43
|
+
else
|
44
|
+
Error.new('Error retrieving the root ca certificate', response)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def upgrade_product(product_guid, to_version)
|
49
|
+
response = http_client.upgrade_product(product_guid, to_version)
|
50
|
+
basic_success_or_error("Error upgrading '#{product_guid}' to '#{to_version}'", response)
|
51
|
+
end
|
52
|
+
|
53
|
+
def download_staged_manifest(product_guid)
|
54
|
+
response = http_client.download_staged_manifest(product_guid)
|
55
|
+
if response.code == '200'
|
56
|
+
StagedManifestResult.new(response.body)
|
57
|
+
else
|
58
|
+
Error.new("Error downloading staged manifest for '#{product_guid}'", response)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def list_products
|
63
|
+
response = http_client.list_products
|
64
|
+
if response.code == '200'
|
65
|
+
ListProductsResult.new(JSON.parse(response.body))
|
66
|
+
else
|
67
|
+
Error.new('Error listing products', response)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def installed_products
|
72
|
+
response = http_client.installed_products
|
73
|
+
if response.code == '200'
|
74
|
+
InstalledProductsResult.new(Opsmgr::Settings::Microbosh::ProductList.new(JSON.parse(response.body)))
|
75
|
+
else
|
76
|
+
Error.new('Error listing installed products', response)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def delete_unused_products
|
81
|
+
response = http_client.delete_unused_products
|
82
|
+
basic_success_or_error('There was an error deleting the unused products:', response)
|
83
|
+
end
|
84
|
+
|
85
|
+
def basic_success_or_error(message, response)
|
86
|
+
if response.code == '200'
|
87
|
+
Result.new
|
88
|
+
else
|
89
|
+
Error.new(message, response)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def import_installation(path, password)
|
94
|
+
response = http_client.import_installation(path, password)
|
95
|
+
basic_success_or_error("Error importing #{path}", response)
|
96
|
+
end
|
97
|
+
|
98
|
+
def import_stemcell(path)
|
99
|
+
response = http_client.import_stemcell(path)
|
100
|
+
basic_success_or_error("Error importing stemcell #{path}", response)
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
attr_reader :http_client
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
# Copyright (c) 2014-2015 Pivotal Software, Inc.
|
110
|
+
# All rights reserved.
|
111
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
112
|
+
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
113
|
+
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
114
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
115
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
116
|
+
# USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@@ -0,0 +1,399 @@
|
|
1
|
+
# rubocop:disable Metrics/ClassLength
|
2
|
+
require 'backport_refinements'
|
3
|
+
using OpsManagerUiDrivers::BackportRefinements
|
4
|
+
|
5
|
+
require 'net/http'
|
6
|
+
require 'net/http/post/multipart'
|
7
|
+
require 'json'
|
8
|
+
require 'open4'
|
9
|
+
require 'opsmgr/log'
|
10
|
+
require 'opsmgr/api/version20/endpoints'
|
11
|
+
require 'uaa'
|
12
|
+
|
13
|
+
# noinspection RubyResolve
|
14
|
+
module Opsmgr
|
15
|
+
module Api
|
16
|
+
class HttpClient
|
17
|
+
include Loggable
|
18
|
+
attr_reader :uri, :environment, :endpoints
|
19
|
+
|
20
|
+
def self.build(environment, om_version)
|
21
|
+
new(environment, Opsmgr::Api::Version20::Endpoints.new, om_version)
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize(environment, endpoints, om_version)
|
25
|
+
@environment = environment
|
26
|
+
@uri = URI.parse(environment.settings.dig('ops_manager', 'url'))
|
27
|
+
@endpoints = endpoints
|
28
|
+
@om_version = om_version
|
29
|
+
end
|
30
|
+
|
31
|
+
def upload_product_installation_settings(settings_file_path)
|
32
|
+
req = Net::HTTP::Post::Multipart.new(
|
33
|
+
endpoints.installation_settings_post_path,
|
34
|
+
'installation[file]' =>
|
35
|
+
UploadIO.new(
|
36
|
+
settings_file_path,
|
37
|
+
'application/octet-stream',
|
38
|
+
File.basename(settings_file_path)
|
39
|
+
)
|
40
|
+
)
|
41
|
+
|
42
|
+
add_auth_header(req)
|
43
|
+
|
44
|
+
http.request(req)
|
45
|
+
end
|
46
|
+
|
47
|
+
def upload_component(product_path)
|
48
|
+
# We ran into a possible Net::HTTP bug where Ruby would always drop the connection while waiting for the
|
49
|
+
# uploaded zip file to unzip. Curl behaved correctly, but curb (Ruby bindings for libcurl) did not behave
|
50
|
+
# well with WebMock, so here we are.
|
51
|
+
upload_component_command =
|
52
|
+
%W(
|
53
|
+
curl -k
|
54
|
+
--silent
|
55
|
+
--fail
|
56
|
+
#{uri}#{endpoints.upload_product_path}
|
57
|
+
-F #{endpoints.upload_product_form_key}[file]=@#{product_path}
|
58
|
+
-X POST
|
59
|
+
)
|
60
|
+
|
61
|
+
if Gem::Version.new(@om_version) >= Gem::Version.new('1.7')
|
62
|
+
log.info('using oauth')
|
63
|
+
token = get_oauth_token(web_auth_user)
|
64
|
+
upload_component_command.push("-H")
|
65
|
+
upload_component_command.push("Authorization: #{token}")
|
66
|
+
else
|
67
|
+
log.info('using basic auth')
|
68
|
+
upload_component_command.push("-u")
|
69
|
+
upload_component_command.push("#{web_auth_user}:#{web_auth_password}")
|
70
|
+
end
|
71
|
+
|
72
|
+
log.info('uploading product')
|
73
|
+
|
74
|
+
error = nil
|
75
|
+
status =
|
76
|
+
Open4.popen4(*upload_component_command) do |_, _, stdout, stderr|
|
77
|
+
log.info(stdout.read)
|
78
|
+
error = stderr.read
|
79
|
+
end
|
80
|
+
|
81
|
+
if status.success?
|
82
|
+
FakeResponse.new('200', '{}')
|
83
|
+
else
|
84
|
+
error_code = (error.match(/^\< HTTP\/.* (\d+) /) || [nil, '???'])[1]
|
85
|
+
FakeResponse.new(error_code, error)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def root_ca_certificate
|
90
|
+
req = Net::HTTP::Get.new(endpoints.root_ca_certificate_path)
|
91
|
+
add_auth_header(req)
|
92
|
+
|
93
|
+
http.request(req)
|
94
|
+
end
|
95
|
+
|
96
|
+
def add_product(product_name, version)
|
97
|
+
req = Net::HTTP::Post.new(endpoints.add_product_path)
|
98
|
+
req.set_form_data('name' => product_name, 'product_version' => version)
|
99
|
+
add_auth_header(req)
|
100
|
+
|
101
|
+
http.request(req)
|
102
|
+
end
|
103
|
+
|
104
|
+
def upgrade_product(product_guid, to_version)
|
105
|
+
req = Net::HTTP::Put.new(endpoints.upgrade_product_path(product_guid))
|
106
|
+
req.set_form_data('to_version' => to_version)
|
107
|
+
add_auth_header(req)
|
108
|
+
|
109
|
+
http.request(req)
|
110
|
+
end
|
111
|
+
|
112
|
+
def download_staged_manifest(product_guid)
|
113
|
+
req = Net::HTTP::Get.new(endpoints.download_staged_manifest(product_guid))
|
114
|
+
add_auth_header(req)
|
115
|
+
|
116
|
+
http.request(req)
|
117
|
+
end
|
118
|
+
|
119
|
+
def trigger_install
|
120
|
+
req = Net::HTTP::Post.new(endpoints.install_post_path)
|
121
|
+
req.body = ''
|
122
|
+
add_auth_header(req)
|
123
|
+
|
124
|
+
http.request(req)
|
125
|
+
end
|
126
|
+
|
127
|
+
# components are both uploaded AND configured AND deployed
|
128
|
+
def list_components
|
129
|
+
get_with_basic_auth(endpoints.list_components_path)
|
130
|
+
end
|
131
|
+
|
132
|
+
# products are uploaded but not necessarily configured or deployed
|
133
|
+
def list_products
|
134
|
+
get_with_basic_auth(endpoints.list_products_path)
|
135
|
+
end
|
136
|
+
|
137
|
+
# products that have been uploaded, configured, and installed
|
138
|
+
def installed_products
|
139
|
+
get_with_basic_auth(endpoints.installed_products_path)
|
140
|
+
end
|
141
|
+
|
142
|
+
def product_manifest(product_guid)
|
143
|
+
get_with_basic_auth(endpoints.product_manifest_path(product_guid))
|
144
|
+
end
|
145
|
+
|
146
|
+
def installation_settings
|
147
|
+
get_with_basic_auth(endpoints.installation_settings_get_path)
|
148
|
+
end
|
149
|
+
|
150
|
+
def installation_delete
|
151
|
+
req = Net::HTTP::Delete.new(endpoints.installation_path)
|
152
|
+
add_auth_header(req)
|
153
|
+
|
154
|
+
http.request(req)
|
155
|
+
end
|
156
|
+
|
157
|
+
def installation_deletion_status
|
158
|
+
get_with_basic_auth(endpoints.installation_deletion_status_path)
|
159
|
+
end
|
160
|
+
|
161
|
+
def create_the_first_user
|
162
|
+
if Gem::Version.new(@om_version) >= Gem::Version.new('1.6')
|
163
|
+
req = Net::HTTP::Post.new(endpoints.api_setup_path)
|
164
|
+
req.set_form_data(
|
165
|
+
'setup[user_name]' => web_auth_user,
|
166
|
+
'setup[password]' => web_auth_password,
|
167
|
+
'setup[password_confirmation]' => web_auth_password,
|
168
|
+
'setup[eula_accepted]' => true
|
169
|
+
)
|
170
|
+
else
|
171
|
+
req = Net::HTTP::Post.new(endpoints.api_user_path)
|
172
|
+
req.set_form_data(
|
173
|
+
'user[user_name]' => web_auth_user,
|
174
|
+
'user[password]' => web_auth_password,
|
175
|
+
'user[password_confirmation]' => web_auth_password,
|
176
|
+
)
|
177
|
+
end
|
178
|
+
|
179
|
+
http.request(req)
|
180
|
+
end
|
181
|
+
|
182
|
+
def install_status(install_id)
|
183
|
+
get_with_basic_auth(endpoints.show_installation_status(install_id))
|
184
|
+
end
|
185
|
+
|
186
|
+
def install_log(install_id)
|
187
|
+
get_with_basic_auth(endpoints.installation_log_path(install_id))
|
188
|
+
end
|
189
|
+
|
190
|
+
def mark_product_for_deletion(product_guid)
|
191
|
+
req = Net::HTTP::Delete.new(endpoints.mark_for_deletion_path(product_guid))
|
192
|
+
add_auth_header(req)
|
193
|
+
|
194
|
+
http.request(req)
|
195
|
+
end
|
196
|
+
|
197
|
+
def delete_unused_products
|
198
|
+
req = Net::HTTP::Delete.new(endpoints.list_products_path)
|
199
|
+
add_auth_header(req)
|
200
|
+
|
201
|
+
http.request(req)
|
202
|
+
end
|
203
|
+
|
204
|
+
def version
|
205
|
+
endpoints.version
|
206
|
+
end
|
207
|
+
|
208
|
+
def import_installation(installation_file, password)
|
209
|
+
create_the_first_user unless Gem::Version.new(@om_version) >= Gem::Version.new('1.7')
|
210
|
+
|
211
|
+
log.info('uploading the installation file')
|
212
|
+
req = Net::HTTP::Post::Multipart.new(
|
213
|
+
endpoints.import_installation_path,
|
214
|
+
'installation[file]' =>
|
215
|
+
UploadIO.new(
|
216
|
+
installation_file,
|
217
|
+
'application/octet-stream',
|
218
|
+
File.basename(installation_file)
|
219
|
+
),
|
220
|
+
import_secret_parameter_name => password
|
221
|
+
)
|
222
|
+
|
223
|
+
# The post-1.7 import happens before a user has been created so we cannot authenticate.
|
224
|
+
add_auth_header(req) unless Gem::Version.new(@om_version) >= Gem::Version.new('1.7')
|
225
|
+
|
226
|
+
response = http.request(req)
|
227
|
+
|
228
|
+
if Gem::Version.new(@om_version) == Gem::Version.new('1.7')
|
229
|
+
wait_for_uaa_to_be_available
|
230
|
+
|
231
|
+
ensure_env_admin_user_exists
|
232
|
+
end
|
233
|
+
|
234
|
+
response
|
235
|
+
end
|
236
|
+
|
237
|
+
def wait_for_uaa_to_be_available(sleep_interval = 10, max_retry_count = 24)
|
238
|
+
retry_count = 0
|
239
|
+
|
240
|
+
loop do
|
241
|
+
request = Net::HTTP::Get.new(
|
242
|
+
endpoints.login_ensure_availability
|
243
|
+
)
|
244
|
+
|
245
|
+
response = http.request(request)
|
246
|
+
|
247
|
+
http_location = response['location']
|
248
|
+
|
249
|
+
break if response.code == '302' && http_location == auth_redirect_location
|
250
|
+
|
251
|
+
retry_count += 1
|
252
|
+
|
253
|
+
if retry_count >= max_retry_count
|
254
|
+
retry_wait_time = sleep_interval * retry_count
|
255
|
+
|
256
|
+
raise("Timed out waiting for UAA to be available after #{retry_wait_time} seconds")
|
257
|
+
end
|
258
|
+
|
259
|
+
Kernel.sleep(sleep_interval)
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
def ensure_env_admin_user_exists
|
264
|
+
token = get_oauth_token('admin')
|
265
|
+
|
266
|
+
create_env_admin_user(token) unless verify_if_env_admin_user_exists?(token)
|
267
|
+
end
|
268
|
+
|
269
|
+
def verify_if_env_admin_user_exists?(token)
|
270
|
+
request = Net::HTTP::Get.new(
|
271
|
+
endpoints.uaa_get_user_by_username_path(web_auth_user)
|
272
|
+
)
|
273
|
+
request['Authorization'] = token
|
274
|
+
|
275
|
+
response = http.request(request)
|
276
|
+
|
277
|
+
if response.code != '200'
|
278
|
+
raise("Invalid response from UAA: #{response.code}")
|
279
|
+
end
|
280
|
+
|
281
|
+
reply = JSON.parse(response.body)
|
282
|
+
|
283
|
+
if reply['resources'].nil?
|
284
|
+
raise("Invalid response body from UAA: #{response.body}")
|
285
|
+
end
|
286
|
+
|
287
|
+
!reply['resources'].empty?
|
288
|
+
end
|
289
|
+
|
290
|
+
def create_env_admin_user(token)
|
291
|
+
request = Net::HTTP::Post.new(
|
292
|
+
endpoints.uaa_create_user
|
293
|
+
)
|
294
|
+
request['Content-Type'] = 'application/json'
|
295
|
+
request['Authorization'] = token
|
296
|
+
request.body = {
|
297
|
+
userName: web_auth_user,
|
298
|
+
password: web_auth_password,
|
299
|
+
emails: [
|
300
|
+
{ value: web_auth_user }
|
301
|
+
]
|
302
|
+
}.to_json
|
303
|
+
|
304
|
+
response = http.request(request)
|
305
|
+
|
306
|
+
if response.code != '201'
|
307
|
+
raise("Unexpected response from UAA: code #{response.code}, body: #{response.body}")
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
def import_secret_parameter_name
|
312
|
+
Gem::Version.new(@om_version) >= Gem::Version.new('1.7') ? 'passphrase' : 'password'
|
313
|
+
end
|
314
|
+
|
315
|
+
def import_stemcell(stemcell_file)
|
316
|
+
req = Net::HTTP::Post::Multipart.new(
|
317
|
+
endpoints.import_stemcell_path,
|
318
|
+
'stemcell[file]' =>
|
319
|
+
UploadIO.new(
|
320
|
+
stemcell_file,
|
321
|
+
'application/octet-stream',
|
322
|
+
File.basename(stemcell_file)
|
323
|
+
)
|
324
|
+
)
|
325
|
+
|
326
|
+
add_auth_header(req)
|
327
|
+
|
328
|
+
http.request(req)
|
329
|
+
end
|
330
|
+
|
331
|
+
def read_timeout
|
332
|
+
environment.settings.dig('iaas_type') != 'vcloud' ? 600 : 3600
|
333
|
+
end
|
334
|
+
|
335
|
+
def auth_redirect_location
|
336
|
+
host = environment.settings.dig('ops_manager', 'url')
|
337
|
+
|
338
|
+
host.concat('/') unless host.end_with? '/'
|
339
|
+
|
340
|
+
host+'auth/cloudfoundry'
|
341
|
+
end
|
342
|
+
|
343
|
+
private
|
344
|
+
|
345
|
+
def add_auth_header(request)
|
346
|
+
if Gem::Version.new(@om_version) >= Gem::Version.new('1.7')
|
347
|
+
log.info('using oauth')
|
348
|
+
token = get_oauth_token(web_auth_user)
|
349
|
+
request['Authorization'] = token
|
350
|
+
else
|
351
|
+
log.info('using basic auth')
|
352
|
+
request.basic_auth(web_auth_user, web_auth_password)
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
def get_oauth_token(user)
|
357
|
+
target_url = environment.settings.dig('ops_manager', 'url') + '/uaa'
|
358
|
+
token_issuer = CF::UAA::TokenIssuer.new(target_url, 'opsman', nil, skip_ssl_validation: true)
|
359
|
+
token_issuer.owner_password_grant(user, web_auth_password).auth_header
|
360
|
+
end
|
361
|
+
|
362
|
+
def web_auth_user
|
363
|
+
environment.settings.dig('ops_manager', 'username')
|
364
|
+
end
|
365
|
+
|
366
|
+
def web_auth_password
|
367
|
+
environment.settings.dig('ops_manager', 'password')
|
368
|
+
end
|
369
|
+
|
370
|
+
def http
|
371
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
372
|
+
if uri.scheme == 'https'
|
373
|
+
http.use_ssl = true
|
374
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
375
|
+
end
|
376
|
+
http.read_timeout = read_timeout
|
377
|
+
http
|
378
|
+
end
|
379
|
+
|
380
|
+
def get_with_basic_auth(path)
|
381
|
+
req = Net::HTTP::Get.new(path)
|
382
|
+
add_auth_header(req)
|
383
|
+
|
384
|
+
http.request(req)
|
385
|
+
end
|
386
|
+
|
387
|
+
class FakeResponse < Struct.new(:code, :body)
|
388
|
+
end
|
389
|
+
end
|
390
|
+
end
|
391
|
+
end
|
392
|
+
# Copyright (c) 2014-2015 Pivotal Software, Inc.
|
393
|
+
# All rights reserved.
|
394
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
395
|
+
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
396
|
+
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
397
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
398
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
399
|
+
# USE OR OTHER DEALINGS IN THE SOFTWARE.
|