vagrant-compose 0.2.4 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,139 @@
1
+ require 'open4'
2
+ require_relative "../node"
3
+
4
+ module VagrantPlugins
5
+ module Compose
6
+ module Declarative
7
+
8
+ class Cluster
9
+
10
+ # The name of the cluster
11
+ attr_reader :name
12
+
13
+ # The default vagrant base box to be used for creating vagrant machines in this cluster.
14
+ # This setting can be changed at group/node level
15
+ attr_accessor :box
16
+
17
+ # The network domain to wich the cluster belongs (used for computing nodes fqdn)
18
+ attr_accessor :domain
19
+
20
+ # A variable that reflects if vagrant is tageting a single machine, like f.i. when executing vagrant up machine-name
21
+ attr_reader :multimachine_filter
22
+
23
+ # The root path for ansible playbook; it is used as a base path for computing ansible_group_vars and ansible_host_vars
24
+ # It defaults to current directory/provisioning
25
+ attr_accessor :ansible_playbook_path
26
+
27
+ # Costruttore di una istanza di cluster.
28
+ def initialize()
29
+ @multimachine_filter = ""
30
+ end
31
+
32
+ # Implements cluster creation from a playbook file
33
+ def from (file)
34
+ # calls vagrant-playbook utility for executing the playbook file.
35
+ playbook = YAML.load(pycompose (file))
36
+
37
+ # extract cluster attributes
38
+ @name = playbook.keys[0]
39
+ @box = playbook[@name]['box']
40
+ @domain = playbook[@name]['domain']
41
+ @ansible_playbook_path = playbook[@name]['ansible_playbook_path']
42
+
43
+ # extract nodes
44
+ nodes = []
45
+ playbook[@name]['nodes'].each do |node|
46
+
47
+ boxname = node.keys[0]
48
+
49
+ box = node[boxname]['box']
50
+ hostname = node[boxname]['hostname']
51
+ aliases = node[boxname]['hostname']
52
+ fqdn = node[boxname]['fqdn']
53
+ ip = node[boxname]['ip']
54
+ cpus = node[boxname]['cpus']
55
+ memory = node[boxname]['memory']
56
+ ansible_groups = node[boxname]['ansible_groups']
57
+ attributes = node[boxname]['attributes']
58
+ index = node[boxname]['index']
59
+ group_index = node[boxname]['group_index']
60
+
61
+ nodes << VagrantPlugins::Compose::Node.new(box, boxname, hostname, fqdn, aliases, ip, cpus, memory, ansible_groups, attributes, index, group_index)
62
+ end
63
+
64
+ # extract ansible inventory, ansible_group_vars, ansible_host_vars
65
+ ansible_groups = {}
66
+ if playbook[@name].key?("ansible")
67
+ ansible = playbook[@name]['ansible']
68
+
69
+ # extract ansible inventory
70
+ ansible_groups = ansible['inventory']
71
+
72
+ # cleanup ansible_group_vars files
73
+ # TODO: make safe
74
+ ansible_group_vars_path = File.join(@ansible_playbook_path, 'group_vars')
75
+
76
+ FileUtils.mkdir_p(ansible_group_vars_path) unless File.exists?(ansible_group_vars_path)
77
+ Dir.foreach(ansible_group_vars_path) {|f| fn = File.join(ansible_group_vars_path, f); File.delete(fn) if f.end_with?(".yml")}
78
+
79
+ #generazione ansible_group_vars file (NB. 1 group = 1 gruppo host ansible)
80
+ ansible['group_vars'].each do |group, vars|
81
+ # crea il file (se sono state generate delle variabili)
82
+ unless vars.empty?
83
+ # TODO: make safe
84
+ File.open(File.join(ansible_group_vars_path,"#{group}.yml") , 'w+') do |file|
85
+ file.puts YAML::dump(vars)
86
+ end
87
+ end
88
+ end
89
+
90
+ # cleanup ansible_host_vars files (NB. 1 nodo = 1 host)
91
+ # TODO: make safe
92
+ ansible_host_vars_path = File.join(@ansible_playbook_path, 'host_vars')
93
+
94
+ FileUtils.mkdir_p(ansible_host_vars_path) unless File.exists?(ansible_host_vars_path)
95
+ Dir.foreach(ansible_host_vars_path) {|f| fn = File.join(ansible_host_vars_path, f); File.delete(fn) if f.end_with?(".yml")}
96
+
97
+ #generazione ansible_host_vars file
98
+ ansible['host_vars'].each do |host, vars|
99
+ # crea il file (se sono state generate delle variabili)
100
+ unless vars.empty?
101
+ # TODO: make safe
102
+ File.open(File.join(ansible_host_vars_path,"#{host}.yml") , 'w+') do |file|
103
+ file.puts YAML::dump(vars)
104
+ end
105
+ end
106
+ end
107
+ end
108
+
109
+ return nodes, ansible_groups
110
+ end
111
+
112
+
113
+ # Executes pycompose command
114
+ def pycompose (file)
115
+ p_err = ""
116
+ p_out = ""
117
+
118
+ begin
119
+ p_status = Open4::popen4("vagrant-playbook -f #{file}") do |pid, stdin, stdout, stderr|
120
+ p_err = stderr.read.strip
121
+ p_out = stdout.read.strip
122
+ end
123
+ rescue Errno::ENOENT
124
+ raise VagrantPlugins::Compose::Errors::PyComposeMissing
125
+ rescue Exception => e
126
+ raise VagrantPlugins::Compose::Errors::PyComposeError, :message => e.message
127
+ end
128
+
129
+ if p_status.exitstatus != 0
130
+ raise VagrantPlugins::Compose::Errors::PyComposeError, :message => p_err
131
+ end
132
+
133
+ return p_out
134
+ end
135
+
136
+ end
137
+ end
138
+ end
139
+ end
@@ -30,9 +30,13 @@ module VagrantPlugins
30
30
  error_key(:host_var_expression_error)
