skywriter 1.0.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.
Files changed (154) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +8 -0
  5. data/CHANGES.md +5 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.md +22 -0
  8. data/README.md +139 -0
  9. data/Rakefile +7 -0
  10. data/lib/skywriter/function.rb +133 -0
  11. data/lib/skywriter/resource/auto_scaling/auto_scaling_group.rb +28 -0
  12. data/lib/skywriter/resource/auto_scaling/launch_configuration.rb +28 -0
  13. data/lib/skywriter/resource/auto_scaling/scaling_policy.rb +18 -0
  14. data/lib/skywriter/resource/auto_scaling/scheduled_action.rb +21 -0
  15. data/lib/skywriter/resource/auto_scaling/trigger.rb +26 -0
  16. data/lib/skywriter/resource/cloud_formation/authentication.rb +46 -0
  17. data/lib/skywriter/resource/cloud_formation/custom_resource.rb +17 -0
  18. data/lib/skywriter/resource/cloud_formation/stack.rb +15 -0
  19. data/lib/skywriter/resource/cloud_formation/wait_condition.rb +15 -0
  20. data/lib/skywriter/resource/cloud_formation/wait_condition_handle.rb +12 -0
  21. data/lib/skywriter/resource/cloud_front/distribution.rb +13 -0
  22. data/lib/skywriter/resource/cloud_watch/alarm.rb +27 -0
  23. data/lib/skywriter/resource/dynamo_db/table.rb +18 -0
  24. data/lib/skywriter/resource/ec2/customer_gateway.rb +16 -0
  25. data/lib/skywriter/resource/ec2/dhcp_options.rb +18 -0
  26. data/lib/skywriter/resource/ec2/eip.rb +14 -0
  27. data/lib/skywriter/resource/ec2/eip_association.rb +17 -0
  28. data/lib/skywriter/resource/ec2/instance.rb +34 -0
  29. data/lib/skywriter/resource/ec2/internet_gateway.rb +13 -0
  30. data/lib/skywriter/resource/ec2/network_acl.rb +14 -0
  31. data/lib/skywriter/resource/ec2/network_acl_entry.rb +20 -0
  32. data/lib/skywriter/resource/ec2/network_interface.rb +20 -0
  33. data/lib/skywriter/resource/ec2/network_interface_attachment.rb +16 -0
  34. data/lib/skywriter/resource/ec2/route.rb +17 -0
  35. data/lib/skywriter/resource/ec2/route_table.rb +14 -0
  36. data/lib/skywriter/resource/ec2/security_group.rb +17 -0
  37. data/lib/skywriter/resource/ec2/security_group_egress.rb +23 -0
  38. data/lib/skywriter/resource/ec2/security_group_ingress.rb +26 -0
  39. data/lib/skywriter/resource/ec2/subnet.rb +16 -0
  40. data/lib/skywriter/resource/ec2/subnet_network_acl_association.rb +14 -0
  41. data/lib/skywriter/resource/ec2/subnet_route_table_association.rb +14 -0
  42. data/lib/skywriter/resource/ec2/volume.rb +18 -0
  43. data/lib/skywriter/resource/ec2/volume_attachment.rb +15 -0
  44. data/lib/skywriter/resource/ec2/vpc.rb +17 -0
  45. data/lib/skywriter/resource/ec2/vpc_dhcp_options_association.rb +14 -0
  46. data/lib/skywriter/resource/ec2/vpc_gateway_attachment.rb +15 -0
  47. data/lib/skywriter/resource/ec2/vpn_connection.rb +17 -0
  48. data/lib/skywriter/resource/ec2/vpn_connection_route.rb +14 -0
  49. data/lib/skywriter/resource/ec2/vpn_gateway.rb +14 -0
  50. data/lib/skywriter/resource/ec2/vpn_gateway_route_propagation.rb +14 -0
  51. data/lib/skywriter/resource/elasti_cache/cache_cluster.rb +27 -0
  52. data/lib/skywriter/resource/elastic_beanstalk/application.rb +14 -0
  53. data/lib/skywriter/resource/elastic_beanstalk/application_version.rb +15 -0
  54. data/lib/skywriter/resource/elastic_beanstalk/configuration_template.rb +18 -0
  55. data/lib/skywriter/resource/elastic_beanstalk/environment.rb +21 -0
  56. data/lib/skywriter/resource/elastic_load_balancing/load_balancer.rb +25 -0
  57. data/lib/skywriter/resource/elasticache/parameter_group.rb +15 -0
  58. data/lib/skywriter/resource/elasticache/security_group.rb +13 -0
  59. data/lib/skywriter/resource/elasticache/security_group_ingress.rb +15 -0
  60. data/lib/skywriter/resource/elasticache/subnet_group.rb +14 -0
  61. data/lib/skywriter/resource/iam/access_key.rb +16 -0
  62. data/lib/skywriter/resource/iam/group.rb +15 -0
  63. data/lib/skywriter/resource/iam/instance_profile.rb +15 -0
  64. data/lib/skywriter/resource/iam/policy.rb +18 -0
  65. data/lib/skywriter/resource/iam/role.rb +13 -0
  66. data/lib/skywriter/resource/iam/user.rb +17 -0
  67. data/lib/skywriter/resource/iam/user_to_group_addition.rb +15 -0
  68. data/lib/skywriter/resource/logical_name_pointer.rb +11 -0
  69. data/lib/skywriter/resource/pointer.rb +23 -0
  70. data/lib/skywriter/resource/rds/db_instance.rb +37 -0
  71. data/lib/skywriter/resource/rds/db_parameter_group.rb +17 -0
  72. data/lib/skywriter/resource/rds/db_security_group.rb +17 -0
  73. data/lib/skywriter/resource/rds/db_security_group_ingress.rb +18 -0
  74. data/lib/skywriter/resource/rds/db_subnet_group.rb +16 -0
  75. data/lib/skywriter/resource/redshift/cluster.rb +37 -0
  76. data/lib/skywriter/resource/redshift/cluster_parameter_group.rb +16 -0
  77. data/lib/skywriter/resource/redshift/cluster_security_group.rb +14 -0
  78. data/lib/skywriter/resource/redshift/cluster_security_group_ingress.rb +17 -0
  79. data/lib/skywriter/resource/redshift/cluster_subnet_group.rb +15 -0
  80. data/lib/skywriter/resource/ref_pointer.rb +11 -0
  81. data/lib/skywriter/resource/route_53/record_set.rb +24 -0
  82. data/lib/skywriter/resource/route_53/record_set_group.rb +17 -0
  83. data/lib/skywriter/resource/s3/bucket.rb +17 -0
  84. data/lib/skywriter/resource/s3/bucket_policy.rb +15 -0
  85. data/lib/skywriter/resource/sdb/domain.rb +13 -0
  86. data/lib/skywriter/resource/sns/topic.rb +16 -0
  87. data/lib/skywriter/resource/sns/topic_policy.rb +15 -0
  88. data/lib/skywriter/resource/sqs/queue.rb +18 -0
  89. data/lib/skywriter/resource/sqs/queue_policy.rb +15 -0
  90. data/lib/skywriter/resource.rb +165 -0
  91. data/lib/skywriter/resource_property/README.md +64 -0
  92. data/lib/skywriter/resource_property/auto_scaling/block_device_mapping.rb +12 -0
  93. data/lib/skywriter/resource_property/auto_scaling/ebs_block_device.rb +17 -0
  94. data/lib/skywriter/resource_property/auto_scaling/notification_configuration.rb +11 -0
  95. data/lib/skywriter/resource_property/auto_scaling/tag.rb +15 -0
  96. data/lib/skywriter/resource_property/cloud_formation/resource_tag.rb +12 -0
  97. data/lib/skywriter/resource_property/cloud_front/cache_behavior.rb +14 -0
  98. data/lib/skywriter/resource_property/cloud_front/custom_origin.rb +11 -0
  99. data/lib/skywriter/resource_property/cloud_front/default_cache_behavior.rb +13 -0
  100. data/lib/skywriter/resource_property/cloud_front/distribution_config.rb +16 -0
  101. data/lib/skywriter/resource_property/cloud_front/forwarded_value.rb +13 -0
  102. data/lib/skywriter/resource_property/cloud_front/logging.rb +10 -0
  103. data/lib/skywriter/resource_property/cloud_front/origin.rb +12 -0
  104. data/lib/skywriter/resource_property/cloud_front/s3_origin.rb +9 -0
  105. data/lib/skywriter/resource_property/cloud_watch/metric_dimension.rb +10 -0
  106. data/lib/skywriter/resource_property/dynamo_db/attribute_definition.rb +12 -0
  107. data/lib/skywriter/resource_property/dynamo_db/global_secondary_index.rb +14 -0
  108. data/lib/skywriter/resource_property/dynamo_db/key_schema.rb +10 -0
  109. data/lib/skywriter/resource_property/dynamo_db/local_secondary_index.rb +13 -0
  110. data/lib/skywriter/resource_property/dynamo_db/projection.rb +12 -0
  111. data/lib/skywriter/resource_property/dynamo_db/provisioned_throughput.rb +10 -0
  112. data/lib/skywriter/resource_property/ec2/block_device_mapping.rb +12 -0
  113. data/lib/skywriter/resource_property/ec2/ebs_block_device.rb +15 -0
  114. data/lib/skywriter/resource_property/ec2/icmp.rb +10 -0
  115. data/lib/skywriter/resource_property/ec2/mount_point.rb +10 -0
  116. data/lib/skywriter/resource_property/ec2/network_interface.rb +18 -0
  117. data/lib/skywriter/resource_property/ec2/network_interface_association.rb +12 -0
  118. data/lib/skywriter/resource_property/ec2/network_interface_attachment.rb +10 -0
  119. data/lib/skywriter/resource_property/ec2/network_interface_group_item.rb +10 -0
  120. data/lib/skywriter/resource_property/ec2/network_interface_private_ip_specification.rb +10 -0
  121. data/lib/skywriter/resource_property/ec2/port_range.rb +10 -0
  122. data/lib/skywriter/resource_property/ec2/security_group_rule.rb +12 -0
  123. data/lib/skywriter/resource_property/ec2/tag.rb +10 -0
  124. data/lib/skywriter/resource_property/elastic_beanstalk/environment_tier.rb +11 -0
  125. data/lib/skywriter/resource_property/elastic_beanstalk/option_setting.rb +13 -0
  126. data/lib/skywriter/resource_property/elastic_beanstalk/source_bundle.rb +10 -0
  127. data/lib/skywriter/resource_property/elastic_beanstalk/source_configuration.rb +10 -0
  128. data/lib/skywriter/resource_property/elastic_load_balancing/app_cookie_stickiness_policy.rb +10 -0
  129. data/lib/skywriter/resource_property/elastic_load_balancing/health_check.rb +13 -0
  130. data/lib/skywriter/resource_property/elastic_load_balancing/lb_cookie_stickiness_policy.rb +10 -0
  131. data/lib/skywriter/resource_property/elastic_load_balancing/listener.rb +14 -0
  132. data/lib/skywriter/resource_property/elastic_load_balancing/policy.rb +13 -0
  133. data/lib/skywriter/resource_property/rds/security_group_rule.rb +12 -0
  134. data/lib/skywriter/resource_property/redshift/parameter.rb +10 -0
  135. data/lib/skywriter/resource_property/route53/alias_target.rb +10 -0
  136. data/lib/skywriter/resource_property/s3/website_configuration_policy.rb +16 -0
  137. data/lib/skywriter/resource_property/sns/subscription.rb +10 -0
  138. data/lib/skywriter/resource_property/sqs/redrive_policy.rb +10 -0
  139. data/lib/skywriter/resource_property.rb +57 -0
  140. data/lib/skywriter/template.rb +143 -0
  141. data/lib/skywriter/version.rb +3 -0
  142. data/lib/skywriter.rb +8 -0
  143. data/skywriter.gemspec +29 -0
  144. data/spec/skywriter/function_spec.rb +99 -0
  145. data/spec/skywriter/resource/cloud_formation/authentication_spec.rb +36 -0
  146. data/spec/skywriter/resource/cloud_formation/custom_resource_spec.rb +30 -0
  147. data/spec/skywriter/resource/logical_name_pointer_spec.rb +15 -0
  148. data/spec/skywriter/resource/ref_pointer_spec.rb +15 -0
  149. data/spec/skywriter/resource_property/ec2/security_group_rule_spec.rb +7 -0
  150. data/spec/skywriter/resource_property_spec.rb +153 -0
  151. data/spec/skywriter/resource_spec.rb +236 -0
  152. data/spec/skywriter/template_spec.rb +246 -0
  153. data/spec/spec_helper.rb +29 -0
  154. metadata +306 -0
