cloudshaper 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +4 -0
  3. data/.travis.yml +3 -0
  4. data/Gemfile +7 -0
  5. data/Gemfile.lock +27 -0
  6. data/LICENSE +23 -0
  7. data/README.md +162 -0
  8. data/Rakefile +9 -0
  9. data/TODO.md +7 -0
  10. data/examples/secretconfig/README.md +3 -0
  11. data/examples/secretconfig/atlas.json +5 -0
  12. data/examples/secretconfig/aws.json +6 -0
  13. data/examples/secretconfig/cloudflare.json +6 -0
  14. data/examples/secretconfig/cloudstack.json +7 -0
  15. data/examples/secretconfig/digitalocean.json +5 -0
  16. data/examples/secretconfig/dme.json +6 -0
  17. data/examples/secretconfig/heroku.json +6 -0
  18. data/examples/secretconfig/mailgun.json +5 -0
  19. data/examples/simple_app.rb +61 -0
  20. data/lib/tasks/tasks.rb +12 -0
  21. data/lib/tasks/terraform.rake +127 -0
  22. data/lib/terraform_dsl.rb +6 -0
  23. data/lib/terraform_dsl/aws/remote_s3.rb +20 -0
  24. data/lib/terraform_dsl/aws/tagging.rb +23 -0
  25. data/lib/terraform_dsl/command.rb +58 -0
  26. data/lib/terraform_dsl/module.rb +38 -0
  27. data/lib/terraform_dsl/output.rb +6 -0
  28. data/lib/terraform_dsl/provider.rb +13 -0
  29. data/lib/terraform_dsl/remote.rb +31 -0
  30. data/lib/terraform_dsl/resource.rb +44 -0
  31. data/lib/terraform_dsl/secrets.rb +29 -0
  32. data/lib/terraform_dsl/stack.rb +79 -0
  33. data/lib/terraform_dsl/stack_element.rb +62 -0
  34. data/lib/terraform_dsl/stack_module.rb +121 -0
  35. data/lib/terraform_dsl/stack_modules.rb +24 -0
  36. data/lib/terraform_dsl/stacks.rb +64 -0
  37. data/lib/terraform_dsl/variable.rb +6 -0
  38. data/lib/terraform_dsl/version.rb +3 -0
  39. data/terraform_dsl.gemspec +25 -0
  40. data/test/stack_module_test.rb +152 -0
  41. data/test/stack_test.rb +5 -0
  42. data/test/test_helper.rb +4 -0
  43. metadata +131 -0