31
31
  end
32
32
 
33
+ class PyComposeMissing < VagrantComposeError
34
+ error_key(:pycompose_missing)
35
+ end
36
+
33
37
  class PyComposeError < VagrantComposeError
34
38
  error_key(:pycompose_error)
35
39
  end
36
40
  end
37
41
  end
38
- end
42
+ end
File without changes
@@ -0,0 +1,227 @@
1
+ require_relative "node_group"
2
+
3
+ module VagrantPlugins
4
+ module Compose
5
+ module Programmatic
6
+
7
+ # This class defines a cluster, thas is a set of group of nodes, where nodes in each group has similar characteristics.
8
+ # Basically, a cluster is a data structure that can be used as a recipe for setting up and provisioning a
9
+ # vagrant cluster composed by several machines with different roles.
10
+ class Cluster
11
+
12
+ # The name of the cluster
13
+ attr_reader :name
14
+
15
+ # The default vagrant base box to be used for creating vagrant machines in this cluster.
16
+ # This setting can be changed at group/node level
17
+ attr_accessor :box
18
+
19
+ # The network domain to wich the cluster belongs (used for computing nodes fqdn)
20
+ attr_accessor :domain
21
+
22
+ # The root path for ansible playbook; it is used as a base path for computing ansible_group_vars and ansible_host_vars
23
+ # It defaults to current directory/provisioning
24
+ attr_accessor :ansible_playbook_path
25
+
26
+ # A dictionary, allowing to setup ansible_group_vars generators foreach node_group
27
+ attr_reader :ansible_group_vars
28
+
29
+ # A dictionary, allowing to setup ansible_host_vars generators foreach node_group
30
+ attr_reader :ansible_host_vars
31
+
32
+ # A dictionary, allowing to setup context vars to be uses is value_generators when composing nodes
33
+ attr_reader :ansible_context_vars
34
+
35
+ # Costruttore di una istanza di cluster.
36
+ def initialize(name)
37
+ @group_index = 0
38
+ @node_groups = {}
39
+ @ansible_context_vars = {}
40
+ @ansible_group_vars = {}
41
+ @ansible_host_vars = {}
42
+ @multimachine_filter = ""
43
+ @ansible_playbook_path = File.join(Dir.pwd, 'provisioning')
44
+
45
+ @name = name
46
+ @box = 'ubuntu/trusty64'
47
+ @domain = 'vagrant'
48
+ end
49
+
50
+ # Metodo per la creazione di un gruppo di nodi; in fase di creazione, il blocco inizializza
51
+ # i valori/le expressioni da utilizzarsi nella valorizzazione degli attributi dei nodi in fase di compose.
52
+ #
53
+ # Oltre alla creazione dei nodi, il metodo prevede anche l'esecuzione di un blocco di codice per
54
+ # la configurazione del gruppo di nodi stesso.
55
+ def nodes(instances, name, &block)
56
+ raise RuntimeError, "Nodes #{name} already exists in this cluster." unless not @node_groups.has_key?(name)
57
+
58
+ @node_groups[name] = NodeGroup.new(@group_index, instances, name)
59
+ @node_groups[name].box = @box
60
+ @node_groups[name].boxname = lambda { |group_index, group_name, node_index| return "#{group_name}#{node_index + 1}" }
61
+ @node_groups[name].hostname = lambda { |group_index, group_name, node_index| return "#{group_name}#{node_index + 1}" }
62
+ @node_groups[name].aliases = []
63
+ @node_groups[name].ip = lambda { |group_index, group_name, node_index| return "172.31.#{group_index}.#{100 + node_index + 1}" }
64
+ @node_groups[name].cpus = 1
65
+ @node_groups[name].memory = 256
66
+ @node_groups[name].ansible_groups = []
67
+ @node_groups[name].attributes = {}
68
+
69
+ @group_index += 1
70
+
71
+ block.call(@node_groups[name]) if block_given?
72
+ end
73
+
74
+ # Prepara il provisioning del cluster
75
+ def compose
76
+
77
+ ## Fase1: Creazione dei nodi
78
+
79
+ # sviluppa i vari gruppi di nodi, creando i singoli nodi
80
+ nodes = []
81
+
82
+ @node_groups.each do |key, group|
83
+ group.compose(@name, @domain, nodes.size) do |node|
84
+ nodes << node
85
+ end
86
+ end
87
+
88
+ # sviluppa i gruppi abbinando a ciascono i nodi creati
89
+ # NB. tiene in considerazione anche l'eventualità che un gruppo possa essere composto da nodi appartenenti a diversi node_groups
90
+ ansible_groups= {}
91
+ nodes.each do |node|
92
+ node.ansible_groups.each do |ansible_group|
93
+ ansible_groups[ansible_group] = [] unless ansible_groups.has_key? (ansible_group)
94
+ ansible_groups[ansible_group] << node
95
+ end
96
+ end
97
+
98
+ ## Fase2: Configurazione provisioning del cluster via Ansible
99
+ # Ogni nodo diventerà una vm su cui sarà fatto il provisioning, ovvero un host nell'inventory di ansible
100
+ # Ad ogni gruppo corrispondono nodi con caratteristiche simili
101
+
102
+ # genearazione inventory file per ansible, aka ansible_groups in Vagrant (NB. 1 group = 1 gruppo ansible)
103
+ ansible_groups_provision = {}
104
+ ansible_groups.each do |ansible_group, ansible_group_nodes|
105
+ ansible_groups_provision[ansible_group] = []
106
+ ansible_group_nodes.each do |node|
107
+ ansible_groups_provision[ansible_group] << {"boxname" => node.boxname , "hostname" => node.hostname}
108
+ end
109
+ end
110
+
111
+ # Oltre alla creazione del file di inventory per ansible, contenente gruppi e host, è supportata:
112
+ # - la creazione di file ansible_group_vars, ovvero di file preposti a contenere una serie di variabili - specifico di ogni gruppo di host -
113
+ # per condizionare il provisioning ansible sulla base delle caratteristiche del cluster specifico
114
+ # - la creazione di file ansible_host_vars, ovvero di file preposti a contenere una serie di variabili - specifico di ogni host -
115
+ # per condizionare il provisioning ansible sulla base delle caratteristiche del cluster specifico
116
+
117
+ # La generazione delle variabili utilizza una serie di VariableProvisioner, uno o più d'uno per ogni gruppo di hosts, configurati durante la
118
+ # definizione del cluster.
119
+
120
+ context = {}
121
+
122
+ #genearazione context (NB. 1 group = 1 gruppo host ansible)
123
+ ansible_groups.each do |ansible_group, ansible_group_nodes|
124
+ # genero le variabili per il group
125
+ provisioners = @ansible_context_vars[ansible_group]
126
+ unless provisioners.nil?
127
+
128
+ # se necessario, normalizzo provisioner in array provisioners
129
+ provisioners = [ provisioners ] if not provisioners.respond_to?('each')
130
+ # per tutti i provisioners abbinati al ruolo
131
+ provisioners.each do |provisioner|
132
+ begin
133
+ vars = provisioner.call(context, ansible_group_nodes)
134
+
135
+ #TODO: gestire conflitto (n>=2 gruppi che generano la stessa variabile - con valori diversi)
136
+ context = context.merge(vars)
137
+ rescue Exception => e
138
+ raise VagrantPlugins::Compose::Errors::ContextVarExpressionError, :message => e.message, :ansible_group => ansible_group
139
+ end
140
+ end
141
+ end
142
+ end
143
+
144
+ # cleanup ansible_group_vars files
145
+ # TODO: make safe
146
+ ansible_group_vars_path = File.join(@ansible_playbook_path, 'group_vars')
147
+
148
+ FileUtils.mkdir_p(ansible_group_vars_path) unless File.exists?(ansible_group_vars_path)
149
+ Dir.foreach(ansible_group_vars_path) {|f| fn = File.join(ansible_group_vars_path, f); File.delete(fn) if f.end_with?(".yml")}
150
+
151
+ #generazione ansible_group_vars file (NB. 1 group = 1 gruppo host ansible)
152
+ ansible_groups.each do |ansible_group, ansible_group_nodes|
153
+ ansible_group_vars = {}
154
+ # genero le variabili per il group
155
+ provisioners = @ansible_group_vars[ansible_group]
156
+ unless provisioners.nil?
157
+ # se necessario, normalizzo provisioner in array provisioners
158
+ provisioners = [ provisioners ] if not provisioners.respond_to?('each')
159
+ # per tutti i provisioners abbinati al ruolo
160
+ provisioners.each do |provisioner|
161
+ begin
162
+ vars = provisioner.call(context, ansible_group_nodes)
163
+
164
+ #TODO: gestire conflitto (n>=2 gruppi che generano la stessa variabile - con valori diversi)
165
+ ansible_group_vars = ansible_group_vars.merge(vars)
166
+ rescue Exception => e
167
+ raise VagrantPlugins::Compose::Errors::GroupVarExpressionError, :message => e.message, :ansible_group => ansible_group
168
+ end
169
+ end
170
+ end
171
+
172
+ # crea il file (se sono state generate delle variabili)
173
+ unless ansible_group_vars.empty?
174
+ # TODO: make safe
175
+ File.open(File.join(ansible_group_vars_path,"#{ansible_group}.yml") , 'w+') do |file|
176
+ file.puts YAML::dump(ansible_group_vars)
177
+ end
178
+ end
179
+ end
180
+
181
+ # cleanup ansible_host_vars files (NB. 1 nodo = 1 host)
182
+ # TODO: make safe
183
+ ansible_host_vars_path = File.join(@ansible_playbook_path, 'host_vars')
184
+
185
+ FileUtils.mkdir_p(ansible_host_vars_path) unless File.exists?(ansible_host_vars_path)
186
+ Dir.foreach(ansible_host_vars_path) {|f| fn = File.join(ansible_host_vars_path, f); File.delete(fn) if f.end_with?(".yml")}
187
+
188
+ #generazione ansible_host_vars file
189
+ nodes.each do |node|
190
+ # genero le variabili per il nodo; il nodo, può essere abbinato a diversi gruppi
191
+ ansible_host_vars = {}
192
+ node.ansible_groups.each do |ansible_group|
193
+ # genero le variabili per il gruppo
194
+ provisioners = @ansible_host_vars[ansible_group]
195
+ unless provisioners.nil?
196
+ # se necessario, normalizzo provisioner in array provisioners
197
+ provisioners = [ provisioners ] if not provisioners.respond_to?('each')
198
+ # per tutti i provisioners abbinati al gruppo
199
+ provisioners.each do |provisioner|
200
+ begin
201
+ vars = provisioner.call(context, node)
202
+
203
+ #TODO: gestire conflitto (n>=2 gruppi che generano la stessa variabile - con valori diversi)
204
+ ansible_host_vars = ansible_host_vars.merge(vars)
205
+ rescue Exception => e
206
+ raise VagrantPlugins::Compose::Errors::HostVarExpressionError, :message => e.message, :host => node.hostname, :ansible_group => ansible_group
207
+ end
208
+ end
209
+ end
210
+ end
211
+
212
+ # crea il file (se sono state generate delle variabili)
213
+ unless ansible_host_vars.empty?
214
+ # TODO: make safe
215
+ File.open(File.join(ansible_host_vars_path,"#{node.hostname}.yml") , 'w+') do |file|
216
+ file.puts YAML::dump(ansible_host_vars)
217
+ end
218
+ end
219
+ end
220
+
221
+ return nodes, ansible_groups_provision
222
+ end
223
+ end
224
+
225
+ end
226
+ end
227
+ end
@@ -0,0 +1,104 @@
1
+ require_relative "../node"
2
+
3
+ module VagrantPlugins
4
+ module Compose
5
+ module Programmatic
6
+
7
+ # This class defines a group of nodes, representig a set of vagrant machines with similar characteristics.
8
+ # Nodes will be composed by NodeGroup.compose method, according with the configuration of values/value_generator
9
+ # of the group of node itself.
10
+ class NodeGroup
11
+
12
+ # A number identifying the group of nodes withing the cluster.
13
+ attr_reader :index
14
+
15
+ # The name of the group of nodes
16
+ attr_reader :name
17
+
18
+ # The number of nodes/instances to be created in the group of nodes.
19
+ attr_reader :instances
20
+
21
+ # The value/value generator to be used for assigning to each node in this group a vagrant base box to be used for creating vagrant machines implementing nodes in this group.
22
+ attr_accessor :box
23
+
24
+ # The value/value generator to be used for assigning to each node in this group a box name a.k.a. the name for the machine in VirtualBox/VMware console.
25
+ attr_accessor :boxname
26
+
27
+ # The value/value generator to be used for assigning to each node in this group a unique hostname
28
+ attr_accessor :hostname
29
+
30
+ # The value/value generator to be used for assigning to each node in this group a unique list of aliases a.k.a. alternative host names
31
+ attr_accessor :aliases
32
+
33
+ # The value/value generator to be used for assigning to each node in this groupa unique ip
34
+ attr_accessor :ip
35
+
36
+ # The value/value generator to be used for assigning to each node in this group cpus
37
+ attr_accessor :cpus
38
+
39
+ # The value/value generator to be used for assigning to each node in this group memory
40
+ attr_accessor :memory
41
+
42
+ # The value/value generator to be used for assigning each node in this group to a list of ansible groups
43
+ attr_accessor :ansible_groups
44
+
45
+ # The value/value generator to be used for assigning a dictionary with custom attributes - Hash(String, obj) - to each node in this group.
46
+ attr_accessor :attributes
47
+
48
+ def initialize(index, instances, name)
49
+ @index = index
50
+ @name = name
51
+ @instances = instances
52
+ end
53
+
54
+ # Composes the group of nodes, by creating the required number of nodes
55
+ # in accordance with values/value_generators.
56
+ # Additionally, some "embedded" trasformation will be applied to attributes (boxname, hostname) and
57
+ # some "autogenerated" node properties will be computed (fqdn).
58
+ def compose(cluster_name, cluster_domain, cluster_offset)
59
+ node_index = 0
60
+ while node_index < @instances
61
+ box = generate(:box, @box, node_index)
62
+ boxname = maybe_prefix(cluster_name,
63
+ "#{generate(:boxname, @boxname, node_index)}")
64
+ hostname = maybe_prefix(cluster_name,
65
+ "#{generate(:hostname, @hostname, node_index)}")
66
+ aliases = generate(:aliases, @aliases, node_index).join(',')
67
+ fqdn = cluster_domain.empty? ? "#{hostname}" : "#{hostname}.#{cluster_domain}"
68
+ ip = generate(:ip, @ip, node_index)
69
+ cpus = generate(:cpus, @cpus, node_index)
70
+ memory = generate(:memory, @memory, node_index)
71
+ ansible_groups = generate(:ansible_groups, @ansible_groups, node_index)
72
+ attributes = generate(:attributes, @attributes, node_index)
73
+ yield VagrantPlugins::Compose::Node.new(box, boxname, hostname, fqdn, aliases, ip, cpus, memory, ansible_groups, attributes, cluster_offset + node_index, node_index)
74
+
75
+ node_index += 1
76
+ end
77
+ end
78
+
79
+ # utility function for concatenating cluster name (if present) to boxname/hostname
80
+ def maybe_prefix(cluster_name, name)
81
+ if cluster_name && cluster_name.length > 0
82
+ "#{cluster_name}-" + name
83
+ else
84
+ name
85
+ end
86
+ end
87
+
88
+ # utility function for resolving value/value generators
89
+ def generate(var, generator, node_index)
90
+ unless generator.respond_to? :call
91
+ return generator
92
+ else
93
+ begin
94
+ return generator.call(@index, @name, node_index)
95
+ rescue Exception => e
96
+ raise VagrantPlugins::Compose::Errors::AttributeExpressionError, :message => e.message, :attribute => var, :node_index => node_index, :node_group_name => name
97
+ end
98
+ end
99
+ end
100
+ end
101
+
102
+ end
103
+ end
104
+ end
@@ -1,5 +1,5 @@
1
1
  module Vagrant
