chemtrail 0.2.0 → 0.3.0
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 +4 -4
- data/README.md +14 -0
- data/bin/chemtrail +0 -1
- data/examples/.rspec +2 -0
- data/examples/Guardfile +8 -0
- data/examples/lib/templates/config/mappings.yml +53 -0
- data/examples/lib/templates/config/parameters.yml +18 -0
- data/examples/lib/templates/opsworks_vpc_template.rb +44 -0
- data/examples/spec/lib/templates/opsworks_vpc_template_spec.rb +30 -0
- data/examples/spec/spec_helper.rb +15 -0
- data/lib/chemtrail/cli.rb +1 -0
- data/lib/chemtrail/mapping.rb +2 -1
- data/lib/chemtrail/parameter.rb +5 -5
- data/lib/chemtrail/rspec.rb +131 -0
- data/lib/chemtrail/version.rb +1 -1
- data/spec/lib/chemtrail/cli_spec.rb +3 -2
- data/spec/lib/chemtrail/mapping_spec.rb +9 -3
- data/spec/lib/chemtrail/parameter_spec.rb +5 -5
- metadata +9 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0b457fc52081b5875c31d1d124429aa6d438b31a
|
4
|
+
data.tar.gz: 77706788871003cba5307760765b907f986a80e4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cf6193b91a72aeafb284aa0c928c599a04796379af5d90005fa67caed9b5283f442eb076bf0dd22acbb4f773bb151f505975ac82e095ab7a9f39a3d9bfc8ff7b
|
7
|
+
data.tar.gz: d81f93f39b399601bfd3cb96f1bef9314df9e4360f327651a36b9baae7f4635ec11a6c5542fd68d890d88cd894823fad0e7d8d0ad9172d47c7dcb477c14e2a11
|
data/README.md
CHANGED
@@ -33,6 +33,20 @@ Or install it yourself as:
|
|
33
33
|
Usage
|
34
34
|
-----
|
35
35
|
|
36
|
+
See the `examples/` directory for examples of subclassing and testing templates.
|
37
|
+
|
38
|
+
Listing all available templates in `lib/templates`:
|
39
|
+
|
40
|
+
$ chemtrail list
|
41
|
+
|
42
|
+
Listing templates in a different path:
|
43
|
+
|
44
|
+
$ chemtrail list --path lib/taco/panic
|
45
|
+
|
46
|
+
Building a template:
|
47
|
+
|
48
|
+
$ chemtrail build crazy:cat:pants
|
49
|
+
|
36
50
|
|
37
51
|
Contributing
|
38
52
|
------------
|
data/bin/chemtrail
CHANGED
data/examples/.rspec
ADDED
data/examples/Guardfile
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
AWSNATAMI:
|
2
|
+
us-east-1:
|
3
|
+
AMI: ami-c6699baf
|
4
|
+
us-west-2:
|
5
|
+
AMI: ami-52ff7262
|
6
|
+
us-west-1:
|
7
|
+
AMI: ami-3bcc9e7e
|
8
|
+
eu-west-1:
|
9
|
+
AMI: ami-0b5b6c7f
|
10
|
+
ap-southeast-1:
|
11
|
+
AMI: ami-02eb9350
|
12
|
+
ap-southeast-2:
|
13
|
+
AMI: ami-ab990e91
|
14
|
+
ap-northeast-1:
|
15
|
+
AMI: ami-14d86d15
|
16
|
+
sa-east-1:
|
17
|
+
AMI: ami-0439e619
|
18
|
+
|
19
|
+
AWSInstanceType2Arch:
|
20
|
+
t1.micro:
|
21
|
+
Arch: "64"
|
22
|
+
m1.small:
|
23
|
+
Arch: "64"
|
24
|
+
m1.medium:
|
25
|
+
Arch: "64"
|
26
|
+
m1.large:
|
27
|
+
Arch: "64"
|
28
|
+
m1.xlarge:
|
29
|
+
Arch: "64"
|
30
|
+
m2.xlarge:
|
31
|
+
Arch: "64"
|
32
|
+
m2.2xlarge:
|
33
|
+
Arch: "64"
|
34
|
+
m2.4xlarge:
|
35
|
+
Arch: "64"
|
36
|
+
c1.medium:
|
37
|
+
Arch: "64"
|
38
|
+
c1.xlarge:
|
39
|
+
Arch: "64"
|
40
|
+
cc1.4xlarge:
|
41
|
+
Arch: 64Cluster
|
42
|
+
cc2.8xlarge:
|
43
|
+
Arch: 64Cluster
|
44
|
+
cg1.4xlarge:
|
45
|
+
Arch: 64GPU
|
46
|
+
|
47
|
+
SubnetConfig:
|
48
|
+
VPC:
|
49
|
+
CIDR: 10.0.0.0/16
|
50
|
+
Public:
|
51
|
+
CIDR: 10.0.0.0/24
|
52
|
+
Private:
|
53
|
+
CIDR: 10.0.1.0/24
|
@@ -0,0 +1,18 @@
|
|
1
|
+
NATInstanceType:
|
2
|
+
Default: m1.small
|
3
|
+
Description: NAT Device EC2 instance type
|
4
|
+
ConstraintDescription: must be a valid EC2 instance type.
|
5
|
+
AllowedValues:
|
6
|
+
- t1.micro
|
7
|
+
- m1.small
|
8
|
+
- m1.medium
|
9
|
+
- m1.large
|
10
|
+
- m1.xlarge
|
11
|
+
- m2.xlarge
|
12
|
+
- m2.2xlarge
|
13
|
+
- m2.4xlarge
|
14
|
+
- c1.medium
|
15
|
+
- c1.xlarge
|
16
|
+
- cc1.4xlarge
|
17
|
+
- cc2.8xlarge
|
18
|
+
- cg1.4xlarge
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require "chemtrail"
|
2
|
+
require "yaml"
|
3
|
+
|
4
|
+
class OpsworksVpc < Chemtrail::Template
|
5
|
+
def description
|
6
|
+
<<-DESCRIPTION.strip.gsub!(/\s+/, ' ')
|
7
|
+
Sample template showing how to create a VPC environment for AWS OpsWorks.
|
8
|
+
The stack contains 2 subnets: the first subnet is public and contains the
|
9
|
+
load balancer, a NAT device for internet access from the private subnet.
|
10
|
+
The second subnet is private.
|
11
|
+
|
12
|
+
You will be billed for the AWS resources used if you create a stack from
|
13
|
+
this template.
|
14
|
+
DESCRIPTION
|
15
|
+
end
|
16
|
+
|
17
|
+
def parameters
|
18
|
+
[
|
19
|
+
Chemtrail::Parameter.new("NATInstanceType", "String", parameters_config["NATInstanceType"])
|
20
|
+
]
|
21
|
+
end
|
22
|
+
|
23
|
+
def mappings
|
24
|
+
[
|
25
|
+
Chemtrail::Mapping.new("AWSNATAMI", mappings_config["AWSNATAMI"]),
|
26
|
+
Chemtrail::Mapping.new("AWSInstanceType2Arch", mappings_config["AWSInstanceType2Arch"]),
|
27
|
+
Chemtrail::Mapping.new("SubnetConfig", mappings_config["SubnetConfig"])
|
28
|
+
]
|
29
|
+
end
|
30
|
+
|
31
|
+
protected
|
32
|
+
|
33
|
+
def parameters_config
|
34
|
+
@parameters_config ||= YAML.load_file(File.expand_path("../config/parameters.yml", __FILE__))
|
35
|
+
end
|
36
|
+
|
37
|
+
def mappings_config
|
38
|
+
@mappings_config ||= YAML.load_file(File.expand_path("../config/mappings.yml", __FILE__))
|
39
|
+
end
|
40
|
+
|
41
|
+
def resources_config
|
42
|
+
@resources_config ||= YAML.load_file(File.expand_path("../config/resources.yml", __FILE__))
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe OpsworksVpc do
|
4
|
+
subject(:template) { OpsworksVpc.new }
|
5
|
+
|
6
|
+
its(:description) { should include("VPC environment for AWS OpsWorks") }
|
7
|
+
|
8
|
+
describe "#parameters" do
|
9
|
+
it { should have_parameter("NATInstanceType").with_type("String") }
|
10
|
+
|
11
|
+
it { should have_field("Default").with_value("m1.small").on("NATInstanceType") }
|
12
|
+
it { should have_field("AllowedValues").including("t1.micro").on("NATInstanceType") }
|
13
|
+
it { should have_field("ConstraintDescription").including("valid EC2 instance").on("NATInstanceType") }
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#mappings" do
|
17
|
+
it { should have_mapping("AWSNATAMI") }
|
18
|
+
it { should have_mapping("AWSInstanceType2Arch") }
|
19
|
+
it { should have_mapping("SubnetConfig") }
|
20
|
+
|
21
|
+
it { should have_mapping_key("us-east-1").including("AMI" => "ami-c6699baf").on("AWSNATAMI") }
|
22
|
+
it { should have_mapping_key("m1.medium").including("Arch" => "64").on("AWSInstanceType2Arch") }
|
23
|
+
it { should have_mapping_key("VPC").including("CIDR" => "10.0.0.0/16").on("SubnetConfig") }
|
24
|
+
it { should have_mapping_key("Public").including("CIDR" => "10.0.0.0/24").on("SubnetConfig") }
|
25
|
+
it { should have_mapping_key("Private").including("CIDR" => "10.0.1.0/24").on("SubnetConfig") }
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "#resources" do
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
$:<< File.expand_path("../../../lib", __FILE__)
|
2
|
+
|
3
|
+
require "chemtrail"
|
4
|
+
require "chemtrail/rspec"
|
5
|
+
|
6
|
+
Dir.glob(File.expand_path("../../lib/templates/**/*_template.rb", __FILE__)).each { |t| require t }
|
7
|
+
|
8
|
+
RSpec.configure do |config|
|
9
|
+
config.include Chemtrail::RSpec
|
10
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
11
|
+
config.run_all_when_everything_filtered = true
|
12
|
+
config.filter_run :focus
|
13
|
+
config.order = 'random'
|
14
|
+
end
|
15
|
+
|
data/lib/chemtrail/cli.rb
CHANGED
data/lib/chemtrail/mapping.rb
CHANGED
data/lib/chemtrail/parameter.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
class Chemtrail::Parameter
|
2
2
|
attr_reader :id, :type
|
3
3
|
|
4
|
-
def initialize(id, type,
|
4
|
+
def initialize(id, type, fields = {})
|
5
5
|
@id = id
|
6
6
|
@type = type
|
7
|
-
@
|
7
|
+
@fields = fields
|
8
8
|
end
|
9
9
|
|
10
|
-
def
|
11
|
-
@
|
10
|
+
def fields
|
11
|
+
@fields ||= {}
|
12
12
|
end
|
13
13
|
|
14
14
|
def to_reference
|
@@ -21,7 +21,7 @@ class Chemtrail::Parameter
|
|
21
21
|
{
|
22
22
|
id => {
|
23
23
|
"Type" => type
|
24
|
-
}.merge(
|
24
|
+
}.merge(fields)
|
25
25
|
}
|
26
26
|
end
|
27
27
|
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
require "chemtrail"
|
2
|
+
require "rspec/expectations"
|
3
|
+
|
4
|
+
module Chemtrail::RSpec
|
5
|
+
extend RSpec::Matchers::DSL
|
6
|
+
|
7
|
+
matcher :have_parameter do |parameter_id|
|
8
|
+
define_method :parameter_for do |actual|
|
9
|
+
actual.parameters.detect { |param| param.id == parameter_id }
|
10
|
+
end
|
11
|
+
|
12
|
+
define_method :matches_type? do |actual|
|
13
|
+
@type.nil? || parameter_for(actual).type == @type
|
14
|
+
end
|
15
|
+
|
16
|
+
match do |actual|
|
17
|
+
!parameter_for(actual).nil? && matches_type?(actual)
|
18
|
+
end
|
19
|
+
|
20
|
+
chain :with_type do |type|
|
21
|
+
@type = type
|
22
|
+
end
|
23
|
+
|
24
|
+
failure_message_for_should do |actual|
|
25
|
+
if parameter = parameter_for(actual)
|
26
|
+
%(expected parameter #{parameter_id.inspect} to have type #{@type.inspect}, but got #{parameter.type.inspect})
|
27
|
+
else
|
28
|
+
%(expected to find parameter #{parameter_id.inspect}, but got nothing)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
matcher :have_field do |field_name|
|
34
|
+
define_method :parameter_for do |actual|
|
35
|
+
actual.parameters.detect { |p| p.id == @parameter_id }
|
36
|
+
end
|
37
|
+
|
38
|
+
define_method :field_for do |parameter|
|
39
|
+
parameter.fields[field_name]
|
40
|
+
end
|
41
|
+
|
42
|
+
define_method :matches_value? do |field|
|
43
|
+
if @value
|
44
|
+
field == @value
|
45
|
+
elsif @included_value
|
46
|
+
field.include?(@included_value)
|
47
|
+
else
|
48
|
+
true
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
match do |actual|
|
53
|
+
parameter = parameter_for(actual)
|
54
|
+
field = field_for(parameter)
|
55
|
+
!parameter.nil? && !field.nil? && matches_value?(field)
|
56
|
+
end
|
57
|
+
|
58
|
+
chain :on do |parameter_id|
|
59
|
+
@parameter_id = parameter_id
|
60
|
+
end
|
61
|
+
|
62
|
+
chain :with_value do |value|
|
63
|
+
@value = value
|
64
|
+
end
|
65
|
+
|
66
|
+
chain :including do |value|
|
67
|
+
@included_value = value
|
68
|
+
end
|
69
|
+
|
70
|
+
failure_message_for_should do |actual|
|
71
|
+
if parameter = parameter_for(actual)
|
72
|
+
if field = field_for(parameter)
|
73
|
+
expected_field = @value || @included_value
|
74
|
+
%(expected parameter #{@parameter_id.inspect} field #{field_name.inspect} to have value #{expected_field.inspect}, but got #{field.inspect})
|
75
|
+
else
|
76
|
+
%(expected parameter #{@parameter_id.inspect} to have type #{field_name.inspect})
|
77
|
+
end
|
78
|
+
else
|
79
|
+
%(expected to find parameter #{@parameter_id.inspect}, but got nothing)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
matcher :have_mapping do |expected|
|
85
|
+
match { |actual| actual.mappings.any? { |m| m.id == expected } }
|
86
|
+
end
|
87
|
+
|
88
|
+
matcher :have_mapping_key do |entry_name|
|
89
|
+
define_method :mapping_for do |actual|
|
90
|
+
actual.mappings.detect { |m| m.id == @mapping_id }
|
91
|
+
end
|
92
|
+
|
93
|
+
define_method :entry_for do |mapping|
|
94
|
+
mapping.entries[entry_name]
|
95
|
+
end
|
96
|
+
|
97
|
+
define_method :matches_value? do |entry|
|
98
|
+
if @included_value
|
99
|
+
entry.values_at(*@included_value.keys) == @included_value.values
|
100
|
+
else
|
101
|
+
true
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
match do |actual|
|
106
|
+
mapping = mapping_for(actual)
|
107
|
+
entry = entry_for(mapping)
|
108
|
+
!mapping.nil? && !entry.nil? && matches_value?(entry)
|
109
|
+
end
|
110
|
+
|
111
|
+
chain :on do |mapping_id|
|
112
|
+
@mapping_id = mapping_id
|
113
|
+
end
|
114
|
+
|
115
|
+
chain :including do |value|
|
116
|
+
@included_value = value
|
117
|
+
end
|
118
|
+
|
119
|
+
failure_message_for_should do |actual|
|
120
|
+
if mapping = mapping_for(actual)
|
121
|
+
if entry = entry_for(mapping)
|
122
|
+
%(expected mapping #{@mapping_id.inspect} field #{entry_name.inspect} to have value #{@included_value.inspect}, but got #{entry.inspect})
|
123
|
+
else
|
124
|
+
%(expected mapping #{@mapping_id.inspect} to have type #{entry_name.inspect})
|
125
|
+
end
|
126
|
+
else
|
127
|
+
%(expected to find mapping #{@mapping_id.inspect}, but got nothing)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
data/lib/chemtrail/version.rb
CHANGED
@@ -5,8 +5,9 @@ describe Chemtrail::Cli do
|
|
5
5
|
|
6
6
|
describe "#list" do
|
7
7
|
it "lists available templates" do
|
8
|
-
|
9
|
-
|
8
|
+
got_tacos = false
|
9
|
+
Kernel.stub(:puts) { |string| got_tacos ||= (string == "tacos") }
|
10
|
+
expect { cli.list }.to change{ got_tacos }.to(true)
|
10
11
|
end
|
11
12
|
end
|
12
13
|
|
@@ -5,13 +5,19 @@ describe Chemtrail::Mapping do
|
|
5
5
|
|
6
6
|
describe "#to_hash" do
|
7
7
|
context "when there are no entries" do
|
8
|
-
its(:to_hash) { should
|
8
|
+
its(:to_hash) { should == {"atlas" => {}} }
|
9
9
|
end
|
10
10
|
|
11
11
|
context "when an entry has been added" do
|
12
|
-
before { mapping.entries[
|
12
|
+
before { mapping.entries[:teeth] = {} }
|
13
13
|
|
14
|
-
specify { mapping.to_hash["atlas"].should
|
14
|
+
specify { mapping.to_hash["atlas"].should == {teeth: {}} }
|
15
|
+
end
|
16
|
+
|
17
|
+
context "when an entry is passed into the initializer" do
|
18
|
+
subject(:mapping) { Chemtrail::Mapping.new("atlas", charles: {}) }
|
19
|
+
|
20
|
+
specify { mapping.to_hash["atlas"].should == {charles: {}} }
|
15
21
|
end
|
16
22
|
end
|
17
23
|
|
@@ -3,15 +3,15 @@ require "spec_helper"
|
|
3
3
|
describe Chemtrail::Parameter do
|
4
4
|
subject(:parameter) { Chemtrail::Parameter.new("parmesan", "String") }
|
5
5
|
|
6
|
-
describe "#
|
7
|
-
context "when there are no
|
8
|
-
its(:
|
6
|
+
describe "#fields" do
|
7
|
+
context "when there are no fields" do
|
8
|
+
its(:fields) { should be_empty }
|
9
9
|
end
|
10
10
|
|
11
11
|
context "when a specification has been passed into the initializer" do
|
12
12
|
subject(:parameter) { Chemtrail::Parameter.new("parmesan", "String", ok: "great") }
|
13
13
|
|
14
|
-
its(:
|
14
|
+
its(:fields) { should == {ok: "great"} }
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
@@ -24,7 +24,7 @@ describe Chemtrail::Parameter do
|
|
24
24
|
specify { parameter.to_hash["parmesan"].should include("Type" => "String") }
|
25
25
|
|
26
26
|
context "when there is a specification" do
|
27
|
-
before { parameter.
|
27
|
+
before { parameter.fields[:ducks] = "amazing" }
|
28
28
|
|
29
29
|
specify { parameter.to_hash["parmesan"].should include(ducks: "amazing") }
|
30
30
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chemtrail
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Doc Ritezel
|
@@ -99,6 +99,13 @@ files:
|
|
99
99
|
- README.md
|
100
100
|
- bin/chemtrail
|
101
101
|
- chemtrail.gemspec
|
102
|
+
- examples/.rspec
|
103
|
+
- examples/Guardfile
|
104
|
+
- examples/lib/templates/config/mappings.yml
|
105
|
+
- examples/lib/templates/config/parameters.yml
|
106
|
+
- examples/lib/templates/opsworks_vpc_template.rb
|
107
|
+
- examples/spec/lib/templates/opsworks_vpc_template_spec.rb
|
108
|
+
- examples/spec/spec_helper.rb
|
102
109
|
- lib/chemtrail.rb
|
103
110
|
- lib/chemtrail/class_name_inflector.rb
|
104
111
|
- lib/chemtrail/cli.rb
|
@@ -109,6 +116,7 @@ files:
|
|
109
116
|
- lib/chemtrail/property_list.rb
|
110
117
|
- lib/chemtrail/reference_presenter.rb
|
111
118
|
- lib/chemtrail/resource.rb
|
119
|
+
- lib/chemtrail/rspec.rb
|
112
120
|
- lib/chemtrail/section_presenter.rb
|
113
121
|
- lib/chemtrail/template.rb
|
114
122
|
- lib/chemtrail/version.rb
|