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.
Files changed (40) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +201 -0
  3. data/README.md +100 -0
  4. data/bin/topo-provision +23 -0
  5. data/lib/topo/converter.rb +80 -0
  6. data/lib/topo/converter/cloudformation/converter.rb +219 -0
  7. data/lib/topo/exporter.rb +15 -0
  8. data/lib/topo/loader.rb +31 -0
  9. data/lib/topo/provision.rb +3 -0
  10. data/lib/topo/provision/aws/generator.rb +55 -0
  11. data/lib/topo/provision/aws/generators/aws_auto_scaling_group.rb +61 -0
  12. data/lib/topo/provision/aws/generators/aws_launch_configuration.rb +65 -0
  13. data/lib/topo/provision/aws/generators/context.rb +33 -0
  14. data/lib/topo/provision/aws/generators/load_balancer.rb +47 -0
  15. data/lib/topo/provision/aws/generators/machine.rb +36 -0
  16. data/lib/topo/provision/aws/generators/machine_image.rb +38 -0
  17. data/lib/topo/provision/aws/generators/node_group.rb +64 -0
  18. data/lib/topo/provision/cli.rb +95 -0
  19. data/lib/topo/provision/generator.rb +185 -0
  20. data/lib/topo/provision/generators/chef_node.rb +35 -0
  21. data/lib/topo/provision/generators/context.rb +70 -0
  22. data/lib/topo/provision/generators/load_balancer.rb +40 -0
  23. data/lib/topo/provision/generators/machine.rb +50 -0
  24. data/lib/topo/provision/generators/machine_image.rb +43 -0
  25. data/lib/topo/provision/generators/node_group.rb +74 -0
  26. data/lib/topo/provision/generators/resource.rb +91 -0
  27. data/lib/topo/provision/generators/templates/context.erb +8 -0
  28. data/lib/topo/provision/generators/templates/machine_deploy.erb +11 -0
  29. data/lib/topo/provision/generators/templates/machine_stop.erb +5 -0
  30. data/lib/topo/provision/generators/templates/node_group_action.erb +6 -0
  31. data/lib/topo/provision/generators/templates/node_group_deploy.erb +5 -0
  32. data/lib/topo/provision/generators/templates/resource_deploy.erb +5 -0
  33. data/lib/topo/provision/generators/templates/resource_undeploy.erb +5 -0
  34. data/lib/topo/provision/topology_generator.rb +84 -0
  35. data/lib/topo/provision/vagrant/generator.rb +33 -0
  36. data/lib/topo/provision/version.rb +5 -0
  37. data/lib/topo/topology.rb +61 -0
  38. data/lib/topo/utils/output.rb +31 -0
  39. data/lib/topo/utils/parsegen.rb +101 -0
  40. 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,5 @@
1
+
2
+ <%= resource_type %> "<%= name %>" do
3
+ action :stop
4
+
5
+ end
@@ -0,0 +1,6 @@
1
+
2
+ <%= resource_type %> do
3
+ <%= " machines #{machine_names.inspect} \n" %>
4
+ <%= " action #{action.to_sym.inspect} \n" %>
5
+ end
6
+
@@ -0,0 +1,5 @@
1
+
2
+ <%= resource_type %> do
3
+ <%="1.upto(#{size}) do |i|\n" %><%=" #{machine_output}" %>end
4
+ end
5
+
@@ -0,0 +1,5 @@
1
+
2
+ <%= resource_type %> "<%= name %>" do
3
+ <% resource_attributes.each do |key, val| %><%=" #{key}(#{val.inspect})\n" %><% end %>
4
+ end
5
+
@@ -0,0 +1,5 @@
1
+
2
+ <%= resource_type %> "<%= name %>" do
3
+ action <%= undeploy_action.inspect %>
4
+
5
+ end
@@ -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,5 @@
1
+ module Topo
2
+ module Provision
3
+ VERSION = "0.0.1"
4
+ end
5
+ 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