ey-core 3.1.2 → 3.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. data/.ruby-version +1 -1
  2. data/.travis.yml +1 -0
  3. data/Gemfile +0 -2
  4. data/examples/add_instance.rb +74 -0
  5. data/examples/boot_env.rb +60 -0
  6. data/examples/stop_env.rb +51 -0
  7. data/examples/terminate_instance.rb +58 -0
  8. data/lib/ey-core/cli/accounts.rb +14 -6
  9. data/lib/ey-core/cli/applications.rb +32 -12
  10. data/lib/ey-core/cli/console.rb +24 -10
  11. data/lib/ey-core/cli/current_user.rb +13 -5
  12. data/lib/ey-core/cli/deploy.rb +110 -52
  13. data/lib/ey-core/cli/environments.rb +34 -12
  14. data/lib/ey-core/cli/errors.rb +10 -6
  15. data/lib/ey-core/cli/help.rb +30 -0
  16. data/lib/ey-core/cli/helpers/archive.rb +70 -0
  17. data/lib/ey-core/cli/helpers/chef.rb +35 -0
  18. data/lib/ey-core/cli/helpers/core.rb +195 -0
  19. data/lib/ey-core/cli/helpers/deprecated.rb +39 -0
  20. data/lib/ey-core/cli/helpers/log_streaming.rb +41 -0
  21. data/lib/ey-core/cli/helpers/stream_printer.rb +42 -0
  22. data/lib/ey-core/cli/init.rb +11 -8
  23. data/lib/ey-core/cli/login.rb +33 -21
  24. data/lib/ey-core/cli/logout.rb +18 -10
  25. data/lib/ey-core/cli/logs.rb +57 -35
  26. data/lib/ey-core/cli/main.rb +52 -15
  27. data/lib/ey-core/cli/recipes.rb +5 -87
  28. data/lib/ey-core/cli/recipes/apply.rb +83 -43
  29. data/lib/ey-core/cli/recipes/download.rb +48 -22
  30. data/lib/ey-core/cli/recipes/main.rb +21 -0
  31. data/lib/ey-core/cli/recipes/upload.rb +56 -23
  32. data/lib/ey-core/cli/scp.rb +11 -8
  33. data/lib/ey-core/cli/servers.rb +37 -15
  34. data/lib/ey-core/cli/ssh.rb +127 -70
  35. data/lib/ey-core/cli/status.rb +54 -14
  36. data/lib/ey-core/cli/subcommand.rb +47 -108
  37. data/lib/ey-core/cli/timeout_deploy.rb +56 -26
  38. data/lib/ey-core/cli/version.rb +13 -5
  39. data/lib/ey-core/cli/web.rb +7 -7
  40. data/lib/ey-core/cli/web/disable.rb +46 -20
  41. data/lib/ey-core/cli/web/enable.rb +40 -17
  42. data/lib/ey-core/cli/web/main.rb +21 -0
  43. data/lib/ey-core/cli/web/restart.rb +34 -15
  44. data/lib/ey-core/cli/whoami.rb +11 -3
  45. data/lib/ey-core/mock/searching.rb +4 -0
  46. data/lib/ey-core/model.rb +5 -0
  47. data/lib/ey-core/models/deployment.rb +7 -0
  48. data/lib/ey-core/models/environment.rb +5 -0
  49. data/lib/ey-core/models/request.rb +2 -0
  50. data/lib/ey-core/models/user.rb +2 -0
  51. data/lib/ey-core/requests/get_servers.rb +1 -1
  52. data/lib/ey-core/response.rb +4 -0
  53. data/lib/ey-core/subscribable.rb +3 -3
  54. data/lib/ey-core/version.rb +1 -1
  55. data/spec/ey-core/cli/accounts_spec.rb +20 -0
  56. data/spec/ey-core/cli/recipes/apply_spec.rb +4 -17
  57. data/spec/ey-core/cli/recipes/download_spec.rb +93 -0
  58. data/spec/ey-core/cli/recipes/upload_spec.rb +80 -0
  59. data/spec/servers_spec.rb +15 -0
  60. data/spec/spec_helper.rb +7 -0
  61. data/spec/support/cli_helpers.rb +38 -2
  62. metadata +116 -53
  63. checksums.yaml +0 -7
