ey_cli 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +3 -0
- data/Gemfile.lock +57 -0
- data/LICENSE +22 -0
- data/README.md +104 -0
- data/Rakefile +129 -0
- data/bin/ey_cli +5 -0
- data/ey_cli.gemspec +117 -0
- data/history.md +3 -0
- data/lib/ey_cli/api.rb +96 -0
- data/lib/ey_cli/cli.rb +17 -0
- data/lib/ey_cli/command_manager.rb +29 -0
- data/lib/ey_cli/commands/accounts.rb +26 -0
- data/lib/ey_cli/commands/apps.rb +24 -0
- data/lib/ey_cli/commands/base.rb +16 -0
- data/lib/ey_cli/commands/console.rb +38 -0
- data/lib/ey_cli/commands/create_app.rb +76 -0
- data/lib/ey_cli/commands/create_env.rb +106 -0
- data/lib/ey_cli/commands/deploy.rb +23 -0
- data/lib/ey_cli/commands/help.rb +65 -0
- data/lib/ey_cli/commands/show.rb +65 -0
- data/lib/ey_cli/controllers/accounts.rb +23 -0
- data/lib/ey_cli/controllers/apps.rb +66 -0
- data/lib/ey_cli/controllers/environments.rb +78 -0
- data/lib/ey_cli/git_utils.rb +12 -0
- data/lib/ey_cli/models/account.rb +6 -0
- data/lib/ey_cli/models/app.rb +15 -0
- data/lib/ey_cli/models/base.rb +54 -0
- data/lib/ey_cli/models/environment.rb +32 -0
- data/lib/ey_cli/options_parser.rb +47 -0
- data/lib/ey_cli/smarty_parser.rb +29 -0
- data/lib/ey_cli/term.rb +58 -0
- data/lib/ey_cli.rb +46 -0
- data/spec/auth_helper.rb +28 -0
- data/spec/ey_cli/api_spec.rb +70 -0
- data/spec/ey_cli/command_manager_spec.rb +33 -0
- data/spec/ey_cli/commands/help_spec.rb +36 -0
- data/spec/ey_cli/controllers/accounts_spec.rb +40 -0
- data/spec/ey_cli/controllers/apps_spec.rb +97 -0
- data/spec/ey_cli/controllers/environments_spec.rb +101 -0
- data/spec/ey_cli/models/app_spec.rb +50 -0
- data/spec/ey_cli/models/base_spec.rb +98 -0
- data/spec/ey_cli/models/environment_spec.rb +51 -0
- data/spec/ey_cli/options_parser_spec.rb +19 -0
- data/spec/ey_cli/smarty_parser_spec.rb +19 -0
- data/spec/spec_helper.rb +29 -0
- metadata +288 -0
@@ -0,0 +1,76 @@
|
|
1
|
+
module EYCli
|
2
|
+
module Command
|
3
|
+
class CreateApp < Base
|
4
|
+
def initialize
|
5
|
+
@accounts = EYCli::Controller::Accounts.new
|
6
|
+
@apps = EYCli::Controller::Apps.new
|
7
|
+
@envs = EYCli::Controller::Environments.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def invoke
|
11
|
+
account = @accounts.fetch_account(options.delete(:account))
|
12
|
+
app = @apps.create(account, Dir.pwd, options)
|
13
|
+
if app
|
14
|
+
@envs.create(app, CreateEnv::EnvParser.new.fill_create_env_options(options)) unless options[:no_env]
|
15
|
+
EYCli.term.say("You can run now 'ey_cli show #{app.name}' to know the status of the application")
|
16
|
+
end
|
17
|
+
app
|
18
|
+
end
|
19
|
+
|
20
|
+
def help
|
21
|
+
<<-EOF
|
22
|
+
|
23
|
+
It takes its arguments(name, git repository and application type) from the base directory.
|
24
|
+
Usage: ey_cli create_app
|
25
|
+
|
26
|
+
Options:
|
27
|
+
--account name Name of the account to add the application to.
|
28
|
+
--name name Name of the app.
|
29
|
+
--git uri Git repository uri.
|
30
|
+
--type type Application type, either rack, rails2 or rails3.
|
31
|
+
--env_name name Name of the environment to create.
|
32
|
+
--framework_env env Type of the environment (production, staging...).
|
33
|
+
--url url Domain name for the app. It accepts comma-separated values.
|
34
|
+
--app_instances number Number of application instances.
|
35
|
+
--db_instances number Number of database slaves.
|
36
|
+
--solo A single instance for application and database.
|
37
|
+
--stack App server stack, either passenger, unicorn or trinidad.
|
38
|
+
--no_env Prevent to not create a default environment.
|
39
|
+
EOF
|
40
|
+
end
|
41
|
+
|
42
|
+
def options_parser
|
43
|
+
AppParser.new
|
44
|
+
end
|
45
|
+
|
46
|
+
class AppParser
|
47
|
+
require 'slop'
|
48
|
+
|
49
|
+
def parse(args)
|
50
|
+
opts = Slop.parse(args, {:multiple_switches => false}) do
|
51
|
+
on :account, true
|
52
|
+
on :name, true
|
53
|
+
on :git, true
|
54
|
+
on :type, true
|
55
|
+
on :env_name, true
|
56
|
+
on :framework_env, true
|
57
|
+
on :url, true
|
58
|
+
on :app_instances, true, :as => :integer
|
59
|
+
on :db_instances, true, :as => :integer
|
60
|
+
#on :util_instances, true, :as => :integer # FIXME: utils instances are handled differently
|
61
|
+
on :solo, false, :default => false
|
62
|
+
on :stack, true, :matches => /passenger|unicorn|trinidad/
|
63
|
+
on :no_env, false, :default => false
|
64
|
+
on :app_size, true do |size|
|
65
|
+
CreateEnv::EnvParser.check_instance_size(size)
|
66
|
+
end
|
67
|
+
on :db_size, true do |size|
|
68
|
+
CreateEnv::EnvParser.check_instance_size(size)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
opts.to_hash
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
module EYCli
|
2
|
+
module Command
|
3
|
+
class CreateEnv < Base
|
4
|
+
def initialize
|
5
|
+
@accounts = EYCli::Controller::Accounts.new
|
6
|
+
@apps = EYCli::Controller::Apps.new
|
7
|
+
@environments = EYCli::Controller::Environments.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def invoke
|
11
|
+
account = @accounts.fetch_account(options[:account]) if options[:account]
|
12
|
+
app = @apps.fetch_app(account, {:app_name => options[:app]})
|
13
|
+
@environments.create(app, options_parser.fill_create_env_options(options))
|
14
|
+
end
|
15
|
+
|
16
|
+
def help
|
17
|
+
<<-EOF
|
18
|
+
|
19
|
+
It takes the information from the current directory. It will guide you if it cannot reach all that information.
|
20
|
+
Usage: ey_cli create_env
|
21
|
+
|
22
|
+
Options:
|
23
|
+
--app name Name of the app to create the environment for.
|
24
|
+
--name name Name of the environment.
|
25
|
+
--framework_env env Type of the environment (production, staging...).
|
26
|
+
--url url Domain name for the app. It accepts comma-separated values.
|
27
|
+
--app_instances number Number of application instances.
|
28
|
+
--db_instances number Number of database slaves.
|
29
|
+
--solo A single instance for application and database.
|
30
|
+
--stack App server stack, either passenger, unicorn or trinidad.
|
31
|
+
EOF
|
32
|
+
end
|
33
|
+
|
34
|
+
def options_parser
|
35
|
+
EnvParser.new
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
class EnvParser
|
40
|
+
require 'slop'
|
41
|
+
|
42
|
+
def parse(args)
|
43
|
+
opts = Slop.parse(args, {:multiple_switches => false}) do
|
44
|
+
on :app, true
|
45
|
+
on :name, true
|
46
|
+
on :framework_env, true
|
47
|
+
on :url, true
|
48
|
+
on :app_instances, true, :as => :integer
|
49
|
+
on :db_instances, true, :as => :integer
|
50
|
+
#on :util_instances, true, :as => :integer # FIXME: utils instances are handled differently
|
51
|
+
on :solo, false, :default => false
|
52
|
+
on :stack, true, :matches => /passenger|unicorn|trinidad/
|
53
|
+
on :app_size, true do |size|
|
54
|
+
EnvParser.check_instance_size(size)
|
55
|
+
end
|
56
|
+
on :db_size, true do |size|
|
57
|
+
EnvParser.check_instance_size(size)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
opts.to_hash
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.check_instance_size(size)
|
64
|
+
sizes_list = [
|
65
|
+
'm1.small', 'm1.large', 'm1.xlarge',
|
66
|
+
'm2.xlarge', 'm2.2xlarge', 'm2.4xlarge',
|
67
|
+
'c1.medium', 'c1.xlarge'
|
68
|
+
]
|
69
|
+
unless sizes_list.include?(size)
|
70
|
+
EYCli.term.say("Unknown instance size: #{size}. Please, use one of the following list:")
|
71
|
+
EYCli.term.say(sizes_list.inspect)
|
72
|
+
exit 1
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def fill_create_env_options(options)
|
77
|
+
opts = {:name => options[:name], :framework_env => options[:framework_env]}
|
78
|
+
if options[:stack]
|
79
|
+
case options[:stack].to_sym
|
80
|
+
when :passenger then options[:stack] = 'nginx_passenger3'
|
81
|
+
when :unicorn then options[:stack] = 'nginx_unicorn'
|
82
|
+
when :trinidad then options[:ruby_version] = 'JRuby'
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
if options[:app_instances] || options[:db_instances] || options[:solo] ||
|
87
|
+
options[:app_size] || options[:db_size]
|
88
|
+
cluster_conf = options.dup
|
89
|
+
if options[:solo]
|
90
|
+
EYCli.term.say('~> creating solo environment, ignoring instance numbers')
|
91
|
+
cluster_conf[:configuration] = 'single'
|
92
|
+
else
|
93
|
+
cluster_conf[:configuration] = 'custom'
|
94
|
+
end
|
95
|
+
|
96
|
+
opts[:cluster_configuration] = cluster_conf
|
97
|
+
else
|
98
|
+
opts[:cluster_configuration] = {:configuration => 'cluster'}
|
99
|
+
end
|
100
|
+
|
101
|
+
opts
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module EYCli
|
2
|
+
module Command
|
3
|
+
class Deploy < Base
|
4
|
+
def initialize
|
5
|
+
@apps = EYCli::Controller::Apps.new
|
6
|
+
@environments = EYCli::Controller::Environments.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def invoke
|
10
|
+
app = @apps.fetch_app(nil, options)
|
11
|
+
@environments.deploy(app, options)
|
12
|
+
end
|
13
|
+
|
14
|
+
def help
|
15
|
+
<<-EOF
|
16
|
+
|
17
|
+
Usage: ey_cli deploy
|
18
|
+
Note: takes the application's information from the current directory. It will guide you if it cannot reach that information.
|
19
|
+
EOF
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module EYCli
|
2
|
+
module Command
|
3
|
+
class Help < Base
|
4
|
+
|
5
|
+
def invoke
|
6
|
+
name = options[:command_name] || 'help'
|
7
|
+
if name == 'commands'
|
8
|
+
print_commands
|
9
|
+
else
|
10
|
+
print_command_help(name)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def print_command_help(name)
|
15
|
+
command = EYCli.command_manager[name]
|
16
|
+
if command_help = (command and command.help)
|
17
|
+
EYCli.term.say(command_help)
|
18
|
+
else
|
19
|
+
EYCli.term.say("help not available for command: '#{name}'")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def print_commands
|
24
|
+
EYCli.term.say("available commands:")
|
25
|
+
command_names = EYCli.command_manager.commands.keys.map {|name| "- #{name}"}.sort
|
26
|
+
EYCli.term.say("\t" + command_names.join("\n\t"))
|
27
|
+
end
|
28
|
+
|
29
|
+
def options_parser
|
30
|
+
HelpParser.new
|
31
|
+
end
|
32
|
+
|
33
|
+
def help
|
34
|
+
<<-EOF
|
35
|
+
|
36
|
+
Usage: ey_cli command [args]
|
37
|
+
Try `ey_cli help commands' to list the available commands.
|
38
|
+
Try `ey_cli help [command]' for more information about a command.
|
39
|
+
|
40
|
+
Currently available commands:
|
41
|
+
|
42
|
+
General info
|
43
|
+
accounts List the accounts associated to a user.
|
44
|
+
console Start an interactive session to use ey_cli.
|
45
|
+
help Show commands information.
|
46
|
+
|
47
|
+
Applications
|
48
|
+
apps List the applications associated to a user.
|
49
|
+
create_app Create a new application. It takes the information from the current directory.
|
50
|
+
show Show information and status of an application.
|
51
|
+
|
52
|
+
Environments
|
53
|
+
create_env Create a new environment for an application.
|
54
|
+
deploy Run a deploy for an application.
|
55
|
+
EOF
|
56
|
+
end
|
57
|
+
|
58
|
+
class HelpParser
|
59
|
+
def parse(args)
|
60
|
+
{:command_name => args.shift}
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module EYCli
|
2
|
+
module Command
|
3
|
+
class Show < Base
|
4
|
+
def initialize
|
5
|
+
@apps = EYCli::Controller::Apps.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def invoke
|
9
|
+
app = @apps.fetch_app(nil, options)
|
10
|
+
if app
|
11
|
+
EYCli.term.say info(app)
|
12
|
+
EYCli.term.say status(app)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def info(app)
|
17
|
+
%Q{
|
18
|
+
#{app.name}:
|
19
|
+
- Info:
|
20
|
+
+ git repository: #{app.git_repository}}
|
21
|
+
end
|
22
|
+
|
23
|
+
def status(app)
|
24
|
+
status = %Q{
|
25
|
+
|
26
|
+
- Status per environment:}
|
27
|
+
app.environments.each do |env|
|
28
|
+
status << %Q{
|
29
|
+
+ #{env.name}:
|
30
|
+
- environment: #{env.framework_env}
|
31
|
+
- stack: #{env.app_server_stack_name}
|
32
|
+
- status: #{env.instance_status}}
|
33
|
+
status << %Q{
|
34
|
+
- instances:}
|
35
|
+
env.instances.each do |instance|
|
36
|
+
status << %Q{
|
37
|
+
+ #{instance.role}:
|
38
|
+
- Amazon ID: #{instance.amazon_id}
|
39
|
+
- status: #{instance.status}}
|
40
|
+
end
|
41
|
+
end
|
42
|
+
status
|
43
|
+
end
|
44
|
+
|
45
|
+
def help
|
46
|
+
<<-EOF
|
47
|
+
|
48
|
+
Show information and status of an application. If a name is not supplied it assumes the current directory as application base.
|
49
|
+
Usage: `ey_cli show app_name'
|
50
|
+
EOF
|
51
|
+
end
|
52
|
+
|
53
|
+
def options_parser
|
54
|
+
ShowParser.new
|
55
|
+
end
|
56
|
+
|
57
|
+
class ShowParser
|
58
|
+
def parse(args)
|
59
|
+
name = args.empty? ? nil : args.shift.downcase
|
60
|
+
{:app_name => name}
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module EYCli
|
2
|
+
module Controller
|
3
|
+
class Accounts
|
4
|
+
def fetch_account(name = nil)
|
5
|
+
accounts = fetch_accounts
|
6
|
+
if name
|
7
|
+
EYCli::Model::Account.find_by_name(name, accounts)
|
8
|
+
else
|
9
|
+
return accounts.first if accounts.empty? || accounts.size == 1
|
10
|
+
|
11
|
+
name = EYCli.term.choose_resource(accounts,
|
12
|
+
"I don't know which account you want to use.",
|
13
|
+
'Please, select an account:')
|
14
|
+
EYCli::Model::Account.find_by_name(name, accounts)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def fetch_accounts
|
19
|
+
EYCli::Model::Account.all.sort_by {|account| account.name}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module EYCli
|
2
|
+
module Controller
|
3
|
+
class Apps
|
4
|
+
include EYCli::GitUtils
|
5
|
+
|
6
|
+
def create(account, base = Dir.pwd, options = {})
|
7
|
+
if git_repository?(base) || options[:git]
|
8
|
+
app = EYCli::Model::App.create({
|
9
|
+
:account => account,
|
10
|
+
'app[name]' => options[:name] || File.basename(base),
|
11
|
+
'app[app_type_id]' => options[:type] || fetch_type(base).to_s,
|
12
|
+
'app[repository_uri]' => options[:git] || fetch_repository(base)
|
13
|
+
})
|
14
|
+
|
15
|
+
if app.errors?
|
16
|
+
EYCli.term.print_errors(app.errors, "App creation failed:")
|
17
|
+
else
|
18
|
+
EYCli.term.success("App '#{app.name}' created successfully")
|
19
|
+
end
|
20
|
+
app
|
21
|
+
else
|
22
|
+
EYCli.term.error("Not a git repository: #{base}")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def fetch_type(base)
|
27
|
+
if File.exist?(File.join(base, 'config.ru')) && File.exist?(File.join(base, 'config', 'environment.rb'))
|
28
|
+
:rails3
|
29
|
+
elsif File.exist?(File.join(base, 'config', 'environment.rb'))
|
30
|
+
:rails2
|
31
|
+
elsif File.exist?(File.join(base, 'config.ru'))
|
32
|
+
:rack
|
33
|
+
else # Raise unkown application type?
|
34
|
+
:rails3
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def fetch_app(account = nil, options = {}, base = Dir.pwd)
|
39
|
+
if account
|
40
|
+
# search for account. Should we really care?
|
41
|
+
else
|
42
|
+
all_apps = fetch_apps
|
43
|
+
return all_apps.first if all_apps.empty? || all_apps.size == 1
|
44
|
+
|
45
|
+
app = if options[:app_name]
|
46
|
+
EYCli::Model::App.find_by_name(options[:app_name], all_apps)
|
47
|
+
elsif git_repository?(base)
|
48
|
+
EYCli::Model::App.find_by_repository_uri(fetch_repository(base), all_apps)
|
49
|
+
end
|
50
|
+
|
51
|
+
unless app
|
52
|
+
choice = EYCli.term.choose_resource(all_apps,
|
53
|
+
"I don't know which app you want to use.",
|
54
|
+
"Please, select an application:")
|
55
|
+
app = EYCli::Model::App.find_by_name(choice, all_apps)
|
56
|
+
end
|
57
|
+
app
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def fetch_apps
|
62
|
+
EYCli::Model::App.all.sort_by {|app| app.name}
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module EYCli
|
2
|
+
module Controller
|
3
|
+
class Environments
|
4
|
+
def create(app, options = {})
|
5
|
+
framework_env = options[:framework_env] || 'production'
|
6
|
+
env_name = options[:name] || "#{app.name}_#{framework_env}"
|
7
|
+
|
8
|
+
create_options = {
|
9
|
+
:app => app,
|
10
|
+
'environment[name]' => env_name,
|
11
|
+
'environment[framework_env]' => framework_env
|
12
|
+
}
|
13
|
+
create_options.merge! fetch_custom_arguments(options)
|
14
|
+
|
15
|
+
create_options.merge! fetch_cluster_options(options[:cluster_configuration])
|
16
|
+
env = EYCli::Model::Environment.create(create_options)
|
17
|
+
|
18
|
+
if env.errors?
|
19
|
+
EYCli.term.print_errors(env.errors, "Environment creation failed:")
|
20
|
+
else
|
21
|
+
EYCli.term.success("Environment '#{env.name}' created successfully")
|
22
|
+
end
|
23
|
+
env
|
24
|
+
end
|
25
|
+
|
26
|
+
def deploy(app, options = {})
|
27
|
+
if !app.environments? || app.environments.empty?
|
28
|
+
EYCli.term.error <<-EOF
|
29
|
+
You don't have any environment associated to this application.
|
30
|
+
Try running `ey_cli create_env' to create your first environment.
|
31
|
+
EOF
|
32
|
+
elsif app.environments.size == 1
|
33
|
+
env = app.environments.first
|
34
|
+
else
|
35
|
+
name = EYCli.term.choose_resource(app.environments,
|
36
|
+
"I don't know which environment deploy on.",
|
37
|
+
"Please, select and environment")
|
38
|
+
env = EYCli::Model::Environment.find_by_name(name, app.environments)
|
39
|
+
end
|
40
|
+
|
41
|
+
if env
|
42
|
+
deploy = env.deploy(app, options)
|
43
|
+
|
44
|
+
if deploy.errors?
|
45
|
+
EYCli.term.print_errors(deploy.errors, "Application deployment failed:")
|
46
|
+
else
|
47
|
+
EYCli.term.success('Application deployed successfully')
|
48
|
+
end
|
49
|
+
else
|
50
|
+
EYCli.term.say('Nothing deployed')
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def fetch_cluster_options(options)
|
55
|
+
return {} unless options
|
56
|
+
cluster = {
|
57
|
+
'cluster_configuration[configuration]' => options[:configuration],
|
58
|
+
'cluster_configuration[ip_id]' => 'new'
|
59
|
+
}
|
60
|
+
if options[:configuration] == 'custom'
|
61
|
+
cluster['cluster_configuration[app_server_count]'] = options[:app_instances] || 2
|
62
|
+
cluster['cluster_configuration[db_slave_count]'] = options[:db_instances] || 0
|
63
|
+
cluster['cluster_configuration[instance_size]'] = options[:app_size] if options[:app_size]
|
64
|
+
cluster['cluster_configuration[db_instance_size]'] = options[:db_size] if options[:db_size]
|
65
|
+
end
|
66
|
+
cluster
|
67
|
+
end
|
68
|
+
|
69
|
+
def fetch_custom_arguments(options)
|
70
|
+
custom = {}
|
71
|
+
custom['app_deployment[new][domain_name]'] = options[:url] if options[:url]
|
72
|
+
custom['environment[app_server_stack_name]'] = options[:stack] if options[:stack]
|
73
|
+
custom['environment[ruby_version]'] = options[:ruby_version] if options[:ruby_version]
|
74
|
+
custom
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module EYCli
|
2
|
+
module Model
|
3
|
+
class App < Base
|
4
|
+
def self.find_by_repository_uri(repository_uri, collection = all)
|
5
|
+
collection.find {|resource| resource.repository_uri == repository_uri}
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.create_collection_path(hash)
|
9
|
+
account = hash.delete(:account)
|
10
|
+
raise Faraday::Error::ClientError, {:body => MultiJson.encode({:errors => {:account => 'Not found'}})} unless account
|
11
|
+
(account.class.base_path + '/%s/apps') % account.id
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module EYCli
|
2
|
+
module Model
|
3
|
+
class Base < Hashie::Mash
|
4
|
+
extend EYCli::SmartyParser
|
5
|
+
|
6
|
+
def self.all
|
7
|
+
resp = EYCli.api.get(base_path)
|
8
|
+
parse resp.body[base_path]
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.find(*args)
|
12
|
+
resp = EYCli.api.get(resolve_child_path(args))
|
13
|
+
parse resp.body[class_name]
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.find_by_name(name, collection = all)
|
17
|
+
# FIXME: EY api doesn't have filters. Let's do it by hand.
|
18
|
+
collection.select {|a| a.name == name }.first
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.base_path(path = "#{class_name}s") # HAX: pluralize!
|
22
|
+
@base_path ||= path
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.class_name
|
26
|
+
self.name.split('::').last.downcase
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.resolve_child_path(args)
|
30
|
+
collection_path = base_path % args[0..-1]
|
31
|
+
"#{collection_path}/#{args.last}"
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.create(hash)
|
35
|
+
path = create_collection_path(hash)
|
36
|
+
|
37
|
+
response = EYCli.api.post(path, nil, hash)
|
38
|
+
new response.body[class_name]
|
39
|
+
rescue Faraday::Error::ClientError => e
|
40
|
+
new MultiJson.decode(e.response[:body])
|
41
|
+
end
|
42
|
+
|
43
|
+
# Overrides Hashie::Mash#convert_value to not convert already parsed Mashes again
|
44
|
+
def convert_value(val, duping=false) #:nodoc:
|
45
|
+
return val.dup if val.is_a?(Hashie::Mash)
|
46
|
+
super(val, duping)
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.create_collection_path(hash)
|
50
|
+
raise "Not implemented. Override this method for each model"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module EYCli
|
2
|
+
module Model
|
3
|
+
class Environment < Base
|
4
|
+
base_path 'apps/%s/environments'
|
5
|
+
|
6
|
+
def self.create_collection_path(hash)
|
7
|
+
app = hash.delete(:app)
|
8
|
+
raise Faraday::Error::ClientError, {:body => MultiJson.encode({:errors => {:app => 'Not found'}})} unless app
|
9
|
+
base_path % app.id
|
10
|
+
end
|
11
|
+
|
12
|
+
def deploy(app, options = {})
|
13
|
+
deployment_options = deployment_configurations[app.name]
|
14
|
+
|
15
|
+
post_params = {
|
16
|
+
'deployment[migrate]' => options.key?(:migrate) ? options[:migrate] : deployment_options.migrate.perform,
|
17
|
+
'deployment[migrate_command]' => options[:migrate_command] || deployment_options.migrate.command,
|
18
|
+
'deployment[ref]' => options[:ref] || deployment_options.ref || 'HEAD'
|
19
|
+
}
|
20
|
+
|
21
|
+
response = EYCli.api.post(deploy_path(app), nil, post_params)
|
22
|
+
Hashie::Mash.new response['deployment']
|
23
|
+
rescue Faraday::Error::ClientError => e
|
24
|
+
Hashie::Mash.new MultiJson.decode(e.response[:body])
|
25
|
+
end
|
26
|
+
|
27
|
+
def deploy_path(app)
|
28
|
+
"#{self.class.resolve_child_path([app.id, id])}/deployments/deploy"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module EYCli
|
2
|
+
class OptionsParser
|
3
|
+
require 'optparse'
|
4
|
+
|
5
|
+
attr_reader :options
|
6
|
+
|
7
|
+
def self.parse(args)
|
8
|
+
new.parse(args)
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(options = {})
|
12
|
+
@options = options
|
13
|
+
end
|
14
|
+
|
15
|
+
def parse(args)
|
16
|
+
options_parser.parse!(args)
|
17
|
+
options
|
18
|
+
rescue OptionParser::InvalidOption => e
|
19
|
+
p e, options_parser
|
20
|
+
exit 1
|
21
|
+
end
|
22
|
+
|
23
|
+
def options_parser
|
24
|
+
::OptionParser.new do |opts|
|
25
|
+
opts.banner = 'ey_cli options:'
|
26
|
+
opts.separator ' '
|
27
|
+
|
28
|
+
opts.on('-v', '--version', 'display the current version') do
|
29
|
+
puts "ey_cli #{EYCli::VERSION}"
|
30
|
+
exit
|
31
|
+
end
|
32
|
+
|
33
|
+
opts.on('-a', '--account ACCOUNT_NAME') do |account|
|
34
|
+
options[:account] = account
|
35
|
+
end
|
36
|
+
|
37
|
+
opts.on('-p', '--app APP_NAME') do |app|
|
38
|
+
options[:app] = app
|
39
|
+
end
|
40
|
+
|
41
|
+
opts.on('-e', '--environment ENVIRONMENT_NAME') do |environment|
|
42
|
+
options[:environment] = environment
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|