2
2
  module Compose
3
- VERSION = "0.2.4"
3
+ VERSION = "0.7.0"
4
4
  end
5
5
  end
@@ -8,7 +8,7 @@ Gem::Specification.new do |spec|
8
8
  spec.license = "MIT"
9
9
  spec.authors = ["Fabrizio Pandini"]
10
10
  spec.email = ["fabrizio.pandini@unicredit.eu"]
11
- spec.homepage = "https://github.com/fabriziopandini/vagrant-compose/"
11
+ spec.homepage = "https://github.com/fabriziopandini/vagrant-compose/"
12
12
  spec.summary = %q{A Vagrant plugin that helps building complex multi-machine scenarios.}
13
13
  spec.description = %q{A Vagrant plugin that helps building complex multi-machine scenarios.}
14
14
 
@@ -17,6 +17,7 @@ Gem::Specification.new do |spec|
17
17
  spec.add_development_dependency "rake", "~> 10.4.2"
18
18
  spec.add_development_dependency "rspec", "~> 3.4.0"
19
19
  spec.add_development_dependency "rspec-its", "~> 1.2.0"
20
+ spec.add_dependency "open4", "~> 1.3.4"
20
21
 
21
22
  # The following block of code determines the files that should be included
22
23
  # in the gem. It does this by reading all the files in the directory where
