jdc 0.1.2 → 0.2.0

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.
Files changed (151) hide show
  1. data/LICENSE +1277 -24
  2. data/Rakefile +13 -0
  3. data/bin/jdc +12 -2
  4. data/lib/admin/README.md +15 -0
  5. data/lib/admin/curl.rb +60 -0
  6. data/lib/admin/guid.rb +89 -0
  7. data/lib/admin/plugin.rb +6 -0
  8. data/lib/admin/service_auth_token.rb +94 -0
  9. data/lib/admin/service_broker/add.rb +47 -0
  10. data/lib/admin/service_broker/service_brokers.rb +24 -0
  11. data/lib/admin/set_quota.rb +44 -0
  12. data/lib/console/README.md +8 -0
  13. data/lib/console/console.rb +187 -0
  14. data/lib/console/plugin.rb +33 -0
  15. data/lib/jdc/cli/app/app.rb +43 -0
  16. data/lib/jdc/cli/app/apps.rb +87 -0
  17. data/lib/jdc/cli/app/base.rb +72 -0
  18. data/lib/jdc/cli/app/delete.rb +95 -0
  19. data/lib/jdc/cli/app/deprecated.rb +11 -0
  20. data/lib/jdc/cli/app/env.rb +78 -0
  21. data/lib/jdc/cli/app/events.rb +45 -0
  22. data/lib/jdc/cli/app/files.rb +137 -0
  23. data/lib/jdc/cli/app/health.rb +26 -0
  24. data/lib/jdc/cli/app/instances.rb +53 -0
  25. data/lib/jdc/cli/app/logs.rb +76 -0
  26. data/lib/jdc/cli/app/push/create.rb +108 -0
  27. data/lib/jdc/cli/app/push/interactions.rb +86 -0
  28. data/lib/jdc/cli/app/push/sync.rb +57 -0
  29. data/lib/jdc/cli/app/push.rb +103 -0
  30. data/lib/jdc/cli/app/rename.rb +35 -0
  31. data/lib/jdc/cli/app/restart.rb +31 -0
  32. data/lib/jdc/cli/app/scale.rb +63 -0
  33. data/lib/jdc/cli/app/start.rb +161 -0
  34. data/lib/jdc/cli/app/stats.rb +67 -0
  35. data/lib/jdc/cli/app/stop.rb +27 -0
  36. data/lib/jdc/cli/domain/base.rb +9 -0
  37. data/lib/jdc/cli/domain/domains.rb +40 -0
  38. data/lib/jdc/cli/domain/map.rb +55 -0
  39. data/lib/jdc/cli/domain/unmap.rb +56 -0
  40. data/lib/jdc/cli/help.rb +15 -0
  41. data/lib/jdc/cli/interactive.rb +105 -0
  42. data/lib/jdc/cli/login_requirements.rb +15 -0
  43. data/lib/jdc/cli/organization/base.rb +14 -0
  44. data/lib/jdc/cli/organization/create.rb +37 -0
  45. data/lib/jdc/cli/organization/delete.rb +63 -0
  46. data/lib/jdc/cli/organization/org.rb +45 -0
  47. data/lib/jdc/cli/organization/orgs.rb +30 -0
  48. data/lib/jdc/cli/organization/rename.rb +37 -0
  49. data/lib/jdc/cli/populators/base.rb +16 -0
  50. data/lib/jdc/cli/populators/organization.rb +32 -0
  51. data/lib/jdc/cli/populators/populator_methods.rb +64 -0
  52. data/lib/jdc/cli/populators/space.rb +33 -0
  53. data/lib/jdc/cli/populators/target.rb +13 -0
  54. data/lib/jdc/cli/route/base.rb +9 -0
  55. data/lib/jdc/cli/route/delete.rb +28 -0
  56. data/lib/jdc/cli/route/map.rb +68 -0
  57. data/lib/jdc/cli/route/routes.rb +26 -0
  58. data/lib/jdc/cli/route/unmap.rb +56 -0
  59. data/lib/jdc/cli/service/base.rb +9 -0
  60. data/lib/jdc/cli/service/bind.rb +44 -0
  61. data/lib/jdc/cli/service/create.rb +159 -0
  62. data/lib/jdc/cli/service/delete.rb +83 -0
  63. data/lib/jdc/cli/service/rename.rb +36 -0
  64. data/lib/jdc/cli/service/service.rb +42 -0
  65. data/lib/jdc/cli/service/service_instance_helper.rb +99 -0
  66. data/lib/jdc/cli/service/services.rb +111 -0
  67. data/lib/jdc/cli/service/unbind.rb +37 -0
  68. data/lib/jdc/cli/space/base.rb +29 -0
  69. data/lib/jdc/cli/space/create.rb +67 -0
  70. data/lib/jdc/cli/space/delete.rb +56 -0
  71. data/lib/jdc/cli/space/rename.rb +38 -0
  72. data/lib/jdc/cli/space/space.rb +66 -0
  73. data/lib/jdc/cli/space/spaces.rb +57 -0
  74. data/lib/jdc/cli/space/switch.rb +19 -0
  75. data/lib/jdc/cli/start/base.rb +41 -0
  76. data/lib/jdc/cli/start/colors.rb +13 -0
  77. data/lib/jdc/cli/start/target.rb +50 -0
  78. data/lib/jdc/cli/start/target_prettifier.rb +17 -0
  79. data/lib/jdc/cli/start/targets.rb +16 -0
  80. data/lib/jdc/cli/user/base.rb +30 -0
  81. data/lib/jdc/cli/user/create.rb +52 -0
  82. data/lib/jdc/cli/user/passwd.rb +37 -0
  83. data/lib/jdc/cli/user/register.rb +43 -0
  84. data/lib/jdc/cli/user/users.rb +32 -0
  85. data/lib/jdc/cli.rb +544 -0
  86. data/lib/jdc/constants.rb +11 -0
  87. data/lib/jdc/errors.rb +19 -0
  88. data/lib/jdc/object_extensions.rb +15 -0
  89. data/lib/jdc/plugin.rb +56 -0
  90. data/lib/jdc/spacing.rb +89 -0
  91. data/lib/jdc/spec_helper.rb +1 -0
  92. data/lib/jdc/test_support.rb +6 -0
  93. data/lib/jdc/version.rb +3 -0
  94. data/lib/jdc.rb +15 -2
  95. data/lib/manifests/errors.rb +35 -0
  96. data/lib/manifests/loader/builder.rb +39 -0
  97. data/lib/manifests/loader/normalizer.rb +145 -0
  98. data/lib/manifests/loader/resolver.rb +79 -0
  99. data/lib/manifests/loader.rb +31 -0
  100. data/lib/manifests/manifests.rb +344 -0
  101. data/lib/manifests/plugin.rb +140 -0
  102. data/lib/micro/README.md +9 -0
  103. data/lib/micro/errors.rb +4 -0
  104. data/lib/{jdc → micro}/micro.rb +15 -15
  105. data/lib/micro/plugin.rb +197 -0
  106. data/lib/micro/switcher/base.rb +79 -0
  107. data/lib/{jdc/micro → micro}/switcher/darwin.rb +5 -3
  108. data/lib/{jdc/micro → micro}/switcher/dummy.rb +1 -1
  109. data/lib/micro/switcher/linux.rb +16 -0
  110. data/lib/{jdc/micro → micro}/switcher/windows.rb +5 -5
  111. data/lib/{jdc/micro → micro}/vmrun.rb +26 -19
  112. data/lib/tasks/gem_release.rake +42 -0
  113. data/lib/tunnel/README.md +29 -0
  114. data/{config → lib/tunnel/config}/clients.yml +2 -2
  115. data/lib/tunnel/helper-app/Gemfile +10 -0
  116. data/lib/tunnel/helper-app/Gemfile.lock +48 -0
  117. data/{caldecott_helper → lib/tunnel/helper-app}/server.rb +5 -5
  118. data/lib/tunnel/plugin.rb +183 -0
  119. data/lib/tunnel/tunnel.rb +295 -0
  120. metadata +319 -89
  121. data/README.md +0 -102
  122. data/config/micro/paths.yml +0 -22
  123. data/config/micro/refresh_ip.rb +0 -20
  124. data/lib/cli/commands/admin.rb +0 -58
  125. data/lib/cli/commands/apps.rb +0 -1129
  126. data/lib/cli/commands/base.rb +0 -228
  127. data/lib/cli/commands/manifest.rb +0 -56
  128. data/lib/cli/commands/micro.rb +0 -115
  129. data/lib/cli/commands/misc.rb +0 -126
  130. data/lib/cli/commands/services.rb +0 -178
  131. data/lib/cli/commands/user.rb +0 -14
  132. data/lib/cli/config.rb +0 -173
  133. data/lib/cli/console_helper.rb +0 -170
  134. data/lib/cli/core_ext.rb +0 -122
  135. data/lib/cli/errors.rb +0 -19
  136. data/lib/cli/frameworks.rb +0 -265
  137. data/lib/cli/manifest_helper.rb +0 -302
  138. data/lib/cli/runner.rb +0 -505
  139. data/lib/cli/services_helper.rb +0 -84
  140. data/lib/cli/tunnel_helper.rb +0 -332
  141. data/lib/cli/usage.rb +0 -86
  142. data/lib/cli/version.rb +0 -7
  143. data/lib/cli/zip_util.rb +0 -77
  144. data/lib/cli.rb +0 -53
  145. data/lib/jdc/client.rb +0 -457
  146. data/lib/jdc/const.rb +0 -25
  147. data/lib/jdc/micro/switcher/base.rb +0 -97
  148. data/lib/jdc/micro/switcher/linux.rb +0 -16
  149. data/lib/jdc/signature/version.rb +0 -27
  150. data/lib/jdc/signer.rb +0 -13
  151. data/lib/jdc/timer.rb +0 -12
