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
@@ -0,0 +1,64 @@
1
+ require "vmc/detect"
2
+ require "vmc/cli/app/base"
3
+ require "vmc/cli/app/push/sync"
4
+ require "vmc/cli/app/push/create"
5
+
6
+ module VMC::App
7
+ class Push < Base
8
+ module Interactions
9
+ def name
10
+ ask("Name")
11
+ end
12
+
13
+ def url(name)
14
+ choices = url_choices(name)
15
+
16
+ options = {
17
+ :choices => choices + ["none"],
18
+ :allow_other => true
19
+ }
20
+
21
+ options[:default] = choices.first if choices.size == 1
22
+
23
+ url = ask "URL", options
24
+
25
+ unless url == "none"
26
+ url
27
+ end
28
+ end
29
+
30
+ def memory(limit)
31
+ ask("Memory Limit",
32
+ :choices => memory_choices,
33
+ :allow_other => true,
34
+ :default => default || "64M")
35
+ end
36
+
37
+ def instances
38
+ ask("Instances", :default => 1)
39
+ end
40
+
41
+ def framework(choices, default, other)
42
+ ask_with_other("Framework", client.frameworks, choices, default, other)
43
+ end
44
+
45
+ def runtime(choices, default, other)
46
+ ask_with_other("Runtime", client.runtimes, choices, default, other)
47
+ end
48
+
49
+ def command
50
+ ask("Startup command")
51
+ end
52
+
53
+ def create_services
54
+ ask "Create services for application?", :default => false
55
+ end
56
+
57
+ def bind_services
58
+ return if all_instances.empty?
59
+
60
+ ask "Bind other services to application?", :default => false
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,59 @@
1
+ module VMC::App
2
+ module Sync
3
+ def apply_changes(app)
4
+ app.memory = megabytes(input[:memory]) if input.given?(:memory)
5
+ app.total_instances = input[:instances] if input.given?(:instances)
6
+ app.command = input[:command] if input.given?(:command)
7
+ app.production = input[:plan].upcase.start_with?("P") if input.given?(:plan)
8
+ app.framework = input[:framework] if input.given?(:framework)
9
+ app.runtime = input[:runtime] if input.given?(:runtime)
10
+ end
11
+
12
+ def display_changes(app)
13
+ return unless app.changed?
14
+
15
+ line "Changes:"
16
+
17
+ app.changes.each do |attr, (old, new)|
18
+ line "#{c(attr, :name)}: #{diff_str(attr, old)} -> #{diff_str(attr, new)}"
19
+ end
20
+ end
21
+
22
+ def commit_changes(app)
23
+ return unless app.changed?
24
+
25
+ with_progress("Updating #{c(app.name, :name)}") do
26
+ app.update!
27
+ end
28
+
29
+ if input[:restart] && app.started?
30
+ invoke :restart, :app => app
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def diff_str(attr, val)
37
+ case attr
38
+ when :memory
39
+ human_mb(val)
40
+ when :framework, :runtime
41
+ val.name
42
+ when :command
43
+ "'#{val}'"
44
+ when :production
45
+ bool(val)
46
+ else
47
+ val
48
+ end
49
+ end
50
+
51
+ def bool(b)
52
+ if b
53
+ c("true", :yes)
54
+ else
55
+ c("false", :no)
56
+ end
57
+ end
58
+ end
59
+ end
@@ -5,7 +5,7 @@ require "vmc/cli/app/base"
5
5
  module VMC::App
6
6
  class Rename < Base
7
7
  desc "Rename an application"
8
- group :apps, :manage
8
+ group :apps, :manage, :hidden => true
9
9
  input(:app, :argument => :optional, :desc => "Application to rename",
10
10
  :from_given => by_name("app")) {
11
11
  apps = client.apps
@@ -0,0 +1,14 @@
1
+ require "vmc/cli"
2
+
3
+ module VMC
4
+ module Organization
5
+ class Base < CLI
6
+ def precondition
7
+ check_target
8
+ check_logged_in
9
+
10
+ fail "This command is v2-only." unless v2?
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,28 @@
1
+ require "vmc/cli/organization/base"
2
+
3
+ module VMC::Organization
4
+ class CreateOrg < Base
5
+ desc "Create an organization"
6
+ group :organizations
7
+ input(:name, :argument => :optional, :desc => "Organization name") {
8
+ ask("Name")
9
+ }
10
+ input :target, :alias => "-t", :type => :boolean,
11
+ :desc => "Switch to the organization after creation"
12
+ input :add_self, :type => :boolean, :default => true,
13
+ :desc => "Add yourself to the organization"
14
+ def create_org
15
+ org = client.organization
16
+ org.name = input[:name]
17
+ org.users = [client.current_user] if input[:add_self]
18
+
19
+ with_progress("Creating organization #{c(org.name, :name)}") do
20
+ org.create!
21
+ end
22
+
23
+ if input[:target]
24
+ invoke :target, :organization => org
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,65 @@
1
+ require "vmc/cli/organization/base"
2
+
3
+ module VMC::Organization
4
+ class DeleteOrg < Base
5
+ desc "Delete an organization"
6
+ group :organizations
7
+ input(:organization, :aliases => ["--org", "-o"],
8
+ :argument => :optional,
9
+ :from_given => by_name("organization"),
10
+ :desc => "Organization to delete") { |orgs|
11
+ ask "Which organization?", :choices => orgs,
12
+ :display => proc(&:name)
13
+ }
14
+ input(:really, :type => :boolean, :forget => true,
15
+ :default => proc { force? || interact }) { |org|
16
+ ask("Really delete #{c(org.name, :name)}?", :default => false)
17
+ }
18
+ input(:recursive, :alias => "-r", :type => :boolean, :forget => true) {
19
+ ask "Delete #{c("EVERYTHING", :bad)}?", :default => false
20
+ }
21
+ input :warn, :type => :boolean, :default => true,
22
+ :desc => "Show warning if it was the last org"
23
+ def delete_org
24
+ orgs = client.organizations
25
+ fail "No organizations." if orgs.empty?
26
+
27
+ org = input[:organization, orgs]
28
+ return unless input[:really, org]
29
+
30
+ spaces = org.spaces
31
+ unless spaces.empty?
32
+ unless force?
33
+ line "This organization is not empty!"
34
+ line
35
+ line "spaces: #{name_list(spaces)}"
36
+ line
37
+
38
+ return unless input[:recursive]
39
+ end
40
+
41
+ spaces.each do |s|
42
+ invoke :delete_space, :space => s, :really => true,
43
+ :recursive => true, :warn => false
44
+ end
45
+ end
46
+
47
+ is_current = org == client.current_organization
48
+
49
+ with_progress("Deleting organization #{c(org.name, :name)}") do
50
+ org.delete!
51
+ end
52
+
53
+ if orgs.size == 1
54
+ return unless input[:warn]
55
+
56
+ line
57
+ line c("There are no longer any organizations.", :warning)
58
+ line "You may want to create one with #{c("create-org", :good)}."
59
+ elsif is_current
60
+ invalidate_target
61
+ invoke :target
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,46 @@
1
+ require "vmc/cli/organization/base"
2
+
3
+ module VMC::Organization
4
+ class Org < Base
5
+ desc "Show organization information"
6
+ group :organizations
7
+ input :organization, :aliases => ["--org", "-o"],
8
+ :argument => :optional,
9
+ :from_given => by_name("organization"),
10
+ :default => proc { client.current_organization },
11
+ :desc => "Organization to show"
12
+ input :full, :type => :boolean,
13
+ :desc => "Show full information for spaces, domains, etc."
14
+ def org
15
+ org = input[:organization]
16
+
17
+ unless org
18
+ return if quiet?
19
+ fail "No current organization."
20
+ end
21
+
22
+ if quiet?
23
+ puts org.name
24
+ return
25
+ end
26
+
27
+ line "#{c(org.name, :name)}:"
28
+
29
+ indented do
30
+ line "domains: #{name_list(org.domains)}"
31
+
32
+ if input[:full]
33
+ line "spaces:"
34
+
35
+ spaced(org.spaces(:depth => 2)) do |s|
36
+ indented do
37
+ invoke :space, :space => s
38
+ end
39
+ end
40
+ else
41
+ line "spaces: #{name_list(org.spaces)}"
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,35 @@
1
+ require "vmc/cli/organization/base"
2
+
3
+ module VMC::Organization
4
+ class Orgs < Base
5
+ desc "List available organizations"
6
+ group :organizations
7
+ input :one_line, :alias => "-l", :type => :boolean, :default => false,
8
+ :desc => "Single-line tabular format"
9
+ input :full, :type => :boolean, :default => false,
10
+ :desc => "Show full information for apps, service instances, etc."
11
+ def orgs
12
+ orgs =
13
+ with_progress("Getting organizations") do
14
+ client.organizations
15
+ end
16
+
17
+ line unless quiet?
18
+
19
+ if input[:one_line]
20
+ table(
21
+ %w{name spaces domains},
22
+ orgs.collect { |o|
23
+ [ c(o.name, :name),
24
+ name_list(o.spaces),
25
+ name_list(o.domains)
26
+ ]
27
+ })
28
+ else
29
+ orgs.each do |o|
30
+ invoke :org, :organization => o, :full => input[:full]
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,32 @@
1
+ require "vmc/detect"
2
+
3
+ require "vmc/cli/organization/base"
4
+
5
+ module VMC::Organization
6
+ class Rename < Base
7
+ desc "Rename an organization"
8
+ group :organizations, :hidden => true
9
+ input(:organization, :aliases => ["--org", "-o"],
10
+ :argument => :optional, :desc => "Organization to rename",
11
+ :from_given => by_name("organization")) {
12
+ organizations = client.organizations
13
+ fail "No organizations." if organizations.empty?
14
+
15
+ ask("Rename which organization?", :choices => organizations.sort_by(&:name),
16
+ :display => proc(&:name))
17
+ }
18
+ input(:name, :argument => :optional, :desc => "New organization name") {
19
+ ask("New name")
20
+ }
21
+ def rename_org
22
+ organization = input[:organization]
23
+ name = input[:name]
24
+
25
+ organization.name = name
26
+
27
+ with_progress("Renaming to #{c(name, :name)}") do
28
+ organization.update!
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,8 @@
1
+ require "vmc/cli"
2
+
3
+ module VMC
4
+ module Service
5
+ class Base < CLI
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,66 @@
1
+ require "vmc/detect"
2
+
3
+ require "vmc/cli/service/base"
4
+
5
+ module VMC::Service
6
+ class Binding < Base
7
+ desc "Bind a service instance to an application"
8
+ group :services, :manage
9
+ input(:instance, :argument => true,
10
+ :from_given => by_name("service instance", :service_instance),
11
+ :desc => "Service to bind") { |app|
12
+ instances = client.service_instances
13
+ fail "No service instances." if instances.empty?
14
+
15
+ ask "Which service instance?",
16
+ :choices => instances - app.services,
17
+ :display => proc(&:name)
18
+ }
19
+ input(:app, :argument => true,
20
+ :from_given => by_name("app"),
21
+ :desc => "Application to bind to") {
22
+ ask "Which application?", :choices => client.apps(:depth => 2),
23
+ :display => proc(&:name)
24
+ }
25
+ def bind_service
26
+ app = input[:app]
27
+ instance = input[:instance, app]
28
+
29
+ with_progress(
30
+ "Binding #{c(instance.name, :name)} to #{c(app.name, :name)}") do |s|
31
+ if app.binds?(instance)
32
+ s.skip do
33
+ err "App #{b(app.name)} already binds #{b(instance.name)}."
34
+ end
35
+ else
36
+ app.bind(instance)
37
+ end
38
+ end
39
+ end
40
+
41
+
42
+ desc "Unbind a service from an application"
43
+ group :services, :manage
44
+ input(:instance, :argument => true,
45
+ :from_given => find_by_name("service instance"),
46
+ :desc => "Service to bind") { |services|
47
+ ask "Which service instance?", :choices => services,
48
+ :display => proc(&:name)
49
+ }
50
+ input(:app, :argument => true,
51
+ :from_given => by_name("app"),
52
+ :desc => "Application to bind to") {
53
+ ask "Which application?", :choices => client.apps(:depth => 2),
54
+ :display => proc(&:name)
55
+ }
56
+ def unbind_service
57
+ app = input[:app]
58
+ instance = input[:instance, app.services]
59
+
60
+ with_progress(
61
+ "Unbinding #{c(instance.name, :name)} from #{c(app.name, :name)}") do
62
+ app.unbind(instance)
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,104 @@
1
+ require "vmc/detect"
2
+
3
+ require "vmc/cli/service/base"
4
+
5
+ module VMC::Service
6
+ class Create < Base
7
+ services_from_label = proc { |label, services|
8
+ services.select { |s| s.label == label }
9
+ }
10
+
11
+ desc "Create a service"
12
+ group :services, :manage
13
+ input(:service, :argument => true,
14
+ :desc => "What kind of service (e.g. redis, mysql)",
15
+ :from_given => services_from_label) { |services|
16
+ [ask("What kind?", :choices => services.sort_by(&:label),
17
+ :display => proc { |s|
18
+ str = "#{c(s.label, :name)} #{s.version}"
19
+ if s.provider != "core"
20
+ str << ", via #{s.provider}"
21
+ end
22
+ str
23
+ },
24
+ :complete => proc { |s| "#{s.label} #{s.version}" })]
25
+ }
26
+ input(:name, :argument => true,
27
+ :desc => "Name for your instance") { |service|
28
+ random = sprintf("%x", rand(1000000))
29
+ ask "Name?", :default => "#{service.label}-#{random}"
30
+ }
31
+ input(:plan, :desc => "Service plan",
32
+ :default => proc { |plans|
33
+ plans.find { |p| p.name == "D100" } ||
34
+ interact
35
+ },
36
+ :from_given => find_by_name_insensitive("plan")) { |plans|
37
+ ask "Which plan?", :choices => plans.sort_by(&:name),
38
+ :display => proc { |p| "#{p.name}: #{p.description}" },
39
+ :complete => proc(&:name)
40
+ }
41
+ input :provider, :desc => "Service provider"
42
+ input :version, :desc => "Service version"
43
+ input :app, :alias => "--bind", :from_given => by_name("app"),
44
+ :desc => "Application to immediately bind to"
45
+ def create_service
46
+ services = client.services
47
+
48
+ if input[:provider]
49
+ services.reject! { |s| s.provider != input[:provider] }
50
+ end
51
+
52
+ if input[:version]
53
+ services.reject! { |s| s.version != input[:version] }
54
+ elsif !v2?
55
+ services.reject!(&:deprecated?)
56
+ end
57
+
58
+ if v2? && plan = input.given(:plan)
59
+ services.reject! do |s|
60
+ if plan.is_a?(String)
61
+ s.service_plans.none? { |p| p.name == plan.upcase }
62
+ else
63
+ s.service_plans.include? plan
64
+ end
65
+ end
66
+ end
67
+
68
+ until services.size < 2
69
+ # cast to Array since it might be given as a Service with #invoke
70
+ services = Array(input[:service, services.sort_by(&:label)])
71
+ input.forget(:service)
72
+ end
73
+
74
+ if services.empty?
75
+ fail "Cannot find services matching the given criteria."
76
+ end
77
+
78
+ service = services.first
79
+
80
+ instance = client.service_instance
81
+ instance.name = input[:name, service]
82
+
83
+ if v2?
84
+ instance.service_plan = input[:plan, service.service_plans]
85
+ instance.space = client.current_space
86
+ else
87
+ instance.type = service.type
88
+ instance.vendor = service.label
89
+ instance.version = service.version
90
+ instance.tier = "free"
91
+ end
92
+
93
+ with_progress("Creating service #{c(instance.name, :name)}") do
94
+ instance.create!
95
+ end
96
+
97
+ if app = input[:app]
98
+ invoke :bind_service, :instance => instance, :app => app
99
+ end
100
+
101
+ instance
102
+ end
103
+ end
104
+ end