@@ -1,20 +1,60 @@
1
- class Ey::Core::Cli::Status < Ey::Core::Cli::Subcommand
2
- title "status"
3
- summary "Show the deployment status of the app"
1
+ require 'ey-core/cli/subcommand'
2
+ require 'ey-core/cli/helpers/log_streaming'
4
3
 
5
- option :environment, short: "e", long: "environment", description: "Name or id of the environment to deploy to.", argument: "Environment"
6
- option :account, short: 'c', long: 'account', description: 'Name or ID of the account that the environment resides in. If no account is specified, the app will deploy to the first environment that meets the criteria, in the accounts you have access to.', argument: 'Account name or id'
7
- option :app, short: "a", long: "app", description: "Application name or ID to deploy. If :account is not specified, this will be the first app that matches the criteria in the accounts you have access to.", argument: "app"
4
+ module Ey
5
+ module Core
6
+ module Cli
7
+ class Status < Subcommand
8
+ include Ey::Core::Cli::Helpers::LogStreaming
9
+ title "status"
10
+ summary "Show the deployment status of the app"
11
+ description <<-DESC
12
+ Show the current status of the most recent deployment of the specifed application and environment
13
+ DESC
8
14
 
9
- description <<-DESC
10
- Show the current status of the most recent deployment of the specifed application and environment
11
- DESC
15
+ option :environment,
16
+ short: "e",
17
+ long: "environment",
18
+ description: "Name or id of the environment to deploy to.",
19
+ argument: "Environment"
12
20
 
13
- def handle
14
- operator, environment = core_operator_and_environment_for(self.options)
15
- app = core_application_for(self.options)
16
- deployments = core_client.deployments.all(environment_id: environment.id, application_id: app.id)
21
+ option :account,
22
+ short: 'c',
23
+ long: 'account',
24
+ description: 'Name or ID of the account that the environment resides in. If no account is specified, the app will deploy to the first environment that meets the criteria, in the accounts you have access to.',
25
+ argument: 'Account name or id'
17
26
 
18
- ap deployments.first
27
+ option :app,
28
+ short: "a",
29
+ long: "app",
30
+ description: "Application name or ID to deploy. If :account is not specified, this will be the first app that matches the criteria in the accounts you have access to.",
31
+ argument: "app"
32
+
33
+ switch :tail,
34
+ long: "tail",
35
+ description: "tail in-progress deployment log"
36
+
37
+ def handle
38
+ operator, environment = core_operator_and_environment_for(self.options)
39
+ app = core_application_for(environment, self.options)
40
+ deploy = environment.latest_deploy(app)
41
+
42
+ puts environment.release_label
43
+ puts "#{environment.servers.size} servers"
44
+ environment.servers.each do |s|
45
+ puts [s.provisioned_id, s.role, s.state].join(" ")
46
+ end
47
+ if deploy
48
+ ap deploy
49
+ if switch_active?(:tail)
50
+ stream_deploy_log(deploy.request)
51
+ end
52
+ else
53
+ puts "Never Deployed"
54
+ end
55
+ end
56
+
57
+ end
58
+ end
19
59
  end
20
60
  end
