jack-eb 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +25 -0
- data/.rspec +1 -0
- data/.travis.yml +6 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +107 -0
- data/Guardfile +12 -0
- data/LICENSE.txt +22 -0
- data/README.md +135 -0
- data/Rakefile +6 -0
- data/bin/jack +9 -0
- data/jack.gemspec +30 -0
- data/lib/jack.rb +14 -0
- data/lib/jack/cli.rb +54 -0
- data/lib/jack/cli/help.rb +107 -0
- data/lib/jack/config.rb +13 -0
- data/lib/jack/config/diff.rb +44 -0
- data/lib/jack/config/download.rb +66 -0
- data/lib/jack/config/sort.rb +19 -0
- data/lib/jack/config/transmit.rb +77 -0
- data/lib/jack/config/upload.rb +97 -0
- data/lib/jack/config/yaml_formatter.rb +30 -0
- data/lib/jack/create.rb +78 -0
- data/lib/jack/default/create.yml +1 -0
- data/lib/jack/ext/hash.rb +17 -0
- data/lib/jack/ui.rb +16 -0
- data/lib/jack/util.rb +20 -0
- data/lib/jack/version.rb +3 -0
- data/lib/jack/version_checker.rb +37 -0
- data/spec/fixtures/project/jack/cfg/stag-rails-app.cfg.yml +3 -0
- data/spec/lib/cli_spec.rb +44 -0
- data/spec/lib/config/diff_spec.rb +21 -0
- data/spec/lib/config/download_spec.rb +19 -0
- data/spec/lib/config/sort_spec.rb +16 -0
- data/spec/lib/config/transmit_spec.rb +41 -0
- data/spec/lib/config/upload_spec.rb +26 -0
- data/spec/lib/config/yaml_formatter_spec.rb +49 -0
- data/spec/lib/config_spec.rb +6 -0
- data/spec/lib/create_spec.rb +34 -0
- data/spec/lib/verison_checker_spec.rb +32 -0
- data/spec/spec_helper.rb +35 -0
- metadata +211 -0
@@ -0,0 +1,107 @@
|
|
1
|
+
module Jack
|
2
|
+
class CLI < Thor
|
3
|
+
class Help
|
4
|
+
class << self
|
5
|
+
def convention
|
6
|
+
<<-EOL
|
7
|
+
The configuration name is based on convention. An environment with the name of stag-rails-app-s1 results in the jack/cfg/stag-rails-app.cfg.yml being used. The convention can be overriden with the --cfg option.
|
8
|
+
EOL
|
9
|
+
end
|
10
|
+
|
11
|
+
def create
|
12
|
+
<<-EOL
|
13
|
+
Creates a new environment using the configuration in jack/cfg folder.
|
14
|
+
|
15
|
+
#{convention}
|
16
|
+
|
17
|
+
Example:
|
18
|
+
|
19
|
+
$ jack create stag-rails-app-s1
|
20
|
+
|
21
|
+
$ jack create -c myconfig stag-rails-app-s1
|
22
|
+
|
23
|
+
$ jack create -a myapp -c myconfig stag-rails-app-s1
|
24
|
+
EOL
|
25
|
+
end
|
26
|
+
|
27
|
+
def upload
|
28
|
+
<<-EOL
|
29
|
+
Uploads the specified template configuration in jack/cfg and applies it to the environment immediately.
|
30
|
+
|
31
|
+
#{convention}
|
32
|
+
|
33
|
+
Example:
|
34
|
+
|
35
|
+
$ jack config upload stag-rails-app-s1
|
36
|
+
|
37
|
+
$ jack config upload -a myapp -c myconfig stag-rails-app-s1
|
38
|
+
EOL
|
39
|
+
end
|
40
|
+
|
41
|
+
def download
|
42
|
+
<<-EOL
|
43
|
+
Downloads the environment's config to jack/cfg/[CONFIG_NAME].cfg.yml
|
44
|
+
|
45
|
+
#{convention}
|
46
|
+
|
47
|
+
Example:
|
48
|
+
|
49
|
+
$ jack config download stag-rails-app-s1
|
50
|
+
|
51
|
+
$ jack config download -a myapp -c myconfig stag-rails-app-s1
|
52
|
+
EOL
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
def diff
|
57
|
+
<<-EOL
|
58
|
+
Diff local jack config vs environment config. The environment config is generated on the fly.
|
59
|
+
|
60
|
+
If you have colordiff installed the diff command will use make use of it. If you want to have your own custom diff, you can set your JACK_DIFF environment variable to it.
|
61
|
+
|
62
|
+
#{convention}
|
63
|
+
|
64
|
+
Example:
|
65
|
+
|
66
|
+
$ jack config diff stag-rails-app-s1
|
67
|
+
|
68
|
+
$ jack config diff -a myapp -c myconfig stag-rails-app-s1
|
69
|
+
EOL
|
70
|
+
end
|
71
|
+
|
72
|
+
def sort
|
73
|
+
<<-EOL
|
74
|
+
Reformats local jack config file to a sorted yaml format.
|
75
|
+
|
76
|
+
#{convention}
|
77
|
+
|
78
|
+
Example:
|
79
|
+
|
80
|
+
$ jack config sort stag-rails-app-s1
|
81
|
+
|
82
|
+
$ jack config sort -c myconfig stag-rails-app-s1 # env name doesnt matter here
|
83
|
+
EOL
|
84
|
+
end
|
85
|
+
|
86
|
+
# dumb thor bug, so this doesnt even show, leaving here in case Thor is fixed
|
87
|
+
def config
|
88
|
+
<<-EOL
|
89
|
+
Manage the environment's config. Can use this to download the environment's config to jack/cfg folder or upload config in jack/cfg folder and apply it to the environment.
|
90
|
+
|
91
|
+
Example:
|
92
|
+
|
93
|
+
$ jack config download stag-rails-app-s1
|
94
|
+
|
95
|
+
For more info:
|
96
|
+
|
97
|
+
$ jack help config
|
98
|
+
|
99
|
+
$ jack config help apply
|
100
|
+
|
101
|
+
$ jack config help download
|
102
|
+
EOL
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
data/lib/jack/config.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Jack
|
4
|
+
module Config
|
5
|
+
autoload :Base, 'jack/config/base'
|
6
|
+
autoload :Diff, 'jack/config/diff'
|
7
|
+
autoload :Download, 'jack/config/download'
|
8
|
+
autoload :Sort, 'jack/config/sort'
|
9
|
+
autoload :Transmit, 'jack/config/transmit'
|
10
|
+
autoload :Upload, 'jack/config/upload'
|
11
|
+
autoload :YamlFormatter, 'jack/config/yaml_formatter'
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Jack
|
2
|
+
module Config
|
3
|
+
class Diff
|
4
|
+
attr_reader :transmit
|
5
|
+
def initialize(options={})
|
6
|
+
@options = options
|
7
|
+
@root = options[:root] || '.'
|
8
|
+
@env_name = options[:env_name]
|
9
|
+
@download = Jack::Config::Download.new(options)
|
10
|
+
end
|
11
|
+
|
12
|
+
def run
|
13
|
+
@download.get_current_cfg
|
14
|
+
do_diff(@download.current_path, @download.local_config_path)
|
15
|
+
cleanup_files
|
16
|
+
end
|
17
|
+
|
18
|
+
def do_diff(current, local)
|
19
|
+
UI.say "Comparing #{current} and #{local}"
|
20
|
+
return if @options[:noop]
|
21
|
+
sorter = YamlFormatter.new
|
22
|
+
sorter.process(current)
|
23
|
+
sorter.process(local)
|
24
|
+
# need to use system so that the diff shows up properly in the terminal
|
25
|
+
system(diff_command, @download.current_path, @download.local_config_path)
|
26
|
+
puts ""
|
27
|
+
end
|
28
|
+
|
29
|
+
def cleanup_files
|
30
|
+
return false if @options[:dirty]
|
31
|
+
@download.clean(silent=true)
|
32
|
+
end
|
33
|
+
|
34
|
+
def diff_command
|
35
|
+
return ENV['JACK_DIFF'] if ENV['JACK_DIFF']
|
36
|
+
if system("type colordiff > /dev/null 2>&1")
|
37
|
+
"colordiff"
|
38
|
+
else
|
39
|
+
"diff"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
module Jack
|
5
|
+
module Config
|
6
|
+
class Download < Transmit
|
7
|
+
include Util
|
8
|
+
|
9
|
+
attr_reader :current_path, :current_name
|
10
|
+
|
11
|
+
def initialize(options={})
|
12
|
+
super
|
13
|
+
@current_path = "#{@saved_configs}/current-#{timestamp}.cfg.yml"
|
14
|
+
@current_name = extract_name(@current_path)
|
15
|
+
end
|
16
|
+
|
17
|
+
def run
|
18
|
+
download
|
19
|
+
end
|
20
|
+
|
21
|
+
def download
|
22
|
+
get_current_cfg
|
23
|
+
copy_to_local_cfg
|
24
|
+
clean
|
25
|
+
UI.say "Config downloaded to #{@local_config_path}".colorize(:green)
|
26
|
+
end
|
27
|
+
|
28
|
+
def get_current_cfg
|
29
|
+
UI.say "Downloading config file..."
|
30
|
+
eb_config_save
|
31
|
+
end
|
32
|
+
|
33
|
+
# for specs
|
34
|
+
def eb_config_save
|
35
|
+
do_cmd("eb config save --cfg #{current_name} #{@env_name}", @options)
|
36
|
+
end
|
37
|
+
|
38
|
+
def copy_to_local_cfg
|
39
|
+
UI.say "Writing to local config file: #{@local_config_path}"
|
40
|
+
dirname = File.dirname("#{@root}/#{@local_config_path}")
|
41
|
+
FileUtils.mkdir_p(dirname) unless File.exist?(dirname)
|
42
|
+
do_copy_to_local_cfg
|
43
|
+
end
|
44
|
+
|
45
|
+
# for specs
|
46
|
+
def do_copy_to_local_cfg
|
47
|
+
return if @options[:noop]
|
48
|
+
local_path = "#{@root}/#{@local_config_path}"
|
49
|
+
FileUtils.cp(@current_path, local_path)
|
50
|
+
YamlFormatter.new.process(local_path)
|
51
|
+
end
|
52
|
+
|
53
|
+
# remove both the local download file and remote eb config
|
54
|
+
def clean(silent=false)
|
55
|
+
return if @options[:dirty]
|
56
|
+
UI.say "Cleaning up eb remote config and local files" unless silent
|
57
|
+
eb.delete_configuration_template(
|
58
|
+
application_name: @app_name,
|
59
|
+
template_name: current_name
|
60
|
+
) unless @options[:noop]
|
61
|
+
FileUtils.rm_f(@current_path)
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Jack
|
4
|
+
module Config
|
5
|
+
class Sort < Transmit # for the local_config_path method
|
6
|
+
include Util
|
7
|
+
|
8
|
+
def initialize(options={})
|
9
|
+
super
|
10
|
+
@options = options
|
11
|
+
end
|
12
|
+
|
13
|
+
def run
|
14
|
+
YamlFormatter.new.process("#{@root}/#{local_config_path}")
|
15
|
+
UI.say "Reformatted the local config to a sorted yaml format at #{local_config_path}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
module Jack
|
5
|
+
module Config
|
6
|
+
class Transmit
|
7
|
+
include Util
|
8
|
+
|
9
|
+
attr_reader :local_config_path
|
10
|
+
def initialize(options={})
|
11
|
+
@options = options
|
12
|
+
@root = options[:root] || '.'
|
13
|
+
@env_name = options[:env_name]
|
14
|
+
@app_name = @options[:app_name] || app_name_convention(@env_name)
|
15
|
+
|
16
|
+
@saved_configs = "#{@root}/.elasticbeanstalk/saved_configs"
|
17
|
+
|
18
|
+
local_config_name = options[:cfg] || config_name_convention(@env_name)
|
19
|
+
@local_config_path = "jack/cfg/#{local_config_name}.cfg.yml"
|
20
|
+
|
21
|
+
sync_eb_config_yml
|
22
|
+
end
|
23
|
+
|
24
|
+
def eb_config_path
|
25
|
+
"#{@root}/.elasticbeanstalk/config.yml"
|
26
|
+
end
|
27
|
+
|
28
|
+
def sync_eb_config_yml(force=false)
|
29
|
+
# should break out to another class but too much work right now
|
30
|
+
create = Create.new(@options)
|
31
|
+
create.ensure_eb_init
|
32
|
+
do_sync_eb_config_yml(force)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
# force flag for specs
|
38
|
+
def do_sync_eb_config_yml(force)
|
39
|
+
return if @options[:noop] and !force
|
40
|
+
envs = describe_environments
|
41
|
+
env = envs[:environments].first
|
42
|
+
if env
|
43
|
+
write_eb_config_yml(env.application_name, env.solution_stack_name)
|
44
|
+
else
|
45
|
+
UI.say "#{@env_name} could not be found".colorize(:red)
|
46
|
+
exit 0
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def write_eb_config_yml(application_name, solution_stack_name)
|
51
|
+
data = YAML.load_file(eb_config_path)
|
52
|
+
data['global']['application_name'] = application_name
|
53
|
+
data['global']['default_platform'] = solution_stack_name
|
54
|
+
dump = YAML.dump(data).gsub("!ruby/object:Hash", '')
|
55
|
+
dump = dump.split("\n")[1..-1].join("\n") # strip first line
|
56
|
+
File.write(eb_config_path, dump)
|
57
|
+
end
|
58
|
+
|
59
|
+
# useful for specs
|
60
|
+
def describe_environments
|
61
|
+
eb.describe_environments(environment_names: [@env_name])
|
62
|
+
end
|
63
|
+
|
64
|
+
def config_name_convention(env_name)
|
65
|
+
env_name.split('-')[0..-2].join('-')
|
66
|
+
end
|
67
|
+
|
68
|
+
def timestamp
|
69
|
+
Time.now.strftime "%Y-%m-%d_%H-%M-%S"
|
70
|
+
end
|
71
|
+
|
72
|
+
def extract_name(path)
|
73
|
+
path.split('/').last.sub('.cfg.yml','')
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Jack
|
4
|
+
module Config
|
5
|
+
class Upload < Transmit
|
6
|
+
include Util
|
7
|
+
|
8
|
+
attr_reader :upload_path, :upload_name
|
9
|
+
|
10
|
+
def initialize(options={})
|
11
|
+
super
|
12
|
+
@upload_path = "#{@saved_configs}/#{@env_name}-#{timestamp}.cfg.yml"
|
13
|
+
@upload_name = extract_name(@upload_path)
|
14
|
+
end
|
15
|
+
|
16
|
+
def run
|
17
|
+
unless local_cfg_exist?
|
18
|
+
UI.say "#{local_config_path} does not exist, nothing to upload"
|
19
|
+
exit 0
|
20
|
+
end
|
21
|
+
compare
|
22
|
+
if confirm
|
23
|
+
upload
|
24
|
+
update_env
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def compare
|
29
|
+
Diff.new(@options).run
|
30
|
+
end
|
31
|
+
|
32
|
+
def upload
|
33
|
+
return false unless local_cfg_exist?
|
34
|
+
UI.say("Copying #{@local_config_path} to #{@upload_path} for the upload")
|
35
|
+
cp_to_save_configs
|
36
|
+
upload_to_eb
|
37
|
+
clean_up
|
38
|
+
end
|
39
|
+
|
40
|
+
def confirm
|
41
|
+
UI.say("Are you sure you want to update the environment with your the new config #{@config_path}?".colorize(:yellow))
|
42
|
+
UI.say(<<-EOL)
|
43
|
+
If the difference is not what you expected, you should say no.
|
44
|
+
A blank newline indicates that there was no difference.
|
45
|
+
If you want to download the config from the environment and
|
46
|
+
overwrite your #{@local_config_path} instead, you can use this command:
|
47
|
+
$ jack config download #{@env_name}
|
48
|
+
$ jack config help download # for more info
|
49
|
+
EOL
|
50
|
+
print "yes/no? [no] " unless @options[:silent]
|
51
|
+
answer = get_answer
|
52
|
+
answer =~ /^y/
|
53
|
+
end
|
54
|
+
|
55
|
+
def get_answer
|
56
|
+
return 'y' if @options[:force]
|
57
|
+
$stdin.gets
|
58
|
+
end
|
59
|
+
|
60
|
+
def update_env
|
61
|
+
UI.say("Updating environment #{@env_name} with template #{upload_name}")
|
62
|
+
eb.update_environment(
|
63
|
+
environment_name: @env_name,
|
64
|
+
template_name: upload_name
|
65
|
+
) unless @options[:noop]
|
66
|
+
end
|
67
|
+
|
68
|
+
def local_cfg_exist?
|
69
|
+
File.exist?("#{@root}/#{@local_config_path}")
|
70
|
+
end
|
71
|
+
|
72
|
+
def cp_to_save_configs
|
73
|
+
ensure_folder_exist(@saved_configs)
|
74
|
+
FileUtils.cp("#{@root}/#{@local_config_path}", @upload_path)
|
75
|
+
end
|
76
|
+
|
77
|
+
def upload_to_eb
|
78
|
+
eb_config_put
|
79
|
+
end
|
80
|
+
|
81
|
+
# for specs
|
82
|
+
def eb_config_put
|
83
|
+
do_cmd("eb config put #{upload_name}", @options)
|
84
|
+
end
|
85
|
+
|
86
|
+
def clean_up
|
87
|
+
return if @options[:dirty]
|
88
|
+
FileUtils.rm_f(@upload_path)
|
89
|
+
end
|
90
|
+
|
91
|
+
def ensure_folder_exist(folder)
|
92
|
+
FileUtils.mkdir_p(folder) unless File.exist?(folder)
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "yaml"
|
2
|
+
|
3
|
+
module Jack
|
4
|
+
module Config
|
5
|
+
# Class does very specific formatting for the eb config files:
|
6
|
+
#
|
7
|
+
# * Makes sure that the keys are sorted so we can compare them
|
8
|
+
# * It also scripts out the generated DateModified and DateCreated Metadata
|
9
|
+
class YamlFormatter
|
10
|
+
def process(file)
|
11
|
+
data = YAML.load_file(file)
|
12
|
+
data = strip_metadata_dates(data)
|
13
|
+
dump = YAML.dump(data).gsub("!ruby/object:Hash", '')
|
14
|
+
dump = dump.split("\n")[1..-1].join("\n") + "\n" # strip first line
|
15
|
+
outfile = "#{file}.sorted"
|
16
|
+
File.open(outfile, 'w') { |f| f.write(dump) }
|
17
|
+
FileUtils.mv(outfile, file)
|
18
|
+
end
|
19
|
+
|
20
|
+
def strip_metadata_dates(data)
|
21
|
+
metadata = data['EnvironmentConfigurationMetadata']
|
22
|
+
if metadata
|
23
|
+
metadata.delete('DateModified')
|
24
|
+
metadata.delete('DateCreated')
|
25
|
+
end
|
26
|
+
data
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|