cf 0.1.5 → 0.6.0.rc1
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/LICENSE +1277 -30
- data/Rakefile +12 -1
- data/bin/cf +0 -3
- data/lib/cf.rb +6 -0
- data/lib/cf/cli.rb +389 -190
- data/lib/cf/cli/app/app.rb +45 -0
- data/lib/cf/cli/app/apps.rb +99 -0
- data/lib/cf/cli/app/base.rb +90 -0
- data/lib/cf/cli/app/crashes.rb +42 -0
- data/lib/cf/cli/app/delete.rb +95 -0
- data/lib/cf/cli/app/deprecated.rb +11 -0
- data/lib/cf/cli/app/env.rb +78 -0
- data/lib/cf/cli/app/files.rb +137 -0
- data/lib/cf/cli/app/health.rb +26 -0
- data/lib/cf/cli/app/instances.rb +53 -0
- data/lib/cf/cli/app/logs.rb +76 -0
- data/lib/cf/cli/app/push.rb +105 -0
- data/lib/cf/cli/app/push/create.rb +149 -0
- data/lib/cf/cli/app/push/interactions.rb +94 -0
- data/lib/cf/cli/app/push/sync.rb +64 -0
- data/lib/cf/cli/app/rename.rb +35 -0
- data/lib/cf/cli/app/restart.rb +20 -0
- data/lib/cf/cli/app/scale.rb +69 -0
- data/lib/cf/cli/app/start.rb +143 -0
- data/lib/cf/cli/app/stats.rb +67 -0
- data/lib/cf/cli/app/stop.rb +27 -0
- data/lib/cf/cli/domain/base.rb +8 -0
- data/lib/cf/cli/domain/domains.rb +40 -0
- data/lib/cf/cli/domain/map.rb +55 -0
- data/lib/cf/cli/domain/unmap.rb +56 -0
- data/lib/cf/cli/help.rb +15 -0
- data/lib/cf/cli/interactive.rb +105 -0
- data/lib/cf/cli/organization/base.rb +12 -0
- data/lib/cf/cli/organization/create.rb +32 -0
- data/lib/cf/cli/organization/delete.rb +73 -0
- data/lib/cf/cli/organization/org.rb +45 -0
- data/lib/cf/cli/organization/orgs.rb +35 -0
- data/lib/cf/cli/organization/rename.rb +36 -0
- data/lib/cf/cli/route/base.rb +8 -0
- data/lib/cf/cli/route/map.rb +70 -0
- data/lib/cf/cli/route/routes.rb +26 -0
- data/lib/cf/cli/route/unmap.rb +62 -0
- data/lib/cf/cli/service/base.rb +8 -0
- data/lib/cf/cli/service/bind.rb +44 -0
- data/lib/cf/cli/service/create.rb +107 -0
- data/lib/cf/cli/service/delete.rb +82 -0
- data/lib/cf/cli/service/rename.rb +35 -0
- data/lib/cf/cli/service/service.rb +40 -0
- data/lib/cf/cli/service/services.rb +99 -0
- data/lib/cf/cli/service/unbind.rb +38 -0
- data/lib/cf/cli/space/base.rb +19 -0
- data/lib/cf/cli/space/create.rb +63 -0
- data/lib/cf/cli/space/delete.rb +95 -0
- data/lib/cf/cli/space/rename.rb +39 -0
- data/lib/cf/cli/space/space.rb +64 -0
- data/lib/cf/cli/space/spaces.rb +55 -0
- data/lib/cf/cli/space/switch.rb +16 -0
- data/lib/cf/cli/start/base.rb +93 -0
- data/lib/cf/cli/start/colors.rb +13 -0
- data/lib/cf/cli/start/info.rb +124 -0
- data/lib/cf/cli/start/login.rb +94 -0
- data/lib/cf/cli/start/logout.rb +17 -0
- data/lib/cf/cli/start/target.rb +69 -0
- data/lib/cf/cli/start/target_interactions.rb +37 -0
- data/lib/cf/cli/start/targets.rb +16 -0
- data/lib/cf/cli/user/base.rb +29 -0
- data/lib/cf/cli/user/create.rb +39 -0
- data/lib/cf/cli/user/passwd.rb +43 -0
- data/lib/cf/cli/user/register.rb +42 -0
- data/lib/cf/cli/user/users.rb +32 -0
- data/lib/cf/constants.rb +10 -7
- data/lib/cf/detect.rb +113 -48
- data/lib/cf/errors.rb +17 -0
- data/lib/cf/plugin.rb +28 -12
- data/lib/cf/spacing.rb +89 -0
- data/lib/cf/spec_helper.rb +1 -0
- data/lib/cf/test_support.rb +6 -0
- data/lib/cf/version.rb +1 -1
- data/spec/assets/hello-sinatra/Gemfile +3 -0
- data/spec/assets/hello-sinatra/Gemfile.lock +17 -0
- data/spec/assets/hello-sinatra/config.ru +3 -0
- data/spec/assets/hello-sinatra/fat-cat-makes-app-larger.png +0 -0
- data/spec/assets/hello-sinatra/main.rb +6 -0
- data/spec/assets/specker_runner/specker_runner_input.rb +6 -0
- data/spec/assets/specker_runner/specker_runner_pause.rb +5 -0
- data/spec/cf/cli/app/base_spec.rb +17 -0
- data/spec/cf/cli/app/delete_spec.rb +188 -0
- data/spec/cf/cli/app/instances_spec.rb +65 -0
- data/spec/cf/cli/app/push/create_spec.rb +661 -0
- data/spec/cf/cli/app/push_spec.rb +369 -0
- data/spec/cf/cli/app/rename_spec.rb +104 -0
- data/spec/cf/cli/app/scale_spec.rb +75 -0
- data/spec/cf/cli/app/start_spec.rb +208 -0
- data/spec/cf/cli/app/stats_spec.rb +68 -0
- data/spec/cf/cli/domain/map_spec.rb +130 -0
- data/spec/cf/cli/domain/unmap_spec.rb +69 -0
- data/spec/cf/cli/organization/orgs_spec.rb +108 -0
- data/spec/cf/cli/organization/rename_spec.rb +113 -0
- data/spec/cf/cli/route/map_spec.rb +121 -0
- data/spec/cf/cli/route/unmap_spec.rb +155 -0
- data/spec/cf/cli/service/bind_spec.rb +25 -0
- data/spec/cf/cli/service/delete_spec.rb +22 -0
- data/spec/cf/cli/service/rename_spec.rb +105 -0
- data/spec/cf/cli/service/service_spec.rb +23 -0
- data/spec/cf/cli/service/unbind_spec.rb +25 -0
- data/spec/cf/cli/space/create_spec.rb +93 -0
- data/spec/cf/cli/space/rename_spec.rb +102 -0
- data/spec/cf/cli/space/spaces_spec.rb +104 -0
- data/spec/cf/cli/space/switch_space_spec.rb +55 -0
- data/spec/cf/cli/start/info_spec.rb +160 -0
- data/spec/cf/cli/start/login_spec.rb +142 -0
- data/spec/cf/cli/start/logout_spec.rb +50 -0
- data/spec/cf/cli/start/target_spec.rb +123 -0
- data/spec/cf/cli/user/create_spec.rb +54 -0
- data/spec/cf/cli/user/passwd_spec.rb +102 -0
- data/spec/cf/cli/user/register_spec.rb +140 -0
- data/spec/cf/cli_spec.rb +442 -0
- data/spec/cf/detect_spec.rb +54 -0
- data/spec/console_app_specker/console_app_specker_matchers_spec.rb +173 -0
- data/spec/console_app_specker/specker_runner_spec.rb +167 -0
- data/spec/features/account_lifecycle_spec.rb +85 -0
- data/spec/features/login_spec.rb +66 -0
- data/spec/features/push_flow_spec.rb +125 -0
- data/spec/features/switching_targets_spec.rb +32 -0
- data/spec/spec_helper.rb +72 -0
- data/spec/support/command_helper.rb +81 -0
- data/spec/support/config_helper.rb +15 -0
- data/spec/support/console_app_specker_matchers.rb +86 -0
- data/spec/support/fake_home_dir.rb +55 -0
- data/spec/support/interact_helper.rb +29 -0
- data/spec/support/shared_examples/errors.rb +40 -0
- data/spec/support/shared_examples/input.rb +14 -0
- data/spec/support/specker_runner.rb +80 -0
- data/spec/support/tracking_expector.rb +71 -0
- metadata +427 -66
- data/lib/cf/cli/app.rb +0 -595
- data/lib/cf/cli/command.rb +0 -444
- data/lib/cf/cli/dots.rb +0 -133
- data/lib/cf/cli/service.rb +0 -112
- data/lib/cf/cli/user.rb +0 -71
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require "cf/cli/organization/base"
|
|
2
|
+
|
|
3
|
+
module CF::Organization
|
|
4
|
+
class Orgs < Base
|
|
5
|
+
desc "List available organizations"
|
|
6
|
+
group :organizations
|
|
7
|
+
input :full, :desc => "Show full information for apps, services, etc.",
|
|
8
|
+
:default => false
|
|
9
|
+
def orgs
|
|
10
|
+
orgs =
|
|
11
|
+
with_progress("Getting organizations") do
|
|
12
|
+
client.organizations.sort_by(&:name)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
return if orgs.empty?
|
|
16
|
+
|
|
17
|
+
line unless quiet?
|
|
18
|
+
|
|
19
|
+
if input[:full]
|
|
20
|
+
orgs.each do |o|
|
|
21
|
+
invoke :org, :organization => o, :full => true
|
|
22
|
+
end
|
|
23
|
+
else
|
|
24
|
+
table(
|
|
25
|
+
%w{name spaces domains},
|
|
26
|
+
orgs.collect { |o|
|
|
27
|
+
[ c(o.name, :name),
|
|
28
|
+
name_list(o.spaces),
|
|
29
|
+
name_list(o.domains)
|
|
30
|
+
]
|
|
31
|
+
})
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
require "cf/cli/organization/base"
|
|
2
|
+
|
|
3
|
+
module CF::Organization
|
|
4
|
+
class Rename < Base
|
|
5
|
+
desc "Rename an organization"
|
|
6
|
+
group :organizations, :hidden => true
|
|
7
|
+
input :organization, :desc => "Organization to rename",
|
|
8
|
+
:aliases => ["--org", "-o"], :argument => :optional,
|
|
9
|
+
:from_given => by_name(:organization)
|
|
10
|
+
input :name, :desc => "New organization name", :argument => :optional
|
|
11
|
+
def rename_org
|
|
12
|
+
organization = input[:organization]
|
|
13
|
+
name = input[:name]
|
|
14
|
+
|
|
15
|
+
organization.name = name
|
|
16
|
+
|
|
17
|
+
with_progress("Renaming to #{c(name, :name)}") do
|
|
18
|
+
organization.update!
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def ask_name
|
|
25
|
+
ask("New name")
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def ask_organization
|
|
29
|
+
organizations = client.organizations
|
|
30
|
+
fail "No organizations." if organizations.empty?
|
|
31
|
+
|
|
32
|
+
ask("Rename which organization?", :choices => organizations.sort_by(&:name),
|
|
33
|
+
:display => proc(&:name))
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
require "cf/cli/route/base"
|
|
2
|
+
|
|
3
|
+
module CF::Route
|
|
4
|
+
class Map < Base
|
|
5
|
+
def precondition; end
|
|
6
|
+
|
|
7
|
+
desc "Add a URL mapping"
|
|
8
|
+
group :apps, :info, :hidden => true
|
|
9
|
+
input :app, :desc => "Application to add the URL to",
|
|
10
|
+
:argument => :optional, :from_given => by_name(:app)
|
|
11
|
+
input :host, :desc => "Host name for the route",
|
|
12
|
+
:argument => :optional, :default => ""
|
|
13
|
+
input :domain, :desc => "Domain to add the route to",
|
|
14
|
+
:argument => true,
|
|
15
|
+
:from_given => proc { |name, space|
|
|
16
|
+
space.domain_by_name(name) ||
|
|
17
|
+
fail_unknown("domain", name)
|
|
18
|
+
}
|
|
19
|
+
def map
|
|
20
|
+
app = input[:app]
|
|
21
|
+
space = app.space
|
|
22
|
+
|
|
23
|
+
host = input[:host]
|
|
24
|
+
domain = input[:domain, space]
|
|
25
|
+
|
|
26
|
+
route = find_or_create_route(domain, host, space)
|
|
27
|
+
|
|
28
|
+
bind_route(route, app) if app
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def bind_route(route, app)
|
|
34
|
+
with_progress("Binding #{c(route.name, :name)} to #{c(app.name, :name)}") do
|
|
35
|
+
app.add_route(route)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def find_or_create_route(domain, host, space)
|
|
40
|
+
find_route(domain, host) || create_route(domain, host, space)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def find_route(domain, host)
|
|
44
|
+
client.routes_by_host(host, :depth => 0).find { |r| r.domain == domain }
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def create_route(domain, host, space)
|
|
48
|
+
route = client.route
|
|
49
|
+
route.host = host
|
|
50
|
+
route.domain = domain
|
|
51
|
+
route.space = space
|
|
52
|
+
|
|
53
|
+
with_progress("Creating route #{c(route.name, :name)}") do
|
|
54
|
+
route.create!
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
route
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def find_domain(space, name)
|
|
61
|
+
domain = space.domain_by_name(name, :depth => 0)
|
|
62
|
+
fail "Invalid domain '#{name}'" unless domain
|
|
63
|
+
domain
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def ask_app
|
|
67
|
+
ask("Which application?", :choices => client.apps, :display => proc(&:name))
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require "cf/cli/route/base"
|
|
2
|
+
|
|
3
|
+
module CF::Route
|
|
4
|
+
class Routes < Base
|
|
5
|
+
desc "List routes in a space"
|
|
6
|
+
group :routes
|
|
7
|
+
|
|
8
|
+
def routes
|
|
9
|
+
# TODO: scope to space once space.routes is possible
|
|
10
|
+
routes =
|
|
11
|
+
with_progress("Getting routes") do
|
|
12
|
+
client.routes
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
line unless quiet?
|
|
16
|
+
|
|
17
|
+
table(
|
|
18
|
+
%w{host domain},
|
|
19
|
+
routes.sort_by { |r| "#{r.domain.name} #{r.host}" }.collect { |r|
|
|
20
|
+
[c(r.host, :name),
|
|
21
|
+
r.domain.name
|
|
22
|
+
]
|
|
23
|
+
})
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
require "cf/cli/route/base"
|
|
2
|
+
|
|
3
|
+
module CF::Route
|
|
4
|
+
class Unmap < Base
|
|
5
|
+
desc "Remove a URL mapping"
|
|
6
|
+
group :apps, :info, :hidden => true
|
|
7
|
+
input :url, :desc => "URL to unmap", :argument => :optional,
|
|
8
|
+
:from_given => find_by_name("route") { client.routes }
|
|
9
|
+
input :app, :desc => "Application to remove the URL from",
|
|
10
|
+
:argument => :optional, :from_given => by_name(:app)
|
|
11
|
+
input :delete, :desc => "Delete route", :type => :boolean
|
|
12
|
+
input :all, :desc => "Act on all routes", :type => :boolean
|
|
13
|
+
input :really, :type => :boolean, :forget => true, :hidden => true,
|
|
14
|
+
:default => proc { force? || interact }
|
|
15
|
+
def unmap
|
|
16
|
+
if input[:all]
|
|
17
|
+
if input.has?(:app)
|
|
18
|
+
app = target = input[:app]
|
|
19
|
+
return unless !input[:delete] || input[:really, "ALL URLS bound to #{target.name}", :bad]
|
|
20
|
+
else
|
|
21
|
+
target = client
|
|
22
|
+
return unless !input[:delete] || input[:really, "ALL URLS", :bad]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
target.routes.each do |r|
|
|
26
|
+
begin
|
|
27
|
+
invoke :unmap, :delete => input[:delete], :url => r, :really => true, :app => app
|
|
28
|
+
rescue CFoundry::APIError => e
|
|
29
|
+
err "#{e.class}: #{e.message}"
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
return
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
app = input[:app]
|
|
37
|
+
url = input[:url, app ? app.routes : client.routes]
|
|
38
|
+
|
|
39
|
+
if input[:delete]
|
|
40
|
+
with_progress("Deleting route #{c(url.name, :name)}") do
|
|
41
|
+
url.delete!
|
|
42
|
+
end
|
|
43
|
+
elsif app
|
|
44
|
+
with_progress("Unbinding #{c(url.name, :name)} from #{c(app.name, :name)}") do
|
|
45
|
+
app.remove_route(url)
|
|
46
|
+
end
|
|
47
|
+
else
|
|
48
|
+
fail "Missing either --delete or --app."
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
private
|
|
53
|
+
|
|
54
|
+
def ask_url(choices)
|
|
55
|
+
ask("Which URL?", :choices => choices.sort_by(&:name), :display => proc(&:name))
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def ask_really(name, color)
|
|
59
|
+
ask("Really delete #{c(name, color)}?", :default => false)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
require "cf/detect"
|
|
2
|
+
|
|
3
|
+
require "cf/cli/service/base"
|
|
4
|
+
|
|
5
|
+
module CF::Service
|
|
6
|
+
class Bind < Base
|
|
7
|
+
desc "Bind a service to an application"
|
|
8
|
+
group :services, :manage
|
|
9
|
+
input :service, :desc => "Service to bind", :argument => :optional,
|
|
10
|
+
:from_given => by_name(:service_instance, "service")
|
|
11
|
+
input :app, :desc => "Application to bind to", :argument => :optional,
|
|
12
|
+
:from_given => by_name(:app)
|
|
13
|
+
def bind_service
|
|
14
|
+
app = input[:app]
|
|
15
|
+
service = input[:service, app]
|
|
16
|
+
|
|
17
|
+
with_progress(
|
|
18
|
+
"Binding #{c(service.name, :name)} to #{c(app.name, :name)}") do |s|
|
|
19
|
+
if app.binds?(service)
|
|
20
|
+
s.skip do
|
|
21
|
+
err "App #{b(app.name)} already binds #{b(service.name)}."
|
|
22
|
+
end
|
|
23
|
+
else
|
|
24
|
+
app.bind(service)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def ask_service(app)
|
|
32
|
+
services = client.service_instances
|
|
33
|
+
fail "No services." if services.empty?
|
|
34
|
+
|
|
35
|
+
ask "Which service?", :choices => services - app.services,
|
|
36
|
+
:display => proc(&:name)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def ask_app
|
|
40
|
+
ask "Which application?", :choices => client.apps,
|
|
41
|
+
:display => proc(&:name)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
require "cf/cli/service/base"
|
|
2
|
+
|
|
3
|
+
module CF::Service
|
|
4
|
+
class Create < Base
|
|
5
|
+
offerings_from_label = proc { |label, offerings|
|
|
6
|
+
offerings.select { |s| s.label == label }
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
desc "Create a service"
|
|
10
|
+
group :services, :manage
|
|
11
|
+
input :offering, :desc => "What kind of service (e.g. redis, mysql)",
|
|
12
|
+
:argument => :optional, :from_given => offerings_from_label
|
|
13
|
+
input :name, :desc => "Name for your service", :argument => :optional
|
|
14
|
+
input :plan, :desc => "Service plan",
|
|
15
|
+
:from_given => find_by_name_insensitive("plan"),
|
|
16
|
+
:default => proc { |plans|
|
|
17
|
+
plans.find { |p| p.name == "D100" } ||
|
|
18
|
+
interact
|
|
19
|
+
}
|
|
20
|
+
input :provider, :desc => "Service provider"
|
|
21
|
+
input :version, :desc => "Service version"
|
|
22
|
+
input :app, :desc => "Application to immediately bind to",
|
|
23
|
+
:alias => "--bind", :from_given => by_name(:app)
|
|
24
|
+
def create_service
|
|
25
|
+
offerings = client.services
|
|
26
|
+
|
|
27
|
+
if input[:provider]
|
|
28
|
+
offerings.reject! { |s| s.provider != input[:provider] }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
if input[:version]
|
|
32
|
+
offerings.reject! { |s| s.version != input[:version] }
|
|
33
|
+
else
|
|
34
|
+
offerings.reject!(&:deprecated?)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# filter the offerings based on a given plan value, which will be a
|
|
38
|
+
# string if the user provided it with a flag, or a ServicePlan if
|
|
39
|
+
# something invoked this command with a particular plan
|
|
40
|
+
if plan = input.direct(:plan)
|
|
41
|
+
offerings.reject! do |s|
|
|
42
|
+
if plan.is_a?(String)
|
|
43
|
+
s.service_plans.none? { |p| p.name == plan.upcase }
|
|
44
|
+
else
|
|
45
|
+
s.service_plans.include? plan
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
until offerings.size < 2
|
|
51
|
+
# cast to Array since it might be given as a Service with #invoke
|
|
52
|
+
offerings = Array(input[:offering, offerings.sort_by(&:label)])
|
|
53
|
+
input.forget(:offering)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
if offerings.empty?
|
|
57
|
+
fail "Cannot find services matching the given criteria."
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
offering = offerings.first
|
|
61
|
+
|
|
62
|
+
service = client.service_instance
|
|
63
|
+
service.name = input[:name, offering]
|
|
64
|
+
|
|
65
|
+
service.service_plan = input[:plan, offering.service_plans]
|
|
66
|
+
service.space = client.current_space
|
|
67
|
+
|
|
68
|
+
with_progress("Creating service #{c(service.name, :name)}") do
|
|
69
|
+
service.create!
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
if app = input[:app]
|
|
73
|
+
invoke :bind_service, :service => service, :app => app
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
service
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
private
|
|
80
|
+
|
|
81
|
+
def ask_offering(offerings)
|
|
82
|
+
[ask("What kind?", :choices => offerings.sort_by(&:label),
|
|
83
|
+
:display => proc { |s|
|
|
84
|
+
str = "#{c(s.label, :name)} #{s.version}"
|
|
85
|
+
if s.provider != "core"
|
|
86
|
+
str << ", via #{s.provider}"
|
|
87
|
+
end
|
|
88
|
+
str
|
|
89
|
+
},
|
|
90
|
+
:complete => proc { |s| "#{s.label} #{s.version}" })]
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def ask_name(offering)
|
|
94
|
+
random = sprintf("%x", rand(1000000))
|
|
95
|
+
ask "Name?", :default => "#{offering.label}-#{random}"
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def ask_plan(plans, default_plan = nil)
|
|
99
|
+
ask "Which plan?",
|
|
100
|
+
:choices => plans.sort_by(&:name),
|
|
101
|
+
:indexed => true,
|
|
102
|
+
:display => proc { |p| "#{p.name}: #{p.description || 'No description'}" },
|
|
103
|
+
:default => default_plan,
|
|
104
|
+
:complete => proc(&:name)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
require "cf/cli/service/base"
|
|
2
|
+
|
|
3
|
+
module CF::Service
|
|
4
|
+
class Delete < Base
|
|
5
|
+
desc "Delete a service"
|
|
6
|
+
group :services, :manage
|
|
7
|
+
input :service, :desc => "Service to bind", :argument => :optional,
|
|
8
|
+
:from_given => by_name(:service_instance, :service)
|
|
9
|
+
input :unbind, :desc => "Unbind from applications before deleting?",
|
|
10
|
+
:type => :boolean, :default => proc { force? || interact }
|
|
11
|
+
input :all, :desc => "Delete all services", :default => false
|
|
12
|
+
input :really, :type => :boolean, :forget => true, :hidden => true,
|
|
13
|
+
:default => proc { force? || interact }
|
|
14
|
+
def delete_service
|
|
15
|
+
if input[:all]
|
|
16
|
+
return unless input[:really, "ALL SERVICES", :bad]
|
|
17
|
+
|
|
18
|
+
client.service_instances.each do |i|
|
|
19
|
+
invoke :delete_service, :service => i, :really => true
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
return
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
service = input[:service]
|
|
26
|
+
|
|
27
|
+
return unless input[:really, service.name, :name]
|
|
28
|
+
|
|
29
|
+
bindings = service.service_bindings
|
|
30
|
+
|
|
31
|
+
unless bindings.empty? || !input[:unbind, bindings.collect(&:app)]
|
|
32
|
+
bindings.each do |b|
|
|
33
|
+
invoke :unbind_service, :service => service, :app => b.app
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
bindings = []
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
with_progress("Deleting #{c(service.name, :name)}") do |s|
|
|
40
|
+
if bindings.empty?
|
|
41
|
+
service.delete!
|
|
42
|
+
else
|
|
43
|
+
s.skip do
|
|
44
|
+
apps = bindings.collect(&:app).collect { |a| b(a.name) }
|
|
45
|
+
err "Service is bound to #{human_list(apps)}."
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
private
|
|
52
|
+
|
|
53
|
+
def ask_service
|
|
54
|
+
services = client.service_instances
|
|
55
|
+
fail "No services." if services.empty?
|
|
56
|
+
|
|
57
|
+
ask "Which service?", :choices => services,
|
|
58
|
+
:display => proc(&:name)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def ask_unbind(apps)
|
|
62
|
+
names = human_list(apps.collect { |a| c(a.name, :name) })
|
|
63
|
+
|
|
64
|
+
ask("Unbind from #{names} before deleting?", :default => true)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def ask_really(name, color)
|
|
68
|
+
ask("Really delete #{c(name, color)}?", :default => false)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def human_list(xs)
|
|
72
|
+
if xs.size == 1
|
|
73
|
+
xs.first
|
|
74
|
+
elsif xs.size == 2
|
|
75
|
+
"#{xs.first} and #{xs.last}"
|
|
76
|
+
else
|
|
77
|
+
last = xs.pop
|
|
78
|
+
xs.join(", ") + ", and #{last}"
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|