@@ -1,113 +1,52 @@
1
- class Ey::Core::Cli::Subcommand < Belafonte::App
2
- def self.descendants
3
- ObjectSpace.each_object(Class).select { |klass| klass < self }
4
- end
5
-
6
- class << self
7
- attr_accessor :core_file
8
-
9
- def core_file
10
- @core_file ||= File.expand_path("~/.ey-core")
11
- end
12
-
13
- def eyrc
14
- @eyrc ||= File.expand_path("~/.eyrc")
15
- end
16
- end
17
-
18
- def unauthenticated_core_client
19
- @unauthenticated_core_client ||= Ey::Core::Client.new(token: nil, url: core_url)
20
- end
21
-
22
- def core_client
23
- @core_client ||= Ey::Core::Client.new(url: core_url, config_file: self.class.core_file)
24
- rescue RuntimeError => e
25
- if legacy_token = e.message.match(/missing token/i) && eyrc_yaml["api_token"]
26
- puts "Found legacy .eyrc token. Migrating to core file".green
27
- write_core_yaml(legacy_token)
28
- retry
29
- elsif e.message.match(/missing token/i)
30
- abort "Missing credentials: Run 'ey login' to retrieve your Engine Yard Cloud API token.".yellow
31
- else
32
- raise e
33
- end
34
- end
35
-
36
- def core_url
37
- env_url = ENV["CORE_URL"] || ENV["CLOUD_URL"]
38
- (env_url && File.join(env_url, '/')) || "https://api.engineyard.com/"
39
- end
40
-
41
- def current_accounts
42
- core_client.users.current.accounts
43
- end
44
-
45
- def longest_length_by_name(collection)
46
- collection.map(&:name).group_by(&:size).max.last.length
47
- end
48
-
49
- def write_core_yaml(token=nil)
50
- core_yaml[core_url] = token if token
51
- File.open(self.class.core_file, "w") { |f| f.puts core_yaml.to_yaml }
52
- end
53
-
54
- def eyrc_yaml
55
- @eyrc_yaml ||= YAML.load_file(self.class.eyrc) || {}
56
- rescue Errno::ENOENT => e # we don't really care if this doesn't exist
57
- {}
58
- end
59
-
60
- def core_yaml
61
- @core_yaml ||= YAML.load_file(self.class.core_file) || {}
62
- rescue Errno::ENOENT => e
63
- puts "Creating #{self.class.core_file}".yellow
64
- FileUtils.touch(self.class.core_file)
65
- retry
66
- end
67
-
68
- def core_account_for(options={})
69
- @core_account ||= core_client.accounts.get(options[:account])
70
- @core_account ||= core_client.users.current.accounts.first(name: options[:account])
71
- end
72
-
73
- def operator(options)
74
- options[:account] ? core_account_for(options) : core_client
75
- end
76
-
77
- def core_operator_and_environment_for(options={})
78
- operator = operator(options)
79
- environment = operator.environments.get(options[:environment]) || operator.environments.first(name: options[:environment])
80
- [operator, environment]
81
- end
82
-
83
- def core_environment_for(options={})
84
- core_client.environments.get(options[:environment]) || core_client.environments.first(name: options[:environment])
85
- end
86
-
87
- def core_server_for(options={})
88
- operator = options.fetch(:operator, core_client)
89
- operator.servers.get(options[:server]) || operator.servers.first(provisioned_id: options[:server])
90
- end
91
-
92
- def core_application_for(options={})
93
- return nil unless options[:app]
94
-
95
- app = begin
96
- Integer(options[:app])
97
- rescue
98
- options[:app]
1
+ require 'belafonte'
2
+ require 'colorize'
3
+ require 'table_print'
4
+ require 'ey-core'
5
+ require 'ey-core/cli/helpers/core'
6
+
7
+ module Ey
8
+ module Core
9
+ module Cli
10
+ class Subcommand < Belafonte::App
11
+ include Ey::Core::Cli::Helpers::Core
12
+
13
+ def setup
14
+ $stdout = stdout
15
+ $stderr = stderr
16
+ $stdin = stdin
17
+ $kernel = kernel
18
+ end
19
+
20
+ def run_handle
21
+ super
22
+ rescue Ey::Core::Response::Error => e
23
+ if ENV["DEBUG"]
24
+ puts e.inspect
25
+ puts e.backtrace
99
26
  end
