moose-inventory 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +0 -0
  3. data/.gitignore +17 -0
  4. data/.rubocop.yml +793 -0
  5. data/Gemfile +3 -0
  6. data/Guardfile +38 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +31 -0
  9. data/README.md.orig +35 -0
  10. data/Rakefile +1 -0
  11. data/bin/moose_inventory +10 -0
  12. data/config/dotfiles/coveralls.yml +0 -0
  13. data/config/dotfiles/gitignore +17 -0
  14. data/config/dotfiles/rubocop.yml +793 -0
  15. data/lib/moose/inventory/cli/application.rb +30 -0
  16. data/lib/moose/inventory/cli/formatter.rb +92 -0
  17. data/lib/moose/inventory/cli/group.rb +23 -0
  18. data/lib/moose/inventory/cli/group_add.rb +98 -0
  19. data/lib/moose/inventory/cli/group_addchild.rb +21 -0
  20. data/lib/moose/inventory/cli/group_addhost.rb +97 -0
  21. data/lib/moose/inventory/cli/group_addvar.rb +72 -0
  22. data/lib/moose/inventory/cli/group_get.rb +52 -0
  23. data/lib/moose/inventory/cli/group_list.rb +41 -0
  24. data/lib/moose/inventory/cli/group_rm.rb +77 -0
  25. data/lib/moose/inventory/cli/group_rmchild.rb +20 -0
  26. data/lib/moose/inventory/cli/group_rmhost.rb +89 -0
  27. data/lib/moose/inventory/cli/group_rmvar.rb +65 -0
  28. data/lib/moose/inventory/cli/host.rb +24 -0
  29. data/lib/moose/inventory/cli/host_add.rb +93 -0
  30. data/lib/moose/inventory/cli/host_addgroup.rb +88 -0
  31. data/lib/moose/inventory/cli/host_addvar.rb +76 -0
  32. data/lib/moose/inventory/cli/host_get.rb +59 -0
  33. data/lib/moose/inventory/cli/host_list.rb +40 -0
  34. data/lib/moose/inventory/cli/host_rm.rb +62 -0
  35. data/lib/moose/inventory/cli/host_rmgroup.rb +80 -0
  36. data/lib/moose/inventory/cli/host_rmvar.rb +69 -0
  37. data/lib/moose/inventory/config/config.rb +169 -0
  38. data/lib/moose/inventory/db/db.rb +249 -0
  39. data/lib/moose/inventory/db/exceptions.rb +14 -0
  40. data/lib/moose/inventory/db/models.rb +32 -0
  41. data/lib/moose/inventory/moose_inventory_cli.rb +25 -0
  42. data/lib/moose/inventory/version.rb +7 -0
  43. data/moose-inventory.gemspec +45 -0
  44. data/scripts/guard_quality.sh +3 -0
  45. data/scripts/guard_test.sh +2 -0
  46. data/scripts/reports.sh +4 -0
  47. data/spec/config/config.yml +12 -0
  48. data/spec/lib/moose/inventory/cli/application_spec.rb +15 -0
  49. data/spec/lib/moose/inventory/cli/cli_spec.rb +26 -0
  50. data/spec/lib/moose/inventory/cli/formatter_spec.rb +63 -0
  51. data/spec/lib/moose/inventory/cli/group_add_spec.rb +398 -0
  52. data/spec/lib/moose/inventory/cli/group_addhost_spec.rb +251 -0
  53. data/spec/lib/moose/inventory/cli/group_addvar_spec.rb +235 -0
  54. data/spec/lib/moose/inventory/cli/group_get_spec.rb +107 -0
  55. data/spec/lib/moose/inventory/cli/group_list_spec.rb +79 -0
  56. data/spec/lib/moose/inventory/cli/group_rm_spec.rb +191 -0
  57. data/spec/lib/moose/inventory/cli/group_rmhost_spec.rb +215 -0
  58. data/spec/lib/moose/inventory/cli/group_rmvar_spec.rb +202 -0
  59. data/spec/lib/moose/inventory/cli/group_spec.rb +15 -0
  60. data/spec/lib/moose/inventory/cli/host_add_spec.rb +330 -0
  61. data/spec/lib/moose/inventory/cli/host_addgroup_spec.rb +248 -0
  62. data/spec/lib/moose/inventory/cli/host_addvar_spec.rb +233 -0
  63. data/spec/lib/moose/inventory/cli/host_get_spec.rb +106 -0
  64. data/spec/lib/moose/inventory/cli/host_list_spec.rb +83 -0
  65. data/spec/lib/moose/inventory/cli/host_rm_spec.rb +132 -0
  66. data/spec/lib/moose/inventory/cli/host_rmgroup_spec.rb +245 -0
  67. data/spec/lib/moose/inventory/cli/host_rmvar_spec.rb +206 -0
  68. data/spec/lib/moose/inventory/cli/host_spec.rb +12 -0
  69. data/spec/lib/moose/inventory/config/config_spec.rb +80 -0
  70. data/spec/lib/moose/inventory/db/db_spec.rb +184 -0
  71. data/spec/lib/moose/inventory/db/models_spec.rb +150 -0
  72. data/spec/shared/shared_config_setup.rb +21 -0
  73. data/spec/spec_helper.rb +110 -0
  74. metadata +386 -0