@@ -48,7 +49,7 @@ Gem::Specification.new do |spec|
48
49
  File.fnmatch(ignore, File.basename(file), File::FNM_PATHNAME)
49
50
  end
50
51
  end
51
-
52
+
52
53
  spec.files = unignored_files
53
54
  spec.executables = unignored_files.map { |f| f[/^bin\/(.*)/, 1] }.compact
54
55
  spec.require_path = 'lib'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vagrant-compose
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fabrizio Pandini
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-06-26 00:00:00.000000000 Z
11
+ date: 2016-11-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - ~>
53
53
  - !ruby/object:Gem::Version
54
54
  version: 1.2.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: open4
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 1.3.4
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: 1.3.4
55
69
  description: A Vagrant plugin that helps building complex multi-machine scenarios.
56
70
  email:
57
71
  - fabrizio.pandini@unicredit.eu
@@ -64,14 +78,17 @@ files:
64
78
  - bin/console
65
79
  - bin/setup
66
80
  - CHANGELOG.md
81
+ - doc/declarative.md
82
+ - doc/programmatic.md
67
83
  - Gemfile
68
84
  - lib/locales/en.yml
69
85
  - lib/vagrant/compose/config.rb
86
+ - lib/vagrant/compose/declarative/cluster.rb
70
87
  - lib/vagrant/compose/errors.rb
88
+ - lib/vagrant/compose/node.rb
71
89
  - 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
90
+ - lib/vagrant/compose/programmatic/cluster.rb
91
+ - lib/vagrant/compose/programmatic/node_group.rb
75
92
  - lib/vagrant/compose/version.rb
76
93
  - lib/vagrant/compose.rb
77
94
  - LICENCE