27
+ handle_core_error(e)
28
+ rescue => e
29
+ if ENV["DEBUG"]
30
+ puts e.inspect
31
+ puts e.backtrace
32
+ end
33
+ stderr.puts "Error:".red
34
+ stderr.puts Wrapomatic.wrap(e.message, indents: 1)
35
+ raise SystemExit.new(255)
36
+ end
37
+
38
+ #TODO: a lot more errors that would could handle with nice messages, eventually this should probably be it's own class
39
+ def handle_core_error(e)
40
+ stderr.puts "Error: #{e.error_type}".red
41
+ (e.response.body["errors"] || [e.message]).each do |message|
42
+ stderr.puts Wrapomatic.wrap(message, indents: 1)
43
+ end
44
+ if e.is_a?(Ey::Core::Response::Unauthorized)
45
+ stderr.puts "Check the contents of ~/.ey-core vs https://cloud.engineyard.com/cli"
46
+ end
47
+ raise SystemExit.new(255)
48
+ end
100
49
 
101
- actor = options[:environment].is_a?(Ey::Core::Client::Environment) ? options[:environment].account : operator(options)
102
-
103
- if app.is_a?(Integer)
104
- actor.applications.get(app)
105
- else
106
- applications = actor.applications.all(name: app)
107
- if applications.count == 1
108
- applications.first
109
- else
110
- raise Ey::Core::Cli::AmbiguousSearch.new("Found multiple applications that matched that search. Please be more specific by specifying the account, environment, and application name.")
111
50
  end
112
51
  end
113
52
  end
@@ -1,28 +1,58 @@
1
- class Ey::Core::Cli::TimeoutDeploy < Ey::Core::Cli::Subcommand
2
- title "timeout-deploy"
3
- summary "Fail a stuck unfinished deployment"
4
- description <<-DESC
5
- NOTICE: Timing out a deploy does not stop currently running deploy
6
- processes.
7
-
8
- The latest running deployment will be marked as failed, allowing a
9
- new deployment to be run. It is possible to mark a potentially successful
10
- deployment as failed. Only run this when a deployment is known to be
11
- wrongly unfinished/stuck and when further deployments are blocked.
12
- DESC
13
-
14
- option :environment, short: "e", long: "environment", description: "Name or id of the environment to deploy to.", argument: "Environment"
15
- option :account, short: 'c', long: 'account', description: 'Name or ID of the account that the environment resides in. If no account is specified, the app will deploy to the first environment that meets the criteria, in the accounts you have access to.', argument: 'Account name or id'
16
- option :app, short: "a", long: "app", description: "Application name or ID to deploy. If :account is not specified, this will be the first app that matches the criteria in the accounts you have access to.", argument: "app"
17
- option :message, short: "m", long: "message", description: "Custom message for why the deploy is timed out", argument: "message"
18
-
19
- def handle
20
- operator, environment = core_operator_and_environment_for(self.options)
21
- app = core_application_for(self.options)
22
- deployment = core_client.deployments.first(environment_id: environment.id, application_id: app.id)
23
-
24
- puts "Timing out the most recent deployment (deploy started at: #{deployment.started_at})".green
25
- deployment.timeout(option(:message))
26
- ap deployment
1
+ require 'ey-core/cli/subcommand'
2
+
3
+ module Ey
4
+ module Core
5
+ module Cli
6
+ class TimeoutDeploy < Subcommand
7
+ title "timeout-deploy"
8
+ summary "Fail a stuck unfinished deployment"
9
+ description <<-DESC
10
+ NOTICE: Timing out a deploy does not stop currently running deploy
11
+ processes.
12
+
13
+ The latest running deployment will be marked as failed, allowing a
14
+ new deployment to be run. It is possible to mark a potentially successful
15
+ deployment as failed. Only run this when a deployment is known to be
16
+ wrongly unfinished/stuck and when further deployments are blocked.
17
+ DESC
18
+
19
+ option :environment,
20
+ short: "e",
21
+ long: "environment",
22
+ description: "Name or id of the environment to deploy to.",
23
+ argument: "Environment"
24
+
25
+ option :account,
26
+ short: 'c',
27
+ long: 'account',
28
+ description: 'Name or ID of the account that the environment resides in. If no account is specified, the app will deploy to the first environment that meets the criteria, in the accounts you have access to.',
29
+ argument: 'Account name or id'
30
+
31
+ option :app,
32
+ short: "a",
33
+ long: "app",
34
+ description: "Application name or ID to deploy. If :account is not specified, this will be the first app that matches the criteria in the accounts you have access to.",
35
+ argument: "app"
36
+
37
+ option :message,
38
+ short: "m",
39
+ long: "message",
40
+ description: "Custom message for why the deploy is timed out",
41
+ argument: "message"
42
+
43
+ def handle
44
+ operator, environment = core_operator_and_environment_for(self.options)
45
+ app = core_application_for(environment, options)
46
+ deployment = core_client.
47
+ deployments.
48
+ first(environment_id: environment.id, application_id: app.id)
49
+
50
+ puts "Timing out the most recent deployment (deploy started at: #{deployment.started_at})".green
51
+
52
+ deployment.timeout(option(:message))
53
+ ap deployment
54
+ end
55
+ end
56
+ end
27
57
  end
