vmc 0.4.2 → 0.4.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.
Files changed (63) hide show
  1. data/lib/vmc.rb +2 -5
  2. data/lib/vmc/cli/app/apps.rb +4 -1
  3. data/lib/vmc/cli/app/push.rb +38 -221
  4. data/lib/vmc/cli/app/push/create.rb +125 -0
  5. data/lib/vmc/cli/app/push/interaction.rb +64 -0
  6. data/lib/vmc/cli/app/push/sync.rb +59 -0
  7. data/lib/vmc/cli/app/rename.rb +1 -1
  8. data/lib/vmc/cli/organization/base.rb +14 -0
  9. data/lib/vmc/cli/organization/create_org.rb +28 -0
  10. data/lib/vmc/cli/organization/delete_org.rb +65 -0
  11. data/lib/vmc/cli/organization/org.rb +46 -0
  12. data/lib/vmc/cli/organization/orgs.rb +35 -0
  13. data/lib/vmc/cli/organization/rename.rb +32 -0
  14. data/lib/vmc/cli/service/base.rb +8 -0
  15. data/lib/vmc/cli/service/binding.rb +66 -0
  16. data/lib/vmc/cli/service/create.rb +104 -0
  17. data/lib/vmc/cli/service/delete.rb +84 -0
  18. data/lib/vmc/cli/service/rename.rb +32 -0
  19. data/lib/vmc/cli/service/service.rb +45 -0
  20. data/lib/vmc/cli/service/services.rb +118 -0
  21. data/lib/vmc/cli/space/base.rb +21 -0
  22. data/lib/vmc/cli/space/create.rb +57 -0
  23. data/lib/vmc/cli/space/delete.rb +92 -0
  24. data/lib/vmc/cli/space/rename.rb +36 -0
  25. data/lib/vmc/cli/space/space.rb +67 -0
  26. data/lib/vmc/cli/space/spaces.rb +57 -0
  27. data/lib/vmc/cli/space/take.rb +18 -0
  28. data/lib/vmc/cli/start/base.rb +100 -0
  29. data/lib/vmc/cli/start/colors.rb +14 -0
  30. data/lib/vmc/cli/start/info.rb +124 -0
  31. data/lib/vmc/cli/start/login.rb +94 -0
  32. data/lib/vmc/cli/start/logout.rb +14 -0
  33. data/lib/vmc/cli/start/register.rb +38 -0
  34. data/lib/vmc/cli/start/target.rb +68 -0
  35. data/lib/vmc/cli/start/targets.rb +17 -0
  36. data/lib/vmc/version.rb +1 -1
  37. data/spec/factories/app_factory.rb +5 -0
  38. data/spec/factories/client_factory.rb +10 -1
  39. data/spec/factories/domain_factory.rb +2 -1
  40. data/spec/factories/factory.rb +1 -0
  41. data/spec/factories/framework_factory.rb +1 -0
  42. data/spec/factories/organization_factory.rb +18 -0
  43. data/spec/factories/route_factory.rb +1 -0
  44. data/spec/factories/runtime_factory.rb +10 -0
  45. data/spec/factories/service_binding_factory.rb +9 -0
  46. data/spec/factories/service_factory.rb +17 -0
  47. data/spec/factories/service_instance_factory.rb +10 -0
  48. data/spec/factories/service_plan_factory.rb +11 -0
  49. data/spec/factories/space_factory.rb +10 -0
  50. data/spec/support/interact_helpers.rb +7 -3
  51. data/spec/vmc/cli/app/push/create_spec.rb +450 -0
  52. data/spec/vmc/cli/app/push_spec.rb +303 -9
  53. data/spec/vmc/cli/app/rename_spec.rb +9 -4
  54. data/spec/vmc/cli/organization/rename_spec.rb +113 -0
  55. data/spec/vmc/cli/route/delete_route_spec.rb +2 -2
  56. data/spec/vmc/cli/service/rename_spec.rb +114 -0
  57. data/spec/vmc/cli/space/rename_spec.rb +114 -0
  58. metadata +109 -64
  59. data/lib/vmc/cli/organization.rb +0 -176
  60. data/lib/vmc/cli/service.rb +0 -387
  61. data/lib/vmc/cli/space.rb +0 -284
  62. data/lib/vmc/cli/start.rb +0 -432
  63. data/spec/assets/hello-sinatra/Gemfile.lock +0 -17