@@ -0,0 +1,107 @@
1
+ require 'spec_helper'
2
+
3
+ # TODO: the usual respond_to? method doesn't seem to work on Thor objects.
4
+ # Why not? For now, we'll check against instance_methods.
5
+
6
+ RSpec.describe Moose::Inventory::Cli::Group do
7
+ before(:all) do
8
+ # Set up the configuration object
9
+ @mockarg_parts = {
10
+ config: File.join(spec_root, 'config/config.yml'),
11
+ format: 'yaml',
12
+ env: 'test'
13
+ }
14
+
15
+ @mockargs = []
16
+ @mockarg_parts.each do |key, val|
17
+ @mockargs << "--#{key}"
18
+ @mockargs << val
19
+ end
20
+
21
+ @config = Moose::Inventory::Config
22
+ @config.init(@mockargs)
23
+ @console = Moose::Inventory::Cli::Formatter
24
+
25
+ @db = Moose::Inventory::DB
26
+ @db.init if @db.db.nil?
27
+
28
+ @group = Moose::Inventory::Cli::Group
29
+ @app = Moose::Inventory::Cli::Application
30
+ end
31
+
32
+ before(:each) do
33
+ @db.reset
34
+ end
35
+
36
+ #=======================
37
+ describe 'get' do
38
+ #---------------------
39
+ it 'should be responsive' do
40
+ result = @group.instance_methods(false).include?(:get)
41
+ expect(result).to eq(true)
42
+ end
43
+
44
+ #---------------------
45
+ it '<missing args> ... should abort with an error' do
46
+ actual = runner { @app.start(%W(group get)) }
47
+
48
+ #@console.out(actual,'y')
49
+
50
+ desired = {aborted: true}
51
+ desired[:STDERR] = "ERROR: Wrong number of arguments, 0 for 1 or more\n"
52
+
53
+ expected(actual, desired)
54
+ end
55
+
56
+ #---------------------
57
+ it "GROUP ... should return an empty set when GROUP doesn't exist" do
58
+ group_name = 'does-not-exist'
59
+ actual = runner { @app.start(%W(group get #{ group_name })) }
60
+
61
+ #@console.out(actual, 'y')
62
+
63
+ desired = {}
64
+ desired[:STDOUT] = {}.to_yaml
65
+
66
+ expected(actual, desired)
67
+ end
68
+
69
+ #---------------------
70
+ it 'GROUP ... should get a group from the db' do
71
+ name = 'test_group'
72
+ runner { @app.start(%W(group add #{ name })) }
73
+
74
+ actual = runner { @app.start(%W(group get #{ name })) }
75
+
76
+ mock = {}
77
+ mock[name.to_sym] = {}
78
+ # mock[name.to_sym][:hosts] = [] # TODO: Should this be present or not?
79
+
80
+ desired = { aborted: false, STDOUT: '', STDERR: '' }
81
+ desired[:STDOUT] = mock.to_yaml
82
+
83
+ expected(actual, desired)
84
+ end
85
+
86
+ #---------------------
87
+ it 'GROUP ... should display groupvars, if any are set' do
88
+ name = 'test_group'
89
+ var = 'foo=bar'
90
+ tmp = runner { @app.start(%W(group add #{ name })) }
91
+ tmp = runner { @app.start(%W(group addvar #{ name } #{ var })) }
92
+
93
+ actual = runner { @app.start(%W(group get #{ name })) }
94
+ #@console.out(actual, 'y')
95
+
96
+ mock = {}
97
+ mock[name.to_sym] = {}
98
+ mock[name.to_sym][:groupvars] = {foo: 'bar'}
99
+
100
+ desired = {}
101
+ desired[:STDOUT] = mock.to_yaml
102
+
103
+ expected(actual, desired)
104
+ end
105
+
106
+ end
107
+ end
@@ -0,0 +1,79 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Moose::Inventory::Cli::Group do
4
+ before(:all) do
5
+ # Set up the configuration object
6
+ @mockarg_parts = {
7
+ config: File.join(spec_root, 'config/config.yml'),
8
+ format: 'yaml',
9
+ env: 'test'
10
+ }
11
+
12
+ @mockargs = []
13
+ @mockarg_parts.each do |key, val|
14
+ @mockargs << "--#{key}"
15
+ @mockargs << val
16
+ end
17
+
18
+ @config = Moose::Inventory::Config
19
+ @config.init(@mockargs)
20
+
21
+ @db = Moose::Inventory::DB
22
+ @db.init if @db.db.nil?
23
+
24
+ @group = Moose::Inventory::Cli::Group
25
+ @app = Moose::Inventory::Cli::Application
26
+ end
27
+
28
+ before(:each) do
29
+ @db.reset
30
+ end
31
+
32
+ #====================
33
+ describe 'list' do
34
+ #---------------------
35
+ it 'should be responsive' do
36
+ result = @group.instance_methods(false).include?(:list)
37
+ expect(result).to eq(true)
38
+ end
39
+
40
+ #---------------------
41
+ it 'should return an empty set when no results' do
42
+ # no items in the db
43
+ actual = runner { @app.start(%W(group list)) }
44
+
45
+ desired = { aborted: false, STDOUT: '', STDERR: '' }
46
+ desired[:STDOUT] = {}.to_yaml
47
+
48
+ expected(actual, desired)
49
+ end
50
+
51
+ #---------------------
52
+ it 'should get a list of group from the db' do
53
+ var = 'foo=bar'
54
+ host_name = 'test_host'
55
+
56
+ mock = {}
57
+ groups = %w(group1 group2 group3)
58
+ groups.each do |name|
59
+ runner { @app.start(%W(group add #{name})) }
60
+ runner { @app.start(%W(group addvar #{ name } #{var})) }
61
+ mock[name.to_sym] = {}
62
+ mock[name.to_sym][:groupvars] = {foo: 'bar'}
63
+ end
64
+
65
+ # items should now be in the db
66
+ actual = runner{ @app.start(%w(group list)) }
67
+
68
+ desired = { aborted: false, STDOUT: '', STDERR: '' }
69
+ desired[:STDOUT] = mock.to_yaml
70
+
71
+ expected(actual, desired)
72
+ end
73
+ # #---------------------
74
+ # it 'host list ... should display hostvars, if any are set' do
75
+ # Covered by 'should get a list of hosts from the db'
76
+ # end
77
+
78
+ end
79
+ end
@@ -0,0 +1,191 @@
1
+ require 'spec_helper'
2
+
3
+ # TODO: the usual respond_to? method doesn't seem to work on Thor objects.
4
+ # Why not? For now, we'll check against instance_methods.
5
+
6
+ RSpec.describe Moose::Inventory::Cli::Group do
7
+ before(:all) do
8
+ # Set up the configuration object
9
+ @mockarg_parts = {
10
+ config: File.join(spec_root, 'config/config.yml'),
11
+ format: 'yaml',
12
+ env: 'test'
13
+ }
14
+
15
+ @mockargs = []
16
+ @mockarg_parts.each do |key, val|
17
+ @mockargs << "--#{key}"
18
+ @mockargs << val
19
+ end
20
+
21
+ @config = Moose::Inventory::Config
22
+ @config.init(@mockargs)
23
+
24
+ @console = Moose::Inventory::Cli::Formatter
25
+
26
+ @db = Moose::Inventory::DB
27
+ @db.init if @db.db.nil?
28
+
29
+ @group = Moose::Inventory::Cli::Group
30
+ @host = Moose::Inventory::Cli::Host
31
+ @app = Moose::Inventory::Cli::Application
32
+ end
33
+
34
+ before(:each) do
35
+ @db.reset
36
+ end
37
+
38
+ #======================
39
+ describe 'rm' do
40
+ #---------------
41
+ it 'Group.rm() should be responsive' do
42
+ result = @group.instance_methods(false).include?(:rm)
43
+ expect(result).to eq(true)
44
+ end
45
+
46
+ #---------------
47
+ it '<missing argument> ... should abort with an error' do
48
+ actual = runner { @app.start(%w(host rm)) }
49
+
50
+ # Check output
51
+ desired = { aborted: true, STDERR: '', STDOUT: '' }
52
+ desired[:STDERR] = "ERROR: Wrong number of arguments, 0 for 1 or more.\n"
53
+ expected(actual, desired)
54
+ end
55
+
56
+ # --------------------
57
+ it 'ungrouped ... should abort with an error' do
58
+ actual = runner { @app.start(%W(group rm ungrouped)) }
59
+
60
+ # Check output
61
+ desired = {aborted: true}
62
+ desired[:STDERR] =
63
+ "Cannot manually manipulate the automatic group 'ungrouped'\n"
64
+ expected(actual, desired)
65
+ end
66
+
67
+
68
+ #---------------
69
+ it '<non-existent group> ... should warn about non-existent groups' do
70
+ # Rationale:
71
+ # The request implies the desired state is that the group is not present
72
+ # If the group is not present, for whatever reason, then the desired state
73
+ # already exists.
74
+
75
+ # no items in the db
76
+ group_name = "fake"
77
+ actual = runner { @app.start(%W(group rm #{group_name})) }
78
+
79
+ #@console.out(actual,'y')
80
+ desired = {}
81
+ desired[:STDOUT] =
82
+ "Remove group '#{group_name}':\n"\
83
+ " - Retrieve group '#{group_name}'...\n"\
84
+ " - No such group, skipping.\n"\
85
+ " - OK\n"\
86
+ " - All OK\n"\
87
+ "Succeeded, with warnings.\n"
88
+ desired[:STDERR] =
89
+ "WARNING: Group '#{group_name}' does not exist, skipping.\n"
90
+
91
+ expected(actual, desired)
92
+ end
93
+
94
+ #---------------
95
+ it 'GROUP ... should remove a group' do
96
+ group_name = 'test1'
97
+ @db.models[:group].create(name: group_name)
98
+
99
+ actual = runner { @app.start(%W(group rm #{group_name})) }
100
+
101
+ # Check output
102
+ desired = {}
103
+ desired[:STDOUT] =
104
+ "Remove group '#{group_name}':\n"\
105
+ " - Retrieve group '#{group_name}'...\n"\
106
+ " - OK\n"\
107
+ " - Destroy group '#{group_name}'...\n"\
108
+ " - OK\n"\
109
+ " - All OK\n"\
110
+ "Succeeded.\n"
111
+ expected(actual, desired)
112
+
113
+ # Check db
114
+ group = @db.models[:group].find(name: group_name)
115
+ expect(group).to be_nil
116
+ end
117
+
118
+ #---------------
119
+ it "GROUP ... should handle the automatic 'ungrouped' group for associated hosts" do
120
+ host_name = 'test-host1'
121
+ group_name = 'test-group1'
122
+
123
+ tmp = runner { @app.start(%W(group add #{group_name} --hosts #{host_name})) }
124
+ expect(tmp[:unexpected]).to eq(false)
125
+ expect(tmp[:aborted]).to eq(false)
126
+ host = @db.models[:host].find(name: host_name)
127
+ groups_ds = host.groups_dataset
128
+ expect(groups_ds).not_to be_nil
129
+ expect(groups_ds[name: 'ungrouped']).to be_nil # Shouldn't be ungrouped
130
+
131
+ # Now do the rm
132
+ actual = runner { @app.start(%W(group rm #{group_name})) }
133
+
134
+ # @console.out(actual)
135
+
136
+ # Check output
137
+ desired = {}
138
+ desired[:STDOUT] =
139
+ "Remove group '#{group_name}':\n"\
140
+ " - Retrieve group '#{group_name}'...\n"\
141
+ " - OK\n"\
142
+ " - Adding automatic association {group:ungrouped <-> host:#{host_name}}...\n"\
143
+ " - OK\n"\
144
+ " - Destroy group '#{group_name}'...\n"\
145
+ " - OK\n"\
146
+ " - All OK\n"\
147
+ "Succeeded.\n"
148
+ expected(actual, desired)
149
+
150
+ # Check db
151
+ group = @db.models[:group].find(name: group_name)
152
+ expect(group).to be_nil
153
+
154
+ host = @db.models[:host].find(name: host_name)
155
+ expect(host).not_to be_nil
156
+ groups_ds = host.groups_dataset
157
+ expect(groups_ds).not_to be_nil
158
+ expect(groups_ds[name: 'ungrouped']).not_to be_nil
159
+ end
160
+
161
+ #---------------
162
+ it 'GROUP1 GROUP2 ... should remove multiple groups' do
163
+ names = %w(group1 group2 group3)
164
+ names.each do |name|
165
+ @db.models[:group].create(name: name)
166
+ end
167
+
168
+ actual = runner { @app.start(%w(group rm) + names) }
169
+
170
+ # Check output
171
+ desired = {STDOUT: ''}
172
+ names.each do |name|
173
+ # Check output
174
+ desired[:STDOUT] = desired[:STDOUT] +
175
+ "Remove group '#{name}':\n"\
176
+ " - Retrieve group '#{name}'...\n"\
177
+ " - OK\n"\
178
+ " - Destroy group '#{name}'...\n"\
179
+ " - OK\n"\
180
+ " - All OK\n"
181
+ end
182
+ desired[:STDOUT] = desired[:STDOUT] + "Succeeded.\n"
183
+ expected(actual, desired)
184
+
185
+
186
+ # Check db
187
+ hosts = @db.models[:host].all
188
+ expect(hosts.count).to eq(0)
189
+ end
190
+ end
191
+ end
@@ -0,0 +1,215 @@
1
+ require 'spec_helper'
2
+
3
+ # TODO: the usual respond_to? method doesn't seem to work on Thor objects.
4
+ # Why not? For now, we'll check against instance_methods.
5
+
6
+ RSpec.describe Moose::Inventory::Cli::Group do
7
+ before(:all) do
8
+ # Set up the configuration object
9
+ @mockarg_parts = {
10
+ config: File.join(spec_root, 'config/config.yml'),
11
+ format: 'yaml',
12
+ env: 'test'
13
+ }
14
+
15
+ @mockargs = []
16
+ @mockarg_parts.each do |key, val|
17
+ @mockargs << "--#{key}"
18
+ @mockargs << val
19
+ end
20
+
21
+ @console = Moose::Inventory::Cli::Formatter
22
+ @config = Moose::Inventory::Config
23
+ @config.init(@mockargs)
24
+
25
+ @db = Moose::Inventory::DB
26
+ @db.init if @db.db.nil?
27
+
28
+ @group = Moose::Inventory::Cli::Group
29
+ @host = Moose::Inventory::Cli::Host
30
+ @app = Moose::Inventory::Cli::Application
31
+ end
32
+
33
+ before(:each) do
34
+ @db.reset
35
+ end
36
+
37
+ #====================
38
+ describe 'rmgroup' do
39
+ #----------------
40
+ it 'should be responsive' do
41
+ result = @group.instance_methods(false).include?(:rmhost)
42
+ expect(result).to eq(true)
43
+ end
44
+
45
+ #----------------
46
+
47
+ #------------------------
48
+ it '<missing args> ... should abort with an error' do
49
+ actual = runner do
50
+ @app.start(%w(group rmhost)) # <- no group or hosts given
51
+ end
52
+
53
+ # Check output
54
+ desired = { aborted: true}
55
+ desired[:STDERR] = "ERROR: Wrong number of arguments, 0 for 2 or more.\n"
56
+ expected(actual, desired)
57
+ end
58
+
59
+ #------------------------
60
+ it 'GROUP GROUP ... should abort if the group does not exist' do
61
+ group_name = 'not-a-group'
62
+ host_name = 'example'
63
+ actual = runner do
64
+ @app.start(%W(group rmhost #{group_name} #{host_name}))
65
+ end
66
+
67
+ # Check output
68
+ desired = { aborted: true}
69
+ desired[:STDOUT] =
70
+ "Dissociate group '#{group_name}' from host(s) '#{host_name}':\n"\
71
+ " - retrieve group '#{group_name}'...\n"
72
+ desired[:STDERR] =
73
+ "ERROR: The group '#{group_name}' does not exist.\n"\
74
+ "An error occurred during a transaction, any changes have been rolled back.\n"
75
+ expected(actual, desired)
76
+ end
77
+
78
+ #------------------------
79
+ it 'GROUP HOST ... should dissociate the group from an existing group' do
80
+ host_name = 'test1'
81
+ group_name = 'group1'
82
+
83
+ runner { @app.start(%W(host add #{host_name})) }
84
+ runner { @app.start(%W(group add #{group_name})) }
85
+ runner { @app.start(%W(group addhost #{group_name} #{host_name} )) }
86
+
87
+ #
88
+ # Dissociate the host
89
+ # 1. expect that the group association is removed
90
+ # 2. expect that no association with ungrouped is made.
91
+
92
+ actual = runner do
93
+ @app.start(%W(group rmhost #{group_name} #{host_name} ))
94
+ end
95
+
96
+ #@console.dump(actual, 'y')
97
+
98
+ # rubocop:disable Metrics/LineLength
99
+ desired = { aborted: false}
100
+ desired[:STDOUT] =
101
+ "Dissociate group '#{group_name}' from host(s) '#{host_name}':\n"\
102
+ " - retrieve group '#{group_name}'...\n"\
103
+ " - OK\n"\
104
+ " - remove association {group:#{group_name} <-> host:#{host_name}}...\n"\
105
+ " - OK\n"\
106
+ " - add automatic association {group:ungrouped <-> host:#{host_name}}...\n"\
107
+ " - OK\n"\
108
+ " - all OK\n"\
109
+ "Succeeded.\n"
110
+ expected(actual, desired)
111
+ # rubocop:enable Metrics/LineLength
112
+
113
+ # We should have the correct group associations
114
+ group = @db.models[:group].find(name: group_name)
115
+ hosts = group.hosts_dataset
116
+ expect(hosts.count).to eq(0)
117
+ end
118
+
119
+ #------------------------
120
+ it 'GROUP HOST ... should warn about non-existing associations' do
121
+ # 1. Should warn that the association doesn't exist.
122
+ # 2. Should complete with success. (desired state == actual state)
123
+
124
+ host_name = 'test_host'
125
+ group_name = 'test_group'
126
+ runner { @app.start(%W(host add #{host_name})) }
127
+ runner { @app.start(%W(group add #{group_name})) }
128
+ runner { @app.start(%W(group addhost #{host_name})) }
129
+
130
+ actual = runner do
131
+ @app.start(%W(group rmhost #{group_name} #{host_name}))
132
+ end
133
+
134
+ # rubocop:disable Metrics/LineLength
135
+ desired = { aborted: false}
136
+ desired[:STDOUT] =
137
+ "Dissociate group '#{group_name}' from host(s) '#{host_name}':\n"\
138
+ " - retrieve group \'#{group_name}\'...\n"\
139
+ " - OK\n"\
140
+ " - remove association {group:#{group_name } <-> host:#{host_name}}...\n"\
141
+ " - doesn't exist, skipping.\n"\
142
+ " - OK\n"\
143
+ " - all OK\n"\
144
+ "Succeeded, with warnings.\n"
145
+ desired[:STDERR] =
146
+ "WARNING: Association {group:#{group_name} <-> host:#{host_name}} "\
147
+ "doesn't exist, skipping.\n"
148
+
149
+ expected(actual, desired)
150
+ end
151
+
152
+ #------------------------
153
+ it '\'ungrouped\' HOST ... should abort with an error' do
154
+
155
+ host_name = 'test_host'
156
+ group_name = 'ungrouped'
157
+
158
+ runner { @app.start(%W(host add #{name})) } # <- auto creates the association with ungrouped
159
+
160
+ actual = runner { @app.start(%W(group rmhost #{group_name} #{host_name} )) }
161
+
162
+ desired = { aborted: true}
163
+ desired[:STDERR] =
164
+ "ERROR: Cannot manually manipulate the automatic group 'ungrouped'.\n"
165
+ expected(actual, desired)
166
+ end
167
+
168
+ #------------------------
169
+ it 'GROUP HOST1 HOST2 ... should dissociate the group from'\
170
+ ' multiple hosts at once' do
171
+ # 1. Should dissociate hosts from the group
172
+ # 2. Should add each host to the 'ungrouped' automatic group
173
+ # if it has no other groups.
174
+
175
+ group_name = 'test_group'
176
+ host_names = %W( test_host1 test_host2 test_host3 )
177
+
178
+ runner { @app.start(%W(group add #{group_name} )) }
179
+ runner { @app.start(%W(group addhost #{group_name}) + host_names) }
180
+
181
+ actual = runner do
182
+ @app.start(%W(group rmhost #{group_name}) + host_names)
183
+ end
184
+
185
+ #@console.out(actual, 'y')
186
+
187
+ # rubocop:disable Metrics/LineLength
188
+ desired = { aborted: false}
189
+ desired[:STDOUT] =
190
+ "Dissociate group '#{group_name}' from host(s) '#{host_names.join(',')}':\n"\
191
+ " - retrieve group \'#{group_name}\'...\n"\
192
+ " - OK\n"
193
+ host_names.each do |host|
194
+ desired[:STDOUT] = desired[:STDOUT] +
195
+ " - remove association {group:#{group_name} <-> host:#{host}}...\n"\
196
+ " - OK\n"\
197
+ " - add automatic association {group:ungrouped <-> host:#{host}}...\n"\
198
+ " - OK\n"\
199
+ end
200
+ desired[:STDOUT] = desired[:STDOUT] +
201
+ " - all OK\n"\
202
+ "Succeeded.\n"
203
+ expected(actual, desired)
204
+ # rubocop:enable Metrics/LineLength
205
+
206
+ # We should have the correct group associations
207
+ group = @db.models[:group].find(name: group_name)
208
+ hosts = group.hosts_dataset
209
+ expect(hosts.count).to eq(0)
210
+ host_names.each do |host|
211
+ expect(hosts[name: host]).to be_nil
212
+ end
213
+ end
214
+ end
215
+ end