ec2 0.0.4
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.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +31 -0
- data/Rakefile +2 -0
- data/bin/ec2 +72 -0
- data/dev_bin/ec2 +4 -0
- data/ec2.gemspec +24 -0
- data/examples/profiles.rb +10 -0
- data/examples/templates.rb +10 -0
- data/examples/test.rb +18 -0
- data/lib/ec2/cli/hosts.rb +51 -0
- data/lib/ec2/cli/resources.rb +56 -0
- data/lib/ec2/config.rb +58 -0
- data/lib/ec2/custom_logger.rb +34 -0
- data/lib/ec2/erb_profile.rb +30 -0
- data/lib/ec2/error.rb +4 -0
- data/lib/ec2/ext/string.rb +33 -0
- data/lib/ec2/helper.rb +9 -0
- data/lib/ec2/lock.rb +19 -0
- data/lib/ec2/logger.rb +27 -0
- data/lib/ec2/profile.rb +92 -0
- data/lib/ec2/profile_dsl.rb +96 -0
- data/lib/ec2/query_api.rb +35 -0
- data/lib/ec2/resources.rb +30 -0
- data/lib/ec2/salt_cloud.rb +112 -0
- data/lib/ec2/security_group.rb +196 -0
- data/lib/ec2/subnet.rb +105 -0
- data/lib/ec2/version.rb +3 -0
- data/lib/ec2.rb +5 -0
- metadata +117 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 67a8f18079f6dcaab371130b7bb5719adde84853
|
4
|
+
data.tar.gz: 3507f5c9ef4d942386a463aac6561e6d6e9ae98e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6aba022af5c0fd56b1cdcd944715bf30a60dfe376b4574e89494ff9bfb01d3365b77e36608d5701dd60cc17629c4f131f8b82436d637c57cd88dcff7f31254ff
|
7
|
+
data.tar.gz: 168ded50b3abd14b310a53c3f8afccaa02a5ca195a36e9cc2e61212a1e77be3d0ed9831de08a82f5b85fe7ef454179e562dcddf1a4c5c2689344928f393ba932
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Neeraj Bhunwal
|
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,31 @@
|
|
1
|
+
# Ec2
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'ec2'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install ec2
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
TODO: Write usage instructions here
|
24
|
+
|
25
|
+
## Contributing
|
26
|
+
|
27
|
+
1. Fork it ( https://github.com/[my-github-username]/ec2/fork )
|
28
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
29
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
30
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
31
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/bin/ec2
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
Signal.trap("INT") { exit 1 }
|
3
|
+
|
4
|
+
require 'optparse'
|
5
|
+
require 'ec2/version'
|
6
|
+
require 'ec2/error'
|
7
|
+
require 'ec2/logger'
|
8
|
+
|
9
|
+
logger = ::Ec2::Logger.logger
|
10
|
+
options = {}
|
11
|
+
|
12
|
+
opts_parser = OptionParser.new do |opts|
|
13
|
+
|
14
|
+
banner = []
|
15
|
+
banner << "Usage: ec2 [global options] command [options] args"
|
16
|
+
banner << "Commands:"
|
17
|
+
banner << " hosts"
|
18
|
+
|
19
|
+
banner << "Options: "
|
20
|
+
opts.banner = banner.join("\n")
|
21
|
+
|
22
|
+
opts.on("-v", "--version", "Show version") do |v|
|
23
|
+
puts ::Ec2::VERSION
|
24
|
+
exit
|
25
|
+
end
|
26
|
+
|
27
|
+
opts.on("--debug", "Show debug messages") do
|
28
|
+
options[:debug] = true
|
29
|
+
logger.level = ::Logger::DEBUG
|
30
|
+
end
|
31
|
+
|
32
|
+
opts.on("--trace", "Show debug messages and exception stack trace") do
|
33
|
+
options[:debug] = true
|
34
|
+
options[:trace] = true
|
35
|
+
logger.level = ::Logger::DEBUG
|
36
|
+
logger.trace = true
|
37
|
+
end
|
38
|
+
|
39
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
40
|
+
puts opts
|
41
|
+
exit
|
42
|
+
end
|
43
|
+
end
|
44
|
+
begin
|
45
|
+
opts_parser.order!(ARGV)
|
46
|
+
command = ( ARGV.shift || '').to_sym
|
47
|
+
case command
|
48
|
+
when :hosts
|
49
|
+
require 'ec2/cli/hosts'
|
50
|
+
cli = ::Ec2::Cli::Hosts.new(ARGV)
|
51
|
+
cli.run
|
52
|
+
when :resources
|
53
|
+
require 'ec2/cli/resources'
|
54
|
+
cli = ::Ec2::Cli::Resources.new(ARGV)
|
55
|
+
cli.run
|
56
|
+
when :''
|
57
|
+
puts opts_parser
|
58
|
+
else
|
59
|
+
raise ::Ec2::Error, "no such command #{command}"
|
60
|
+
end
|
61
|
+
|
62
|
+
rescue OptionParser::InvalidOption, OptionParser::MissingArgument, Ec2::Error => e
|
63
|
+
cause = e.cause
|
64
|
+
if options[:trace]
|
65
|
+
puts cause
|
66
|
+
cause ? (raise cause) : (raise e)
|
67
|
+
else
|
68
|
+
logger.debug "#{cause.message}" if cause
|
69
|
+
logger.error "#{e.message}"
|
70
|
+
abort
|
71
|
+
end
|
72
|
+
end
|
data/dev_bin/ec2
ADDED
data/ec2.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'ec2/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "ec2"
|
8
|
+
spec.version = Ec2::VERSION
|
9
|
+
spec.authors = ["Neeraj Bhunwal"]
|
10
|
+
spec.email = ["neeraj.bhunwal@gmail.com"]
|
11
|
+
spec.summary = %q{Integrates ec2 resources with salt}
|
12
|
+
spec.description = %q{Integrates ec2 resources with salt}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
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 = ["lib"]
|
20
|
+
|
21
|
+
spec.add_runtime_dependency 'aws-sdk', '2.0.23'
|
22
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
23
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
24
|
+
end
|
data/examples/test.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'pry'
|
2
|
+
lib = File.expand_path(__dir__ + '/../lib')
|
3
|
+
$LOAD_PATH.unshift(lib)
|
4
|
+
|
5
|
+
require 'aws-sdk'
|
6
|
+
require 'ec2/config'
|
7
|
+
require 'ec2/query_api'
|
8
|
+
require 'ec2/profile_dsl'
|
9
|
+
|
10
|
+
config = Ec2::Config.new(".ec2.rb").config
|
11
|
+
credentials = Aws::Credentials.new(config[:aws_key], config[:aws_secret])
|
12
|
+
Aws.config[:credentials] = credentials
|
13
|
+
Aws.config[:region] = config[:region]
|
14
|
+
|
15
|
+
api = Ec2::QueryApi.new(vpc_id: config[:vpc_id])
|
16
|
+
|
17
|
+
x = Ec2::ProfileDsl.new("profiles.rb", api: api)
|
18
|
+
pry
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'ec2/lock'
|
2
|
+
require 'ec2/salt_cloud'
|
3
|
+
require 'ec2/config'
|
4
|
+
|
5
|
+
module Ec2
|
6
|
+
module Cli
|
7
|
+
class Hosts
|
8
|
+
|
9
|
+
def initialize(argv)
|
10
|
+
@argv = argv
|
11
|
+
end
|
12
|
+
|
13
|
+
def run
|
14
|
+
lock.acquire
|
15
|
+
opts.parse!(@argv)
|
16
|
+
salt.config = config
|
17
|
+
salt.run
|
18
|
+
puts "ran hosts"
|
19
|
+
end
|
20
|
+
|
21
|
+
def salt
|
22
|
+
@salt ||= ::Ec2::SaltCloud.new
|
23
|
+
end
|
24
|
+
|
25
|
+
def lock
|
26
|
+
@lock ||= ::Ec2::Lock.new
|
27
|
+
end
|
28
|
+
|
29
|
+
def config
|
30
|
+
@config ||= ::Ec2::Config.new("ec2.conf").config
|
31
|
+
end
|
32
|
+
|
33
|
+
def opts
|
34
|
+
OptionParser.new do |opts|
|
35
|
+
|
36
|
+
opts.banner = "Usage: ec2 hosts [options] [target]"
|
37
|
+
|
38
|
+
opts.on("-f", "--file FILE", "Specify hosts file") do |f|
|
39
|
+
salt.hosts_file = f
|
40
|
+
end
|
41
|
+
|
42
|
+
opts.on("-h", "--help", "Help") do
|
43
|
+
puts opts
|
44
|
+
exit
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'ec2/lock'
|
2
|
+
require 'ec2/resources'
|
3
|
+
require 'ec2/config'
|
4
|
+
|
5
|
+
module Ec2
|
6
|
+
module Cli
|
7
|
+
class Resources
|
8
|
+
|
9
|
+
def initialize(argv)
|
10
|
+
@argv = argv
|
11
|
+
end
|
12
|
+
|
13
|
+
def run
|
14
|
+
lock.acquire
|
15
|
+
opts.parse!(@argv)
|
16
|
+
init_aws
|
17
|
+
@argv.each do |file|
|
18
|
+
resources = ::Ec2::Resources.new(file)
|
19
|
+
resources.apply
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def lock
|
24
|
+
@lock ||= ::Ec2::Lock.new
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
def init_aws
|
29
|
+
credentials = Aws::Credentials.new(config[:aws_key], config[:aws_secret])
|
30
|
+
Aws.config[:credentials] = credentials
|
31
|
+
Aws.config[:region] = config[:region]
|
32
|
+
end
|
33
|
+
|
34
|
+
def config
|
35
|
+
@config ||= ::Ec2::Config.new("ec2.conf").config
|
36
|
+
end
|
37
|
+
|
38
|
+
def opts
|
39
|
+
OptionParser.new do |opts|
|
40
|
+
|
41
|
+
opts.banner = "Usage: ec2 resources [options] [target]"
|
42
|
+
|
43
|
+
opts.on("-f", "--file FILE", "Specify hosts file") do |f|
|
44
|
+
salt.hosts_file = f
|
45
|
+
end
|
46
|
+
|
47
|
+
opts.on("-h", "--help", "Help") do
|
48
|
+
puts opts
|
49
|
+
exit
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/ec2/config.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'ec2/helper'
|
2
|
+
module Ec2
|
3
|
+
class Config
|
4
|
+
|
5
|
+
include Helper
|
6
|
+
|
7
|
+
def initialize(config_path)
|
8
|
+
@config_path = config_path
|
9
|
+
end
|
10
|
+
|
11
|
+
def config
|
12
|
+
return @config if @config
|
13
|
+
@config = {
|
14
|
+
region: "ap-southeast-1",
|
15
|
+
}
|
16
|
+
read_config
|
17
|
+
return @config
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def region(region)
|
23
|
+
set :region, region
|
24
|
+
end
|
25
|
+
|
26
|
+
def vpc_id(vpc)
|
27
|
+
set :vpc_id, vpc
|
28
|
+
end
|
29
|
+
|
30
|
+
def aws_key(aws_key)
|
31
|
+
set :aws_key, aws_key
|
32
|
+
end
|
33
|
+
|
34
|
+
def aws_secret(aws_secret)
|
35
|
+
set :aws_secret, aws_secret
|
36
|
+
end
|
37
|
+
|
38
|
+
def set(key, value)
|
39
|
+
@config.store key, value
|
40
|
+
end
|
41
|
+
|
42
|
+
def read_config
|
43
|
+
read("#{Dir.home}/.ec2.rb", required: false)
|
44
|
+
read(@config_path, required: false)
|
45
|
+
end
|
46
|
+
|
47
|
+
def read(file, required: true)
|
48
|
+
if not File.readable? file
|
49
|
+
raise error "config: #{file} not readable" if required
|
50
|
+
return
|
51
|
+
end
|
52
|
+
instance_eval(File.read(file), file)
|
53
|
+
rescue NoMethodError => e
|
54
|
+
error "invalid option used in config: #{e.name}"
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'ec2/ext/string'
|
2
|
+
module Ec2
|
3
|
+
class CustomLogger < ::Logger
|
4
|
+
|
5
|
+
attr_writer :trace
|
6
|
+
|
7
|
+
def initialize(file)
|
8
|
+
super(file)
|
9
|
+
@level = ::Logger::INFO
|
10
|
+
end
|
11
|
+
|
12
|
+
def format_message(severity, timestamp, progname, msg)
|
13
|
+
case severity
|
14
|
+
when "INFO"
|
15
|
+
"#{msg}\n"
|
16
|
+
when "ERROR"
|
17
|
+
"#{severity.bold.red} #{msg}\n"
|
18
|
+
when "WARN"
|
19
|
+
"#{severity.downcase.bold.yellow} #{msg}\n"
|
20
|
+
else
|
21
|
+
"#{severity[0].bold.blue} #{msg}\n"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def bullet(msg)
|
26
|
+
puts "#{"\u2219".bold.blue} #{msg}"
|
27
|
+
end
|
28
|
+
|
29
|
+
def trace?
|
30
|
+
@trace
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'ec2/logger'
|
2
|
+
require 'ec2/helper'
|
3
|
+
require 'erb'
|
4
|
+
|
5
|
+
module Ec2
|
6
|
+
class ErbProfile
|
7
|
+
|
8
|
+
include Logger
|
9
|
+
include Helper
|
10
|
+
|
11
|
+
attr_accessor :api
|
12
|
+
|
13
|
+
def initialize(file, api: nil)
|
14
|
+
@file = file
|
15
|
+
@api = api
|
16
|
+
end
|
17
|
+
|
18
|
+
def binding
|
19
|
+
api.instance_eval { binding }
|
20
|
+
end
|
21
|
+
|
22
|
+
def render
|
23
|
+
erb = ERB.new(File.read(@file), nil, '-')
|
24
|
+
erb.result(binding)
|
25
|
+
rescue => e
|
26
|
+
error "while rendering erb file #{@file}"
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
data/lib/ec2/error.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
class String
|
2
|
+
def colorize(color_code)
|
3
|
+
"\e[#{color_code}m#{self}\e[0m"
|
4
|
+
end
|
5
|
+
|
6
|
+
def bold
|
7
|
+
"\e[1m#{self}\e[0m"
|
8
|
+
end
|
9
|
+
|
10
|
+
def white
|
11
|
+
colorize(37)
|
12
|
+
end
|
13
|
+
|
14
|
+
def green
|
15
|
+
colorize(32)
|
16
|
+
end
|
17
|
+
|
18
|
+
def yellow
|
19
|
+
colorize(33)
|
20
|
+
end
|
21
|
+
|
22
|
+
def red
|
23
|
+
colorize(31)
|
24
|
+
end
|
25
|
+
|
26
|
+
def blue
|
27
|
+
colorize(34)
|
28
|
+
end
|
29
|
+
|
30
|
+
def grey
|
31
|
+
colorize("90")
|
32
|
+
end
|
33
|
+
end
|
data/lib/ec2/helper.rb
ADDED
data/lib/ec2/lock.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'ec2/logger'
|
2
|
+
module Ec2
|
3
|
+
class Lock
|
4
|
+
|
5
|
+
include Logger
|
6
|
+
|
7
|
+
def acquire
|
8
|
+
logger.debug "acquiring lock"
|
9
|
+
lock_acquired = lock_file.flock(File::LOCK_NB | File::LOCK_EX)
|
10
|
+
raise "exclusive lock not available" if not lock_acquired
|
11
|
+
end
|
12
|
+
|
13
|
+
def lock_file
|
14
|
+
@lock_file ||= File.open(".ec2.lock", "a+")
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
data/lib/ec2/logger.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'ec2/custom_logger'
|
3
|
+
module Ec2
|
4
|
+
module Logger
|
5
|
+
|
6
|
+
def self.logger
|
7
|
+
@logger ||= CustomLogger.new(STDOUT)
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.stderr
|
11
|
+
@stderr ||= ::Logger.new(STDERR)
|
12
|
+
end
|
13
|
+
|
14
|
+
def logger
|
15
|
+
::Ec2::Logger.logger
|
16
|
+
end
|
17
|
+
|
18
|
+
def stderr
|
19
|
+
::Ec2::Logger.stderr
|
20
|
+
end
|
21
|
+
|
22
|
+
def debug?
|
23
|
+
logger.level == ::Logger::DEBUG
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
data/lib/ec2/profile.rb
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'ec2/logger'
|
3
|
+
require 'ec2/helper'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
module Ec2
|
7
|
+
class Profile
|
8
|
+
|
9
|
+
include Logger
|
10
|
+
include Helper
|
11
|
+
|
12
|
+
attr_reader :api, :data
|
13
|
+
|
14
|
+
def initialize(api: nil, data: nil)
|
15
|
+
@data = deep_copy(data) || {}
|
16
|
+
@api = api
|
17
|
+
init_network
|
18
|
+
end
|
19
|
+
|
20
|
+
def create(transform: true, &block)
|
21
|
+
instance_eval &block
|
22
|
+
transform_name_to_id if transform
|
23
|
+
end
|
24
|
+
|
25
|
+
def init_network
|
26
|
+
return if @data['network_interfaces'].is_a? Array
|
27
|
+
@data['network_interfaces'] = [
|
28
|
+
{
|
29
|
+
"DeviceIndex" => 0,
|
30
|
+
"AssociatePublicIpAddress" => true,
|
31
|
+
"SecurityGroupId" => []
|
32
|
+
}
|
33
|
+
]
|
34
|
+
end
|
35
|
+
|
36
|
+
def extends(value)
|
37
|
+
@data.store "extends", value
|
38
|
+
end
|
39
|
+
|
40
|
+
def size(value)
|
41
|
+
@data.store "size", value
|
42
|
+
end
|
43
|
+
|
44
|
+
def security_group(name, interface: 0)
|
45
|
+
@data["network_interfaces"][interface]["SecurityGroupId"] << name
|
46
|
+
end
|
47
|
+
|
48
|
+
def subnet(name, interface: 0)
|
49
|
+
@data["network_interfaces"][interface]["SubnetId"] = name
|
50
|
+
end
|
51
|
+
|
52
|
+
def security_groups(*names, interface: 0)
|
53
|
+
names.each { |name| security_group name, interface: interface }
|
54
|
+
end
|
55
|
+
|
56
|
+
def volume(device:, type: "gp2", size:)
|
57
|
+
@data["volumes"] ||= []
|
58
|
+
volumes = @data["volumes"]
|
59
|
+
volume = {
|
60
|
+
"device" => device,
|
61
|
+
"type" => type,
|
62
|
+
"size" => size
|
63
|
+
}
|
64
|
+
existing_volume = volumes.find { |v| v["device"] == device }
|
65
|
+
if existing_volume
|
66
|
+
existing_volume.merge! volume
|
67
|
+
else
|
68
|
+
volumes << volume
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def deep_copy(hash)
|
75
|
+
return nil if not hash.is_a? Hash
|
76
|
+
Marshal.load(Marshal.dump hash)
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
def transform_name_to_id
|
81
|
+
@data["network_interfaces"].each do |n|
|
82
|
+
n["SubnetId"] = api.subnet(n["SubnetId"])
|
83
|
+
security_groups = n["SecurityGroupId"]
|
84
|
+
|
85
|
+
security_groups.each_with_index do |name, i|
|
86
|
+
logger.debug "resolving security_group #{name}"
|
87
|
+
security_groups[i] = api.security_group(name)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'ec2/logger'
|
3
|
+
require 'ec2/helper'
|
4
|
+
require 'ec2/profile'
|
5
|
+
require 'set'
|
6
|
+
|
7
|
+
module Ec2
|
8
|
+
class ProfileDsl
|
9
|
+
|
10
|
+
include Logger
|
11
|
+
include Helper
|
12
|
+
|
13
|
+
attr_reader :api
|
14
|
+
|
15
|
+
def initialize(file, api:)
|
16
|
+
@file = file
|
17
|
+
@profiles = {}
|
18
|
+
@api = api
|
19
|
+
@templates = {}
|
20
|
+
@availability_zones = ["a", "b"]
|
21
|
+
@required = Set.new
|
22
|
+
end
|
23
|
+
|
24
|
+
def use(*templates)
|
25
|
+
templates.each do |t|
|
26
|
+
t = t.to_s
|
27
|
+
mprofile(t, template: t){}
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def template(name, &block)
|
32
|
+
profile = Profile.new(api: api)
|
33
|
+
profile.extends(@base_profile) if @base_profile
|
34
|
+
profile.create(transform: false, &block)
|
35
|
+
@templates[name] = profile.data
|
36
|
+
@templates[name].freeze
|
37
|
+
end
|
38
|
+
|
39
|
+
def mprofile(name, template: nil, &block)
|
40
|
+
data = @templates.fetch template if template
|
41
|
+
@availability_zones.each do |az|
|
42
|
+
profile = Profile.new(data: data, api: api)
|
43
|
+
profile.extends(@base_profile) if @base_profile
|
44
|
+
profile.subnet("#{@base_subnet}-#{az}")
|
45
|
+
profile.create &block
|
46
|
+
profile_name = "#{name}-#{az}"
|
47
|
+
profile.data.freeze
|
48
|
+
@profiles[profile_name] = profile.data
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def profile(name, template: nil, &block)
|
53
|
+
data = @templates.fetch template if template
|
54
|
+
profile = Profile.new(data: data, api: api)
|
55
|
+
profile.extends(@base_profile) if @base_profile
|
56
|
+
profile.create &block
|
57
|
+
profile.data.freeze
|
58
|
+
@profiles[name] = profile.data
|
59
|
+
end
|
60
|
+
|
61
|
+
def base_profile(name)
|
62
|
+
@base_profile = name
|
63
|
+
end
|
64
|
+
|
65
|
+
def base_subnet(name)
|
66
|
+
@base_subnet = name
|
67
|
+
end
|
68
|
+
|
69
|
+
def availability_zones(*zones)
|
70
|
+
@availability_zones = zones
|
71
|
+
end
|
72
|
+
|
73
|
+
def render
|
74
|
+
if not File.readable? @file
|
75
|
+
logger.info "#{@file} not readable"
|
76
|
+
return
|
77
|
+
end
|
78
|
+
instance_eval(File.read(@file), @file)
|
79
|
+
YAML.dump @profiles
|
80
|
+
rescue NoMethodError => e
|
81
|
+
error "invalid option used in profiles config: #{e.name}"
|
82
|
+
end
|
83
|
+
|
84
|
+
def vpc_id(vpc_id)
|
85
|
+
@vpc_id = vpc_id
|
86
|
+
end
|
87
|
+
|
88
|
+
def import(path)
|
89
|
+
abs_path = File.realpath path
|
90
|
+
return if @required.include? abs_path
|
91
|
+
instance_eval((File.read abs_path), abs_path)
|
92
|
+
@required << abs_path
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'ec2/helper'
|
2
|
+
require 'ec2/security_group'
|
3
|
+
require 'ec2/subnet'
|
4
|
+
|
5
|
+
module Ec2
|
6
|
+
class QueryApi
|
7
|
+
|
8
|
+
include Helper
|
9
|
+
|
10
|
+
def initialize(vpc_id: nil)
|
11
|
+
@vpc_id = vpc_id
|
12
|
+
end
|
13
|
+
|
14
|
+
def security_group(name)
|
15
|
+
security_group = SecurityGroup.new(name, vpc_id: @vpc_id)
|
16
|
+
sg_cache[name] ||= security_group.id!
|
17
|
+
end
|
18
|
+
|
19
|
+
def subnet(name)
|
20
|
+
subnet = Subnet.new(name, vpc_id: @vpc_id)
|
21
|
+
subnet_cache[name] ||= subnet.id!
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def sg_cache
|
27
|
+
@sg_cache ||= {}
|
28
|
+
end
|
29
|
+
|
30
|
+
def subnet_cache
|
31
|
+
@subnet_cache ||= {}
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'ec2/security_group'
|
2
|
+
require 'ec2/subnet'
|
3
|
+
module Ec2
|
4
|
+
class Resources
|
5
|
+
|
6
|
+
|
7
|
+
def initialize(file)
|
8
|
+
@file = file
|
9
|
+
end
|
10
|
+
|
11
|
+
def vpc_id(vpc_id)
|
12
|
+
@vpc_id = vpc_id
|
13
|
+
end
|
14
|
+
|
15
|
+
def security_group(name, &block)
|
16
|
+
sg = SecurityGroup.new(name, vpc_id: @vpc_id)
|
17
|
+
sg.created &block
|
18
|
+
end
|
19
|
+
|
20
|
+
def subnet(name, &block)
|
21
|
+
subnet = Subnet.new(name, vpc_id: @vpc_id)
|
22
|
+
subnet.created &block
|
23
|
+
end
|
24
|
+
|
25
|
+
def apply
|
26
|
+
instance_eval(File.read(@file), @file)
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'pathname'
|
3
|
+
require 'aws-sdk'
|
4
|
+
|
5
|
+
require 'ec2/query_api'
|
6
|
+
require 'ec2/profile_dsl'
|
7
|
+
require 'ec2/erb_profile'
|
8
|
+
require 'ec2/logger'
|
9
|
+
|
10
|
+
module Ec2
|
11
|
+
class SaltCloud
|
12
|
+
|
13
|
+
include Logger
|
14
|
+
attr_writer :hosts_file
|
15
|
+
attr_accessor :config
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
end
|
19
|
+
|
20
|
+
def run
|
21
|
+
init_working_dir
|
22
|
+
copy_providers
|
23
|
+
copy_profiles
|
24
|
+
copy_master_config
|
25
|
+
copy_deploy_scripts
|
26
|
+
init_aws
|
27
|
+
render_global_profiles
|
28
|
+
render_local_profile
|
29
|
+
run_salt_cloud
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def init_aws
|
35
|
+
credentials = Aws::Credentials.new(config[:aws_key], config[:aws_secret])
|
36
|
+
Aws.config[:credentials] = credentials
|
37
|
+
Aws.config[:region] = config[:region]
|
38
|
+
end
|
39
|
+
|
40
|
+
def api
|
41
|
+
@api ||= QueryApi.new(vpc_id: config[:vpc_id])
|
42
|
+
end
|
43
|
+
|
44
|
+
def working_dir
|
45
|
+
@working_dir ||= ".salt.tmp"
|
46
|
+
end
|
47
|
+
|
48
|
+
def hosts_file
|
49
|
+
@hosts_file ||= "hosts"
|
50
|
+
end
|
51
|
+
|
52
|
+
def init_working_dir
|
53
|
+
FileUtils.rm_r working_dir if File.directory? working_dir
|
54
|
+
FileUtils.mkdir_p "#{working_dir}/cloud.profiles.d"
|
55
|
+
end
|
56
|
+
|
57
|
+
def copy_providers
|
58
|
+
return if not File.directory? "/etc/salt/cloud.providers.d"
|
59
|
+
FileUtils.cp_r "/etc/salt/cloud.providers.d", working_dir
|
60
|
+
end
|
61
|
+
|
62
|
+
def copy_profiles
|
63
|
+
return if not File.directory? "/etc/salt/cloud.profiles.d"
|
64
|
+
Dir["/etc/salt/cloud.profiles.d/*.conf"].each do |f|
|
65
|
+
path = Pathname.new f
|
66
|
+
FileUtils.cp path, "#{working_dir}/cloud.profiles.d/_#{path.basename}"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def copy_master_config
|
71
|
+
FileUtils.cp "/etc/salt/master", working_dir
|
72
|
+
end
|
73
|
+
|
74
|
+
def copy_deploy_scripts
|
75
|
+
return if not File.directory? "/etc/salt/cloud.deploy.d"
|
76
|
+
FileUtils.cp_r "/etc/salt/cloud.deploy.d", working_dir
|
77
|
+
end
|
78
|
+
|
79
|
+
def render_global_profiles
|
80
|
+
Dir["/etc/salt/cloud.profiles.d/*.erb"].each do |f|
|
81
|
+
render(f, prefix: "_")
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def render_local_profile
|
86
|
+
local_profile = ["profiles.rb", "profiles.erb"].find { |f| File.readable? f }
|
87
|
+
render(local_profile) if local_profile
|
88
|
+
end
|
89
|
+
|
90
|
+
def render(path, prefix: nil)
|
91
|
+
extname = File.extname path
|
92
|
+
name = File.basename(path, extname)
|
93
|
+
outfile = "#{working_dir}/cloud.profiles.d/#{prefix}#{name}.conf"
|
94
|
+
case extname
|
95
|
+
when ".rb"
|
96
|
+
profile_dsl = ProfileDsl.new(path, api: api)
|
97
|
+
File.open(outfile, "w") { |f| f.write profile_dsl.render }
|
98
|
+
when ".erb"
|
99
|
+
erb = ErbProfile.new(path, api: api)
|
100
|
+
File.open(outfile, "w") { |f| f.write erb.render }
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def run_salt_cloud
|
105
|
+
logger.debug "running salt cloud"
|
106
|
+
command = %Q( salt-cloud -m #{hosts_file} -c #{working_dir} )
|
107
|
+
command << " -l debug" if logger.trace?
|
108
|
+
system command
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,196 @@
|
|
1
|
+
require 'ec2/helper'
|
2
|
+
require 'ec2/logger'
|
3
|
+
require 'aws-sdk'
|
4
|
+
require 'set'
|
5
|
+
|
6
|
+
module Ec2
|
7
|
+
class SecurityGroup
|
8
|
+
|
9
|
+
include Helper
|
10
|
+
include Logger
|
11
|
+
attr_reader :desired_permissions
|
12
|
+
|
13
|
+
def initialize(name, vpc_id: nil)
|
14
|
+
error "vpc_id not specified for security group" if not vpc_id
|
15
|
+
@vpc_id = vpc_id.to_s
|
16
|
+
@name = name
|
17
|
+
@dry_run = false
|
18
|
+
end
|
19
|
+
|
20
|
+
def id
|
21
|
+
return @id unless @id.nil?
|
22
|
+
@id = load_id
|
23
|
+
end
|
24
|
+
|
25
|
+
def description(description)
|
26
|
+
@description = description
|
27
|
+
end
|
28
|
+
|
29
|
+
def id!
|
30
|
+
error "specified security_group #{@name} doesn't exist in vpc #{@vpc_id}" if not exists?
|
31
|
+
id
|
32
|
+
end
|
33
|
+
|
34
|
+
def created(&block)
|
35
|
+
clear_vars
|
36
|
+
instance_eval &block
|
37
|
+
create if not exists?
|
38
|
+
sync
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def sg
|
44
|
+
@sg ||= ::Aws::EC2::SecurityGroup.new(id)
|
45
|
+
end
|
46
|
+
|
47
|
+
def create
|
48
|
+
resp = ec2.create_security_group(
|
49
|
+
group_name: @name,
|
50
|
+
description: @description,
|
51
|
+
vpc_id: @vpc_id
|
52
|
+
)
|
53
|
+
@id = resp.group_id
|
54
|
+
logger.info "(#{@name}) created security group"
|
55
|
+
rescue Aws::Errors::ServiceError, ArgumentError
|
56
|
+
error "while creating security_group #{@name}"
|
57
|
+
end
|
58
|
+
|
59
|
+
def load_id
|
60
|
+
filters = []
|
61
|
+
filters << { name: "group-name", values: [@name.to_s] }
|
62
|
+
filters << vpc_filter
|
63
|
+
result = ec2.describe_security_groups(filters: filters)
|
64
|
+
if result.security_groups.size == 1
|
65
|
+
return result.security_groups.first.group_id
|
66
|
+
else
|
67
|
+
return false
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def exists?
|
72
|
+
id
|
73
|
+
end
|
74
|
+
|
75
|
+
def vpc_filter
|
76
|
+
{ name: "vpc-id", values: [@vpc_id.to_s] }
|
77
|
+
end
|
78
|
+
|
79
|
+
def outbound(&block)
|
80
|
+
@outbound = true
|
81
|
+
instance_eval &block
|
82
|
+
ensure
|
83
|
+
@outbound = false
|
84
|
+
end
|
85
|
+
|
86
|
+
def parse_ports(port)
|
87
|
+
if port.is_a? Integer
|
88
|
+
return port, port
|
89
|
+
elsif port =~ /\A([0-9]+)\z/
|
90
|
+
return $1.to_i, $1.to_i
|
91
|
+
elsif port =~ /\A([0-9]+)\-([0-9]+)\z/
|
92
|
+
return $1.to_i, $2.to_i
|
93
|
+
else
|
94
|
+
error "invalid port specified #{port}"
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def tcp(port, **args)
|
99
|
+
(from_port, to_port) = parse_ports(port)
|
100
|
+
rule(ip_protocol: "tcp", from_port: from_port, to_port: to_port, **args)
|
101
|
+
end
|
102
|
+
|
103
|
+
def udp(port, **args)
|
104
|
+
(from_port, to_port) = parse_ports(port)
|
105
|
+
rule(ip_protocol: "udp", from_port: from_port, to_port: to_port, **args)
|
106
|
+
end
|
107
|
+
|
108
|
+
def icmp(**args)
|
109
|
+
rule(ip_protocol: "icmp", from_port: -1, to_port: -1, **args)
|
110
|
+
end
|
111
|
+
|
112
|
+
def rule(ip_protocol: nil, from_port: nil, to_port: nil, cidr_ip: nil)
|
113
|
+
options = {
|
114
|
+
ip_protocol: ip_protocol,
|
115
|
+
from_port: from_port,
|
116
|
+
to_port: to_port,
|
117
|
+
cidr_ip: cidr_ip
|
118
|
+
}
|
119
|
+
if not @outbound
|
120
|
+
@desired_permissions ||= Set.new
|
121
|
+
@desired_permissions << options
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def current_permissions
|
126
|
+
@current_permissions ||= begin
|
127
|
+
permissions = Set.new
|
128
|
+
sg.ip_permissions.each do |permission|
|
129
|
+
rules = permission_to_rules(permission)
|
130
|
+
rules.each { |r| permissions << r }
|
131
|
+
end
|
132
|
+
permissions
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def diff(current, desired)
|
137
|
+
to_add = desired - current
|
138
|
+
to_remove = current - desired
|
139
|
+
s = Struct.new(:to_add, :to_remove)
|
140
|
+
s.new(to_add, to_remove)
|
141
|
+
end
|
142
|
+
|
143
|
+
def sync
|
144
|
+
ingress_diff.to_add.each { |r| authorize_ingress r }
|
145
|
+
ingress_diff.to_remove.each { |r| revoke_ingress r }
|
146
|
+
end
|
147
|
+
|
148
|
+
|
149
|
+
def authorize_ingress(rule)
|
150
|
+
sg.authorize_ingress rule if not @dry_run
|
151
|
+
logger.info "(#{@name}) #{"+".green.bold} allow #{rule[:cidr_ip]} #{rule[:from_port]}-#{rule[:to_port]}"
|
152
|
+
rescue Aws::Errors::ServiceError
|
153
|
+
error "error authorizing rule #{rule}"
|
154
|
+
end
|
155
|
+
|
156
|
+
def revoke_ingress(rule)
|
157
|
+
sg.revoke_ingress rule if not @dry_run
|
158
|
+
logger.info "(#{@name}) #{"-".red.bold} allow #{rule[:cidr_ip]} #{rule[:from_port]}-#{rule[:to_port]}"
|
159
|
+
end
|
160
|
+
|
161
|
+
def ingress_diff
|
162
|
+
@ingress_diff ||= diff(current_permissions, desired_permissions)
|
163
|
+
end
|
164
|
+
|
165
|
+
def clear_vars
|
166
|
+
@desired_permissions = nil
|
167
|
+
@current_permissions = nil
|
168
|
+
@ingress_diff = nil
|
169
|
+
end
|
170
|
+
|
171
|
+
def permission_to_rules(permission)
|
172
|
+
rules = Set.new
|
173
|
+
permission.ip_ranges.each do |r|
|
174
|
+
rule = {
|
175
|
+
ip_protocol: permission.ip_protocol,
|
176
|
+
from_port: permission.from_port,
|
177
|
+
to_port: permission.to_port,
|
178
|
+
cidr_ip: r.cidr_ip
|
179
|
+
}
|
180
|
+
rules << rule
|
181
|
+
end
|
182
|
+
rules
|
183
|
+
end
|
184
|
+
|
185
|
+
def ec2
|
186
|
+
@ec2 ||= begin
|
187
|
+
if @region
|
188
|
+
Aws::EC2::Client.new(region: @region)
|
189
|
+
else
|
190
|
+
Aws::EC2::Client.new
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
end
|
196
|
+
end
|
data/lib/ec2/subnet.rb
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'ec2/helper'
|
2
|
+
require 'ec2/logger'
|
3
|
+
module Ec2
|
4
|
+
class Subnet
|
5
|
+
|
6
|
+
include Helper
|
7
|
+
include Logger
|
8
|
+
|
9
|
+
def initialize(name, vpc_id: nil)
|
10
|
+
error "vpc_id not specified for subnet" if not vpc_id
|
11
|
+
@vpc_id = vpc_id.to_s
|
12
|
+
@name = name.to_s
|
13
|
+
end
|
14
|
+
|
15
|
+
def id!
|
16
|
+
load_id if not @id
|
17
|
+
error "specified subnet #{@name} doesn't exist in vpc #{@vpc_id}" if not exists?
|
18
|
+
@id
|
19
|
+
end
|
20
|
+
|
21
|
+
def created(&block)
|
22
|
+
instance_eval &block
|
23
|
+
load_id using_cidr: true
|
24
|
+
if exists?
|
25
|
+
tag if not tagged?
|
26
|
+
verify
|
27
|
+
else
|
28
|
+
create
|
29
|
+
tag
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def subnet
|
36
|
+
@subnet ||= ::Aws::EC2::Subnet.new(@id)
|
37
|
+
end
|
38
|
+
|
39
|
+
def create
|
40
|
+
resp = ec2.create_subnet(
|
41
|
+
vpc_id: @vpc_id,
|
42
|
+
cidr_block: @cidr,
|
43
|
+
availability_zone: @availability_zone
|
44
|
+
)
|
45
|
+
@id = resp.subnet.subnet_id
|
46
|
+
logger.info "(#{@name}) created subnet: #{@cidr}"
|
47
|
+
rescue Aws::Errors::ServiceError, ArgumentError
|
48
|
+
error "while creating subnet #{@name}"
|
49
|
+
end
|
50
|
+
|
51
|
+
def tag
|
52
|
+
subnet.create_tags(
|
53
|
+
tags: [ { key: "Name", value: @name } ]
|
54
|
+
)
|
55
|
+
subnet.load
|
56
|
+
end
|
57
|
+
|
58
|
+
def tagged?
|
59
|
+
subnet.tags.any? { |tag| tag.key == "Name"}
|
60
|
+
end
|
61
|
+
|
62
|
+
def verify
|
63
|
+
name_tag = subnet.tags.find { |tag| tag.key == "Name" }.value
|
64
|
+
error "availability zone mismatch for subnet #{@name}" if subnet.availability_zone != @availability_zone
|
65
|
+
error "subnet #{@name} already tagged with another name #{name_tag}" if @name != name_tag
|
66
|
+
end
|
67
|
+
|
68
|
+
def cidr(cidr)
|
69
|
+
@cidr = cidr
|
70
|
+
end
|
71
|
+
|
72
|
+
def availability_zone(availability_zone)
|
73
|
+
@availability_zone = availability_zone
|
74
|
+
end
|
75
|
+
|
76
|
+
alias_method :az, :availability_zone
|
77
|
+
|
78
|
+
|
79
|
+
def load_id(using_cidr: false)
|
80
|
+
filters = []
|
81
|
+
|
82
|
+
if using_cidr
|
83
|
+
filters << { name: "cidr", values: [@cidr.to_s] }
|
84
|
+
else
|
85
|
+
filters << { name: "tag:Name", values: [@name.to_s] }
|
86
|
+
end
|
87
|
+
|
88
|
+
filters << { name: "vpc-id", values: [@vpc_id.to_s] }
|
89
|
+
result = ec2.describe_subnets(filters: filters)
|
90
|
+
error "mulitple subnets found with name #{@name}" if result.subnets.size > 1
|
91
|
+
@id = result.subnets.first.subnet_id if result.subnets.size == 1
|
92
|
+
end
|
93
|
+
|
94
|
+
def exists?
|
95
|
+
@id
|
96
|
+
end
|
97
|
+
|
98
|
+
def ec2
|
99
|
+
@ec2 ||= begin
|
100
|
+
@region ? Aws::EC2::Client.new(region: @region) : Aws::EC2::Client.new
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
end
|
data/lib/ec2/version.rb
ADDED
data/lib/ec2.rb
ADDED
metadata
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ec2
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.4
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Neeraj Bhunwal
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-07-31 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.0.23
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 2.0.23
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.7'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.7'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
description: Integrates ec2 resources with salt
|
56
|
+
email:
|
57
|
+
- neeraj.bhunwal@gmail.com
|
58
|
+
executables:
|
59
|
+
- ec2
|
60
|
+
extensions: []
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- .gitignore
|
64
|
+
- Gemfile
|
65
|
+
- LICENSE.txt
|
66
|
+
- README.md
|
67
|
+
- Rakefile
|
68
|
+
- bin/ec2
|
69
|
+
- dev_bin/ec2
|
70
|
+
- ec2.gemspec
|
71
|
+
- examples/profiles.rb
|
72
|
+
- examples/templates.rb
|
73
|
+
- examples/test.rb
|
74
|
+
- lib/ec2.rb
|
75
|
+
- lib/ec2/cli/hosts.rb
|
76
|
+
- lib/ec2/cli/resources.rb
|
77
|
+
- lib/ec2/config.rb
|
78
|
+
- lib/ec2/custom_logger.rb
|
79
|
+
- lib/ec2/erb_profile.rb
|
80
|
+
- lib/ec2/error.rb
|
81
|
+
- lib/ec2/ext/string.rb
|
82
|
+
- lib/ec2/helper.rb
|
83
|
+
- lib/ec2/lock.rb
|
84
|
+
- lib/ec2/logger.rb
|
85
|
+
- lib/ec2/profile.rb
|
86
|
+
- lib/ec2/profile_dsl.rb
|
87
|
+
- lib/ec2/query_api.rb
|
88
|
+
- lib/ec2/resources.rb
|
89
|
+
- lib/ec2/salt_cloud.rb
|
90
|
+
- lib/ec2/security_group.rb
|
91
|
+
- lib/ec2/subnet.rb
|
92
|
+
- lib/ec2/version.rb
|
93
|
+
homepage: ''
|
94
|
+
licenses:
|
95
|
+
- MIT
|
96
|
+
metadata: {}
|
97
|
+
post_install_message:
|
98
|
+
rdoc_options: []
|
99
|
+
require_paths:
|
100
|
+
- lib
|
101
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - '>='
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '0'
|
106
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
requirements: []
|
112
|
+
rubyforge_project:
|
113
|
+
rubygems_version: 2.0.14
|
114
|
+
signing_key:
|
115
|
+
specification_version: 4
|
116
|
+
summary: Integrates ec2 resources with salt
|
117
|
+
test_files: []
|