convection 0.2.33 → 0.2.34.pre.beta.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -0
  3. data/CONTRIBUTING.md +22 -0
  4. data/README.md +15 -202
  5. data/Rakefile +3 -0
  6. data/docs/adding-new-resource-coverage.md +265 -0
  7. data/docs/canceling-stack-updates.md +5 -0
  8. data/docs/deleting-stacks.md +5 -0
  9. data/docs/getting-started.md +904 -0
  10. data/docs/index.md +69 -0
  11. data/docs/pygment.css +62 -0
  12. data/docs/relationship-to-cloudformation.md +51 -0
  13. data/docs/stacks.md +86 -0
  14. data/docs/template.html +130 -0
  15. data/example/getting-started-guide/Cloudfile +12 -0
  16. data/example/getting-started-guide/vpc.rb +74 -0
  17. data/example/stacks/Cloudfile +12 -0
  18. data/example/stacks/tasks/lookup_vpc_task.rb +28 -0
  19. data/example/stacks/templates/vpc.rb +14 -0
  20. data/lib/convection.rb +6 -0
  21. data/lib/convection/control/cloud.rb +1 -0
  22. data/lib/convection/control/stack.rb +126 -15
  23. data/lib/convection/model/cloudfile.rb +3 -0
  24. data/lib/convection/model/template/resource/aws_cloudfront_distribution.rb +24 -30
  25. data/lib/convection/model/template/resource/aws_ec2_dhcp_options.rb +38 -0
  26. data/lib/convection/model/template/resource/aws_ec2_security_group.rb +24 -2
  27. data/lib/convection/model/template/resource/aws_iam_user.rb +17 -3
  28. data/lib/convection/model/template/resource/aws_s3_bucket.rb +9 -3
  29. data/lib/convection/model/template/resource/aws_s3_bucket_policy.rb +10 -3
  30. data/lib/convection/model/template/resource/aws_sns_topic.rb +6 -3
  31. data/lib/convection/model/template/resource/aws_sns_topic_policy.rb +10 -3
  32. data/lib/convection/model/template/resource/aws_sqs_queue.rb +5 -3
  33. data/lib/convection/model/template/resource/aws_sqs_queue_policy.rb +10 -3
  34. data/spec/convection/model/template/resource/ec2_dhcp_options_spec.rb +55 -0
  35. data/yard_extensions.rb +4 -0
  36. data/yard_extensions/properties_handler.rb +30 -0
  37. data/yard_extensions/type_handler.rb +188 -0
  38. metadata +27 -23
  39. data/example/Cloudfile +0 -13
  40. data/example/deprecated/elb.rb +0 -27
  41. data/example/deprecated/iam_access_key.rb +0 -18
  42. data/example/deprecated/iam_group.rb +0 -31
  43. data/example/deprecated/iam_role.rb +0 -52
  44. data/example/deprecated/iam_user.rb +0 -31
  45. data/example/deprecated/rds.rb +0 -70
  46. data/example/deprecated/s3.rb +0 -13
  47. data/example/deprecated/sqs.rb +0 -32
  48. data/example/deprecated/vpc.rb +0 -85
  49. data/example/instances.rb +0 -93
  50. data/example/output/vpc.json +0 -335
  51. data/example/security-groups.rb +0 -77
  52. data/example/sqs-queue/Cloudfile +0 -19
  53. data/example/sqs-queue/README.md +0 -12
  54. data/example/trust_cloudtrail.rb +0 -24
  55. data/example/vpc.rb +0 -143
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 70262a473c642f00cc51b9077ca02c2617194320
4
- data.tar.gz: bba7acb1a3242c6b354a384e9924f33c8a69ce13
3
+ metadata.gz: 837d14e5ddd6639c86b5c3bb0cf6dd5396919125
4
+ data.tar.gz: 2079fa841463566dd1b7eacd62a104f1e70d627e
5
5
  SHA512:
