topo-provision 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|