awsdsl 0.0.1

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.
data/lib/awsdsl/dsl.rb ADDED
@@ -0,0 +1,79 @@
1
+ require 'awsdsl/ext/proc'
2
+ require 'awsdsl/ext/symbol'
3
+ require 'active_support/core_ext/object/blank'
4
+ require 'awsdsl/fn'
5
+
6
+ module AWSDSL
7
+ module DSL
8
+ include Fn
9
+ attr_accessor :name
10
+
11
+ def self.included(base)
12
+ base.extend(ClassMethods)
13
+ end
14
+
15
+ def initialize(name, &block)
16
+ @name = name
17
+ self.class.class_eval do
18
+ attributes.each do |attr|
19
+ define_method(attr) do |*args|
20
+ if args.length > 0
21
+ args = args.length > 1 ? args : args.first
22
+ instance_variable_set(attr.ivar, args)
23
+ else
24
+ instance_variable_get(attr.ivar)
25
+ end
26
+ end
27
+ end
28
+
29
+ multi_attributes.each do |attr|
30
+ define_method(attr) do |*args|
31
+ cur = instance_variable_get(attr.plural_ivar) || []
32
+ instance_variable_set(attr.plural_ivar, cur + args)
33
+ end
34
+ define_method(attr.plural_fn) do |*_, &_|
35
+ instance_variable_get(attr.plural_ivar) || []
36
+ end
37
+ end
38
+
39
+ sub_components.each do |attr|
40
+ define_method(attr) do |*args, &b|
41
+ cur = instance_variable_get(attr.plural_ivar) || []
42
+ klass_name = attr.to_s.split('_').collect!(&:capitalize).join
43
+ klass = Object.const_get("AWSDSL::#{klass_name}")
44
+ instance_variable_set(attr.plural_ivar, cur + [klass.new(args.first, &b)])
45
+ end
46
+ define_method(attr.plural_fn) do |*_, &_|
47
+ instance_variable_get(attr.plural_ivar) || []
48
+ end
49
+ end
50
+ end
51
+
52
+ instance_eval(&block) if block_given?
53
+ end
54
+
55
+ def to_h
56
+ h = {}
57
+ (self.class.attributes + [:name]).each { |attr| h.store(attr, send(attr)) }
58
+ self.class.multi_attributes.each { |attr| h.store(attr.plural_fn, send(attr.plural_fn)) }
59
+ self.class.sub_components.each do |attr|
60
+ comp = send(attr.plural_fn).map(&:to_h)
61
+ h.store(attr.plural_fn, comp)
62
+ end
63
+ h.delete_if { |_, v| v.blank? }
64
+ h
65
+ end
66
+
67
+ module ClassMethods
68
+ [:sub_components, :attributes, :multi_attributes].each do |method|
69
+ define_method(method) do |*args|
70
+ if args.length > 0
71
+ instance_variable_set(method.ivar, args)
72
+ else
73
+ instance_variable_get(method.ivar) || []
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,14 @@
1
+ require 'active_support/core_ext/kernel/singleton_class'
2
+
3
+ class Proc
4
+ def bind(object)
5
+ block, time = self, Time.now
6
+ object.class_eval do
7
+ method_name = "__bind_#{time.to_i}_#{time.usec}"
8
+ define_method(method_name, &block)
9
+ method = instance_method(method_name)
10
+ remove_method(method_name)
11
+ method
12
+ end.bind(object)
13
+ end
14
+ end
@@ -0,0 +1,13 @@
1
+ class Symbol
2
+ def ivar
3
+ "@#{self}".to_sym
4
+ end
5
+
6
+ def plural_ivar
7
+ "@#{self}s".to_sym
8
+ end
9
+
10
+ def plural_fn
11
+ "#{self}s".to_sym
12
+ end
13
+ end
data/lib/awsdsl/fn.rb ADDED
@@ -0,0 +1,7 @@
1
+ module AWSDSL
2
+ module Fn
3
+ def stack(*a, &block)
4
+ Stack.new(*a, &block)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,24 @@
1
+ require 'awsdsl/dsl'
2
+ require 'awsdsl/dsl/stack'
3
+ require 'awsdsl/dsl/role'
4
+ require 'awsdsl/dsl/role_profile'
5
+ require 'awsdsl/dsl/load_balancer'
6
+ require 'awsdsl/dsl/elasticache'
7
+ require 'awsdsl/dsl/vpc'
8
+ require 'awsdsl/dsl/subnet'
9
+ require 'awsdsl/fn'
10
+
11
+ module AWSDSL
12
+ module Loader
13
+ def self.stack(*a, &block)
14
+ Stack.new(*a, &block)
15
+ end
16
+
17
+ def self.load(fname)
18
+ stack = binding.eval(File.read(fname), fname)
19
+ # TODO(jpg): Add default profiles to stack
20
+ stack.mixin_profiles
21
+ stack
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,28 @@
1
+ module AWSDSL
2
+ class Runner
3
+ def initialize(stackfile: 'Stackfile')
4
+ @stack = Loader.load(stackfile)
5
+ @cfn = AWS::CloudFormation.new
6
+ end
7
+
8
+ def build_amis
9
+ AMIBuilder.build(@stack)
10
+ end
11
+
12
+ def create
13
+ build_amis
14
+ t = CfnBuilder.build(@stack)
15
+ @cfn.stacks.create(@stack.name, t, capabilities: ['CAPABILITY_IAM'])
16
+ end
17
+
18
+ def update
19
+ build_amis
20
+ t = CfnBuilder.build(stack)
21
+ @cfn.stacks[@stack.name].update(template: t, capabiltiies: ['CAPABILITY_IAM'])
22
+ end
23
+
24
+ def delete
25
+ @cfn.stacks[@stack.name].delete
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,3 @@
1
+ module AWSDSL
2
+ VERSION = '0.0.1'
3
+ end
data/lib/awsdsl.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'awsdsl/loader'
2
+ require 'awsdsl/cfn_builder'
3
+ require 'awsdsl/ami_builder'
4
+
5
+ module AWSDSL
6
+ end
@@ -0,0 +1,28 @@
1
+ require 'English'
2
+ require 'awsdsl'
3
+ require 'pry'
4
+
5
+ module AWSDSL
6
+ describe CfnBuilder do
7
+ describe :build do
8
+ it 'should build the test stack' do
9
+ stack = Loader.load(fixture_path('test_stack.rb'))
10
+ CfnBuilder.new(stack).build
11
+ end
12
+
13
+ it 'should generate valid cloudformation', type: :integration do
14
+ stack = Loader.load(fixture_path('test_stack.rb'))
15
+ stack.roles.each do |role|
16
+ role.ami = 'ami-id'
17
+ end
18
+ json = CfnBuilder.new(stack).build.to_json
19
+ temp = Tempfile.new('awsdsl_cfn_json')
20
+ temp.write(json)
21
+ `aws cloudformation validate-template --template-body file://#{temp.path}`
22
+ temp.close
23
+ temp.unlink
24
+ expect($CHILD_STATUS.exitstatus).to eq(0)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,12 @@
1
+ require 'awsdsl'
2
+ require 'pry'
3
+
4
+ module AWSDSL
5
+ describe Loader do
6
+ describe :load do
7
+ it 'should load the test data' do
8
+ Loader.load(fixture_path('test_stack.rb'))
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,100 @@
1
+ stack 'logs' do
2
+ description 'logstash cluster'
3
+ ssl_cert_arn = 'arn:aws:iam::account_id::certificate'
4
+ zone_arn = 'arn:aws:route53:::hostedzone/zone_id'
5
+ snapshot_bucket_arn = 'arn:aws:s3:::snapshot_bucket'
6
+ cloudtrail_queue_arn = 'arn:aws:sqs:ap-southeast-2:account_id:queue'
7
+
8
+ vpc 'logs' do
9
+ region 'ap-southeast-2'
10
+ subnet 'public' do
11
+ az 'a', 'b'
12
+ end
13
+ subnet 'private' do
14
+ az 'a', 'b'
15
+ igw false
16
+ end
17
+ end
18
+
19
+ role_profile 'es_comms' do
20
+ security_group 'sg-id'
21
+ subnet 'public'
22
+ vpc 'logs'
23
+ end
24
+
25
+ role_profile 'es_bucket' do
26
+ policy_statement effect: 'Allow', action: 's3:ListBucket', resource: snapshot_bucket_arn
27
+ policy_statement effect: 'Allow',
28
+ action: %w(s3:GetObject s3:PutObjecs3:DeleteObject s3:DeleteObject),
29
+ resource: "#{snapshot_bucket_arn}/*"
30
+ end
31
+
32
+ role_profile 'ec2_discovery' do
33
+ policy_statement effect: 'Allow', action: 'ec2:DescribeInstances', resource: '*'
34
+ end
35
+
36
+ role 'logstash' do
37
+ include_profile 'ec2_discovery', 'es_comms'
38
+ load_balancer 'logstash' do
39
+ listener port: 80
40
+ listener port: 443, proto: 'HTTPS', cert: ssl_cert_arn
41
+ listener port: 9000, proto: 'TCP'
42
+ dns_record name: 'logstash.zone.com', zone: 'zone-id'
43
+ health_check target: 'HTTP:80/health'
44
+ end
45
+ policy_statement effect: 'Allow', action: 'sqs:*', resource: cloudtrail_queue_arn
46
+ min_size 2
47
+ max_size 4
48
+ tgt_size 2
49
+ update_policy pause_time: '5M'
50
+ instance_type 't2.micro'
51
+ chef_provisioner runlist: 'logstash'
52
+ end
53
+
54
+ role 'elasticsearch' do
55
+ include_profile 'ec2_discovery', 'es_bucket', 'es_comms'
56
+ load_balancer 'elasticsearch' do
57
+ listener port: 9200
58
+ health_check target: 'HTTP:9200/'
59
+ dns_record name: 'elasticsearch.zone.com', zone: 'zone-id'
60
+ security_group 'sg-id'
61
+ internal true
62
+ end
63
+ min_size 3
64
+ max_size 5
65
+ tgt_size 5
66
+ update_policy pause_time: '10M', min_inservice: 3
67
+ instance_type 't2.micro'
68
+ block_device name: '/dev/sda1', size: 20
69
+ chef_provisioner runlist: 'elasticsearch'
70
+ allow role: 'logstash', ports: 9200
71
+ allow role: 'utility', ports: 9200
72
+ allow role: 'elasticsearch', ports: 9200
73
+ end
74
+
75
+ role 'utility' do
76
+ include_profile 'es_bucket', 'es_comms'
77
+ policy_statement effect: 'Allow',
78
+ action: [
79
+ 'route53:ChangeResourceRecordSets',
80
+ 'route53:GetHostedZone',
81
+ 'route53:ListResourceRecordSets'
82
+ ],
83
+ resource: zone_arn
84
+ policy_statement effect: 'Allow', action: 'route53:ListHostedZones', resource: '*'
85
+ min_size 0
86
+ max_size 1
87
+ tgt_size 1
88
+ update_policy min_inservice: 0
89
+ instance_type 't2.micro'
90
+ chef_provisioner runlist: 'utility'
91
+ end
92
+
93
+ elasticache 'redis' do
94
+ vpc 'logs'
95
+ subnet 'private'
96
+ engine 'redis'
97
+ node_type 't2.micro'
98
+ allow role: 'logstash'
99
+ end
100
+ end
@@ -0,0 +1,30 @@
1
+ require 'pry'
2
+ require 'awsdsl'
3
+ require 'awsdsl/cfn_helpers'
4
+
5
+ ROOT = File.join(File.dirname(__FILE__), '..')
6
+ FIXTURES = File.join(File.dirname(__FILE__), 'fixtures')
7
+
8
+ def fixture_path(*path)
9
+ File.join(FIXTURES, path)
10
+ end
11
+
12
+ def fixture(*path)
13
+ File.open(fixture_path(path)) { |f| f.read }
14
+ end
15
+
16
+ def json_fixture(*path)
17
+ last = path.pop
18
+ JSON.parse(fixture(path << last + '.json'))
19
+ end
20
+
21
+ def yaml_fixture(*path)
22
+ last = path.pop
23
+ YAML.parse(fixture(path << last + '.yml'))
24
+ end
25
+
26
+ AWS.stub!
27
+
28
+ RSpec.configure do |config|
29
+ config.filter_run_excluding type: 'integration' unless ENV['INTEGRATION']
30
+ end
metadata ADDED
@@ -0,0 +1,165 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: awsdsl
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Joseph Glanville
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-04-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: aws-sdk
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activesupport
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '4'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '4'
41
+ - !ruby/object:Gem::Dependency
42
+ name: clamp
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.6'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.6'
55
+ - !ruby/object:Gem::Dependency
56
+ name: cfndsl
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.1'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.1'
69
+ - !ruby/object:Gem::Dependency
70
+ name: gersberms
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: netaddr
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.5'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.5'
97
+ description: A simple DSL for deploying and running apps on AWS
98
+ email:
99
+ - jpg@jpg.id.au
100
+ executables:
101
+ - awsdsl
102
+ extensions: []
103
+ extra_rdoc_files: []
104
+ files:
105
+ - ".gitignore"
106
+ - ".rspec"
107
+ - Gemfile
108
+ - Gemfile.lock
109
+ - README.md
110
+ - Rakefile
111
+ - awsdsl.gemspec
112
+ - bin/awsdsl
113
+ - lib/awsdsl.rb
114
+ - lib/awsdsl/ami_builder.rb
115
+ - lib/awsdsl/base_ami.rb
116
+ - lib/awsdsl/cfn_builder.rb
117
+ - lib/awsdsl/cfn_helpers.rb
118
+ - lib/awsdsl/command_line.rb
119
+ - lib/awsdsl/dsl.rb
120
+ - lib/awsdsl/dsl/elasticache.rb
121
+ - lib/awsdsl/dsl/load_balancer.rb
122
+ - lib/awsdsl/dsl/role.rb
123
+ - lib/awsdsl/dsl/role_profile.rb
124
+ - lib/awsdsl/dsl/stack.rb
125
+ - lib/awsdsl/dsl/subnet.rb
126
+ - lib/awsdsl/dsl/vpc.rb
127
+ - lib/awsdsl/ext/proc.rb
128
+ - lib/awsdsl/ext/symbol.rb
129
+ - lib/awsdsl/fn.rb
130
+ - lib/awsdsl/loader.rb
131
+ - lib/awsdsl/runner.rb
132
+ - lib/awsdsl/version.rb
133
+ - spec/awsdsl/cfn_builder_spec.rb
134
+ - spec/awsdsl/loader_spec.rb
135
+ - spec/fixtures/test_stack.rb
136
+ - spec/spec_helper.rb
137
+ homepage: https://github.com/josephglanville/awsdsl
138
+ licenses:
139
+ - MIT
140
+ metadata: {}
141
+ post_install_message:
142
+ rdoc_options: []
143
+ require_paths:
144
+ - lib
145
+ required_ruby_version: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - ">="
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ required_rubygems_version: !ruby/object:Gem::Requirement
151
+ requirements:
152
+ - - ">="
153
+ - !ruby/object:Gem::Version
154
+ version: '0'
155
+ requirements: []
156
+ rubyforge_project:
157
+ rubygems_version: 2.4.3
158
+ signing_key:
159
+ specification_version: 4
160
+ summary: A simple DSL for deploying and running apps on AWS
161
+ test_files:
162
+ - spec/awsdsl/cfn_builder_spec.rb
163
+ - spec/awsdsl/loader_spec.rb
164
+ - spec/fixtures/test_stack.rb
165
+ - spec/spec_helper.rb