@@ -0,0 +1,153 @@
1
+ require 'spec_helper'
2
+
3
+ describe Skywriter::ResourceProperty do
4
+ let(:resource_property_class) do
5
+ Class.new(Skywriter::ResourceProperty) do
6
+ property :FooBar
7
+ property :BazQux
8
+ end
9
+ end
10
+
11
+ let(:resource_class) do
12
+ class Skywriter::Resource::TestResource
13
+ include Skywriter::Resource
14
+
15
+ property :FooBar
16
+ end
17
+ Skywriter::Resource::TestResource
18
+ end
19
+
20
+
21
+ describe "#to_json" do
22
+ context "with pointer in resource property" do
23
+ let(:resource) do
24
+ resource_class.new("resource")
25
+ end
26
+
27
+ subject { resource_property_class.new(foo_bar: resource.as_pointer) }
28
+
29
+ it "doesn't explode with in resource property in a resource" do
30
+ expect { subject.to_json }.to_not raise_error
31
+ end
32
+ end
33
+ end
34
+
35
+ describe "#as_json" do
36
+ context "with missing properties" do
37
+ subject { resource_property_class.new(foo_bar: '1').as_json }
38
+
39
+ it "includes present properties" do
40
+ expect(subject).to have_key('FooBar')
41
+ end
42
+
43
+ it "excludes missing properties" do
44
+ expect(subject).to_not have_key('BazQux')
45
+ end
46
+ end
47
+
48
+ context "with nil properties" do
49
+ subject { resource_property_class.new(foo_bar: '1', baz_qux: nil).as_json }
50
+
51
+ it "includes present properties" do
52
+ expect(subject).to have_key('FooBar')
53
+ end
54
+
55
+ it "excludes nil properties" do
56
+ expect(subject).to_not have_key('BazQux')
57
+ end
58
+ end
59
+
60
+ context "with snake case symbol property names" do
61
+ subject { resource_property_class.new(foo_bar: 'baz').as_json }
62
+
63
+ it "sets value" do
64
+ expect(subject).to have_key('FooBar')
65
+ end
66
+ end
67
+
68
+ context "with snake case string property names" do
69
+ subject { resource_property_class.new('foo_bar' => 'baz').as_json }
70
+
71
+ it "sets value" do
72
+ expect(subject).to have_key('FooBar')
73
+ end
74
+ end
75
+
76
+ context "with CamelCase symbol property names" do
77
+ subject { resource_property_class.new(FooBar: 'baz').as_json }
78
+
79
+ it "sets value" do
80
+ expect(subject).to have_key('FooBar')
81
+ end
82
+ end
83
+
84
+ context "with CamelCase string property names" do
85
+ subject { resource_property_class.new('FooBar' => 'baz').as_json }
86
+
87
+ it "sets value" do
88
+ expect(subject).to have_key('FooBar')
89
+ end
90
+ end
91
+ end
92
+ end
93
+
94
+ describe "The implementation" do
95
+ [
96
+ Skywriter::ResourceProperty::AutoScaling::BlockDeviceMapping,
97
+ Skywriter::ResourceProperty::AutoScaling::EBSBlockDevice,
98
+ Skywriter::ResourceProperty::AutoScaling::NotificationConfiguration,
99
+ Skywriter::ResourceProperty::AutoScaling::Tag,
100
+ Skywriter::ResourceProperty::AutoScaling::EBSBlockDevice,
101
+ Skywriter::ResourceProperty::CloudFront::CacheBehavior,
102
+ Skywriter::ResourceProperty::CloudFront::ForwardedValue,
103
+ Skywriter::ResourceProperty::CloudFront::CustomOrigin,
104
+ Skywriter::ResourceProperty::CloudFront::DefaultCacheBehavior,
105
+ Skywriter::ResourceProperty::CloudFront::DistributionConfig,
106
+ Skywriter::ResourceProperty::CloudFront::Logging,
107
+ Skywriter::ResourceProperty::CloudFront::Origin,
108
+ Skywriter::ResourceProperty::CloudFront::S3Origin,
109
+ Skywriter::ResourceProperty::CloudWatch::MetricDimension,
110
+ Skywriter::ResourceProperty::DynamoDB::AttributeDefinition,
111
+ Skywriter::ResourceProperty::DynamoDB::GlobalSecondaryIndex,
112
+ Skywriter::ResourceProperty::DynamoDB::KeySchema,
113
+ Skywriter::ResourceProperty::DynamoDB::LocalSecondaryIndex,
114
+ Skywriter::ResourceProperty::DynamoDB::Projection,
115
+ Skywriter::ResourceProperty::DynamoDB::ProvisionedThroughput,
116
+ Skywriter::ResourceProperty::EC2::BlockDeviceMapping,
117
+ Skywriter::ResourceProperty::EC2::EBSBlockDevice,
118
+ Skywriter::ResourceProperty::EC2::ICMP,
119
+ Skywriter::ResourceProperty::EC2::MountPoint,
120
+ Skywriter::ResourceProperty::EC2::NetworkInterface,
121
+ Skywriter::ResourceProperty::EC2::NetworkInterfaceAssociation,
122
+ Skywriter::ResourceProperty::EC2::NetworkInterfaceAttachment,
123
+ Skywriter::ResourceProperty::EC2::NetworkInterfaceGroupItem,
124
+ Skywriter::ResourceProperty::EC2::NetworkInterfacePrivateIPSpecification,
125
+ Skywriter::ResourceProperty::EC2::PortRange,
126
+ Skywriter::ResourceProperty::EC2::SecurityGroupRule,
127
+ Skywriter::Resource::EC2::SecurityGroupEgress,
128
+ Skywriter::Resource::EC2::SecurityGroupIngress,
129
+ Skywriter::ResourceProperty::EC2::Tag,
130
+ Skywriter::ResourceProperty::ElasticBeanstalk::EnvironmentTier,
131
+ Skywriter::ResourceProperty::ElasticBeanstalk::OptionSetting,
132
+ Skywriter::ResourceProperty::ElasticBeanstalk::SourceBundle,
133
+ Skywriter::ResourceProperty::ElasticBeanstalk::SourceConfiguration,
134
+ Skywriter::ResourceProperty::ElasticLoadBalancing::AppCookieStickinessPolicy,
135
+ Skywriter::ResourceProperty::ElasticLoadBalancing::HealthCheck,
136
+ Skywriter::ResourceProperty::ElasticLoadBalancing::LBCookieStickinessPolicy,
137
+ Skywriter::ResourceProperty::ElasticLoadBalancing::Listener,
138
+ Skywriter::ResourceProperty::ElasticLoadBalancing::Policy,
139
+ Skywriter::ResourceProperty::Redshift::Parameter,
140
+ Skywriter::ResourceProperty::CloudFormation::ResourceTag,
141
+ Skywriter::ResourceProperty::RDS::SecurityGroupRule,
142
+ Skywriter::ResourceProperty::Route53::AliasTarget,
143
+ Skywriter::ResourceProperty::S3::WebsiteConfiguration,
144
+ Skywriter::ResourceProperty::SNS::Subscription,
145
+ Skywriter::ResourceProperty::SQS::RedrivePolicy,
146
+ ].each do |klass|
147
+ context "of #{klass.name}" do
148
+ it "inherits from resource property" do
149
+ expect(klass.new).to be_a(Skywriter::ResourceProperty)
150
+ end
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,236 @@
1
+ require 'spec_helper'
2
+
3
+ describe Skywriter::Resource do
4
+ let(:resource_class) do
5
+ class Skywriter::Resource::TestResource
6
+ include Skywriter::Resource
7
+
8
+ property :FooBar
9
+ end
10
+ Skywriter::Resource::TestResource
11
+ end
12
+
13
+ let(:child_class) do
14
+ class ChildClass < resource_class; end
15
+ ChildClass
16
+ end
17
+
18
+
19
+ describe "#as_json" do
20
+ it "serializes literal property values specified with snake case symbols" do
21
+ resource = resource_class.new('resource name', foo_bar: 'value')
22
+
23
+ expect(resource.as_json['resource name']['Properties']['FooBar']).to eq("value")
24
+ end
25
+
26
+ it "serializes literal property values specified with snake case strings" do
27
+ resource = resource_class.new('resource name', 'foo_bar' => 'value')
28
+
29
+ expect(resource.as_json['resource name']['Properties']['FooBar']).to eq("value")
30
+ end
31
+
32
+ it "serializes literal property values specified with CamelCase symbols" do
33
+ resource = resource_class.new('resource name', FooBar: 'value')
34
+
35
+ expect(resource.as_json['resource name']['Properties']['FooBar']).to eq("value")
36
+ end
37
+
38
+ it "serializes literal property values specified with CamelCase strings" do
39
+ resource = resource_class.new('resource name', 'FooBar' => 'value')
40
+
41
+ expect(resource.as_json['resource name']['Properties']['FooBar']).to eq("value")
42
+ end
43
+
44
+ it "sets type" do
45
+ resource = resource_class.new('resource name', foo_bar: 'value')
46
+
47
+ expect(resource.as_json['resource name']['Type']).to eq("AWS::TestResource")
48
+ end
49
+
50
+ it "sets type correctly in child classes" do
51
+ resource = child_class.new('resource name', foo_bar: 'value')
52
+
53
+ expect(resource.as_json['resource name']['Type']).to eq("AWS::TestResource")
54
+ end
55
+
56
+ it "sets additional dependencies" do
57
+ resource = resource_class.new('resource name', additional_dependencies: 'value')
58
+
59
+ expect(resource.as_json['resource name']['DependsOn']).to include('value')
60
+ end
61
+
62
+ it "sets depends on key if pointer passed" do
63
+ reference = resource_class.new('reference')
64
+ resource = resource_class.new('resource name', foo_bar: reference.as_pointer)
65
+
66
+ expect(resource.as_json['resource name']['DependsOn']).to include('reference')
67
+ end
68
+
69
+ it "merges magical and additional depedencies" do
70
+ reference = resource_class.new('reference')
71
+ resource = resource_class.new('resource name', foo_bar: reference.as_pointer, additional_dependencies: ['depends on'])
72
+
73
+ expect(resource.as_json['resource name']['DependsOn']).to include('reference')
74
+ expect(resource.as_json['resource name']['DependsOn']).to include('depends on')
75
+ end
76
+
77
+ it "removes duplicate depedencies" do
78
+ reference = resource_class.new('reference')
79
+ resource = resource_class.new('resource name', foo_bar: reference.as_pointer, additional_dependencies: ['reference', 'reference'])
80
+
81
+ expect(resource.as_json['resource name']['DependsOn']).to eq(['reference'])
82
+ end
83
+
84
+ it "creates a DeletionPolicy key" do
85
+ resource = resource_class.new('resource name', foo_bar: 'x', deletion_policy: 'Retain')
86
+
87
+ expect(resource.as_json['resource name']['DeletionPolicy']).to eq('Retain')
88
+ end
89
+
90
+ it "creates a Metadata key" do
91
+ resource = resource_class.new('resource name', foo_bar: 'x', metadata: { foo: 'bar', baz: 'qux' })
92
+
93
+ expect(resource.as_json['resource name']['Metadata']).to eq(foo: 'bar', baz: 'qux')
94
+ end
95
+
96
+ it "creates a UpdatePolicy key" do
97
+ resource = resource_class.new(
98
+ 'resource name',
99
+ foo_bar: 'x',
100
+ update_policy: {
101
+ AutoScalingRollingUpdate: {
102
+ MinInstancesInService: "1",
103
+ MaxBatchSize: "1",
104
+ PauseTime: "PT12M5S"
105
+ }
106
+ },
107
+ )
108
+
109
+ expect(resource.as_json['resource name']['UpdatePolicy']).to eq(
110
+ AutoScalingRollingUpdate: {
111
+ MinInstancesInService: "1",
112
+ MaxBatchSize: "1",
113
+ PauseTime: "PT12M5S"
114
+ }
115
+ )
116
+ end
117
+ end
118
+
119
+ describe "#register_dependency" do
120
+ it "adds logical name to dependency list" do
121
+ resource = resource_class.new('resource')
122
+ resource.register_dependency(double(logical_name: 'logical name'))
123
+
124
+ expect(resource.as_json['resource']['DependsOn']).to include('logical name')
125
+ end
126
+ end
127
+
128
+ describe "#as_pointer" do
129
+ context "with no args" do
130
+ subject { resource_class.new('resource name').as_pointer }
131
+
132
+ it "returns a reference" do
133
+ expect(subject).to be_a(Skywriter::Resource::RefPointer)
134
+ end
135
+ end
136
+
137
+ context "when asked for a ref" do
138
+ subject { resource_class.new('resource name').as_pointer(with: :ref) }
139
+
140
+ it "returns a logical name" do
141
+ expect(subject).to be_a(Skywriter::Resource::RefPointer)
142
+ end
143
+ end
144
+
145
+ context "when asked for a logical name" do
146
+ subject { resource_class.new('resource name').as_pointer(with: :logical_name) }
147
+
148
+ it "returns a logical name" do
149
+ expect(subject).to be_a(Skywriter::Resource::LogicalNamePointer)
150
+ end
151
+ end
152
+ end
153
+ end
154
+
155
+ describe "The implementation" do
156
+ [
157
+ Skywriter::Resource::AutoScaling::AutoScalingGroup,
158
+ Skywriter::Resource::AutoScaling::LaunchConfiguration,
159
+ Skywriter::Resource::AutoScaling::ScalingPolicy,
160
+ Skywriter::Resource::AutoScaling::ScheduledAction,
161
+ Skywriter::Resource::AutoScaling::Trigger,
162
+ Skywriter::Resource::CloudFormation::Stack,
163
+ Skywriter::Resource::CloudFormation::WaitConditionHandle,
164
+ Skywriter::Resource::CloudFormation::WaitCondition,
165
+ Skywriter::Resource::CloudFront::Distribution,
166
+ Skywriter::Resource::CloudWatch::Alarm,
167
+ Skywriter::Resource::DynamoDB::Table,
168
+ Skywriter::Resource::EC2::CustomerGateway,
169
+ Skywriter::Resource::EC2::DHCPOptions,
170
+ Skywriter::Resource::EC2::EIPAssociation,
171
+ Skywriter::Resource::EC2::EIP,
172
+ Skywriter::Resource::EC2::Instance,
173
+ Skywriter::Resource::EC2::InternetGateway,
174
+ Skywriter::Resource::EC2::NetworkAclEntry,
175
+ Skywriter::Resource::EC2::NetworkAcl,
176
+ Skywriter::Resource::EC2::NetworkInterfaceAttachment,
177
+ Skywriter::Resource::EC2::NetworkInterface,
178
+ Skywriter::Resource::EC2::Route,
179
+ Skywriter::Resource::EC2::RouteTable,
180
+ Skywriter::Resource::EC2::SecurityGroup,
181
+ Skywriter::Resource::EC2::SubnetNetworkAclAssociation,
182
+ Skywriter::Resource::EC2::SubnetRouteTableAssociation,
183
+ Skywriter::Resource::EC2::Subnet,
184
+ Skywriter::Resource::EC2::VolumeAttachment,
185
+ Skywriter::Resource::EC2::Volume,
186
+ Skywriter::Resource::EC2::VPCDHCPOptionsAssociation,
187
+ Skywriter::Resource::EC2::VPCGatewayAttachment,
188
+ Skywriter::Resource::EC2::VPC,
189
+ Skywriter::Resource::EC2::VPNConnectionRoute,
190
+ Skywriter::Resource::EC2::VPNConnection,
191
+ Skywriter::Resource::EC2::VPNGatewayRoutePropagation,
192
+ Skywriter::Resource::EC2::VPNGateway,
193
+ Skywriter::Resource::ElastiCache::CacheCluster,
194
+ Skywriter::Resource::ElastiCache::ParameterGroup,
195
+ Skywriter::Resource::ElastiCache::SecurityGroup,
196
+ Skywriter::Resource::ElastiCache::SecurityGroupIngress,
197
+ Skywriter::Resource::ElastiCache::SubnetGroup,
198
+ Skywriter::Resource::ElasticBeanstalk::Application,
199
+ Skywriter::Resource::ElasticBeanstalk::ApplicationVersion,
200
+ Skywriter::Resource::ElasticBeanstalk::ConfigurationTemplate,
201
+ Skywriter::Resource::ElasticBeanstalk::Environment,
202
+ Skywriter::Resource::ElasticLoadBalancing::LoadBalancer,
203
+ Skywriter::Resource::IAM::AccessKey,
204
+ Skywriter::Resource::IAM::Group,
205
+ Skywriter::Resource::IAM::InstanceProfile,
206
+ Skywriter::Resource::IAM::Policy,
207
+ Skywriter::Resource::IAM::Role,
208
+ Skywriter::Resource::IAM::User,
209
+ Skywriter::Resource::IAM::UserToGroupAddition,
210
+ Skywriter::Resource::Redshift::Cluster,
211
+ Skywriter::Resource::Redshift::ClusterParameterGroup,
212
+ Skywriter::Resource::Redshift::ClusterSecurityGroup,
213
+ Skywriter::Resource::Redshift::ClusterSecurityGroupIngress,
214
+ Skywriter::Resource::Redshift::ClusterSubnetGroup,
215
+ Skywriter::Resource::RDS::DBInstance,
216
+ Skywriter::Resource::RDS::DBParameterGroup,
217
+ Skywriter::Resource::RDS::DBSubnetGroup,
218
+ Skywriter::Resource::RDS::DBSecurityGroup,
219
+ Skywriter::Resource::RDS::DBSecurityGroupIngress,
220
+ Skywriter::Resource::Route53::RecordSet,
221
+ Skywriter::Resource::Route53::RecordSetGroup,
222
+ Skywriter::Resource::S3::Bucket,
223
+ Skywriter::Resource::S3::BucketPolicy,
224
+ Skywriter::Resource::SDB::Domain,
225
+ Skywriter::Resource::SNS::TopicPolicy,
226
+ Skywriter::Resource::SNS::Topic,
227
+ Skywriter::Resource::SQS::Queue,
228
+ Skywriter::Resource::SQS::QueuePolicy
229
+ ].each do |klass|
230
+ context "of #{klass.name}" do
231
+ it "is a resource" do
232
+ expect(klass.new('name')).to be_a(Skywriter::Resource)
233
+ end
234
+ end
235
+ end
236
+ end
@@ -0,0 +1,246 @@
1
+ require 'spec_helper'
2
+
3
+ describe Skywriter::Template do
4
+ describe "#to_json" do
5
+ it "doesn't explode" do
6
+ expect { Skywriter::Template.new.to_json }.to_not raise_error
7
+ end
8
+
9
+ end
10
+
11
+ describe "#as_json" do
12
+ context "with an empty object" do
13
+ let(:template) { Skywriter::Template.new }
14
+ let(:hash) { template.as_json }
15
+
16
+ it "uses default FormatVersion value" do
17
+ expect(hash['FormatVersion']).to eq('2010-09-09')
18
+ end
19
+
20
+ it "does not have a Description key" do
21
+ expect(hash).to_not have_key('Description')
22
+ end
23
+
24
+ it "has a Parameters key" do
25
+ expect(hash).to have_key('Parameters')
26
+ end
27
+
28
+ it "has a Mappings key" do
29
+ expect(hash).to have_key('Mappings')
30
+ end
31
+
32
+ it "has a Conditions key" do
33
+ expect(hash).to have_key('Conditions')
34
+ end
35
+
36
+ it "has a Resources key" do
37
+ expect(hash).to have_key('Resources')
38
+ end
39
+
40
+ it "has a Outputs key" do
41
+ expect(hash).to have_key('Outputs')
42
+ end
43
+ end
44
+
45
+ context "with format version" do
46
+ let(:template) { Skywriter::Template.new(:format_version => 'foo') }
47
+ let(:hash) { template.as_json }
48
+
49
+ it "has the passed FormatVersion value" do
50
+ expect(hash['FormatVersion']).to eq('foo')
51
+ end
52
+ end
53
+
54
+ context "with description" do
55
+ let(:template) { Skywriter::Template.new(:description => 'foo') }
56
+ let(:hash) { template.as_json }
57
+
58
+ it "has a Description key" do
59
+ expect(hash).to have_key('Description')
60
+ end
61
+ end
62
+
63
+ context "with array of Resources" do
64
+ let(:resource) do
65
+ double("Resource", as_json: {"Resource" => {}})
66
+ end
67
+
68
+ let(:other_resource) do
69
+ double("OtherResource", as_json: {"OtherResource" => {}})
70
+ end
71
+
72
+ let(:template) do
73
+ Skywriter::Template.new(
74
+ resources: [resource, other_resource]
75
+ )
76
+ end
77
+
78
+ let(:hash) { template.as_json }
79
+
80
+ it "includes resources" do
81
+ expect(hash['Resources']).to have_key('Resource')
82
+ expect(hash['Resources']).to have_key('OtherResource')
83
+ end
84
+ end
85
+
86
+ context "with resources hash" do
87
+ let(:template) do
88
+ Skywriter::Template.new(
89
+ resources: {"foo" => "bar"}
90
+ )
91
+ end
92
+
93
+ it "includes resources hash" do
94
+ expect(template.as_json['Resources']).to eq("foo" => "bar")
95
+ end
96
+ end
97
+
98
+ context "with snake case symbol key name" do
99
+ let(:template) do
100
+ Skywriter::Template.new(
101
+ resources: {"foo" => "bar"}
102
+ )
103
+ end
104
+
105
+ it "sets value" do
106
+ expect(template.as_json['Resources']).to eq("foo" => "bar")
107
+ end
108
+ end
109
+
110
+ context "with snake case string key name" do
111
+ let(:template) do
112
+ Skywriter::Template.new(
113
+ 'resources' => {"foo" => "bar"}
114
+ )
115
+ end
116
+
117
+ it "sets value" do
118
+ expect(template.as_json['Resources']).to eq("foo" => "bar")
119
+ end
120
+ end
121
+
122
+ context "with CameCase symbol key name" do
123
+ let(:template) do
124
+ Skywriter::Template.new(
125
+ Resources: {"foo" => "bar"}
126
+ )
127
+ end
128
+
129
+ it "sets value" do
130
+ expect(template.as_json['Resources']).to eq("foo" => "bar")
131
+ end
132
+ end
133
+
134
+ context "with CamelCase string key name" do
135
+ let(:template) do
136
+ Skywriter::Template.new(
137
+ 'Resources' => {"foo" => "bar"}
138
+ )
139
+ end
140
+
141
+ it "sets value" do
142
+ expect(template.as_json['Resources']).to eq("foo" => "bar")
143
+ end
144
+ end
145
+ end
146
+
147
+ describe "#merge" do
148
+ let(:resource) do
149
+ double("Resource", as_json: {'foo' => 'bar'})
150
+ end
151
+
152
+ let(:template) do
153
+ Skywriter::Template.new(
154
+ parameters: {'foo' => 'bar'},
155
+ mappings: {'foo' => 'bar'},
156
+ conditions: {'foo' => 'bar'},
157
+ resources: [resource],
158
+ outputs: {'foo' => 'bar'},
159
+ )
160
+ end
161
+
162
+ context "with another template containing conflicting values" do
163
+ let(:other_template) { Skywriter::Template.new(format_version: 'other format version') }
164
+
165
+ it "raises a MergeError" do
166
+ expect { template.merge(other_template) }.to raise_error(Skywriter::Template::MergeError)
167
+ end
168
+ end
169
+
170
+ context "with another template containing disjoint values" do
171
+ let(:other_template) { Skywriter::Template.new(description: 'description') }
172
+
173
+ it "sets the value on returned template" do
174
+ expect(template.merge(other_template).description).to eq('description')
175
+ end
176
+ end
177
+
178
+ # Disjoint
179
+ #
180
+ context "where the values of 'other' are disjoint" do
181
+ let(:disjoint_resource) do
182
+ double("OtherResource", as_json: {'baz' => 'qux'})
183
+ end
184
+
185
+ let(:disjoint_template) do
186
+ Skywriter::Template.new(
187
+ parameters: {'baz' => 'qux'},
188
+ mappings: {'baz' => 'qux'},
189
+ conditions: {'baz' => 'qux'},
190
+ resources: [disjoint_resource],
191
+ outputs: {'baz' => 'qux'},
192
+ )
193
+ end
194
+
195
+ subject { template.merge(disjoint_template) }
196
+
197
+ ['Parameters', 'Mappings', 'Conditions', 'Resources', 'Outputs'].each do |meth|
198
+ it "sets value of #{meth} to 'other' merged into 'self'" do
199
+ disjoint_template.as_json[meth].each_key do |other_key|
200
+ expect(subject.as_json[meth]).to have_key(other_key)
201
+ end
202
+
203
+ template.as_json[meth].each_key do |template_key|
204
+ expect(subject.as_json[meth]).to have_key(template_key)
205
+ end
206
+ end
207
+ end
208
+ end
209
+
210
+ # Duplicate
211
+ #
212
+ context "where the values of 'other' are duplicated" do
213
+ subject { template.merge(template) }
214
+
215
+ [:parameters, :mappings, :conditions, :resources, :outputs].each do |meth|
216
+ it "sets value of #{meth} to value from 'self'" do
217
+ template.send(meth).each_key do |other_key|
218
+ expect(subject.send(meth)).to have_key(other_key)
219
+ end
220
+ end
221
+ end
222
+ end
223
+
224
+ # Conflicting
225
+ #
226
+ context "where the values of 'other' are conflicting" do
227
+ let(:conflicting_resource) do
228
+ double("ConflictingResource", as_json: {'foo' => 'not bar'})
229
+ end
230
+
231
+ let(:conflicting_template) do
232
+ Skywriter::Template.new(
233
+ parameters: {'foo' => 'not bar'},
234
+ mappings: {'foo' => 'not bar'},
235
+ conditions: {'foo' => 'not bar'},
236
+ resources: [conflicting_resource],
237
+ outputs: {'foo' => 'not bar'},
238
+ )
239
+ end
240
+
241
+ it "raises an exception" do
242
+ expect { template.merge(conflicting_template) }.to raise_error(Skywriter::Template::MergeError)
243
+ end
244
+ end
245
+ end
246
+ end
@@ -0,0 +1,29 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+ require 'pry'
8
+
9
+ require 'skywriter'
10
+
11
+ RSpec.configure do |config|
12
+ config.treat_symbols_as_metadata_keys_with_true_values = true
13
+ config.run_all_when_everything_filtered = true
14
+ config.filter_run :focus
15
+
16
+ config.expect_with :rspec do |expectations|
17
+ expectations.syntax = :expect
18
+ end
19
+
20
+ config.mock_with :rspec do |mocks|
21
+ mocks.syntax = :expect
22
+ end
23
+
24
+ # Run specs in random order to surface order dependencies. If you find an
25
+ # order dependency and want to debug it, you can fix the order by providing
26
+ # the seed, which is printed after each run.
27
+ # --seed 1234
28
+ config.order = 'random'
29
+ end