cloudshaper 0.0.4 → 0.0.5
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 +4 -4
- data/Gemfile.lock +3 -1
- data/README.md +9 -39
- data/bin/cloudshaper +14 -0
- data/{terraform_dsl.gemspec → cloudshaper.gemspec} +6 -5
- data/lib/{terraform_dsl → cloudshaper}/aws/remote_s3.rb +1 -1
- data/lib/{terraform_dsl → cloudshaper}/aws/tagging.rb +2 -2
- data/lib/cloudshaper/cli.rb +98 -0
- data/lib/{terraform_dsl → cloudshaper}/command.rb +2 -2
- data/lib/cloudshaper/module.rb +30 -0
- data/lib/cloudshaper/output.rb +6 -0
- data/lib/{terraform_dsl → cloudshaper}/provider.rb +6 -4
- data/lib/{terraform_dsl → cloudshaper}/remote.rb +2 -2
- data/lib/{terraform_dsl → cloudshaper}/resource.rb +2 -2
- data/lib/{terraform_dsl → cloudshaper}/secrets.rb +0 -0
- data/lib/{terraform_dsl → cloudshaper}/stack.rb +14 -16
- data/lib/{terraform_dsl → cloudshaper}/stack_element.rb +8 -3
- data/lib/{terraform_dsl → cloudshaper}/stack_module.rb +42 -35
- data/lib/{terraform_dsl → cloudshaper}/stack_modules.rb +6 -2
- data/lib/{terraform_dsl → cloudshaper}/stacks.rb +3 -7
- data/lib/cloudshaper/variable.rb +6 -0
- data/lib/cloudshaper/version.rb +3 -0
- data/lib/cloudshaper.rb +4 -0
- data/lib/tasks/terraform.rake +19 -19
- data/test/stack_module_test.rb +41 -55
- data/test/test_helper.rb +1 -1
- metadata +44 -28
- data/lib/tasks/tasks.rb +0 -12
- data/lib/terraform_dsl/module.rb +0 -38
- data/lib/terraform_dsl/output.rb +0 -6
- data/lib/terraform_dsl/variable.rb +0 -6
- data/lib/terraform_dsl/version.rb +0 -3
- data/lib/terraform_dsl.rb +0 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 993c81cd51249cfba9467ea7fcbdf922a1d520dd
|
|
4
|
+
data.tar.gz: c2ac2bdea9eb45c58004053069af40567aced2d9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 27de4a1c4291b51e313559fc4fe23614ec25889c0134704e5c0414ec2136809b71de27d4bd815f16e04f8f2e1c8b6e2cc817ed370457e0496c8d1beb9f44b7b5
|
|
7
|
+
data.tar.gz: c576febad8b279a24f829ba7ed1b16857958e5dc18bbfb81d20869eda2866fabf12fb9032c246f4bfccb2d0b3d1067737388006375d5e52a34aa2192811f4841
|
data/Gemfile.lock
CHANGED
|
@@ -2,7 +2,7 @@ PATH
|
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
4
|
cloudshaper (0.0.4)
|
|
5
|
-
|
|
5
|
+
thor (~> 0.19.1)
|
|
6
6
|
|
|
7
7
|
GEM
|
|
8
8
|
remote: https://rubygems.org/
|
|
@@ -16,6 +16,7 @@ GEM
|
|
|
16
16
|
json (~> 1.8)
|
|
17
17
|
simplecov-html (~> 0.10.0)
|
|
18
18
|
simplecov-html (0.10.0)
|
|
19
|
+
thor (0.19.1)
|
|
19
20
|
|
|
20
21
|
PLATFORMS
|
|
21
22
|
ruby
|
|
@@ -24,4 +25,5 @@ DEPENDENCIES
|
|
|
24
25
|
bundler
|
|
25
26
|
cloudshaper!
|
|
26
27
|
minitest (~> 5.6)
|
|
28
|
+
rake (~> 10.4)
|
|
27
29
|
simplecov (= 0.10.0)
|
data/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
[](https://travis-ci.org/dalehamel/cloudshaper)
|
|
2
2
|
|
|
3
|
-
#
|
|
3
|
+
# Cloudshaper
|
|
4
4
|
|
|
5
5
|
This is a simple DSL for wrapping hashicorp's [terraform configuration](https://terraform.io/docs/configuration/index.html).
|
|
6
6
|
|
|
@@ -50,13 +50,13 @@ Create a stack module, like one of our [examples](examples), such as our [simple
|
|
|
50
50
|
Generally, you need to do:
|
|
51
51
|
|
|
52
52
|
```
|
|
53
|
-
require '
|
|
53
|
+
require 'cloudshaper'
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
-
And then subclass
|
|
56
|
+
And then subclass Cloudshaper::StackModule
|
|
57
57
|
|
|
58
58
|
```
|
|
59
|
-
class MyAwesomeStackModule <
|
|
59
|
+
class MyAwesomeStackModule < Cloudshaper::StackModule
|
|
60
60
|
```
|
|
61
61
|
|
|
62
62
|
Within that class, define resources using a similar syntax to [terraform's configuration](https://terraform.io/docs/configuration/index.html).
|
|
@@ -107,7 +107,7 @@ common:
|
|
|
107
107
|
region: us-east-1
|
|
108
108
|
stacks:
|
|
109
109
|
- name: teststack
|
|
110
|
-
uuid:
|
|
110
|
+
uuid: 8adcbfb1-fdcc-4558-8958-ea8a9e1874ea # must be unique
|
|
111
111
|
description: just a test stack
|
|
112
112
|
root: simpleapp
|
|
113
113
|
variables:
|
|
@@ -117,43 +117,13 @@ stacks:
|
|
|
117
117
|
|
|
118
118
|
You may also specify a 'common' block, that will be merged into all stacks.
|
|
119
119
|
|
|
120
|
-
|
|
120
|
+
Cloudshaper stacks need somewhere to store their state. By default, this will be the local filesystem.
|
|
121
121
|
|
|
122
122
|
It's highly recommended that you use a [remote backend](https://www.terraform.io/docs/commands/remote-config.html) instead, so that you can share your stacks.
|
|
123
123
|
|
|
124
|
-
###
|
|
124
|
+
### Commands
|
|
125
125
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
```
|
|
129
|
-
## Loads terraform tasks and modules
|
|
130
|
-
require 'terraform_dsl'
|
|
131
|
-
Terraform::Tasks.loadall
|
|
132
|
-
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
This will add some terraform tasks for managing your terraform stacks:
|
|
136
|
-
|
|
137
|
-
```
|
|
138
|
-
rake terraform:apply[name] # Apply pending changes for a stack
|
|
139
|
-
rake terraform:apply_all # Apply all pending stack changes
|
|
140
|
-
rake terraform:destroy[name] # Destroy a stack
|
|
141
|
-
rake terraform:get[name] # Fetch modules for a stack
|
|
142
|
-
rake terraform:get_all # Fetch modules for all stacks
|
|
143
|
-
rake terraform:init # Initialize stacks.yml if it does not exist
|
|
144
|
-
rake terraform:list # List all available stacks
|
|
145
|
-
rake terraform:load # Loads available stack modules
|
|
146
|
-
rake terraform:plan[name] # Show pending changes for a stack
|
|
147
|
-
rake terraform:pull[name] # Pulls stack state from remote location
|
|
148
|
-
rake terraform:pull_all # Pulls stack states from remote location
|
|
149
|
-
rake terraform:push[name] # Push stack state to remote location
|
|
150
|
-
rake terraform:push_all # Push stack states to remote location
|
|
151
|
-
rake terraform:remote_config[name] # Sets up remote config for a stack
|
|
152
|
-
rake terraform:remote_config_all # Sets up remote config for all stacks that support it
|
|
153
|
-
rake terraform:show[name] # Show details about a stack by name
|
|
154
|
-
rake terraform:show_all # Show all pending stack changes
|
|
155
|
-
rake terraform:uuid # Generate a UUID for a stack, so stacks do not clobber each other
|
|
156
|
-
```
|
|
126
|
+
TODO
|
|
157
127
|
|
|
158
128
|
# Credits
|
|
159
129
|
|
data/bin/cloudshaper
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
$LOAD_PATH.unshift(File.expand_path('../lib', __dir__))
|
|
3
|
+
require 'cloudshaper/cli'
|
|
4
|
+
|
|
5
|
+
begin
|
|
6
|
+
ENV["THOR_DEBUG"] = "1"
|
|
7
|
+
Cloudshaper::CLI.start(ARGV)
|
|
8
|
+
rescue Thor::UndefinedCommandError, Thor::UnknownArgumentError, Thor::AmbiguousCommandError, Thor::InvocationError => e
|
|
9
|
+
$stderr.puts(e.message)
|
|
10
|
+
exit(64)
|
|
11
|
+
rescue Thor::Error => e
|
|
12
|
+
$stderr.puts(e.message)
|
|
13
|
+
exit(1)
|
|
14
|
+
end
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
lib = File.expand_path('../lib', __FILE__)
|
|
2
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
3
|
-
require '
|
|
3
|
+
require 'cloudshaper/version'
|
|
4
4
|
|
|
5
5
|
Gem::Specification.new do |spec|
|
|
6
6
|
spec.name = 'cloudshaper'
|
|
7
|
-
spec.version =
|
|
7
|
+
spec.version = Cloudshaper::VERSION
|
|
8
8
|
spec.summary = 'Wrap hashicorps "terraform" in a ruby DSL for managing stack templates'
|
|
9
|
-
spec.description = '
|
|
9
|
+
spec.description = 'Cloudshaper provides a syntax for managing terraform infrastructure entirely in git'
|
|
10
10
|
spec.authors = ['Dale Hamel']
|
|
11
11
|
spec.email = 'dale.hamel@srvthe.net'
|
|
12
12
|
spec.files = Dir['lib/**/*']
|
|
13
|
-
spec.homepage = 'https://
|
|
13
|
+
spec.homepage = 'https://github.com/dalehamel/cloudshaper'
|
|
14
14
|
spec.license = 'MIT'
|
|
15
15
|
|
|
16
16
|
spec.files = `git ls-files`.split($/)
|
|
@@ -18,8 +18,9 @@ Gem::Specification.new do |spec|
|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
19
19
|
spec.require_paths = ["lib"]
|
|
20
20
|
|
|
21
|
-
spec.add_runtime_dependency '
|
|
21
|
+
spec.add_runtime_dependency 'thor', '~> 0.19.1'
|
|
22
22
|
|
|
23
23
|
spec.add_development_dependency 'bundler'
|
|
24
|
+
spec.add_development_dependency 'rake', '~> 10.4'
|
|
24
25
|
spec.add_development_dependency 'minitest', '~> 5.6'
|
|
25
26
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
module
|
|
1
|
+
module Cloudshaper
|
|
2
2
|
# Aws provider-specific functionality, to be mixed in to stack elements
|
|
3
3
|
module Aws
|
|
4
4
|
def self.taggable?(resource_type)
|
|
@@ -17,7 +17,7 @@ module Terraform
|
|
|
17
17
|
def post_processing_aws
|
|
18
18
|
return unless Aws.taggable?(@resource_type)
|
|
19
19
|
@fields[:tags] ||= {}
|
|
20
|
-
@fields[:tags][:
|
|
20
|
+
@fields[:tags][:cloudshaper_stack_id] = var(:cloudshaper_stack_id)
|
|
21
21
|
end
|
|
22
22
|
end
|
|
23
23
|
end
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
require 'thor'
|
|
2
|
+
require 'cloudshaper'
|
|
3
|
+
|
|
4
|
+
module Cloudshaper
|
|
5
|
+
class CLI < Thor
|
|
6
|
+
class_option "template_dir", type: "string", default: "templates"
|
|
7
|
+
class_option "remote_state", type: "boolean"
|
|
8
|
+
|
|
9
|
+
desc "list", "List all available stacks"
|
|
10
|
+
def list
|
|
11
|
+
Cloudshaper::Stacks.stacks.each do |name, _stack|
|
|
12
|
+
puts name
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
desc "show NAME", "Show details about a stack by name"
|
|
17
|
+
def show(name)
|
|
18
|
+
stack = load_stack(name, options)
|
|
19
|
+
puts stack
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
desc "plan NAME", "Show pending changes for a stack"
|
|
23
|
+
def plan(name)
|
|
24
|
+
stack = load_stack(name, options)
|
|
25
|
+
stack.plan
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
desc "apply NAME", "Apply all pending stack changes"
|
|
29
|
+
def apply(name)
|
|
30
|
+
stack = load_stack(name, options)
|
|
31
|
+
stack.apply
|
|
32
|
+
push(name) if remote_state?
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
desc "destroy NAME", "Destroy a stack"
|
|
36
|
+
def destroy(name)
|
|
37
|
+
stack = load_stack(name, options)
|
|
38
|
+
stack.destroy
|
|
39
|
+
push(name) if remote_state?
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
desc "pull NAME", "Pull stack state from remote location"
|
|
43
|
+
def pull(name)
|
|
44
|
+
stack = load_stack(name, options)
|
|
45
|
+
remote_config(name)
|
|
46
|
+
stack.pull
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
desc "push NAME", "Push stack state from remote location"
|
|
50
|
+
def push(name)
|
|
51
|
+
stack = load_stack(name, options)
|
|
52
|
+
remote_config(name)
|
|
53
|
+
stack.push
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
desc "remote_config NAME", "Sets up remote config for a stack"
|
|
57
|
+
def remote_config(name)
|
|
58
|
+
stack = load_stack(name, options)
|
|
59
|
+
stack.remote_config
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
desc "init", "Initialize stacks.yml if it does not exist"
|
|
63
|
+
def init
|
|
64
|
+
Cloudshaper::Stacks.init
|
|
65
|
+
puts "Created stacks.yml, you're ready to configure your stack"
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
desc "uuid", "Generate a UUID for your stacks, so they don't clobber each other"
|
|
69
|
+
def uuid
|
|
70
|
+
puts SecureRandom.uuid
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
desc "version", "Prints the version of cloudshaper"
|
|
74
|
+
def version
|
|
75
|
+
puts Cloudshaper::VERSION
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
private
|
|
79
|
+
|
|
80
|
+
def load_stack(stack, options)
|
|
81
|
+
puts options
|
|
82
|
+
load_modules(options['template_dir'])
|
|
83
|
+
Cloudshaper::Stacks.load
|
|
84
|
+
pull(stack) if remote_state?
|
|
85
|
+
stack = Cloudshaper::Stacks.stacks[stack]
|
|
86
|
+
stack.get
|
|
87
|
+
stack
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def remote_state?
|
|
91
|
+
options["remote_stack"]
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def load_modules(dir)
|
|
95
|
+
Dir.glob("#{File.join(Dir.pwd, dir)}/*.rb").each { |t| puts t; require_relative t }
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
module
|
|
1
|
+
module Cloudshaper
|
|
2
2
|
# Wraps terraform command execution
|
|
3
3
|
class Command
|
|
4
4
|
attr_accessor :command
|
|
@@ -11,7 +11,7 @@ module Terraform
|
|
|
11
11
|
|
|
12
12
|
def env
|
|
13
13
|
vars = {}
|
|
14
|
-
@stack.
|
|
14
|
+
@stack.module.each_variable { |k, v| vars["TF_VAR_#{k}"] = v[:default] }
|
|
15
15
|
@stack.module.secrets.each do |_provider, secrets|
|
|
16
16
|
secrets.each do |k, v|
|
|
17
17
|
vars[k.to_s] = v
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require 'cloudshaper/stack_element'
|
|
2
|
+
require 'cloudshaper/stack_modules'
|
|
3
|
+
require 'cloudshaper/stack_module'
|
|
4
|
+
require 'cloudshaper/stacks'
|
|
5
|
+
|
|
6
|
+
module Cloudshaper
|
|
7
|
+
# Supports terraform 'modules'. In our case, we call them submodules because
|
|
8
|
+
# Module is a ruby keyword. We also support directly referencing other ruby-defined modules.
|
|
9
|
+
class Module < StackElement
|
|
10
|
+
def initialize(parent_module, &block)
|
|
11
|
+
super(parent_module, &block)
|
|
12
|
+
|
|
13
|
+
if StackModules.has? @fields[:source].to_s
|
|
14
|
+
mod = StackModules.get @fields[:source].to_s
|
|
15
|
+
module_path = File.join(Stacks.dir, parent_module.id, mod.name)
|
|
16
|
+
FileUtils.mkdir_p(module_path)
|
|
17
|
+
@fields[:source] = File.expand_path(module_path)
|
|
18
|
+
|
|
19
|
+
file_path = File.join(module_path, 'stack_module.tf.json')
|
|
20
|
+
build_submodule(file_path, parent_module, mod)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def build_submodule(file_path, parent_module, child_module)
|
|
25
|
+
return if File.exists? file_path
|
|
26
|
+
child_module.build(cloudshaper_stack_id: parent_module.id)
|
|
27
|
+
File.open(file_path, 'w') { |f| f.write(child_module.generate) }
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
require '
|
|
2
|
-
require '
|
|
1
|
+
require 'cloudshaper/secrets'
|
|
2
|
+
require 'cloudshaper/stack_element'
|
|
3
3
|
|
|
4
|
-
module
|
|
4
|
+
module Cloudshaper
|
|
5
5
|
# Implements DSL for a terraform provider, and a means of loading secrets.
|
|
6
6
|
class Provider < StackElement
|
|
7
7
|
def load_secrets(name)
|
|
8
8
|
@secrets ||= {}
|
|
9
|
-
|
|
9
|
+
if SECRETS.has_key? name.to_sym
|
|
10
|
+
@secrets[name.to_sym] = SECRETS[name.to_sym]
|
|
11
|
+
end
|
|
10
12
|
@secrets
|
|
11
13
|
end
|
|
12
14
|
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'cloudshaper/aws/remote_s3'
|
|
2
2
|
|
|
3
|
-
module
|
|
3
|
+
module Cloudshaper
|
|
4
4
|
# Wrap 'remote' commands, such as config, pull, and push
|
|
5
5
|
# This allows us to store state remotely using different providers
|
|
6
6
|
class Remote < Command
|
|
File without changes
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
require '
|
|
2
|
-
require '
|
|
3
|
-
require '
|
|
4
|
-
require '
|
|
1
|
+
require 'cloudshaper/stacks'
|
|
2
|
+
require 'cloudshaper/stack_modules'
|
|
3
|
+
require 'cloudshaper/command'
|
|
4
|
+
require 'cloudshaper/remote'
|
|
5
5
|
|
|
6
|
-
module
|
|
6
|
+
module Cloudshaper
|
|
7
7
|
# Wrapper to instantiate a stack from a yaml definition
|
|
8
8
|
class Stack
|
|
9
9
|
class MalformedConfig < Exception; end
|
|
@@ -20,15 +20,17 @@ module Terraform
|
|
|
20
20
|
:stack_dir, :stack_id, :remote
|
|
21
21
|
|
|
22
22
|
def initialize(config)
|
|
23
|
-
@name = config
|
|
24
|
-
@uuid = config
|
|
25
|
-
@description = config['description'] || ''
|
|
26
|
-
@variables = config['variables'] || {}
|
|
23
|
+
@name = config.fetch('name')
|
|
24
|
+
@uuid = config.fetch('uuid')
|
|
27
25
|
@remote = config['remote'] || {}
|
|
28
|
-
@
|
|
29
|
-
|
|
30
|
-
@
|
|
26
|
+
@description = config['description'] || ''
|
|
27
|
+
|
|
28
|
+
@stack_id = "cloudshaper#{@name}_#{@uuid}"
|
|
31
29
|
@stack_dir = File.join(Stacks.dir, @stack_id)
|
|
30
|
+
|
|
31
|
+
@module = StackModules.get(config.fetch('root'))
|
|
32
|
+
@variables = config['variables'] || {}
|
|
33
|
+
@variables['cloudshaper_stack_id'] = @stack_id
|
|
32
34
|
@module.build(@variables.map { |k, v| [k.to_sym, v] }.to_h)
|
|
33
35
|
end
|
|
34
36
|
|
|
@@ -64,10 +66,6 @@ module Terraform
|
|
|
64
66
|
Remote.new(self, :config).execute
|
|
65
67
|
end
|
|
66
68
|
|
|
67
|
-
def variables
|
|
68
|
-
@module.variables
|
|
69
|
-
end
|
|
70
|
-
|
|
71
69
|
def to_s
|
|
72
70
|
<<-eos
|
|
73
71
|
Name: #{@name}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'cloudshaper/aws/tagging'
|
|
2
2
|
|
|
3
|
-
module
|
|
3
|
+
module Cloudshaper
|
|
4
4
|
# Defines a single terraform stack element, subclass for any element defined in terraform DSL
|
|
5
5
|
class StackElement
|
|
6
6
|
include Aws
|
|
@@ -24,7 +24,7 @@ module Terraform
|
|
|
24
24
|
end
|
|
25
25
|
add_field(symbol, args[0])
|
|
26
26
|
else
|
|
27
|
-
add_field(symbol,
|
|
27
|
+
add_field(symbol, Cloudshaper::StackElement.new(@module, &block).fields)
|
|
28
28
|
end
|
|
29
29
|
end
|
|
30
30
|
|
|
@@ -38,6 +38,11 @@ module Terraform
|
|
|
38
38
|
"${var.#{variable_name}}"
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
+
# Reference a list variable
|
|
42
|
+
def var_list(variable_name)
|
|
43
|
+
["${split(\",\",var.#{variable_name})}"]
|
|
44
|
+
end
|
|
45
|
+
|
|
41
46
|
# Syntax to handle interpolation of resource variables
|
|
42
47
|
def value_of(resource_type, resource_name, value_type)
|
|
43
48
|
"${#{resource_type}.#{resource_name}.#{value_type}}"
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
require 'json'
|
|
2
2
|
require 'fileutils'
|
|
3
3
|
|
|
4
|
-
require '
|
|
5
|
-
require '
|
|
6
|
-
require '
|
|
7
|
-
require '
|
|
8
|
-
require '
|
|
9
|
-
require '
|
|
10
|
-
|
|
11
|
-
module
|
|
4
|
+
require 'cloudshaper/stack_modules'
|
|
5
|
+
require 'cloudshaper/resource'
|
|
6
|
+
require 'cloudshaper/provider'
|
|
7
|
+
require 'cloudshaper/variable'
|
|
8
|
+
require 'cloudshaper/module'
|
|
9
|
+
require 'cloudshaper/output'
|
|
10
|
+
|
|
11
|
+
module Cloudshaper
|
|
12
12
|
# Stack Modules contain stack elements. A stack is made up of a root module, which may have submodules
|
|
13
13
|
class StackModule
|
|
14
14
|
class << self
|
|
@@ -30,13 +30,14 @@ module Terraform
|
|
|
30
30
|
end
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
-
attr_accessor :secrets
|
|
33
|
+
attr_accessor :name, :secrets
|
|
34
34
|
|
|
35
|
-
def initialize(
|
|
35
|
+
def initialize(name, &block)
|
|
36
|
+
@name = name
|
|
36
37
|
@stack_elements = { resource: {}, provider: {}, variable: {}, output: {}, module: {} }
|
|
37
38
|
@secrets = {}
|
|
38
39
|
@block = block
|
|
39
|
-
variable(:
|
|
40
|
+
variable(:cloudshaper_stack_id) { default '' }
|
|
40
41
|
end
|
|
41
42
|
|
|
42
43
|
def clone
|
|
@@ -55,18 +56,24 @@ module Terraform
|
|
|
55
56
|
JSON.pretty_generate(elements)
|
|
56
57
|
end
|
|
57
58
|
|
|
58
|
-
def
|
|
59
|
-
|
|
59
|
+
def id
|
|
60
|
+
get(:cloudshaper_stack_id)
|
|
60
61
|
end
|
|
61
62
|
|
|
62
|
-
def
|
|
63
|
-
|
|
63
|
+
def get(variable)
|
|
64
|
+
elements[:variable].fetch(variable)[:default]
|
|
64
65
|
end
|
|
65
66
|
|
|
66
|
-
def
|
|
67
|
-
|
|
67
|
+
def each_variable(&b)
|
|
68
|
+
elements[:variable].each(&b)
|
|
68
69
|
end
|
|
69
70
|
|
|
71
|
+
def get_resource(type, id)
|
|
72
|
+
@stack_elements[:resource].fetch(type).fetch(id)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
private
|
|
76
|
+
|
|
70
77
|
def elements
|
|
71
78
|
elements = @stack_elements.clone
|
|
72
79
|
variables = StackModule.flatten_variable_arrays(@stack_elements[:variable])
|
|
@@ -77,45 +84,45 @@ module Terraform
|
|
|
77
84
|
elements
|
|
78
85
|
end
|
|
79
86
|
|
|
80
|
-
def id
|
|
81
|
-
get(:terraform_stack_id)
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
private
|
|
85
|
-
|
|
86
87
|
def register_resource(resource_type, name, &block)
|
|
87
88
|
@stack_elements[:resource] ||= {}
|
|
88
89
|
@stack_elements[:resource][resource_type.to_sym] ||= {}
|
|
89
|
-
@stack_elements[:resource][resource_type.to_sym][name.to_sym] =
|
|
90
|
+
@stack_elements[:resource][resource_type.to_sym][name.to_sym] = Cloudshaper::Resource.new(self, name, resource_type, &block).fields
|
|
90
91
|
end
|
|
91
92
|
|
|
92
93
|
def register_variable(name, &block)
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
94
|
+
return if @stack_elements[:variable].key?(name)
|
|
95
|
+
|
|
96
|
+
new_variable = Cloudshaper::Variable.new(self, &block).fields
|
|
97
|
+
if new_variable[:default].nil?
|
|
98
|
+
@stack_elements[:variable][name.to_sym] = {}
|
|
99
|
+
else
|
|
100
|
+
@stack_elements[:variable][name.to_sym] = {
|
|
101
|
+
default: new_variable[:default]
|
|
102
|
+
}
|
|
96
103
|
end
|
|
97
104
|
end
|
|
98
105
|
|
|
99
106
|
def register_output(name, &block)
|
|
100
|
-
new_output =
|
|
107
|
+
new_output = Cloudshaper::Output.new(self, &block).fields
|
|
101
108
|
@stack_elements[:output][name.to_sym] = new_output
|
|
102
109
|
end
|
|
103
110
|
|
|
104
111
|
def register_module(name, &block)
|
|
105
|
-
new_module =
|
|
112
|
+
new_module = Cloudshaper::Module.new(self, &block).fields
|
|
106
113
|
@stack_elements[:module][name.to_sym] = new_module
|
|
107
114
|
end
|
|
108
115
|
|
|
109
116
|
def register_provider(name, &block)
|
|
110
|
-
provider =
|
|
117
|
+
provider = Cloudshaper::Provider.new(self, &block)
|
|
111
118
|
@secrets.merge!(provider.load_secrets(name))
|
|
112
119
|
@stack_elements[:provider][name.to_sym] = provider.fields
|
|
113
120
|
end
|
|
114
121
|
|
|
115
|
-
alias_method :resource,
|
|
116
|
-
alias_method :variable,
|
|
117
|
-
alias_method :provider,
|
|
118
|
-
alias_method :output,
|
|
119
|
-
alias_method :submodule,
|
|
122
|
+
alias_method :resource, :register_resource
|
|
123
|
+
alias_method :variable, :register_variable
|
|
124
|
+
alias_method :provider, :register_provider
|
|
125
|
+
alias_method :output, :register_output
|
|
126
|
+
alias_method :submodule, :register_module
|
|
120
127
|
end
|
|
121
128
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
module
|
|
1
|
+
module Cloudshaper
|
|
2
2
|
# Stack module factory, register a module and provide clones of it
|
|
3
3
|
class StackModules
|
|
4
4
|
class ModuleNotFound < StandardError; end
|
|
@@ -10,13 +10,17 @@ module Terraform
|
|
|
10
10
|
@stack_modules[name.downcase] = stack_module
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
+
def has?(stack_module_name)
|
|
14
|
+
@stack_modules.key?(stack_module_name.downcase)
|
|
15
|
+
end
|
|
16
|
+
|
|
13
17
|
def get(stack_module_name)
|
|
14
18
|
fail ModuleNotFound, "#{stack_module_name} module module not found" unless @stack_modules.key?(stack_module_name.downcase)
|
|
15
19
|
@stack_modules[stack_module_name.downcase].clone
|
|
16
20
|
end
|
|
17
21
|
|
|
18
22
|
def reset!
|
|
19
|
-
@stack_modules
|
|
23
|
+
@stack_modules = {}
|
|
20
24
|
end
|
|
21
25
|
end
|
|
22
26
|
reset!
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
require 'yaml'
|
|
2
2
|
require 'securerandom'
|
|
3
3
|
|
|
4
|
-
require '
|
|
4
|
+
require 'cloudshaper/stack'
|
|
5
5
|
|
|
6
|
-
module
|
|
6
|
+
module Cloudshaper
|
|
7
7
|
# Singleton to keep track of stack templates
|
|
8
8
|
class Stacks
|
|
9
9
|
class MalformedConfig < StandardError; end
|
|
@@ -30,10 +30,6 @@ module Terraform
|
|
|
30
30
|
end
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
-
def uuid
|
|
34
|
-
"#{Time.now.utc.to_i}_#{SecureRandom.urlsafe_base64(6)}"
|
|
35
|
-
end
|
|
36
|
-
|
|
37
33
|
def base_config
|
|
38
34
|
{
|
|
39
35
|
'common' => {},
|
|
@@ -44,7 +40,7 @@ module Terraform
|
|
|
44
40
|
def base_stack_config
|
|
45
41
|
{
|
|
46
42
|
'name' => 'SET_NAME',
|
|
47
|
-
'uuid' => uuid,
|
|
43
|
+
'uuid' => SecureRandom.uuid,
|
|
48
44
|
'description' => 'SET_A_DESCRIPTION',
|
|
49
45
|
'root' => 'SET_A_TEMPLATE',
|
|
50
46
|
'variables' => {}
|
data/lib/cloudshaper.rb
ADDED
data/lib/tasks/terraform.rake
CHANGED
|
@@ -1,32 +1,32 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'cloudshaper'
|
|
2
2
|
|
|
3
3
|
namespace 'terraform' do
|
|
4
4
|
desc 'Loads available stack modules'
|
|
5
5
|
task :load do
|
|
6
|
-
|
|
6
|
+
Cloudshaper::Stacks.load
|
|
7
7
|
end
|
|
8
8
|
|
|
9
9
|
desc 'Initialize stacks.yml if it does not exist'
|
|
10
10
|
task :init do
|
|
11
|
-
|
|
11
|
+
Cloudshaper::Stacks.init
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
desc 'Fetch modules for a stack'
|
|
15
15
|
task :get, [:name] => :load do |_t, args|
|
|
16
|
-
stack =
|
|
16
|
+
stack = Cloudshaper::Stacks.stacks[args[:name]]
|
|
17
17
|
stack.get
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
desc 'Fetch modules for all stacks'
|
|
21
21
|
task get_all: :load do
|
|
22
|
-
|
|
22
|
+
Cloudshaper::Stacks.stacks.each do |_name, stack|
|
|
23
23
|
stack.get
|
|
24
24
|
end
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
desc 'List all available stacks'
|
|
28
28
|
task list: :load do
|
|
29
|
-
|
|
29
|
+
Cloudshaper::Stacks.stacks.each do |name, _stack|
|
|
30
30
|
puts name
|
|
31
31
|
end
|
|
32
32
|
end
|
|
@@ -34,14 +34,14 @@ namespace 'terraform' do
|
|
|
34
34
|
desc 'Show details about a stack by name'
|
|
35
35
|
task :show, [:name] => :load do |_t, args|
|
|
36
36
|
fail 'Specify a name' unless args[:name]
|
|
37
|
-
stack =
|
|
37
|
+
stack = Cloudshaper::Stacks.stacks[args[:name]]
|
|
38
38
|
puts stack
|
|
39
39
|
stack.plan
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
desc 'Show all pending stack changes'
|
|
43
43
|
task show_all: [:load, :get_all] do
|
|
44
|
-
|
|
44
|
+
Cloudshaper::Stacks.stacks.each do |_name, stack|
|
|
45
45
|
puts stack
|
|
46
46
|
stack.plan
|
|
47
47
|
end
|
|
@@ -50,20 +50,20 @@ namespace 'terraform' do
|
|
|
50
50
|
desc 'Show pending changes for a stack'
|
|
51
51
|
task :plan, [:name] => :load do |_t, args|
|
|
52
52
|
fail 'Specify a name' unless args[:name]
|
|
53
|
-
stack =
|
|
53
|
+
stack = Cloudshaper::Stacks.stacks[args[:name]]
|
|
54
54
|
stack.plan
|
|
55
55
|
end
|
|
56
56
|
|
|
57
57
|
desc 'Apply pending changes for a stack'
|
|
58
58
|
task :apply, [:name] => :load do |_t, args|
|
|
59
59
|
fail 'Specify a name' unless args[:name]
|
|
60
|
-
stack =
|
|
60
|
+
stack = Cloudshaper::Stacks.stacks[args[:name]]
|
|
61
61
|
stack.apply
|
|
62
62
|
end
|
|
63
63
|
|
|
64
64
|
desc 'Apply all pending stack changes'
|
|
65
65
|
task apply_all: :load do
|
|
66
|
-
|
|
66
|
+
Cloudshaper::Stacks.stacks.each do |_name, stack|
|
|
67
67
|
puts stack
|
|
68
68
|
stack.apply
|
|
69
69
|
end
|
|
@@ -72,19 +72,19 @@ namespace 'terraform' do
|
|
|
72
72
|
desc 'Destroy a stack'
|
|
73
73
|
task :destroy, [:name] => :load do |_t, args|
|
|
74
74
|
fail 'Specify a name' unless args[:name]
|
|
75
|
-
stack =
|
|
75
|
+
stack = Cloudshaper::Stacks.stacks[args[:name]]
|
|
76
76
|
stack.destroy
|
|
77
77
|
end
|
|
78
78
|
|
|
79
79
|
desc 'Push stack state to remote location'
|
|
80
80
|
task :push, [:name] => [:load, :remote_config] do |_t, args|
|
|
81
|
-
stack =
|
|
81
|
+
stack = Cloudshaper::Stacks.stacks[args[:name]]
|
|
82
82
|
stack.push
|
|
83
83
|
end
|
|
84
84
|
|
|
85
85
|
desc 'Push stack states to remote location'
|
|
86
86
|
task push_all: [:load, :remote_config_all] do
|
|
87
|
-
|
|
87
|
+
Cloudshaper::Stacks.stacks.each do |_name, stack|
|
|
88
88
|
puts stack
|
|
89
89
|
stack.push
|
|
90
90
|
end
|
|
@@ -92,13 +92,13 @@ namespace 'terraform' do
|
|
|
92
92
|
|
|
93
93
|
desc 'Pulls stack state from remote location'
|
|
94
94
|
task :pull, [:name] => [:load, :remote_config] do |_t, args|
|
|
95
|
-
stack =
|
|
95
|
+
stack = Cloudshaper::Stacks.stacks[args[:name]]
|
|
96
96
|
stack.pull
|
|
97
97
|
end
|
|
98
98
|
|
|
99
99
|
desc 'Pulls stack states from remote location'
|
|
100
100
|
task pull_all: [:load, :remote_config_all] do
|
|
101
|
-
|
|
101
|
+
Cloudshaper::Stacks.stacks.each do |_name, stack|
|
|
102
102
|
puts stack
|
|
103
103
|
stack.pull
|
|
104
104
|
end
|
|
@@ -106,13 +106,13 @@ namespace 'terraform' do
|
|
|
106
106
|
|
|
107
107
|
desc 'Sets up remote config for a stack'
|
|
108
108
|
task :remote_config, [:name] => [:load] do |_t, args|
|
|
109
|
-
stack =
|
|
109
|
+
stack = Cloudshaper::Stacks.stacks[args[:name]]
|
|
110
110
|
stack.remote_config
|
|
111
111
|
end
|
|
112
112
|
|
|
113
113
|
desc 'Sets up remote config for all stacks that support it'
|
|
114
114
|
task remote_config_all: :load do
|
|
115
|
-
|
|
115
|
+
Cloudshaper::Stacks.stacks.each do |_name, stack|
|
|
116
116
|
puts stack
|
|
117
117
|
stack.remote_config
|
|
118
118
|
end
|
|
@@ -120,7 +120,7 @@ namespace 'terraform' do
|
|
|
120
120
|
|
|
121
121
|
desc 'Generate a UUID for a stack, so stacks do not clobber each other'
|
|
122
122
|
task :uuid do
|
|
123
|
-
uuid =
|
|
123
|
+
uuid = Cloudshaper::Stacks.uuid
|
|
124
124
|
puts "uuid: #{uuid}"
|
|
125
125
|
puts 'Add this as a field to a new stack to prevent clobbering stacks with the same name'
|
|
126
126
|
end
|
data/test/stack_module_test.rb
CHANGED
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
require 'test_helper'
|
|
2
2
|
|
|
3
3
|
class StackModuleTest < Minitest::Test
|
|
4
|
-
include
|
|
4
|
+
include Cloudshaper
|
|
5
|
+
|
|
6
|
+
def setup
|
|
7
|
+
StackModules.reset!
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def test_multiple_modules_same_name_raises_exception
|
|
11
|
+
StackModule.define 'same_name_test'
|
|
12
|
+
assert_raises(StackModules::ModuleAlreadyRegistered) do
|
|
13
|
+
StackModule.define 'same_name_test'
|
|
14
|
+
end
|
|
15
|
+
end
|
|
5
16
|
|
|
6
17
|
def test_multiple_instantiations_of_module
|
|
7
18
|
StackModule.define 'factory_instantiation_test' do
|
|
@@ -19,48 +30,45 @@ class StackModuleTest < Minitest::Test
|
|
|
19
30
|
first.build(ports: '80')
|
|
20
31
|
second.build(ports: '443')
|
|
21
32
|
|
|
22
|
-
sg_first = first.
|
|
23
|
-
sg_second = second.
|
|
33
|
+
sg_first = first.get_resource(:aws_security_group, :a)
|
|
34
|
+
sg_second = second.get_resource(:aws_security_group, :a)
|
|
24
35
|
|
|
25
36
|
assert_equal '80', sg_first[:ingress].fetch(:from_port)
|
|
26
37
|
assert_equal '443', sg_second[:ingress].fetch(:from_port)
|
|
27
38
|
end
|
|
28
39
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
40
|
+
def test_module_build_registers_variable_with_defaults
|
|
41
|
+
mod = StackModule.define('variable_register_default') do
|
|
42
|
+
variable(:name) { default 'spam' }
|
|
43
|
+
end
|
|
44
|
+
mod.build
|
|
32
45
|
|
|
33
|
-
|
|
34
|
-
|
|
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
|
|
46
|
+
assert_equal 'spam', mod.get(:name)
|
|
47
|
+
end
|
|
39
48
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
49
|
+
def test_required_variable_has_no_default_value
|
|
50
|
+
mod = StackModule.define('resource_required_variable') { variable(:name) {} }
|
|
51
|
+
mod.build
|
|
43
52
|
|
|
44
|
-
|
|
45
|
-
|
|
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
|
|
53
|
+
assert_nil mod.get(:name)
|
|
54
|
+
end
|
|
50
55
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
56
|
+
def test_module_build_registers_variables_at_runtime
|
|
57
|
+
mod = StackModule.define('variable_override') do
|
|
58
|
+
variable(:name) { default 'default' }
|
|
59
|
+
end
|
|
60
|
+
mod.build(name: 'not-default')
|
|
54
61
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
# end
|
|
62
|
+
assert_equal 'not-default', mod.get(:name)
|
|
63
|
+
end
|
|
58
64
|
|
|
59
65
|
def test_register_resource
|
|
60
|
-
mod = StackModule.define('register_resource')
|
|
66
|
+
mod = StackModule.define('register_resource') do
|
|
67
|
+
resource('aws_instance', :a) { default 'default' }
|
|
68
|
+
end
|
|
61
69
|
mod.build
|
|
62
70
|
|
|
63
|
-
instance = mod.
|
|
71
|
+
instance = mod.get_resource(:aws_instance, :a)
|
|
64
72
|
assert_equal 'default', instance.fetch(:default)
|
|
65
73
|
end
|
|
66
74
|
|
|
@@ -74,7 +82,7 @@ class StackModuleTest < Minitest::Test
|
|
|
74
82
|
end
|
|
75
83
|
mod.build
|
|
76
84
|
|
|
77
|
-
instance = mod.
|
|
85
|
+
instance = mod.get_resource(:aws_instance, :a)
|
|
78
86
|
assert_equal 'root', instance.fetch(:connection).fetch(:user)
|
|
79
87
|
end
|
|
80
88
|
|
|
@@ -90,7 +98,7 @@ class StackModuleTest < Minitest::Test
|
|
|
90
98
|
end
|
|
91
99
|
mod.build
|
|
92
100
|
|
|
93
|
-
instance = mod.
|
|
101
|
+
instance = mod.get_resource(:aws_instance, :a)
|
|
94
102
|
provisioner = instance.fetch(:provisioner).first
|
|
95
103
|
connection = provisioner.fetch(:file).fetch(:connection)
|
|
96
104
|
assert_equal 'root', connection.fetch(:user)
|
|
@@ -105,7 +113,7 @@ class StackModuleTest < Minitest::Test
|
|
|
105
113
|
end
|
|
106
114
|
mod.build
|
|
107
115
|
|
|
108
|
-
sg = mod.
|
|
116
|
+
sg = mod.get_resource(:aws_security_group, :a)
|
|
109
117
|
ingress = sg.fetch(:ingress)
|
|
110
118
|
|
|
111
119
|
assert_kind_of Array, ingress
|
|
@@ -123,30 +131,8 @@ class StackModuleTest < Minitest::Test
|
|
|
123
131
|
end
|
|
124
132
|
mod.build(ports: '22,80,443')
|
|
125
133
|
|
|
126
|
-
|
|
127
|
-
sg = mod.elements.fetch(:resource).fetch(:aws_security_group).fetch(:a)
|
|
134
|
+
sg = mod.get_resource(:aws_security_group, :a)
|
|
128
135
|
ingress = sg.fetch(:ingress)
|
|
129
136
|
assert_equal [{from_port: "22"}, {from_port: "80"}, {from_port: "443"}], ingress
|
|
130
137
|
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
138
|
end
|
data/test/test_helper.rb
CHANGED
metadata
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: cloudshaper
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dale Hamel
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2015-06-
|
|
11
|
+
date: 2015-06-17 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
|
-
name:
|
|
14
|
+
name: thor
|
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
|
16
16
|
requirements:
|
|
17
17
|
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version:
|
|
19
|
+
version: 0.19.1
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version:
|
|
26
|
+
version: 0.19.1
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: bundler
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -38,6 +38,20 @@ dependencies:
|
|
|
38
38
|
- - ">="
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
40
|
version: '0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: rake
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '10.4'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '10.4'
|
|
41
55
|
- !ruby/object:Gem::Dependency
|
|
42
56
|
name: minitest
|
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -52,10 +66,11 @@ dependencies:
|
|
|
52
66
|
- - "~>"
|
|
53
67
|
- !ruby/object:Gem::Version
|
|
54
68
|
version: '5.6'
|
|
55
|
-
description:
|
|
56
|
-
|
|
69
|
+
description: Cloudshaper provides a syntax for managing terraform infrastructure entirely
|
|
70
|
+
in git
|
|
57
71
|
email: dale.hamel@srvthe.net
|
|
58
|
-
executables:
|
|
72
|
+
executables:
|
|
73
|
+
- cloudshaper
|
|
59
74
|
extensions: []
|
|
60
75
|
extra_rdoc_files: []
|
|
61
76
|
files:
|
|
@@ -67,6 +82,8 @@ files:
|
|
|
67
82
|
- README.md
|
|
68
83
|
- Rakefile
|
|
69
84
|
- TODO.md
|
|
85
|
+
- bin/cloudshaper
|
|
86
|
+
- cloudshaper.gemspec
|
|
70
87
|
- examples/secretconfig/README.md
|
|
71
88
|
- examples/secretconfig/atlas.json
|
|
72
89
|
- examples/secretconfig/aws.json
|
|
@@ -77,30 +94,29 @@ files:
|
|
|
77
94
|
- examples/secretconfig/heroku.json
|
|
78
95
|
- examples/secretconfig/mailgun.json
|
|
79
96
|
- examples/simple_app.rb
|
|
80
|
-
- lib/
|
|
97
|
+
- lib/cloudshaper.rb
|
|
98
|
+
- lib/cloudshaper/aws/remote_s3.rb
|
|
99
|
+
- lib/cloudshaper/aws/tagging.rb
|
|
100
|
+
- lib/cloudshaper/cli.rb
|
|
101
|
+
- lib/cloudshaper/command.rb
|
|
102
|
+
- lib/cloudshaper/module.rb
|
|
103
|
+
- lib/cloudshaper/output.rb
|
|
104
|
+
- lib/cloudshaper/provider.rb
|
|
105
|
+
- lib/cloudshaper/remote.rb
|
|
106
|
+
- lib/cloudshaper/resource.rb
|
|
107
|
+
- lib/cloudshaper/secrets.rb
|
|
108
|
+
- lib/cloudshaper/stack.rb
|
|
109
|
+
- lib/cloudshaper/stack_element.rb
|
|
110
|
+
- lib/cloudshaper/stack_module.rb
|
|
111
|
+
- lib/cloudshaper/stack_modules.rb
|
|
112
|
+
- lib/cloudshaper/stacks.rb
|
|
113
|
+
- lib/cloudshaper/variable.rb
|
|
114
|
+
- lib/cloudshaper/version.rb
|
|
81
115
|
- 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
116
|
- test/stack_module_test.rb
|
|
101
117
|
- test/stack_test.rb
|
|
102
118
|
- test/test_helper.rb
|
|
103
|
-
homepage: https://
|
|
119
|
+
homepage: https://github.com/dalehamel/cloudshaper
|
|
104
120
|
licenses:
|
|
105
121
|
- MIT
|
|
106
122
|
metadata: {}
|
data/lib/tasks/tasks.rb
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
require 'rake'
|
|
2
|
-
|
|
3
|
-
module Terraform
|
|
4
|
-
# Loads all rake tasks when terraform_dsl is included by a rake script
|
|
5
|
-
class Tasks
|
|
6
|
-
def self.loadall
|
|
7
|
-
Dir.glob("#{File.join(File.dirname(__dir__), 'tasks')}/*.rake").each { |r| load r }
|
|
8
|
-
template_path = ENV['TERRAFORM_TEMPLATE_PATH'] || 'templates'
|
|
9
|
-
Dir.glob("#{File.join(Dir.pwd, template_path)}/*.rb").each { |t| require_relative t }
|
|
10
|
-
end
|
|
11
|
-
end
|
|
12
|
-
end
|
data/lib/terraform_dsl/module.rb
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
require 'terraform_dsl/stack_element'
|
|
2
|
-
require 'terraform_dsl/stack_modules'
|
|
3
|
-
require 'terraform_dsl/stack_module'
|
|
4
|
-
require 'terraform_dsl/stacks'
|
|
5
|
-
|
|
6
|
-
module Terraform
|
|
7
|
-
# Supports terraform 'modules'. In our case, we call them submodules because
|
|
8
|
-
# Module is a ruby keyword. We also support directly referencing other ruby-defined modules.
|
|
9
|
-
class Module < StackElement
|
|
10
|
-
def initialize(parent_module, module_name, &block)
|
|
11
|
-
super(parent_module, &block)
|
|
12
|
-
|
|
13
|
-
if @fields[:source].match(/^module_/)
|
|
14
|
-
build_submodule(parent_module, module_name)
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
private
|
|
19
|
-
|
|
20
|
-
def build_submodule(parent_module, module_name)
|
|
21
|
-
generated = generate_child_module(parent_module)
|
|
22
|
-
module_path = File.join(Stacks.dir, parent_module.id, module_name.to_s)
|
|
23
|
-
FileUtils.mkdir_p(module_path)
|
|
24
|
-
File.open(File.join(module_path, 'stack_module.tf.json'), 'w') { |f| f.write(generated) }
|
|
25
|
-
@fields[:source] = File.expand_path(module_path)
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def generate_child_module(parent_module)
|
|
29
|
-
variables = @fields.clone
|
|
30
|
-
variables.delete(:source)
|
|
31
|
-
variables[:terraform_stack_id] = parent_module.id
|
|
32
|
-
child_name = @fields[:source].gsub(/^module_/, '')
|
|
33
|
-
child_module = StackModules.get(child_name)
|
|
34
|
-
child_module.build(variables)
|
|
35
|
-
child_module.generate
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
end
|
data/lib/terraform_dsl/output.rb
DELETED