biosphere 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.
- checksums.yaml +7 -0
- data/bin/biosphere +105 -0
- data/examples/example.rb +24 -0
- data/lib/biosphere.rb +9 -0
- data/lib/biosphere/mixing/from_file.rb +16 -0
- data/lib/biosphere/node.rb +34 -0
- data/lib/biosphere/suite.rb +100 -0
- data/lib/biosphere/terraformproxy.rb +244 -0
- data/lib/biosphere/version.rb +3 -0
- metadata +97 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 7db29e14878fca926e12f7a6f393b1b9a469fb10
|
4
|
+
data.tar.gz: 77bd008db21e926a6e8fa2d9038a0bccc0f6931d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3718f49c615032c74a2803843096660bc9e2c1bf9c9e6d1f793f0a289f698917a4ef40c631119242c3afeeca4372df8dbb3c1a2ec83de669f13db7bde585a565
|
7
|
+
data.tar.gz: 69ca441a4659994b292630eef52e73bc827a65e9507419e2da8d742dd3041f62d88d1de9f685dd938a1e0c5765181c414176372fce2a0879ca072adf88ce6824
|
data/bin/biosphere
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
require 'biosphere'
|
4
|
+
require 'optparse'
|
5
|
+
require 'ostruct'
|
6
|
+
require 'pp'
|
7
|
+
require "awesome_print"
|
8
|
+
|
9
|
+
class BiosphereOpts
|
10
|
+
|
11
|
+
def self.parse(args)
|
12
|
+
|
13
|
+
options = OpenStruct.new
|
14
|
+
options.build = "build"
|
15
|
+
options.src = "./"
|
16
|
+
|
17
|
+
opt_parser = OptionParser.new do |opts|
|
18
|
+
|
19
|
+
|
20
|
+
opts.banner = "Usage: \"biosphere [options] <action>\""
|
21
|
+
|
22
|
+
opts.separator ""
|
23
|
+
opts.separator "Commands:"
|
24
|
+
opts.separator "\tplan\tRun the planning phase"
|
25
|
+
opts.separator "\tjson\tWrite tf files as json into build directory"
|
26
|
+
opts.separator "\taction [action]\tCall an action defined in the application .rb files"
|
27
|
+
opts.separator ""
|
28
|
+
|
29
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
30
|
+
puts opts
|
31
|
+
exit
|
32
|
+
end
|
33
|
+
|
34
|
+
opts.on("--src PATH", "Directory where the application .rb files are") do |path|
|
35
|
+
options.src = path
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
opts.on("--build PATH", "Directory where to build json files") do |path|
|
40
|
+
options.build = path
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
opt_parser.parse!(args)
|
46
|
+
options
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
|
53
|
+
options = BiosphereOpts.parse(ARGV)
|
54
|
+
|
55
|
+
if ARGV.length == 0
|
56
|
+
STDERR.puts "No action spesified. Use -h to get help."
|
57
|
+
exit -1
|
58
|
+
end
|
59
|
+
|
60
|
+
if !File.directory?(options.src)
|
61
|
+
STDERR.puts "Directory #{options.build} is not a directory or it doesn't exists."
|
62
|
+
exit -1
|
63
|
+
end
|
64
|
+
|
65
|
+
if options.src
|
66
|
+
suite = Biosphere::Suite.new(options.src)
|
67
|
+
suite.load_all()
|
68
|
+
else
|
69
|
+
STDERR.puts "No --src set"
|
70
|
+
end
|
71
|
+
|
72
|
+
if ARGV[0] == "json" && options.src
|
73
|
+
suite.evaluate_resources()
|
74
|
+
|
75
|
+
if !File.directory?(options.build)
|
76
|
+
STDERR.puts "Directory #{options.build} is not a directory or it doesn't exists."
|
77
|
+
exit -1
|
78
|
+
end
|
79
|
+
|
80
|
+
count = 0
|
81
|
+
suite.write_json_to(options.build) do |file_name, destination, str, proxy|
|
82
|
+
puts "Wrote #{str.length} bytes from #{file_name} to #{destination} (#{proxy.export["resource"].length} resources)"
|
83
|
+
count = count + 1
|
84
|
+
end
|
85
|
+
|
86
|
+
puts "Wrote #{count} files into #{options.build}"
|
87
|
+
suite.save_node()
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
if ARGV[0] == "plan" && options.src
|
92
|
+
suite.evaluate_plans()
|
93
|
+
ap suite.node
|
94
|
+
end
|
95
|
+
|
96
|
+
if ARGV[0] == "action" && options.src
|
97
|
+
context = Biosphere::ActionContext.new()
|
98
|
+
|
99
|
+
context.build_directory = options.build
|
100
|
+
|
101
|
+
suite.call_action(ARGV[1], context)
|
102
|
+
|
103
|
+
suite.save_node()
|
104
|
+
end
|
105
|
+
|
data/examples/example.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
|
2
|
+
puts "At example.rb"
|
3
|
+
|
4
|
+
resource "type", "name",
|
5
|
+
foo: "one",
|
6
|
+
bar: false
|
7
|
+
|
8
|
+
resource "aws_vpc", "default",
|
9
|
+
cidr_block: "1.0.0.0/16",
|
10
|
+
enable_dns_hostnames: true,
|
11
|
+
tags: {
|
12
|
+
Name: "Garo's machine"
|
13
|
+
}
|
14
|
+
|
15
|
+
resource "aws_security_group", "nat",
|
16
|
+
name: "vpc-nat",
|
17
|
+
ingress: [
|
18
|
+
{
|
19
|
+
from_port: 80,
|
20
|
+
to_port: 80,
|
21
|
+
protocol: "tcp",
|
22
|
+
cidr_blocks: ["${var.private_subnet_cidr}"]
|
23
|
+
}
|
24
|
+
]
|
data/lib/biosphere.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
|
2
|
+
class Biosphere
|
3
|
+
module Mixing
|
4
|
+
module FromFile
|
5
|
+
def from_file(filename)
|
6
|
+
|
7
|
+
if File.exists?(filename) && File.readable?(filename)
|
8
|
+
self.instance_eval(IO.read(filename), filename, 1)
|
9
|
+
else
|
10
|
+
raise IOError, "Cannot open or read #{filename}!"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'pp'
|
2
|
+
|
3
|
+
class Biosphere
|
4
|
+
class Node
|
5
|
+
attr_reader :data
|
6
|
+
def initialize(from_string = nil)
|
7
|
+
if from_string
|
8
|
+
blob = Marshal.load(from_string)
|
9
|
+
@data = blob.data
|
10
|
+
else
|
11
|
+
@data = {}
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def include?(symbol)
|
16
|
+
@data.include?(symbol)
|
17
|
+
end
|
18
|
+
|
19
|
+
def []=(symbol, *args)
|
20
|
+
@data[symbol] = args[0]
|
21
|
+
end
|
22
|
+
|
23
|
+
def [](symbol, *args)
|
24
|
+
if !@data[symbol]
|
25
|
+
@data[symbol] = Node.new
|
26
|
+
end
|
27
|
+
return @data[symbol]
|
28
|
+
end
|
29
|
+
|
30
|
+
def save()
|
31
|
+
return Marshal.dump(self)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'pp'
|
2
|
+
require 'ipaddress'
|
3
|
+
require 'biosphere/node'
|
4
|
+
|
5
|
+
class Biosphere
|
6
|
+
class Suite
|
7
|
+
|
8
|
+
attr_accessor :files
|
9
|
+
attr_accessor :actions
|
10
|
+
|
11
|
+
def initialize(directory)
|
12
|
+
|
13
|
+
@files = {}
|
14
|
+
@actions = {}
|
15
|
+
@directory = directory
|
16
|
+
|
17
|
+
files = Dir::glob("#{directory}/*.rb")
|
18
|
+
|
19
|
+
@plan_proxy = PlanProxy.new
|
20
|
+
|
21
|
+
for file in files
|
22
|
+
proxy = Biosphere::TerraformProxy.new(file, @plan_proxy)
|
23
|
+
|
24
|
+
@files[file[directory.length+1..-1]] = proxy
|
25
|
+
end
|
26
|
+
|
27
|
+
if File.exists?(directory + "/state.node")
|
28
|
+
@plan_proxy.node = Marshal.load(File.read(directory + "/state.node"))
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def node(name=nil)
|
33
|
+
if name
|
34
|
+
return @plan_proxy.node[name]
|
35
|
+
else
|
36
|
+
return @plan_proxy.node
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
def evaluate_resources()
|
42
|
+
@files.each do |file_name, proxy|
|
43
|
+
proxy.evaluate_resources()
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def load_all()
|
48
|
+
@files.each do |file_name, proxy|
|
49
|
+
proxy.load_from_file()
|
50
|
+
|
51
|
+
proxy.actions.each do |key, value|
|
52
|
+
|
53
|
+
if @actions[key]
|
54
|
+
raise "Action '#{key}' already defined at #{value[:location]}"
|
55
|
+
end
|
56
|
+
@actions[key] = value
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def save_node(filename = "state.node")
|
62
|
+
str = Marshal.dump(@plan_proxy.node)
|
63
|
+
File.write(@directory + "/" + filename, str)
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
def evaluate_plans()
|
68
|
+
@files.each do |file_name, proxy|
|
69
|
+
puts "evaluating plans for #{file_name}"
|
70
|
+
|
71
|
+
proxy.evaluate_plans()
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def call_action(name, context)
|
76
|
+
@files.each do |file_name, proxy|
|
77
|
+
if proxy.actions[name]
|
78
|
+
proxy.call_action(name, context)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def write_json_to(destination_dir)
|
84
|
+
if !File.directory?(destination_dir)
|
85
|
+
Dir.mkdir(destination_dir)
|
86
|
+
end
|
87
|
+
|
88
|
+
@files.each do |file_name, proxy|
|
89
|
+
json_name = file_name[0..-4] + ".json.tf"
|
90
|
+
str = proxy.to_json(true) + "\n"
|
91
|
+
destination_name = destination_dir + "/" + json_name
|
92
|
+
File.write(destination_name, str)
|
93
|
+
|
94
|
+
yield file_name, destination_name, str, proxy if block_given?
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,244 @@
|
|
1
|
+
require 'biosphere/mixing/from_file.rb'
|
2
|
+
require 'json'
|
3
|
+
require 'pathname'
|
4
|
+
|
5
|
+
class Biosphere
|
6
|
+
class ActionContext
|
7
|
+
attr_accessor :build_directory
|
8
|
+
attr_accessor :caller
|
9
|
+
|
10
|
+
def initialize()
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
def method_missing(symbol, *args)
|
15
|
+
#puts ">>>>>>>> method missing: #{symbol}, #{args}"
|
16
|
+
|
17
|
+
if @caller.methods.include?(symbol)
|
18
|
+
return @caller.method(symbol).call(*args)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
class PlanProxy
|
27
|
+
attr_accessor :node
|
28
|
+
def initialize()
|
29
|
+
@node = Node.new
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
class ResourceProxy
|
35
|
+
attr_reader :output
|
36
|
+
attr_reader :caller
|
37
|
+
|
38
|
+
def initialize(caller)
|
39
|
+
@output = {}
|
40
|
+
@caller = caller
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
def respond_to?(symbol, include_private = false)
|
45
|
+
return true
|
46
|
+
end
|
47
|
+
|
48
|
+
def method_missing(symbol, *args)
|
49
|
+
#puts ">>>>>>>> method missing: #{symbol}, #{args}"
|
50
|
+
|
51
|
+
if @caller.methods.include?(symbol)
|
52
|
+
return @caller.method(symbol).call(*args)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Support getter here
|
56
|
+
if args.length == 0
|
57
|
+
return @output[symbol]
|
58
|
+
end
|
59
|
+
|
60
|
+
# Support setter here
|
61
|
+
if [:ingress, :egress, :route].include?(symbol)
|
62
|
+
@output[symbol] ||= []
|
63
|
+
if args[0].kind_of?(Array)
|
64
|
+
@output[symbol] += args[0]
|
65
|
+
else
|
66
|
+
@output[symbol] << args[0]
|
67
|
+
end
|
68
|
+
else
|
69
|
+
@output[symbol] = args[0]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
class TerraformProxy
|
75
|
+
|
76
|
+
attr_accessor :export
|
77
|
+
attr_accessor :resources
|
78
|
+
attr_accessor :actions
|
79
|
+
attr_accessor :plans
|
80
|
+
attr_accessor :plan_proxy
|
81
|
+
attr_reader :src_path
|
82
|
+
|
83
|
+
|
84
|
+
def initialize(script_name, plan_proxy = nil)
|
85
|
+
@script_name = script_name
|
86
|
+
@src_path = [File.dirname(script_name)]
|
87
|
+
|
88
|
+
@export = {
|
89
|
+
"provider" => {},
|
90
|
+
"resource" => {},
|
91
|
+
"variable" => {},
|
92
|
+
"output" => {}
|
93
|
+
}
|
94
|
+
if !plan_proxy
|
95
|
+
plan_proxy = PlanProxy.new
|
96
|
+
end
|
97
|
+
@plan_proxy = plan_proxy
|
98
|
+
@resources = []
|
99
|
+
@actions = {}
|
100
|
+
@plans = []
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
def load_from_file()
|
105
|
+
self.from_file(@script_name)
|
106
|
+
end
|
107
|
+
|
108
|
+
def load_from_block(&block)
|
109
|
+
self.instance_eval(&block)
|
110
|
+
end
|
111
|
+
|
112
|
+
def load(filename)
|
113
|
+
src_path = Pathname.new(@src_path.last + "/" + File.dirname(filename)).cleanpath.to_s
|
114
|
+
# Push current src_path and overwrite @src_path so that it tracks recursive loads
|
115
|
+
@src_path << src_path
|
116
|
+
|
117
|
+
#puts "Trying to open file: " + src_path + "/" + File.basename(filename)
|
118
|
+
if File.exists?(src_path + "/" + File.basename(filename))
|
119
|
+
self.from_file(src_path + "/" + File.basename(filename))
|
120
|
+
elsif File.exists?(src_path + "/" + File.basename(filename) + ".rb")
|
121
|
+
self.from_file(src_path + "/" + File.basename(filename) + ".rb")
|
122
|
+
else
|
123
|
+
raise "Can't find #{filename}"
|
124
|
+
end
|
125
|
+
|
126
|
+
# Restore it as we are unwinding the call stack
|
127
|
+
@src_path.pop
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
include Biosphere::Mixing::FromFile
|
132
|
+
|
133
|
+
def provider(name, spec={})
|
134
|
+
@export["provider"][name.to_s] = spec
|
135
|
+
end
|
136
|
+
|
137
|
+
def variable(name, value)
|
138
|
+
@export["variable"][name] = {
|
139
|
+
"default" => value
|
140
|
+
}
|
141
|
+
end
|
142
|
+
|
143
|
+
def output(name, value)
|
144
|
+
@export["output"][name] = {
|
145
|
+
"value" => value
|
146
|
+
}
|
147
|
+
end
|
148
|
+
|
149
|
+
def action(name, description, &block)
|
150
|
+
@actions[name] = {
|
151
|
+
:name => name,
|
152
|
+
:description => description,
|
153
|
+
:block => block,
|
154
|
+
:location => caller[0]
|
155
|
+
}
|
156
|
+
end
|
157
|
+
|
158
|
+
def plan(name, &block)
|
159
|
+
plan = {
|
160
|
+
:name => name,
|
161
|
+
:block => block,
|
162
|
+
:location => caller[0]
|
163
|
+
}
|
164
|
+
@plans << plan
|
165
|
+
end
|
166
|
+
|
167
|
+
def node
|
168
|
+
return @plan_proxy.node
|
169
|
+
end
|
170
|
+
|
171
|
+
def evaluate_plans()
|
172
|
+
@plans.each do |resource|
|
173
|
+
@plan_proxy.instance_eval(&resource[:block])
|
174
|
+
end
|
175
|
+
|
176
|
+
end
|
177
|
+
|
178
|
+
def call_action(name, context)
|
179
|
+
context.caller = self
|
180
|
+
|
181
|
+
context.instance_eval(&@actions[name][:block])
|
182
|
+
end
|
183
|
+
|
184
|
+
def resource(type, name, &block)
|
185
|
+
@export["resource"][type.to_s] ||= {}
|
186
|
+
if @export["resource"][type.to_s][name.to_s]
|
187
|
+
throw "Tried to create a resource of type #{type} called '#{name}' when one already exists"
|
188
|
+
end
|
189
|
+
|
190
|
+
spec = {}
|
191
|
+
resource = {
|
192
|
+
:name => name,
|
193
|
+
:type => type,
|
194
|
+
:location => caller[0] + "a"
|
195
|
+
}
|
196
|
+
|
197
|
+
if block_given?
|
198
|
+
resource[:block] = block
|
199
|
+
else
|
200
|
+
STDERR.puts("WARNING: No block set for resource call '#{type}', '#{name}' at #{caller[0]}")
|
201
|
+
end
|
202
|
+
|
203
|
+
|
204
|
+
|
205
|
+
@resources << resource
|
206
|
+
|
207
|
+
end
|
208
|
+
|
209
|
+
def evaluate_resources()
|
210
|
+
@resources.each do |resource|
|
211
|
+
proxy = ResourceProxy.new(self)
|
212
|
+
proxy.instance_eval(&resource[:block])
|
213
|
+
|
214
|
+
@export["resource"][resource[:type].to_s][resource[:name].to_s] = proxy.output
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
def id_of(type,name)
|
219
|
+
"${#{type}.#{name}.id}"
|
220
|
+
end
|
221
|
+
|
222
|
+
def output_of(type, name, *values)
|
223
|
+
"${#{type}.#{name}.#{values.join(".")}}"
|
224
|
+
end
|
225
|
+
|
226
|
+
def add_resource_alias(type)
|
227
|
+
define_singleton_method type.to_sym do |name, spec={}|
|
228
|
+
resource(type, name, spec)
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
def use_resource_shortcuts!
|
233
|
+
require_relative 'resource_shortcuts'
|
234
|
+
end
|
235
|
+
|
236
|
+
def to_json(pretty=false)
|
237
|
+
if pretty
|
238
|
+
return JSON.pretty_generate(@export)
|
239
|
+
else
|
240
|
+
return JSON.generate(@export)
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
metadata
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: biosphere
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Juho Mäkinen
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-11-01 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rspec
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 3.4.0
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 3.4.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: ipaddress
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.8.3
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.8.3
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: awesome_print
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 1.7.0
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.7.0
|
55
|
+
description: "Terraform's HCL lacks quite many programming features like iterators,
|
56
|
+
true variables, advanced string manipulation, functions etc.\n\n This Ruby tool
|
57
|
+
provides an easy-to-use DSL to define Terraform compatible .json files which can
|
58
|
+
then be used with Terraform side-by-side with HCL files.\n "
|
59
|
+
email: juho@unity3d.com
|
60
|
+
executables:
|
61
|
+
- biosphere
|
62
|
+
extensions: []
|
63
|
+
extra_rdoc_files: []
|
64
|
+
files:
|
65
|
+
- bin/biosphere
|
66
|
+
- examples/example.rb
|
67
|
+
- lib/biosphere.rb
|
68
|
+
- lib/biosphere/mixing/from_file.rb
|
69
|
+
- lib/biosphere/node.rb
|
70
|
+
- lib/biosphere/suite.rb
|
71
|
+
- lib/biosphere/terraformproxy.rb
|
72
|
+
- lib/biosphere/version.rb
|
73
|
+
homepage: http://github.com/UnityTech/biosphere
|
74
|
+
licenses:
|
75
|
+
- MIT
|
76
|
+
metadata: {}
|
77
|
+
post_install_message:
|
78
|
+
rdoc_options: []
|
79
|
+
require_paths:
|
80
|
+
- lib
|
81
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
requirements: []
|
92
|
+
rubyforge_project:
|
93
|
+
rubygems_version: 2.4.5.1
|
94
|
+
signing_key:
|
95
|
+
specification_version: 4
|
96
|
+
summary: Tool to provision VPC with Terraform with a Ruby DSL
|
97
|
+
test_files: []
|