@@ -0,0 +1,24 @@
1
+ module Terraform
2
+ # Stack module factory, register a module and provide clones of it
3
+ class StackModules
4
+ class ModuleNotFound < StandardError; end
5
+ class ModuleAlreadyRegistered < StandardError; end
6
+
7
+ class << self
8
+ def register(name, stack_module)
9
+ fail ModuleAlreadyRegistered, "#{name} is already a registered stack_module" if @stack_modules.key?(name.downcase)
10
+ @stack_modules[name.downcase] = stack_module
11
+ end
12
+
13
+ def get(stack_module_name)
14
+ fail ModuleNotFound, "#{stack_module_name} module module not found" unless @stack_modules.key?(stack_module_name.downcase)
15
+ @stack_modules[stack_module_name.downcase].clone
16
+ end
17
+
18
+ def reset!
19
+ @stack_modules ||= {}
20
+ end
21
+ end
22
+ reset!
23
+ end
24
+ end
@@ -0,0 +1,64 @@
1
+ require 'yaml'
2
+ require 'securerandom'
3
+
4
+ require 'terraform_dsl/stack'
5
+
6
+ module Terraform
7
+ # Singleton to keep track of stack templates
8
+ class Stacks
9
+ class MalformedConfig < StandardError; end
10
+ class << self
11
+ attr_reader :stacks
12
+
13
+ def load
14
+ config = ENV['STACK_CONFIG'] || 'stacks.yml'
15
+ fail 'stacks.yml must exist in root directory, or specify STACK_CONFIG pointing to stacks.yml' unless File.exist?(config)
16
+ stack_specs = YAML.load(File.read(config))
17
+ fail MalformedConfig, 'Stacks must be an array' unless stack_specs.key?('stacks') && stack_specs['stacks'].is_a?(Array)
18
+ common = stack_specs['common'] || {}
19
+ stack_specs['stacks'].each do |stack_spec|
20
+ stack = Stack.load(stack_spec.merge(common))
21
+ @stacks[stack.name] = stack
22
+ end
23
+ end
24
+
25
+ def init
26
+ config = ENV['STACK_CONFIG'] || 'stacks.yml'
27
+ fail "stacks.yaml already exists at #{File.expand_path(config)}" if File.exist?(config)
28
+ File.open(config, 'w') do |f|
29
+ f.write(YAML.dump(base_config))
30
+ end
31
+ end
32
+
33
+ def uuid
34
+ "#{Time.now.utc.to_i}_#{SecureRandom.urlsafe_base64(6)}"
35
+ end
36
+
37
+ def base_config
38
+ {
39
+ 'common' => {},
40
+ 'stacks' => [base_stack_config]
41
+ }
42
+ end
43
+
44
+ def base_stack_config
45
+ {
46
+ 'name' => 'SET_NAME',
47
+ 'uuid' => uuid,
48
+ 'description' => 'SET_A_DESCRIPTION',
49
+ 'root' => 'SET_A_TEMPLATE',
50
+ 'variables' => {}
51
+ }
52
+ end
53
+
54
+ def reset!
55
+ @stacks ||= {}
56
+ end
57
+
58
+ def dir
59
+ File.expand_path(File.join(ENV['TERRAFORM_DATA_DIR'] || 'data', 'stacks'))
60
+ end
61
+ end
62
+ reset!
63
+ end
64
+ end
@@ -0,0 +1,6 @@
1
+ require 'terraform_dsl/stack_element'
2
+
3
+ module Terraform
4
+ class Variable < StackElement
5
+ end
6
+ end
@@ -0,0 +1,3 @@
1
+ module Terraform
2
+ VERSION = '0.0.4'
3
+ end
@@ -0,0 +1,25 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'terraform_dsl/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'cloudshaper'
7
+ spec.version = Terraform::VERSION
8
+ spec.summary = 'Wrap hashicorps "terraform" in a ruby DSL for managing stack templates'
9
+ spec.description = 'Terraform DSL provides a syntax for managing terraform infrastructure entirely in git'
10
+ spec.authors = ['Dale Hamel']
11
+ spec.email = 'dale.hamel@srvthe.net'
12
+ spec.files = Dir['lib/**/*']
13
+ spec.homepage = 'https://rubygems.org/gems/terraform_dsl'
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_runtime_dependency 'rake', '~> 10.4'
22
+
23
+ spec.add_development_dependency 'bundler'
24
+ spec.add_development_dependency 'minitest', '~> 5.6'
25
+ end
@@ -0,0 +1,152 @@
1
+ require 'test_helper'
2
+
3
+ class StackModuleTest < Minitest::Test
4
+ include Terraform
5
+
6
+ def test_multiple_instantiations_of_module
7
+ StackModule.define 'factory_instantiation_test' do
8
+ variable(:ports) { default '22' }
9
+ resource 'aws_security_group', :a do
10
+ get(:ports).split(',').each do |port|
11
+ ingress { from_port port }
12
+ end
13
+ end
14
+ end
15
+
16
+ first = StackModules.get('factory_instantiation_test')
17
+ second = StackModules.get('factory_instantiation_test')
18
+
19
+ first.build(ports: '80')
20
+ second.build(ports: '443')
21
+
22
+ sg_first = first.elements[:resource][:aws_security_group][:a]
23
+ sg_second = second.elements[:resource][:aws_security_group][:a]
24
+
25
+ assert_equal '80', sg_first[:ingress].fetch(:from_port)
26
+ assert_equal '443', sg_second[:ingress].fetch(:from_port)
27
+ end
28
+
29
+ # it 'should register variables with default values' do
30
+ # mod = StackModule.define('variable_register_default') { variable(:name) { default 'default' } }
31
+ # mod.build
32
+
33
+ # expect(mod.variables).to be_a(Hash)
34
+ # expect(mod.variables).to include(:name)
35
+ # expect(mod.variables[:name]).to be_a(Hash)
36
+ # expect(mod.variables[:name]).to include(:default)
37
+ # expect(mod.variables[:name][:default]).to eq('default')
38
+ # end
39
+
40
+ # it 'should register variables without default values' do
41
+ # mod = StackModule.define('variable_register_nodefault') { variable(:name) {} }
42
+ # mod.build
43
+
44
+ # expect(mod.variables).to be_a(Hash)
45
+ # expect(mod.variables).to include(:name)
46
+ # expect(mod.variables[:name]).to be_a(Hash)
47
+ # expect(mod.variables[:name]).to include(:default)
48
+ # expect(mod.variables[:name][:default]).to eq('')
49
+ # end
50
+
51
+ # it 'should accept variables at runtime' do
52
+ # mod = StackModule.define('variable_override') { variable(:name) { default 'default' } }
53
+ # mod.build(name: 'not-default')
54
+
55
+ # expect(mod.variables[:name][:default]).to eql('not-default')
56
+ # end
57
+ # end
58
+
59
+ def test_register_resource
60
+ mod = StackModule.define('register_resource') { resource('aws_instance', :a) { default 'default' } }
61
+ mod.build
62
+
63
+ instance = mod.elements.fetch(:resource).fetch(:aws_instance).fetch(:a)
64
+ assert_equal 'default', instance.fetch(:default)
65
+ end
66
+
67
+ def test_register_resource_with_connections
68
+ mod = StackModule.define 'register_connection_test' do
69
+ resource 'aws_instance', :a do
70
+ connection do
71
+ user 'root'
72
+ end
73
+ end
74
+ end
75
+ mod.build
76
+
77
+ instance = mod.elements.fetch(:resource).fetch(:aws_instance).fetch(:a)
78
+ assert_equal 'root', instance.fetch(:connection).fetch(:user)
79
+ end
80
+
81
+ def test_register_resource_with_provisioners_with_connections
82
+ mod = StackModule.define 'register_provision_connection_test' do
83
+ resource 'aws_instance', :a do
84
+ provisioner 'file' do
85
+ connection do
86
+ user 'root'
87
+ end
88
+ end
89
+ end
90
+ end
91
+ mod.build
92
+
93
+ instance = mod.elements.fetch(:resource).fetch(:aws_instance).fetch(:a)
94
+ provisioner = instance.fetch(:provisioner).first
95
+ connection = provisioner.fetch(:file).fetch(:connection)
96
+ assert_equal 'root', connection.fetch(:user)
97
+ end
98
+
99
+ def test_group_attributes_into_arrays
100
+ mod = StackModule.define 'resource_scalar_variable_groups' do
101
+ resource 'aws_security_group', :a do
102
+ ingress { from_port 80 }
103
+ ingress { from_port 443 }
104
+ end
105
+ end
106
+ mod.build
107
+
108
+ sg = mod.elements.fetch(:resource).fetch(:aws_security_group).fetch(:a)
109
+ ingress = sg.fetch(:ingress)
110
+
111
+ assert_kind_of Array, ingress
112
+ assert_equal [{from_port: 80}, {from_port: 443}], ingress
113
+ end
114
+
115
+ def test_support_overriding_attributes
116
+ mod = StackModule.define 'resource_overriden_runtime_variable' do
117
+ variable(:ports) { default '22' }
118
+ resource 'aws_security_group', :a do
119
+ get(:ports).split(',').each do |port|
120
+ ingress { from_port port }
121
+ end
122
+ end
123
+ end
124
+ mod.build(ports: '22,80,443')
125
+
126
+
127
+ sg = mod.elements.fetch(:resource).fetch(:aws_security_group).fetch(:a)
128
+ ingress = sg.fetch(:ingress)
129
+ assert_equal [{from_port: "22"}, {from_port: "80"}, {from_port: "443"}], ingress
130
+ end
131
+
132
+
133
+ # it 'it should be able to access overridden default variables at runtime' do
134
+ # mod = StackModule.define 'resource_overriden_runtime_variable' do
135
+ # variable(:ports) { default '22' }
136
+ # resource 'aws_security_group', :a do
137
+ # get(:ports).split(',').each do |port|
138
+ # ingress { from_port port }
139
+ # end
140
+ # end
141
+ # end
142
+
143
+ # mod.build(ports: '22,80,443')
144
+
145
+ # sg = mod.elements[:resource][:aws_security_group][:a]
146
+ # expect(sg).to include(:ingress)
147
+ # expect(sg[:ingress]).to be_a(Array)
148
+ # expect(sg[:ingress].first).to eq(from_port: '22')
149
+ # expect(sg[:ingress].last).to eq(from_port: '443')
150
+ # end
151
+ # end
152
+ end
@@ -0,0 +1,5 @@
1
+ require 'test_helper'
2
+
3
+ class StackTest < Minitest::Test
4
+
5
+ end
@@ -0,0 +1,4 @@
1
+ require 'minitest/autorun'
2
+ require 'minitest/pride'
3
+
4
+ require 'terraform_dsl'
metadata ADDED
@@ -0,0 +1,131 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cloudshaper
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.4
5
+ platform: ruby
6
+ authors:
7
+ - Dale Hamel
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-06-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '10.4'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '10.4'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '5.6'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.6'
55
+ description: Terraform DSL provides a syntax for managing terraform infrastructure
56
+ entirely in git
57
+ email: dale.hamel@srvthe.net
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - ".travis.yml"
64
+ - Gemfile
65
+ - Gemfile.lock
66
+ - LICENSE
67
+ - README.md
68
+ - Rakefile
69
+ - TODO.md
70
+ - examples/secretconfig/README.md
71
+ - examples/secretconfig/atlas.json
72
+ - examples/secretconfig/aws.json
73
+ - examples/secretconfig/cloudflare.json
74
+ - examples/secretconfig/cloudstack.json
75
+ - examples/secretconfig/digitalocean.json
76
+ - examples/secretconfig/dme.json
77
+ - examples/secretconfig/heroku.json
78
+ - examples/secretconfig/mailgun.json
79
+ - examples/simple_app.rb
80
+ - lib/tasks/tasks.rb
81
+ - lib/tasks/terraform.rake
82
+ - lib/terraform_dsl.rb
83
+ - lib/terraform_dsl/aws/remote_s3.rb
84
+ - lib/terraform_dsl/aws/tagging.rb
85
+ - lib/terraform_dsl/command.rb
86
+ - lib/terraform_dsl/module.rb
87
+ - lib/terraform_dsl/output.rb
88
+ - lib/terraform_dsl/provider.rb
89
+ - lib/terraform_dsl/remote.rb
90
+ - lib/terraform_dsl/resource.rb
91
+ - lib/terraform_dsl/secrets.rb
92
+ - lib/terraform_dsl/stack.rb
93
+ - lib/terraform_dsl/stack_element.rb
94
+ - lib/terraform_dsl/stack_module.rb
95
+ - lib/terraform_dsl/stack_modules.rb
96
+ - lib/terraform_dsl/stacks.rb
97
+ - lib/terraform_dsl/variable.rb
98
+ - lib/terraform_dsl/version.rb
99
+ - terraform_dsl.gemspec
100
+ - test/stack_module_test.rb
101
+ - test/stack_test.rb
102
+ - test/test_helper.rb
103
+ homepage: https://rubygems.org/gems/terraform_dsl
104
+ licenses:
105
+ - MIT
106
+ metadata: {}
107
+ post_install_message:
108
+ rdoc_options: []
109
+ require_paths:
110
+ - lib
111
+ required_ruby_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ required_rubygems_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ requirements: []
122
+ rubyforge_project:
123
+ rubygems_version: 2.4.6
124
+ signing_key:
125
+ specification_version: 4
126
+ summary: Wrap hashicorps "terraform" in a ruby DSL for managing stack templates
127
+ test_files:
128
+ - test/stack_module_test.rb
129
+ - test/stack_test.rb
130
+ - test/test_helper.rb
131
+ has_rdoc: