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,435 @@
1
+ # Programmatic Approach
2
+
3
+ Vagrant requires some ruby knowledge, because the Vagrantfile itself is based on ruby.
4
+
5
+ With the support of vagrant-compose, and leveraging on the same programming skills it is possible to define a cluster composed by many VMs.
6
+
7
+ ## Quick start
8
+
9
+ Create the following `Vagrantfile` for implementing a multi-machine scenario that defines a cluster named `test` with 3 `consul-server` nodes.
10
+
11
+ ``` ruby
12
+ Vagrant.configure(2) do |config|
13
+ #cluster definition
14
+ config.cluster.compose('test') do |c|
15
+ c.nodes(3, 'consul-server')
16
+ end
17
+
18
+ #cluster creation
19
+ config.cluster.nodes.each do |node, index|
20
+ config.vm.define "#{node.boxname}" do |node_vm|
21
+ node_vm.vm.box = "#{node.box}"
22
+ end
23
+ end
24
+ end
25
+ ```
26
+
27
+ The first part of the `Vagrantfile` contains the definition of the `test` cluster:
28
+
29
+ ``` ruby
30
+ config.cluster.compose('test') do |c|
31
+ ...
32
+ end
33
+ ```
34
+
35
+ Please note that the cluster definition, is followed by a block of code that allows to configure the cluster itself; in this example the configuration consists in defining a set of 3 `consul-server` nodes.
36
+
37
+ ``` ruby
38
+ c.nodes(3, 'consul-server')
39
+ ```
40
+
41
+ When the definition of the cluster is completed, behind the scene vagrant-compose take care of composing the cluster, and the resulting list of nodes will be available in the `config.cluster.nodes` variable.
42
+
43
+ The second part of the `Vagrantfile` creates the cluster by defining a vm in VirtualBox for each node in the cluster:
44
+
45
+ ``` ruby
46
+ config.cluster.nodes.each do |node, index|
47
+ config.vm.define "#{node.boxname}" do |node_vm|
48
+ node_vm.vm.box = "#{node.box}"
49
+ end
50
+ end
51
+ ```
52
+
53
+ If you run `vagrant up` you will get a 3 node cluster with following machines, based on `ubuntu/trusty64` base box (default).
54
+
55
+ - `test-consul-server1`
56
+ - `test-consul-server2`
57
+ - `test-consul-server3`
58
+
59
+ Done !
60
+
61
+ Of course, real-word scenarios are more complex; it is necessary to get more control in configuring the cluster topology and machine attributes, and finally you need also to implement automatic provisioning of software stack installed in the machines.
62
+
63
+ See following chapters for more details.
64
+
65
+ ## Configuring the cluster
66
+
67
+ Each cluster can be named passing a value to `cluster.compose` method, and the default behaviour is that name of vagrant boxes and hostnames will be prefixed by such name; if cluster name will be set to nil or "", vagrant boxes and hostnames will be composed without prefix.
68
+
69
+ Apart for cluster name, there are several options to customize the cluster definition.
70
+
71
+ ### Defining cluster attributes
72
+
73
+ Cluster attributes apply to all the node in the cluster.
74
+
75
+ You can set set cluster attributes in the block of code that is passed as a second parameter to the `cluster.compose` method, as show in the following example:
76
+
77
+ ``` ruby
78
+ config.cluster.compose('test') do |c|
79
+ c.box = "centos/7"
80
+ ...
81
+ end
82
+ ```
83
+
84
+ Following cluster attributes are available:
85
+
86
+ - **box**, [String], default = 'ubuntu/trusty64'
87
+
88
+ Sets the base box for nodes, a.k.a the image that will be used to spin up the machine; please note that the base box can be customized also for each set of nodes (see Defining set of nodes).
89
+
90
+
91
+ - **domain**, [String], default = 'vagrant'
92
+
93
+ Sets the domain used for computing the nodes in the cluster; if the `domain` value is set to `nil` or `““` (empty string), the fully qualified name and the hostname of each nodes will be the same.
94
+
95
+ ### Defining set of nodes
96
+
97
+ A cluster can be composed by one or more set of nodes.
98
+
99
+ Each set of nodes represent a group of one or more nodes with similar characteristics. For instance, in a cluster defined for testing [Consul](https://consul.io/), you will get at least two set of nodes:
100
+
101
+ - Consul server nodes
102
+ - Consul agent nodes
103
+
104
+ Set of nodes can be defined in the block of code that is passed as a second parameter to the `cluster.compose` method, by using the `nodes` method as show in the following example:
105
+
106
+ ``` ruby
107
+ config.cluster.compose('test') do |c|
108
+ ...
109
+ c.nodes(3, 'consul-agents')
110
+ ...
111
+ end
112
+ ```
113
+
114
+ The first parameter of the `nodes` method is the number of nodes in the set, while the second parameter is the name of the set; `nodes` accepts an optional third parameter, allowing to define a block of code where it is possible to customize several attributes of the set of nodes itself:
115
+
116
+ ``` ruby
117
+ config.cluster.compose('test') do |c|
118
+ ...
119
+ c.nodes(3, 'zookeeper') do |n|
120
+ n.box = "centos/7"
121
+ end
122
+ ...
123
+ end
124
+ ```
125
+
126
+ Please note that all the available attributes can be set to:
127
+
128
+ - A literal value, like for instance `"centos/7". This value will be inherited - without changes - by all nodes in the set.
129
+
130
+ - A block of code, afterwards value_generator, that will be executed when building the nodes in the set. When calling the block of code, three parameters will be given:
131
+
132
+ - **group_index**, [integer (zero based)], uniquely assigned to each set of nodes
133
+ - **group_name**, [String], with the name of the set of nodes
134
+ - **node_index**, [integer (zero based)], uniquely assigned to each node in the set
135
+
136
+ An example of value_generator is the following lambda expression, that computes the host-name for each node in the cluster (`test-consul-server1`, `test-consul-server2`, etc. etc.):
137
+
138
+ ``` ruby
139
+ lambda { |group_index, group_name, node_index|
140
+ return "#{group_name}#{node_index + 1}"
141
+ }
142
+ ```
143
+
144
+ Following set of nodes attributes are available:
145
+
146
+ - **box**, [String|String_Generator], default = `cluster.box`
147
+
148
+ Sets the base box used for creating nodes in this set.
149
+
150
+ - **boxname**, [String|String_Generator], default = `"#{group_name}#{node_index + 1}"`
151
+
152
+ Sets the box name (a.k.a. the name of the machine in VirtualBox/VMware) for each node in this set.
153
+ Note: when generating nodes, if cluster name not equals to nil or empty string the resulting boxname will be automatically prefixed by `"#{cluster_name}-"` if cluster name not equals to nil or empty string.
154
+
155
+ - **hostname**, [String|String_Generator], default = `"#{group_name}#{node_index + 1}"`
156
+
157
+ Sets the hostname for each node in this set.
158
+
159
+ Note: when generating nodes, if cluster name not equals to nil or empty string the resulting hostname will be automatically prefixed by `"#{cluster_name}-"`; additionally the **fqdn** attribute will be computed by concatenating `".#{cluster.domain}"`, if defined (if `domain` is not defined, fqdn will be the same of hostname).
160
+
161
+ - **aliases**, [Array(String)|Array(String)_Generator], default = `[]`
162
+
163
+ Allows to provide aliases for each node in this set.
164
+
165
+ Note: when generating nodes, aliases will be automatically concatenated into a string, comma separated.
166
+
167
+ - **ip**, [String|String_Generator], default = `"172.31.#{group_index}.#{100 + node_index + 1}"`
168
+
169
+ Sets the ip for for each node in this set.
170
+
171
+ - **cpus**, [Integer|Integer_Generator], default = `1`
172
+
173
+ Sets the number of cpus for each node in this set.
174
+
175
+ - **memory**, [Integer|Integer_Generator], default = `256` (MB)
176
+
177
+ Sets the memory allocated for each node in this set.
178
+
179
+ - **attributes**, [Hash(String, obj)|Hash(String, obj)_Generator], default = `{}`
180
+
181
+ Allows to provide custom additional attributes for each node in this set.
182
+
183
+ > Please note that some attribute, like boxname, hostname, ip, *must* be different for each node in the set (and in the cluster).
184
+ >
185
+ > Use value_generators for those attributes.
186
+
187
+ ### Composing nodes
188
+
189
+ By executing the code blocks provided to `cluster.compose` method, and also inner code blocks provided to `nodes` calls, the vagrant-compose plugin can compose the cluster topology, as a sum of all the nodes generated by each set.
190
+
191
+ The resulting list of nodes is stored in the `config.cluster.nodes` variable; each node has following attributes assigned using value/value generators:
192
+
193
+ - **box**
194
+ - **boxname**
195
+ - **hostname**
196
+ - **fqdn**
197
+ - **aliases**
198
+ - **ip**
199
+ - **cpus**
200
+ - **memory**
201
+ - **attributes**
202
+
203
+ Two additional attributes will be automatically set for each node:
204
+
205
+ - **index**, [integer (zero based)], uniquely assigned to each node in the cluster
206
+ - **group_index**, [integer (zero based)], uniquely assigned to each node in a set of nodes
207
+
208
+ ## Checking cluster configuration
209
+
210
+ It is possible to check the resulting list of nodes by using the `debug` command:
211
+
212
+ ``` ruby
213
+ Vagrant.configure(2) do |config|
214
+ #cluster definition
215
+ config.cluster.compose('test') do |c|
216
+ ...
217
+ end
218
+
219
+ config.cluster.debug
220
+ end
221
+ ```
222
+
223
+ Main information about nodes will be printed into the sequence of vagrant messages that is generated afeter each vagrant command, like f.i. `vagrant status`.
224
+
225
+ `debug` accepts also a parameter `verbose', which defaults to `false`; by changing this parameter you can get all the information about nodes.
226
+
227
+ ## Creating nodes
228
+
229
+ Given the list of nodes stored in the `config.cluster.nodes` variable, it is possible to create a multi-machine environment by iterating over the list:
230
+
231
+ ``` ruby
232
+ config.cluster.nodes.each do |node|
233
+ ...
234
+ end
235
+ ```
236
+
237
+ Within the cycle you can instruct vagrant to create machines based on attributes of the current node; for instance, you can define a VM in VirtualBox (default Vagrant provider); the example uses the [vagrant-hostmanager](https://github.com/smdahlen/vagrant-hostmanager) plugin to set the hostname into the guest machine:
238
+
239
+ ``` ruby
240
+ config.cluster.nodes.each do |node|
241
+ config.vm.define "#{node.boxname}" do |node_vm|
242
+ node_vm.vm.box = "#{node.box}"
243
+ node_vm.vm.network :private_network, ip: "#{node.ip}"
244
+ node_vm.vm.hostname = "#{node.fqdn}"
245
+ node_vm.hostmanager.aliases = node.aliases unless node.aliases.empty?
246
+ node_vm.vm.provision :hostmanager
247
+
248
+ node_vm.vm.provider "virtualbox" do |vb|
249
+ vb.name = "#{node.boxname}"
250
+ vb.memory = node.memory
251
+ vb.cpus = node.cpus
252
+ end
253
+ end
254
+ end
255
+ ```
256
+
257
+ > In order to increase performance of node creation, you can leverage on support for linked clones introduced by Vagrant 1.8.1. Add the following line to the above script:
258
+ >
259
+ > vb.linked_clone = true if Vagrant::VERSION =~ /^1.8/
260
+
261
+ Hostmanager requires following additional settings before the `config.cluster.nodes.each` command:
262
+
263
+ ``` ruby
264
+ config.hostmanager.enabled = false
265
+ config.hostmanager.manage_host = true
266
+ config.hostmanager.include_offline = true
267
+ ```
268
+
269
+ ## Configuring ansible provisioning
270
+
271
+ The vagrant-compose plugin provides support for a straight forward provisioning of nodes in the cluster implemented with Ansible.
272
+
273
+ ### Defining ansible_groups
274
+
275
+ Each set of nodes, and therefore all the nodes within the set, can be assigned to one or more ansible_groups.
276
+
277
+ In the following example, `consul-agent` nodes will be part of `consul` and `docker` ansible_groups.
278
+
279
+ ``` ruby
280
+ c.nodes(3, 'consul-agent') do |n|
281
+ ...
282
+ n.ansible_groups = ['consul', 'docker']
283
+ end
284
+ ```
285
+
286
+ This configuration is used by the `cluster.compose` method in order to define an **inventory file** where nodes (hosts in ansible "") clustered in group; the resulting list of ansible_groups, each with its own list of host is stored in the `config.cluster.ansible_groups` variable.
287
+
288
+ Ansible playbook will use groups for providing different software stack to different machines.
289
+
290
+ Please note that the possibility to assign a node to one or more groups introduces an high degree of flexibility; for instance, it is easy to change the topology of the cluster above for instance when it is required to implement an http load balancer based on consul service discovery:
291
+
292
+ ``` ruby
293
+ c.nodes(3, 'consul-agent') do |n|
294
+ ...
295
+ n.ansible_groups = ['consul', 'docker', 'registrator']
296
+ end
297
+ c.nodes(1, 'load-balancer') do |n|
298
+ ...
299
+ n.ansible_groups = ['consul', 'docker', 'consul-template', 'nginx']
300
+ end
301
+ ```
302
+
303
+ As you can see, `consul` and `docker` ansible_groups now include both nodes from `consul-agent` and `load-balancer` node set; vice versa, other groups like `registrator`, `consul-template`, `nginx` contain node only from one of the two nodes set.
304
+
305
+ Ansible playbook can leverage on groups for providing machines with the required software stacks.
306
+
307
+ NB. you can see resulting ansible_groups by using `debug` command with `verbose` equal to `true`.
308
+
309
+ ### Defining group vars
310
+
311
+ In Ansible, the inventory file is usually integrated with a set of variables containing settings that will influence playbooks behaviour for all the host in a group.
312
+
313
+ The vagrant-compose plugin allows you to define one or more group_vars generator for each ansible_groups; group_vars generators are code block that will be instantiated during `cluster.compose` with two input parameters:
314
+
315
+ - **context_vars** see below
316
+ - **nodes**, list of nodes in the ansible_group
317
+
318
+ Expected output type is `Hash(String, Obj)`.
319
+
320
+ For instance, when building a [Consul](https://consul.io/) cluster, all the `consul-server` nodes have to be configured with the same `bootstrap_expect` parameter, that must be set to the number of `consul-server` nodes in the cluster:
321
+
322
+ ``` ruby
323
+ config.cluster.compose('test') do |c|
324
+ ...
325
+ c.ansible_group_vars['consul-server'] = lambda { |context, nodes|
326
+ return { 'consul_bootstrap_expect' => nodes.length }
327
+ }
328
+ ...
329
+ end
330
+ ```
331
+
332
+ Ansible group vars will be stored into yaml files saved into `{cluster.ansible_playbook_path}\group_vars` folder.
333
+
334
+ The variable `cluster.ansible_playbook_path` defaults to the current directory (the directory of the Vagrantfile) + `/provisioning`; this value can be changed like any other cluster attributes (see Defining cluster attributes).
335
+
336
+ ### Defining host vars
337
+
338
+ While group vars will influence playbooks behaviour for all hosts in a group, in Ansible host vars will influence playbooks behaviour for a specific host.
339
+
340
+ The vagrant-compose plugin allows to define one or more host_vars generator for each ansible_groups; host_vars generators are code block that will be instantiated during `cluster.compose` with two input parameters:
341
+
342
+ - **context_vars** see below
343
+ - **node**, one node in the ansible_group
344
+
345
+ Expected output type is `Hash(String, Obj)`.
346
+
347
+ For instance, when building a [Consul](https://consul.io/) cluster, all the `consul-server` nodes should be configured with the ip to which Consul will bind client interfaces:
348
+
349
+ ``` ruby
350
+ config.cluster.compose('test') do |c|
351
+ ...
352
+ c.ansible_host_vars['consul-server'] = lambda { |context, node|
353
+ return { 'consul_client_ip' => node.ip }
354
+ }
355
+ ...
356
+ end
357
+ ```
358
+
359
+ Ansible host vars will be stored into yaml files saved into `{cluster.ansible_playbook_path}\host_vars` folder.
360
+
361
+ ### Context vars
362
+
363
+ Group vars and host var generation by design can operate only with the set of information that comes with a groups of nodes or a single node.
364
+
365
+ However, sometimes, it is necessary to share some information across group of nodes.
366
+ This can be achieved by setting one or more context_vars generator for each ansible_groups.
367
+
368
+ For instance, when building a [Consul](https://consul.io/) cluster, all the `consul-agent` nodes should be configured with the ip - the list of ip - to be used when joining the cluster; such list can be generated from the list of nodes in the `consul-server` set of nodes, and stored in a context_vars:
369
+
370
+ ``` ruby
371
+ config.cluster.compose('test') do |c|
372
+ ...
373
+ c.ansible_context_vars['consul-server'] = lambda { |context, nodes|
374
+ return { 'consul-serverIPs' => nodes.map { |n| n.ip }.to_a }
375
+ }
376
+ ...
377
+ end
378
+ ```
379
+
380
+ > Context_vars generator are always executed before group_vars and host_vars generators; the resulting context, is given in input to group_vars and host_vars generators.
381
+
382
+ Then, you can use the above context var when generating group_vars for nodes in the `consul-agent` group.
383
+
384
+ ``` ruby
385
+ config.cluster.compose('test') do |c|
386
+ ...
387
+ c.ansible_context_vars['consul-server'] = lambda { |context, nodes|
388
+ return { 'serverIPs' => nodes.map { |n| n.ip }.to_a }
389
+ }
390
+ c.ansible_group_vars['consul-agent'] = lambda { |context, nodes|
391
+ return { 'consul_joins' => context['consul-serverIPs'] }
392
+ }
393
+ ...
394
+ end
395
+ ```
396
+
397
+ ### Group of groups
398
+ A useful ansible inventory feature is [group of groups](http://docs.ansible.com/ansible/intro_inventory.html#hosts-and-groups).
399
+
400
+ By default vagrant-compose will generate a group named `[all_groups:children]` with all the ansible_groups defined in cluster configuration; however:
401
+ - you cannot rename all_groups
402
+ - you cannot exclude any ansible group from all_groups.
403
+
404
+ If you need higher control on groups of groups you can simply add a new item to the variable `config.cluster.ansible_groups` before creating nodes.
405
+
406
+ For instance:
407
+ ```ruby
408
+ config.cluster.ansible_groups['k8s-cluster:children'] = ['kube-master', 'kube-nodes']
409
+ ```
410
+
411
+ Please note that you can use this approach also for setting group variables directly into the inventory file using :vars (see ansible documentation).
412
+
413
+ ## Creating nodes (with provisioning)
414
+
415
+ Given `config.cluster.ansible_groups` variable, generated group_vars and host_vars files, and of course an ansible playbook, it is possible to integrate provisioning into the node creation sequence.
416
+
417
+ NB. The example uses ansible parallel execution (all nodes are provisioned together in parallel after completing node creation).
418
+
419
+ ``` ruby
420
+ config.cluster.nodes.each do |node|
421
+ config.vm.define "#{node.boxname}" do |node_vm|
422
+ ...
423
+ if node.index == config.cluster.nodes.size - 1
424
+ node_vm.vm.provision "ansible" do |ansible|
425
+ ansible.limit = 'all' # enable parallel provisioning
426
+ ansible.playbook = "provisioning/playbook.yml"
427
+ ansible.groups = config.cluster.ansible_groups
428
+ end
429
+ end
430
+ end
431
+ end
432
+
433
+
434
+ ```
435
+
data/lib/locales/en.yml CHANGED
@@ -16,26 +16,29 @@ en:
16
16
  Attribute expression expected to be a literal or a code block returning a literal (see documentation).
17
17
 
18
18
  context_var_expression_error: |-
19
- Error generating ansible context vars for ansible_group => %{ansible_group}
19
+ Error generating ansible context vars for ansible_group => %{ansible_group}
20
20
  The error message is shown below:
21
21
  %{message}
22
22
 
23
23
  Ansible context var expression expected to be a Hash literal or a code block returning an Hash literal (see documentation).
24
24
 
25
25
  group_var_expression_error: |-
26
- Error generating ansible group vars for ansible_group => %{ansible_group}
26
+ Error generating ansible group vars for ansible_group => %{ansible_group}
27
27
  The error message is shown below:
28
28
  %{message}
29
29
 
30
30
  Ansible group var expression expected to be a Hash literal or a code block returning an Hash literal (see documentation).
31
31
 
32
32
  host_var_expression_error: |-
33
- Error generating ansible host vars for host => %{host} in ansible_group => %{ansible_group}
33
+ Error generating ansible host vars for host => %{host} in ansible_group => %{ansible_group}
34
34
  The error message is shown below:
35
35
  %{message}
36
36
 
37
37
  Ansible host var expression expected to be a Hash literal or a code block returning an Hash literal (see documentation).
38
38
 
39
+ pycompose_missing: |-
40
+ Utitity pycompose missing. see documentation.
41
+
39
42
  pycompose_error: |-
40
- Error generating:
43
+ Error running cluster playbook:
41
44
  %{message}
@@ -1,6 +1,7 @@
1
1
  require "vagrant"
2
2
 
3
- require_relative "util/cluster"
3
+ require_relative "programmatic/cluster"
4
+ require_relative "declarative/cluster"
4
5
 
5
6
  module VagrantPlugins
6
7
  module Compose
@@ -18,14 +19,16 @@ module VagrantPlugins
18
19
  attr_reader :ansible_groups
19
20
 
20
21
  def initialize
22
+ @cluster = nil
21
23
  @nodes = {}
22
- @ansible_groups = {}
24
+ @ansible_groups ={}
25
+ @multimachine_filter = ((['up', 'provision'].include? ARGV[0]) && ARGV.length > 1) ? ARGV.drop(1) : [] # detect if running vagrant up/provision MACHINE
23
26
  end
24
27
 
25
28
  # Implements cluster creation, through the execution of the give code.
26
29
  def compose (name, &block)
27
30
  # create the cluster (the data structure representing the cluster)
28
- @cluster = Cluster.new(name)
31
+ @cluster = VagrantPlugins::Compose::Programmatic::Cluster.new(name)
29
32
  begin
30
33
  # executes the cluster configuration code
31
34
  block.call(@cluster)
@@ -33,31 +36,97 @@ module VagrantPlugins
33
36
  raise VagrantPlugins::Compose::Errors::ClusterInitializeError, :message => e.message, :cluster_name => name
34
37
  end
35
38
  # tranform cluster configuration into a list of nodes/ansible groups to be used for
36
- @nodes, @ansible_groups = @cluster.compose
39
+ @nodes, inventory = @cluster.compose
40
+ @ansible_groups = filterInventory(inventory)
37
41
  end
38
42
 
39
- # Implements cluster creation, through the execution of the give code.
40
- def from (file)
41
- puts "from #{file}"
42
- begin
43
- a = `xxxxx`
44
- puts "get #{a}"
45
- rescue Exception => e
46
- raise VagrantPlugins::Compose::Errors::PyComposeError, :message => e.message
43
+ # Implements cluster creation
44
+ def from (playbook_file)
45
+ # create the cluster (the data structure representing the cluster)
46
+ @cluster = VagrantPlugins::Compose::Declarative::Cluster.new()
47
+
48
+ # executes the vagrant playbook
49
+ @nodes, inventory = @cluster.from(playbook_file)
50
+ @ansible_groups = filterInventory(inventory)
51
+ end
52
+
53
+ #filter ansible groups if vagrant command specify filters and maps to a list of hostnames
54
+ def filterInventory(inventory)
55
+ ansible_groups = {}
56
+ inventory.each do |group, hosts|
57
+ ansible_groups[group] = []
58
+ hosts.each do |host|
59
+ if filterBoxname(host['boxname'])
60
+ ansible_groups[group] << host['hostname']
61
+ end
62
+ end
47
63
  end
48
64
 
65
+ ansible_groups['all_groups:children'] = ansible_groups.keys
66
+
67
+ return ansible_groups
68
+ end
49
69
 
50
- # tranform cluster configuration into a list of nodes/ansible groups to be used for
51
- @nodes, @ansible_groups = @cluster.compose
70
+ def filterBoxname(boxname)
71
+ if @multimachine_filter.length > 0
72
+ @multimachine_filter.each do |name|
73
+ if pattern = name[/^\/(.+?)\/$/, 1]
74
+ # This is a regular expression filter, so we convert to a regular
75
+ # expression check for matching.
76
+ regex = Regexp.new(pattern)
77
+ return boxname =~ regex
78
+ else
79
+ # filter name, just look for a specific VM
80
+ return boxname == name
81
+ end
82
+ end
83
+ else
84
+ # No filter was given, so we return every VM in the order
85
+ # configured.
86
+ return true
87
+ end
52
88
  end
53
89
 
54
90
  # Implements a utility method that allows to check the list of nodes generated by compose.
55
- def debug
56
- puts "==> cluster #{@cluster.name} with #{nodes.size} nodes"
57
- @nodes.each do |node|
58
- puts " #{node.boxname} accessible as #{node.fqdn} #{node.aliases} #{node.ip} => [#{node.box}, #{node.cpus} cpus, #{node.memory} memory]"
59
- end
60
- puts " ansible_groups filtered by #{@cluster.multimachine_filter}" if not @cluster.multimachine_filter.empty?
91
+ def debug(verbose = false)
92
+ puts "==> cluster #{@cluster.name} with #{nodes.size} nodes"
93
+
94
+ if not verbose
95
+ @nodes.each do |node|
96
+ puts " #{node.boxname} accessible as #{node.fqdn} #{node.aliases} #{node.ip} => [#{node.box}, #{node.cpus} cpus, #{node.memory} memory]"
97
+ end
98
+ else
99
+ puts "- nodes"
100
+ @nodes.each do |node|
101
+ puts ""
102
+ puts " - #{node.boxname}"
103
+ puts " box #{node.box}"
104
+ puts " boxname #{node.boxname}"
105
+ puts " hostname #{node.hostname}"
106
+ puts " fqdn #{node.fqdn}"
107
+ puts " aliases #{node.aliases}"
108
+ puts " ip #{node.ip}"
109
+ puts " cpus #{node.cpus}"
110
+ puts " memory #{node.memory}"
111
+ puts " ansible_groups #{node.ansible_groups}"
112
+ puts " attributes #{node.attributes}"
113
+ puts " index #{node.index}"
114
+ puts " group_index #{node.group_index}"
115
+ end
116
+
117
+ filter = " (NB. filtered by #{@cluster.multimachine_filter})" if not @multimachine_filter.empty?
118
+ puts ""
119
+ puts "- ansible_groups #{filter}"
120
+
121
+ @ansible_groups.each do |group, hosts|
122
+ puts ""
123
+ puts " - #{group}"
124
+ hosts.each do |host|
125
+ puts " - #{host}"
126
+ end
127
+ end
128
+ end
129
+ puts ""
61
130
  end
62
131
  end
63
132
  end