ey_cli 0.1.0
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.
- 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
|