jack-eb 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,78 @@
1
+ require "yaml"
2
+
3
+ module Jack
4
+ class Create
5
+ include Util
6
+
7
+ def initialize(options={})
8
+ @options = options
9
+ @root = options[:root] || '.'
10
+ @env_name = options[:env_name]
11
+ @app_name = options[:app_name] || app_name_convention(@env_name)
12
+ end
13
+
14
+ def run
15
+ ensure_eb_init
16
+ create_env
17
+ end
18
+
19
+ def ensure_eb_init
20
+ unless File.exist?("#{@root}/.elasticbeanstalk/config.yml")
21
+ do_cmd(%Q|eb init -p "#{platform}" "#{@app_name}"|, @options)
22
+ end
23
+ end
24
+
25
+ def platform
26
+ create_yaml['platform'] || latest_docker_platform
27
+ end
28
+
29
+ def latest_docker_platform
30
+ return if @options[:noop] # for cli spec
31
+ solution_stacks.grep(/Docker/).reject {|x| x =~ /Preconfigured/}.sort.last
32
+ end
33
+
34
+ # for specs
35
+ def solution_stacks
36
+ eb.list_available_solution_stacks.solution_stacks
37
+ end
38
+
39
+ def create_env
40
+ command = build_command
41
+ do_cmd(command, @options)
42
+ end
43
+
44
+ def build_command
45
+ @cfg = upload_cfg
46
+ flags = create_yaml.inject("") {|s,(k,v)| s << %{--#{k} "#{v}" } ; s }.strip
47
+ "eb create --nohang #{flags} #{@cfg}#{cname}#{@env_name}"
48
+ end
49
+
50
+ def create_yaml
51
+ return @create_yaml if @create_yaml
52
+
53
+ project_file = "#{@root}/jack/create.yml"
54
+ project = File.exist?(project_file) ? YAML.load_file(project_file) : {}
55
+
56
+ user_file = "#{ENV['HOME']}/.jack/create.yml"
57
+ user = File.exist?(user_file) ? YAML.load_file(user_file) : {}
58
+
59
+ default_file = File.expand_path("../default/create.yml", __FILE__)
60
+ default = YAML.load_file(default_file)
61
+
62
+ @create_yaml = default.merge(project.merge(user))
63
+ end
64
+
65
+ def upload_cfg
66
+ @upload = Config::Upload.new(@options)
67
+ if @upload.local_cfg_exist?
68
+ @upload.upload
69
+ cfg = "--cfg #{@upload.upload_name} "
70
+ end
71
+ end
72
+
73
+ def cname
74
+ "--cname #{@env_name} "
75
+ end
76
+
77
+ end
78
+ end
@@ -0,0 +1 @@
1
+ keyname: default
@@ -0,0 +1,17 @@
1
+ # http://www.dzone.com/snippets/generating-yaml-hashes-sorted
2
+
3
+ require 'yaml'
4
+ class Hash
5
+ # Replacing the to_yaml function so it'll serialize hashes sorted (by their keys)
6
+ #
7
+ # Original function is in /usr/lib/ruby/1.8/yaml/rubytypes.rb
8
+ def to_yaml( opts = {} )
9
+ YAML::quick_emit( object_id, opts ) do |out|
10
+ out.map( taguri, to_yaml_style ) do |map|
11
+ sort.each do |k, v| # <-- here's my addition (the 'sort')
12
+ map.add( k, v )
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,16 @@
1
+ module Jack
2
+ class UI
3
+ class << self
4
+ @@mute = false
5
+ def mute
6
+ @@mute
7
+ end
8
+ def mute=(v)
9
+ @@mute=v
10
+ end
11
+ def say(msg='')
12
+ puts msg unless mute
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,20 @@
1
+ module Jack
2
+ module Util
3
+ def do_cmd(command, options={})
4
+ UI.say "Running: #{command.colorize(:green)}" unless options[:silent]
5
+ return command if options[:noop]
6
+ out = `#{command}`
7
+ UI.say out unless options[:silent]
8
+ end
9
+
10
+ def app_name_convention(env_name)
11
+ env_name.split('-')[1] # convention
12
+ end
13
+
14
+ def eb
15
+ region = ENV['AWS_REGION'] || 'us-east-1'
16
+ @@eb ||= Aws::ElasticBeanstalk::Client.new(region: region)
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,3 @@
1
+ module Jack
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,37 @@
1
+ module Jack
2
+ class VersionChecker
3
+ REQUIRED_VERSION = "3.1.2"
4
+
5
+ def run
6
+ leave("eb cli tool is not installed") unless system("type eb > /dev/null 2>&1")
7
+ leave("eb version is too low") unless check
8
+ end
9
+
10
+ def check
11
+ major, minor, patch = parse_version(get_version)
12
+ r_major, r_minor, r_patch = normalize_version(REQUIRED_VERSION)
13
+ (major > r_major) ||
14
+ (major == r_major && minor > r_minor) ||
15
+ (major == r_major && minor == r_minor && patch >= r_patch)
16
+ end
17
+
18
+ def get_version
19
+ `eb --version`
20
+ end
21
+
22
+ def parse_version(version)
23
+ parsed = version.match(/EB CLI (\d+\.\d+\.\d+)/)[1]
24
+ normalize_version(parsed)
25
+ end
26
+
27
+ def normalize_version(parsed)
28
+ parsed.split('.').collect(&:to_i)
29
+ end
30
+
31
+ # for specs
32
+ def leave(message='')
33
+ puts("SORRY: #{message}, please install at least version #{REQUIRED_VERSION}")
34
+ exit 0
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,3 @@
1
+ AWSConfigurationTemplateVersion: 1.1.0.0
2
+ EnvironmentConfigurationMetadata:
3
+ Description: test.
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ describe Jack::CLI do
4
+ before(:all) do
5
+ @args = "stag-rails-app-s9 --root spec/fixtures/project --noop --force"
6
+ FileUtils.rm_rf("spec/fixtures/project/.elasticbeanstalk")
7
+ end
8
+
9
+ describe "jack" do
10
+ it "should create environment" do
11
+ out = execute("bin/jack create #{@args}")
12
+ # puts out
13
+ expect(out).to include('eb create')
14
+ expect(out).to include('--cname stag-rails-app-s9')
15
+ expect(out).to include('--keyname "default"')
16
+ expect(out).to include('--cfg stag-rails-app')
17
+ expect(out).to include('stag-rails-app-s9')
18
+ end
19
+
20
+ it "should upload and apply config to environment" do
21
+ out = execute("bin/jack config upload #{@args}")
22
+ # puts out
23
+ expect(out).to include('eb config put')
24
+ end
25
+
26
+ it "should download config from environment" do
27
+ out = execute("bin/jack config download #{@args}")
28
+ # puts out
29
+ expect(out).to include("Config downloaded")
30
+ end
31
+
32
+ it "should diff local config from eb environment config" do
33
+ out = execute("bin/jack config diff #{@args}")
34
+ # puts out
35
+ expect(out).to include("Comparing")
36
+ end
37
+
38
+ it "should reformat the local config to a sorted yaml format" do
39
+ out = execute("bin/jack config sort #{@args}")
40
+ # puts out
41
+ expect(out).to include("Reformatted the local config")
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe Jack::Config do
4
+ before(:all) do
5
+ Jack::UI.mute = true
6
+ end
7
+
8
+ let(:diff) { Jack::Config::Diff.new(test_options) }
9
+
10
+ describe "diff" do
11
+ it "diff do_diff" do
12
+ expect(diff).to receive(:do_diff)
13
+ diff.run
14
+ end
15
+
16
+ it "diff diff_command" do
17
+ command = diff.diff_command
18
+ expect(command).to match /diff/
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe Jack::Config do
4
+ before(:all) do
5
+ Jack::UI.mute = true
6
+ end
7
+
8
+ let(:download) { Jack::Config::Download.new(test_options) }
9
+
10
+ describe "download" do
11
+ it "download" do
12
+ # mock methods way down deep to test code paths, test reads weird though
13
+ expect(download).to receive(:eb_config_save)
14
+ expect(download).to receive(:do_copy_to_local_cfg)
15
+ download.download
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ describe Jack::Config do
4
+ before(:all) do
5
+ Jack::UI.mute = true
6
+ end
7
+
8
+ let(:sort) { Jack::Config::Sort.new(test_options) }
9
+
10
+ describe "sort" do
11
+ it "process" do
12
+ # not much to check just for syntax errors
13
+ sort.run
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+ require 'ostruct'
3
+
4
+ describe Jack::Config do
5
+ before(:all) do
6
+ Jack::UI.mute = true
7
+ fake_eb_config
8
+ end
9
+
10
+ let(:transmit) { Jack::Config::Transmit.new(test_options) }
11
+
12
+ def fake_eb_config
13
+ input = <<-EOL
14
+ ---
15
+ global:
16
+ application_name: blah
17
+ default_platform: 64bit Amazon Linux 2014.09 v1.2.0 running Docker 1.3.3
18
+ EOL
19
+ file = "#{@root}/.elasticbeanstalk/config.yml"
20
+ File.open(file, 'w') { |file| file.write(input) }
21
+ end
22
+
23
+ def mock
24
+ {environments: [OpenStruct.new(
25
+ application_name: "myapp",
26
+ solution_stack_name: "my solution stack")]}
27
+ end
28
+
29
+ describe "transmit" do
30
+ it "sync_eb_config_yml" do
31
+ expect(transmit).to receive(:describe_environments).and_return(mock)
32
+ transmit.sync_eb_config_yml(true)
33
+
34
+ data = YAML.load_file(transmit.eb_config_path)
35
+ global = data['global']
36
+ expect(global['application_name']).to eq "myapp"
37
+ expect(global['default_platform']).to eq "my solution stack"
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe Jack::Config::Upload do
4
+ before(:all) do
5
+ Jack::UI.mute = true
6
+ end
7
+
8
+ let(:upload) { Jack::Config::Upload.new(test_options.merge(silent: true)) }
9
+
10
+ describe "upload" do
11
+ it "upload code paths" do
12
+ exist = upload.local_cfg_exist?
13
+ expect(exist).to be true # checking fixture
14
+ # mock methods way down deep to test code paths, test reads weird though
15
+ expect(upload).to receive(:eb_config_put)
16
+ upload.upload
17
+ end
18
+
19
+ it "upload flow" do
20
+ expect(upload).to receive(:compare)
21
+ expect(upload).to receive(:upload)
22
+ expect(upload).to receive(:update_env)
23
+ upload.run
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+
3
+ describe Jack::Config::YamlFormatter do
4
+ let(:sorter) { Jack::Config::YamlFormatter.new }
5
+
6
+ describe "sorter" do
7
+ it "process should sort the keys" do
8
+ input = <<-EOL
9
+ EnvironmentConfigurationMetadata:
10
+ Description: test.
11
+ Foo: 1
12
+ AWSConfigurationTemplateVersion: 1.1.0.0
13
+ EOL
14
+ file = "spec/fixtures/fake.cfg.yml"
15
+
16
+ File.open(file, 'w') { |file| file.write(input) }
17
+ sorter.process(file)
18
+ output = File.read(file)
19
+
20
+ expect(output).to eq <<-EOL
21
+ AWSConfigurationTemplateVersion: 1.1.0.0
22
+ EnvironmentConfigurationMetadata:
23
+ Description: test.
24
+ Foo: 1
25
+ EOL
26
+ end
27
+
28
+ it "process should strip date modified and created" do
29
+ input = <<-EOL
30
+ EnvironmentConfigurationMetadata:
31
+ DateModified: '1425215243000'
32
+ Description: test.
33
+ DateCreated: '1425215243000'
34
+ AWSConfigurationTemplateVersion: 1.1.0.0
35
+ EOL
36
+ file = "spec/fixtures/fake.cfg.yml"
37
+
38
+ File.open(file, 'w') { |file| file.write(input) }
39
+ sorter.process(file)
40
+ output = File.read(file)
41
+
42
+ expect(output).to eq <<-EOL
43
+ AWSConfigurationTemplateVersion: 1.1.0.0
44
+ EnvironmentConfigurationMetadata:
45
+ Description: test.
46
+ EOL
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,6 @@
1
+ require 'spec_helper'
2
+
3
+ describe Jack::Config do
4
+ before(:all) do
5
+ end
6
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe Jack::Create do
4
+ before(:all) do
5
+ @create = Jack::Create.new(test_options)
6
+ end
7
+
8
+ def solution_stacks
9
+ ["64bit Amazon Linux 2014.09 v1.2.0 running Docker 1.3.3", "64bit Amazon Linux 2014.03 v1.0.0 running Docker 1.0.0", "64bit Amazon Linux 2014.03 v1.0.1 running Docker 1.0.0", "64bit Amazon Linux 2014.03 v1.0.4 running Docker 0.9.0", "64bit Amazon Linux 2014.03 v1.0.5 running Docker 0.9.0", "64bit Debian jessie v1.2.0 running Go 1.3 (Preconfigured - Docker)", "64bit Debian jessie v1.2.0 running Go 1.4 (Preconfigured - Docker)"]
10
+ end
11
+
12
+ describe "jack" do
13
+ it "create environment" do
14
+ command = @create.build_command
15
+ # puts "command = #{command }"
16
+ expect(command).to include('eb create')
17
+ expect(command).to include('--cname stag-rails-app-s9')
18
+ expect(command).to include('--keyname "default"')
19
+ expect(command).to include('--cfg stag-rails-app')
20
+ expect(command).to include('stag-rails-app-s9')
21
+ end
22
+
23
+ it "create_yaml" do
24
+ data = @create.create_yaml
25
+ expect(data["keyname"]).to eq "default"
26
+ end
27
+
28
+ it "list solution stacks" do
29
+ @create = Jack::Create.new(test_options.merge(noop: false))
30
+ expect(@create).to receive(:solution_stacks).and_return(solution_stacks)
31
+ expect(@create.latest_docker_platform).to eq "64bit Amazon Linux 2014.09 v1.2.0 running Docker 1.3.3"
32
+ end
33
+ end
34
+ end