humidifier 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +11 -0
- data/lib/humidifier/aws_adapters/base.rb +10 -8
- data/lib/humidifier/aws_adapters/sdkv1.rb +6 -0
- data/lib/humidifier/aws_adapters/sdkv2.rb +8 -2
- data/lib/humidifier/aws_shim.rb +1 -1
- data/lib/humidifier/configuration.rb +29 -0
- data/lib/humidifier/sdk_payload.rb +66 -1
- data/lib/humidifier/stack.rb +10 -1
- data/lib/humidifier/version.rb +1 -1
- data/lib/humidifier.rb +11 -0
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9de50c50176d088372a188ac60aea7e4087f2389
|
4
|
+
data.tar.gz: f613c462e5ee7ed74403409d7b6b82ff87eb4632
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9c7fcc5768d0f2a7d2cbeefbb3f6a3497a5977542e1990d9d811284b72a5f04d9ffc1bd45c153a4a4dcd4ac6a281c3f5ff3fc46af38bbf006ba75bb59e2c100a
|
7
|
+
data.tar.gz: 586ecf805909463042c9310272bd348a5c8c33273fc5860115151644a2297496e8db7f35489b73c59eb009f0b121a755e0febd0d9f8d037125573d78120d5bd0
|
data/README.md
CHANGED
@@ -59,6 +59,17 @@ Humidifier itself contains a registry of all possible resources that it supports
|
|
59
59
|
|
60
60
|
Resources have an `aws_name` method to see how AWS references them. They also contain a `props` method that contains a hash of the name that Humidifier uses to reference the prop pointing to the appropriate prop object.
|
61
61
|
|
62
|
+
### Large templates
|
63
|
+
|
64
|
+
When templates are especially large (larger than 51,200 bytes), they cannot be uploaded directly through the AWS SDK. You can configure Humidifier to seemlessly upload the templates to S3 and reference them using an S3 URL instead by:
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
Humidifier.configure do |config|
|
68
|
+
config.s3_bucket = 'my.s3.bucket'
|
69
|
+
config.s3_prefix = 'my-prefix/' # optional
|
70
|
+
end
|
71
|
+
```
|
72
|
+
|
62
73
|
## Development
|
63
74
|
|
64
75
|
To get started, ensure you have ruby installed, version 2.0 or later. From there, install the `bundler` gem: `gem install bundler` and then `bundle install` in the root of the repository.
|
@@ -9,8 +9,7 @@ module Humidifier
|
|
9
9
|
# Create a CFN stack
|
10
10
|
def create(payload)
|
11
11
|
try_valid do
|
12
|
-
|
13
|
-
response = client.create_stack(params)
|
12
|
+
response = client.create_stack(payload.create_params)
|
14
13
|
payload.id = response.stack_id
|
15
14
|
response
|
16
15
|
end
|
@@ -18,7 +17,7 @@ module Humidifier
|
|
18
17
|
|
19
18
|
# Delete a CFN stack
|
20
19
|
def delete(payload)
|
21
|
-
client.delete_stack(
|
20
|
+
client.delete_stack(payload.delete_params)
|
22
21
|
true
|
23
22
|
end
|
24
23
|
|
@@ -29,15 +28,18 @@ module Humidifier
|
|
29
28
|
|
30
29
|
# Update a CFN stack
|
31
30
|
def update(payload)
|
32
|
-
try_valid
|
33
|
-
|
34
|
-
|
35
|
-
|
31
|
+
try_valid { client.update_stack(payload.update_params) }
|
32
|
+
end
|
33
|
+
|
34
|
+
# Upload a CFN stack to S3 so that it can be referenced via template_url
|
35
|
+
def upload(payload)
|
36
|
+
Humidifier.config.ensure_upload_configured!(payload)
|
37
|
+
upload_object(payload, "#{Humidifier.config.s3_prefix}#{payload.identifier}.json")
|
36
38
|
end
|
37
39
|
|
38
40
|
# Validate a template in CFN
|
39
41
|
def valid?(payload)
|
40
|
-
try_valid { client.validate_template(
|
42
|
+
try_valid { client.validate_template(payload.validate_params) }
|
41
43
|
end
|
42
44
|
|
43
45
|
%i[create delete deploy update].each do |method|
|
@@ -47,6 +47,12 @@ module Humidifier
|
|
47
47
|
response
|
48
48
|
end
|
49
49
|
|
50
|
+
def upload_object(payload, key)
|
51
|
+
base_module.config(region: AwsShim::REGION)
|
52
|
+
@s3 ||= base_module::S3.new
|
53
|
+
@s3.buckets[Humidifier.config.s3_bucket].objects.create(key, payload.template_body).url_for(:read)
|
54
|
+
end
|
55
|
+
|
50
56
|
def unsupported(method)
|
51
57
|
puts "WARNING: Cannot #{method} because that functionality is not supported in V1 of aws-sdk."
|
52
58
|
false
|
@@ -7,8 +7,7 @@ module Humidifier
|
|
7
7
|
# Create a change set in CFN
|
8
8
|
def create_change_set(payload)
|
9
9
|
payload.merge(change_set_name: "changeset-#{Time.now.strftime('%Y-%m-%d-%H-%M-%S')}")
|
10
|
-
|
11
|
-
try_valid { client.create_change_set(params) }
|
10
|
+
try_valid { client.create_change_set(payload.create_change_set_params) }
|
12
11
|
end
|
13
12
|
|
14
13
|
# Create a change set if the stack exists, otherwise create the stack
|
@@ -38,6 +37,13 @@ module Humidifier
|
|
38
37
|
|
39
38
|
response
|
40
39
|
end
|
40
|
+
|
41
|
+
def upload_object(payload, key)
|
42
|
+
base_module.config.update(region: AwsShim::REGION)
|
43
|
+
@s3_client ||= base_module::S3::Client.new
|
44
|
+
@s3_client.put_object(body: payload.template_body, bucket: Humidifier.config.s3_bucket, key: key)
|
45
|
+
base_module::S3::Object.new(Humidifier.config.s3_bucket, key).presigned_url(:get)
|
46
|
+
end
|
41
47
|
end
|
42
48
|
end
|
43
49
|
end
|
data/lib/humidifier/aws_shim.rb
CHANGED
@@ -13,7 +13,7 @@ module Humidifier
|
|
13
13
|
|
14
14
|
# Methods that are sent over to the aws adapter from the stack
|
15
15
|
STACK_METHODS = %i[
|
16
|
-
create delete deploy exists? update valid?
|
16
|
+
create delete deploy exists? update upload valid?
|
17
17
|
create_and_wait delete_and_wait deploy_and_wait update_and_wait
|
18
18
|
create_change_set deploy_change_set
|
19
19
|
].freeze
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Humidifier
|
2
|
+
|
3
|
+
# a container for user params
|
4
|
+
class Configuration
|
5
|
+
|
6
|
+
UPLOAD_MESSAGE = <<-MSG.freeze
|
7
|
+
The %{identifier} stack's body is too large to be use the template_body option, and therefore must use the
|
8
|
+
template_url option instead. You can configure Humidifier to do this automatically by setting up the s3 config
|
9
|
+
on the top-level Humidifier object like so:
|
10
|
+
|
11
|
+
Humidifier.configure do |config|
|
12
|
+
config.s3_bucket = 'my.s3.bucket'
|
13
|
+
config.s3_prefix = 'my-prefix/' # optional
|
14
|
+
end
|
15
|
+
MSG
|
16
|
+
|
17
|
+
attr_accessor :s3_bucket, :s3_prefix
|
18
|
+
|
19
|
+
def initialize(opts = {})
|
20
|
+
self.s3_bucket = opts[:s3_bucket]
|
21
|
+
self.s3_prefix = opts[:s3_prefix]
|
22
|
+
end
|
23
|
+
|
24
|
+
# raise an error unless the s3_bucket field is set
|
25
|
+
def ensure_upload_configured!(payload)
|
26
|
+
raise UPLOAD_MESSAGE.gsub('%{identifier}', payload.identifier) if s3_bucket.nil?
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -3,13 +3,30 @@ module Humidifier
|
|
3
3
|
# The payload sent to the shim methods, representing the stack and the options
|
4
4
|
class SdkPayload
|
5
5
|
|
6
|
+
# The maximum size a template body can be before it has to be put somewhere and referenced through a URL
|
7
|
+
MAX_TEMPLATE_BODY_SIZE = 51_200
|
8
|
+
|
9
|
+
# The maximum size a template body can be inside of an S3 bucket
|
10
|
+
MAX_TEMPLATE_URL_SIZE = 460_800
|
11
|
+
|
6
12
|
# The maximum amount of time that Humidifier should wait for a stack to complete a CRUD operation
|
7
13
|
MAX_WAIT = 600
|
8
14
|
|
15
|
+
# Thrown when a template is too large to use the template_url option
|
16
|
+
class TemplateTooLargeError < StandardError
|
17
|
+
def initialize(bytesize)
|
18
|
+
message = <<-MSG
|
19
|
+
Cannot use a template > #{MAX_TEMPLATE_URL_SIZE} bytes (currently #{bytesize} bytes), consider using nested stacks
|
20
|
+
(http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-stack.html)
|
21
|
+
MSG
|
22
|
+
super(message)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
9
26
|
attr_accessor :stack, :options, :max_wait
|
10
27
|
|
11
28
|
extend Forwardable
|
12
|
-
def_delegators :stack, :id=, :identifier, :name
|
29
|
+
def_delegators :stack, :id=, :identifier, :name
|
13
30
|
|
14
31
|
def initialize(stack, options)
|
15
32
|
self.stack = stack
|
@@ -26,5 +43,53 @@ module Humidifier
|
|
26
43
|
def merge(new_options)
|
27
44
|
self.options = new_options.merge(options)
|
28
45
|
end
|
46
|
+
|
47
|
+
# The body of the template
|
48
|
+
def template_body
|
49
|
+
@template_body ||= stack.to_cf
|
50
|
+
end
|
51
|
+
|
52
|
+
###
|
53
|
+
# Param sets
|
54
|
+
###
|
55
|
+
|
56
|
+
# Param set for the #create_change_set SDK method
|
57
|
+
def create_change_set_params
|
58
|
+
{ stack_name: stack.identifier }.merge(template_param).merge(options)
|
59
|
+
end
|
60
|
+
|
61
|
+
# Param set for the #create_stack SDK method
|
62
|
+
def create_params
|
63
|
+
{ stack_name: stack.name }.merge(template_param).merge(options)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Param set for the #delete_stack SDK method
|
67
|
+
def delete_params
|
68
|
+
{ stack_name: stack.identifier }.merge(options)
|
69
|
+
end
|
70
|
+
|
71
|
+
# Param set for the #update_stack SDK method
|
72
|
+
def update_params
|
73
|
+
{ stack_name: stack.identifier }.merge(template_param).merge(options)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Param set for the #validate_template SDK method
|
77
|
+
def validate_params
|
78
|
+
template_param.merge(options)
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def template_param
|
84
|
+
@template_param ||= begin
|
85
|
+
raise TemplateTooLargeError, template_body.bytesize if template_body.bytesize > MAX_TEMPLATE_URL_SIZE
|
86
|
+
|
87
|
+
if template_body.bytesize > MAX_TEMPLATE_BODY_SIZE
|
88
|
+
{ template_url: AwsShim.upload(self) }
|
89
|
+
else
|
90
|
+
{ template_body: template_body }
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
29
94
|
end
|
30
95
|
end
|
data/lib/humidifier/stack.rb
CHANGED
@@ -14,6 +14,7 @@ module Humidifier
|
|
14
14
|
def initialize(opts = {})
|
15
15
|
self.name = opts[:name]
|
16
16
|
self.id = opts[:id]
|
17
|
+
self.default_identifier = self.class.next_default_identifier
|
17
18
|
|
18
19
|
ENUMERABLE_RESOURCES.values.each { |prop| send(:"#{prop}=", opts.fetch(prop, {})) }
|
19
20
|
STATIC_RESOURCES.values.each { |prop| send(:"#{prop}=", opts[prop]) }
|
@@ -28,7 +29,7 @@ module Humidifier
|
|
28
29
|
|
29
30
|
# The identifier used by the shim to find the stack in CFN, prefers id to name
|
30
31
|
def identifier
|
31
|
-
id || name
|
32
|
+
id || name || default_identifier
|
32
33
|
end
|
33
34
|
|
34
35
|
# A string representation of the stack that's valid for CFN
|
@@ -46,8 +47,16 @@ module Humidifier
|
|
46
47
|
define_method(method) { |opts = {}| AwsShim.send(method, SdkPayload.new(self, opts)) }
|
47
48
|
end
|
48
49
|
|
50
|
+
# Increment the default identifier
|
51
|
+
def self.next_default_identifier
|
52
|
+
@count = (@count || 0) + 1
|
53
|
+
"humidifier-stack-template-#{@count}"
|
54
|
+
end
|
55
|
+
|
49
56
|
private
|
50
57
|
|
58
|
+
attr_accessor :default_identifier
|
59
|
+
|
51
60
|
def enumerable_resources
|
52
61
|
ENUMERABLE_RESOURCES.each_with_object({}) do |(name, prop), list|
|
53
62
|
resources = send(prop)
|
data/lib/humidifier/version.rb
CHANGED
data/lib/humidifier.rb
CHANGED
@@ -11,6 +11,7 @@ require 'humidifier/props'
|
|
11
11
|
|
12
12
|
require 'humidifier/aws_shim'
|
13
13
|
require 'humidifier/condition'
|
14
|
+
require 'humidifier/configuration'
|
14
15
|
require 'humidifier/loader'
|
15
16
|
require 'humidifier/mapping'
|
16
17
|
require 'humidifier/output'
|
@@ -25,6 +26,16 @@ require 'humidifier/version'
|
|
25
26
|
# container module for all gem classes
|
26
27
|
module Humidifier
|
27
28
|
class << self
|
29
|
+
# the configuration instance
|
30
|
+
def config
|
31
|
+
@config ||= Configuration.new
|
32
|
+
end
|
33
|
+
|
34
|
+
# yield the config object to the block for setting user params
|
35
|
+
def configure
|
36
|
+
yield config
|
37
|
+
end
|
38
|
+
|
28
39
|
# convenience method for calling cloudformation functions
|
29
40
|
def fn
|
30
41
|
Fn
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: humidifier
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Localytics
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-07-
|
11
|
+
date: 2016-07-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -44,14 +44,14 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '5.
|
47
|
+
version: '5.9'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '5.
|
54
|
+
version: '5.9'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: nokogiri
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -157,6 +157,7 @@ files:
|
|
157
157
|
- lib/humidifier/aws_adapters/sdkv2.rb
|
158
158
|
- lib/humidifier/aws_shim.rb
|
159
159
|
- lib/humidifier/condition.rb
|
160
|
+
- lib/humidifier/configuration.rb
|
160
161
|
- lib/humidifier/fn.rb
|
161
162
|
- lib/humidifier/humidifier.bundle
|
162
163
|
- lib/humidifier/loader.rb
|