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.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.rspec +2 -0
- data/.travis.yml +8 -0
- data/CHANGES.md +5 -0
- data/Gemfile +4 -0
- data/LICENSE.md +22 -0
- data/README.md +139 -0
- data/Rakefile +7 -0
- data/lib/skywriter/function.rb +133 -0
- data/lib/skywriter/resource/auto_scaling/auto_scaling_group.rb +28 -0
- data/lib/skywriter/resource/auto_scaling/launch_configuration.rb +28 -0
- data/lib/skywriter/resource/auto_scaling/scaling_policy.rb +18 -0
- data/lib/skywriter/resource/auto_scaling/scheduled_action.rb +21 -0
- data/lib/skywriter/resource/auto_scaling/trigger.rb +26 -0
- data/lib/skywriter/resource/cloud_formation/authentication.rb +46 -0
- data/lib/skywriter/resource/cloud_formation/custom_resource.rb +17 -0
- data/lib/skywriter/resource/cloud_formation/stack.rb +15 -0
- data/lib/skywriter/resource/cloud_formation/wait_condition.rb +15 -0
- data/lib/skywriter/resource/cloud_formation/wait_condition_handle.rb +12 -0
- data/lib/skywriter/resource/cloud_front/distribution.rb +13 -0
- data/lib/skywriter/resource/cloud_watch/alarm.rb +27 -0
- data/lib/skywriter/resource/dynamo_db/table.rb +18 -0
- data/lib/skywriter/resource/ec2/customer_gateway.rb +16 -0
- data/lib/skywriter/resource/ec2/dhcp_options.rb +18 -0
- data/lib/skywriter/resource/ec2/eip.rb +14 -0
- data/lib/skywriter/resource/ec2/eip_association.rb +17 -0
- data/lib/skywriter/resource/ec2/instance.rb +34 -0
- data/lib/skywriter/resource/ec2/internet_gateway.rb +13 -0
- data/lib/skywriter/resource/ec2/network_acl.rb +14 -0
- data/lib/skywriter/resource/ec2/network_acl_entry.rb +20 -0
- data/lib/skywriter/resource/ec2/network_interface.rb +20 -0
- data/lib/skywriter/resource/ec2/network_interface_attachment.rb +16 -0
- data/lib/skywriter/resource/ec2/route.rb +17 -0
- data/lib/skywriter/resource/ec2/route_table.rb +14 -0
- data/lib/skywriter/resource/ec2/security_group.rb +17 -0
- data/lib/skywriter/resource/ec2/security_group_egress.rb +23 -0
- data/lib/skywriter/resource/ec2/security_group_ingress.rb +26 -0
- data/lib/skywriter/resource/ec2/subnet.rb +16 -0
- data/lib/skywriter/resource/ec2/subnet_network_acl_association.rb +14 -0
- data/lib/skywriter/resource/ec2/subnet_route_table_association.rb +14 -0
- data/lib/skywriter/resource/ec2/volume.rb +18 -0
- data/lib/skywriter/resource/ec2/volume_attachment.rb +15 -0
- data/lib/skywriter/resource/ec2/vpc.rb +17 -0
- data/lib/skywriter/resource/ec2/vpc_dhcp_options_association.rb +14 -0
- data/lib/skywriter/resource/ec2/vpc_gateway_attachment.rb +15 -0
- data/lib/skywriter/resource/ec2/vpn_connection.rb +17 -0
- data/lib/skywriter/resource/ec2/vpn_connection_route.rb +14 -0
- data/lib/skywriter/resource/ec2/vpn_gateway.rb +14 -0
- data/lib/skywriter/resource/ec2/vpn_gateway_route_propagation.rb +14 -0
- data/lib/skywriter/resource/elasti_cache/cache_cluster.rb +27 -0
- data/lib/skywriter/resource/elastic_beanstalk/application.rb +14 -0
- data/lib/skywriter/resource/elastic_beanstalk/application_version.rb +15 -0
- data/lib/skywriter/resource/elastic_beanstalk/configuration_template.rb +18 -0
- data/lib/skywriter/resource/elastic_beanstalk/environment.rb +21 -0
- data/lib/skywriter/resource/elastic_load_balancing/load_balancer.rb +25 -0
- data/lib/skywriter/resource/elasticache/parameter_group.rb +15 -0
- data/lib/skywriter/resource/elasticache/security_group.rb +13 -0
- data/lib/skywriter/resource/elasticache/security_group_ingress.rb +15 -0
- data/lib/skywriter/resource/elasticache/subnet_group.rb +14 -0
- data/lib/skywriter/resource/iam/access_key.rb +16 -0
- data/lib/skywriter/resource/iam/group.rb +15 -0
- data/lib/skywriter/resource/iam/instance_profile.rb +15 -0
- data/lib/skywriter/resource/iam/policy.rb +18 -0
- data/lib/skywriter/resource/iam/role.rb +13 -0
- data/lib/skywriter/resource/iam/user.rb +17 -0
- data/lib/skywriter/resource/iam/user_to_group_addition.rb +15 -0
- data/lib/skywriter/resource/logical_name_pointer.rb +11 -0
- data/lib/skywriter/resource/pointer.rb +23 -0
- data/lib/skywriter/resource/rds/db_instance.rb +37 -0
- data/lib/skywriter/resource/rds/db_parameter_group.rb +17 -0
- data/lib/skywriter/resource/rds/db_security_group.rb +17 -0
- data/lib/skywriter/resource/rds/db_security_group_ingress.rb +18 -0
- data/lib/skywriter/resource/rds/db_subnet_group.rb +16 -0
- data/lib/skywriter/resource/redshift/cluster.rb +37 -0
- data/lib/skywriter/resource/redshift/cluster_parameter_group.rb +16 -0
- data/lib/skywriter/resource/redshift/cluster_security_group.rb +14 -0
- data/lib/skywriter/resource/redshift/cluster_security_group_ingress.rb +17 -0
- data/lib/skywriter/resource/redshift/cluster_subnet_group.rb +15 -0
- data/lib/skywriter/resource/ref_pointer.rb +11 -0
- data/lib/skywriter/resource/route_53/record_set.rb +24 -0
- data/lib/skywriter/resource/route_53/record_set_group.rb +17 -0
- data/lib/skywriter/resource/s3/bucket.rb +17 -0
- data/lib/skywriter/resource/s3/bucket_policy.rb +15 -0
- data/lib/skywriter/resource/sdb/domain.rb +13 -0
- data/lib/skywriter/resource/sns/topic.rb +16 -0
- data/lib/skywriter/resource/sns/topic_policy.rb +15 -0
- data/lib/skywriter/resource/sqs/queue.rb +18 -0
- data/lib/skywriter/resource/sqs/queue_policy.rb +15 -0
- data/lib/skywriter/resource.rb +165 -0
- data/lib/skywriter/resource_property/README.md +64 -0
- data/lib/skywriter/resource_property/auto_scaling/block_device_mapping.rb +12 -0
- data/lib/skywriter/resource_property/auto_scaling/ebs_block_device.rb +17 -0
- data/lib/skywriter/resource_property/auto_scaling/notification_configuration.rb +11 -0
- data/lib/skywriter/resource_property/auto_scaling/tag.rb +15 -0
- data/lib/skywriter/resource_property/cloud_formation/resource_tag.rb +12 -0
- data/lib/skywriter/resource_property/cloud_front/cache_behavior.rb +14 -0
- data/lib/skywriter/resource_property/cloud_front/custom_origin.rb +11 -0
- data/lib/skywriter/resource_property/cloud_front/default_cache_behavior.rb +13 -0
- data/lib/skywriter/resource_property/cloud_front/distribution_config.rb +16 -0
- data/lib/skywriter/resource_property/cloud_front/forwarded_value.rb +13 -0
- data/lib/skywriter/resource_property/cloud_front/logging.rb +10 -0
- data/lib/skywriter/resource_property/cloud_front/origin.rb +12 -0
- data/lib/skywriter/resource_property/cloud_front/s3_origin.rb +9 -0
- data/lib/skywriter/resource_property/cloud_watch/metric_dimension.rb +10 -0
- data/lib/skywriter/resource_property/dynamo_db/attribute_definition.rb +12 -0
- data/lib/skywriter/resource_property/dynamo_db/global_secondary_index.rb +14 -0
- data/lib/skywriter/resource_property/dynamo_db/key_schema.rb +10 -0
- data/lib/skywriter/resource_property/dynamo_db/local_secondary_index.rb +13 -0
- data/lib/skywriter/resource_property/dynamo_db/projection.rb +12 -0
- data/lib/skywriter/resource_property/dynamo_db/provisioned_throughput.rb +10 -0
- data/lib/skywriter/resource_property/ec2/block_device_mapping.rb +12 -0
- data/lib/skywriter/resource_property/ec2/ebs_block_device.rb +15 -0
- data/lib/skywriter/resource_property/ec2/icmp.rb +10 -0
- data/lib/skywriter/resource_property/ec2/mount_point.rb +10 -0
- data/lib/skywriter/resource_property/ec2/network_interface.rb +18 -0
- data/lib/skywriter/resource_property/ec2/network_interface_association.rb +12 -0
- data/lib/skywriter/resource_property/ec2/network_interface_attachment.rb +10 -0
- data/lib/skywriter/resource_property/ec2/network_interface_group_item.rb +10 -0
- data/lib/skywriter/resource_property/ec2/network_interface_private_ip_specification.rb +10 -0
- data/lib/skywriter/resource_property/ec2/port_range.rb +10 -0
- data/lib/skywriter/resource_property/ec2/security_group_rule.rb +12 -0
- data/lib/skywriter/resource_property/ec2/tag.rb +10 -0
- data/lib/skywriter/resource_property/elastic_beanstalk/environment_tier.rb +11 -0
- data/lib/skywriter/resource_property/elastic_beanstalk/option_setting.rb +13 -0
- data/lib/skywriter/resource_property/elastic_beanstalk/source_bundle.rb +10 -0
- data/lib/skywriter/resource_property/elastic_beanstalk/source_configuration.rb +10 -0
- data/lib/skywriter/resource_property/elastic_load_balancing/app_cookie_stickiness_policy.rb +10 -0
- data/lib/skywriter/resource_property/elastic_load_balancing/health_check.rb +13 -0
- data/lib/skywriter/resource_property/elastic_load_balancing/lb_cookie_stickiness_policy.rb +10 -0
- data/lib/skywriter/resource_property/elastic_load_balancing/listener.rb +14 -0
- data/lib/skywriter/resource_property/elastic_load_balancing/policy.rb +13 -0
- data/lib/skywriter/resource_property/rds/security_group_rule.rb +12 -0
- data/lib/skywriter/resource_property/redshift/parameter.rb +10 -0
- data/lib/skywriter/resource_property/route53/alias_target.rb +10 -0
- data/lib/skywriter/resource_property/s3/website_configuration_policy.rb +16 -0
- data/lib/skywriter/resource_property/sns/subscription.rb +10 -0
- data/lib/skywriter/resource_property/sqs/redrive_policy.rb +10 -0
- data/lib/skywriter/resource_property.rb +57 -0
- data/lib/skywriter/template.rb +143 -0
- data/lib/skywriter/version.rb +3 -0
- data/lib/skywriter.rb +8 -0
- data/skywriter.gemspec +29 -0
- data/spec/skywriter/function_spec.rb +99 -0
- data/spec/skywriter/resource/cloud_formation/authentication_spec.rb +36 -0
- data/spec/skywriter/resource/cloud_formation/custom_resource_spec.rb +30 -0
- data/spec/skywriter/resource/logical_name_pointer_spec.rb +15 -0
- data/spec/skywriter/resource/ref_pointer_spec.rb +15 -0
- data/spec/skywriter/resource_property/ec2/security_group_rule_spec.rb +7 -0
- data/spec/skywriter/resource_property_spec.rb +153 -0
- data/spec/skywriter/resource_spec.rb +236 -0
- data/spec/skywriter/template_spec.rb +246 -0
- data/spec/spec_helper.rb +29 -0
- metadata +306 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module Skywriter
|
|
2
|
+
class ResourceProperty
|
|
3
|
+
module ElasticLoadBalancing
|
|
4
|
+
class HealthCheck < Skywriter::ResourceProperty
|
|
5
|
+
property :HealthyThreshold
|
|
6
|
+
property :Interval
|
|
7
|
+
property :Target
|
|
8
|
+
property :Timeout
|
|
9
|
+
property :UnhealthyThreshold
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module Skywriter
|
|
2
|
+
class ResourceProperty
|
|
3
|
+
module ElasticLoadBalancing
|
|
4
|
+
class Listener < Skywriter::ResourceProperty
|
|
5
|
+
property :InstancePort
|
|
6
|
+
property :InstanceProtocol
|
|
7
|
+
property :LoadBalancerPort
|
|
8
|
+
property :PolicyNames
|
|
9
|
+
property :Protocol
|
|
10
|
+
property :SSLCertificateId
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module Skywriter
|
|
2
|
+
class ResourceProperty
|
|
3
|
+
module ElasticLoadBalancing
|
|
4
|
+
class Policy < Skywriter::ResourceProperty
|
|
5
|
+
property :Attributes
|
|
6
|
+
property :InstancePorts
|
|
7
|
+
property :LoadBalancerPorts
|
|
8
|
+
property :PolicyName
|
|
9
|
+
property :PolicyType
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module Skywriter
|
|
2
|
+
class ResourceProperty
|
|
3
|
+
module S3
|
|
4
|
+
class WebsiteConfiguration < Skywriter::ResourceProperty
|
|
5
|
+
property :IndexDocument
|
|
6
|
+
property :ErrorDocument
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# This attribute looks like it should be in the 'CloudFormation' namespace, but it's actually
|
|
11
|
+
# and embedded property of a resource in the 'S3' namespace
|
|
12
|
+
module CloudFormation
|
|
13
|
+
WebsiteConfiguration = ::Skywriter::ResourceProperty::S3::WebsiteConfiguration
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module Skywriter
|
|
2
|
+
class ResourceProperty
|
|
3
|
+
# Declare a ResourceProperty property
|
|
4
|
+
#
|
|
5
|
+
# @param name [Symbol] The property name as it exists in the AWS documentation
|
|
6
|
+
def self.property(name)
|
|
7
|
+
property_definitions << PropertyDefinition.new(name)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# @param [Hash] options Options hash. Valid values depend on the implementing class - see the AWS documentation
|
|
11
|
+
# at http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-product-property-reference.html
|
|
12
|
+
# for details
|
|
13
|
+
def initialize(options = {})
|
|
14
|
+
@options = options.freeze
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Returns a JSON-able hash representing the Resource
|
|
18
|
+
#
|
|
19
|
+
# @return [Hash] A JSON-able hash
|
|
20
|
+
#
|
|
21
|
+
def as_json(*)
|
|
22
|
+
@as_json ||= property_definitions.each_with_object({}) do |property_definition, hash|
|
|
23
|
+
if (value = property_value(property_definition))
|
|
24
|
+
hash[property_definition.name] = value
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
attr_reader :options
|
|
32
|
+
|
|
33
|
+
def self.property_definitions
|
|
34
|
+
@property_definitions ||= []
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def property_value(property_definition)
|
|
38
|
+
options[property_definition.key.to_sym] ||
|
|
39
|
+
options[property_definition.key.to_s] ||
|
|
40
|
+
options[property_definition.name.to_sym] ||
|
|
41
|
+
options[property_definition.name.to_s]
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def property_definitions
|
|
45
|
+
self.class.property_definitions
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
class PropertyDefinition
|
|
50
|
+
attr_reader :name, :key
|
|
51
|
+
|
|
52
|
+
def initialize(name)
|
|
53
|
+
@name = name.to_s
|
|
54
|
+
@key = name.to_s.underscore.to_sym
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
module Skywriter
|
|
2
|
+
# CloudFormation Template
|
|
3
|
+
#
|
|
4
|
+
# Represents a CloudFormation template.
|
|
5
|
+
#
|
|
6
|
+
# @example
|
|
7
|
+
# parameters = {"foo" => "bar"}
|
|
8
|
+
# webserver = Skywriter::Resource::EC2::Instance.new('MyWebserver')
|
|
9
|
+
# load_balancer = Skywriter::Resource::ElasticLoadBalancing::LoadBalancer.new('MyLoadBalancer')
|
|
10
|
+
#
|
|
11
|
+
# template = Skywriter::Template.new(
|
|
12
|
+
# description: "My Template",
|
|
13
|
+
# parameters: parameters,
|
|
14
|
+
# resources: [webserver, load_balancer]
|
|
15
|
+
# )
|
|
16
|
+
#
|
|
17
|
+
# AWS::CloudFormation.new.stacks.create('my-stack', template.to_json)
|
|
18
|
+
#
|
|
19
|
+
class Template
|
|
20
|
+
class MergeError < StandardError; end
|
|
21
|
+
|
|
22
|
+
attr_reader :format_version, :description
|
|
23
|
+
attr_reader :parameters, :mappings, :conditions, :resources, :outputs
|
|
24
|
+
|
|
25
|
+
# Constructor
|
|
26
|
+
#
|
|
27
|
+
# See the AWS Documentation for details on the meaning of these parameters:
|
|
28
|
+
# http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/concept-template.html
|
|
29
|
+
#
|
|
30
|
+
# @param format_version [String] The AWS CloudFormation template version
|
|
31
|
+
# @param description [String] The stack description
|
|
32
|
+
# @param parameters [Hash] A hash of parameters
|
|
33
|
+
# @param mappings [Hash] A hash of mappings
|
|
34
|
+
# @param conditions [Hash] A hash of condition
|
|
35
|
+
# @param resources [Hash, Array<Skywriter::Resource>] Either a hash of
|
|
36
|
+
# resources or an array of objects whose classwhich include
|
|
37
|
+
# Skywriter::Resource, for example Skywriter::Resource::EC2::Instance.
|
|
38
|
+
# @param outputs [Hash] A hash of outputs
|
|
39
|
+
def initialize(options = {})
|
|
40
|
+
@format_version = (options[:format_version] || '2010-09-09').freeze
|
|
41
|
+
@description = options[:description].freeze
|
|
42
|
+
|
|
43
|
+
@parameters = (access_liberally(options, :parameters) || {}).freeze
|
|
44
|
+
@mappings = (access_liberally(options, :mappings) || {}).freeze
|
|
45
|
+
@conditions = (access_liberally(options, :conditions) || {}).freeze
|
|
46
|
+
@resources = resources_as_json(access_liberally(options, :resources)).freeze
|
|
47
|
+
@outputs = (access_liberally(options, :outputs) || {}).freeze
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Returns a JSON string representing the Template
|
|
51
|
+
#
|
|
52
|
+
# @return [String] A JSON string
|
|
53
|
+
#
|
|
54
|
+
def to_json(*)
|
|
55
|
+
JSON.pretty_generate(as_json)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Returns a hash representing the Template
|
|
59
|
+
#
|
|
60
|
+
# @return [Hash] A JSON-able hash
|
|
61
|
+
#
|
|
62
|
+
def as_json(*)
|
|
63
|
+
{
|
|
64
|
+
'FormatVersion' => format_version,
|
|
65
|
+
'Description' => description,
|
|
66
|
+
'Parameters' => parameters,
|
|
67
|
+
'Mappings' => mappings,
|
|
68
|
+
'Conditions' => conditions,
|
|
69
|
+
'Resources' => resources,
|
|
70
|
+
'Outputs' => outputs,
|
|
71
|
+
}.reject { |key, value| value.nil? }
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def merge(other)
|
|
75
|
+
dup.merge!(other)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
protected
|
|
79
|
+
|
|
80
|
+
def merge!(other)
|
|
81
|
+
raise ArgumentError, "Don't know how to merge with a #{other.class.name}" unless other.kind_of?(Template)
|
|
82
|
+
|
|
83
|
+
merge_value!(:format_version, other.format_version)
|
|
84
|
+
merge_value!(:description, other.description)
|
|
85
|
+
|
|
86
|
+
merge_hash!(:parameters, other.parameters)
|
|
87
|
+
merge_hash!(:mappings, other.mappings)
|
|
88
|
+
merge_hash!(:conditions, other.conditions)
|
|
89
|
+
merge_hash!(:resources, other.resources)
|
|
90
|
+
merge_hash!(:outputs, other.outputs)
|
|
91
|
+
|
|
92
|
+
self
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
private
|
|
96
|
+
|
|
97
|
+
def access_liberally(object, key)
|
|
98
|
+
object[key.to_sym] ||
|
|
99
|
+
object[key.to_s] ||
|
|
100
|
+
object[key.to_s.camelcase.to_sym] ||
|
|
101
|
+
object[key.to_s.camelcase.to_s]
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def merge_value!(attribute, other_value)
|
|
105
|
+
self_value = send(attribute)
|
|
106
|
+
|
|
107
|
+
raise MergeError, "Duplicate attribute '#{attribute}' found" if self_value && (self_value != other_value)
|
|
108
|
+
|
|
109
|
+
instance_variable_set("@#{attribute}", other_value)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def merge_hash!(attribute, other_value)
|
|
113
|
+
self_value = send(attribute)
|
|
114
|
+
|
|
115
|
+
new_hash = self_value.merge(other_value) do |key, old, new|
|
|
116
|
+
raise MergeError, "Duplicate key '#{key}' found with different value in attribute '#{attribute}'" if old != new
|
|
117
|
+
old
|
|
118
|
+
end.freeze
|
|
119
|
+
|
|
120
|
+
instance_variable_set("@#{attribute}", new_hash)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def resources_as_json(resources_option = nil)
|
|
124
|
+
case resources_option
|
|
125
|
+
when Array
|
|
126
|
+
merge_disjoint_keys_and_duplicated_values(resources_option.map(&:as_json))
|
|
127
|
+
when Hash
|
|
128
|
+
resources_option.as_json
|
|
129
|
+
else
|
|
130
|
+
{}
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def merge_disjoint_keys_and_duplicated_values(hashes)
|
|
135
|
+
hashes.reduce({}) do |memo, hash|
|
|
136
|
+
memo.merge(hash) do |key, old, new|
|
|
137
|
+
raise MergeError, "Duplicate key '#{key}' has different values" unless old == new
|
|
138
|
+
old
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
data/lib/skywriter.rb
ADDED
data/skywriter.gemspec
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
+
require 'skywriter/version'
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |spec|
|
|
7
|
+
spec.name = "skywriter"
|
|
8
|
+
spec.version = Skywriter::VERSION
|
|
9
|
+
spec.authors = ["Ryan Michael", "Ben Hamill"]
|
|
10
|
+
spec.email = ["ryanmichael@otherinbox.com", "ben@context.io"]
|
|
11
|
+
spec.summary = %q{Writes cloud formations}
|
|
12
|
+
spec.description = %q{Writes AWS CloudFormation templates.}
|
|
13
|
+
spec.homepage = "https://github.com/otherinbox/skywriter#readme"
|
|
14
|
+
spec.license = "MIT"
|
|
15
|
+
|
|
16
|
+
spec.files = `git ls-files`.split($/)
|
|
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_dependency "require_all", "~> 1.3"
|
|
22
|
+
spec.add_dependency "activesupport", "~> 4.0"
|
|
23
|
+
|
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
|
25
|
+
spec.add_development_dependency "rake"
|
|
26
|
+
spec.add_development_dependency "rspec", "~> 2.14"
|
|
27
|
+
spec.add_development_dependency "pry"
|
|
28
|
+
spec.add_development_dependency "fuubar"
|
|
29
|
+
end
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Skywriter::Function do
|
|
4
|
+
describe "#ref" do
|
|
5
|
+
it "returns expected value" do
|
|
6
|
+
expect(Skywriter::Function.ref('value')).to eq("Ref" => 'value')
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
describe "#base64" do
|
|
11
|
+
it "returns expected value" do
|
|
12
|
+
expect(Skywriter::Function.base64('value')).to eq("Fn::Base64" => 'value')
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
describe "#find_in_map" do
|
|
17
|
+
it "returns expected value" do
|
|
18
|
+
expect(Skywriter::Function.find_in_map("MapName", "TopLevelKey", "SecondLevelKey")).to eq(
|
|
19
|
+
"Fn::FindInMap" => ["MapName", "TopLevelKey", "SecondLevelKey"]
|
|
20
|
+
)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
describe "#get_att" do
|
|
25
|
+
it "returns expected value" do
|
|
26
|
+
expect(Skywriter::Function.get_att('resource', 'attribute')).to eq(
|
|
27
|
+
"Fn::GetAtt" => ['resource', 'attribute']
|
|
28
|
+
)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
describe "#get_azs" do
|
|
33
|
+
it "returns expected value" do
|
|
34
|
+
expect(Skywriter::Function.get_azs('region')).to eq("Fn::GetAZs" => "region")
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
describe "#join" do
|
|
39
|
+
it "returns expected value" do
|
|
40
|
+
expect(Skywriter::Function.join('delimiter', 'value1', 'value2')).to eq(
|
|
41
|
+
"Fn::Join" => ["delimiter", ['value1', 'value2']]
|
|
42
|
+
)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
describe "#select" do
|
|
47
|
+
it "returns expected value" do
|
|
48
|
+
expect(Skywriter::Function.select('1', 'apples', 'grapes', 'oranges', 'mangoes')).to eq(
|
|
49
|
+
"Fn::Select" => [ "1", [ "apples", "grapes", "oranges", "mangoes" ] ]
|
|
50
|
+
)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it "converts numeric index to string" do
|
|
54
|
+
expect(Skywriter::Function.select(1, 'apples', 'grapes', 'oranges', 'mangoes')).to eq(
|
|
55
|
+
"Fn::Select" => [ "1", [ "apples", "grapes", "oranges", "mangoes" ] ]
|
|
56
|
+
)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
describe "#and" do
|
|
61
|
+
it "returns expected value" do
|
|
62
|
+
expect(Skywriter::Function.and('one', 'two')).to eq(
|
|
63
|
+
"Fn::And" => ['one', 'two']
|
|
64
|
+
)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
describe "#equals" do
|
|
69
|
+
it "returns expected value" do
|
|
70
|
+
expect(Skywriter::Function.equals('value_1', 'value_2')).to eq(
|
|
71
|
+
"Fn::Equals" => ["value_1", "value_2"]
|
|
72
|
+
)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
describe "#if" do
|
|
77
|
+
it "returns expected value" do
|
|
78
|
+
expect(Skywriter::Function.if('condition', 'when_true', 'when_false')).to eq(
|
|
79
|
+
"Fn::If" => ['condition', 'when_true', 'when_false']
|
|
80
|
+
)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
describe "#not" do
|
|
85
|
+
it "returns expected value" do
|
|
86
|
+
expect(Skywriter::Function.not('condition')).to eq(
|
|
87
|
+
"Fn::Not" => ['condition']
|
|
88
|
+
)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
describe "#or" do
|
|
93
|
+
it "returns expected value" do
|
|
94
|
+
expect(Skywriter::Function.or('condition 1', 'condition 2')).to eq(
|
|
95
|
+
"Fn::Or" => ['condition 1', 'condition 2']
|
|
96
|
+
)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Skywriter::Resource::CloudFormation::Authentication do
|
|
4
|
+
it "is a Resource" do
|
|
5
|
+
expect(Skywriter::Resource::CloudFormation::Authentication.new('name')).to be_a(Skywriter::Resource)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
describe "#as_json" do
|
|
9
|
+
it "allows the user to define the keyspace" do
|
|
10
|
+
resource = Skywriter::Resource::CloudFormation::Authentication.new(
|
|
11
|
+
'name',
|
|
12
|
+
Foo: {
|
|
13
|
+
access_key_id: 'some kind of key'
|
|
14
|
+
},
|
|
15
|
+
Bar: {
|
|
16
|
+
access_key_id: 'some other kind of key'
|
|
17
|
+
}
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
expect(resource.as_json).to eq(
|
|
21
|
+
{
|
|
22
|
+
'name' => {
|
|
23
|
+
'Type' => "AWS::CloudFormation::Authentication",
|
|
24
|
+
'Foo' => {
|
|
25
|
+
'accessKeyId' => 'some kind of key',
|
|
26
|
+
},
|
|
27
|
+
'Bar' => {
|
|
28
|
+
'accessKeyId' => 'some other kind of key',
|
|
29
|
+
},
|
|
30
|
+
'DependsOn' => [],
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Skywriter::Resource::CloudFormation::CustomResource do
|
|
4
|
+
it "is a Resource" do
|
|
5
|
+
expect(Skywriter::Resource::CloudFormation::CustomResource.new('name')).to be_a(Skywriter::Resource)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
describe "#as_json" do
|
|
9
|
+
it "allows the user to define the keyspace" do
|
|
10
|
+
resource = Skywriter::Resource::CloudFormation::CustomResource.new(
|
|
11
|
+
'name',
|
|
12
|
+
Foo: 'some foo value',
|
|
13
|
+
Bar: { 'SomeKey' => 'some value' },
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
expect(resource.as_json).to eq(
|
|
17
|
+
{
|
|
18
|
+
'name' => {
|
|
19
|
+
'Type' => "AWS::CloudFormation::CustomResource",
|
|
20
|
+
'Properties' => {
|
|
21
|
+
'Foo' => 'some foo value',
|
|
22
|
+
'Bar' => { 'SomeKey' => 'some value' },
|
|
23
|
+
},
|
|
24
|
+
'DependsOn' => [],
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Skywriter::Resource::LogicalNamePointer do
|
|
4
|
+
let(:resource) { double("Resource", logical_name: "logical name") }
|
|
5
|
+
|
|
6
|
+
let(:pointer) do
|
|
7
|
+
Skywriter::Resource::LogicalNamePointer.new(resource)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
describe "#as_json" do
|
|
11
|
+
it "returns the logical name" do
|
|
12
|
+
expect(pointer.as_json).to eq("logical name")
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Skywriter::Resource::RefPointer do
|
|
4
|
+
let(:resource) { double("Resource", logical_name: "logical name") }
|
|
5
|
+
|
|
6
|
+
let(:pointer) do
|
|
7
|
+
Skywriter::Resource::RefPointer.new(resource)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
describe "#as_json" do
|
|
11
|
+
it "returns Ref" do
|
|
12
|
+
expect(pointer.as_json).to eq("Ref" => "logical name")
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|