cf 5.0.0.rc1 → 5.0.0.rc3
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.
- data/lib/admin/plugin.rb +1 -0
- data/lib/admin/service_broker/add.rb +46 -0
- data/lib/cf/cli.rb +8 -3
- data/lib/cf/cli/service/create.rb +68 -20
- data/lib/cf/cli/service/delete.rb +1 -1
- data/lib/cf/cli/service/service_instance_helper.rb +99 -0
- data/lib/cf/cli/service/services.rb +12 -32
- data/lib/cf/cli/start/target.rb +1 -1
- data/lib/cf/version.rb +1 -1
- data/lib/manifests/manifests.rb +41 -25
- data/lib/tasks/gem_release.rake +1 -1
- data/spec/admin/service_broker/add_spec.rb +59 -0
- data/spec/assets/env/Gemfile +4 -0
- data/spec/assets/env/Gemfile.lock +20 -0
- data/spec/assets/env/env_test.rb +58 -0
- data/spec/cf/cli/app/delete_spec.rb +2 -2
- data/spec/cf/cli/app/push/create_spec.rb +1 -1
- data/spec/cf/cli/service/create_spec.rb +51 -4
- data/spec/cf/cli/service/rename_spec.rb +1 -1
- data/spec/cf/cli/service/service_instance_helper_spec.rb +155 -0
- data/spec/cf/cli/service/services_spec.rb +63 -34
- data/spec/cf/cli/space/space_spec.rb +1 -1
- data/spec/cf/cli/space/spaces_spec.rb +3 -3
- data/spec/factories/cfoundry/v2/{service_instances_factory.rb → managed_service_instances_factory.rb} +2 -2
- data/spec/factories/cfoundry/v2/user_provided_service_instances_factory.rb +12 -0
- data/spec/features/delete_orphaned_service_spec.rb +64 -0
- data/spec/features/manifests_spec.rb +86 -0
- data/spec/features/org_spec.rb +4 -4
- data/spec/{integration → features}/push_flow_spec.rb +27 -3
- data/spec/features/services_spec.rb +96 -0
- data/spec/integration/service_broker_spec.rb +49 -0
- data/spec/manifests/manifests_spec.rb +46 -25
- data/spec/spec_helper.rb +7 -1
- data/spec/support/features_helper.rb +36 -3
- data/spec/support/matchers.rb +14 -3
- metadata +109 -9
data/lib/admin/plugin.rb
CHANGED
@@ -0,0 +1,46 @@
|
|
1
|
+
require "cf/cli"
|
2
|
+
|
3
|
+
module CFAdmin::ServiceBroker
|
4
|
+
class Add < CF::CLI
|
5
|
+
def precondition
|
6
|
+
check_target
|
7
|
+
end
|
8
|
+
|
9
|
+
desc "Add a Service Broker."
|
10
|
+
group :admin
|
11
|
+
input :name, :argument => :optional,
|
12
|
+
:desc => "broker name"
|
13
|
+
input :url,
|
14
|
+
:desc => "broker url"
|
15
|
+
input :token,
|
16
|
+
:desc => "broker token"
|
17
|
+
|
18
|
+
def add_service_broker
|
19
|
+
broker = client.service_broker
|
20
|
+
|
21
|
+
broker.name = input[:name]
|
22
|
+
finalize
|
23
|
+
broker.broker_url = input[:url]
|
24
|
+
finalize
|
25
|
+
broker.token = input[:token]
|
26
|
+
finalize
|
27
|
+
|
28
|
+
with_progress("") do
|
29
|
+
broker.create!
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
def ask_name
|
35
|
+
ask("name")
|
36
|
+
end
|
37
|
+
|
38
|
+
def ask_url
|
39
|
+
ask("url")
|
40
|
+
end
|
41
|
+
|
42
|
+
def ask_token
|
43
|
+
ask("token")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/cf/cli.rb
CHANGED
@@ -414,10 +414,8 @@ EOS
|
|
414
414
|
|
415
415
|
fail "V1 targets are no longer supported." if info[:version] == 1
|
416
416
|
|
417
|
-
@@client =
|
417
|
+
@@client = build_client(target, token)
|
418
418
|
|
419
|
-
@@client.http_proxy = input[:http_proxy] || ENV['HTTP_PROXY'] || ENV['http_proxy']
|
420
|
-
@@client.https_proxy = input[:https_proxy] || ENV['HTTPS_PROXY'] || ENV['https_proxy']
|
421
419
|
@@client.trace = input[:trace]
|
422
420
|
|
423
421
|
uri = URI.parse(target)
|
@@ -435,6 +433,13 @@ EOS
|
|
435
433
|
rescue CFoundry::InvalidTarget
|
436
434
|
end
|
437
435
|
|
436
|
+
def build_client(target, token = nil)
|
437
|
+
client = CFoundry::V2::Client.new(target, token)
|
438
|
+
client.http_proxy = input[:http_proxy] || ENV['HTTP_PROXY'] || ENV['http_proxy']
|
439
|
+
client.https_proxy = input[:https_proxy] || ENV['HTTPS_PROXY'] || ENV['https_proxy']
|
440
|
+
client
|
441
|
+
end
|
442
|
+
|
438
443
|
def fail_unknown(display, name)
|
439
444
|
fail("Unknown #{display} '#{name}'.")
|
440
445
|
end
|
@@ -1,6 +1,16 @@
|
|
1
1
|
require "cf/cli/service/base"
|
2
2
|
|
3
3
|
module CF::Service
|
4
|
+
USER_PROVIDED_OFFERING = "user-provided" # I'd rather move this to CFoundry
|
5
|
+
|
6
|
+
class UPDummy
|
7
|
+
def label
|
8
|
+
"user-provided"
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_reader :version, :provider
|
12
|
+
end
|
13
|
+
|
4
14
|
class Create < Base
|
5
15
|
offerings_from_label = proc { |label, offerings|
|
6
16
|
offerings.select { |s| s.label == label }
|
@@ -46,6 +56,8 @@ module CF::Service
|
|
46
56
|
end
|
47
57
|
finalize
|
48
58
|
|
59
|
+
offerings << UPDummy.new
|
60
|
+
|
49
61
|
selected_offerings = offerings.any? ? Array(input[:offering, offerings.sort_by(&:label)]) : []
|
50
62
|
finalize
|
51
63
|
|
@@ -55,48 +67,84 @@ module CF::Service
|
|
55
67
|
|
56
68
|
offering = selected_offerings.first
|
57
69
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
70
|
+
if offering.label == CF::Service::USER_PROVIDED_OFFERING
|
71
|
+
service_instance = client.user_provided_service_instance
|
72
|
+
service_instance.name = input[:name, offering]
|
73
|
+
finalize
|
74
|
+
|
75
|
+
# at this point there's no way input[:credentials] can work interactively...
|
76
|
+
service_instance.credentials = input[:credentials, nil] || ask_credentials
|
77
|
+
else
|
78
|
+
service_instance = client.managed_service_instance
|
79
|
+
service_instance.name = input[:name, offering]
|
80
|
+
finalize
|
81
|
+
|
82
|
+
plan = input[:plan, offering.service_plans]
|
83
|
+
finalize
|
84
|
+
service_instance.service_plan = if plan.is_a?(String)
|
85
|
+
offering.service_plans.find { |p| p.name.casecmp(plan) == 0 }
|
86
|
+
else
|
87
|
+
plan
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
service_instance.space = client.current_space
|
92
|
+
|
93
|
+
with_progress("Creating service #{c(service_instance.name, :name)}") do
|
94
|
+
service_instance.create!
|
72
95
|
end
|
73
96
|
|
74
97
|
app = input[:app]
|
75
98
|
finalize
|
76
99
|
|
77
100
|
if app
|
78
|
-
invoke :bind_service, :service =>
|
101
|
+
invoke :bind_service, :service => service_instance, :app => app
|
79
102
|
end
|
80
|
-
|
103
|
+
service_instance
|
81
104
|
end
|
82
105
|
|
83
106
|
private
|
84
107
|
|
108
|
+
def ask_credentials
|
109
|
+
credentials = {}
|
110
|
+
|
111
|
+
while keys = ask("What credential parameters should applications use to connect to this service instance?\n(e.g. hostname, port, password)").split(/\s*,\s*/).map(&:strip)
|
112
|
+
if bad_key = keys.detect { |key| key !~ /^[-\w]+$/ }
|
113
|
+
line("'#{bad_key}' is not a valid key")
|
114
|
+
else
|
115
|
+
break
|
116
|
+
end
|
117
|
+
end
|
118
|
+
finalize
|
119
|
+
keys.each do |key|
|
120
|
+
value = ask(key)
|
121
|
+
finalize
|
122
|
+
credentials[key] = value
|
123
|
+
end
|
124
|
+
|
125
|
+
credentials
|
126
|
+
end
|
127
|
+
|
85
128
|
def ask_offering(offerings)
|
86
129
|
[ask("What kind?", :choices => offerings.sort_by(&:label),
|
87
|
-
:display => proc
|
130
|
+
:display => proc do |s|
|
88
131
|
str = "#{c(s.label, :name)} #{s.version}"
|
89
132
|
if s.provider != "core"
|
90
133
|
str << ", via #{s.provider}"
|
91
134
|
end
|
92
135
|
str
|
93
|
-
|
136
|
+
end,
|
94
137
|
:complete => proc { |s| "#{s.label} #{s.version}" })]
|
95
138
|
end
|
96
139
|
|
97
140
|
def ask_name(offering)
|
98
|
-
|
99
|
-
|
141
|
+
default = nil
|
142
|
+
unless offering == CF::Service::USER_PROVIDED_OFFERING
|
143
|
+
random = sprintf("%x", rand(1000000))
|
144
|
+
default = "#{offering.label}-#{random}"
|
145
|
+
end
|
146
|
+
|
147
|
+
ask "Name?", :default => default
|
100
148
|
end
|
101
149
|
|
102
150
|
def ask_plan(plans)
|
@@ -4,7 +4,7 @@ module CF::Service
|
|
4
4
|
class Delete < Base
|
5
5
|
desc "Delete a service"
|
6
6
|
group :services, :manage
|
7
|
-
input :service, :desc => "Service to
|
7
|
+
input :service, :desc => "Service to delete", :argument => :optional,
|
8
8
|
:from_given => by_name(:service_instance, :service)
|
9
9
|
input :unbind, :desc => "Unbind from applications before deleting?",
|
10
10
|
:type => :boolean, :default => proc { force? || interact }
|
@@ -0,0 +1,99 @@
|
|
1
|
+
class ServiceInstanceHelper
|
2
|
+
def self.new(instance)
|
3
|
+
"#{instance.class.name.demodulize}Helper".constantize.new(instance)
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
class UserProvidedServiceInstanceHelper
|
8
|
+
def initialize(instance)
|
9
|
+
@instance = instance
|
10
|
+
end
|
11
|
+
|
12
|
+
def service_label
|
13
|
+
"user-provided"
|
14
|
+
end
|
15
|
+
|
16
|
+
def service_provider
|
17
|
+
"n/a"
|
18
|
+
end
|
19
|
+
|
20
|
+
def version
|
21
|
+
"n/a"
|
22
|
+
end
|
23
|
+
|
24
|
+
def plan_name
|
25
|
+
"n/a"
|
26
|
+
end
|
27
|
+
|
28
|
+
def matches(opts = {})
|
29
|
+
label = opts[:service]
|
30
|
+
if label
|
31
|
+
return label == service_label
|
32
|
+
end
|
33
|
+
|
34
|
+
true
|
35
|
+
end
|
36
|
+
|
37
|
+
def name
|
38
|
+
@instance.name
|
39
|
+
end
|
40
|
+
|
41
|
+
def service_bindings
|
42
|
+
@instance.service_bindings
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class ManagedServiceInstanceHelper
|
47
|
+
def initialize(service_instance)
|
48
|
+
@instance = service_instance
|
49
|
+
end
|
50
|
+
|
51
|
+
def service_label
|
52
|
+
@instance.service_plan.service.label
|
53
|
+
end
|
54
|
+
|
55
|
+
def service_provider
|
56
|
+
@instance.service_plan.service.provider
|
57
|
+
end
|
58
|
+
|
59
|
+
def version
|
60
|
+
@instance.service_plan.service.version
|
61
|
+
end
|
62
|
+
|
63
|
+
def plan_name
|
64
|
+
@instance.service_plan.name
|
65
|
+
end
|
66
|
+
|
67
|
+
def service_bindings
|
68
|
+
@instance.service_bindings
|
69
|
+
end
|
70
|
+
|
71
|
+
def name
|
72
|
+
@instance.name
|
73
|
+
end
|
74
|
+
|
75
|
+
def matches(opts = {})
|
76
|
+
service = opts[:service]
|
77
|
+
plan = opts[:plan]
|
78
|
+
provider = opts[:provider]
|
79
|
+
version = opts[:version]
|
80
|
+
|
81
|
+
if service
|
82
|
+
return false unless File.fnmatch(service, service_label)
|
83
|
+
end
|
84
|
+
|
85
|
+
if plan
|
86
|
+
return false unless File.fnmatch(plan.upcase, plan_name.upcase)
|
87
|
+
end
|
88
|
+
|
89
|
+
if provider
|
90
|
+
return false unless File.fnmatch(provider, service_provider)
|
91
|
+
end
|
92
|
+
|
93
|
+
if version
|
94
|
+
return false unless File.fnmatch(version, self.version)
|
95
|
+
end
|
96
|
+
|
97
|
+
true
|
98
|
+
end
|
99
|
+
end
|
@@ -71,19 +71,16 @@ module CF::Service
|
|
71
71
|
def show_services_table
|
72
72
|
table(
|
73
73
|
["name", "service", "provider", "version", "plan", "bound apps"],
|
74
|
-
@services.collect { |
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
provider = service.provider
|
85
|
-
[ c(i.name, :name), label, provider, version, plan.name, apps]
|
86
|
-
end
|
74
|
+
@services.collect { |instance|
|
75
|
+
presenter = ServiceInstanceHelper.new(instance)
|
76
|
+
apps = name_list(presenter.service_bindings.collect(&:app))
|
77
|
+
|
78
|
+
label = presenter.service_label
|
79
|
+
provider = presenter.service_provider
|
80
|
+
version = presenter.version
|
81
|
+
plan_name = presenter.plan_name
|
82
|
+
|
83
|
+
[ c(presenter.name, :name), label, provider, version, plan_name, apps]
|
87
84
|
})
|
88
85
|
|
89
86
|
end
|
@@ -105,25 +102,8 @@ module CF::Service
|
|
105
102
|
return false unless File.fnmatch(name, i.name)
|
106
103
|
end
|
107
104
|
|
108
|
-
|
109
|
-
|
110
|
-
if service = options[:service]
|
111
|
-
return false unless File.fnmatch(service, plan.service.label)
|
112
|
-
end
|
113
|
-
|
114
|
-
if plan = options[:plan]
|
115
|
-
return false unless File.fnmatch(plan.upcase, plan.name.upcase)
|
116
|
-
end
|
117
|
-
|
118
|
-
if provider = options[:provider]
|
119
|
-
return false unless File.fnmatch(provider, plan.service.provider)
|
120
|
-
end
|
121
|
-
|
122
|
-
if version = options[:version]
|
123
|
-
return false unless File.fnmatch(version, plan.service.version)
|
124
|
-
end
|
125
|
-
|
126
|
-
true
|
105
|
+
helper = ServiceInstanceHelper.new(i)
|
106
|
+
return helper.matches(options)
|
127
107
|
end
|
128
108
|
end
|
129
109
|
end
|
data/lib/cf/cli/start/target.rb
CHANGED
@@ -21,7 +21,7 @@ module CF::Start
|
|
21
21
|
target = sane_target_url(input[:url])
|
22
22
|
with_progress("Setting target to #{c(target, :name)}") do
|
23
23
|
begin
|
24
|
-
|
24
|
+
build_client(target).info # check that it's valid before setting
|
25
25
|
rescue CFoundry::TargetRefused
|
26
26
|
fail "Target refused connection."
|
27
27
|
rescue CFoundry::InvalidTarget
|
data/lib/cf/version.rb
CHANGED
data/lib/manifests/manifests.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require "yaml"
|
2
2
|
require "set"
|
3
|
+
require "cf/cli/service/create"
|
3
4
|
|
4
5
|
require "manifests/loader"
|
5
6
|
|
@@ -182,16 +183,23 @@ module CFManifests
|
|
182
183
|
unless services.empty?
|
183
184
|
meta["services"] = {}
|
184
185
|
|
185
|
-
services.each do |
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
186
|
+
services.each do |service_instance|
|
187
|
+
if service_instance.is_a?(CFoundry::V2::UserProvidedServiceInstance)
|
188
|
+
meta["services"][service_instance.name] = {
|
189
|
+
"label" => "user-provided",
|
190
|
+
"credentials" => service_instance.credentials.stringify_keys,
|
191
|
+
}
|
192
|
+
else
|
193
|
+
service_plan = service_instance.service_plan
|
194
|
+
service = service_plan.service
|
195
|
+
|
196
|
+
meta["services"][service_instance.name] = {
|
197
|
+
"label" => service.label,
|
198
|
+
"provider" => service.provider,
|
199
|
+
"version" => service.version,
|
200
|
+
"plan" => service_plan.name
|
201
|
+
}
|
202
|
+
end
|
195
203
|
end
|
196
204
|
end
|
197
205
|
|
@@ -292,25 +300,33 @@ module CFManifests
|
|
292
300
|
if instance = client.service_instance_by_name(name)
|
293
301
|
to_bind << instance
|
294
302
|
else
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
303
|
+
if svc[:label] == "user-provided"
|
304
|
+
invoke :create_service,
|
305
|
+
name: name,
|
306
|
+
offering: CF::Service::UPDummy.new,
|
307
|
+
app: app,
|
308
|
+
credentials: svc[:credentials]
|
309
|
+
else
|
310
|
+
offering = offerings.find { |o|
|
311
|
+
o.label == (svc[:label] || svc[:type] || svc[:vendor]) &&
|
312
|
+
(!svc[:version] || o.version == svc[:version]) &&
|
313
|
+
(o.provider == (svc[:provider] || "core"))
|
314
|
+
}
|
300
315
|
|
301
|
-
|
316
|
+
fail "Unknown service offering: #{svc.inspect}." unless offering
|
302
317
|
|
303
|
-
|
304
|
-
|
305
|
-
|
318
|
+
plan = offering.service_plans.find { |p|
|
319
|
+
p.name == (svc[:plan] || "D100")
|
320
|
+
}
|
306
321
|
|
307
|
-
|
322
|
+
fail "Unknown service plan: #{svc[:plan]}." unless plan
|
308
323
|
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
324
|
+
invoke :create_service,
|
325
|
+
:name => name,
|
326
|
+
:offering => offering,
|
327
|
+
:plan => plan,
|
328
|
+
:app => app
|
329
|
+
end
|
314
330
|
end
|
315
331
|
end
|
316
332
|
|