moose-inventory 2.0 → 2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/release.yml +2 -0
- data/.gitignore +2 -1
- data/.rubocop.yml +21 -0
- data/BACKLOG.md +630 -8
- data/Gemfile +2 -0
- data/Gemfile.lock +1 -1
- data/README.md +315 -39
- data/Rakefile +2 -0
- data/bin/moose-inventory +2 -1
- data/docs/architecture/architecture-and-trust-boundaries.md +444 -0
- data/docs/compatibility/cli-output-compatibility.md +76 -0
- data/docs/governance/approval-register.md +37 -0
- data/docs/maintenance/database-backup-restore-guidance.md +162 -0
- data/docs/maintenance/package-maintenance-and-agent-boundaries.md +260 -0
- data/docs/process/conformance-gap-analysis-2026-05-28.md +192 -0
- data/docs/product/product-brief.md +161 -0
- data/docs/product/requirements-baseline.md +477 -0
- data/docs/qa/qa-documentation-and-release-gates.md +283 -0
- data/docs/release/package-provenance-hardening.md +126 -0
- data/docs/release/publishing.md +11 -3
- data/docs/release/release-environment-protection.md +70 -0
- data/docs/release/release-readiness.md +23 -4
- data/docs/security/accepted-risk-register.md +84 -0
- data/docs/security/security-privacy-process.md +287 -0
- data/docs/security-audit-2026-05-26-rerun.md +2 -2
- data/docs/ux/cli-workflow-notes.md +287 -0
- data/examples/ansible/ansible.cfg +3 -0
- data/examples/ansible/inventory/moose_inventory.yml +5 -0
- data/examples/ansible/inventory_plugins/moose_inventory.py +100 -0
- data/examples/ci/README.md +16 -0
- data/examples/ci/github-actions/inventory-review.yml +38 -0
- data/examples/ci/inventory/example-snapshot.yml +19 -0
- data/examples/ci/scripts/validate-inventory-snapshot.sh +30 -0
- data/lib/moose_inventory/cli/application.rb +133 -5
- data/lib/moose_inventory/cli/association_rendering.rb +74 -0
- data/lib/moose_inventory/cli/association_rendering_support.rb +89 -0
- data/lib/moose_inventory/cli/audit.rb +62 -0
- data/lib/moose_inventory/cli/audit_recording.rb +40 -0
- data/lib/moose_inventory/cli/child_relation_rendering.rb +110 -0
- data/lib/moose_inventory/cli/console.rb +135 -0
- data/lib/moose_inventory/cli/db.rb +64 -0
- data/lib/moose_inventory/cli/factory.rb +28 -0
- data/lib/moose_inventory/cli/formatter.rb +8 -12
- data/lib/moose_inventory/cli/group.rb +5 -2
- data/lib/moose_inventory/cli/group_add.rb +11 -9
- data/lib/moose_inventory/cli/group_addchild.rb +23 -65
- data/lib/moose_inventory/cli/group_addhost.rb +16 -67
- data/lib/moose_inventory/cli/group_addvar.rb +27 -47
- data/lib/moose_inventory/cli/group_get.rb +8 -42
- data/lib/moose_inventory/cli/group_list.rb +7 -40
- data/lib/moose_inventory/cli/group_listvars.rb +9 -55
- data/lib/moose_inventory/cli/group_rm.rb +12 -10
- data/lib/moose_inventory/cli/group_rmchild.rb +26 -82
- data/lib/moose_inventory/cli/group_rmhost.rb +18 -53
- data/lib/moose_inventory/cli/group_rmvar.rb +30 -41
- data/lib/moose_inventory/cli/group_tags.rb +33 -0
- data/lib/moose_inventory/cli/helpers.rb +68 -1
- data/lib/moose_inventory/cli/host.rb +6 -3
- data/lib/moose_inventory/cli/host_add.rb +69 -29
- data/lib/moose_inventory/cli/host_addgroup.rb +22 -58
- data/lib/moose_inventory/cli/host_addvar.rb +28 -52
- data/lib/moose_inventory/cli/host_get.rb +9 -37
- data/lib/moose_inventory/cli/host_list.rb +24 -21
- data/lib/moose_inventory/cli/host_listvars.rb +9 -62
- data/lib/moose_inventory/cli/host_rm.rb +60 -42
- data/lib/moose_inventory/cli/host_rmgroup.rb +25 -44
- data/lib/moose_inventory/cli/host_rmvar.rb +31 -45
- data/lib/moose_inventory/cli/host_tags.rb +33 -0
- data/lib/moose_inventory/cli/listvars_support.rb +55 -0
- data/lib/moose_inventory/cli/plan_rendering.rb +50 -0
- data/lib/moose_inventory/cli/relation_transaction_support.rb +51 -0
- data/lib/moose_inventory/cli/tag_support.rb +97 -0
- data/lib/moose_inventory/cli/variable_rendering.rb +67 -0
- data/lib/moose_inventory/config/config.rb +185 -108
- data/lib/moose_inventory/db/db.rb +170 -195
- data/lib/moose_inventory/db/exceptions.rb +6 -3
- data/lib/moose_inventory/db/models.rb +16 -0
- data/lib/moose_inventory/db/schema_migrations.rb +248 -0
- data/lib/moose_inventory/inventory_context.rb +68 -2
- data/lib/moose_inventory/operations/add_associations.rb +20 -16
- data/lib/moose_inventory/operations/add_groups.rb +21 -13
- data/lib/moose_inventory/operations/add_hosts.rb +30 -17
- data/lib/moose_inventory/operations/add_variables.rb +77 -0
- data/lib/moose_inventory/operations/entity_variable_operation_support.rb +46 -0
- data/lib/moose_inventory/operations/group_child_relations.rb +23 -16
- data/lib/moose_inventory/operations/group_cleanup.rb +23 -8
- data/lib/moose_inventory/operations/import_inventory_snapshot.rb +41 -0
- data/lib/moose_inventory/operations/inventory_doctor.rb +172 -0
- data/lib/moose_inventory/operations/inventory_snapshot.rb +60 -0
- data/lib/moose_inventory/operations/inventory_snapshot_applier.rb +112 -0
- data/lib/moose_inventory/operations/inventory_snapshot_preview.rb +174 -0
- data/lib/moose_inventory/operations/inventory_snapshot_validator.rb +134 -0
- data/lib/moose_inventory/operations/operation_event_support.rb +27 -0
- data/lib/moose_inventory/operations/query_inventory/base_query.rb +24 -0
- data/lib/moose_inventory/operations/query_inventory/group_queries.rb +86 -0
- data/lib/moose_inventory/operations/query_inventory/host_queries.rb +106 -0
- data/lib/moose_inventory/operations/query_inventory.rb +47 -0
- data/lib/moose_inventory/operations/remove_associations.rb +30 -18
- data/lib/moose_inventory/operations/remove_groups.rb +12 -12
- data/lib/moose_inventory/operations/remove_hosts.rb +68 -0
- data/lib/moose_inventory/operations/remove_variables.rb +67 -0
- data/lib/moose_inventory/runtime_options.rb +31 -0
- data/lib/moose_inventory/version.rb +3 -1
- data/lib/moose_inventory.rb +10 -7
- data/moose-inventory.gemspec +19 -35
- data/scripts/check.sh +1 -0
- data/scripts/ci/check_generated_artifacts.sh +41 -0
- data/scripts/ci/check_permissions.sh +2 -0
- data/scripts/ci/check_rubocop.sh +30 -25
- data/scripts/files.rb +5 -4
- data/spec/examples/ci_examples_spec.rb +37 -0
- data/spec/lib/moose_inventory/ansible_plugin_examples_spec.rb +29 -0
- data/spec/lib/moose_inventory/cli/application_doctor_spec.rb +50 -0
- data/spec/lib/moose_inventory/cli/application_import_export_spec.rb +100 -0
- data/spec/lib/moose_inventory/cli/application_spec.rb +25 -15
- data/spec/lib/moose_inventory/cli/audit_spec.rb +56 -0
- data/spec/lib/moose_inventory/cli/cli_spec.rb +15 -19
- data/spec/lib/moose_inventory/cli/console_spec.rb +98 -0
- data/spec/lib/moose_inventory/cli/factory_spec.rb +27 -0
- data/spec/lib/moose_inventory/cli/formatter_spec.rb +95 -3
- data/spec/lib/moose_inventory/cli/group_add_spec.rb +140 -116
- data/spec/lib/moose_inventory/cli/group_addchild_spec.rb +89 -35
- data/spec/lib/moose_inventory/cli/group_addhost_spec.rb +81 -84
- data/spec/lib/moose_inventory/cli/group_addvar_spec.rb +65 -68
- data/spec/lib/moose_inventory/cli/group_get_spec.rb +17 -33
- data/spec/lib/moose_inventory/cli/group_list_spec.rb +16 -38
- data/spec/lib/moose_inventory/cli/group_listvar_spec.rb +33 -40
- data/spec/lib/moose_inventory/cli/group_rm_spec.rb +136 -96
- data/spec/lib/moose_inventory/cli/group_rmchild_spec.rb +66 -41
- data/spec/lib/moose_inventory/cli/group_rmhost_spec.rb +76 -78
- data/spec/lib/moose_inventory/cli/group_rmvar_spec.rb +57 -63
- data/spec/lib/moose_inventory/cli/group_spec.rb +2 -0
- data/spec/lib/moose_inventory/cli/helpers_spec.rb +146 -0
- data/spec/lib/moose_inventory/cli/host_add_spec.rb +170 -116
- data/spec/lib/moose_inventory/cli/host_addgroup_spec.rb +100 -83
- data/spec/lib/moose_inventory/cli/host_addvar_spec.rb +92 -74
- data/spec/lib/moose_inventory/cli/host_get_spec.rb +14 -33
- data/spec/lib/moose_inventory/cli/host_list_spec.rb +41 -33
- data/spec/lib/moose_inventory/cli/host_listvar_spec.rb +45 -53
- data/spec/lib/moose_inventory/cli/host_rm_spec.rb +66 -48
- data/spec/lib/moose_inventory/cli/host_rmgroup_spec.rb +73 -83
- data/spec/lib/moose_inventory/cli/host_rmvar_spec.rb +56 -63
- data/spec/lib/moose_inventory/cli/host_spec.rb +2 -0
- data/spec/lib/moose_inventory/cli/tags_spec.rb +81 -0
- data/spec/lib/moose_inventory/config/config_spec.rb +41 -3
- data/spec/lib/moose_inventory/db/db_spec.rb +396 -36
- data/spec/lib/moose_inventory/db/exceptions_spec.rb +18 -0
- data/spec/lib/moose_inventory/db/models_spec.rb +7 -3
- data/spec/lib/moose_inventory/db_lifecycle_spec.rb +73 -0
- data/spec/lib/moose_inventory/inventory_context_spec.rb +10 -0
- data/spec/lib/moose_inventory/operations/add_associations_spec.rb +34 -0
- data/spec/lib/moose_inventory/operations/add_groups_spec.rb +15 -0
- data/spec/lib/moose_inventory/operations/add_hosts_spec.rb +13 -0
- data/spec/lib/moose_inventory/operations/add_variables_spec.rb +103 -0
- data/spec/lib/moose_inventory/operations/group_child_relations_spec.rb +46 -0
- data/spec/lib/moose_inventory/operations/import_inventory_snapshot_spec.rb +226 -0
- data/spec/lib/moose_inventory/operations/inventory_doctor_spec.rb +77 -0
- data/spec/lib/moose_inventory/operations/inventory_snapshot_spec.rb +50 -0
- data/spec/lib/moose_inventory/operations/operation_event_support_spec.rb +78 -0
- data/spec/lib/moose_inventory/operations/query_inventory_spec.rb +146 -0
- data/spec/lib/moose_inventory/operations/remove_associations_spec.rb +35 -0
- data/spec/lib/moose_inventory/operations/remove_groups_spec.rb +21 -0
- data/spec/lib/moose_inventory/operations/remove_hosts_spec.rb +55 -0
- data/spec/lib/moose_inventory/operations/remove_variables_spec.rb +83 -0
- data/spec/shared/shared_config_setup.rb +4 -3
- data/spec/spec_helper.rb +50 -40
- data/spec/support/cli_harness.rb +33 -0
- metadata +80 -41
|
@@ -1,15 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# rubocop:disable Metrics/BlockLength
|
|
1
4
|
require 'spec_helper'
|
|
2
5
|
|
|
3
|
-
# TODO: the usual respond_to? method doesn't seem to work on Thor objects.
|
|
4
6
|
# Why not? For now, we'll check against instance_methods.
|
|
5
7
|
|
|
6
8
|
RSpec.describe Moose::Inventory::Cli::Group do
|
|
7
9
|
before(:all) do
|
|
8
10
|
# Set up the configuration object
|
|
9
11
|
@mockarg_parts = {
|
|
10
|
-
config:
|
|
11
|
-
format:
|
|
12
|
-
env:
|
|
12
|
+
config: File.join(spec_root, 'config/config.yml'),
|
|
13
|
+
format: 'yaml',
|
|
14
|
+
env: 'test'
|
|
13
15
|
}
|
|
14
16
|
|
|
15
17
|
@mockargs = []
|
|
@@ -39,14 +41,14 @@ RSpec.describe Moose::Inventory::Cli::Group do
|
|
|
39
41
|
describe 'rmchild' do
|
|
40
42
|
#------------------------
|
|
41
43
|
it 'Group.rmchild() should be responsive' do
|
|
42
|
-
result = @group.
|
|
44
|
+
result = @group.method_defined?(:rmchild, false)
|
|
43
45
|
expect(result).to eq(true)
|
|
44
46
|
end
|
|
45
47
|
|
|
46
48
|
#------------------------
|
|
47
49
|
it '<missing args> ... should abort with an error' do
|
|
48
50
|
actual = runner do
|
|
49
|
-
@app.start(%w
|
|
51
|
+
@app.start(%w[group addchild])
|
|
50
52
|
end
|
|
51
53
|
|
|
52
54
|
# @console.out(actual, 'y')
|
|
@@ -63,7 +65,7 @@ RSpec.describe Moose::Inventory::Cli::Group do
|
|
|
63
65
|
child_name = 'fake'
|
|
64
66
|
|
|
65
67
|
actual = runner do
|
|
66
|
-
@app.start(%W
|
|
68
|
+
@app.start(%W[group addchild #{parent_name} #{child_name}])
|
|
67
69
|
end
|
|
68
70
|
|
|
69
71
|
# @console.out(actual, 'y')
|
|
@@ -79,7 +81,7 @@ RSpec.describe Moose::Inventory::Cli::Group do
|
|
|
79
81
|
child_name = 'ungrouped'
|
|
80
82
|
|
|
81
83
|
actual = runner do
|
|
82
|
-
@app.start(%W
|
|
84
|
+
@app.start(%W[group rmchild #{parent_name} #{child_name} --yes])
|
|
83
85
|
end
|
|
84
86
|
|
|
85
87
|
# @console.out(actual, 'y')
|
|
@@ -96,17 +98,17 @@ RSpec.describe Moose::Inventory::Cli::Group do
|
|
|
96
98
|
cname = 'child group'
|
|
97
99
|
|
|
98
100
|
actual = runner do
|
|
99
|
-
@app.start(%W
|
|
101
|
+
@app.start(%W[group rmchild #{pname} #{cname} --yes])
|
|
100
102
|
end
|
|
101
103
|
|
|
102
104
|
# @console.out(actual, 'y')
|
|
103
105
|
# Check output
|
|
104
106
|
desired = { aborted: true }
|
|
105
107
|
desired[:STDOUT] =
|
|
106
|
-
"Dissociate parent group '#{pname}' from child group(s) '#{cname}':\n"\
|
|
107
|
-
"
|
|
108
|
+
"Dissociate parent group '#{pname}' from child group(s) '#{cname}':\n " \
|
|
109
|
+
"- retrieve group '#{pname}'...\n"
|
|
108
110
|
desired[:STDERR] =
|
|
109
|
-
"ERROR: The group '#{pname}' does not exist.\n"\
|
|
111
|
+
"ERROR: The group '#{pname}' does not exist.\n" \
|
|
110
112
|
"An error occurred during a transaction, any changes have been rolled back.\n"
|
|
111
113
|
expected(actual, desired)
|
|
112
114
|
end
|
|
@@ -116,10 +118,10 @@ RSpec.describe Moose::Inventory::Cli::Group do
|
|
|
116
118
|
pname = 'parent_group'
|
|
117
119
|
cname = 'child group'
|
|
118
120
|
|
|
119
|
-
runner { @app.start(%W
|
|
121
|
+
runner { @app.start(%W[group add #{pname} #{cname}]) }
|
|
120
122
|
|
|
121
123
|
actual = runner do
|
|
122
|
-
@app.start(%W
|
|
124
|
+
@app.start(%W[group rmchild #{pname} #{cname} --yes])
|
|
123
125
|
end
|
|
124
126
|
|
|
125
127
|
# @console.out(actual, 'y')
|
|
@@ -127,13 +129,13 @@ RSpec.describe Moose::Inventory::Cli::Group do
|
|
|
127
129
|
# Check output
|
|
128
130
|
desired = {}
|
|
129
131
|
desired[:STDOUT] =
|
|
130
|
-
"Dissociate parent group '#{pname}' from child group(s) '#{cname}':\n"\
|
|
131
|
-
"
|
|
132
|
-
"
|
|
133
|
-
"
|
|
134
|
-
"
|
|
135
|
-
"
|
|
136
|
-
"
|
|
132
|
+
"Dissociate parent group '#{pname}' from child group(s) '#{cname}':\n " \
|
|
133
|
+
"- retrieve group '#{pname}'...\n " \
|
|
134
|
+
"- OK\n " \
|
|
135
|
+
"- remove association {group:#{pname} <-> group:#{cname}}...\n " \
|
|
136
|
+
"- doesn't exist, skipping.\n " \
|
|
137
|
+
"- OK\n " \
|
|
138
|
+
"- all OK\n" \
|
|
137
139
|
"Succeeded, with warnings.\n"
|
|
138
140
|
|
|
139
141
|
desired[:STDERR] =
|
|
@@ -147,11 +149,11 @@ RSpec.describe Moose::Inventory::Cli::Group do
|
|
|
147
149
|
pname = 'parent_group'
|
|
148
150
|
cname = 'child group'
|
|
149
151
|
|
|
150
|
-
runner { @app.start(%W
|
|
151
|
-
runner { @app.start(%W
|
|
152
|
+
runner { @app.start(%W[group add #{pname} #{cname}]) }
|
|
153
|
+
runner { @app.start(%W[group addchild #{pname} #{cname}]) }
|
|
152
154
|
|
|
153
155
|
actual = runner do
|
|
154
|
-
@app.start(%W
|
|
156
|
+
@app.start(%W[group rmchild #{pname} #{cname} --yes])
|
|
155
157
|
end
|
|
156
158
|
|
|
157
159
|
# @console.out(actual, 'y')
|
|
@@ -159,27 +161,49 @@ RSpec.describe Moose::Inventory::Cli::Group do
|
|
|
159
161
|
# Check output
|
|
160
162
|
desired = {}
|
|
161
163
|
desired[:STDOUT] =
|
|
162
|
-
"Dissociate parent group '#{pname}' from child group(s) '#{cname}':\n"\
|
|
163
|
-
"
|
|
164
|
-
"
|
|
165
|
-
"
|
|
166
|
-
"
|
|
167
|
-
"
|
|
164
|
+
"Dissociate parent group '#{pname}' from child group(s) '#{cname}':\n " \
|
|
165
|
+
"- retrieve group '#{pname}'...\n " \
|
|
166
|
+
"- OK\n " \
|
|
167
|
+
"- remove association {group:#{pname} <-> group:#{cname}}...\n " \
|
|
168
|
+
"- OK\n " \
|
|
169
|
+
"- all OK\n" \
|
|
168
170
|
"Succeeded.\n"
|
|
169
171
|
|
|
170
172
|
expected(actual, desired)
|
|
171
173
|
end
|
|
172
174
|
|
|
175
|
+
#------------------------
|
|
176
|
+
it 'GROUP CHILDGROUP --delete-orphans --dry-run should not remove or delete groups' do
|
|
177
|
+
runner { @app.start(%w[group add parent]) }
|
|
178
|
+
runner { @app.start(%w[group add child --hosts child-host]) }
|
|
179
|
+
runner { @app.start(%w[group addchild parent child]) }
|
|
180
|
+
|
|
181
|
+
actual = runner do
|
|
182
|
+
@app.start(%w[group rmchild --delete-orphans parent child --dry-run])
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
expect(actual[:unexpected]).to eq(false)
|
|
186
|
+
expect(actual[:aborted]).to eq(false)
|
|
187
|
+
expect(actual[:STDOUT]).to include('Dry run complete. No changes applied.')
|
|
188
|
+
expect(actual[:STDOUT]).to include("- Recursively delete orphaned group 'child'...
|
|
189
|
+
")
|
|
190
|
+
parent = @db.models[:group].find(name: 'parent')
|
|
191
|
+
expect(parent.children_dataset[name: 'child']).not_to be_nil
|
|
192
|
+
expect(@db.models[:group].find(name: 'child')).not_to be_nil
|
|
193
|
+
host = @db.models[:host].find(name: 'child-host')
|
|
194
|
+
expect(host.groups_dataset[name: 'ungrouped']).to be_nil
|
|
195
|
+
end
|
|
196
|
+
|
|
173
197
|
#------------------------
|
|
174
198
|
it 'GROUP CHILDGROUP --delete-orphans ... should delete orphaned child groups recursively' do
|
|
175
|
-
runner { @app.start(%w
|
|
176
|
-
runner { @app.start(%w
|
|
177
|
-
runner { @app.start(%w
|
|
178
|
-
runner { @app.start(%w
|
|
179
|
-
runner { @app.start(%w
|
|
199
|
+
runner { @app.start(%w[group add parent]) }
|
|
200
|
+
runner { @app.start(%w[group add child --hosts child-host]) }
|
|
201
|
+
runner { @app.start(%w[group add grandchild]) }
|
|
202
|
+
runner { @app.start(%w[group addchild parent child]) }
|
|
203
|
+
runner { @app.start(%w[group addchild child grandchild]) }
|
|
180
204
|
|
|
181
205
|
actual = runner do
|
|
182
|
-
@app.start(%w
|
|
206
|
+
@app.start(%w[group rmchild --delete-orphans parent child --yes])
|
|
183
207
|
end
|
|
184
208
|
|
|
185
209
|
expect(actual[:unexpected]).to eq(false)
|
|
@@ -188,7 +212,7 @@ RSpec.describe Moose::Inventory::Cli::Group do
|
|
|
188
212
|
expect(actual[:STDOUT]).to include("- Recursively delete orphaned group 'grandchild'...\n")
|
|
189
213
|
|
|
190
214
|
expect(@db.models[:group].find(name: 'parent')).not_to be_nil
|
|
191
|
-
%w
|
|
215
|
+
%w[child grandchild].each do |name|
|
|
192
216
|
expect(@db.models[:group].find(name: name)).to be_nil
|
|
193
217
|
end
|
|
194
218
|
|
|
@@ -198,12 +222,12 @@ RSpec.describe Moose::Inventory::Cli::Group do
|
|
|
198
222
|
|
|
199
223
|
#------------------------
|
|
200
224
|
it 'GROUP CHILDGROUP --delete-orphans ... should preserve child groups with another parent' do
|
|
201
|
-
runner { @app.start(%w
|
|
202
|
-
runner { @app.start(%w
|
|
203
|
-
runner { @app.start(%w
|
|
225
|
+
runner { @app.start(%w[group add parent other-parent]) }
|
|
226
|
+
runner { @app.start(%w[group addchild parent child]) }
|
|
227
|
+
runner { @app.start(%w[group addchild other-parent child]) }
|
|
204
228
|
|
|
205
229
|
actual = runner do
|
|
206
|
-
@app.start(%w
|
|
230
|
+
@app.start(%w[group rmchild --delete-orphans parent child --yes])
|
|
207
231
|
end
|
|
208
232
|
|
|
209
233
|
expect(actual[:unexpected]).to eq(false)
|
|
@@ -216,3 +240,4 @@ RSpec.describe Moose::Inventory::Cli::Group do
|
|
|
216
240
|
end
|
|
217
241
|
end
|
|
218
242
|
end
|
|
243
|
+
# rubocop:enable Metrics/BlockLength
|
|
@@ -1,44 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# rubocop:disable Metrics/BlockLength
|
|
1
4
|
require 'spec_helper'
|
|
2
5
|
|
|
3
|
-
# TODO: the usual respond_to? method doesn't seem to work on Thor objects.
|
|
4
6
|
# Why not? For now, we'll check against instance_methods.
|
|
5
7
|
|
|
6
8
|
RSpec.describe Moose::Inventory::Cli::Group do
|
|
7
9
|
before(:all) do
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
|
10
|
+
setup_cli_harness(
|
|
11
|
+
command_class: Moose::Inventory::Cli::Group,
|
|
12
|
+
command_ivar: :@group,
|
|
13
|
+
extra_commands: { :@host => Moose::Inventory::Cli::Host }
|
|
14
|
+
)
|
|
31
15
|
end
|
|
32
16
|
|
|
33
17
|
before(:each) do
|
|
34
|
-
|
|
18
|
+
reset_cli_harness
|
|
35
19
|
end
|
|
36
20
|
|
|
37
21
|
#====================
|
|
38
22
|
describe 'rmgroup' do
|
|
39
23
|
#----------------
|
|
40
24
|
it 'should be responsive' do
|
|
41
|
-
result = @group.
|
|
25
|
+
result = @group.method_defined?(:rmhost, false)
|
|
42
26
|
expect(result).to eq(true)
|
|
43
27
|
end
|
|
44
28
|
|
|
@@ -47,7 +31,7 @@ RSpec.describe Moose::Inventory::Cli::Group do
|
|
|
47
31
|
#------------------------
|
|
48
32
|
it '<missing args> ... should abort with an error' do
|
|
49
33
|
actual = runner do
|
|
50
|
-
@app.start(%w
|
|
34
|
+
@app.start(%w[group rmhost]) # <- no group or hosts given
|
|
51
35
|
end
|
|
52
36
|
|
|
53
37
|
# Check output
|
|
@@ -61,16 +45,16 @@ RSpec.describe Moose::Inventory::Cli::Group do
|
|
|
61
45
|
group_name = 'not-a-group'
|
|
62
46
|
host_name = 'example'
|
|
63
47
|
actual = runner do
|
|
64
|
-
@app.start(%W
|
|
48
|
+
@app.start(%W[group rmhost #{group_name} #{host_name} --yes])
|
|
65
49
|
end
|
|
66
50
|
|
|
67
51
|
# Check output
|
|
68
52
|
desired = { aborted: true }
|
|
69
53
|
desired[:STDOUT] =
|
|
70
|
-
"Dissociate group '#{group_name}' from host(s) '#{host_name}':\n"\
|
|
71
|
-
"
|
|
54
|
+
"Dissociate group '#{group_name}' from host(s) '#{host_name}':\n " \
|
|
55
|
+
"- retrieve group '#{group_name}'...\n"
|
|
72
56
|
desired[:STDERR] =
|
|
73
|
-
"ERROR: The group '#{group_name}' does not exist.\n"\
|
|
57
|
+
"ERROR: The group '#{group_name}' does not exist.\n" \
|
|
74
58
|
"An error occurred during a transaction, any changes have been rolled back.\n"
|
|
75
59
|
expected(actual, desired)
|
|
76
60
|
end
|
|
@@ -80,9 +64,9 @@ RSpec.describe Moose::Inventory::Cli::Group do
|
|
|
80
64
|
host_name = 'test1'
|
|
81
65
|
group_name = 'group1'
|
|
82
66
|
|
|
83
|
-
runner { @app.start(%W
|
|
84
|
-
runner { @app.start(%W
|
|
85
|
-
runner { @app.start(%W
|
|
67
|
+
runner { @app.start(%W[host add #{host_name}]) }
|
|
68
|
+
runner { @app.start(%W[group add #{group_name}]) }
|
|
69
|
+
runner { @app.start(%W[group addhost #{group_name} #{host_name}]) }
|
|
86
70
|
|
|
87
71
|
#
|
|
88
72
|
# Dissociate the host
|
|
@@ -90,32 +74,48 @@ RSpec.describe Moose::Inventory::Cli::Group do
|
|
|
90
74
|
# 2. expect that no association with ungrouped is made.
|
|
91
75
|
|
|
92
76
|
actual = runner do
|
|
93
|
-
@app.start(%W
|
|
77
|
+
@app.start(%W[group rmhost #{group_name} #{host_name} --yes])
|
|
94
78
|
end
|
|
95
79
|
|
|
96
80
|
# @console.dump(actual, 'y')
|
|
97
81
|
|
|
98
|
-
# rubocop:disable Metrics/LineLength
|
|
99
82
|
desired = { aborted: false }
|
|
100
83
|
desired[:STDOUT] =
|
|
101
|
-
"Dissociate group '#{group_name}' from host(s) '#{host_name}':\n"\
|
|
102
|
-
"
|
|
103
|
-
"
|
|
104
|
-
"
|
|
105
|
-
"
|
|
106
|
-
"
|
|
107
|
-
"
|
|
108
|
-
"
|
|
84
|
+
"Dissociate group '#{group_name}' from host(s) '#{host_name}':\n " \
|
|
85
|
+
"- retrieve group '#{group_name}'...\n " \
|
|
86
|
+
"- OK\n " \
|
|
87
|
+
"- remove association {group:#{group_name} <-> host:#{host_name}}...\n " \
|
|
88
|
+
"- OK\n " \
|
|
89
|
+
"- add automatic association {group:ungrouped <-> host:#{host_name}}...\n " \
|
|
90
|
+
"- OK\n " \
|
|
91
|
+
"- all OK\n" \
|
|
109
92
|
"Succeeded.\n"
|
|
110
93
|
expected(actual, desired)
|
|
111
|
-
# rubocop:enable Metrics/LineLength
|
|
112
|
-
|
|
113
94
|
# We should have the correct group associations
|
|
114
95
|
group = @db.models[:group].find(name: group_name)
|
|
115
96
|
hosts = group.hosts_dataset
|
|
116
97
|
expect(hosts.count).to eq(0)
|
|
117
98
|
end
|
|
118
99
|
|
|
100
|
+
#------------------------
|
|
101
|
+
it 'group rmhost GROUP HOST --dry-run should not remove membership or add ungrouped' do
|
|
102
|
+
host_name = 'test1'
|
|
103
|
+
group_name = 'group1'
|
|
104
|
+
runner { @app.start(%W[host add #{host_name}]) }
|
|
105
|
+
runner { @app.start(%W[group add #{group_name}]) }
|
|
106
|
+
runner { @app.start(%W[group addhost #{group_name} #{host_name}]) }
|
|
107
|
+
|
|
108
|
+
actual = runner { @app.start(%W[group rmhost #{group_name} #{host_name} --dry-run]) }
|
|
109
|
+
|
|
110
|
+
expect(actual[:unexpected]).to eq(false)
|
|
111
|
+
expect(actual[:aborted]).to eq(false)
|
|
112
|
+
expect(actual[:STDOUT]).to include('Dry run complete. No changes applied.')
|
|
113
|
+
group = @db.models[:group].find(name: group_name)
|
|
114
|
+
host = @db.models[:host].find(name: host_name)
|
|
115
|
+
expect(group.hosts_dataset[name: host_name]).not_to be_nil
|
|
116
|
+
expect(host.groups_dataset[name: 'ungrouped']).to be_nil
|
|
117
|
+
end
|
|
118
|
+
|
|
119
119
|
#------------------------
|
|
120
120
|
it 'GROUP HOST ... should warn about non-existing associations' do
|
|
121
121
|
# 1. Should warn that the association doesn't exist.
|
|
@@ -123,28 +123,27 @@ RSpec.describe Moose::Inventory::Cli::Group do
|
|
|
123
123
|
|
|
124
124
|
host_name = 'test_host'
|
|
125
125
|
group_name = 'test_group'
|
|
126
|
-
runner { @app.start(%W
|
|
127
|
-
runner { @app.start(%W
|
|
128
|
-
runner { @app.start(%W
|
|
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
129
|
|
|
130
130
|
actual = runner do
|
|
131
|
-
@app.start(%W
|
|
131
|
+
@app.start(%W[group rmhost #{group_name} #{host_name} --yes])
|
|
132
132
|
end
|
|
133
133
|
|
|
134
|
-
# rubocop:disable Metrics/LineLength
|
|
135
134
|
desired = { aborted: false }
|
|
136
135
|
desired[:STDOUT] =
|
|
137
|
-
"Dissociate group '#{group_name}' from host(s) '#{host_name}':\n"\
|
|
138
|
-
"
|
|
139
|
-
"
|
|
140
|
-
"
|
|
141
|
-
"
|
|
142
|
-
"
|
|
143
|
-
"
|
|
136
|
+
"Dissociate group '#{group_name}' from host(s) '#{host_name}':\n " \
|
|
137
|
+
"- retrieve group '#{group_name}'...\n " \
|
|
138
|
+
"- OK\n " \
|
|
139
|
+
"- remove association {group:#{group_name} <-> host:#{host_name}}...\n " \
|
|
140
|
+
"- doesn't exist, skipping.\n " \
|
|
141
|
+
"- OK\n " \
|
|
142
|
+
"- all OK\n" \
|
|
144
143
|
"Succeeded, with warnings.\n"
|
|
145
144
|
desired[:STDERR] =
|
|
146
|
-
"WARNING: Association {group:#{group_name} <-> host:#{host_name}} "\
|
|
147
|
-
|
|
145
|
+
"WARNING: Association {group:#{group_name} <-> host:#{host_name}} " \
|
|
146
|
+
"doesn't exist, skipping.\n"
|
|
148
147
|
|
|
149
148
|
expected(actual, desired)
|
|
150
149
|
end
|
|
@@ -154,9 +153,9 @@ RSpec.describe Moose::Inventory::Cli::Group do
|
|
|
154
153
|
host_name = 'test_host'
|
|
155
154
|
group_name = 'ungrouped'
|
|
156
155
|
|
|
157
|
-
runner { @app.start(%W
|
|
156
|
+
runner { @app.start(%W[host add #{name}]) } # <- auto creates the association with ungrouped
|
|
158
157
|
|
|
159
|
-
actual = runner { @app.start(%W
|
|
158
|
+
actual = runner { @app.start(%W[group rmhost #{group_name} #{host_name} --yes]) }
|
|
160
159
|
|
|
161
160
|
desired = { aborted: true }
|
|
162
161
|
desired[:STDERR] =
|
|
@@ -165,41 +164,39 @@ RSpec.describe Moose::Inventory::Cli::Group do
|
|
|
165
164
|
end
|
|
166
165
|
|
|
167
166
|
#------------------------
|
|
168
|
-
it 'GROUP HOST1 HOST2 ... should dissociate the group from'\
|
|
169
|
-
|
|
167
|
+
it 'GROUP HOST1 HOST2 ... should dissociate the group from ' \
|
|
168
|
+
'multiple hosts at once' do
|
|
170
169
|
# 1. Should dissociate hosts from the group
|
|
171
170
|
# 2. Should add each host to the 'ungrouped' automatic group
|
|
172
171
|
# if it has no other groups.
|
|
173
172
|
|
|
174
173
|
group_name = 'test_group'
|
|
175
|
-
host_names = %w
|
|
174
|
+
host_names = %w[test_host1 test_host2 test_host3]
|
|
176
175
|
|
|
177
|
-
runner { @app.start(%W
|
|
178
|
-
runner { @app.start(%W
|
|
176
|
+
runner { @app.start(%W[group add #{group_name}]) }
|
|
177
|
+
runner { @app.start(%W[group addhost #{group_name}] + host_names) }
|
|
179
178
|
|
|
180
179
|
actual = runner do
|
|
181
|
-
@app.start(%W
|
|
180
|
+
@app.start(%W[group rmhost #{group_name} --yes] + host_names)
|
|
182
181
|
end
|
|
183
182
|
|
|
184
183
|
# @console.out(actual, 'y')
|
|
185
184
|
desired = { aborted: false }
|
|
186
185
|
desired[:STDOUT] =
|
|
187
|
-
"Dissociate group '#{group_name}' from host(s) '#{host_names.join(',')}':\n"\
|
|
188
|
-
"
|
|
189
|
-
"
|
|
186
|
+
"Dissociate group '#{group_name}' from host(s) '#{host_names.join(',')}':\n " \
|
|
187
|
+
"- retrieve group '#{group_name}'...\n " \
|
|
188
|
+
"- OK\n"
|
|
190
189
|
host_names.each do |host|
|
|
191
190
|
desired[:STDOUT] = desired[:STDOUT] +
|
|
192
|
-
" - remove association {group:#{group_name} <-> host:#{host}}...\n"\
|
|
193
|
-
"
|
|
194
|
-
"
|
|
195
|
-
"
|
|
191
|
+
" - remove association {group:#{group_name} <-> host:#{host}}...\n " \
|
|
192
|
+
"- OK\n " \
|
|
193
|
+
"- add automatic association {group:ungrouped <-> host:#{host}}...\n " \
|
|
194
|
+
"- OK\n" \
|
|
196
195
|
end
|
|
197
196
|
desired[:STDOUT] = desired[:STDOUT] +
|
|
198
|
-
" - all OK\n"\
|
|
197
|
+
" - all OK\n" \
|
|
199
198
|
"Succeeded.\n"
|
|
200
199
|
expected(actual, desired)
|
|
201
|
-
# rubocop:enable Metrics/LineLength
|
|
202
|
-
|
|
203
200
|
# We should have the correct group associations
|
|
204
201
|
group = @db.models[:group].find(name: group_name)
|
|
205
202
|
hosts = group.hosts_dataset
|
|
@@ -210,3 +207,4 @@ RSpec.describe Moose::Inventory::Cli::Group do
|
|
|
210
207
|
end
|
|
211
208
|
end
|
|
212
209
|
end
|
|
210
|
+
# rubocop:enable Metrics/BlockLength
|