chemtrail 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e54ce07e90240967020fa7a8dc856b944338f78e
4
- data.tar.gz: 132975f191f9df48d66606e27648852cb29a8608
3
+ metadata.gz: 0b457fc52081b5875c31d1d124429aa6d438b31a
4
+ data.tar.gz: 77706788871003cba5307760765b907f986a80e4
5
5
  SHA512:
6
- metadata.gz: 0cd2a647db49fb8ecef0863955670ea9dadbec2087e68a561376fbd2c4ca5ea3e55eb883fa404a8d17e2f1b180c5dfbc12d49e42b6d1f5d87e88bdf37f541c25
7
- data.tar.gz: 22f400b9b20b389bec87ba1951f374cb37cd16a5c72359c8debe4913db6d7528cd3106477fb9ea659873cee5d270d06bd9a18d757a6e6155f2dbf57a73a078d0
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
@@ -1,6 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
  lib = File.expand_path("../../lib", __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require "chemtrail"
5
4
  require "chemtrail/cli"
6
5
  Chemtrail::Cli.start
data/examples/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ guard :rspec do
4
+ watch(%r{^spec/.+_spec\.rb$})
5
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
6
+ watch('spec/spec_helper.rb') { "spec" }
7
+ end
8
+
@@ -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
@@ -1,5 +1,6 @@
1
1
  require "thor"
2
2
  require "json"
3
+ require "chemtrail"
3
4
 
4
5
  class Chemtrail::Cli < Thor
5
6
  default_task :list
@@ -3,8 +3,9 @@ require "chemtrail/reference_presenter"
3
3
  class Chemtrail::Mapping
4
4
  attr_reader :id
5
5
 
6
- def initialize(id)
6
+ def initialize(id, entries = nil)
7
7
  @id = id
8
+ @entries = entries
8
9
  end
9
10
 
10
11
  def entries
@@ -1,14 +1,14 @@
1
1
  class Chemtrail::Parameter
2
2
  attr_reader :id, :type
3
3
 
4
- def initialize(id, type, specifications = {})
4
+ def initialize(id, type, fields = {})
5
5
  @id = id
6
6
  @type = type
7
- @specifications = specifications
7
+ @fields = fields
8
8
  end
9
9
 
10
- def specifications
11
- @specifications ||= {}
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(specifications)
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
@@ -1,3 +1,3 @@
1
1
  module Chemtrail
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -5,8 +5,9 @@ describe Chemtrail::Cli do
5
5
 
6
6
  describe "#list" do
7
7
  it "lists available templates" do
8
- Kernel.should_receive(:puts).with("tacos")
9
- cli.list
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 have_key "atlas" }
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["teeth"] = {} }
12
+ before { mapping.entries[:teeth] = {} }
13
13
 
14
- specify { mapping.to_hash["atlas"].should have_key "teeth" }
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 "#specifications" do
7
- context "when there are no specifications" do
8
- its(:specifications) { should be_empty }
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(:specifications) { should == {ok: "great"} }
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.specifications[:ducks] = "amazing" }
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.2.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