moose-inventory 1.0.9 → 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/ci.yml +15 -1
- data/.github/workflows/release.yml +60 -0
- data/.gitignore +2 -1
- data/.gitleaks.toml +9 -0
- data/.rubocop.yml +49 -0
- data/BACKLOG.md +752 -24
- data/Gemfile +2 -0
- data/Gemfile.lock +36 -1
- data/README.md +340 -44
- 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 +54 -50
- data/docs/release/release-environment-protection.md +70 -0
- data/docs/release/release-readiness.md +37 -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 +75 -0
- data/docs/security-audit-2026-05-26.md +63 -0
- 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 +7 -1
- data/lib/moose_inventory/cli/group_add.rb +91 -73
- data/lib/moose_inventory/cli/group_addchild.rb +41 -66
- data/lib/moose_inventory/cli/group_addhost.rb +33 -71
- 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 +105 -73
- data/lib/moose_inventory/cli/group_rmchild.rb +47 -57
- data/lib/moose_inventory/cli/group_rmhost.rb +34 -61
- 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 +143 -0
- data/lib/moose_inventory/cli/host.rb +8 -2
- data/lib/moose_inventory/cli/host_add.rb +91 -66
- data/lib/moose_inventory/cli/host_addgroup.rb +39 -66
- 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 +39 -55
- 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 +188 -193
- 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 +116 -0
- data/lib/moose_inventory/operations/add_associations.rb +131 -0
- data/lib/moose_inventory/operations/add_groups.rb +123 -0
- data/lib/moose_inventory/operations/add_hosts.rb +123 -0
- 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 +125 -0
- data/lib/moose_inventory/operations/group_cleanup.rb +70 -0
- 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 +113 -0
- data/lib/moose_inventory/operations/remove_groups.rb +79 -0
- 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 +22 -35
- data/scripts/check.sh +3 -0
- data/scripts/ci/check_generated_artifacts.sh +41 -0
- data/scripts/ci/check_permissions.sh +5 -0
- data/scripts/ci/check_rubocop.sh +33 -0
- data/scripts/ci/check_secrets.sh +26 -0
- data/scripts/ci/check_security.sh +18 -0
- data/scripts/ci/install_security_tools.sh +47 -0
- data/scripts/files.rb +5 -4
- data/scripts/install_dependencies.sh +2 -0
- 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 +165 -85
- data/spec/lib/moose_inventory/cli/group_rmchild_spec.rb +100 -30
- 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 +551 -29
- 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 +111 -0
- data/spec/lib/moose_inventory/operations/add_groups_spec.rb +80 -0
- data/spec/lib/moose_inventory/operations/add_hosts_spec.rb +82 -0
- data/spec/lib/moose_inventory/operations/add_variables_spec.rb +103 -0
- data/spec/lib/moose_inventory/operations/group_child_relations_spec.rb +122 -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 +113 -0
- data/spec/lib/moose_inventory/operations/remove_groups_spec.rb +78 -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 +163 -35
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
require 'cli/factory'
|
|
5
|
+
require 'operations/query_inventory'
|
|
6
|
+
|
|
7
|
+
RSpec.describe Moose::Inventory::Cli::Factory do
|
|
8
|
+
let(:context) { instance_double('InventoryContext') }
|
|
9
|
+
subject(:factory) { described_class.new(context: context) }
|
|
10
|
+
|
|
11
|
+
it 'builds operations with the shared context' do
|
|
12
|
+
operation_class = class_double('OperationClass')
|
|
13
|
+
operation = instance_double('Operation')
|
|
14
|
+
|
|
15
|
+
expect(operation_class).to receive(:new).with(context: context, emitter: :emit).and_return(operation)
|
|
16
|
+
|
|
17
|
+
expect(factory.operation(operation_class, emitter: :emit)).to eq(operation)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it 'memoizes the query inventory wrapper for the shared context' do
|
|
21
|
+
first = factory.query_inventory
|
|
22
|
+
second = factory.query_inventory
|
|
23
|
+
|
|
24
|
+
expect(first).to be_a(Moose::Inventory::Operations::QueryInventory)
|
|
25
|
+
expect(second).to equal(first)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'spec_helper'
|
|
2
4
|
|
|
3
|
-
# TODO: the usual respond_to? method doesn't seem to work on Thor objects.
|
|
4
5
|
# Why not? For now, we'll check against instance_methods.
|
|
5
6
|
|
|
6
7
|
RSpec.describe Moose::Inventory::Cli::Formatter do
|
|
@@ -33,7 +34,7 @@ RSpec.describe Moose::Inventory::Cli::Formatter do
|
|
|
33
34
|
actual = runner { @formatter.out(test, 'json') }
|
|
34
35
|
|
|
35
36
|
desired = { aborted: false, STDOUT: '', STDERR: '' }
|
|
36
|
-
desired[:STDOUT] = test.to_json
|
|
37
|
+
desired[:STDOUT] = "#{test.to_json}\n"
|
|
37
38
|
|
|
38
39
|
expected(actual, desired)
|
|
39
40
|
end
|
|
@@ -44,7 +45,7 @@ RSpec.describe Moose::Inventory::Cli::Formatter do
|
|
|
44
45
|
actual = runner { @formatter.out(test, 'prettyjson') }
|
|
45
46
|
|
|
46
47
|
desired = { aborted: false, STDOUT: '', STDERR: '' }
|
|
47
|
-
desired[:STDOUT] = JSON.pretty_generate(test)
|
|
48
|
+
desired[:STDOUT] = "#{JSON.pretty_generate(test)}\n"
|
|
48
49
|
|
|
49
50
|
expected(actual, desired)
|
|
50
51
|
end
|
|
@@ -59,5 +60,96 @@ RSpec.describe Moose::Inventory::Cli::Formatter do
|
|
|
59
60
|
|
|
60
61
|
expected(actual, desired)
|
|
61
62
|
end
|
|
63
|
+
|
|
64
|
+
it 'info() prints the provided message instead of a literal placeholder' do
|
|
65
|
+
actual = runner { @formatter.info(2, 'hello world') }
|
|
66
|
+
|
|
67
|
+
desired = { aborted: false, STDOUT: '', STDERR: '' }
|
|
68
|
+
desired[:STDOUT] = ' INFO: hello world'
|
|
69
|
+
|
|
70
|
+
expected(actual, desired)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
describe 'stream helpers' do
|
|
75
|
+
it 'puts() writes indented text to stdout by default' do
|
|
76
|
+
actual = runner { @formatter.puts(2, 'hello world') }
|
|
77
|
+
|
|
78
|
+
desired = { aborted: false, STDOUT: " hello world\n", STDERR: '' }
|
|
79
|
+
|
|
80
|
+
expected(actual, desired)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it 'puts() writes indented text to stderr when requested' do
|
|
84
|
+
actual = runner { @formatter.puts(2, 'hello world', 'STDERR') }
|
|
85
|
+
|
|
86
|
+
desired = { aborted: false, STDOUT: '', STDERR: " hello world\n" }
|
|
87
|
+
|
|
88
|
+
expected(actual, desired)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it 'puts() aborts on an unknown output stream' do
|
|
92
|
+
actual = runner { @formatter.puts(2, 'hello world', 'BOGUS') }
|
|
93
|
+
|
|
94
|
+
desired = { aborted: true, STDOUT: '', STDERR: "Output stream 'BOGUS' is not known.\n" }
|
|
95
|
+
|
|
96
|
+
expected(actual, desired)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it 'print() writes indented text to stdout by default' do
|
|
100
|
+
actual = runner { @formatter.print(2, 'hello world') }
|
|
101
|
+
|
|
102
|
+
desired = { aborted: false, STDOUT: ' hello world', STDERR: '' }
|
|
103
|
+
|
|
104
|
+
expected(actual, desired)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
it 'print() writes indented text to stderr when requested' do
|
|
108
|
+
actual = runner { @formatter.print(2, 'hello world', 'STDERR') }
|
|
109
|
+
|
|
110
|
+
desired = { aborted: false, STDOUT: '', STDERR: ' hello world' }
|
|
111
|
+
|
|
112
|
+
expected(actual, desired)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
it 'print() aborts on an unknown output stream' do
|
|
116
|
+
actual = runner { @formatter.print(2, 'hello world', 'BOGUS') }
|
|
117
|
+
|
|
118
|
+
desired = { aborted: true, STDOUT: '', STDERR: "Output stream 'BOGUS' is not known.\n" }
|
|
119
|
+
|
|
120
|
+
expected(actual, desired)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it 'info() writes to stderr when requested' do
|
|
124
|
+
actual = runner { @formatter.info(2, 'hello world', 'STDERR') }
|
|
125
|
+
|
|
126
|
+
desired = { aborted: false, STDOUT: '', STDERR: ' INFO: hello world' }
|
|
127
|
+
|
|
128
|
+
expected(actual, desired)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
it 'info() aborts on an unknown output stream' do
|
|
132
|
+
actual = runner { @formatter.info(2, 'hello world', 'BOGUS') }
|
|
133
|
+
|
|
134
|
+
desired = { aborted: true, STDOUT: '', STDERR: "Output stream 'BOGUS' is not known.\n" }
|
|
135
|
+
|
|
136
|
+
expected(actual, desired)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
it 'warn() writes to stderr with the warning prefix' do
|
|
140
|
+
actual = runner { @formatter.warn('hello world') }
|
|
141
|
+
|
|
142
|
+
desired = { aborted: false, STDOUT: '', STDERR: 'WARNING: hello world' }
|
|
143
|
+
|
|
144
|
+
expected(actual, desired)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
it 'error() writes to stderr with the error prefix' do
|
|
148
|
+
actual = runner { @formatter.error('hello world') }
|
|
149
|
+
|
|
150
|
+
desired = { aborted: false, STDOUT: '', STDERR: 'ERROR: hello world' }
|
|
151
|
+
|
|
152
|
+
expected(actual, desired)
|
|
153
|
+
end
|
|
62
154
|
end
|
|
63
155
|
end
|
|
@@ -1,52 +1,35 @@
|
|
|
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
|
-
@mockargs << '--trace' # extra info for debugging
|
|
21
|
-
|
|
22
|
-
@console = Moose::Inventory::Cli::Formatter
|
|
23
|
-
|
|
24
|
-
@config = Moose::Inventory::Config
|
|
25
|
-
@config.init(@mockargs)
|
|
26
|
-
|
|
27
|
-
@db = Moose::Inventory::DB
|
|
28
|
-
@db.init if @db.db.nil?
|
|
29
|
-
|
|
30
|
-
@host = Moose::Inventory::Cli::Host
|
|
31
|
-
@group = Moose::Inventory::Cli::Group
|
|
32
|
-
@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
|
+
extra_args: ['--trace']
|
|
15
|
+
)
|
|
33
16
|
end
|
|
34
17
|
|
|
35
18
|
before(:each) do
|
|
36
|
-
|
|
19
|
+
reset_cli_harness
|
|
37
20
|
end
|
|
38
21
|
|
|
39
22
|
# ============================
|
|
40
23
|
describe 'add' do
|
|
41
24
|
# --------------------
|
|
42
25
|
it 'Group.add() method should be responsive' do
|
|
43
|
-
result = @group.
|
|
26
|
+
result = @group.method_defined?(:add, false)
|
|
44
27
|
expect(result).to eq(true)
|
|
45
28
|
end
|
|
46
29
|
|
|
47
30
|
# --------------------
|
|
48
31
|
it '<no arguments> ... should bail with an error' do
|
|
49
|
-
actual = runner { @app.start(%w
|
|
32
|
+
actual = runner { @app.start(%w[group add]) }
|
|
50
33
|
|
|
51
34
|
desired = { aborted: true }
|
|
52
35
|
desired[:STDERR] = "ERROR: Wrong number of arguments, 0 for 1 or more.\n"
|
|
@@ -55,7 +38,7 @@ RSpec.describe Moose::Inventory::Cli::Group do
|
|
|
55
38
|
|
|
56
39
|
# --------------------
|
|
57
40
|
it 'ungrouped ... should abort with an error' do
|
|
58
|
-
actual = runner { @app.start(%w
|
|
41
|
+
actual = runner { @app.start(%w[group add ungrouped]) }
|
|
59
42
|
|
|
60
43
|
# Check output
|
|
61
44
|
desired = { aborted: true }
|
|
@@ -67,17 +50,17 @@ RSpec.describe Moose::Inventory::Cli::Group do
|
|
|
67
50
|
# --------------------
|
|
68
51
|
it 'GROUP ... should add a group to the db' do
|
|
69
52
|
name = 'test'
|
|
70
|
-
actual = runner { @app.start(%W
|
|
53
|
+
actual = runner { @app.start(%W[group add #{name}]) }
|
|
71
54
|
|
|
72
55
|
# @console.out(actual)
|
|
73
56
|
|
|
74
57
|
# Check output
|
|
75
58
|
desired = {}
|
|
76
59
|
desired[:STDOUT] =
|
|
77
|
-
"Add group '#{name}':\n"\
|
|
78
|
-
"
|
|
79
|
-
"
|
|
80
|
-
"
|
|
60
|
+
"Add group '#{name}':\n " \
|
|
61
|
+
"- create group...\n " \
|
|
62
|
+
"- OK\n " \
|
|
63
|
+
"- all OK\n" \
|
|
81
64
|
"Succeeded\n"
|
|
82
65
|
|
|
83
66
|
expected(actual, desired)
|
|
@@ -87,23 +70,68 @@ RSpec.describe Moose::Inventory::Cli::Group do
|
|
|
87
70
|
expect(group[:name]).to eq(name)
|
|
88
71
|
end
|
|
89
72
|
|
|
73
|
+
# --------------------
|
|
74
|
+
it 'GROUP --dry-run should show planned group creation without writing to the db' do
|
|
75
|
+
name = 'dry-run-group'
|
|
76
|
+
|
|
77
|
+
actual = runner { @app.start(%W[group add #{name} --dry-run]) }
|
|
78
|
+
|
|
79
|
+
desired = {}
|
|
80
|
+
desired[:STDOUT] =
|
|
81
|
+
"Add group '#{name}':\n " \
|
|
82
|
+
"- create group...\n " \
|
|
83
|
+
"- OK\n " \
|
|
84
|
+
"- all OK\n" \
|
|
85
|
+
"Dry run complete. No changes applied.\n" \
|
|
86
|
+
"Succeeded\n"
|
|
87
|
+
|
|
88
|
+
expected(actual, desired)
|
|
89
|
+
expect(@db.models[:group].find(name: name)).to be_nil
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# --------------------
|
|
93
|
+
it 'GROUP --hosts HOST --dry-run should not create the group or missing host' do
|
|
94
|
+
group_name = 'dry-run-group'
|
|
95
|
+
host_name = 'dry-run-host'
|
|
96
|
+
|
|
97
|
+
actual = runner { @app.start(%W[group add #{group_name} --hosts #{host_name} --dry-run]) }
|
|
98
|
+
|
|
99
|
+
desired = {}
|
|
100
|
+
desired[:STDOUT] =
|
|
101
|
+
"Add group '#{group_name}':\n " \
|
|
102
|
+
"- create group...\n " \
|
|
103
|
+
"- OK\n " \
|
|
104
|
+
"- add association {group:#{group_name} <-> host:#{host_name}}...\n " \
|
|
105
|
+
"- host doesn't exist, creating now...\n " \
|
|
106
|
+
"- OK\n " \
|
|
107
|
+
"- OK\n " \
|
|
108
|
+
"- all OK\n" \
|
|
109
|
+
"Dry run complete. No changes applied.\n" \
|
|
110
|
+
"Succeeded, with warnings.\n"
|
|
111
|
+
desired[:STDERR] =
|
|
112
|
+
"WARNING: Host '#{host_name}' doesn't exist, but will be created.\n"
|
|
113
|
+
|
|
114
|
+
expected(actual, desired)
|
|
115
|
+
expect(@db.models[:group].find(name: group_name)).to be_nil
|
|
116
|
+
expect(@db.models[:host].find(name: host_name)).to be_nil
|
|
117
|
+
end
|
|
90
118
|
# --------------------
|
|
91
119
|
it 'GROUP ... should skip GROUP creation if it already exists' do
|
|
92
120
|
name = 'test-group'
|
|
93
121
|
@db.models[:group].create(name: name)
|
|
94
122
|
|
|
95
|
-
actual = runner { @app.start(%W
|
|
123
|
+
actual = runner { @app.start(%W[group add #{name}]) }
|
|
96
124
|
|
|
97
125
|
# @console.out(actual)
|
|
98
126
|
|
|
99
127
|
# Check output
|
|
100
128
|
desired = {}
|
|
101
129
|
desired[:STDOUT] =
|
|
102
|
-
"Add group '#{name}':\n"\
|
|
103
|
-
"
|
|
104
|
-
"
|
|
105
|
-
"
|
|
106
|
-
"
|
|
130
|
+
"Add group '#{name}':\n " \
|
|
131
|
+
"- create group...\n " \
|
|
132
|
+
"- already exists, skipping.\n " \
|
|
133
|
+
"- OK\n " \
|
|
134
|
+
"- all OK\n" \
|
|
107
135
|
"Succeeded, with warnings.\n"
|
|
108
136
|
desired[:STDERR] =
|
|
109
137
|
"WARNING: Group '#{name}' already exists, skipping creation.\n"
|
|
@@ -115,9 +143,9 @@ RSpec.describe Moose::Inventory::Cli::Group do
|
|
|
115
143
|
|
|
116
144
|
# --------------------
|
|
117
145
|
it 'GROUP1 GROUP2 GROUP3 ... should add multiple groups' do
|
|
118
|
-
names = %w
|
|
146
|
+
names = %w[test1 test2 test3]
|
|
119
147
|
|
|
120
|
-
actual = runner { @app.start(%w
|
|
148
|
+
actual = runner { @app.start(%w[group add] + names) }
|
|
121
149
|
|
|
122
150
|
# @console.out(actual)
|
|
123
151
|
|
|
@@ -125,12 +153,12 @@ RSpec.describe Moose::Inventory::Cli::Group do
|
|
|
125
153
|
desired = { STDOUT: '' }
|
|
126
154
|
names.each do |name|
|
|
127
155
|
desired[:STDOUT] = desired[:STDOUT] +
|
|
128
|
-
"Add group '#{name}':\n"\
|
|
129
|
-
"
|
|
130
|
-
"
|
|
131
|
-
"
|
|
156
|
+
"Add group '#{name}':\n " \
|
|
157
|
+
"- create group...\n " \
|
|
158
|
+
"- OK\n " \
|
|
159
|
+
"- all OK\n" \
|
|
132
160
|
end
|
|
133
|
-
desired[:STDOUT] = desired[:STDOUT]
|
|
161
|
+
desired[:STDOUT] = "#{desired[:STDOUT]}Succeeded\n"
|
|
134
162
|
|
|
135
163
|
expected(actual, desired)
|
|
136
164
|
|
|
@@ -142,15 +170,14 @@ RSpec.describe Moose::Inventory::Cli::Group do
|
|
|
142
170
|
end
|
|
143
171
|
|
|
144
172
|
# --------------------
|
|
145
|
-
it 'GROUP1 --hosts HOST1 ... should add the '\
|
|
146
|
-
|
|
147
|
-
|
|
173
|
+
it 'GROUP1 --hosts HOST1 ... should add the ' \
|
|
174
|
+
'group and associate it with existing hosts' do
|
|
148
175
|
host_name = 'test-host'
|
|
149
176
|
@db.models[:host].create(name: host_name)
|
|
150
177
|
|
|
151
178
|
group_name = 'test-group'
|
|
152
179
|
actual = runner do
|
|
153
|
-
@app.start(%W
|
|
180
|
+
@app.start(%W[group add #{group_name} --hosts #{host_name}])
|
|
154
181
|
end
|
|
155
182
|
|
|
156
183
|
# @console.out(actual)
|
|
@@ -158,12 +185,12 @@ RSpec.describe Moose::Inventory::Cli::Group do
|
|
|
158
185
|
# Check output
|
|
159
186
|
desired = {}
|
|
160
187
|
desired[:STDOUT] =
|
|
161
|
-
"Add group '#{group_name}':\n"\
|
|
162
|
-
"
|
|
163
|
-
"
|
|
164
|
-
"
|
|
165
|
-
"
|
|
166
|
-
"
|
|
188
|
+
"Add group '#{group_name}':\n " \
|
|
189
|
+
"- create group...\n " \
|
|
190
|
+
"- OK\n " \
|
|
191
|
+
"- add association {group:#{group_name} <-> host:#{host_name}}...\n " \
|
|
192
|
+
"- OK\n " \
|
|
193
|
+
"- all OK\n" \
|
|
167
194
|
"Succeeded\n"
|
|
168
195
|
|
|
169
196
|
expected(actual, desired)
|
|
@@ -184,7 +211,7 @@ RSpec.describe Moose::Inventory::Cli::Group do
|
|
|
184
211
|
|
|
185
212
|
group_name = 'test-group'
|
|
186
213
|
actual = runner do
|
|
187
|
-
@app.start(%W
|
|
214
|
+
@app.start(%W[group add #{group_name} --hosts #{host_name}])
|
|
188
215
|
end
|
|
189
216
|
|
|
190
217
|
# @console.out(actual)
|
|
@@ -192,14 +219,14 @@ RSpec.describe Moose::Inventory::Cli::Group do
|
|
|
192
219
|
# Check output
|
|
193
220
|
desired = {}
|
|
194
221
|
desired[:STDOUT] =
|
|
195
|
-
"Add group '#{group_name}':\n"\
|
|
196
|
-
"
|
|
197
|
-
"
|
|
198
|
-
"
|
|
199
|
-
"
|
|
200
|
-
"
|
|
201
|
-
"
|
|
202
|
-
"
|
|
222
|
+
"Add group '#{group_name}':\n " \
|
|
223
|
+
"- create group...\n " \
|
|
224
|
+
"- OK\n " \
|
|
225
|
+
"- add association {group:#{group_name} <-> host:#{host_name}}...\n " \
|
|
226
|
+
"- host doesn't exist, creating now...\n " \
|
|
227
|
+
"- OK\n " \
|
|
228
|
+
"- OK\n " \
|
|
229
|
+
"- all OK\n" \
|
|
203
230
|
"Succeeded, with warnings.\n"
|
|
204
231
|
desired[:STDERR] =
|
|
205
232
|
"WARNING: Host '#{host_name}' doesn't exist, but will be created.\n"
|
|
@@ -220,11 +247,11 @@ RSpec.describe Moose::Inventory::Cli::Group do
|
|
|
220
247
|
group_name = 'test-group'
|
|
221
248
|
|
|
222
249
|
# Create group and association
|
|
223
|
-
runner { @app.start(%W
|
|
250
|
+
runner { @app.start(%W[group add #{group_name} --hosts #{host_name}]) }
|
|
224
251
|
|
|
225
252
|
# Do it again, to prove that we skip
|
|
226
253
|
actual = runner do
|
|
227
|
-
@app.start(%W
|
|
254
|
+
@app.start(%W[group add #{group_name} --hosts #{host_name}])
|
|
228
255
|
end
|
|
229
256
|
|
|
230
257
|
# @console.out(actual, 'y')
|
|
@@ -232,17 +259,17 @@ RSpec.describe Moose::Inventory::Cli::Group do
|
|
|
232
259
|
# Check output
|
|
233
260
|
desired = {}
|
|
234
261
|
desired[:STDOUT] =
|
|
235
|
-
"Add group '#{group_name}':\n"\
|
|
236
|
-
"
|
|
237
|
-
"
|
|
238
|
-
"
|
|
239
|
-
"
|
|
240
|
-
"
|
|
241
|
-
"
|
|
242
|
-
"
|
|
262
|
+
"Add group '#{group_name}':\n " \
|
|
263
|
+
"- create group...\n " \
|
|
264
|
+
"- already exists, skipping.\n " \
|
|
265
|
+
"- OK\n " \
|
|
266
|
+
"- add association {group:#{group_name} <-> host:#{host_name}}...\n " \
|
|
267
|
+
"- already exists, skipping.\n " \
|
|
268
|
+
"- OK\n " \
|
|
269
|
+
"- all OK\n" \
|
|
243
270
|
"Succeeded, with warnings.\n"
|
|
244
271
|
desired[:STDERR] =
|
|
245
|
-
"WARNING: Group '#{group_name}' already exists, skipping creation.\n"\
|
|
272
|
+
"WARNING: Group '#{group_name}' already exists, skipping creation.\n" \
|
|
246
273
|
"WARNING: Association {group:#{group_name} <-> host:#{host_name}} already exists, skipping creation.\n"
|
|
247
274
|
|
|
248
275
|
expected(actual, desired)
|
|
@@ -256,26 +283,25 @@ RSpec.describe Moose::Inventory::Cli::Group do
|
|
|
256
283
|
end
|
|
257
284
|
|
|
258
285
|
# --------------------
|
|
259
|
-
it 'GROUP --hosts HOST1,HOST2 ... should add the group and '\
|
|
260
|
-
|
|
261
|
-
|
|
286
|
+
it 'GROUP --hosts HOST1,HOST2 ... should add the group and ' \
|
|
287
|
+
'associate it with multiple hosts' do
|
|
262
288
|
# The group should be added
|
|
263
289
|
# Each host should be associated with the group
|
|
264
290
|
# Each host should be removed from the automatic 'ungrouped' group
|
|
265
291
|
|
|
266
292
|
group_name = 'test-group'
|
|
267
|
-
host_names = %w
|
|
293
|
+
host_names = %w[host1 host2 host3]
|
|
268
294
|
|
|
269
295
|
# Add just the first host. This ensure that we cover paths for both
|
|
270
296
|
# and existing host (with an 'ungrouped' association) and for none
|
|
271
297
|
# existing groups.
|
|
272
|
-
|
|
298
|
+
runner { @app.start(%W[host add #{host_names[0]}]) }
|
|
273
299
|
|
|
274
300
|
# @console.out(tmp, 'y')
|
|
275
301
|
|
|
276
302
|
# Now run the actual group addition
|
|
277
303
|
actual = runner do
|
|
278
|
-
@app.start(%W
|
|
304
|
+
@app.start(%W[group add #{group_name} --hosts #{host_names.join(',')}])
|
|
279
305
|
end
|
|
280
306
|
|
|
281
307
|
# @console.out(actual,'y')
|
|
@@ -283,25 +309,25 @@ RSpec.describe Moose::Inventory::Cli::Group do
|
|
|
283
309
|
# Check output
|
|
284
310
|
desired = { aborted: false, STDERR: '', STDOUT: '' }
|
|
285
311
|
desired[:STDOUT] =
|
|
286
|
-
"Add group '#{group_name}':\n"\
|
|
287
|
-
"
|
|
288
|
-
"
|
|
289
|
-
"
|
|
290
|
-
"
|
|
291
|
-
"
|
|
292
|
-
"
|
|
312
|
+
"Add group '#{group_name}':\n " \
|
|
313
|
+
"- create group...\n " \
|
|
314
|
+
"- OK\n " \
|
|
315
|
+
"- add association {group:#{group_name} <-> host:#{host_names[0]}}...\n " \
|
|
316
|
+
"- OK\n " \
|
|
317
|
+
"- remove automatic association {group:ungrouped <-> host:#{host_names[0]}}...\n " \
|
|
318
|
+
"- OK\n"
|
|
293
319
|
|
|
294
320
|
host_names.slice(1, host_names.length - 1).each do |host_name|
|
|
295
321
|
desired[:STDOUT] = desired[:STDOUT] +
|
|
296
|
-
" - add association {group:#{group_name} <-> host:#{host_name}}...\n"\
|
|
297
|
-
"
|
|
298
|
-
"
|
|
299
|
-
"
|
|
322
|
+
" - add association {group:#{group_name} <-> host:#{host_name}}...\n " \
|
|
323
|
+
"- host doesn't exist, creating now...\n " \
|
|
324
|
+
"- OK\n " \
|
|
325
|
+
"- OK\n"
|
|
300
326
|
desired[:STDERR] = desired[:STDERR] +
|
|
301
327
|
"WARNING: Host '#{host_name}' doesn't exist, but will be created.\n"
|
|
302
328
|
end
|
|
303
329
|
desired[:STDOUT] = desired[:STDOUT] +
|
|
304
|
-
" - all OK\n"\
|
|
330
|
+
" - all OK\n" \
|
|
305
331
|
"Succeeded, with warnings.\n"
|
|
306
332
|
|
|
307
333
|
expected(actual, desired)
|
|
@@ -318,13 +344,13 @@ RSpec.describe Moose::Inventory::Cli::Group do
|
|
|
318
344
|
end
|
|
319
345
|
|
|
320
346
|
# --------------------
|
|
321
|
-
it 'HOST --groups GROUP1,ungrouped ... should bail '\
|
|
322
|
-
|
|
347
|
+
it 'HOST --groups GROUP1,ungrouped ... should bail ' \
|
|
348
|
+
'with an error' do
|
|
323
349
|
name = 'testhost'
|
|
324
|
-
group_names = %w
|
|
350
|
+
group_names = %w[group1 ungrouped]
|
|
325
351
|
|
|
326
352
|
actual = runner do
|
|
327
|
-
@app.start(%W
|
|
353
|
+
@app.start(%W[host add #{name} --groups #{group_names.join(',')}])
|
|
328
354
|
end
|
|
329
355
|
|
|
330
356
|
# Check output
|
|
@@ -336,15 +362,14 @@ RSpec.describe Moose::Inventory::Cli::Group do
|
|
|
336
362
|
end
|
|
337
363
|
|
|
338
364
|
# --------------------
|
|
339
|
-
it 'HOST1 HOST2 --groups GROUP1,GROUP2 ... should add multiple '\
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
host_names = %w(host1 host2 host3)
|
|
365
|
+
it 'HOST1 HOST2 --groups GROUP1,GROUP2 ... should add multiple ' \
|
|
366
|
+
'groups, associating each with multiple hosts' do
|
|
367
|
+
host_names = %w[host1 host2 host3]
|
|
343
368
|
# Note, relies on auto-generation of hosts
|
|
344
369
|
|
|
345
|
-
group_names = %w
|
|
370
|
+
group_names = %w[group1 group2 group3]
|
|
346
371
|
actual = runner do
|
|
347
|
-
@app.start(%w
|
|
372
|
+
@app.start(%w[group add] + group_names + %W[--hosts #{host_names.join(',')}])
|
|
348
373
|
end
|
|
349
374
|
|
|
350
375
|
# @console.out(actual,'y')
|
|
@@ -354,27 +379,25 @@ RSpec.describe Moose::Inventory::Cli::Group do
|
|
|
354
379
|
first_pass = true
|
|
355
380
|
group_names.each do |group|
|
|
356
381
|
desired[:STDOUT] = desired[:STDOUT] +
|
|
357
|
-
"Add group '#{group}':\n"\
|
|
358
|
-
"
|
|
359
|
-
"
|
|
382
|
+
"Add group '#{group}':\n " \
|
|
383
|
+
"- create group...\n " \
|
|
384
|
+
"- OK\n"
|
|
360
385
|
|
|
361
386
|
host_names.each do |host|
|
|
362
387
|
desired[:STDOUT] = desired[:STDOUT] +
|
|
363
388
|
" - add association {group:#{group} <-> host:#{host}}...\n"
|
|
364
389
|
if first_pass
|
|
365
390
|
desired[:STDOUT] = desired[:STDOUT] +
|
|
366
|
-
" - host doesn't exist, creating now...\n"\
|
|
367
|
-
"
|
|
391
|
+
" - host doesn't exist, creating now...\n " \
|
|
392
|
+
"- OK\n"
|
|
368
393
|
end
|
|
369
|
-
desired[:STDOUT] = desired[:STDOUT]
|
|
370
|
-
" - OK\n"
|
|
394
|
+
desired[:STDOUT] = "#{desired[:STDOUT]} - OK\n"
|
|
371
395
|
end
|
|
372
|
-
desired[:STDOUT] = desired[:STDOUT]
|
|
373
|
-
" - all OK\n"
|
|
396
|
+
desired[:STDOUT] = "#{desired[:STDOUT]} - all OK\n"
|
|
374
397
|
first_pass = false
|
|
375
398
|
end
|
|
376
399
|
|
|
377
|
-
desired[:STDOUT] = desired[:STDOUT]
|
|
400
|
+
desired[:STDOUT] = "#{desired[:STDOUT]}Succeeded, with warnings.\n"
|
|
378
401
|
host_names.each do |host|
|
|
379
402
|
desired[:STDERR] = desired[:STDERR] +
|
|
380
403
|
"WARNING: Host '#{host}' doesn't exist, but will be created.\n"
|
|
@@ -395,3 +418,4 @@ RSpec.describe Moose::Inventory::Cli::Group do
|
|
|
395
418
|
end
|
|
396
419
|
end
|
|
397
420
|
end
|
|
421
|
+
# rubocop:enable Metrics/BlockLength
|