28
58
  end
@@ -1,8 +1,16 @@
1
- class Ey::Core::Cli::Version < Ey::Core::Cli::Subcommand
2
- title "version"
3
- summary "Print the version of the gem"
1
+ require 'ey-core/cli/subcommand'
4
2
 
5
- def handle
6
- puts Ey::Core::VERSION
3
+ module Ey
4
+ module Core
5
+ module Cli
6
+ class Version < Subcommand
7
+ title "version"
8
+ summary "Print the version of the gem"
9
+
10
+ def handle
11
+ puts Ey::Core::VERSION
12
+ end
13
+ end
14
+ end
7
15
  end
8
16
  end
@@ -1,10 +1,10 @@
1
- class Ey::Core::Cli::Web < Ey::Core::Cli::Subcommand
2
- title "web"
3
- summary "Web related commands"
1
+ require 'ey-core/cli/web/main'
4
2
 
5
- Dir[File.dirname(__FILE__) + "/web/*.rb"].each { |file| load file }
6
-
7
- Ey::Core::Cli::Web.descendants.each do |d|
8
- mount d
3
+ module Ey
4
+ module Core
5
+ module Cli
6
+ module Web
7
+ end
8
+ end
9
9
  end
10
10
  end
@@ -1,23 +1,49 @@
1
- class Ey::Core::Cli::Web::Disable < Ey::Core::Cli::Web
2
- title "disable"
3
- summary "Put up the maintenance page for this application in the given environment."
4
-
5
- option :app, short: "a", long: "app", description: "Name or id of the application whose maintenance page will be put up", argument: "app"
6
- option :environment, short: "e", long: "environment", description: "Name or id of the environment to deploy to.", argument: "Environment"
7
- option :account, short: 'c', long: 'account', description: 'Name or ID of the account that the environment resides in.', argument: 'Account name or id'
8
-
9
- def handle
10
- operator, environment = core_operator_and_environment_for(self.options)
11
- application = core_application_for(self.options)
12
-
13
- puts "Enabling maintenance page for #{application.name} on #{environment.name}".green
14
- request = environment.maintenance(application, "enable")
15
- request.wait_for { |r| r.ready? }
16
- if request.successful
17
- puts "Successfully put up maintenance page".green
18
- else
19
- puts "Enabling maintenance mode was not successful".red
20
- ap request
1
+ require 'ey-core/cli/subcommand'
2
+
3
+ module Ey
4
+ module Core
5
+ module Cli
6
+ module Web
7
+ class Disable < Ey::Core::Cli::Subcommand
8
+ title "disable"
9
+ summary "Put up the maintenance page for this application in the given environment."
10
+
11
+ option :app,
12
+ short: "a",
13
+ long: "app",
14
+ description: "Name or id of the application whose maintenance page will be put up",
15
+ argument: "app"
16
+
17
+ option :environment,
18
+ short: "e",
19
+ long: "environment",
20
+ description: "Name or id of the environment to deploy to.",
21
+ argument: "Environment"
22
+
23
+ option :account,
24
+ short: 'c',
25
+ long: 'account',
26
+ description: 'Name or ID of the account that the environment resides in.',
27
+ argument: 'Account name or id'
28
+
29
+ def handle
30
+ operator, environment = core_operator_and_environment_for(self.options)
31
+ application = core_application_for(environment, self.options)
32
+
33
+ puts "Enabling maintenance page for #{application.name} on #{environment.name}".green
34
+
35
+ request = environment.maintenance(application, "enable")
36
+ request.wait_for { |r| r.ready? }
37
+
38
+ if request.successful
39
+ puts "Successfully put up maintenance page".green
40
+ else
41
+ puts "Enabling maintenance mode was not successful".red
42
+ ap request
43
+ end
44
+ end
45
+ end
46
+ end
21
47
  end
