humidifier-reservoir 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -0,0 +1,3 @@
1
+ service_name: travis-pro
2
+ repo_token: nVKTWyGZRLnQ8DTbx4hEyDsDdBGdetck7
3
+
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
@@ -0,0 +1,14 @@
1
+ AllCops:
2
+ DisplayCopNames: true
3
+ DisplayStyleGuide: true
4
+ TargetRubyVersion: 2.0
5
+ Exclude:
6
+ - 'vendor/**/*'
7
+
8
+ Metrics/LineLength:
9
+ Max: 100
10
+
11
+ Style/PercentLiteralDelimiters:
12
+ PreferredDelimiters:
13
+ '%i': '[]'
14
+ '%w': '[]'
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm: 2.3.1
3
+ cache: bundler
4
+ script:
5
+ - bundle exec rake
6
+ - bundle exec rubocop
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
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.
@@ -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).
@@ -0,0 +1,10 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << 'test'
6
+ t.libs << 'lib'
7
+ t.test_files = FileList['test/**/*_test.rb']
8
+ end
9
+
10
+ task default: :test
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'humidifier/reservoir'
5
+
6
+ require 'irb'
7
+ IRB.start
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -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,8 @@
1
+ module Humidifier
2
+ module Reservoir
3
+ # A parent class for all Reservoir-related errors for easier rescuing in the
4
+ # CLI.
5
+ class Error < StandardError
6
+ end
7
+ end
8
+ 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
@@ -0,0 +1,6 @@
1
+ module Humidifier
2
+ module Reservoir
3
+ # The current version.
4
+ VERSION = '0.0.1'.freeze
5
+ end
6
+ 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: []