6
- metadata.gz: df10a72ab338b4e6dec65b93942a0577d53db0d88bbe30e820a1536918192a8adee745b016c4067e3973a1bffccac2ee3cf9016d0930e3a52774185e7bca1edc
7
- data.tar.gz: 61f8a1e4761e464a1a3a18139c02caa49839d93fb89be9cc68affe13d4baa9dc2bfbbd47cdcea31e442d4e1d154e6878da50dae25304fa09ce6f7850949eb677
6
+ metadata.gz: 0b3f343979e83ddb138d30d97ae57f5a8da0ee6b90346b9d7966a9b0ccbb8ee7f545eb0536695ad053a5f74cd6309d83b21e31436808bbcf1ec26d9acee9e5a0
7
+ data.tar.gz: b39d1d06d1a03e41db3fa78cab20d33a2c2f9be94541896af8b3973f5c71486bee3d0c4df4385b0024ca7643980129830210a8f0e6889e242bbdd28a10f776dc
@@ -0,0 +1 @@
1
+ -e yard_extensions.rb
@@ -0,0 +1,22 @@
1
+ # Contributing to Convection
2
+ The following document is a list of guidelines for making contributing to the Convection project.
3
+
4
+ ## Table Of Contents
5
+ * [Developing](#developing)
6
+ * [Branches](#branches)
7
+
8
+ ## Developing
9
+ ### Branches
10
+ We strive to use [Semantic Versioning](http://semver.org) as much as possible for convection.
11
+
12
+ ### `master`
13
+ **NOTE**: The `master` branch is fully supported by the convection maintainers.
14
+
15
+ The latest and greatest code that we intend to release to Rubygems is merged into this branch.
16
+ Today that code happens to be part of the `v0.2.x` minor version since we have not deemed convection feature
17
+ complete (we'll release a `v1.0.0` release at that point).
18
+
19
+ Backwards incompatible changes until this time *may* be added by bumping the **minor** (not major) version of
20
+ the project. These will be explicitly called out in the release notes for the version that introduced them and if
21
+ possible a deprecation message and compatibility will be kept making users aware of a potential the breaking change in
22
+ the future.
data/README.md CHANGED
@@ -3,15 +3,8 @@ _A fully generic, modular DSL for AWS CloudFormation_
3
3
 
4
4
  This gem aims to provide a reusable model for AWS CloudFormation in Ruby. It exposes a DSL for template definition, and a simple, decoupled abstraction of a CloudFormation Stack to compile and apply templates.
5
5
 
6
- ## Branches
7
- We strive to use [Semantic Versioning](http://semver.org) as much as possible for convection.
8
-
9
- ### `master`
10
- **NOTE**: The `master` branch is fully supported by the convection maintainers.
11
-
12
- The latest and greatest code that we intend to release to Rubygems is merged into this branch.
13
- Today that code happens to be part of the `v0.2.x` minor version since we have not deemed convection feature complete (we'll release a `v1.0.0` release at that point).
14
- Backwards incompatible changes until this time *may* be added by bumping the **minor** (not major) version of the project. These will be explicitly called out in the release notes for the version that introduced them and if possible a deprecation message and compatibility will be kept making users aware of a potential the breaking change in the future.
6
+ ## Contributing
7
+ Please read our [Contributing guidelines](CONTRIBUTING.md) for more information on contributing to Convection.
15
8
 
16
9
  ## Installation
17
10
  Add this line to your application's Gemfile:
@@ -28,204 +21,24 @@ Or install it yourself as:
28
21
 
29
22
  $ gem install convection
30
23
 
31
- ## Template DSL
32
- The core DSL provides all of the available JSON primatives of CloudFormation in the form of ruby methods. These primatives are used to compose higher-order methods for commonly used definitions:
33
-
34
- ```ruby
35
- require 'convection'
36
-
37
- ## Create a new instance of Convection::Model::Template
38
- Convection.template do
39
- description 'An example template'
40
-
41
- parameter 'InstanceSize' do
42
- type 'String'
43
- description 'Instance Size'
44
- default 'm3.medium'
45
-
46
- allow 'm3.medium'
47
- allow 'm3.large'
48
- allow 'm3.xlarge'
49
- end
50
-
51
- ## The `resource` method can be used to define any resource
52
- ## supported by CloudFormation: See http://docs.aws.amazon.com/\
53
- ## AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html
54
- resource 'AnEC2Instance' do
55
- type 'AWS::EC2::Instance'
56
- property 'AvailabilityZone', 'us-east-1a'
57
- property 'ImageId', 'ami-76e27e1e' ## Ubuntu 14.04 hvm:ebs
58
- property 'KeyName', 'test'
59
- property 'SecurityGroupIds', ['sg-dd733c41', 'sg-dd738df3']
60
- property 'Tags', [{
61
- 'Key' => 'Name',
62
- 'Value' => 'test-1'
63
- }]
64
-
65
- property 'DisableApiTermination', false
66
- end
67
-
68
- ## `ec2_instnce` extends `resource`. The following results in JSON
69
- ## identical to that of Resource[AnEC2Instance]
70
- ec2_instance 'AnOtherInstance' do
71
- availability_zone 'us-east-1a'
72
- image_id 'ami-76e27e1e'
73
- key_name 'test'
74
-
75
- security_group 'sg-dd733c41'
76
- security_group 'sg-dd738df3'
77
-
78
- tag 'Name', 'test-2'
79
-
80
- ## All of the methods of the `resource` primative are available in
81
- ## its children:
82
- property 'DisableApiTermination', false
83
- end
84
- end.to_json
85
- ```
86
-
87
- ### Parameters
88
- http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html
89
-
90
- ```ruby
91
- parameter 'InstanceType' do
92
- type 'String'
93
- description 'Set the thing\'s instance flavor'
94
- default 'm3.medium'
95
-
96
- allow 'm3.medium'
97
- allow 'm3.large'
98
- allow 'm3.xlarge'
99
- end
100
- ```
101
-
102
- ### Mappings
103
- http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/mappings-section-structure.html
104
-
105
- ```ruby
106
- mapping 'RegionalAMIs' do
107
- item 'us-east-1', 'hvm', 'ami-76e27e1e'
108
- item 'us-west-1', 'hvm', 'ami-d5180890'
109
- item 'us-east-1', 'pv', 'ami-64e27e0c'
110
- item 'us-west-1', 'pv', 'ami-c5180880'
111
- end
112
- ```
113
-
114
- ### Conditions
115
- http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/conditions-section-structure.html
24
+ ##CLI Commands
25
+ ###### Converging
26
+ - To converge all stacks in your cloudfile run `convection converge`. If you provide the name of your stack as a additional argument such as `convection converge my-stack-name` then all stacks above and including the stack you specified will be converged.
116
27
 
117
- ```ruby
118
- condition 'ThisCondition' do
119
- fn_equals( fn_ref('SomeParameter'), 'value_x' )
120
- end
121
-
122
- condition 'ThatCondition' do
123
- fn_or(
124
- fn_equals( fn_ref('SomeParameter'), 'value_y' ),
125
- fn_equals( fn_ref('SomeParameter'), 'value_z' )
126
- )
127
- end
128
- ```
129
-
130
- ### Resources
131
- http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resources-section-structure.html
132
-
133
- ```ruby
134
- resource 'AnInstance' do
135
- type 'AWS::EC2::Instance'
136
-
137
- ## Optional condition reference
138
- condition 'SomeCondition'
139
-
140
- ## Add Resource Properties
141
- property 'AvailabilityZone', 'us-east-1a'
142
- property 'ImageId', 'ami-76e27e1e' ## Ubuntu 14.04 hvm:ebs
143
- property 'KeyName', 'test'
144
- ...
145
- end
146
- ```
147
-
148
- Using a condition to set a resource property:
149
-
150
- ```ruby
151
- resource 'MySQL' do
152
- type 'AWS::RDS::DBInstance'
153
- ...
154
- property 'Iops', fn_if('ThisCondition', '1000', fn_ref('AWS::NoValue'))
155
- ...
156
- end
157
- ```
158
-
159
- ### Outputs
160
- http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html
161
-
162
- ```ruby
163
- output 'SomeName' do
164
- description 'An Important Attribute'
165
- value get_att('Resource', 'Attribute')
166
-
167
- ## Optional condition reference
168
- condition 'SomeCondition'
169
- end
170
- ```
171
-
172
- ### Intrinsic Functions
173
- http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html
174
-
175
- All intrinsic functions are available as helper methods:
176
-
177
- * base64(content)
178
- * fn_and(conditions...)
179
- * fn_equals(value_1, value_2)
180
- * fn_if(condition, value_true, value_false)
181
- * fn_not(condition)
182
- * fn_or(conditions...)
183
- * find_in_map(map_name, key_1, key_2)
184
- * get_att(resource, attr_name)
185
- * get_azs(region)
186
- * join(delimiter, values...)
187
- * select(index, objects...)
188
- * fn_ref(resource)
189
-
190
- ```ruby
191
- ec2_instance "TestInstanceFoo#{ i }" do
192
- image_id find_in_map('RegionalAMIs', fn_ref('AWS::Region'), 'hvm')
193
- instance_type 'm3.medium'
194
- key_name find_in_map('RegionalKeys', fn_ref('AWS::Region'), 'test')
195
- security_group fn_ref('LousySecurityGroup')
196
- subnet fn_ref("TestSubnet")
197
- end
198
- ```
28
+ ###### Diff
29
+ - To display diff between your local changes and the version of your stack in cloud formation of your changes run `convection diff`.
199
30
 
200
- ## Stack Control
201
- The `Stack` class provides a state wrapper for CloudFormation Stacks. It tracks the state of the managed stack, and creates/updates accordingly. `Stack` is also region-aware, and can be used within a template to define resources that depend upon availability-zones or other region-specific neuances that cannot be represented as maps or require iteration.
31
+ ###### Help
32
+ - To print out a list of available cli options with their descriptions run `convection help`.
202
33
 
203
- ### Class `Convection::Control::Stack`
204
- * `.new(name, template, options = {})`
205
- * _name_ CloudFormation Stack name
206
- * _template_ Instance of Convection::Model::Template
207
- * _options_ - Hash
208
- * _region_ - AWS region, format `us-east-1`. Default us-east-1
209
- * _credentials_ - Optional instance of AWS::Credentials. See the [AWS-SDK Documentation](http://docs.aws.amazon.com/sdkforruby/api/frames.html)
210
- * _parameters_ - Stack parameters, as a `Hash` of `{ key => value }`
211
- * _tags_ - Stack tags, as a `Hash` of `{ key => value }`
212
- * _on_failure_ - Create failure action. Default `DELETE`
213
- * _capabilities_ - See the [AWS-SDK Documentation](http://docs.aws.amazon.com/sdkforruby/api/Aws/CloudFormation/Client.html#create_stack-instance_method)
214
- * Additional options will be passed directly to `create_stack` and `update_stack`
34
+ ###### Print
35
+ - To print out the cloud formation template for a specific stack run `convection print my-stack-name`.
215
36
 
216
- * `#status` - Returns the stack status
217
- * `#exist?` - Returns true if the stack exists and is not in a DELETED state
218
- * `#complete?`
219
- * `#rollback?`
220
- * `#fail?`
221
- * `#render` - Populates the provided template with any environment data included in the stack (e.g. availability zones). Returns a `Hash`
222
- * `#to_json` - Render template and transofrm to a pretty-generated JSON `String`
223
- * `#apply` - Renter template and create/update CloudFormation Stack
224
- * `#delete` - Delete CloudFormation Stack
225
- * `#availability_zones(&block)` - Return an array of strings representing the region's availability zones. Provided codeblock will be called for each AZ.
37
+ ###### Validate
38
+ - To validate your stack is not missing a required resource run `convection validate my-stack-name`.
226
39
 
227
- ## Futures
228
- *
40
+ ## Documentation
41
+ We highly recommend consulting the [getting started guide](./docs/getting-started.md) for a in depth walk through on how to to set up your project and create and deploy a stack. Example stacks and resources are available in the [convection/example](https://github.com/rapid7/convection/tree/master/example) folder
229
42
 
230
43
  ## License
231
44
  _Copyright (c) 2015 John Manero, Rapid7 LLC._
data/Rakefile CHANGED
@@ -1,8 +1,11 @@
1
1
  require 'bundler/gem_tasks'
2
2
  require 'rubocop/rake_task'
3
3
  require 'rspec/core/rake_task'
4
+ require 'yard'
5
+ require_relative './yard_extensions'
4
6
 
5
7
  RuboCop::RakeTask.new
6
8
  RSpec::Core::RakeTask.new(:spec)
9
+ YARD::Rake::YardocTask.new
7
10
 
8
11
  task :default => [:spec, :rubocop]
@@ -0,0 +1,265 @@
1
+ #Adding a CloudFormation resource to Convection
2
+ This guide will document how convection support for AWS::EC2::DHCPOptions was added. This example can be followed to add coverage for other CloudFormation resources
3
+
4
+ 1) Create a new class `convection/lib/convection/model/template/resource/aws_ec2_dhcp_options.rb` See the example below.
5
+ ```ruby
6
+ require_relative '../resource'
7
+
8
+ module Convection
9
+ module Model
10
+ class Template
11
+ class Resource
12
+ ##
13
+ # AWS::EC2::DHCPOptions
14
+ ##
15
+ class EC2DHCPOptions < Resource
16
+ type 'AWS::EC2::DHCPOptions'
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ ```
23
+ 2) Go to the CloudFormation resource documentation and use that as a guide for how you will define the resource properties. Viewing the [DHCPOptions] (http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-dhcp-options.html) api doc we can see that we have several resource properties we will need to handle.
24
+ ```json
25
+ {
26
+ "Type" : "AWS::EC2::DHCPOptions",
27
+ "Properties" : {
28
+ "DomainName" : String,
29
+ "DomainNameServers" : [ String, ... ],
30
+ "NetbiosNameServers" : [ String, ... ],
31
+ "NetbiosNodeType" : Number,
32
+ "NtpServers" : [ String, ... ],
33
+ "Tags" : [ Resource Tag, ... ]
34
+ }
35
+ }
36
+ ```
37
+ 3) Lets define the properties. Map the json key value pairs to ruby. `"DomainName" : String` in json will be defined in our template as `property :domain_name, 'DomainName'`. So with our first property added our new convection resource class will look like
38
+ ```ruby
39
+ require_relative '../resource'
40
+
41
+ module Convection
42
+ module Model
43
+ class Template
44
+ class Resource
45
+ ##
46
+ # AWS::EC2::DHCPOptions
47
+ ##
48
+ class EC2DHCPOptions < Resource
49
+ type 'AWS::EC2::DHCPOptions'
50
+ property :domain_name, 'DomainName'
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ ```
57
+ 4) You have probably noticed that some of these parameters expect a string array. For those we will add `:type => :list`. See below
58
+ ```ruby
59
+ require_relative '../resource'
60
+
61
+ module Convection
62
+ module Model
63
+ class Template
64
+ class Resource
65
+ ##
66
+ # AWS::EC2::DHCPOptions
67
+ ##
68
+ class EC2DHCPOptions < Resource
69
+ type 'AWS::EC2::DHCPOptions'
70
+ property :domain_name, 'DomainName'
71
+ property :domain_name_servers, 'DomainNameServers', :type => :list
72
+ property :netbios_name_servers, 'NetbiosNameServers', :type => :list
73
+ property :netbios_node_type, 'NetbiosNodeType'
74
+ property :ntp_servers, 'NtpServers', :type => :list
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+ ```
81
+ 5) To add tag support to the resource add the below block and include
82
+ ```ruby
83
+ include Model::Mixin::Taggable
84
+
85
+ def render(*args)
86
+ super.tap do |resource|
87
+ render_tags(resource)
88
+ end
89
+ end
90
+ ```
91
+ 6) The completed class should look like the below. Once you are finished developing the class add a yard doc example.
92
+ ```ruby
93
+ require_relative '../resource'
94
+
95
+ module Convection
96
+ module Model
97
+ class Template
98
+ class Resource
99
+ ##
100
+ # AWS::EC2::DHCPOptions
101
+ #
102
+ # @example
103
+ # ec2_dhcp_options 'TestOptions' do
104
+ # domain_name 'example.com'
105
+ # domain_name_servers '10.0.0.1', '10.0.0.2'
106
+ # netbios_name_servers '10.0.0.1', '10.0.0.2'
107
+ # netbios_node_type 1
108
+ # ntp_servers '10.0.0.1', '10.0.0.2'
109
+ # tag 'Name', 'Test'
110
+ # end
111
+ ##
112
+ class EC2DHCPOptions < Resource
113
+ include Model::Mixin::Taggable
114
+ type 'AWS::EC2::DHCPOptions'
115
+ property :domain_name, 'DomainName'
116
+ property :domain_name_servers, 'DomainNameServers', :type => :list
117
+ property :netbios_name_servers, 'NetbiosNameServers', :type => :list
118
+ property :netbios_node_type, 'NetbiosNodeType'
119
+ property :ntp_servers, 'NtpServers', :type => :list
120
+
121
+ def render(*args)
122
+ super.tap do |resource|
123
+ render_tags(resource)
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
131
+ ```
132
+ 7) Unit Tests! Adding tests for resources is simple, create a new test class. `convection/spec/convection/model/template/resource/ec2_dhcp_options_spec.rb`
133
+ 8) Set up the basic structure of the class.
134
+ ```ruby
135
+ require 'spec_helper'
136
+
137
+ class Convection::Model::Template::Resource
138
+ describe DHCPOptions do
139
+ let(:template) do
140
+ Convection.template do
141
+
142
+
143
+ end
144
+ end
145
+
146
+ end
147
+ end
148
+ ```
149
+ 9) Add the mock template. Below is a example
150
+ ```ruby
151
+ require 'spec_helper'
152
+
153
+ class Convection::Model::Template::Resource
154
+ describe DHCPOptions do
155
+ let(:template) do
156
+ Convection.template do
157
+
158
+ ec2_dhcp_options 'TestOptions' do
159
+ domain_name 'example.com'
160
+ domain_name_servers '10.0.0.1', '10.0.0.2'
161
+ netbios_name_servers '10.0.0.1', '10.0.0.2'
162
+ netbios_node_type 1
163
+ ntp_servers '10.0.0.1', '10.0.0.2'
164
+ end
165
+ end
166
+ end
167
+
168
+ end
169
+ end
170
+ ```
171
+ 10) Lets add some helper methods to get retrieve our template parameters. See below, NOTE we added the `subject` block and `template_json` method.
172
+ ```ruby
173
+ require 'spec_helper'
174
+
175
+ class Convection::Model::Template::Resource
176
+ describe EC2DHCPOptions do
177
+ let(:template) do
178
+ Convection.template do
179
+
180
+ ec2_dhcp_options 'TestOptions' do
181
+ domain_name 'example.com'
182
+ domain_name_servers '10.0.0.1', '10.0.0.2'
183
+ netbios_name_servers '10.0.0.1', '10.0.0.2'
184
+ netbios_node_type 1
185
+ ntp_servers '10.0.0.1', '10.0.0.2'
186
+ end
187
+ end
188
+ end
189
+
190
+ subject do
191
+ template_json
192
+ .fetch('Resources')
193
+ .fetch('TestOptions')
194
+ .fetch('Properties')
195
+ end
196
+
197
+
198
+ private
199
+
200
+ def template_json
201
+ JSON.parse(template.to_json)
202
+ end
203
+ end
204
+ end
205
+ ```
206
+ 11) Test time, below is our complete spec file with test for the defined parameters. Note in the test where we reference values in the subject object `subject['DomainName']` the hash key we use is the one set in our property block `property :domain_name, 'DomainName'`.
207
+ ```ruby
208
+ require 'spec_helper'
209
+
210
+ class Convection::Model::Template::Resource
211
+ describe EC2DHCPOptions do
212
+ let(:template) do
213
+ Convection.template do
214
+
215
+ ec2_dhcp_options 'TestOptions' do
216
+ domain_name 'example.com'
217
+ domain_name_servers '10.0.0.1', '10.0.0.2'
218
+ netbios_name_servers '10.0.0.1', '10.0.0.2'
219
+ netbios_node_type 1
220
+ ntp_servers '10.0.0.1', '10.0.0.2'
221
+ tag 'Name', 'Test'
222
+ end
223
+ end
224
+ end
225
+
226
+ subject do
227
+ template_json
228
+ .fetch('Resources')
229
+ .fetch('TestOptions')
230
+ .fetch('Properties')
231
+ end
232
+
233
+ it 'sets the DomainName' do
234
+ expect(subject['DomainName']).to eq('example.com')
235
+ end
236
+
237
+ it 'sets the DomainNameServers' do
238
+ expect(subject['DomainNameServers']).to match_array(['10.0.0.1', '10.0.0.2'])
239
+ end
240
+
241
+ it 'sets the NetbiosNameServers' do
242
+ expect(subject['NetbiosNameServers']).to match_array(['10.0.0.1', '10.0.0.2'])
243
+ end
244
+
245
+ it 'sets the NetbiosNodeType' do
246
+ expect(subject['NetbiosNodeType']).to eq(1)
247
+ end
248
+
249
+ it 'sets the NtpServers' do
250
+ expect(subject['NtpServers']).to match_array(['10.0.0.1', '10.0.0.2'])
251
+ end
252
+
253
+ it 'sets tags' do
254
+ expect(subject['Tags']).to include(hash_including('Key' => 'Name', 'Value' => 'Test'))
255
+ end
256
+
257
+ private
258
+
259
+ def template_json
260
+ JSON.parse(template.to_json)
261
+ end
262
+ end
263
+ end
264
+
265
+ ```