22
48
  end
23
49
  end
@@ -1,23 +1,46 @@
1
- class Ey::Core::Cli::Web::Enable < Ey::Core::Cli::Web
2
- title "enable"
3
- summary "Remove the maintenance page for this application in the given environment."
1
+ require 'ey-core/cli/subcommand'
4
2
 
5
- option :app, short: "a", long: "app", description: "Name or id of the application whose maintenance page will be removed", argument: "app"
6
- option :environment, short: "e", long: "environment", description: "Name or id of the environment to deploy to.", argument: "Environment"
7
- option :account, short: 'c', long: 'account', description: 'Name or ID of the account that the environment resides in.', argument: 'account'
3
+ module Ey
4
+ module Core
5
+ module Cli
6
+ module Web
7
+ class Enable < Ey::Core::Cli::Subcommand
8
+ title "enable"
9
+ summary "Remove the maintenance page for this application in the given environment."
8
10
 
9
- def handle
10
- operator, environment = core_operator_and_environment_for(self.options)
11
- application = core_application_for(self.options)
11
+ option :app,
12
+ short: "a",
13
+ long: "app",
14
+ description: "Name or id of the application whose maintenance page will be removed",
15
+ argument: "app"
12
16
 
13
- puts "Disabling maintenance for #{application.name} on #{environment.name}".green
14
- request = environment.maintenance(application, "disable")
15
- request.wait_for { |r| r.ready? }
16
- if request.successful
17
- puts "Successfully disabled maintenance page".green
18
- else
19
- puts "Disabling maintenance mode was not successful".red
20
- ap request
17
+ option :environment,
18
+ short: "e",
19
+ long: "environment",
20
+ description: "Name or id of the environment to deploy to.",
21
+ argument: "Environment"
22
+
23
+ option :account,
24
+ short: 'c',
25
+ long: 'account',
26
+ description: 'Name or ID of the account that the environment resides in.',
27
+ argument: 'account'
28
+
29
+ def handle
30
+ operator, environment = core_operator_and_environment_for(self.options)
31
+ application = core_application_for(environment, options)
32
+ puts "Disabling maintenance for #{application.name} on #{environment.name}".green
33
+ request = environment.maintenance(application, "disable")
34
+ request.wait_for { |r| r.ready? }
35
+ if request.successful
36
+ puts "Successfully disabled maintenance page".green
37
+ else
38
+ puts "Disabling maintenance mode was not successful".red
39
+ ap request
40
+ end
41
+ end
42
+ end
43
+ end
21
44
  end
22
45
  end
23
46
  end