elastic-beanstalk 0.0.1

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/.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