@@ -0,0 +1,64 @@
1
+ module JDC
2
+ module Populators
3
+ module PopulatorMethods
4
+ def self.included(klass)
5
+ klass.class_eval do
6
+ define_method(:type) do
7
+ klass.name.split("::").last.downcase.to_sym
8
+ end
9
+ end
10
+ end
11
+
12
+ def populate_and_save!
13
+ obj = get_object
14
+ info[type] = obj.guid unless obj.nil?
15
+ save_target_info(info)
16
+ invalidate_client
17
+
18
+ obj
19
+ end
20
+
21
+ private
22
+
23
+ def get_object
24
+ previous_object = client.send(type, (info[type])) if info[type]
25
+
26
+ if input.has?(type)
27
+ if respond_to?(:finder_argument, true)
28
+ object = input[type, finder_argument]
29
+ else
30
+ object = input[type]
31
+ end
32
+
33
+ with_progress("Switching to #{type} #{c(object.name, :name)}") {}
34
+ elsif info[type]
35
+ object = previous_object if valid?(previous_object)
36
+ end
37
+
38
+ object ||= prompt_user
39
+
40
+ if (previous_object != object) && respond_to?(:changed, true)
41
+ changed
42
+ end
43
+
44
+ object
45
+ end
46
+
47
+ def prompt_user
48
+ object_choices = choices
49
+
50
+ if object_choices.empty?
51
+ with_progress("There are no #{type}s. You may want to create one with #{c("create-#{type == :organization ? "org" : type}", :good)}.") {}
52
+ elsif object_choices.is_a?(String)
53
+ raise JDC::UserFriendlyError.new(object_choices)
54
+ elsif object_choices.size == 1 && !input.interactive?(type)
55
+ object_choices.first
56
+ else
57
+ ask(type.to_s.capitalize, :choices => object_choices.sort_by(&:name), :display => proc(&:name)).tap do |object|
58
+ with_progress("Switching to #{type} #{c(object.name, :name)}") {}
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,33 @@
1
+ require "jdc/cli/populators/base"
2
+ require "jdc/cli/populators/populator_methods"
3
+
4
+ module JDC
5
+ module Populators
6
+ class Space < Base
7
+ attr_reader :organization
8
+ include PopulatorMethods
9
+
10
+ def initialize(input, organization)
11
+ super(input)
12
+ @organization = organization
13
+ end
14
+
15
+ private
16
+
17
+ def valid?(space)
18
+ return false unless space.guid
19
+ space.developers.include? client.current_user
20
+ rescue JFoundry::APIError
21
+ false
22
+ end
23
+
24
+ def choices
25
+ organization.spaces(:depth => 0)
26
+ end
27
+
28
+ def finder_argument
29
+ organization
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,13 @@
1
+ require "jdc/cli/populators/organization"
2
+ require "jdc/cli/populators/space"
3
+
4
+ module JDC
5
+ module Populators
6
+ class Target < Base
7
+ def populate_and_save!
8
+ organization = JDC::Populators::Organization.new(input).populate_and_save!
9
+ JDC::Populators::Space.new(input, organization).populate_and_save!
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,9 @@
1
+ require "jdc/cli"
2
+
3
+ module JDC
4
+ module Route
5
+ class Base < CLI
6
+ include LoginRequirements
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,28 @@
1
+ require "jdc/cli/route/base"
2
+
3
+ module JDC::Route
4
+ class Delete < Base
5
+ desc "Delete a route"
6
+ group :routes
7
+ input :route, :desc => "Route to unmap", :argument => true,
8
+ :from_given => find_by_name("route") { client.routes }
9
+ input :really, :type => :boolean, :forget => true, :hidden => true,
10
+ :default => proc { force? || interact }
11
+
12
+ def delete_route
13
+ route = input[:route, client.routes]
14
+
15
+ return unless input[:really, route]
16
+
17
+ with_progress("Deleting route #{c(route.name, :name)}") do
18
+ route.delete!
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def ask_really(route)
25
+ ask("Really delete #{c(route.name, :name)}?", :default => false)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,68 @@
1
+ require "jdc/cli/route/base"
2
+
3
+ module JDC::Route
4
+ class Map < Base
5
+ desc "Add a URL mapping"
6
+ group :apps, :info
7
+ input :app, :desc => "Application to add the URL to",
8
+ :argument => :optional, :from_given => by_name(:app)
9
+ input :host, :desc => "Host name for the route",
10
+ :argument => :optional, :default => ""
11
+ input :domain, :desc => "Domain to add the route to",
12
+ :argument => true,
13
+ :from_given => proc { |name, space|
14
+ space.domain_by_name(name) ||
15
+ fail_unknown("domain", name)
16
+ }
17
+ def map
18
+ app = input[:app]
19
+ space = app.space
20
+
21
+ host = input[:host]
22
+ domain = input[:domain, space]
23
+
24
+ route = find_or_create_route(domain, host, space)
25
+
26
+ bind_route(route, app) if app
27
+ end
28
+
29
+ private
30
+
31
+ def bind_route(route, app)
32
+ with_progress("Binding #{c(route.name, :name)} to #{c(app.name, :name)}") do
33
+ app.add_route(route)
34
+ end
35
+ end
36
+
37
+ def find_or_create_route(domain, host, space)
38
+ find_route(domain, host) || create_route(domain, host, space)
39
+ end
40
+
41
+ def find_route(domain, host)
42
+ client.routes_by_host(host, :depth => 0).find { |r| r.domain == domain }
43
+ end
44
+
45
+ def create_route(domain, host, space)
46
+ route = client.route
47
+ route.host = host
48
+ route.domain = domain
49
+ route.space = space
50
+
51
+ with_progress("Creating route #{c(route.name, :name)}") do
52
+ route.create!
53
+ end
54
+
55
+ route
56
+ end
57
+
58
+ def find_domain(space, name)
59
+ domain = space.domain_by_name(name, :depth => 0)
60
+ fail "Invalid domain '#{name}'" unless domain
61
+ domain
62
+ end
63
+
64
+ def ask_app
65
+ ask("Which application?", :choices => client.apps, :display => proc(&:name))
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,26 @@
1
+ require "jdc/cli/route/base"
2
+
3
+ module JDC::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,56 @@
1
+ require "jdc/cli/route/base"
2
+
3
+ module JDC::Route
4
+ class Unmap < Base
5
+ desc "Remove a URL mapping"
6
+ group :apps, :info
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 :all, :desc => "Act on all routes", :type => :boolean
12
+ input :really, :type => :boolean, :forget => true, :hidden => true,
13
+ :default => proc { force? || interact }
14
+
15
+ def unmap
16
+ if input[:all]
17
+ if input.has?(:app)
18
+ app = target = input[:app]
19
+ else
20
+ target = client
21
+ end
22
+
23
+ target.routes.each do |r|
24
+ begin
25
+ invoke :unmap, :url => r, :really => true, :app => app
26
+ rescue JFoundry::APIError => e
27
+ err "#{e.class}: #{e.message}"
28
+ end
29
+ end
30
+
31
+ return
32
+ end
33
+
34
+ app = input[:app]
35
+ url = input[:url, app ? app.routes : client.routes]
36
+
37
+ if app
38
+ with_progress("Unbinding #{c(url.name, :name)} from #{c(app.name, :name)}") do
39
+ app.remove_route(url)
40
+ end
41
+ else
42
+ fail "Missing --app."
43
+ end
44
+ end
45
+
46
+ private
47
+
48
+ def ask_url(choices)
49
+ ask("Which URL?", :choices => choices.sort_by(&:name), :display => proc(&:name))
50
+ end
51
+
52
+ def ask_really(name, color)
53
+ ask("Really delete #{c(name, color)}?", :default => false)
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,9 @@
1
+ require "jdc/cli"
2
+
3
+ module JDC
4
+ module Service
5
+ class Base < CLI
6
+ include LoginRequirements
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,44 @@
1
+ require "jdc/cli/service/base"
2
+ =begin
3
+ module JDC::Service
4
+ class Bind < Base
5
+ desc "Bind a service to an application"
6
+ group :services, :manage
7
+ input :service, :desc => "Service to bind", :argument => :optional,
8
+ :from_given => by_name(:service_instance, "service")
9
+ input :app, :desc => "Application to bind to", :argument => :optional,
10
+ :from_given => by_name(:app)
11
+ def bind_service
12
+ app = input[:app]
13
+ service = input[:service, app]
14
+ finalize
15
+
16
+ with_progress(
17
+ "Binding #{c(service.name, :name)} to #{c(app.name, :name)}") do |s|
18
+ if app.binds?(service)
19
+ s.skip do
20
+ err "App #{b(app.name)} already binds #{b(service.name)}."
21
+ end
22
+ else
23
+ app.bind(service)
24
+ end
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def ask_service(app)
31
+ services = client.service_instances
32
+ fail "No services." if services.empty?
33
+
34
+ ask "Which service?", :choices => services - app.services,
35
+ :display => proc(&:name)
36
+ end
37
+
38
+ def ask_app
39
+ ask "Which application?", :choices => client.apps,
40
+ :display => proc(&:name)
41
+ end
42
+ end
43
+ end
44
+ =end
@@ -0,0 +1,159 @@
1
+ require "jdc/cli/service/base"
2
+ =begin
3
+ module JDC::Service
4
+ USER_PROVIDED_OFFERING = "user-provided" # I'd rather move this to JFoundry
5
+
6
+ class UPDummy
7
+ def label
8
+ "user-provided"
9
+ end
10
+
11
+ attr_reader :version, :provider
12
+ end
13
+
14
+ class Create < Base
15
+ offerings_from_label = proc { |label, offerings|
16
+ offerings.select { |s| s.label == label }
17
+ }
18
+
19
+ desc "Create a service"
20
+ group :services, :manage
21
+ input :offering, :desc => "What kind of service (e.g. redis, mysql)",
22
+ :argument => :optional, :from_given => offerings_from_label
23
+ input :name, :desc => "Name for your service", :argument => :optional
24
+ input :plan, :desc => "Service plan",
25
+ :from_given => find_by_name_insensitive("plan"),
26
+ :default => proc {
27
+ interact
28
+ }
29
+ input :provider, :desc => "Service provider"
30
+ input :version, :desc => "Service version"
31
+ input :app, :desc => "Application to immediately bind to",
32
+ :alias => "--bind", :from_given => by_name(:app)
33
+
34
+ def create_service
35
+ offerings = client.services
36
+
37
+ if input[:provider]
38
+ offerings.reject! { |s| s.provider != input[:provider] }
39
+ end
40
+
41
+ if input[:version]
42
+ offerings.reject! { |s| s.version != input[:version] }
43
+ end
44
+
45
+ # filter the offerings based on a given plan value, which will be a
46
+ # string if the user provided it with a flag, or a ServicePlan if
47
+ # something invoked this command with a particular plan
48
+ if plan = input.direct(:plan)
49
+ offerings.reject! do |s|
50
+ if plan.is_a?(String)
51
+ s.service_plans.none? { |p| p.name.casecmp(plan) == 0 }
52
+ else
53
+ !s.service_plans.include? plan
54
+ end
55
+ end
56
+ end
57
+ finalize
58
+
59
+ offerings << UPDummy.new
60
+
61
+ selected_offerings = offerings.any? ? Array(input[:offering, offerings.sort_by(&:label)]) : []
62
+ finalize
63
+
64
+ if selected_offerings.empty?
65
+ fail "Cannot find services matching the given criteria."
66
+ end
67
+
68
+ offering = selected_offerings.first
69
+
70
+ if offering.label == JDC::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!
95
+ end
96
+
97
+ app = input[:app]
98
+ finalize
99
+
100
+ if app
101
+ invoke :bind_service, :service => service_instance, :app => app
102
+ end
103
+ service_instance
104
+ end
105
+
106
+ private
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
+
128
+ def ask_offering(offerings)
129
+ [ask("What kind?", :choices => offerings.sort_by(&:label),
130
+ :display => proc do |s|
131
+ str = "#{c(s.label, :name)} #{s.version}"
132
+ if s.provider != "core"
133
+ str << ", via #{s.provider}"
134
+ end
135
+ str
136
+ end,
137
+ :complete => proc { |s| "#{s.label} #{s.version}" })]
138
+ end
139
+
140
+ def ask_name(offering)
141
+ default = nil
142
+ unless offering == JDC::Service::USER_PROVIDED_OFFERING
143
+ random = sprintf("%x", rand(1000000))
144
+ default = "#{offering.label}-#{random}"
145
+ end
146
+
147
+ ask "Name?", :default => default
148
+ end
149
+
150
+ def ask_plan(plans)
151
+ ask "Which plan?",
152
+ :choices => plans.sort_by(&:name),
153
+ :indexed => true,
154
+ :display => proc { |p| "#{p.name}: #{p.description || 'No description'}" },
155
+ :complete => proc(&:name)
156
+ end
157
+ end
158
+ end
159
+ =end
@@ -0,0 +1,83 @@
1
+ require "jdc/cli/service/base"
2
+ =begin
3
+ module JDC::Service
4
+ class Delete < Base
5
+ desc "Delete a service"
6
+ group :services, :manage
7
+ input :service, :desc => "Service to delete", :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
83
+ =end
@@ -0,0 +1,36 @@
1
+ require "jdc/cli/service/base"
2
+ =begin
3
+ module JDC::Service
4
+ class Rename < Base
5
+ desc "Rename a service"
6
+ group :services, :manage
7
+ input :service, :desc => "Service to rename", :argument => :optional,
8
+ :from_given => by_name(:service_instance, :service)
9
+ input :name, :desc => "New service name", :argument => :optional
10
+ def rename_service
11
+ service = input[:service]
12
+ name = input[:name]
13
+
14
+ service.name = name
15
+
16
+ with_progress("Renaming to #{c(name, :name)}") do
17
+ service.update!
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def ask_service
24
+ services = client.service_instances
25
+ fail "No services." if services.empty?
26
+
27
+ ask("Rename which service?", :choices => services.sort_by(&:name),
28
+ :display => proc(&:name))
29
+ end
30
+
31
+ def ask_name
32
+ ask("New name")
33
+ end
34
+ end
35
+ end
36
+ =end
@@ -0,0 +1,42 @@
1
+ require "jdc/cli/service/base"
2
+
3
+ =begin
4
+ module JDC::Service
5
+ class Service < Base
6
+ desc "Show service information"
7
+ group :services
8
+ input :service, :desc => "Service to show", :argument => :required,
9
+ :from_given => by_name(:service_instance, :service)
10
+ def service
11
+ display_service(input[:service])
12
+ end
13
+
14
+ private
15
+
16
+ def display_service(i)
17
+ if quiet?
18
+ line i.name
19
+ else
20
+ plan = i.service_plan
21
+ service = plan.service
22
+
23
+ apps = i.service_bindings.collect { |b|
24
+ c(b.app.name, :name)
25
+ }.join(", ")
26
+
27
+ line "#{c(i.name, :name)}: #{service.label} #{service.version}"
28
+
29
+ indented do
30
+ line "provider: #{c(service.provider, :name)}"
31
+ line "bound to: #{apps}" unless apps.empty?
32
+ line "plan: #{c(plan.name, :name)}"
33
+
34
+ indented do
35
+ line "description: #{plan.description}"
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ =end