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.
Files changed (140) hide show
  1. data/LICENSE +1277 -30
  2. data/Rakefile +12 -1
  3. data/bin/cf +0 -3
  4. data/lib/cf.rb +6 -0
  5. data/lib/cf/cli.rb +389 -190
  6. data/lib/cf/cli/app/app.rb +45 -0
  7. data/lib/cf/cli/app/apps.rb +99 -0
  8. data/lib/cf/cli/app/base.rb +90 -0
  9. data/lib/cf/cli/app/crashes.rb +42 -0
  10. data/lib/cf/cli/app/delete.rb +95 -0
  11. data/lib/cf/cli/app/deprecated.rb +11 -0
  12. data/lib/cf/cli/app/env.rb +78 -0
  13. data/lib/cf/cli/app/files.rb +137 -0
  14. data/lib/cf/cli/app/health.rb +26 -0
  15. data/lib/cf/cli/app/instances.rb +53 -0
  16. data/lib/cf/cli/app/logs.rb +76 -0
  17. data/lib/cf/cli/app/push.rb +105 -0
  18. data/lib/cf/cli/app/push/create.rb +149 -0
  19. data/lib/cf/cli/app/push/interactions.rb +94 -0
  20. data/lib/cf/cli/app/push/sync.rb +64 -0
  21. data/lib/cf/cli/app/rename.rb +35 -0
  22. data/lib/cf/cli/app/restart.rb +20 -0
  23. data/lib/cf/cli/app/scale.rb +69 -0
  24. data/lib/cf/cli/app/start.rb +143 -0
  25. data/lib/cf/cli/app/stats.rb +67 -0
  26. data/lib/cf/cli/app/stop.rb +27 -0
  27. data/lib/cf/cli/domain/base.rb +8 -0
  28. data/lib/cf/cli/domain/domains.rb +40 -0
  29. data/lib/cf/cli/domain/map.rb +55 -0
  30. data/lib/cf/cli/domain/unmap.rb +56 -0
  31. data/lib/cf/cli/help.rb +15 -0
  32. data/lib/cf/cli/interactive.rb +105 -0
  33. data/lib/cf/cli/organization/base.rb +12 -0
  34. data/lib/cf/cli/organization/create.rb +32 -0
  35. data/lib/cf/cli/organization/delete.rb +73 -0
  36. data/lib/cf/cli/organization/org.rb +45 -0
  37. data/lib/cf/cli/organization/orgs.rb +35 -0
  38. data/lib/cf/cli/organization/rename.rb +36 -0
  39. data/lib/cf/cli/route/base.rb +8 -0
  40. data/lib/cf/cli/route/map.rb +70 -0
  41. data/lib/cf/cli/route/routes.rb +26 -0
  42. data/lib/cf/cli/route/unmap.rb +62 -0
  43. data/lib/cf/cli/service/base.rb +8 -0
  44. data/lib/cf/cli/service/bind.rb +44 -0
  45. data/lib/cf/cli/service/create.rb +107 -0
  46. data/lib/cf/cli/service/delete.rb +82 -0
  47. data/lib/cf/cli/service/rename.rb +35 -0
  48. data/lib/cf/cli/service/service.rb +40 -0
  49. data/lib/cf/cli/service/services.rb +99 -0
  50. data/lib/cf/cli/service/unbind.rb +38 -0
  51. data/lib/cf/cli/space/base.rb +19 -0
  52. data/lib/cf/cli/space/create.rb +63 -0
  53. data/lib/cf/cli/space/delete.rb +95 -0
  54. data/lib/cf/cli/space/rename.rb +39 -0
  55. data/lib/cf/cli/space/space.rb +64 -0
  56. data/lib/cf/cli/space/spaces.rb +55 -0
  57. data/lib/cf/cli/space/switch.rb +16 -0
  58. data/lib/cf/cli/start/base.rb +93 -0
  59. data/lib/cf/cli/start/colors.rb +13 -0
  60. data/lib/cf/cli/start/info.rb +124 -0
  61. data/lib/cf/cli/start/login.rb +94 -0
  62. data/lib/cf/cli/start/logout.rb +17 -0
  63. data/lib/cf/cli/start/target.rb +69 -0
  64. data/lib/cf/cli/start/target_interactions.rb +37 -0
  65. data/lib/cf/cli/start/targets.rb +16 -0
  66. data/lib/cf/cli/user/base.rb +29 -0
  67. data/lib/cf/cli/user/create.rb +39 -0
  68. data/lib/cf/cli/user/passwd.rb +43 -0
  69. data/lib/cf/cli/user/register.rb +42 -0
  70. data/lib/cf/cli/user/users.rb +32 -0
  71. data/lib/cf/constants.rb +10 -7
  72. data/lib/cf/detect.rb +113 -48
  73. data/lib/cf/errors.rb +17 -0
  74. data/lib/cf/plugin.rb +28 -12
  75. data/lib/cf/spacing.rb +89 -0
  76. data/lib/cf/spec_helper.rb +1 -0
  77. data/lib/cf/test_support.rb +6 -0
  78. data/lib/cf/version.rb +1 -1
  79. data/spec/assets/hello-sinatra/Gemfile +3 -0
  80. data/spec/assets/hello-sinatra/Gemfile.lock +17 -0
  81. data/spec/assets/hello-sinatra/config.ru +3 -0
  82. data/spec/assets/hello-sinatra/fat-cat-makes-app-larger.png +0 -0
  83. data/spec/assets/hello-sinatra/main.rb +6 -0
  84. data/spec/assets/specker_runner/specker_runner_input.rb +6 -0
  85. data/spec/assets/specker_runner/specker_runner_pause.rb +5 -0
  86. data/spec/cf/cli/app/base_spec.rb +17 -0
  87. data/spec/cf/cli/app/delete_spec.rb +188 -0
  88. data/spec/cf/cli/app/instances_spec.rb +65 -0
  89. data/spec/cf/cli/app/push/create_spec.rb +661 -0
  90. data/spec/cf/cli/app/push_spec.rb +369 -0
  91. data/spec/cf/cli/app/rename_spec.rb +104 -0
  92. data/spec/cf/cli/app/scale_spec.rb +75 -0
  93. data/spec/cf/cli/app/start_spec.rb +208 -0
  94. data/spec/cf/cli/app/stats_spec.rb +68 -0
  95. data/spec/cf/cli/domain/map_spec.rb +130 -0
  96. data/spec/cf/cli/domain/unmap_spec.rb +69 -0
  97. data/spec/cf/cli/organization/orgs_spec.rb +108 -0
  98. data/spec/cf/cli/organization/rename_spec.rb +113 -0
  99. data/spec/cf/cli/route/map_spec.rb +121 -0
  100. data/spec/cf/cli/route/unmap_spec.rb +155 -0
  101. data/spec/cf/cli/service/bind_spec.rb +25 -0
  102. data/spec/cf/cli/service/delete_spec.rb +22 -0
  103. data/spec/cf/cli/service/rename_spec.rb +105 -0
  104. data/spec/cf/cli/service/service_spec.rb +23 -0
  105. data/spec/cf/cli/service/unbind_spec.rb +25 -0
  106. data/spec/cf/cli/space/create_spec.rb +93 -0
  107. data/spec/cf/cli/space/rename_spec.rb +102 -0
  108. data/spec/cf/cli/space/spaces_spec.rb +104 -0
  109. data/spec/cf/cli/space/switch_space_spec.rb +55 -0
  110. data/spec/cf/cli/start/info_spec.rb +160 -0
  111. data/spec/cf/cli/start/login_spec.rb +142 -0
  112. data/spec/cf/cli/start/logout_spec.rb +50 -0
  113. data/spec/cf/cli/start/target_spec.rb +123 -0
  114. data/spec/cf/cli/user/create_spec.rb +54 -0
  115. data/spec/cf/cli/user/passwd_spec.rb +102 -0
  116. data/spec/cf/cli/user/register_spec.rb +140 -0
  117. data/spec/cf/cli_spec.rb +442 -0
  118. data/spec/cf/detect_spec.rb +54 -0
  119. data/spec/console_app_specker/console_app_specker_matchers_spec.rb +173 -0
  120. data/spec/console_app_specker/specker_runner_spec.rb +167 -0
  121. data/spec/features/account_lifecycle_spec.rb +85 -0
  122. data/spec/features/login_spec.rb +66 -0
  123. data/spec/features/push_flow_spec.rb +125 -0
  124. data/spec/features/switching_targets_spec.rb +32 -0
  125. data/spec/spec_helper.rb +72 -0
  126. data/spec/support/command_helper.rb +81 -0
  127. data/spec/support/config_helper.rb +15 -0
  128. data/spec/support/console_app_specker_matchers.rb +86 -0
  129. data/spec/support/fake_home_dir.rb +55 -0
  130. data/spec/support/interact_helper.rb +29 -0
  131. data/spec/support/shared_examples/errors.rb +40 -0
  132. data/spec/support/shared_examples/input.rb +14 -0
  133. data/spec/support/specker_runner.rb +80 -0
  134. data/spec/support/tracking_expector.rb +71 -0
  135. metadata +427 -66
  136. data/lib/cf/cli/app.rb +0 -595
  137. data/lib/cf/cli/command.rb +0 -444
  138. data/lib/cf/cli/dots.rb +0 -133
  139. data/lib/cf/cli/service.rb +0 -112
  140. data/lib/cf/cli/user.rb +0 -71
@@ -0,0 +1,37 @@
1
+ module CF::Start
2
+ module TargetInteractions
3
+ def ask_organization
4
+ orgs = client.organizations(:depth => 0)
5
+
6
+ if orgs.empty?
7
+ unless quiet?
8
+ line
9
+ line c("There are no organizations.", :warning)
10
+ line "You may want to create one with #{c("create-org", :good)}."
11
+ end
12
+ elsif orgs.size == 1 && !input.interactive?(:organization)
13
+ orgs.first
14
+ else
15
+ ask("Organization",
16
+ :choices => orgs.sort_by(&:name),
17
+ :display => proc(&:name))
18
+ end
19
+ end
20
+
21
+ def ask_space(org)
22
+ spaces = org.spaces(:depth => 0)
23
+
24
+ if spaces.empty?
25
+ unless quiet?
26
+ line
27
+ line c("There are no spaces in #{b(org.name)}.", :warning)
28
+ line "You may want to create one with #{c("create-space", :good)}."
29
+ end
30
+ elsif spaces.size == 1 && !input.interactive?(:spaces)
31
+ spaces.first
32
+ else
33
+ ask("Space", :choices => spaces, :display => proc(&:name))
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,16 @@
1
+ require "cf/cli/start/base"
2
+
3
+ module CF::Start
4
+ class Targets < Base
5
+ desc "List known targets."
6
+ group :start, :hidden => true
7
+ def targets
8
+ targets_info.each do |target, _|
9
+ line target
10
+ # TODO: print org/space
11
+ end
12
+ end
13
+ end
14
+ end
15
+
16
+
@@ -0,0 +1,29 @@
1
+ require "cf/cli"
2
+
3
+ module CF
4
+ module User
5
+ class Base < CLI
6
+ def precondition
7
+ check_logged_in
8
+ end
9
+
10
+ private
11
+
12
+ def validate_password!(password)
13
+ validate_password_verified!(password)
14
+ validate_password_strength!(password)
15
+ end
16
+
17
+ def validate_password_verified!(password)
18
+ fail "Passwords do not match." unless force? || password == input[:verify]
19
+ end
20
+
21
+ def validate_password_strength!(password)
22
+ strength = client.base.password_score(password)
23
+ msg = "Your password strength is: #{strength}"
24
+ fail msg if strength == :weak
25
+ line msg
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,39 @@
1
+ require "cf/cli/user/base"
2
+
3
+ module CF::User
4
+ class Create < Base
5
+ desc "Create a user"
6
+ group :admin, :user, :hidden => true
7
+ input :email, :desc => "User email", :argument => :optional
8
+ input :password, :desc => "User password"
9
+ input :verify, :desc => "Repeat password"
10
+ def create_user
11
+ email = input[:email]
12
+ password = input[:password]
13
+
14
+ if !force? && password != input[:verify]
15
+ fail "Passwords don't match."
16
+ end
17
+
18
+ with_progress("Creating user") do
19
+ client.register(email, password)
20
+ end
21
+ end
22
+
23
+ alias_command :add_user, :create_user
24
+
25
+ private
26
+
27
+ def ask_email
28
+ ask("Email")
29
+ end
30
+
31
+ def ask_password
32
+ ask("Password", :echo => "*", :forget => true)
33
+ end
34
+
35
+ def ask_verify
36
+ ask("Verify Password", :echo => "*", :forget => true)
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,43 @@
1
+ require "cf/cli/user/base"
2
+
3
+ module CF::User
4
+ class Passwd < Base
5
+ desc "Update a user's password"
6
+ group :admin, :user, :hidden => true
7
+ input :user, :desc => "User to update", :argument => :optional,
8
+ :default => proc { client.current_user },
9
+ :from_given => proc { |email|
10
+ if client.current_user.email != email
11
+ fail "You can only change your own password."
12
+ end
13
+ }
14
+ input :password, :desc => "Current password"
15
+ input :new_password, :desc => "New password"
16
+ input :verify, :desc => "Repeat new password"
17
+ def passwd
18
+ user = input[:user]
19
+ password = input[:password]
20
+ new_password = input[:new_password]
21
+
22
+ validate_password! new_password
23
+
24
+ with_progress("Changing password") do
25
+ user.change_password!(new_password, password)
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def ask_password
32
+ ask("Current Password", :echo => "*", :forget => true)
33
+ end
34
+
35
+ def ask_new_password
36
+ ask("New Password", :echo => "*", :forget => true)
37
+ end
38
+
39
+ def ask_verify
40
+ ask("Verify Password", :echo => "*", :forget => true)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,42 @@
1
+ require "cf/cli/user/base"
2
+
3
+ module CF::User
4
+ class Register < Base
5
+ def precondition; end
6
+
7
+ desc "Create a user and log in"
8
+ group :admin, :user, :hidden => true
9
+ input :email, :desc => "Desired email", :argument => :optional
10
+ input :password, :desc => "Desired password"
11
+ input :verify, :desc => "Repeat password"
12
+ input :login, :desc => "Automatically log in?", :default => true
13
+ def register
14
+ email = input[:email]
15
+ password = input[:password]
16
+
17
+ validate_password!(password)
18
+
19
+ with_progress("Creating user") do
20
+ client.register(email, password)
21
+ end
22
+
23
+ if input[:login]
24
+ invoke :login, :username => email, :password => password
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def ask_email
31
+ ask("Email")
32
+ end
33
+
34
+ def ask_password
35
+ ask("Password", :echo => "*", :forget => true)
36
+ end
37
+
38
+ def ask_verify
39
+ ask("Confirm Password", :echo => "*", :forget => true)
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,32 @@
1
+ require "cf/cli/user/base"
2
+
3
+ module CF::User
4
+ class Users < Base
5
+ desc "List all users"
6
+ group :admin, :hidden => true
7
+ def users
8
+ users =
9
+ with_progress("Getting users") do
10
+ client.users(:depth => 0)
11
+ end
12
+
13
+ spaced(users) do |u|
14
+ display_user(u)
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def display_user(u)
21
+ if quiet?
22
+ puts u.email
23
+ else
24
+ line "#{c(u.email, :name)}:"
25
+
26
+ indented do
27
+ line "admin?: #{c(u.admin?, u.admin? ? :yes : :no)}"
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -1,10 +1,13 @@
1
1
  module CF
2
- OLD_TARGET_FILE = "~/.vmc_target"
3
- OLD_TOKENS_FILE = "~/.vmc_token"
2
+ OLD_TARGET_FILE = "~/.cf_target".freeze
3
+ OLD_TOKENS_FILE = "~/.cf_token".freeze
4
4
 
5
- CONFIG_DIR = "~/.cf"
6
- PLUGINS_FILE = "#{CONFIG_DIR}/plugins.yml"
7
- TARGET_FILE = "#{CONFIG_DIR}/target"
8
- TOKENS_FILE = "#{CONFIG_DIR}/tokens.yml"
9
- CRASH_FILE = "#{CONFIG_DIR}/crash"
5
+ CONFIG_DIR = "~/.cf".freeze
6
+
7
+ LOGS_DIR = "#{CONFIG_DIR}/logs".freeze
8
+ PLUGINS_FILE = "#{CONFIG_DIR}/plugins.yml".freeze
9
+ TARGET_FILE = "#{CONFIG_DIR}/target".freeze
10
+ TOKENS_FILE = "#{CONFIG_DIR}/tokens.yml".freeze
11
+ COLORS_FILE = "#{CONFIG_DIR}/colors.yml".freeze
12
+ CRASH_FILE = "#{CONFIG_DIR}/crash".freeze
10
13
  end
@@ -1,64 +1,129 @@
1
+ require "set"
2
+
3
+ require "clouseau"
4
+
1
5
  module CF
2
6
  class Detector
7
+ # "Basic" framework names for a detected language
8
+ PSEUDO_FRAMEWORKS = {
9
+ :node => "node",
10
+ :python => "wsgi",
11
+ :java => "java_web",
12
+ :php => "php",
13
+ :erlang => "otp_rebar",
14
+ :dotnet => "dotNet"
15
+ }
16
+
17
+ # Mismatched framework names
18
+ FRAMEWORK_NAMES = {
19
+ :rails => "rails3"
20
+ }
21
+
22
+ # Clouseau language symbol => matching runtime names
23
+ LANGUAGE_RUNTIMES = {
24
+ :ruby => /^ruby.*/,
25
+ :java => /^java.*/,
26
+ :node => /^node.*/,
27
+ :erlang => /^erlang.*/,
28
+ :dotnet => /^dotNet.*/,
29
+ :python => /^python.*/,
30
+ :php => /^php.*/
31
+ }
32
+
3
33
  def initialize(client, path)
4
34
  @client = client
5
35
  @path = path
6
36
  end
7
37
 
8
- def all_frameworks
9
- info = @client.info
10
- info["frameworks"] || {}
38
+ # detect the framework
39
+ def detect_framework
40
+ detected && frameworks[detected]
11
41
  end
12
42
 
13
- def frameworks
14
- info = @client.info
15
-
16
- matches = {}
17
- all_frameworks.each do |name, meta|
18
- matched = false
19
-
20
- # e.g. standalone has no detection
21
- next if meta["detection"].nil?
22
-
23
- meta["detection"].first.each do |file, match|
24
- files =
25
- if File.file? @path
26
- if File.fnmatch(file, @path)
27
- [@path]
28
- else
29
- []
30
- end
31
- else
32
- Dir.glob("#@path/#{file}")
33
- end
34
-
35
- unless files.empty?
36
- if match == true
37
- matched = true
38
- elsif match == false
39
- matched = false
40
- break
41
- else
42
- files.each do |f|
43
- contents = File.open(f, &:read)
44
- if contents =~ Regexp.new(match)
45
- matched = true
46
- end
47
- end
48
- end
49
- end
50
- end
51
-
52
- if matched
53
- matches[name] = meta
54
- end
43
+ # detect the language and return the appropriate runtimes
44
+ def detect_runtimes
45
+ if detected && lang = detected.language_name
46
+ runtimes_for(lang)
47
+ else
48
+ []
49
+ end
50
+ end
51
+
52
+ # determine runtimes for a given framework based on the language its
53
+ # detector reports itself as
54
+ def runtimes(framework)
55
+ if detector = detectors[framework]
56
+ runtimes_for(detector.language_name)
57
+ else
58
+ []
55
59
  end
60
+ end
56
61
 
57
- if matches.size == 1
58
- default = matches.keys.first
62
+ # determine suitable memory allocation via the framework's detector
63
+ def suggested_memory(framework)
64
+ if detector = detectors[framework]
65
+ detector.memory_suggestion
59
66
  end
67
+ end
68
+
69
+ # helper so that this is cached somewhere
70
+ def all_runtimes
71
+ @all_runtimes ||= @client.runtimes
72
+ end
60
73
 
61
- [matches, default]
74
+ # helper so that this is cached somewhere
75
+ def all_frameworks
76
+ @all_frameworks ||= @client.frameworks
77
+ end
78
+
79
+ def detected
80
+ @detected ||= Clouseau.detect(@path)
81
+ end
82
+
83
+ private
84
+
85
+ def map_detectors!
86
+ @framework_detectors = {}
87
+ @detector_frameworks = {}
88
+
89
+ Clouseau.detectors.each do |d|
90
+ name = d.framework_name
91
+ lang = d.language_name
92
+
93
+ framework = all_frameworks.find { |f|
94
+ f.name == name.to_s ||
95
+ f.name == FRAMEWORK_NAMES[name]
96
+ }
97
+
98
+ framework ||= all_frameworks.find { |f|
99
+ f.name == PSEUDO_FRAMEWORKS[lang]
100
+ }
101
+
102
+ next unless framework
103
+
104
+ @framework_detectors[framework] = d
105
+ @detector_frameworks[d] = framework
106
+ end
107
+
108
+ nil
109
+ end
110
+
111
+ # Framework -> Detector
112
+ def detectors
113
+ map_detectors! unless @framework_detectors
114
+ @framework_detectors
115
+ end
116
+
117
+ # Detector -> Framework
118
+ def frameworks
119
+ map_detectors! unless @detector_frameworks
120
+ @detector_frameworks
121
+ end
122
+
123
+ def runtimes_for(language)
124
+ all_runtimes.select do |r|
125
+ LANGUAGE_RUNTIMES[language] === r.name
126
+ end
62
127
  end
63
128
  end
64
129
  end
@@ -0,0 +1,17 @@
1
+ module CF
2
+ class UserError < RuntimeError
3
+ def initialize(msg)
4
+ @message = msg
5
+ end
6
+
7
+ def to_s
8
+ @message
9
+ end
10
+ end
11
+
12
+ class NotAuthorized < UserError
13
+ def initialize
14
+ @message = "Not authorized."
15
+ end
16
+ end
17
+ end