prof 0.29.3
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 +13 -0
- data/lib/prof/cloud_foundry.rb +145 -0
- data/lib/prof/environment/cloud_foundry.rb +150 -0
- data/lib/prof/environment/pcf_drinks.rb +156 -0
- data/lib/prof/environment_manager.rb +93 -0
- data/lib/prof/external_spec/helpers/capybara.rb +58 -0
- data/lib/prof/external_spec/helpers/debug.rb +53 -0
- data/lib/prof/external_spec/helpers/file_helper.rb +35 -0
- data/lib/prof/external_spec/helpers/product_path.rb +23 -0
- data/lib/prof/external_spec/shared_examples/deployment.rb +23 -0
- data/lib/prof/external_spec/shared_examples/ops_manager_upgrade.rb +32 -0
- data/lib/prof/external_spec/shared_examples/service.rb +105 -0
- data/lib/prof/external_spec/shared_examples/service_broker.rb +25 -0
- data/lib/prof/external_spec/spec_helper.rb +35 -0
- data/lib/prof/marketplace_service.rb +20 -0
- data/lib/prof/matchers/metadata.rb +180 -0
- data/lib/prof/matchers/only_support_ssl_with_cipher_set.rb +102 -0
- data/lib/prof/matchers/ssl.rb +67 -0
- data/lib/prof/matchers/tile_configuration.rb +47 -0
- data/lib/prof/ops_manager/rails_500_error.rb +15 -0
- data/lib/prof/ops_manager/web_app_internals/page/checkbox_field.rb +38 -0
- data/lib/prof/ops_manager/web_app_internals/page/click_field.rb +40 -0
- data/lib/prof/ops_manager/web_app_internals/page/dashboard.rb +100 -0
- data/lib/prof/ops_manager/web_app_internals/page/flash_message.rb +53 -0
- data/lib/prof/ops_manager/web_app_internals/page/form.rb +130 -0
- data/lib/prof/ops_manager/web_app_internals/page/form_error.rb +43 -0
- data/lib/prof/ops_manager/web_app_internals/page/form_field.rb +51 -0
- data/lib/prof/ops_manager/web_app_internals/page/form_fields.rb +35 -0
- data/lib/prof/ops_manager/web_app_internals/page/installation_progress.rb +149 -0
- data/lib/prof/ops_manager/web_app_internals/page/login.rb +53 -0
- data/lib/prof/ops_manager/web_app_internals/page/modal.rb +85 -0
- data/lib/prof/ops_manager/web_app_internals/page/rails_500.rb +41 -0
- data/lib/prof/ops_manager/web_app_internals/page/select_field.rb +27 -0
- data/lib/prof/ops_manager/web_app_internals/page/tile_settings.rb +105 -0
- data/lib/prof/ops_manager/web_app_internals.rb +63 -0
- data/lib/prof/ops_manager.rb +141 -0
- data/lib/prof/ops_manager_log_fetcher.rb +30 -0
- data/lib/prof/product.rb +59 -0
- data/lib/prof/pushed_test_app.rb +40 -0
- data/lib/prof/service_instance.rb +21 -0
- data/lib/prof/ssh_gateway.rb +104 -0
- data/lib/prof/ssl/check.rb +79 -0
- data/lib/prof/ssl/cipher_set.rb +56 -0
- data/lib/prof/ssl/result.rb +27 -0
- data/lib/prof/ssl/results.rb +74 -0
- data/lib/prof/test_app.rb +19 -0
- data/lib/prof/tile.rb +25 -0
- data/lib/prof/uaa_client.rb +66 -0
- data/lib/prof/version.rb +13 -0
- metadata +403 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 40bcbedb4a82be8debb7fb4b120faa9ea9480d10
|
4
|
+
data.tar.gz: b3660e7602268aaa31f487c29e5b8820d85f4dab
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 105928b4e69b0d47da3ae17a2e591bd09aa417899b2721297ae85d65387f755ed50e15252af1581bc8c0152d76242d25e0705797c9b1a2fb3167634432e26a92
|
7
|
+
data.tar.gz: 715dd614e05306fa15711845cfb03a54132e025211c5c1c0aceb87a38f4c0d8ec37cc7ced1bb02f4a6a177ab40463430bd700235a2d59a7ad4023be19d0d500e
|
data/LEGAL
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.
|
@@ -0,0 +1,145 @@
|
|
1
|
+
# Copyright (c) 2014-2015 Pivotal Software, Inc.
|
2
|
+
# All rights reserved.
|
3
|
+
# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
4
|
+
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
5
|
+
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
6
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
7
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
8
|
+
# USE OR OTHER DEALINGS IN THE SOFTWARE.
|
9
|
+
#
|
10
|
+
|
11
|
+
require 'forwardable'
|
12
|
+
require 'hula/cloud_foundry'
|
13
|
+
|
14
|
+
require 'prof/marketplace_service'
|
15
|
+
require 'prof/pushed_test_app'
|
16
|
+
require 'prof/service_instance'
|
17
|
+
|
18
|
+
module Prof
|
19
|
+
class CloudFoundry
|
20
|
+
extend Forwardable
|
21
|
+
|
22
|
+
attr_reader :api_url, :domain, :username, :password
|
23
|
+
|
24
|
+
def_delegators :hula_cloud_foundry,
|
25
|
+
:add_public_service_broker,
|
26
|
+
:app_env,
|
27
|
+
:create_org,
|
28
|
+
:target_org,
|
29
|
+
:create_space,
|
30
|
+
:target_space,
|
31
|
+
:create_and_target_org,
|
32
|
+
:create_and_target_space,
|
33
|
+
:create_service_instance,
|
34
|
+
:delete_org,
|
35
|
+
:delete_space,
|
36
|
+
:delete_service_instance_and_unbind,
|
37
|
+
:push_app_and_start,
|
38
|
+
:remove_service_broker,
|
39
|
+
:service_brokers,
|
40
|
+
:setup_permissive_security_group,
|
41
|
+
:app_vcap_services,
|
42
|
+
:marketplace
|
43
|
+
|
44
|
+
def initialize(opts = {})
|
45
|
+
@domain = opts.fetch(:domain)
|
46
|
+
@api_url = opts.fetch(:api_url) { "https://api.#{domain}" }
|
47
|
+
@username = opts.fetch(:username)
|
48
|
+
@password = opts.fetch(:password)
|
49
|
+
end
|
50
|
+
|
51
|
+
def push_app(app, &_block)
|
52
|
+
pushed_app_name = "cf-app-#{SecureRandom.hex(4)}"
|
53
|
+
deployed_app = PushedTestApp.new(name: pushed_app_name, url: hula_cloud_foundry.url_for_app(pushed_app_name))
|
54
|
+
|
55
|
+
hula_cloud_foundry.push_app(app.path, deployed_app.name)
|
56
|
+
|
57
|
+
yield deployed_app
|
58
|
+
ensure
|
59
|
+
hula_cloud_foundry.delete_app deployed_app.name
|
60
|
+
end
|
61
|
+
|
62
|
+
def enable_diego_and_start_app(app)
|
63
|
+
hula_cloud_foundry.enable_diego_for_app(app.name)
|
64
|
+
hula_cloud_foundry.start_app(app.name)
|
65
|
+
end
|
66
|
+
|
67
|
+
def push_app_and_bind_with_service(app, service, &_block)
|
68
|
+
push_app(app) do |pushed_app|
|
69
|
+
provision_service(service) do |service_instance|
|
70
|
+
bind_service_and_run(pushed_app, service_instance) do
|
71
|
+
yield pushed_app, service_instance
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def push_app_and_bind_with_service_instance(app, service_instance, &_block)
|
78
|
+
push_app(app) do |pushed_app|
|
79
|
+
bind_service_and_run(pushed_app, service_instance) do
|
80
|
+
yield pushed_app, service_instance
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def bind_service_and_run(pushed_app, service_instance, &_block)
|
86
|
+
hula_cloud_foundry.bind_app_to_service(pushed_app.name, service_instance.name)
|
87
|
+
hula_cloud_foundry.start_app(pushed_app.name)
|
88
|
+
|
89
|
+
yield
|
90
|
+
|
91
|
+
hula_cloud_foundry.unbind_app_from_service(pushed_app.name, service_instance.name)
|
92
|
+
end
|
93
|
+
|
94
|
+
def provision_and_create_service_key(service, &_block)
|
95
|
+
provision_service(service) do |service_instance|
|
96
|
+
create_service_key(service_instance) do |service_key, service_key_data|
|
97
|
+
yield service_instance, service_key, service_key_data
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def list_service_keys(service_instance)
|
103
|
+
hula_cloud_foundry.list_service_keys(service_instance.name)
|
104
|
+
end
|
105
|
+
|
106
|
+
def create_service_key(service_instance, &_block)
|
107
|
+
service_key_name = "#{service_instance.name}-#{SecureRandom.hex(4)}"
|
108
|
+
hula_cloud_foundry.create_service_key(service_instance.name, service_key_name)
|
109
|
+
service_key_raw = hula_cloud_foundry.service_key(service_instance.name, service_key_name)
|
110
|
+
service_key_data = JSON.parse(
|
111
|
+
service_key_raw.split("\n").slice(2..-1).join
|
112
|
+
)
|
113
|
+
|
114
|
+
yield service_key_name, service_key_data
|
115
|
+
|
116
|
+
hula_cloud_foundry.delete_service_key(service_instance.name, service_key_name)
|
117
|
+
end
|
118
|
+
|
119
|
+
def delete_service_key(service_instance, service_key)
|
120
|
+
hula_cloud_foundry.delete_service_key(service_instance.name, service_key)
|
121
|
+
end
|
122
|
+
|
123
|
+
def provision_service(service, &_block)
|
124
|
+
service_instance = ServiceInstance.new
|
125
|
+
|
126
|
+
hula_cloud_foundry.create_service_instance(service.name, service_instance.name, service.plan)
|
127
|
+
|
128
|
+
yield service_instance if block_given?
|
129
|
+
|
130
|
+
ensure
|
131
|
+
hula_cloud_foundry.delete_service_instance_and_unbind(service_instance.name)
|
132
|
+
end
|
133
|
+
|
134
|
+
private
|
135
|
+
|
136
|
+
def hula_cloud_foundry
|
137
|
+
@hula_cloud_foundry ||= Hula::CloudFoundry.new(
|
138
|
+
api_url: api_url,
|
139
|
+
domain: domain,
|
140
|
+
username: username,
|
141
|
+
password: password
|
142
|
+
)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
# Copyright (c) 2014-2015 Pivotal Software, Inc.
|
2
|
+
# All rights reserved.
|
3
|
+
# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
4
|
+
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
5
|
+
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
6
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
7
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
8
|
+
# USE OR OTHER DEALINGS IN THE SOFTWARE.
|
9
|
+
#
|
10
|
+
|
11
|
+
require 'hula/bosh_director'
|
12
|
+
require 'hula/service_broker/client'
|
13
|
+
require 'hula/bosh_manifest'
|
14
|
+
require 'hula/socks4_proxy_ssh'
|
15
|
+
require 'hula/http_proxy_upstream_socks'
|
16
|
+
|
17
|
+
require 'prof/cloud_foundry'
|
18
|
+
require 'prof/ssh_gateway'
|
19
|
+
require 'prof/uaa_client'
|
20
|
+
|
21
|
+
module Prof
|
22
|
+
module Environment
|
23
|
+
class CloudFoundry
|
24
|
+
attr_reader :bosh_service_broker_job_name
|
25
|
+
|
26
|
+
def initialize(
|
27
|
+
cloud_foundry_domain: nil,
|
28
|
+
|
29
|
+
cloud_controller_identity: 'cloud_controller',
|
30
|
+
cloud_controller_password: 'cc-secret',
|
31
|
+
|
32
|
+
cloud_foundry_username: 'admin',
|
33
|
+
cloud_foundry_password: 'admin',
|
34
|
+
cloud_foundry_api_url: nil,
|
35
|
+
|
36
|
+
bosh_target: 'https://192.168.50.4:25555',
|
37
|
+
bosh_username: 'admin',
|
38
|
+
bosh_password: 'admin',
|
39
|
+
|
40
|
+
ssh_gateway_host: '192.168.50.4',
|
41
|
+
ssh_gateway_username: 'vagrant',
|
42
|
+
ssh_gateway_password: 'vagrant',
|
43
|
+
|
44
|
+
bosh_service_broker_job_name:,
|
45
|
+
bosh_manifest_path:,
|
46
|
+
|
47
|
+
use_proxy: true
|
48
|
+
)
|
49
|
+
@cloud_foundry_domain = cloud_foundry_domain
|
50
|
+
@cloud_controller_identity = cloud_controller_identity
|
51
|
+
@cloud_controller_password = cloud_controller_password
|
52
|
+
@cloud_foundry_username = cloud_foundry_username
|
53
|
+
@cloud_foundry_password = cloud_foundry_password
|
54
|
+
@bosh_target = bosh_target
|
55
|
+
@bosh_username = bosh_username
|
56
|
+
@bosh_password = bosh_password
|
57
|
+
@ssh_gateway_host = ssh_gateway_host
|
58
|
+
@ssh_gateway_username = ssh_gateway_username
|
59
|
+
@ssh_gateway_password = ssh_gateway_password
|
60
|
+
@bosh_service_broker_job_name = bosh_service_broker_job_name
|
61
|
+
@bosh_manifest_path = bosh_manifest_path
|
62
|
+
@cloud_foundry_api_url = cloud_foundry_api_url
|
63
|
+
@use_proxy = use_proxy
|
64
|
+
end
|
65
|
+
|
66
|
+
def cloud_foundry
|
67
|
+
@cloud_foundry ||= ::Prof::CloudFoundry.new(
|
68
|
+
domain: cloud_foundry_domain,
|
69
|
+
username: cloud_foundry_username,
|
70
|
+
password: cloud_foundry_password,
|
71
|
+
api_url: cloud_foundry_api_url
|
72
|
+
)
|
73
|
+
end
|
74
|
+
|
75
|
+
def bosh_manifest
|
76
|
+
@bosh_manifest ||= Hula::BoshManifest.from_file(bosh_manifest_path)
|
77
|
+
end
|
78
|
+
|
79
|
+
def cloud_foundry_domain
|
80
|
+
@cloud_foundry_domain ||= bosh_manifest.property('cf.domain')
|
81
|
+
end
|
82
|
+
|
83
|
+
def service_broker
|
84
|
+
@service_broker ||= Hula::ServiceBroker::Client.new(
|
85
|
+
url: URI::HTTPS.build(host: broker_registrar_properties.fetch('host')),
|
86
|
+
username: broker_registrar_properties.fetch('username'),
|
87
|
+
password: broker_registrar_properties.fetch('password'),
|
88
|
+
http_client: http_json_client(use_proxy: use_proxy)
|
89
|
+
)
|
90
|
+
end
|
91
|
+
|
92
|
+
def service_broker_name
|
93
|
+
broker_registrar_properties.fetch('name')
|
94
|
+
end
|
95
|
+
|
96
|
+
def bosh_director
|
97
|
+
@bosh_director ||= Hula::BoshDirector.new(
|
98
|
+
target_url: bosh_target,
|
99
|
+
username: bosh_username,
|
100
|
+
password: bosh_password,
|
101
|
+
manifest_path: bosh_manifest_path
|
102
|
+
)
|
103
|
+
end
|
104
|
+
|
105
|
+
def ssh_gateway
|
106
|
+
@ssh_gateway ||= SshGateway.new(
|
107
|
+
gateway_host: ssh_gateway_host,
|
108
|
+
gateway_username: ssh_gateway_username,
|
109
|
+
gateway_password: ssh_gateway_password
|
110
|
+
)
|
111
|
+
end
|
112
|
+
|
113
|
+
def cloud_foundry_uaa
|
114
|
+
@cloud_foundry_uaa ||= UAAClient.new(
|
115
|
+
cloud_foundry_domain,
|
116
|
+
cloud_controller_identity,
|
117
|
+
cloud_controller_password
|
118
|
+
)
|
119
|
+
end
|
120
|
+
|
121
|
+
def socks4_proxy
|
122
|
+
@socks4_proxy ||= Hula::Socks4ProxySsh.new(
|
123
|
+
ssh_username: ssh_gateway_username,
|
124
|
+
ssh_password: ssh_gateway_password,
|
125
|
+
ssh_host: ssh_gateway_host
|
126
|
+
).tap(&:start)
|
127
|
+
end
|
128
|
+
|
129
|
+
def http_proxy
|
130
|
+
@http_proxy ||= Hula::HttpProxyUpstreamSocks.new(socks_proxy: socks4_proxy).tap(&:start)
|
131
|
+
end
|
132
|
+
|
133
|
+
private
|
134
|
+
|
135
|
+
attr_reader :cloud_controller_identity, :cloud_controller_password,
|
136
|
+
:cloud_foundry_username, :cloud_foundry_password, :bosh_target, :bosh_username, :bosh_password,
|
137
|
+
:ssh_gateway_host, :ssh_gateway_username, :ssh_gateway_password, :bosh_manifest_path,
|
138
|
+
:cloud_foundry_api_url, :use_proxy
|
139
|
+
|
140
|
+
def broker_registrar_properties
|
141
|
+
bosh_manifest.job('broker-registrar').properties.fetch('broker')
|
142
|
+
end
|
143
|
+
|
144
|
+
def http_json_client(use_proxy:)
|
145
|
+
proxy = use_proxy ? http_proxy : Hula::ServiceBroker::HttpProxyNull.new
|
146
|
+
@http_json_client ||= Hula::ServiceBroker::HttpJsonClient.new(http_proxy: proxy)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
@@ -0,0 +1,156 @@
|
|
1
|
+
# Copyright (c) 2014-2015 Pivotal Software, Inc.
|
2
|
+
# All rights reserved.
|
3
|
+
# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
4
|
+
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
5
|
+
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
6
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
7
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
8
|
+
# USE OR OTHER DEALINGS IN THE SOFTWARE.
|
9
|
+
#
|
10
|
+
|
11
|
+
require 'uri'
|
12
|
+
require 'hula/bosh_director'
|
13
|
+
require 'capybara'
|
14
|
+
|
15
|
+
require 'prof/cloud_foundry'
|
16
|
+
require 'prof/ops_manager'
|
17
|
+
require 'prof/ops_manager_log_fetcher'
|
18
|
+
require 'prof/ssh_gateway'
|
19
|
+
require 'prof/uaa_client'
|
20
|
+
|
21
|
+
module Prof
|
22
|
+
module Environment
|
23
|
+
class NoDirectorVm < StandardError; end
|
24
|
+
|
25
|
+
class PcfDrinks
|
26
|
+
def initialize(tempest_config, page: default_capybara_session)
|
27
|
+
@tempest_config = tempest_config
|
28
|
+
@page = page
|
29
|
+
end
|
30
|
+
|
31
|
+
def ops_manager
|
32
|
+
@ops_manager ||= OpsManager.new(ops_manager_config.merge(page: page))
|
33
|
+
end
|
34
|
+
|
35
|
+
def cloud_foundry
|
36
|
+
@cloud_foundry ||= CloudFoundry.new(
|
37
|
+
domain: cloud_foundry_domain,
|
38
|
+
username: cloud_foundry_credentials.username,
|
39
|
+
password: cloud_foundry_credentials.password
|
40
|
+
)
|
41
|
+
end
|
42
|
+
|
43
|
+
def cloud_foundry_domain
|
44
|
+
tempest_config.fetch(:cloudfoundry).fetch(:domain)
|
45
|
+
end
|
46
|
+
|
47
|
+
def bosh_director
|
48
|
+
@bosh_director ||= Hula::BoshDirector.new(
|
49
|
+
target_url: bosh_director_url,
|
50
|
+
username: bosh_credentials.fetch('identity'),
|
51
|
+
password: bosh_credentials.fetch('password')
|
52
|
+
)
|
53
|
+
end
|
54
|
+
|
55
|
+
def ssh_gateway
|
56
|
+
SshGateway.new(
|
57
|
+
gateway_host: ssh_gateway_config.fetch(:host),
|
58
|
+
gateway_username: ssh_gateway_config.fetch(:username),
|
59
|
+
gateway_password: ssh_gateway_config[:password],
|
60
|
+
ssh_key: ssh_gateway_config[:ssh_key]
|
61
|
+
)
|
62
|
+
end
|
63
|
+
|
64
|
+
def cloud_foundry_uaa
|
65
|
+
@cloud_foundry_uaa ||= UAAClient.new(
|
66
|
+
cloud_foundry_domain,
|
67
|
+
cloud_controller_client_credentials.identity,
|
68
|
+
cloud_controller_client_credentials.password
|
69
|
+
)
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
attr_reader :tempest_config, :page
|
75
|
+
|
76
|
+
def default_capybara_session
|
77
|
+
Capybara::Session.new(Capybara.default_driver)
|
78
|
+
end
|
79
|
+
|
80
|
+
def log_fetcher
|
81
|
+
OpsManagerLogFetcher.new(
|
82
|
+
ssh_gateway: ssh_gateway,
|
83
|
+
host: ops_manager_hostname,
|
84
|
+
username: ops_manager_vm_config.fetch(:username),
|
85
|
+
password: ops_manager_vm_config.fetch(:password)
|
86
|
+
)
|
87
|
+
end
|
88
|
+
|
89
|
+
def cloud_controller_client_credentials
|
90
|
+
@cloud_controller_client_credentials ||= ops_manager.cc_client_credentials
|
91
|
+
end
|
92
|
+
|
93
|
+
def forwarded_bosh_port
|
94
|
+
@forwarded_bosh_port ||=
|
95
|
+
ssh_gateway.with_port_forwarded_to(
|
96
|
+
director.hostname,
|
97
|
+
25555
|
98
|
+
)
|
99
|
+
end
|
100
|
+
|
101
|
+
def director
|
102
|
+
director = ops_manager.vms_for_job_type('director').first
|
103
|
+
|
104
|
+
if director.nil?
|
105
|
+
raise NoDirectorVm, "No director VM found for #{ops_manager.url}"
|
106
|
+
else
|
107
|
+
director
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def ops_manager_hostname
|
112
|
+
URI.parse(ops_manager_config.fetch(:url)).hostname
|
113
|
+
end
|
114
|
+
|
115
|
+
def ops_manager_config
|
116
|
+
tempest_config.fetch(:tempest)
|
117
|
+
end
|
118
|
+
|
119
|
+
def ops_manager_vm_config
|
120
|
+
tempest_config.fetch(:tempest_vm)
|
121
|
+
end
|
122
|
+
|
123
|
+
def ssh_gateway_config
|
124
|
+
tempest_config.fetch(:proxy)
|
125
|
+
end
|
126
|
+
|
127
|
+
def bosh_director_url
|
128
|
+
return URI("https://127.0.0.1:#{forwarded_bosh_port}").to_s if !tempest_config[:proxy].nil?
|
129
|
+
return director.hostname
|
130
|
+
end
|
131
|
+
|
132
|
+
def bosh_product
|
133
|
+
# old versions of OpsMan (< v1.6 RC4)
|
134
|
+
@bosh_product ||= ops_manager
|
135
|
+
.send(:opsmanager_client)
|
136
|
+
.send(:product, 'microbosh')
|
137
|
+
|
138
|
+
# newer versions of OpsMan (>= v1.6 RC4)
|
139
|
+
@bosh_product ||= ops_manager
|
140
|
+
.send(:opsmanager_client)
|
141
|
+
.send(:product, 'p-bosh')
|
142
|
+
end
|
143
|
+
|
144
|
+
def bosh_credentials
|
145
|
+
# TODO: push this code into ops manager
|
146
|
+
@bosh_credentials ||= bosh_product
|
147
|
+
.job_of_type('director')
|
148
|
+
.properties.fetch('director_credentials')
|
149
|
+
end
|
150
|
+
|
151
|
+
def cloud_foundry_credentials
|
152
|
+
@cloud_foundry_credentials ||= ops_manager.cf_admin_credentials
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# Copyright (c) 2014-2015 Pivotal Software, Inc.
|
2
|
+
# All rights reserved.
|
3
|
+
# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
4
|
+
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
5
|
+
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
6
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
7
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
8
|
+
# USE OR OTHER DEALINGS IN THE SOFTWARE.
|
9
|
+
#
|
10
|
+
|
11
|
+
module Prof
|
12
|
+
class EnvironmentManager
|
13
|
+
class OpsManagerNotConfigured < StandardError; end
|
14
|
+
|
15
|
+
def initialize(pcf_environment)
|
16
|
+
@pcf_environment = pcf_environment
|
17
|
+
end
|
18
|
+
|
19
|
+
def isolate_cloud_foundry(&_block)
|
20
|
+
cloud_foundry.create_and_target_org(cf_org_name)
|
21
|
+
cloud_foundry.create_and_target_space(cf_space_name)
|
22
|
+
cloud_foundry.setup_permissive_security_group(cf_org_name, cf_space_name)
|
23
|
+
|
24
|
+
yield
|
25
|
+
|
26
|
+
cloud_foundry.delete_org(cf_org_name)
|
27
|
+
end
|
28
|
+
|
29
|
+
def destroy_orphan_tiles
|
30
|
+
orphans = orphan_tiles
|
31
|
+
return unless orphans.any?
|
32
|
+
|
33
|
+
puts "Removing orphaned tile(s) #{orphans.map(&:name).join(', ')}"
|
34
|
+
ops_manager.uninstall_tiles(orphans)
|
35
|
+
end
|
36
|
+
|
37
|
+
def destroy_orphan_deployments
|
38
|
+
orphans = orphan_deployments
|
39
|
+
return unless orphans.any?
|
40
|
+
|
41
|
+
puts "Removing orphaned deployment(s) '#{orphans.join(', ')}'"
|
42
|
+
orphans.each do |deployment_name|
|
43
|
+
bosh_director.delete_deployment(deployment_name, force: true)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def uninstall_tiles
|
48
|
+
ops_manager.uninstall_tiles(ops_manager.product_tiles)
|
49
|
+
end
|
50
|
+
|
51
|
+
def reset
|
52
|
+
raise OpsManagerNotConfigured, "Please configure #{ops_manager.url}" unless ops_manager.cf_installed?
|
53
|
+
|
54
|
+
destroy_orphan_tiles
|
55
|
+
destroy_orphan_deployments
|
56
|
+
uninstall_tiles
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
attr_reader :pcf_environment
|
62
|
+
|
63
|
+
def cf_org_name
|
64
|
+
@cf_org_name ||= "cf-org-#{SecureRandom.hex(4)}"
|
65
|
+
end
|
66
|
+
|
67
|
+
def cf_space_name
|
68
|
+
@cf_space_name ||= "cf-space-#{SecureRandom.hex(4)}"
|
69
|
+
end
|
70
|
+
|
71
|
+
def cloud_foundry
|
72
|
+
pcf_environment.cloud_foundry
|
73
|
+
end
|
74
|
+
|
75
|
+
def ops_manager
|
76
|
+
pcf_environment.ops_manager
|
77
|
+
end
|
78
|
+
|
79
|
+
def orphan_deployments
|
80
|
+
tile_guids = pcf_environment.ops_manager.tiles.map(&:guid)
|
81
|
+
pcf_environment.bosh_director.deployment_names.reject { |deployment_name| tile_guids.include?(deployment_name) }
|
82
|
+
end
|
83
|
+
|
84
|
+
def orphan_tiles
|
85
|
+
bosh_deployment_names = pcf_environment.bosh_director.deployment_names
|
86
|
+
pcf_environment.ops_manager.product_tiles.reject { |tile| bosh_deployment_names.include?(tile.guid) }
|
87
|
+
end
|
88
|
+
|
89
|
+
def bosh_director
|
90
|
+
pcf_environment.bosh_director
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# Copyright (c) 2014-2015 Pivotal Software, Inc.
|
2
|
+
# All rights reserved.
|
3
|
+
# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
4
|
+
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
5
|
+
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
6
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
7
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
8
|
+
# USE OR OTHER DEALINGS IN THE SOFTWARE.
|
9
|
+
#
|
10
|
+
|
11
|
+
require 'capybara/rspec'
|
12
|
+
require 'capybara/query'
|
13
|
+
require 'capybara/poltergeist'
|
14
|
+
require 'capybara/webkit'
|
15
|
+
|
16
|
+
module Prof
|
17
|
+
module ExternalSpec
|
18
|
+
module Helpers
|
19
|
+
module Capybara
|
20
|
+
def setup_browser(driver = :poltergeist)
|
21
|
+
unless %i{poltergeist webkit}.include?(driver)
|
22
|
+
raise StandardError.new("invalid driver")
|
23
|
+
end
|
24
|
+
|
25
|
+
::Capybara.default_wait_time = 60
|
26
|
+
::Capybara.default_driver = driver
|
27
|
+
::Capybara.javascript_driver = driver
|
28
|
+
|
29
|
+
::Capybara.register_driver :poltergeist do |app|
|
30
|
+
::Capybara::Poltergeist::Driver.new(
|
31
|
+
app,
|
32
|
+
debug: ENV.key?('DEBUG'),
|
33
|
+
timeout: 240,
|
34
|
+
js_errors: false,
|
35
|
+
phantomjs_logger: null_io_object,
|
36
|
+
phantomjs_options: ['--ignore-ssl-errors=yes'],
|
37
|
+
window_size: [1300, 1000]
|
38
|
+
)
|
39
|
+
end
|
40
|
+
|
41
|
+
::Capybara.register_driver :webkit do |app|
|
42
|
+
::Capybara::Webkit::Driver.new(app).tap do |d|
|
43
|
+
d.browser.ignore_ssl_errors
|
44
|
+
d.browser.allow_url('*')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def null_io_object
|
50
|
+
f = File.open('/dev/null')
|
51
|
+
io = IO.for_fd(f.fileno)
|
52
|
+
io.autoclose = true
|
53
|
+
io
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# Copyright (c) 2014-2015 Pivotal Software, Inc.
|
2
|
+
# All rights reserved.
|
3
|
+
# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
4
|
+
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
5
|
+
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
6
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
7
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
8
|
+
# USE OR OTHER DEALINGS IN THE SOFTWARE.
|
9
|
+
#
|
10
|
+
|
11
|
+
module Prof
|
12
|
+
module ExternalSpec
|
13
|
+
module Helpers
|
14
|
+
module Debug
|
15
|
+
|
16
|
+
def recording_exceptions
|
17
|
+
yield
|
18
|
+
rescue Exception => ex
|
19
|
+
@recorded_exception = ex
|
20
|
+
raise
|
21
|
+
end
|
22
|
+
|
23
|
+
def save_exceptions
|
24
|
+
yield
|
25
|
+
rescue Exception => ex
|
26
|
+
ops_manager.browser do |page|
|
27
|
+
name = "failure"
|
28
|
+
puts "Saving failure data for '#{name}'"
|
29
|
+
page.save_page("#{name}.html")
|
30
|
+
page.save_screenshot("#{name}.png")
|
31
|
+
end
|
32
|
+
raise
|
33
|
+
end
|
34
|
+
|
35
|
+
def save_exception_output(example)
|
36
|
+
unless @recorded_exception
|
37
|
+
return unless example.respond_to?(:exception)
|
38
|
+
return unless example.respond_to?(:full_description)
|
39
|
+
return unless respond_to?(:ops_manager)
|
40
|
+
return unless example.exception
|
41
|
+
end
|
42
|
+
|
43
|
+
ops_manager.browser do |page|
|
44
|
+
name = example.full_description.gsub(/\W/, '_')
|
45
|
+
puts "Saving failure data for '#{name}'"
|
46
|
+
page.save_page("#{name}.html")
|
47
|
+
page.save_screenshot("#{name}.png")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|