vagrant-compose 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.rspec +1 -0
- data/.travis.yml +4 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +15 -0
- data/LICENCE +8 -0
- data/README.md +3 -0
- data/Rakefile +23 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/lib/locales/en.yml +37 -0
- data/lib/vagrant/compose.rb +18 -0
- data/lib/vagrant/compose/config.rb +38 -0
- data/lib/vagrant/compose/errors.rb +31 -0
- data/lib/vagrant/compose/plugin.rb +67 -0
- data/lib/vagrant/compose/util/cluster.rb +207 -0
- data/lib/vagrant/compose/util/node.rb +30 -0
- data/lib/vagrant/compose/util/node_group.rb +58 -0
- data/lib/vagrant/compose/version.rb +5 -0
- data/provisioning/group_vars/zookeeper.yml +2 -0
- data/vagrant-compose.gemspec +55 -0
- metadata +109 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 03a7541ea3a7eab57a665a0d510467c444c1683b
|
4
|
+
data.tar.gz: c78fe102cb943bf9f724379a762a6e268c471bda
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 67e92a734dc62de90c13123df626f02830f5a328f6f7619708ef891ade36b4f890ec2f827ade85dbdf1ed91cce89bd51713d4403e038424ee8a3e78534f12e8c
|
7
|
+
data.tar.gz: 0640c723ad84731e00651c5f50ebad963e7fec8931057e12b0ae2542c334099300f97c33d079ae802d38068d94f8e469b5844d09c0ac3dedb64099c17efe09fa
|
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--format doc --order random --color --fail-fast
|
data/.travis.yml
ADDED
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in vagrant-compose.gemspec
|
4
|
+
gemspec
|
5
|
+
|
6
|
+
group :development do
|
7
|
+
# We depend on Vagrant for development, but we don't add it as a
|
8
|
+
# gem dependency because we expect to be installed within the
|
9
|
+
# Vagrant environment itself using `vagrant plugin`.
|
10
|
+
gem "vagrant", :git => "https://github.com/mitchellh/vagrant.git"
|
11
|
+
end
|
12
|
+
|
13
|
+
group :plugins do
|
14
|
+
gem "vagrant-compose" , path: "."
|
15
|
+
end
|
data/LICENCE
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
Copyright (c) 2015 Fabrizio Pandini
|
3
|
+
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
5
|
+
|
6
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
7
|
+
|
8
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
require 'rspec/core/rake_task'
|
4
|
+
|
5
|
+
# Immediately sync all stdout so that tools like buildbot can
|
6
|
+
# immediately load in the output.
|
7
|
+
$stdout.sync = true
|
8
|
+
$stderr.sync = true
|
9
|
+
|
10
|
+
# Change to the directory of this file.
|
11
|
+
Dir.chdir(File.expand_path("../", __FILE__))
|
12
|
+
|
13
|
+
# This installs the tasks that help with gem creation and
|
14
|
+
# publishing.
|
15
|
+
Bundler::GemHelper.install_tasks
|
16
|
+
|
17
|
+
# Install the `spec` task so that we can run tests.
|
18
|
+
RSpec::Core::RakeTask.new
|
19
|
+
|
20
|
+
# Default task is to run the unit tests
|
21
|
+
task :default => "spec"
|
22
|
+
|
23
|
+
print "zzz"
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "vagrant/compose"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
data/lib/locales/en.yml
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
en:
|
2
|
+
vagrant_compose:
|
3
|
+
already_status: |-
|
4
|
+
The machine is already %{status}.
|
5
|
+
errors:
|
6
|
+
initialize_error: |-
|
7
|
+
Error executing initialize code for cluster => %{cluster_name}.
|
8
|
+
The error message is shown below:
|
9
|
+
%{message}
|
10
|
+
|
11
|
+
attribute_expression_error: |-
|
12
|
+
Error generating attribute => %{attribute} for node => %{node_index} in group => %{node_group_name}.
|
13
|
+
The error message is shown below:
|
14
|
+
%{message}
|
15
|
+
|
16
|
+
Attribute expression expected to be a literal or a code block returning a literal (see documentation).
|
17
|
+
|
18
|
+
context_var_expression_error: |-
|
19
|
+
Error generating ansible context vars for ansible_group => %{ansible_group}
|
20
|
+
The error message is shown below:
|
21
|
+
%{message}
|
22
|
+
|
23
|
+
Ansible context var expression expected to be a Hash literal or a code block returning an Hash literal (see documentation).
|
24
|
+
|
25
|
+
group_var_expression_error: |-
|
26
|
+
Error generating ansible group vars for ansible_group => %{ansible_group}
|
27
|
+
The error message is shown below:
|
28
|
+
%{message}
|
29
|
+
|
30
|
+
Ansible group var expression expected to be a Hash literal or a code block returning an Hash literal (see documentation).
|
31
|
+
|
32
|
+
host_var_expression_error: |-
|
33
|
+
Error generating ansible host vars for host => %{host} in ansible_group => %{ansible_group}
|
34
|
+
The error message is shown below:
|
35
|
+
%{message}
|
36
|
+
|
37
|
+
Ansible host var expression expected to be a Hash literal or a code block returning an Hash literal (see documentation).
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require "pathname"
|
2
|
+
|
3
|
+
require "vagrant/compose/plugin"
|
4
|
+
|
5
|
+
module VagrantPlugins
|
6
|
+
module Compose
|
7
|
+
lib_path = Pathname.new(File.expand_path("../compose", __FILE__))
|
8
|
+
|
9
|
+
autoload :Errors, lib_path.join("errors")
|
10
|
+
|
11
|
+
# This returns the path to the source of this plugin.
|
12
|
+
#
|
13
|
+
# @return [Pathname]
|
14
|
+
def self.source_root
|
15
|
+
@source_root ||= Pathname.new(File.expand_path("../../", __FILE__))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require "vagrant"
|
2
|
+
|
3
|
+
require_relative "util/cluster"
|
4
|
+
|
5
|
+
module VagrantPlugins
|
6
|
+
module Compose
|
7
|
+
class Config < Vagrant.plugin("2", :config)
|
8
|
+
|
9
|
+
attr_reader :nodes, :ansible_groups
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@nodes = {}
|
13
|
+
@ansible_groups = {}
|
14
|
+
end
|
15
|
+
|
16
|
+
def compose (name, &block)
|
17
|
+
# implementa la creazione di un cluster, l'esecuzione di un blocco di codice
|
18
|
+
# per la configurazione del cluster stesso, e l'esecuzione della sequenza di compose.
|
19
|
+
@cluster = Cluster.new(name)
|
20
|
+
begin
|
21
|
+
block.call(@cluster)
|
22
|
+
rescue Exception => e
|
23
|
+
raise VagrantPlugins::Compose::Errors::ClusterInitializeError, :message => e.message, :cluster_name => name
|
24
|
+
end
|
25
|
+
@nodes, @ansible_groups = @cluster.compose
|
26
|
+
end
|
27
|
+
|
28
|
+
def debug
|
29
|
+
puts "==> cluster #{@cluster.name} with #{nodes.size} nodes"
|
30
|
+
@nodes.each do |node|
|
31
|
+
puts " #{node.boxname} accessible as #{node.fqdn} #{node.aliases} #{node.ip} => [#{node.box}, #{node.cpus} cpus, #{node.memory} memory]"
|
32
|
+
|
33
|
+
end
|
34
|
+
puts " ansible_groups filtered by #{@cluster.multimachine_filter}" if not @cluster.multimachine_filter.empty?
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require "vagrant"
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module Compose
|
5
|
+
module Errors
|
6
|
+
class VagrantComposeError < Vagrant::Errors::VagrantError
|
7
|
+
error_namespace("vagrant_compose.errors")
|
8
|
+
end
|
9
|
+
|
10
|
+
class ClusterInitializeError < VagrantComposeError
|
11
|
+
error_key(:initialize_error)
|
12
|
+
end
|
13
|
+
|
14
|
+
class AttributeExpressionError < VagrantComposeError
|
15
|
+
error_key(:attribute_expression_error)
|
16
|
+
end
|
17
|
+
|
18
|
+
class ContextVarExpressionError < VagrantComposeError
|
19
|
+
error_key(:context_var_expression_error)
|
20
|
+
end
|
21
|
+
|
22
|
+
class GroupVarExpressionError < VagrantComposeError
|
23
|
+
error_key(:group_var_expression_error)
|
24
|
+
end
|
25
|
+
|
26
|
+
class HostVarExpressionError < VagrantComposeError
|
27
|
+
error_key(:host_var_expression_error)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
begin
|
2
|
+
require "vagrant"
|
3
|
+
rescue LoadError
|
4
|
+
raise "The Vagrant Compose plugin must be run within Vagrant."
|
5
|
+
end
|
6
|
+
|
7
|
+
# This is a sanity check to make sure no one is attempting to install
|
8
|
+
# this into an early Vagrant version.
|
9
|
+
if Vagrant::VERSION < "1.8.1"
|
10
|
+
raise "The Vagrant Compose plugin is only compatible with Vagrant 1.8.1+"
|
11
|
+
end
|
12
|
+
|
13
|
+
module VagrantPlugins
|
14
|
+
module Compose
|
15
|
+
class Plugin < Vagrant.plugin("2")
|
16
|
+
name "Compose"
|
17
|
+
description <<-DESC
|
18
|
+
This plugin installs ...
|
19
|
+
DESC
|
20
|
+
|
21
|
+
config "cluster" do
|
22
|
+
# Setup logging and i18n
|
23
|
+
setup_logging
|
24
|
+
setup_i18n
|
25
|
+
|
26
|
+
require_relative "config"
|
27
|
+
Config
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
# This initializes the internationalization strings.
|
32
|
+
def self.setup_i18n
|
33
|
+
I18n.load_path << File.expand_path("locales/en.yml", Compose.source_root)
|
34
|
+
I18n.reload!
|
35
|
+
end
|
36
|
+
|
37
|
+
# This sets up our log level to be whatever VAGRANT_LOG is.
|
38
|
+
def self.setup_logging
|
39
|
+
require "log4r"
|
40
|
+
|
41
|
+
level = nil
|
42
|
+
begin
|
43
|
+
level = Log4r.const_get(ENV["VAGRANT_LOG"].upcase)
|
44
|
+
rescue NameError
|
45
|
+
# This means that the logging constant wasn't found,
|
46
|
+
# which is fine. We just keep `level` as `nil`. But
|
47
|
+
# we tell the user.
|
48
|
+
level = nil
|
49
|
+
end
|
50
|
+
|
51
|
+
# Some constants, such as "true" resolve to booleans, so the
|
52
|
+
# above error checking doesn't catch it. This will check to make
|
53
|
+
# sure that the log level is an integer, as Log4r requires.
|
54
|
+
level = nil if !level.is_a?(Integer)
|
55
|
+
|
56
|
+
# Set the logging level on all "vagrant" namespaced
|
57
|
+
# logs as long as we have a valid level.
|
58
|
+
if level
|
59
|
+
logger = Log4r::Logger.new("vagrant_compose")
|
60
|
+
logger.outputters = Log4r::Outputter.stderr
|
61
|
+
logger.level = level
|
62
|
+
logger = nil
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,207 @@
|
|
1
|
+
require_relative "node_group"
|
2
|
+
|
3
|
+
# Definisce un cluster, ovvero l'insieme di 1..n gruppi di nodi con caratteristiche simili.
|
4
|
+
class Cluster
|
5
|
+
|
6
|
+
attr_reader :name
|
7
|
+
attr_reader :multimachine_filter
|
8
|
+
attr_accessor :box
|
9
|
+
attr_accessor :domain
|
10
|
+
attr_accessor :ansible_playbook_path
|
11
|
+
attr_accessor :ansible_context_vars
|
12
|
+
attr_accessor :ansible_group_vars
|
13
|
+
attr_accessor :ansible_host_vars
|
14
|
+
|
15
|
+
# Costruttore di una istanza di cluster.
|
16
|
+
def initialize(name)
|
17
|
+
@group_uid = 0
|
18
|
+
@node_groups = {}
|
19
|
+
@ansible_context_vars = {}
|
20
|
+
@ansible_group_vars = {}
|
21
|
+
@ansible_host_vars = {}
|
22
|
+
@multimachine_filter = ""
|
23
|
+
@ansible_playbook_path = File.join(Dir.pwd, 'provisioning')
|
24
|
+
|
25
|
+
@name = name
|
26
|
+
@box = 'ubuntu/trusty64'
|
27
|
+
@domain = 'vagrant'
|
28
|
+
end
|
29
|
+
|
30
|
+
# Metodo per la creazione di un gruppo di nodi; in fase di creazione, il blocco inizializza
|
31
|
+
# i valori/le expressioni da utilizzarsi nella valorizzazione degli attributi dei nodi in fase di compose.
|
32
|
+
#
|
33
|
+
# Oltre alla creazione dei nodi, il metodo prevede anche l'esecuzione di un blocco di codice per
|
34
|
+
# la configurazione del gruppo di nodi stesso.
|
35
|
+
def nodes(name, &block)
|
36
|
+
raise RuntimeError, "Nodes #{name} already exists in this cluster." unless not @node_groups.has_key?(name)
|
37
|
+
|
38
|
+
@node_groups[name] = NodeGroup.new(@group_uid, name)
|
39
|
+
@node_groups[name].box = @box
|
40
|
+
@node_groups[name].boxname = lambda { |group_uid, group_name, node_index| return "#{group_name}#{node_index + 1}" }
|
41
|
+
@node_groups[name].hostname = lambda { |group_uid, group_name, node_index| return "#{group_name}#{node_index + 1}" }
|
42
|
+
@node_groups[name].aliases = []
|
43
|
+
@node_groups[name].ip = lambda { |group_uid, group_name, node_index| return "172.31.#{group_uid}.#{100 + node_index + 1}" }
|
44
|
+
@node_groups[name].cpus = 1
|
45
|
+
@node_groups[name].memory = 256
|
46
|
+
@node_groups[name].ansible_groups = []
|
47
|
+
@node_groups[name].attributes = {}
|
48
|
+
|
49
|
+
@group_uid += 1
|
50
|
+
|
51
|
+
block.call(@node_groups[name])
|
52
|
+
end
|
53
|
+
|
54
|
+
# Prepara il provisioning del cluster
|
55
|
+
def compose
|
56
|
+
|
57
|
+
@multimachine_filter = ARGV.length > 1 ? ARGV[1] : "" # detect if running vagrant up/provision MACHINE
|
58
|
+
|
59
|
+
## Fase1: Creazione dei nodi
|
60
|
+
|
61
|
+
# sviluppa i vari gruppi di nodi, creando i singoli nodi
|
62
|
+
nodes = []
|
63
|
+
|
64
|
+
@node_groups.each do |key, group|
|
65
|
+
group.compose(@name, @domain, nodes.size) do |node|
|
66
|
+
nodes << node
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# sviluppa i gruppi abbinando a ciascono i nodi creati
|
71
|
+
# NB. tiene in considerazione anche l'eventualità che un gruppo possa essere composto da nodi appartenenti a diversi node_groups
|
72
|
+
ansible_groups= {}
|
73
|
+
nodes.each do |node|
|
74
|
+
node.ansible_groups.each do |ansible_group|
|
75
|
+
ansible_groups[ansible_group] = [] unless ansible_groups.has_key? (ansible_group)
|
76
|
+
ansible_groups[ansible_group] << node
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
## Fase2: Configurazione provisioning del cluster via Ansible
|
81
|
+
# Ogni nodo diventerà una vm su cui sarà fatto il provisioning, ovvero un host nell'inventory di ansible
|
82
|
+
# Ad ogni gruppo corrispondono nodi con caratteristiche simili
|
83
|
+
|
84
|
+
# genearazione inventory file per ansible, aka ansible_groups in Vagrant (NB. 1 group = 1 gruppo ansible)
|
85
|
+
ansible_groups_provision = {}
|
86
|
+
ansible_groups.each do |ansible_group, ansible_group_nodes|
|
87
|
+
ansible_groups_provision[ansible_group] = []
|
88
|
+
ansible_group_nodes.each do |node|
|
89
|
+
ansible_groups_provision[ansible_group] << node.hostname if @multimachine_filter.empty? or @multimachine_filter == node.boxname #filter ansible groups if vagrant command on one node
|
90
|
+
end
|
91
|
+
end
|
92
|
+
ansible_groups_provision['all_groups:children'] = ansible_groups.keys
|
93
|
+
|
94
|
+
# Oltre alla creazione del file di inventory per ansible, contenente gruppi e host, è supportata:
|
95
|
+
# - la creazione di file ansible_group_vars, ovvero di file preposti a contenere una serie di variabili - specifico di ogni gruppo di host -
|
96
|
+
# per condizionare il provisioning ansible sulla base delle caratteristiche del cluster specifico
|
97
|
+
# - la creazione di file ansible_host_vars, ovvero di file preposti a contenere una serie di variabili - specifico di ogni host -
|
98
|
+
# per condizionare il provisioning ansible sulla base delle caratteristiche del cluster specifico
|
99
|
+
|
100
|
+
# La generazione delle variabili utilizza una serie di VariableProvisioner, uno o più d'uno per ogni gruppo di hosts, configurati durante la
|
101
|
+
# definizione del cluster.
|
102
|
+
|
103
|
+
context = {}
|
104
|
+
|
105
|
+
#genearazione context (NB. 1 group = 1 gruppo host ansible)
|
106
|
+
ansible_groups.each do |ansible_group, ansible_group_nodes|
|
107
|
+
|
108
|
+
# genero le variabili per il group
|
109
|
+
provisioners = @ansible_context_vars[ansible_group]
|
110
|
+
unless provisioners.nil?
|
111
|
+
# se necessario, normalizzo provisioner in array provisioners
|
112
|
+
provisioners = [ provisioners ] if not provisioners.respond_to?('each')
|
113
|
+
# per tutti i provisioners abbinati al ruolo
|
114
|
+
provisioners.each do |provisioner|
|
115
|
+
begin
|
116
|
+
vars = provisioner.call(context, ansible_group_nodes)
|
117
|
+
|
118
|
+
#TODO: gestire conflitto (n>=2 gruppi che generano la stessa variabile - con valori diversi)
|
119
|
+
context = context.merge(vars)
|
120
|
+
rescue Exception => e
|
121
|
+
raise VagrantPlugins::Compose::Errors::ContextVarExpressionError, :message => e.message, :ansible_group => ansible_group
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# cleanup ansible_group_vars files
|
128
|
+
# TODO: make variable public
|
129
|
+
@ansible_group_vars_path = File.join(@ansible_playbook_path, 'group_vars')
|
130
|
+
# TODO: make safe
|
131
|
+
FileUtils.mkdir_p(@ansible_group_vars_path) unless File.exists?(@ansible_group_vars_path)
|
132
|
+
Dir.foreach(@ansible_group_vars_path) {|f| fn = File.join(@ansible_group_vars_path, f); File.delete(fn) if f.end_with?(".yml")}
|
133
|
+
|
134
|
+
#generazione ansible_group_vars file (NB. 1 group = 1 gruppo host ansible)
|
135
|
+
ansible_groups.each do |ansible_group, ansible_group_nodes|
|
136
|
+
ansible_group_vars = {}
|
137
|
+
# genero le variabili per il group
|
138
|
+
provisioners = @ansible_group_vars[ansible_group]
|
139
|
+
unless provisioners.nil?
|
140
|
+
# se necessario, normalizzo provisioner in array provisioners
|
141
|
+
provisioners = [ provisioners ] if not provisioners.respond_to?('each')
|
142
|
+
# per tutti i provisioners abbinati al ruolo
|
143
|
+
provisioners.each do |provisioner|
|
144
|
+
begin
|
145
|
+
vars = provisioner.call(context, ansible_group_nodes)
|
146
|
+
|
147
|
+
#TODO: gestire conflitto (n>=2 gruppi che generano la stessa variabile - con valori diversi)
|
148
|
+
ansible_group_vars = ansible_group_vars.merge(vars)
|
149
|
+
rescue Exception => e
|
150
|
+
raise VagrantPlugins::Compose::Errors::GroupVarExpressionError, :message => e.message, :ansible_group => ansible_group
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
# crea il file (se sono state generate delle variabili)
|
156
|
+
unless ansible_group_vars.empty?
|
157
|
+
# TODO: make safe
|
158
|
+
File.open(File.join(@ansible_group_vars_path,"#{ansible_group}.yml") , 'w+') do |file|
|
159
|
+
file.puts YAML::dump(ansible_group_vars)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
# cleanup ansible_host_vars files (NB. 1 nodo = 1 host)
|
165
|
+
# TODO: make variable public
|
166
|
+
@ansible_host_vars_path = File.join(@ansible_playbook_path, 'host_vars')
|
167
|
+
# TODO: make safe
|
168
|
+
FileUtils.mkdir_p(@ansible_host_vars_path) unless File.exists?(@ansible_host_vars_path)
|
169
|
+
Dir.foreach(@ansible_host_vars_path) {|f| fn = File.join(@ansible_host_vars_path, f); File.delete(fn) if f.end_with?(".yml")}
|
170
|
+
|
171
|
+
#generazione ansible_host_vars file
|
172
|
+
nodes.each do |node|
|
173
|
+
# genero le variabili per il nodo; il nodo, può essere abbinato a diversi gruppi
|
174
|
+
ansible_host_vars = {}
|
175
|
+
node.ansible_groups.each do |ansible_group|
|
176
|
+
# genero le variabili per il gruppo
|
177
|
+
provisioners = @ansible_host_vars[ansible_group]
|
178
|
+
unless provisioners.nil?
|
179
|
+
# se necessario, normalizzo provisioner in array provisioners
|
180
|
+
provisioners = [ provisioners ] if not provisioners.respond_to?('each')
|
181
|
+
# per tutti i provisioners abbinati al gruppo
|
182
|
+
provisioners.each do |provisioner|
|
183
|
+
begin
|
184
|
+
vars = provisioner.call(context, node)
|
185
|
+
|
186
|
+
#TODO: gestire conflitto (n>=2 gruppi che generano la stessa variabile - con valori diversi)
|
187
|
+
ansible_host_vars = ansible_host_vars.merge(vars)
|
188
|
+
rescue Exception => e
|
189
|
+
raise VagrantPlugins::Compose::Errors::HostVarExpressionError, :message => e.message, :host => node.hostname, :ansible_group => ansible_group
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
# crea il file (se sono state generate delle variabili)
|
196
|
+
unless ansible_host_vars.empty?
|
197
|
+
# TODO: make safe
|
198
|
+
File.open(File.join(@ansible_host_vars_path,"#{node.hostname}.yml") , 'w+') do |file|
|
199
|
+
file.puts YAML::dump(ansible_host_vars)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
return nodes.map.with_index, ansible_groups_provision
|
205
|
+
end
|
206
|
+
|
207
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# Definisce un nodo, ovvero uno delle istanze di nodi che compongono il cluster
|
2
|
+
class Node
|
3
|
+
attr_reader :box
|
4
|
+
attr_reader :boxname
|
5
|
+
attr_reader :hostname
|
6
|
+
attr_reader :fqdn
|
7
|
+
attr_reader :aliases
|
8
|
+
attr_reader :ip
|
9
|
+
attr_reader :cpus
|
10
|
+
attr_reader :memory
|
11
|
+
attr_reader :ansible_groups
|
12
|
+
attr_reader :attributes
|
13
|
+
attr_reader :index
|
14
|
+
attr_reader :group_index
|
15
|
+
|
16
|
+
def initialize(box, boxname, hostname, fqdn, aliases, ip, cpus, memory, ansible_groups, attributes, index, group_index)
|
17
|
+
@box = box
|
18
|
+
@boxname = boxname
|
19
|
+
@hostname = hostname
|
20
|
+
@fqdn = fqdn
|
21
|
+
@aliases = aliases
|
22
|
+
@ip = ip
|
23
|
+
@cpus = cpus
|
24
|
+
@memory = memory
|
25
|
+
@ansible_groups = ansible_groups
|
26
|
+
@attributes = attributes
|
27
|
+
@index = index
|
28
|
+
@group_index = group_index
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require_relative "node"
|
2
|
+
|
3
|
+
# Definisce un node group, ovvero un insieme di nodi con caratteristiche omogenee.
|
4
|
+
# i singoli nodi del gruppo, sono generati in fase di compose tramite delle espressioni
|
5
|
+
# che generano i valori degli attributi che caratterizzano ogni nodo
|
6
|
+
class NodeGroup
|
7
|
+
attr_reader :uid, :name
|
8
|
+
attr_accessor :instances
|
9
|
+
attr_accessor :box
|
10
|
+
attr_accessor :boxname
|
11
|
+
attr_accessor :hostname
|
12
|
+
attr_accessor :aliases
|
13
|
+
attr_accessor :ip
|
14
|
+
attr_accessor :cpus
|
15
|
+
attr_accessor :memory
|
16
|
+
attr_accessor :ansible_groups
|
17
|
+
attr_accessor :attributes
|
18
|
+
|
19
|
+
def initialize(uid, name)
|
20
|
+
@uid = uid
|
21
|
+
@name = name
|
22
|
+
@instances = 1
|
23
|
+
end
|
24
|
+
|
25
|
+
# compone il gruppo, generando le istanze dei vari nodi
|
26
|
+
def compose(cluster_name, cluster_domain, cluster_offset)
|
27
|
+
node_index = 0
|
28
|
+
while node_index < @instances
|
29
|
+
box = generate(:box, @box, node_index)
|
30
|
+
boxname = "#{cluster_name}-#{generate(:boxname, @boxname, node_index)}"
|
31
|
+
hostname = "#{cluster_name}-#{generate(:hostname, @hostname, node_index)}"
|
32
|
+
aliases = generate(:aliases, @aliases, node_index).join(',')
|
33
|
+
fqdn = "#{hostname}.#{cluster_domain}"
|
34
|
+
ip = generate(:ip, @ip, node_index)
|
35
|
+
cpus = generate(:cpus, @cpus, node_index)
|
36
|
+
memory = generate(:memory, @memory, node_index)
|
37
|
+
ansible_groups = generate(:ansible_groups, @ansible_groups, node_index)
|
38
|
+
attributes = generate(:attributes, @attributes, node_index)
|
39
|
+
yield Node.new(box, boxname, hostname, fqdn, aliases, ip, cpus, memory, ansible_groups, attributes, cluster_offset + node_index, node_index)
|
40
|
+
|
41
|
+
node_index += 1
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# funzione di utilità per l'esecuzione delle espressioni che generano
|
46
|
+
# i valori degli attributi
|
47
|
+
def generate(var, generator, node_index)
|
48
|
+
unless generator.respond_to? :call
|
49
|
+
return generator
|
50
|
+
else
|
51
|
+
begin
|
52
|
+
return generator.call(@uid, @name, node_index)
|
53
|
+
rescue Exception => e
|
54
|
+
raise VagrantPlugins::Compose::Errors::AttributeExpressionError, :message => e.message, :attribute => var, :node_index => node_index, :node_group_name => name
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
$:.unshift File.expand_path("../lib", __FILE__)
|
2
|
+
require 'vagrant/compose/version'
|
3
|
+
|
4
|
+
Gem::Specification.new do |spec|
|
5
|
+
spec.name = "vagrant-compose"
|
6
|
+
spec.version = Vagrant::Compose::VERSION
|
7
|
+
spec.platform = Gem::Platform::RUBY
|
8
|
+
spec.license = "MIT"
|
9
|
+
spec.authors = ["Fabrizio Pandini"]
|
10
|
+
spec.email = ["fabrizio.pandini@unicredit.eu"]
|
11
|
+
spec.homepage = "https://github.com/fabriziopandini/vagrant-compose/"
|
12
|
+
spec.summary = %q{A Vagrant plugin that helps building complex multi-machine scenarios.}
|
13
|
+
spec.description = %q{A Vagrant plugin that helps building complex multi-machine scenarios.}
|
14
|
+
|
15
|
+
spec.required_rubygems_version = ">= 2.0.13"
|
16
|
+
|
17
|
+
spec.add_development_dependency "rake", "~> 10.4.2"
|
18
|
+
spec.add_development_dependency "rspec", "~> 3.4.0"
|
19
|
+
spec.add_development_dependency "rspec-its", "~> 1.2.0"
|
20
|
+
|
21
|
+
# The following block of code determines the files that should be included
|
22
|
+
# in the gem. It does this by reading all the files in the directory where
|
23
|
+
# this gemspec is, and parsing out the ignored files from the gitignore.
|
24
|
+
# Note that the entire gitignore(5) syntax is not supported, specifically
|
25
|
+
# the "!" syntax, but it should mostly work correctly.
|
26
|
+
root_path = File.dirname(__FILE__)
|
27
|
+
all_files = Dir.chdir(root_path) { Dir.glob("**/{*,.*}") }
|
28
|
+
all_files.reject! { |file| [".", ".."].include?(File.basename(file)) }
|
29
|
+
gitignore_path = File.join(root_path, ".gitignore")
|
30
|
+
gitignore = File.readlines(gitignore_path)
|
31
|
+
gitignore.map! { |line| line.chomp.strip }
|
32
|
+
gitignore.reject! { |line| line.empty? || line =~ /^(#|!)/ }
|
33
|
+
|
34
|
+
unignored_files = all_files.reject do |file|
|
35
|
+
# Ignore any directories, the gemspec only cares about files
|
36
|
+
next true if File.directory?(file)
|
37
|
+
|
38
|
+
# Ignore any paths that match anything in the gitignore. We do
|
39
|
+
# two tests here:
|
40
|
+
#
|
41
|
+
# - First, test to see if the entire path matches the gitignore.
|
42
|
+
# - Second, match if the basename does, this makes it so that things
|
43
|
+
# like '.DS_Store' will match sub-directories too (same behavior
|
44
|
+
# as git).
|
45
|
+
#
|
46
|
+
gitignore.any? do |ignore|
|
47
|
+
File.fnmatch(ignore, file, File::FNM_PATHNAME) ||
|
48
|
+
File.fnmatch(ignore, File.basename(file), File::FNM_PATHNAME)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
spec.files = unignored_files
|
53
|
+
spec.executables = unignored_files.map { |f| f[/^bin\/(.*)/, 1] }.compact
|
54
|
+
spec.require_path = 'lib'
|
55
|
+
end
|
metadata
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: vagrant-compose
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Fabrizio Pandini
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-12-30 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 10.4.2
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 10.4.2
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 3.4.0
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 3.4.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec-its
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 1.2.0
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.2.0
|
55
|
+
description: A Vagrant plugin that helps building complex multi-machine scenarios.
|
56
|
+
email:
|
57
|
+
- fabrizio.pandini@unicredit.eu
|
58
|
+
executables:
|
59
|
+
- console
|
60
|
+
- setup
|
61
|
+
extensions: []
|
62
|
+
extra_rdoc_files: []
|
63
|
+
files:
|
64
|
+
- bin/console
|
65
|
+
- bin/setup
|
66
|
+
- CHANGELOG.md
|
67
|
+
- Gemfile
|
68
|
+
- lib/locales/en.yml
|
69
|
+
- lib/vagrant/compose/config.rb
|
70
|
+
- lib/vagrant/compose/errors.rb
|
71
|
+
- lib/vagrant/compose/plugin.rb
|
72
|
+
- lib/vagrant/compose/util/cluster.rb
|
73
|
+
- lib/vagrant/compose/util/node.rb
|
74
|
+
- lib/vagrant/compose/util/node_group.rb
|
75
|
+
- lib/vagrant/compose/version.rb
|
76
|
+
- lib/vagrant/compose.rb
|
77
|
+
- LICENCE
|
78
|
+
- provisioning/group_vars/zookeeper.yml
|
79
|
+
- Rakefile
|
80
|
+
- README.md
|
81
|
+
- vagrant-compose.gemspec
|
82
|
+
- .gitignore
|
83
|
+
- .rspec
|
84
|
+
- .travis.yml
|
85
|
+
homepage: https://github.com/fabriziopandini/vagrant-compose/
|
86
|
+
licenses:
|
87
|
+
- MIT
|
88
|
+
metadata: {}
|
89
|
+
post_install_message:
|
90
|
+
rdoc_options: []
|
91
|
+
require_paths:
|
92
|
+
- lib
|
93
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - '>='
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - '>='
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: 2.0.13
|
103
|
+
requirements: []
|
104
|
+
rubyforge_project:
|
105
|
+
rubygems_version: 2.0.14
|
106
|
+
signing_key:
|
107
|
+
specification_version: 4
|
108
|
+
summary: A Vagrant plugin that helps building complex multi-machine scenarios.
|
109
|
+
test_files: []
|