humidifier-reservoir 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/.coveralls.yml +3 -0
- data/.gitignore +9 -0
- data/.rubocop.yml +14 -0
- data/.travis.yml +6 -0
- data/Gemfile +3 -0
- data/LICENSE +21 -0
- data/README.md +127 -0
- data/Rakefile +10 -0
- data/bin/console +7 -0
- data/bin/setup +8 -0
- data/humidifier-reservoir.gemspec +39 -0
- data/lib/humidifier/reservoir.rb +44 -0
- data/lib/humidifier/reservoir/base_mapper.rb +67 -0
- data/lib/humidifier/reservoir/cli.rb +54 -0
- data/lib/humidifier/reservoir/config.rb +37 -0
- data/lib/humidifier/reservoir/error.rb +8 -0
- data/lib/humidifier/reservoir/mapping.rb +21 -0
- data/lib/humidifier/reservoir/stack.rb +72 -0
- data/lib/humidifier/reservoir/version.rb +6 -0
- metadata +206 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c5f85405b3ffe729d470851826a69df6b15d44f2
|
4
|
+
data.tar.gz: c6e4936a707be0f47cc9d7c27eedebc71737fcae
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fef30451ce5594b6c710a5c157284718b87beba2c9553e9086c1c538fbff0aab9ac4495a740d125b1bee77b36b2cc9c6190c7d83e76568bdadbd68db26d8b8d4
|
7
|
+
data.tar.gz: 9ca01c48c83975c056cd9a9bdb8d04e831fde8a31adf3b5b788b9a2cb43f5e4b9339ef549f3202ddd0814f0d21cb3ac748d4e073e4ed86c594cdba5f3aa2581e
|
data/.coveralls.yml
ADDED
data/.gitignore
ADDED
data/.rubocop.yml
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2016 Localytics http://www.localytics.com
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
# Humidifier::Reservoir
|
2
|
+
|
3
|
+
[![Build Status](https://travis-ci.org/localytics/humidifier-reservoir.svg?branch=master)](https://travis-ci.org/localytics/humidifier-reservoir)
|
4
|
+
[![Coverage Status](https://coveralls.io/repos/github/localytics/humidifier-reservoir/badge.svg?branch=master&t=GKTl7x)](https://coveralls.io/github/localytics/humidifier-reservoir?branch=master)
|
5
|
+
|
6
|
+
`Reservoir` is a plugin for the [`humidifier`](https://github.com/localytics/humidifier) gem that allows you to specify CloudFormation resources in [yaml](http://yaml.org/) syntax, while still allowing you to take advantage of the flexibility of `humidifier`.
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
Add this line to your application's Gemfile:
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
gem 'humidifier-reservoir'
|
14
|
+
```
|
15
|
+
|
16
|
+
And then execute:
|
17
|
+
|
18
|
+
$ bundle
|
19
|
+
|
20
|
+
Or install it yourself as:
|
21
|
+
|
22
|
+
$ gem install humidifier-reservoir
|
23
|
+
|
24
|
+
## Usage
|
25
|
+
|
26
|
+
### CLI
|
27
|
+
|
28
|
+
`Reservoir` is meant to be run as a CLI tool. First, build a ruby script that executes the `Humidifier::Reservoir::CLI` class, like so:
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
#!/usr/bin/env ruby
|
32
|
+
require 'humidifier/reservoir'
|
33
|
+
|
34
|
+
Humidifier::Reservoir.configure do |config|
|
35
|
+
config.stack_path = 'stacks'
|
36
|
+
config.stack_prefix = 'reservoir-'
|
37
|
+
|
38
|
+
config.map :users, to: 'AWS::IAM::User'
|
39
|
+
end
|
40
|
+
|
41
|
+
Humidifier::Reservoir::CLI.start(ARGV)
|
42
|
+
```
|
43
|
+
|
44
|
+
This configuration specifies that the directories containing the specifications for each stack are contained under a "stacks" directory, the stack names should be prefixed with a "reservoir-" signifier, and that `users.yml` files should map to IAM users.
|
45
|
+
|
46
|
+
### Resource files
|
47
|
+
|
48
|
+
Inside of the above-configured `stacks` directory, create a subdirectory for each CloudFormation stack that you wish to manage in code. With the above configuration, we can create YAML files in the form of `users.yml` for each stack, which will specify IAM users to create. The file format looks like the below:
|
49
|
+
|
50
|
+
```yaml
|
51
|
+
EngUser:
|
52
|
+
path: /reservoir/
|
53
|
+
user_name: EngUser
|
54
|
+
groups:
|
55
|
+
- Engineering
|
56
|
+
- Testing
|
57
|
+
- Deployment
|
58
|
+
|
59
|
+
AdminUser:
|
60
|
+
path: /reservoir/
|
61
|
+
user_name: AdminUser
|
62
|
+
groups:
|
63
|
+
- Management
|
64
|
+
- Administration
|
65
|
+
```
|
66
|
+
|
67
|
+
The top-level keys are the logical resource names that will be displayed in the CloudFormation screen. They point to a map of key/value pairs that will be passed on to `humidifier`. Any `humidifier` (and therefore any CloudFormation) attribute may be specified. For more information on CloudFormation templates and which attributes may be specified, see both the [`humidifier` docs](http://localytics.github.io/humidifier) and the [CloudFormation docs](http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-guide.html).
|
68
|
+
|
69
|
+
### Mappers
|
70
|
+
|
71
|
+
Oftentimes, specifying these attributes can become repetitive, e.g., each user should automatically receive the same "path" attribute. Other times, you may want custom logic to execute depending on which AWS environment you're running in. Finally, you may want to reference resources in the same or other stacks.
|
72
|
+
|
73
|
+
`Reservoir`'s solution for this is to allow customized "mapper" classes to take the user-provided attributes and transform them into the attributes that CloudFormation expects. Consider the following example for mapping a user:
|
74
|
+
|
75
|
+
```ruby
|
76
|
+
class UserMapper < Humidifier::Reservoir::BaseMapper
|
77
|
+
GROUPS = {
|
78
|
+
'eng' => %w[Engineering Testing Deployment],
|
79
|
+
'admin' => %w[Management Administration]
|
80
|
+
}
|
81
|
+
|
82
|
+
defaults do |logical_name|
|
83
|
+
{ path: '/reservoir/', user_name: logical_name }
|
84
|
+
end
|
85
|
+
|
86
|
+
attribute :group do |group|
|
87
|
+
groups = GROUPS[group]
|
88
|
+
groups.any? ? { groups: GROUPS[group] } : {}
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
Humidifier::Reservoir.configure do |config|
|
93
|
+
config.map :users, to: 'AWS::IAM::User', using: UserMapper
|
94
|
+
end
|
95
|
+
```
|
96
|
+
|
97
|
+
This means that by default, all entries in the `users.yml` files will get a `/reservoir/` path, the `user_name` attribute will be set based on the logical name that was provided for the resource, and you can additionally specify a `group` attribute, even though it is not native to CloudFormation. With this `group` attribute, it will actually map to the `groups` attribute that CloudFormation expects.
|
98
|
+
|
99
|
+
With this new mapper in place, we can simplify our YAML file to:
|
100
|
+
|
101
|
+
```yaml
|
102
|
+
EngUser:
|
103
|
+
group: eng
|
104
|
+
|
105
|
+
AdminUser:
|
106
|
+
group: admin
|
107
|
+
```
|
108
|
+
|
109
|
+
### Deployment
|
110
|
+
|
111
|
+
Now that you've configured your CLI, your resources, and your mappers, you can use the CLI to display, validate, and deploy your infrastructure to CloudFormation. Run your script without any arguments to get the help message and explanations for each command.
|
112
|
+
|
113
|
+
Each command has an `--aws-profile` (or `-p`) option for specifying which profile to authenticate against when querying AWS. You should ensure that this profile has the correct permissions for creating whatever resources are going to part of your stack. You can also rely on the `AWS_*` environment variables, or the EC2 instance profile if you're deploying from an instance. For more information, see the [AWS docs](http://docs.aws.amazon.com/sdkforruby/api/) under the "Configuration" section.
|
114
|
+
|
115
|
+
## Development
|
116
|
+
|
117
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
118
|
+
|
119
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
120
|
+
|
121
|
+
## Contributing
|
122
|
+
|
123
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/localytics/humidifier-reservoir.
|
124
|
+
|
125
|
+
## License
|
126
|
+
|
127
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/bin/console
ADDED
data/bin/setup
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'humidifier/reservoir/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec| # rubocop:disable Metrics/BlockLength
|
7
|
+
spec.name = 'humidifier-reservoir'
|
8
|
+
spec.version = Humidifier::Reservoir::VERSION
|
9
|
+
spec.authors = ['Localytics']
|
10
|
+
spec.email = ['oss@localytics.com']
|
11
|
+
|
12
|
+
spec.summary = 'Specify CloudFormation resources in YAML'
|
13
|
+
spec.description = <<-DESC
|
14
|
+
Reservoir is a plugin for the humidifier gem that allows you to specify
|
15
|
+
CloudFormation resources in yaml syntax, while still allowing you to take
|
16
|
+
advantage of the flexibility of humidifier.
|
17
|
+
DESC
|
18
|
+
spec.homepage = 'https://github.com/localytics/humidifier-reservoir'
|
19
|
+
spec.license = 'MIT'
|
20
|
+
|
21
|
+
files = `git ls-files -z`.split("\x0")
|
22
|
+
spec.files = files.reject { |f| f.match(%r{^(test|spec|features)/}) }
|
23
|
+
|
24
|
+
spec.bindir = 'exe'
|
25
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
26
|
+
spec.require_paths = ['lib']
|
27
|
+
|
28
|
+
spec.add_dependency 'aws-sdk', '~> 2.6'
|
29
|
+
spec.add_dependency 'humidifier', '~> 1.0'
|
30
|
+
spec.add_dependency 'thor', '~> 0.19'
|
31
|
+
spec.add_dependency 'thor-hollaback', '~> 0.1.0'
|
32
|
+
|
33
|
+
spec.add_development_dependency 'bundler', '~> 1.13'
|
34
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
35
|
+
spec.add_development_dependency 'minitest', '~> 5.0'
|
36
|
+
spec.add_development_dependency 'simplecov', '~> 0.11'
|
37
|
+
spec.add_development_dependency 'coveralls', '~> 0.8'
|
38
|
+
spec.add_development_dependency 'rubocop', '~> 0.39'
|
39
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'aws-sdk'
|
2
|
+
require 'humidifier'
|
3
|
+
require 'thor'
|
4
|
+
require 'thor/hollaback'
|
5
|
+
require 'yaml'
|
6
|
+
|
7
|
+
require 'humidifier/reservoir/base_mapper'
|
8
|
+
require 'humidifier/reservoir/cli'
|
9
|
+
require 'humidifier/reservoir/config'
|
10
|
+
require 'humidifier/reservoir/error'
|
11
|
+
require 'humidifier/reservoir/mapping'
|
12
|
+
require 'humidifier/reservoir/stack'
|
13
|
+
require 'humidifier/reservoir/version'
|
14
|
+
|
15
|
+
module Humidifier
|
16
|
+
# The parent module for Reservoir-related constants.
|
17
|
+
module Reservoir
|
18
|
+
class << self
|
19
|
+
def config
|
20
|
+
@config ||= Config.new
|
21
|
+
end
|
22
|
+
|
23
|
+
def configure
|
24
|
+
yield config
|
25
|
+
end
|
26
|
+
|
27
|
+
def files_for(name)
|
28
|
+
config.files_for(name)
|
29
|
+
end
|
30
|
+
|
31
|
+
def mapping_for(type)
|
32
|
+
config.mapping_for(type)
|
33
|
+
end
|
34
|
+
|
35
|
+
def stack_prefix
|
36
|
+
config.stack_prefix
|
37
|
+
end
|
38
|
+
|
39
|
+
def stacks
|
40
|
+
config.stacks
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Humidifier
|
2
|
+
module Reservoir
|
3
|
+
# The parent class for mapper classes. These classes are used to transform
|
4
|
+
# arbitrary attributes coming from the user-provided YAML files into valid
|
5
|
+
# CloudFormation attributes that can then be used in the template. This
|
6
|
+
# class provides an easy-to-extend DSL that allows for default attributes
|
7
|
+
# specifying custom attributes.
|
8
|
+
class BaseMapper
|
9
|
+
class << self
|
10
|
+
# Defines a custom attribute. The given block will receive the
|
11
|
+
# user-provided value for the attribute. The block should return a hash
|
12
|
+
# where the keys are valid humidifier properties and the values are
|
13
|
+
# valid values for those properties. In the below example, we specify
|
14
|
+
# the group attribute which maps to the groups attribute after some
|
15
|
+
# transformation.
|
16
|
+
#
|
17
|
+
# attribute :group do |group|
|
18
|
+
# groups = GROUPS[group]
|
19
|
+
# groups.any? ? { groups: GROUPS[group] } : {}
|
20
|
+
# end
|
21
|
+
def attribute(name, &block)
|
22
|
+
define_method(:"attribute_#{name}", &block)
|
23
|
+
attribute_methods << name
|
24
|
+
end
|
25
|
+
|
26
|
+
# The names of the custom attribute methods.
|
27
|
+
def attribute_methods
|
28
|
+
@attribute_methods ||= []
|
29
|
+
end
|
30
|
+
|
31
|
+
# Defines the default attributes that should be applied to all resources
|
32
|
+
# of this type. The given block will be passed the logical resource
|
33
|
+
# name that the user specified for the resource. The block should return
|
34
|
+
# a hash where the keys are valid humidifier properties and the values
|
35
|
+
# are valid values for those properties. In the example below, the
|
36
|
+
# user_name property is set based on the logical name.
|
37
|
+
#
|
38
|
+
# defaults do |name|
|
39
|
+
# { user_name: name }
|
40
|
+
# end
|
41
|
+
def defaults(&block)
|
42
|
+
define_method(:attribute_defaults, &block)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Builds a humidifier resource using the given humidifier resource class,
|
47
|
+
# the logical name for the resource, and the user-specified attributes.
|
48
|
+
def resource_for(clazz, name, attributes)
|
49
|
+
mapped = respond_to?(:attribute_defaults) ? attribute_defaults(name) : {}
|
50
|
+
attributes.each { |key, value| mapped.merge!(mapped_from(clazz, key, value)) }
|
51
|
+
clazz.new(mapped)
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def mapped_from(clazz, key, value)
|
57
|
+
if self.class.attribute_methods.include?(key.to_sym)
|
58
|
+
public_send(:"attribute_#{key}", value)
|
59
|
+
elsif clazz.prop?(key)
|
60
|
+
{ key.to_sym => value }
|
61
|
+
else
|
62
|
+
raise Error, "Invalid attribute: #{key}"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Humidifier
|
2
|
+
module Reservoir
|
3
|
+
# A CLI for running commands to manipulate the stacks that Reservoir knows
|
4
|
+
# about.
|
5
|
+
class CLI < Thor
|
6
|
+
class_option :aws_profile, desc: 'The AWS profile to authenticate with', aliases: ['-p']
|
7
|
+
|
8
|
+
class_option :debug, desc: 'Sets up debug mode', aliases: ['-d']
|
9
|
+
class_around :safe_execute
|
10
|
+
|
11
|
+
desc 'deploy [?stack]', 'Update one or all stacks'
|
12
|
+
option :wait, desc: 'Wait for the stack to create/update', type: :boolean, default: false
|
13
|
+
def deploy(name = nil)
|
14
|
+
stack_names = name ? [name] : Reservoir.stacks
|
15
|
+
authorize
|
16
|
+
|
17
|
+
stack_names.each do |stack_name|
|
18
|
+
stack = Stack.new(stack_name)
|
19
|
+
puts "Deploying #{stack.stack_name}"
|
20
|
+
stack.deploy(options[:wait])
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
desc 'display [stack] [?pattern]', 'Display the CloudFormation JSON for a given stack'
|
25
|
+
def display(name, pattern = nil)
|
26
|
+
puts Stack.new(name, pattern && /#{pattern}/i).to_cf
|
27
|
+
end
|
28
|
+
|
29
|
+
desc 'validate [?stack]', 'Validate that one or all stacks are valid with CloudFormation'
|
30
|
+
def validate(name = nil)
|
31
|
+
stack_names = name ? [name] : Reservoir.stacks
|
32
|
+
authorize
|
33
|
+
|
34
|
+
print 'Validating... '
|
35
|
+
puts 'Valid.' if stack_names.all? { |stack_name| Stack.new(stack_name).valid? }
|
36
|
+
end
|
37
|
+
|
38
|
+
no_commands do
|
39
|
+
def authorize
|
40
|
+
return unless options[:aws_profile]
|
41
|
+
Aws.config[:credentials] = Aws::SharedCredentials.new(profile_name: options[:aws_profile])
|
42
|
+
end
|
43
|
+
|
44
|
+
def safe_execute
|
45
|
+
yield
|
46
|
+
rescue Error => error
|
47
|
+
raise error if options[:debug]
|
48
|
+
puts error.message
|
49
|
+
exit 1
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Humidifier
|
2
|
+
module Reservoir
|
3
|
+
# A container class for the user-specified Reservoir configuration.
|
4
|
+
class Config
|
5
|
+
attr_reader :mappings, :stack_path
|
6
|
+
attr_accessor :stack_prefix
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@mappings = {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def files_for(name)
|
13
|
+
raise Error, 'You must configure a stack path' if stack_path.nil?
|
14
|
+
Dir["#{stack_path}/#{name}/*.yml"]
|
15
|
+
end
|
16
|
+
|
17
|
+
def map(type, opts = {})
|
18
|
+
mappings[type.to_sym] = Mapping.new(opts)
|
19
|
+
end
|
20
|
+
|
21
|
+
def mapping_for(type)
|
22
|
+
mappings[type.to_sym]
|
23
|
+
end
|
24
|
+
|
25
|
+
def stack_path=(stack_path)
|
26
|
+
raise Error, "Invalid filepath: #{stack_path}" unless File.exist?(stack_path)
|
27
|
+
@stack_path = stack_path
|
28
|
+
end
|
29
|
+
|
30
|
+
def stacks
|
31
|
+
Dir["#{stack_path}/*"].each_with_object([]) do |name, names|
|
32
|
+
names << File.basename(name) if File.directory?(name)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Humidifier
|
2
|
+
module Reservoir
|
3
|
+
# Contains the configuration for a mapping between a YAML file name and an
|
4
|
+
# AWS resource. May optionally contain a Mapper (uses the BaseMapper) by
|
5
|
+
# default.
|
6
|
+
class Mapping
|
7
|
+
attr_reader :clazz, :mapper
|
8
|
+
|
9
|
+
def initialize(opts = {})
|
10
|
+
@clazz = Humidifier[opts[:to]]
|
11
|
+
raise Error, "Invalid resource: #{opts[:to].inspect}" if @clazz.nil?
|
12
|
+
|
13
|
+
@mapper = opts.fetch(:using, BaseMapper).new
|
14
|
+
end
|
15
|
+
|
16
|
+
def resource_for(name, attributes)
|
17
|
+
mapper.resource_for(clazz, name, attributes)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Humidifier
|
2
|
+
module Reservoir
|
3
|
+
# Represents a CloudFormation stack. This contains all of the logic for
|
4
|
+
# interfacing with humidifier to deploy stacks, validate them, and display
|
5
|
+
# them.
|
6
|
+
class Stack
|
7
|
+
attr_reader :name, :pattern
|
8
|
+
|
9
|
+
def initialize(name, pattern = nil)
|
10
|
+
@name = name
|
11
|
+
@pattern = pattern
|
12
|
+
end
|
13
|
+
|
14
|
+
def deploy(wait = false)
|
15
|
+
if humidifier_stack.resources.empty?
|
16
|
+
puts "Refusing to deploy stack #{humidifier_stack.name} with no resources"
|
17
|
+
return
|
18
|
+
end
|
19
|
+
valid?
|
20
|
+
|
21
|
+
opts = { capabilities: %w[CAPABILITY_IAM CAPABILITY_NAMED_IAM] }
|
22
|
+
wait ? humidifier_stack.deploy_and_wait(opts) : humidifier_stack.deploy(opts)
|
23
|
+
end
|
24
|
+
|
25
|
+
def resources
|
26
|
+
Reservoir.files_for(name).each_with_object({}) do |filepath, resources|
|
27
|
+
resources.merge!(parse(filepath, File.basename(filepath, '.yml')))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def stack_name
|
32
|
+
@stack_name ||= "#{Reservoir.stack_prefix}#{name}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_cf
|
36
|
+
humidifier_stack.to_cf
|
37
|
+
end
|
38
|
+
|
39
|
+
def valid?
|
40
|
+
humidifier_stack.valid?
|
41
|
+
rescue Aws::CloudFormation::Errors::AccessDenied
|
42
|
+
raise Error, <<-MSG
|
43
|
+
The authenticated AWS profile does not have the requisite permissions to run
|
44
|
+
this command. Ensure the profile has cloudformation:ValidateTemplate.
|
45
|
+
MSG
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def humidifier_stack
|
51
|
+
Humidifier::Stack.new(
|
52
|
+
name: stack_name,
|
53
|
+
description: "Resources for #{stack_name}",
|
54
|
+
resources: resources
|
55
|
+
)
|
56
|
+
end
|
57
|
+
|
58
|
+
def parse(filepath, type)
|
59
|
+
mapping = Reservoir.mapping_for(type)
|
60
|
+
return {} if mapping.nil?
|
61
|
+
|
62
|
+
loaded = YAML.load_file(filepath)
|
63
|
+
return {} unless loaded
|
64
|
+
|
65
|
+
loaded.each_with_object({}) do |(name, attributes), resources|
|
66
|
+
next if pattern && name !~ pattern
|
67
|
+
resources[name] = mapping.resource_for(name, attributes)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
metadata
ADDED
@@ -0,0 +1,206 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: humidifier-reservoir
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Localytics
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-03-16 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: aws-sdk
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.6'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: humidifier
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: thor
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.19'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.19'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: thor-hollaback
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.1.0
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.1.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: bundler
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.13'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.13'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '10.0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '10.0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: minitest
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '5.0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '5.0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: simplecov
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0.11'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0.11'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: coveralls
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0.8'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0.8'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: rubocop
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0.39'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0.39'
|
153
|
+
description: |2
|
154
|
+
Reservoir is a plugin for the humidifier gem that allows you to specify
|
155
|
+
CloudFormation resources in yaml syntax, while still allowing you to take
|
156
|
+
advantage of the flexibility of humidifier.
|
157
|
+
email:
|
158
|
+
- oss@localytics.com
|
159
|
+
executables: []
|
160
|
+
extensions: []
|
161
|
+
extra_rdoc_files: []
|
162
|
+
files:
|
163
|
+
- ".coveralls.yml"
|
164
|
+
- ".gitignore"
|
165
|
+
- ".rubocop.yml"
|
166
|
+
- ".travis.yml"
|
167
|
+
- Gemfile
|
168
|
+
- LICENSE
|
169
|
+
- README.md
|
170
|
+
- Rakefile
|
171
|
+
- bin/console
|
172
|
+
- bin/setup
|
173
|
+
- humidifier-reservoir.gemspec
|
174
|
+
- lib/humidifier/reservoir.rb
|
175
|
+
- lib/humidifier/reservoir/base_mapper.rb
|
176
|
+
- lib/humidifier/reservoir/cli.rb
|
177
|
+
- lib/humidifier/reservoir/config.rb
|
178
|
+
- lib/humidifier/reservoir/error.rb
|
179
|
+
- lib/humidifier/reservoir/mapping.rb
|
180
|
+
- lib/humidifier/reservoir/stack.rb
|
181
|
+
- lib/humidifier/reservoir/version.rb
|
182
|
+
homepage: https://github.com/localytics/humidifier-reservoir
|
183
|
+
licenses:
|
184
|
+
- MIT
|
185
|
+
metadata: {}
|
186
|
+
post_install_message:
|
187
|
+
rdoc_options: []
|
188
|
+
require_paths:
|
189
|
+
- lib
|
190
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - ">="
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '0'
|
195
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
196
|
+
requirements:
|
197
|
+
- - ">="
|
198
|
+
- !ruby/object:Gem::Version
|
199
|
+
version: '0'
|
200
|
+
requirements: []
|
201
|
+
rubyforge_project:
|
202
|
+
rubygems_version: 2.6.8
|
203
|
+
signing_key:
|
204
|
+
specification_version: 4
|
205
|
+
summary: Specify CloudFormation resources in YAML
|
206
|
+
test_files: []
|