topo-provision 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/LICENSE +201 -0
- data/README.md +100 -0
- data/bin/topo-provision +23 -0
- data/lib/topo/converter.rb +80 -0
- data/lib/topo/converter/cloudformation/converter.rb +219 -0
- data/lib/topo/exporter.rb +15 -0
- data/lib/topo/loader.rb +31 -0
- data/lib/topo/provision.rb +3 -0
- data/lib/topo/provision/aws/generator.rb +55 -0
- data/lib/topo/provision/aws/generators/aws_auto_scaling_group.rb +61 -0
- data/lib/topo/provision/aws/generators/aws_launch_configuration.rb +65 -0
- data/lib/topo/provision/aws/generators/context.rb +33 -0
- data/lib/topo/provision/aws/generators/load_balancer.rb +47 -0
- data/lib/topo/provision/aws/generators/machine.rb +36 -0
- data/lib/topo/provision/aws/generators/machine_image.rb +38 -0
- data/lib/topo/provision/aws/generators/node_group.rb +64 -0
- data/lib/topo/provision/cli.rb +95 -0
- data/lib/topo/provision/generator.rb +185 -0
- data/lib/topo/provision/generators/chef_node.rb +35 -0
- data/lib/topo/provision/generators/context.rb +70 -0
- data/lib/topo/provision/generators/load_balancer.rb +40 -0
- data/lib/topo/provision/generators/machine.rb +50 -0
- data/lib/topo/provision/generators/machine_image.rb +43 -0
- data/lib/topo/provision/generators/node_group.rb +74 -0
- data/lib/topo/provision/generators/resource.rb +91 -0
- data/lib/topo/provision/generators/templates/context.erb +8 -0
- data/lib/topo/provision/generators/templates/machine_deploy.erb +11 -0
- data/lib/topo/provision/generators/templates/machine_stop.erb +5 -0
- data/lib/topo/provision/generators/templates/node_group_action.erb +6 -0
- data/lib/topo/provision/generators/templates/node_group_deploy.erb +5 -0
- data/lib/topo/provision/generators/templates/resource_deploy.erb +5 -0
- data/lib/topo/provision/generators/templates/resource_undeploy.erb +5 -0
- data/lib/topo/provision/topology_generator.rb +84 -0
- data/lib/topo/provision/vagrant/generator.rb +33 -0
- data/lib/topo/provision/version.rb +5 -0
- data/lib/topo/topology.rb +61 -0
- data/lib/topo/utils/output.rb +31 -0
- data/lib/topo/utils/parsegen.rb +101 -0
- metadata +126 -0
@@ -0,0 +1,43 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Christine Draper (<christine_draper@thirdwaveinsights.com>)
|
3
|
+
# Copyright:: Copyright (c) 2015 ThirdWave Insights LLC
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'topo/provision/generators/resource'
|
20
|
+
|
21
|
+
#
|
22
|
+
# The ResourceGenerator class generates the recipe resources
|
23
|
+
#
|
24
|
+
|
25
|
+
module Topo
|
26
|
+
module Provision
|
27
|
+
class MachineImageGenerator < Topo::Provision::MachineGenerator
|
28
|
+
|
29
|
+
attr_reader :machine_options, :normal_attributes, :lazy_attributes
|
30
|
+
|
31
|
+
def initialize(data)
|
32
|
+
@resource_type ||= "machine_image"
|
33
|
+
super
|
34
|
+
@name = data['name'] + "_image"
|
35
|
+
@template_base_name = "machine"
|
36
|
+
# Note: specific driver may need to convert image options to symbols
|
37
|
+
opts = data['provisioning']['image_options']
|
38
|
+
@resource_attributes["image_options"] = opts if opts
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Christine Draper (<christine_draper@thirdwaveinsights.com>)
|
3
|
+
# Copyright:: Copyright (c) 2015 ThirdWave Insights LLC
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'topo/provision/generators/resource'
|
20
|
+
require 'topo/utils/output'
|
21
|
+
|
22
|
+
#
|
23
|
+
# The NodeGroupGenerator class generates multiple resources depending on the node data
|
24
|
+
#
|
25
|
+
|
26
|
+
module Topo
|
27
|
+
module Provision
|
28
|
+
class NodeGroupGenerator < Topo::Provision::ResourceGenerator
|
29
|
+
include Topo::Output
|
30
|
+
|
31
|
+
attr_reader :size
|
32
|
+
|
33
|
+
def initialize(data, machine_generator=nil)
|
34
|
+
@resource_type ||= "machine_batch"
|
35
|
+
super(data)
|
36
|
+
@template_base_name = "node_group"
|
37
|
+
machine_data = data.clone
|
38
|
+
@size = value_from_path(data, %w[provisioning node_group size])
|
39
|
+
# append a number to the name if size is specified
|
40
|
+
if !@size.nil?
|
41
|
+
machine_data['name'] = "#{data['name']}\#{i}"
|
42
|
+
end
|
43
|
+
@size ||= 1
|
44
|
+
@machine_generator = machine_generator || Topo::Provision::MachineGenerator.new(machine_data)
|
45
|
+
end
|
46
|
+
|
47
|
+
def deploy()
|
48
|
+
# temporarily divert stdout & perform machine action
|
49
|
+
machine_output = divert_stdout do
|
50
|
+
@machine_generator.deploy
|
51
|
+
end
|
52
|
+
# put into batch
|
53
|
+
puts(template("deploy").result(binding))
|
54
|
+
end
|
55
|
+
|
56
|
+
def undeploy()
|
57
|
+
batch_action(:undeploy)
|
58
|
+
end
|
59
|
+
|
60
|
+
def stop()
|
61
|
+
batch_action(:stop)
|
62
|
+
end
|
63
|
+
|
64
|
+
def batch_action(action)
|
65
|
+
machine_names = []
|
66
|
+
1.upto @size do |i|
|
67
|
+
machine_names << "#{name}#{@size}"
|
68
|
+
end
|
69
|
+
puts(template("action").result(binding))
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Christine Draper (<christine_draper@thirdwaveinsights.com>)
|
3
|
+
# Copyright:: Copyright (c) 2015 ThirdWave Insights LLC
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'topo/utils/parsegen'
|
20
|
+
|
21
|
+
#
|
22
|
+
# The ResourceGenerator class generates the recipe resources
|
23
|
+
#
|
24
|
+
|
25
|
+
module Topo
|
26
|
+
module Provision
|
27
|
+
|
28
|
+
class ResourceGenerator
|
29
|
+
include Topo::ParseGen
|
30
|
+
|
31
|
+
attr_reader :resource_type, :name, :resource_attributes, :undeploy_action
|
32
|
+
@@templates = {}
|
33
|
+
|
34
|
+
def initialize(data)
|
35
|
+
@resource_type||= "resource" # define in each class
|
36
|
+
@template_base_name = @resource_type
|
37
|
+
@undeploy_action = "delete"
|
38
|
+
@resource_attributes = {} # define in each class
|
39
|
+
@name = data['name']
|
40
|
+
provisioning = data['provisioning']
|
41
|
+
%w[ driver chef_server].each do |key|
|
42
|
+
@resource_attributes[key] = provisioning[key] if provisioning && provisioning.key?(key)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def do_action(action)
|
47
|
+
if (self.respond_to? action)
|
48
|
+
self.send(action)
|
49
|
+
else
|
50
|
+
self.send("default_action", action)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def deploy()
|
55
|
+
puts(template("deploy").result(binding))
|
56
|
+
end
|
57
|
+
|
58
|
+
def undeploy()
|
59
|
+
puts(template("undeploy").result(binding))
|
60
|
+
end
|
61
|
+
|
62
|
+
def default_action(action)
|
63
|
+
end
|
64
|
+
|
65
|
+
def template_root_dir
|
66
|
+
File.expand_path("../templates", __FILE__)
|
67
|
+
end
|
68
|
+
|
69
|
+
def default_resource_template(action)
|
70
|
+
default = "resource_#{action}"
|
71
|
+
if @@templates[default] == nil
|
72
|
+
path = File.join(File.expand_path("../templates", __FILE__), "#{default}.erb")
|
73
|
+
@@templates[default] = ERB.new(File.new(path).read, nil, '>')
|
74
|
+
end
|
75
|
+
@@templates[default]
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
def template(action)
|
80
|
+
name = "#{@template_base_name}_#{action}"
|
81
|
+
if (@@templates[name] == nil)
|
82
|
+
path = File.join(template_root_dir, "#{name}.erb")
|
83
|
+
@@templates[name] = File.exists?(path) ? ERB.new(File.new(path).read, nil, '>') :
|
84
|
+
default_resource_template(action)
|
85
|
+
end
|
86
|
+
@@templates[name]
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
require '<%= @require_driver %>'
|
2
|
+
|
3
|
+
#### THIS RECIPE IS AUTO-GENERATED BY TOPO-PROVISION - EDITS WILL BE OVERWRITTEN ####
|
4
|
+
|
5
|
+
|
6
|
+
<% if (@driver) %><%= "with_driver('#{@driver}')\n" %><% end %>
|
7
|
+
<% if (@machine_options) %><%= "with_machine_options(#{@machine_options.inspect})\n" %><% end %>
|
8
|
+
|
@@ -0,0 +1,11 @@
|
|
1
|
+
|
2
|
+
<%= resource_type %> "<%= name %>" do
|
3
|
+
<% resource_attributes.each do |key, val| %><%=" #{key}(#{val.inspect})\n" %><% end %>
|
4
|
+
<% normal_attributes.each do |key, val| %><%=" attribute '#{key}', #{val.inspect} \n" %><% end %>
|
5
|
+
<% lazy_attributes.each do |key, val| %><%=" attribute '#{key}', lazy{
|
6
|
+
topo_search_node_fn = Proc.new { |node, path| (search(:node, \"name:\" + node, :filter_result => { 'val' => path }).first)['data']['val'] }
|
7
|
+
{#{val}}
|
8
|
+
} \n" %><% end %>
|
9
|
+
<% if (machine_options) %><%= " add_machine_options(#{machine_options.inspect})\n" %><% end %>
|
10
|
+
end
|
11
|
+
|
@@ -0,0 +1,84 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Christine Draper (<christine_draper@thirdwaveinsights.com>)
|
3
|
+
# Copyright:: Copyright (c) 2015 ThirdWave Insights LLC
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'tsort'
|
20
|
+
|
21
|
+
#
|
22
|
+
# The Resource Graph class sorts nodes and services based on their dependencies (topo references)
|
23
|
+
#
|
24
|
+
|
25
|
+
module Topo
|
26
|
+
module Provision
|
27
|
+
class TopologyGenerator
|
28
|
+
|
29
|
+
def initialize
|
30
|
+
@dep = {}
|
31
|
+
end
|
32
|
+
|
33
|
+
# resource - the resource hash
|
34
|
+
# depends_on - an array of resource names
|
35
|
+
# generators - a hash of lambdas that are generator code to run for that resource
|
36
|
+
# keys are: :deploy :undeploy
|
37
|
+
# will be called as block.call resource
|
38
|
+
def add(resource, depends_on=[], generators={})
|
39
|
+
@dep[resource['name']] = [ resource, depends_on, generators ]
|
40
|
+
end
|
41
|
+
|
42
|
+
def tsort_each_node(&block)
|
43
|
+
@dep.each_key(&block)
|
44
|
+
end
|
45
|
+
|
46
|
+
def tsort_each_child(node, &block)
|
47
|
+
resource, depends_on, gen = @dep.fetch node
|
48
|
+
depends_on.each(&block)
|
49
|
+
end
|
50
|
+
|
51
|
+
def generate(action=:deploy)
|
52
|
+
each_strongly_connected_component { |nodes|
|
53
|
+
STDERR.puts "WARN: Topology contains a cyclic dependency: #{nodes.inspect}" if nodes.length > 1
|
54
|
+
nodes.each { |node|
|
55
|
+
resource, depends_on, gen_data = @dep.fetch node
|
56
|
+
resource_generator = gen_data[:resource_generator]
|
57
|
+
if resource_generator && resource_generator.respond_to?(action)
|
58
|
+
resource_generator.send(action)
|
59
|
+
else
|
60
|
+
resource_generator.send("default_action", action)
|
61
|
+
end
|
62
|
+
}
|
63
|
+
}
|
64
|
+
end
|
65
|
+
|
66
|
+
def reverse_generate(action=:undeploy)
|
67
|
+
strongly_connected_components.reverse_each { |nodes|
|
68
|
+
STDERR.puts "WARN: Topology contains a cyclic dependency: #{nodes.inspect}" if nodes.length > 1
|
69
|
+
nodes.each { |node|
|
70
|
+
resource, depends_on, gen_data = @dep.fetch node
|
71
|
+
resource_generator = gen_data[:resource_generator]
|
72
|
+
if resource_generator && resource_generator.respond_to?(action)
|
73
|
+
resource_generator.send(action)
|
74
|
+
else
|
75
|
+
resource_generator.send("default_action", action)
|
76
|
+
end
|
77
|
+
}
|
78
|
+
}
|
79
|
+
end
|
80
|
+
|
81
|
+
include TSort
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Christine Draper (<christine_draper@thirdwaveinsights.com>)
|
3
|
+
# Copyright:: Copyright (c) 2015 ThirdWave Insights LLC
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'topo/provision/generator'
|
20
|
+
require 'topo/topology'
|
21
|
+
require 'json'
|
22
|
+
|
23
|
+
|
24
|
+
module Topo
|
25
|
+
module Provision
|
26
|
+
class VagrantGenerator < Topo::Provision::Generator
|
27
|
+
|
28
|
+
self.register_generator("vagrant", self.name)
|
29
|
+
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Christine Draper (<christine_draper@thirdwaveinsights.com>)
|
3
|
+
# Copyright:: Copyright (c) 2015 ThirdWave Insights LLC
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'json'
|
20
|
+
|
21
|
+
module Topo
|
22
|
+
class Topology
|
23
|
+
|
24
|
+
attr_accessor :nodes, :provisioning, :driver, :services, :network, :format
|
25
|
+
attr_reader :raw_data
|
26
|
+
|
27
|
+
def initialize(raw_data)
|
28
|
+
@raw_data = raw_data
|
29
|
+
|
30
|
+
data = Marshal.load(Marshal.dump(raw_data))
|
31
|
+
@provisioning = data['provisioning'] || {}
|
32
|
+
if @provisioning['driver']
|
33
|
+
@driver = @provisioning['driver'].split(":",2)[0]
|
34
|
+
else
|
35
|
+
@driver = "default"
|
36
|
+
end
|
37
|
+
@nodes = data['nodes'] || []
|
38
|
+
@services = data['services'] || []
|
39
|
+
@network = data['network'] || []
|
40
|
+
|
41
|
+
@nodes.each do |node|
|
42
|
+
parse_node node
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def parse_node(node)
|
47
|
+
node['attributes'] = node['normal'] if node['normal']
|
48
|
+
node['attributes'] ||= {}
|
49
|
+
|
50
|
+
node['lazy_attributes'] ||= {}
|
51
|
+
end
|
52
|
+
|
53
|
+
def to_file(file)
|
54
|
+
begin
|
55
|
+
File.open(file, 'w') { |f| f.write(JSON.pretty_generate(@raw_data)) }
|
56
|
+
rescue => e
|
57
|
+
STDERR.puts "ERROR: Cannot write to topology export file #{file} - #{e.message}"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|