cf 5.0.0.rc1 → 5.0.0.rc3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. data/lib/admin/plugin.rb +1 -0
  2. data/lib/admin/service_broker/add.rb +46 -0
  3. data/lib/cf/cli.rb +8 -3
  4. data/lib/cf/cli/service/create.rb +68 -20
  5. data/lib/cf/cli/service/delete.rb +1 -1
  6. data/lib/cf/cli/service/service_instance_helper.rb +99 -0
  7. data/lib/cf/cli/service/services.rb +12 -32
  8. data/lib/cf/cli/start/target.rb +1 -1
  9. data/lib/cf/version.rb +1 -1
  10. data/lib/manifests/manifests.rb +41 -25
  11. data/lib/tasks/gem_release.rake +1 -1
  12. data/spec/admin/service_broker/add_spec.rb +59 -0
  13. data/spec/assets/env/Gemfile +4 -0
  14. data/spec/assets/env/Gemfile.lock +20 -0
  15. data/spec/assets/env/env_test.rb +58 -0
  16. data/spec/cf/cli/app/delete_spec.rb +2 -2
  17. data/spec/cf/cli/app/push/create_spec.rb +1 -1
  18. data/spec/cf/cli/service/create_spec.rb +51 -4
  19. data/spec/cf/cli/service/rename_spec.rb +1 -1
  20. data/spec/cf/cli/service/service_instance_helper_spec.rb +155 -0
  21. data/spec/cf/cli/service/services_spec.rb +63 -34
  22. data/spec/cf/cli/space/space_spec.rb +1 -1
  23. data/spec/cf/cli/space/spaces_spec.rb +3 -3
  24. data/spec/factories/cfoundry/v2/{service_instances_factory.rb → managed_service_instances_factory.rb} +2 -2
  25. data/spec/factories/cfoundry/v2/user_provided_service_instances_factory.rb +12 -0
  26. data/spec/features/delete_orphaned_service_spec.rb +64 -0
  27. data/spec/features/manifests_spec.rb +86 -0
  28. data/spec/features/org_spec.rb +4 -4
  29. data/spec/{integration → features}/push_flow_spec.rb +27 -3
  30. data/spec/features/services_spec.rb +96 -0
  31. data/spec/integration/service_broker_spec.rb +49 -0
  32. data/spec/manifests/manifests_spec.rb +46 -25
  33. data/spec/spec_helper.rb +7 -1
  34. data/spec/support/features_helper.rb +36 -3
  35. data/spec/support/matchers.rb +14 -3
  36. metadata +109 -9
data/lib/admin/plugin.rb CHANGED
@@ -2,3 +2,4 @@ require "admin/curl"
2
2
  require "admin/guid"
3
3
  require "admin/set_quota"
4
4
  require "admin/service_auth_token"
5
+ require "admin/service_broker/add"
@@ -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 = CFoundry::V2::Client.new(target, token)
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
- service = client.service_instance
59
- service.name = input[:name, offering]
60
- finalize
61
- plan = input[:plan, offering.service_plans]
62
- finalize
63
- service.service_plan = if plan.is_a?(String)
64
- offering.service_plans.find { |p| p.name.casecmp(plan) == 0 }
65
- else
66
- plan
67
- end
68
- service.space = client.current_space
69
-
70
- with_progress("Creating service #{c(service.name, :name)}") do
71
- service.create!
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 => service, :app => app
101
+ invoke :bind_service, :service => service_instance, :app => app
79
102
  end
80
- service
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 { |s|
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
- random = sprintf("%x", rand(1000000))
99
- ask "Name?", :default => "#{offering.label}-#{random}"
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 bind", :argument => :optional,
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 { |i|
75
- apps = name_list(i.service_bindings.collect(&:app))
76
- plan = i.service_plan
77
-
78
- unless plan
79
- [ c(i.name, :name), "none", "none", "none", "none", apps]
80
- else
81
- service = plan.service
82
- label = service.label
83
- version = service.version
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
- plan = i.service_plan
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
@@ -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
- CFoundry::Client.get(target) # check that it's valid before setting
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
@@ -1,3 +1,3 @@
1
1
  module CF
2
- VERSION = "5.0.0.rc1".freeze
2
+ VERSION = "5.0.0.rc3".freeze
3
3
  end
@@ -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 |i|
186
- p = i.service_plan
187
- s = p.service
188
-
189
- meta["services"][i.name] = {
190
- "label" => s.label,
191
- "provider" => s.provider,
192
- "version" => s.version,
193
- "plan" => p.name
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
- offering = offerings.find { |o|
296
- o.label == (svc[:label] || svc[:type] || svc[:vendor]) &&
297
- (!svc[:version] || o.version == svc[:version]) &&
298
- (o.provider == (svc[:provider] || "core"))
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
- fail "Unknown service offering: #{svc.inspect}." unless offering
316
+ fail "Unknown service offering: #{svc.inspect}." unless offering
302
317
 
303
- plan = offering.service_plans.find { |p|
304
- p.name == (svc[:plan] || "D100")
305
- }
318
+ plan = offering.service_plans.find { |p|
319
+ p.name == (svc[:plan] || "D100")
320
+ }
306
321
 
307
- fail "Unknown service plan: #{svc[:plan]}." unless plan
322
+ fail "Unknown service plan: #{svc[:plan]}." unless plan
308
323
 
309
- invoke :create_service,
310
- :name => name,
311
- :offering => offering,
312
- :plan => plan,
313
- :app => app
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