@@ -1,176 +0,0 @@
1
- require "vmc/cli"
2
-
3
- module VMC
4
- class Organization < CLI
5
- def precondition
6
- check_target
7
- check_logged_in
8
-
9
- fail "This command is v2-only." unless v2?
10
- end
11
-
12
- def self.by_name(what, obj = what)
13
- proc { |name, *_|
14
- client.send(:"#{obj}_by_name", name) ||
15
- fail("Unknown #{what} '#{name}'")
16
- }
17
- end
18
-
19
- desc "Show organization information"
20
- group :organizations
21
- input :organization, :aliases => ["--org", "-o"],
22
- :argument => :optional,
23
- :from_given => by_name("organization"),
24
- :default => proc { client.current_organization },
25
- :desc => "Organization to show"
26
- input :full, :type => :boolean,
27
- :desc => "Show full information for spaces, domains, etc."
28
- def org
29
- org = input[:organization]
30
-
31
- unless org
32
- return if quiet?
33
- fail "No current organization."
34
- end
35
-
36
- if quiet?
37
- puts org.name
38
- return
39
- end
40
-
41
- line "#{c(org.name, :name)}:"
42
-
43
- indented do
44
- line "domains: #{name_list(org.domains)}"
45
-
46
- if input[:full]
47
- line "spaces:"
48
-
49
- spaced(org.spaces(:depth => 2)) do |s|
50
- indented do
51
- invoke :space, :space => s
52
- end
53
- end
54
- else
55
- line "spaces: #{name_list(org.spaces)}"
56
- end
57
- end
58
- end
59
-
60
-
61
- desc "List available organizations"
62
- group :organizations
63
- input :one_line, :alias => "-l", :type => :boolean, :default => false,
64
- :desc => "Single-line tabular format"
65
- input :full, :type => :boolean, :default => false,
66
- :desc => "Show full information for apps, service instances, etc."
67
- def orgs
68
- orgs =
69
- with_progress("Getting organizations") do
70
- client.organizations
71
- end
72
-
73
- line unless quiet?
74
-
75
- if input[:one_line]
76
- table(
77
- %w{name spaces domains},
78
- orgs.collect { |o|
79
- [ c(o.name, :name),
80
- name_list(o.spaces),
81
- name_list(o.domains)
82
- ]
83
- })
84
- else
85
- orgs.each do |o|
86
- invoke :org, :organization => o, :full => input[:full]
87
- end
88
- end
89
- end
90
-
91
-
92
- desc "Create an organization"
93
- group :organizations
94
- input(:name, :argument => :optional, :desc => "Organization name") {
95
- ask("Name")
96
- }
97
- input :target, :alias => "-t", :type => :boolean,
98
- :desc => "Switch to the organization after creation"
99
- input :add_self, :type => :boolean, :default => true,
100
- :desc => "Add yourself to the organization"
101
- def create_org
102
- org = client.organization
103
- org.name = input[:name]
104
- org.users = [client.current_user] if input[:add_self]
105
-
106
- with_progress("Creating organization #{c(org.name, :name)}") do
107
- org.create!
108
- end
109
-
110
- if input[:target]
111
- invoke :target, :organization => org
112
- end
113
- end
114
-
115
-
116
- desc "Delete an organization"
117
- group :organizations
118
- input(:organization, :aliases => ["--org", "-o"],
119
- :argument => :optional,
120
- :from_given => by_name("organization"),
121
- :desc => "Organization to delete") { |orgs|
122
- ask "Which organization?", :choices => orgs,
123
- :display => proc(&:name)
124
- }
125
- input(:really, :type => :boolean, :forget => true,
126
- :default => proc { force? || interact }) { |org|
127
- ask("Really delete #{c(org.name, :name)}?", :default => false)
128
- }
129
- input(:recursive, :alias => "-r", :type => :boolean, :forget => true) {
130
- ask "Delete #{c("EVERYTHING", :bad)}?", :default => false
131
- }
132
- input :warn, :type => :boolean, :default => true,
133
- :desc => "Show warning if it was the last org"
134
- def delete_org
135
- orgs = client.organizations
136
- fail "No organizations." if orgs.empty?
137
-
138
- org = input[:organization, orgs]
139
- return unless input[:really, org]
140
-
141
- spaces = org.spaces
142
- unless spaces.empty?
143
- unless force?
144
- line "This organization is not empty!"
145
- line
146
- line "spaces: #{name_list(spaces)}"
147
- line
148
-
149
- return unless input[:recursive]
150
- end
151
-
152
- spaces.each do |s|
153
- invoke :delete_space, :space => s, :really => true,
154
- :recursive => true, :warn => false
155
- end
156
- end
157
-
158
- is_current = org == client.current_organization
159
-
160
- with_progress("Deleting organization #{c(org.name, :name)}") do
161
- org.delete!
162
- end
163
-
164
- if orgs.size == 1
165
- return unless input[:warn]
166
-
167
- line
168
- line c("There are no longer any organizations.", :warning)
169
- line "You may want to create one with #{c("create-org", :good)}."
170
- elsif is_current
171
- invalidate_target
172
- invoke :target
173
- end
174
- end
175
- end
176
- end
@@ -1,387 +0,0 @@
1
- require "vmc/cli"
2
-
3
- module VMC
4
- class Service < CLI
5
- desc "List your service instances"
6
- group :services
7
- input :space,
8
- :from_given => by_name("space"),
9
- :default => proc { client.current_space },
10
- :desc => "Show services in given space"
11
- input :name, :desc => "Filter by name"
12
- input :service, :desc => "Filter by service type"
13
- input :plan, :desc => "Filter by service plan"
14
- input :provider, :desc => "Filter by service provider"
15
- input :version, :desc => "Filter by service version"
16
- input :app, :desc => "Limit to application's service bindings",
17
- :from_given => by_name("app")
18
- input :full, :type => :boolean, :default => false,
19
- :desc => "Verbose output format"
20
- def services
21
- msg =
22
- if space = input[:space]
23
- "Getting services in #{c(space.name, :name)}"
24
- else
25
- "Getting services"
26
- end
27
-
28
- instances =
29
- with_progress(msg) do
30
- client.service_instances(:depth => 2)
31
- end
32
-
33
- line unless quiet?
34
-
35
- if instances.empty? and !quiet?
36
- line "No services."
37
- return
38
- end
39
-
40
- instances.reject! do |i|
41
- !instance_matches(i, input)
42
- end
43
-
44
- if input[:full]
45
- spaced(instances) do |i|
46
- display_service_instance(i)
47
- end
48
- else
49
- table(
50
- ["name", "service", "version", v2? && "plan", v2? && "bound apps"],
51
- instances.collect { |i|
52
- if v2?
53
- plan = i.service_plan
54
- service = plan.service
55
-
56
- label = service.label
57
- version = service.version
58
- apps = name_list(i.service_bindings.collect(&:app))
59
- else
60
- label = i.vendor
61
- version = i.version
62
- end
63
-
64
- [ c(i.name, :name),
65
- label,
66
- version,
67
- v2? && plan.name,
68
- apps
69
- ]
70
- })
71
- end
72
- end
73
-
74
-
75
- desc "Show service instance information"
76
- group :services
77
- input :instance, :argument => :required,
78
- :from_given => by_name("service instance", :service_instance),
79
- :desc => "Service instance to show"
80
- def service
81
- display_service_instance(input[:instance])
82
- end
83
-
84
-
85
- services_from_label = proc { |label, services|
86
- services.select { |s| s.label == label }
87
- }
88
-
89
- desc "Create a service"
90
- group :services, :manage
91
- input(:service, :argument => true,
92
- :desc => "What kind of service (e.g. redis, mysql)",
93
- :from_given => services_from_label) { |services|
94
- [ask("What kind?", :choices => services.sort_by(&:label),
95
- :display => proc { |s|
96
- str = "#{c(s.label, :name)} #{s.version}"
97
- if s.provider != "core"
98
- str << ", via #{s.provider}"
99
- end
100
- str
101
- },
102
- :complete => proc { |s| "#{s.label} #{s.version}" })]
103
- }
104
- input(:name, :argument => true,
105
- :desc => "Name for your instance") { |service|
106
- random = sprintf("%x", rand(1000000))
107
- ask "Name?", :default => "#{service.label}-#{random}"
108
- }
109
- input(:plan, :desc => "Service plan",
110
- :default => proc { |plans|
111
- plans.find { |p| p.name == "D100" } ||
112
- interact
113
- },
114
- :from_given => find_by_name_insensitive("plan")) { |plans|
115
- ask "Which plan?", :choices => plans.sort_by(&:name),
116
- :display => proc { |p| "#{p.name}: #{p.description}" },
117
- :complete => proc(&:name)
118
- }
119
- input :provider, :desc => "Service provider"
120
- input :version, :desc => "Service version"
121
- input :app, :alias => "--bind", :from_given => by_name("app"),
122
- :desc => "Application to immediately bind to"
123
- def create_service
124
- services = client.services
125
-
126
- if input[:provider]
127
- services.reject! { |s| s.provider != input[:provider] }
128
- end
129
-
130
- if input[:version]
131
- services.reject! { |s| s.version != input[:version] }
132
- elsif !v2?
133
- services.reject!(&:deprecated?)
134
- end
135
-
136
- if v2? && plan = input.given(:plan)
137
- services.reject! do |s|
138
- if plan.is_a?(String)
139
- s.service_plans.none? { |p| p.name == plan.upcase }
140
- else
141
- s.service_plans.include? plan
142
- end
143
- end
144
- end
145
-
146
- until services.size < 2
147
- # cast to Array since it might be given as a Service with #invoke
148
- services = Array(input[:service, services.sort_by(&:label)])
149
- input.forget(:service)
150
- end
151
-
152
- if services.empty?
153
- fail "Cannot find services matching the given criteria."
154
- end
155
-
156
- service = services.first
157
-
158
- instance = client.service_instance
159
- instance.name = input[:name, service]
160
-
161
- if v2?
162
- instance.service_plan = input[:plan, service.service_plans]
163
- instance.space = client.current_space
164
- else
165
- instance.type = service.type
166
- instance.vendor = service.label
167
- instance.version = service.version
168
- instance.tier = "free"
169
- end
170
-
171
- with_progress("Creating service #{c(instance.name, :name)}") do
172
- instance.create!
173
- end
174
-
175
- if app = input[:app]
176
- invoke :bind_service, :instance => instance, :app => app
177
- end
178
-
179
- instance
180
- end
181
-
182
-
183
- desc "Bind a service instance to an application"
184
- group :services, :manage
185
- input(:instance, :argument => true,
186
- :from_given => by_name("service instance", :service_instance),
187
- :desc => "Service to bind") { |app|
188
- instances = client.service_instances
189
- fail "No service instances." if instances.empty?
190
-
191
- ask "Which service instance?",
192
- :choices => instances - app.services,
193
- :display => proc(&:name)
194
- }
195
- input(:app, :argument => true,
196
- :from_given => by_name("app"),
197
- :desc => "Application to bind to") {
198
- ask "Which application?", :choices => client.apps(:depth => 2),
199
- :display => proc(&:name)
200
- }
201
- def bind_service
202
- app = input[:app]
203
- instance = input[:instance, app]
204
-
205
- with_progress(
206
- "Binding #{c(instance.name, :name)} to #{c(app.name, :name)}") do |s|
207
- if app.binds?(instance)
208
- s.skip do
209
- err "App #{b(app.name)} already binds #{b(instance.name)}."
210
- end
211
- else
212
- app.bind(instance)
213
- end
214
- end
215
- end
216
-
217
-
218
- desc "Unbind a service from an application"
219
- group :services, :manage
220
- input(:instance, :argument => true,
221
- :from_given => find_by_name("service instance"),
222
- :desc => "Service to bind") { |services|
223
- ask "Which service instance?", :choices => services,
224
- :display => proc(&:name)
225
- }
226
- input(:app, :argument => true,
227
- :from_given => by_name("app"),
228
- :desc => "Application to bind to") {
229
- ask "Which application?", :choices => client.apps(:depth => 2),
230
- :display => proc(&:name)
231
- }
232
- def unbind_service
233
- app = input[:app]
234
- instance = input[:instance, app.services]
235
-
236
- with_progress(
237
- "Unbinding #{c(instance.name, :name)} from #{c(app.name, :name)}") do
238
- app.unbind(instance)
239
- end
240
- end
241
-
242
-
243
- desc "Delete a service"
244
- group :services, :manage
245
- input(:instance, :argument => true,
246
- :from_given => by_name("service instance", :service_instance),
247
- :desc => "Service to bind") {
248
- instances = client.service_instances
249
- fail "No services." if instances.empty?
250
-
251
- ask "Which service instance?", :choices => instances,
252
- :display => proc(&:name)
253
- }
254
- input(:really, :type => :boolean, :forget => true,
255
- :default => proc { force? || interact }) { |name, color|
256
- ask("Really delete #{c(name, color)}?", :default => false)
257
- }
258
- input(:unbind, :type => :boolean, :forget => true,
259
- :default => proc { force? || interact }) { |apps|
260
- names = human_list(apps.collect { |a| c(a.name, :name) })
261
-
262
- ask("Unbind from #{names} before deleting?", :default => true)
263
- }
264
- input :all, :type => :boolean, :default => false,
265
- :desc => "Delete all services"
266
- def delete_service
267
- if input[:all]
268
- return unless input[:really, "ALL SERVICES", :bad]
269
-
270
- client.service_instances.each do |i|
271
- invoke :delete_service, :instance => i, :really => true
272
- end
273
-
274
- return
275
- end
276
-
277
- instance = input[:instance]
278
-
279
- return unless input[:really, instance.name, :name]
280
-
281
- bindings = []
282
-
283
- if v2?
284
- bindings = instance.service_bindings
285
-
286
- unless bindings.empty? || !input[:unbind, bindings.collect(&:app)]
287
- bindings.each do |b|
288
- invoke :unbind_service, :instance => instance, :app => b.app
289
- end
290
-
291
- bindings = []
292
- end
293
- end
294
-
295
- with_progress("Deleting #{c(instance.name, :name)}") do |s|
296
- if bindings.empty?
297
- instance.delete!
298
- else
299
- s.skip do
300
- apps = bindings.collect(&:app).collect { |a| b(a.name) }
301
- err "Service instance is bound to #{human_list(apps)}."
302
- end
303
- end
304
- end
305
- end
306
-
307
- private
308
-
309
- def instance_matches(i, options)
310
- if app = options[:app]
311
- return false unless app.services.include? i
312
- end
313
-
314
- if name = options[:name]
315
- return false unless File.fnmatch(name, i.name)
316
- end
317
-
318
- plan = i.service_plan if v2?
319
-
320
- if service = options[:service]
321
- if v2?
322
- return false unless File.fnmatch(service, plan.service.label)
323
- else
324
- return false unless File.fnmatch(service, i.vendor)
325
- end
326
- end
327
-
328
- if plan = options[:plan]
329
- fail "--plan is not supported on this target" unless v2?
330
- return false unless File.fnmatch(plan.upcase, plan.name.upcase)
331
- end
332
-
333
- if provider = options[:provider]
334
- fail "--provider is not supported on this target" unless v2?
335
- return false unless File.fnmatch(provider, plan.service.provider)
336
- end
337
-
338
- if version = options[:version]
339
- if v2?
340
- return false unless File.fnmatch(version, plan.service.version)
341
- else
342
- return false unless File.fnmatch(version, i.version)
343
- end
344
- end
345
-
346
- true
347
- end
348
-
349
- def display_service_instance(i)
350
- if quiet?
351
- line i.name
352
- elsif v2?
353
- plan = i.service_plan
354
- service = plan.service
355
-
356
- apps = i.service_bindings.collect { |b|
357
- c(b.app.name, :name)
358
- }.join(", ")
359
-
360
- line "#{c(i.name, :name)}: #{service.label} #{service.version}"
361
-
362
- indented do
363
- line "provider: #{c(service.provider, :name)}"
364
- line "bound to: #{apps}" unless apps.empty?
365
- line "plan: #{c(plan.name, :name)}"
366
-
367
- indented do
368
- line "description: #{plan.description}"
369
- end
370
- end
371
- else
372
- line "#{c(i.name, :name)}: #{i.vendor} #{i.version}"
373
- end
374
- end
375
-
376
- def human_list(xs)
377
- if xs.size == 1
378
- xs.first
379
- elsif xs.size == 2
380
- "#{xs.first} and #{xs.last}"
381
- else
382
- last = xs.pop
383
- xs.join(", ") + ", and #{last}"
384
- end
385
- end
386
- end
387
- end