elastic-beanstalk 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+
19
+ .idea
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use ruby-1.9.3@elastic_beanstalk --create
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 AlienFast, LLC
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,153 @@
1
+ # ElasticBeanstalk
2
+
3
+ Configure and deploy a rails app to Elastic Beanstalk via rake in 60 seconds. Maintain multiple environment DRY configurations and .ebextensions in one easy to use configuration file.
4
+
5
+ This gem simplifies configuration, and passes the heavy lifting to the [eb_deployer](https://github.com/ThoughtWorksStudios/eb_deployer) from ThoughtWorksStudios.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'elastic-beanstalk'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install elastic-beanstalk
20
+
21
+ ## Usage
22
+
23
+ Given an application named 'acme':
24
+
25
+ ### Step 1: Add a ~/.aws.acme.yml
26
+ This should contain the access and secret keys generated from the selected IAM user. This is the only file that will need to reside outside the repository.
27
+
28
+ access_key_id: XXXXXX
29
+ secret_access_key: XXXXXX
30
+
31
+ ### Step 2. Add a config/eb.yml to your rails project
32
+ Something like this should get you started
33
+
34
+ app: acme
35
+ region: us-east-1
36
+ solution_stack_name: 64bit Amazon Linux running Ruby 1.9.3
37
+
38
+ development:
39
+ strategy: inplace_update
40
+ options:
41
+ aws:autoscaling:launchconfiguration:
42
+ InstanceType: t1.micro
43
+
44
+ production:
45
+ options:
46
+ aws:autoscaling:launchconfiguration:
47
+ InstanceType: t1.small
48
+
49
+ ### Step 3. Package and deploy
50
+ The default is the 'development' environment, change this via command line by prefixing with i.e. RAILS_ENV=production
51
+
52
+ $ rake eb:package eb:deploy
53
+
54
+ ### Step 4. Get some coffee
55
+ This will take a while. We intend to provide an example in the wiki and/or samples dir that implements a [caching strategy detailed here](http://horewi.cz/faster-rails-3-deployments-to-aws-elastic-beanstalk.html) to speed up deployment.
56
+
57
+ ## Rake Tasks
58
+
59
+ eb:config # Setup AWS.config and merge/override environments into one resolved configuration.
60
+ eb:show_config # Show resolved configuration without doing anything. arguments[:version]
61
+ eb:clobber # Remove any generated package.
62
+ eb:package # Package zip source bundle for Elastic Beanstalk.
63
+ eb:deploy # Deploy to Elastic Beanstalk. arguments[:version]
64
+ eb:destroy # ** Warning: Destroy Elastic Beanstalk application and *all* environments. arguments[:force]
65
+
66
+ ## A real-world example
67
+
68
+ Deploy version 1.1.3 of acme to production
69
+
70
+ $ RAILS_ENV=production rake eb:package eb:deploy[1.1.3]
71
+
72
+ config/eb.yml
73
+
74
+ # This is a sample that has not been executed so it may not be exactly 100%, but is intended to show
75
+ # that access to full options_settings and .ebextensions is intended.
76
+ #---
77
+ app: acme
78
+ region: us-east-1
79
+ solution_stack_name: 64bit Amazon Linux running Ruby 1.9.3
80
+ package:
81
+ verbose: true
82
+ exclude_dirs: [solr, features] # additional dirs that merge with default excludes
83
+ exclude_files: [rspec.xml, README*, db/*.sqlite3]
84
+ smoke_test: |
85
+ lambda { |host|
86
+
87
+ require 'eb_smoke_tester'
88
+
89
+ EbSmokeTester.test_url("http://#{host}/ping", 600, 5, 'All good! Everything is up and checks out.')
90
+ }
91
+ #--
92
+ ebextensions:
93
+ 01settings.config:
94
+ # Run rake tasks before an application deployment
95
+ container_commands:
96
+ 01seed:
97
+ command: rake db:seed
98
+ leader_only: true
99
+ # run any necessary commands
100
+ 02commands.config:
101
+ container_commands:
102
+ 01timezone:
103
+ command: "ln -sf /usr/share/zoneinfo/America/Chicago /etc/localtime"
104
+ #---
105
+ options:
106
+ aws:autoscaling:launchconfiguration:
107
+ EC2KeyName: eb-ssh
108
+ SecurityGroups: 'acme-production-control'
109
+
110
+ aws:autoscaling:asg:
111
+ MinSize: 1
112
+ MaxSize: 5
113
+
114
+ aws:elb:loadbalancer:
115
+ SSLCertificateId: 'arn:aws:iam::XXXXXXX:server-certificate/acme'
116
+ LoadBalancerHTTPSPort: 443
117
+
118
+ aws:elb:policies:
119
+ Stickiness Policy: true
120
+
121
+ aws:elasticbeanstalk:sns:topics:
122
+ Notification Endpoint: 'alerts@acme.com'
123
+
124
+ aws:elasticbeanstalk:application:
125
+ Application Healthcheck URL: '/'
126
+ #---
127
+ development:
128
+ strategy: inplace_update
129
+ options:
130
+ aws:autoscaling:launchconfiguration:
131
+ InstanceType: t1.micro
132
+ aws:elasticbeanstalk:application:environment:
133
+ RAILS_SKIP_ASSET_COMPILATION: true
134
+ #---
135
+ production:
136
+ options:
137
+ aws:autoscaling:launchconfiguration:
138
+ InstanceType: t1.small
139
+
140
+ ## Still to come
141
+ 1. RDS sample config
142
+ 2. Caching sample config
143
+ 3. More thorough access to the Elastic Beanstalk api as-needed.
144
+
145
+ ## Contributing
146
+
147
+ Please contribute! While this is working great, a greater scope of functionality is certainly easily attainable with this foundation in place.
148
+
149
+ 1. Fork it
150
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
151
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
152
+ 4. Push to the branch (`git push origin my-new-feature`)
153
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ # add rspec task
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new('spec')
6
+ task :default => :spec
7
+ task :test => :spec
8
+
@@ -0,0 +1,33 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'elastic_beanstalk/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'elastic-beanstalk'
8
+ spec.version = ElasticBeanstalk::VERSION
9
+ spec.authors = ['Kevin Ross']
10
+ spec.email = ['kevin.ross@alienfast.com']
11
+ spec.description = %q{The simplest way to configure and deploy an Elastic Beanstalk application via rake.}
12
+ spec.summary = %q{Configure and deploy a rails app to Elastic Beanstalk via rake in 60 seconds. Maintain multiple environment DRY configurations and .ebextensions in one easy to use configuration file.}
13
+ spec.homepage = 'https://github.com/alienfast/elastic-beanstalk'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files`.split($/).reject { |f| f =~ /^samples\// }
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = %w(lib)
20
+
21
+ spec.add_development_dependency 'bundler', '~> 1.3'
22
+ spec.add_development_dependency 'rake'
23
+ spec.add_development_dependency 'rspec', '>= 2.14.1'
24
+
25
+ # spec.add_runtime_dependency
26
+ spec.add_development_dependency 'rails' #, '>=3.2.13'
27
+ spec.add_development_dependency 'eb_deployer'
28
+ spec.add_development_dependency 'awesome_print'
29
+ spec.add_development_dependency 'time_diff'
30
+ spec.add_development_dependency 'zipruby'
31
+ spec.add_development_dependency 'safe_yaml', '0.9.3'
32
+
33
+ end
@@ -0,0 +1,74 @@
1
+ # Slightly modified from https://gist.github.com/morhekil/998709
2
+
3
+ # Symbolizes all of hash's keys and subkeys.
4
+ # Also allows for custom pre-processing of keys (e.g. downcasing, etc)
5
+ # if the block is given:
6
+ #
7
+ # somehash.deep_symbolize { |key| key.downcase }
8
+ #
9
+ # Usage: either include it into global Hash class to make it available to
10
+ # to all hashes, or extend only your own hash objects with this
11
+ # module.
12
+ # E.g.:
13
+ # 1) class Hash; include DeepSymbolizable; end
14
+ # 2) myhash.extend DeepSymbolizable
15
+ module DeepSymbolizable
16
+ def deep_symbolize(invert = false, &block)
17
+ method = self.class.to_s.downcase.to_sym
18
+ symbolizers = DeepSymbolizable::Symbolizers
19
+ symbolizers.respond_to?(method) ? symbolizers.send(method, self, invert, &block) : self
20
+ end
21
+
22
+ module Symbolizers
23
+ extend self
24
+
25
+ # the primary method - symbolizes keys of the given hash,
26
+ # preprocessing them with a block if one was given, and recursively
27
+ # going into all nested enumerables
28
+ def hash(hash, invert, &block)
29
+ hash.inject({}) do |result, (key, value)|
30
+ # Recursively deep-symbolize subhashes
31
+ value = _recurse_(value, invert, &block)
32
+
33
+ # Pre-process the key with a block if it was given
34
+ key = yield key if block_given?
35
+
36
+ if invert
37
+ # UN-Symbolize the key
38
+ s_key = key.to_s rescue key
39
+
40
+ # write it back into the result and return the updated hash
41
+ result[s_key] = value
42
+
43
+ else
44
+ # Symbolize the key string if it responds to to_sym
45
+ sym_key = key.to_sym rescue key
46
+
47
+ # write it back into the result and return the updated hash
48
+ result[sym_key] = value
49
+ end
50
+ result
51
+ end
52
+ end
53
+
54
+ # walking over arrays and symbolizing all nested elements
55
+ def array(ary, invert, &block)
56
+ ary.map { |v| _recurse_(v, invert, &block) }
57
+ end
58
+
59
+ # handling recursion - any Enumerable elements (except String)
60
+ # is being extended with the module, and then symbolized
61
+ def _recurse_(value, invert, &block)
62
+ if value.is_a?(Enumerable) && !value.is_a?(String)
63
+ # support for a use case without extended core Hash
64
+ value.extend DeepSymbolizable unless value.class.include?(DeepSymbolizable)
65
+ value = value.deep_symbolize(invert, &block)
66
+ end
67
+ value
68
+ end
69
+ end
70
+
71
+ end
72
+
73
+ # include in all Hash objects
74
+ class Hash; include DeepSymbolizable; end
@@ -0,0 +1,13 @@
1
+
2
+ module ElasticBeanstalk
3
+ require 'deep_symbolize'
4
+ require 'elastic_beanstalk/eb_config'
5
+ require 'elastic_beanstalk/eb_extensions'
6
+ require 'elastic_beanstalk/eb_smoke_tester'
7
+ require 'elastic_beanstalk/railtie' if defined?(Rails)
8
+ require 'elastic_beanstalk/version'
9
+ end
10
+
11
+ EbConfig = ElasticBeanstalk::EbConfig
12
+ EbExtensions = ElasticBeanstalk::EbExtensions
13
+ EbSmokeTester = ElasticBeanstalk::EbSmokeTester
@@ -0,0 +1,203 @@
1
+ require 'deep_symbolize'
2
+ require 'yaml'
3
+
4
+ module ElasticBeanstalk
5
+ #
6
+ # EbConfig allows for default settings and mounting a specific environment with overriding
7
+ # hash values and merging of array values.
8
+ #
9
+ # NOTE: Anything can be overridden and merged into top-level settings (hashes) including
10
+ # anything that is an array value. Array values are merged *not* replaced. If you think
11
+ # something is screwy, see the defaults in the #init as those add some default array values.
12
+ # If this behavior of merging arrays or the defaults are somehow un-sensible, file an issue and we'll revisit it.
13
+ #
14
+ module EbConfig
15
+ # it's a singleton, thus implemented as a self-extended module
16
+ extend self
17
+
18
+ def init
19
+
20
+ # seed the sensible defaults here
21
+ @configuration = {
22
+ environment: nil,
23
+ disallow_environments: %w(cucumber test),
24
+ strategy: :blue_green,
25
+ package: {
26
+ dir: 'pkg',
27
+ verbose: false,
28
+ includes: %w(**/* .ebextensions/**/*),
29
+ exclude_files: [],
30
+ exclude_dirs: %w(pkg tmp log test-reports)
31
+ },
32
+ options: {}
33
+ }
34
+ end
35
+
36
+ init()
37
+ attr_reader :configuration
38
+
39
+ # This is the main point of entry - we call Settings.load! and provide
40
+ # a name of the file to read as it's argument. We can also pass in some
41
+ # options, but at the moment it's being used to allow per-environment
42
+ # overrides in Rails
43
+ def load!(environment = nil, filename = resolve_path('config/eb.yml'))
44
+
45
+ # merge all top level settings with the defaults set in the #init
46
+ #@configuration.deep_merge!( YAML::load_file(filename).deep_symbolize )
47
+ deep_merge!(@configuration, YAML::load_file(filename).deep_symbolize)
48
+
49
+ # add the environment to the top level settings
50
+ @configuration[:environment] = (environment.nil? ? nil : environment.to_s)
51
+
52
+ # overlay the specific environment if provided
53
+ if environment && @configuration[environment.to_sym]
54
+
55
+ # this is environment specific, so prune any environment
56
+ # based settings from the initial set so that they can be overlaid.
57
+ [:development, :test, :staging, :production].each do |env|
58
+ @configuration.delete(env)
59
+ end
60
+
61
+ # re-read the file
62
+ environment_settings = YAML::load_file(filename).deep_symbolize
63
+
64
+ # snag the requested environment
65
+ environment_settings = environment_settings[environment.to_sym]
66
+
67
+ # finally overlay what was provided
68
+ #@configuration.deep_merge!(environment_settings)
69
+ deep_merge!(@configuration, environment_settings)
70
+ end
71
+
72
+
73
+ #ap @configuration
74
+ #generate_accessors
75
+ end
76
+
77
+ def deep_merge!(target, data)
78
+ merger = proc { |key, v1, v2|
79
+ if (Hash === v1 && Hash === v2)
80
+ v1.merge(v2, &merger)
81
+ elsif (Array === v1 && Array === v2)
82
+ v1.concat(v2)
83
+ else
84
+ v2
85
+ end
86
+ }
87
+ target.merge! data, &merger
88
+ end
89
+
90
+ def reload!(options = {}, filename)
91
+ clear
92
+ #filename.nil? ?
93
+ load!(options) # : load!(options, filename)
94
+ end
95
+
96
+ def to_yaml
97
+
98
+ end
99
+
100
+ def method_missing(name, *args, &block)
101
+ @configuration[name.to_sym] ||
102
+ #fail(NoMethodError, "Unknown settings root \'#{name}\'", caller)
103
+ nil
104
+ end
105
+
106
+ def clear
107
+ init
108
+ end
109
+
110
+ def options
111
+ @configuration[:options] = {} if @configuration[:options].nil?
112
+ @configuration[:options]
113
+ end
114
+
115
+ # custom methods for the specifics of eb.yml settings
116
+ def option_settings
117
+ result = []
118
+ options.each_key do |namespace|
119
+ options[namespace].each do |option_name, value|
120
+ result << to_option_setting(namespace, option_name, value)
121
+ end
122
+ end
123
+
124
+ #{"option_settings" => result}
125
+ result
126
+ end
127
+
128
+ def set_option(namespace, option_name, value)
129
+ namespace = namespace.to_sym
130
+
131
+ if options[namespace].nil?
132
+ options[namespace] = {option_name.to_sym => value}
133
+ else
134
+ options[namespace][option_name.to_sym] = value
135
+ end
136
+
137
+ #puts '888888hello'
138
+ end
139
+
140
+ def find_option_setting(name)
141
+ name = name.to_sym
142
+ options.each_key do |namespace|
143
+ options[namespace].each do |option_name, value|
144
+ if option_name.eql? name
145
+ return to_option_setting(namespace, option_name, value)
146
+ end
147
+ end
148
+ end
149
+ return nil
150
+ end
151
+
152
+ def find_option_setting_value(name)
153
+ o = find_option_setting(name)
154
+ o[:value] unless o.nil?
155
+ end
156
+
157
+ def to_option_setting(namespace, option_name, value)
158
+ {
159
+ :"namespace" => "#{namespace}",
160
+ :"option_name" => "#{option_name}",
161
+ :"value" => "#{value}"
162
+ }
163
+ end
164
+
165
+ def resolve_path(relative_path)
166
+ if defined?(Rails)
167
+
168
+ puts '**********************Using Rails.root'
169
+ Rails.root.join(relative_path)
170
+ elsif defined?(Rake.original_dir)
171
+
172
+ puts '**********************Using Rake.original_dir'
173
+ Rake.original_dir.join(relative_path)
174
+ else
175
+
176
+ puts '**********************Using Last resort Dir.pwd'
177
+ #raise 'I have no idea what the root dir is yet.'
178
+ File.expand_path(relative_path, Dir.pwd)
179
+ end
180
+ end
181
+
182
+
183
+ #def environment
184
+ # @configuration[:environment]
185
+ #end
186
+ #
187
+ #def options
188
+ # @configuration[:options]
189
+ #end
190
+
191
+ private
192
+
193
+ #def generate_accessors
194
+ # # generate a method for accessors
195
+ # @configuration.each do |key, value|
196
+ # define_method(key) do
197
+ # value
198
+ # end unless ['options', 'environment'].include? key
199
+ # end
200
+ #end
201
+ end
202
+
203
+ end