moose-inventory 1.0.8 → 2.0
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 +5 -5
- data/.github/workflows/ci.yml +49 -0
- data/.github/workflows/release.yml +58 -0
- data/.gitignore +1 -1
- data/.gitleaks.toml +9 -0
- data/.rubocop.yml +19 -784
- data/BACKLOG.md +290 -0
- data/Gemfile.lock +95 -0
- data/README.md +38 -9
- data/Rakefile +1 -1
- data/bin/moose-inventory +1 -1
- data/docs/release/publishing.md +109 -0
- data/docs/release/release-readiness.md +55 -0
- data/docs/security-audit-2026-05-21.md +71 -0
- data/docs/security-audit-2026-05-26-rerun.md +75 -0
- data/docs/security-audit-2026-05-26.md +63 -0
- data/lib/moose_inventory/cli/formatter.rb +16 -17
- data/lib/moose_inventory/cli/group.rb +4 -1
- data/lib/moose_inventory/cli/group_add.rb +89 -75
- data/lib/moose_inventory/cli/group_addchild.rb +84 -71
- data/lib/moose_inventory/cli/group_addhost.rb +78 -69
- data/lib/moose_inventory/cli/group_addvar.rb +37 -37
- data/lib/moose_inventory/cli/group_get.rb +23 -26
- data/lib/moose_inventory/cli/group_list.rb +12 -15
- data/lib/moose_inventory/cli/group_listvars.rb +12 -14
- data/lib/moose_inventory/cli/group_rm.rb +104 -76
- data/lib/moose_inventory/cli/group_rmchild.rb +99 -54
- data/lib/moose_inventory/cli/group_rmhost.rb +64 -60
- data/lib/moose_inventory/cli/group_rmvar.rb +5 -5
- data/lib/moose_inventory/cli/helpers.rb +76 -0
- data/lib/moose_inventory/cli/host.rb +4 -1
- data/lib/moose_inventory/cli/host_add.rb +51 -66
- data/lib/moose_inventory/cli/host_addgroup.rb +77 -68
- data/lib/moose_inventory/cli/host_addvar.rb +6 -6
- data/lib/moose_inventory/cli/host_get.rb +15 -18
- data/lib/moose_inventory/cli/host_list.rb +3 -3
- data/lib/moose_inventory/cli/host_listvars.rb +21 -23
- data/lib/moose_inventory/cli/host_rm.rb +9 -9
- data/lib/moose_inventory/cli/host_rmgroup.rb +63 -60
- data/lib/moose_inventory/cli/host_rmvar.rb +3 -3
- data/lib/moose_inventory/config/config.rb +43 -40
- data/lib/moose_inventory/db/db.rb +92 -52
- data/lib/moose_inventory/db/models.rb +11 -12
- data/lib/moose_inventory/inventory_context.rb +50 -0
- data/lib/moose_inventory/operations/add_associations.rb +127 -0
- data/lib/moose_inventory/operations/add_groups.rb +115 -0
- data/lib/moose_inventory/operations/add_hosts.rb +110 -0
- data/lib/moose_inventory/operations/group_child_relations.rb +118 -0
- data/lib/moose_inventory/operations/group_cleanup.rb +55 -0
- data/lib/moose_inventory/operations/remove_associations.rb +101 -0
- data/lib/moose_inventory/operations/remove_groups.rb +79 -0
- data/lib/moose_inventory/version.rb +1 -1
- data/moose-inventory.gemspec +38 -20
- data/scripts/check.sh +10 -0
- data/scripts/ci/check_permissions.sh +35 -0
- data/scripts/ci/check_rubocop.sh +28 -0
- data/scripts/ci/check_secrets.sh +26 -0
- data/scripts/ci/check_security.sh +68 -0
- data/scripts/ci/install_security_tools.sh +47 -0
- data/scripts/ci/package_sanity.sh +46 -0
- data/scripts/files.rb +1 -4
- data/scripts/install_dependencies.sh +19 -0
- data/scripts/reports.sh +2 -2
- data/spec/lib/moose_inventory/cli/cli_spec.rb +13 -14
- data/spec/lib/moose_inventory/cli/group_add_spec.rb +118 -119
- data/spec/lib/moose_inventory/cli/group_addchild_spec.rb +49 -51
- data/spec/lib/moose_inventory/cli/group_addhost_spec.rb +80 -83
- data/spec/lib/moose_inventory/cli/group_addvar_spec.rb +91 -91
- data/spec/lib/moose_inventory/cli/group_get_spec.rb +22 -23
- data/spec/lib/moose_inventory/cli/group_list_spec.rb +19 -20
- data/spec/lib/moose_inventory/cli/group_listvar_spec.rb +35 -36
- data/spec/lib/moose_inventory/cli/group_rm_spec.rb +115 -78
- data/spec/lib/moose_inventory/cli/group_rmchild_spec.rb +86 -45
- data/spec/lib/moose_inventory/cli/group_rmhost_spec.rb +43 -46
- data/spec/lib/moose_inventory/cli/group_rmvar_spec.rb +131 -131
- data/spec/lib/moose_inventory/cli/group_spec.rb +9 -9
- data/spec/lib/moose_inventory/cli/host_add_spec.rb +103 -43
- data/spec/lib/moose_inventory/cli/host_addgroup_spec.rb +78 -80
- data/spec/lib/moose_inventory/cli/host_addvar_spec.rb +122 -122
- data/spec/lib/moose_inventory/cli/host_get_spec.rb +16 -16
- data/spec/lib/moose_inventory/cli/host_list_spec.rb +8 -8
- data/spec/lib/moose_inventory/cli/host_listvar_spec.rb +50 -52
- data/spec/lib/moose_inventory/cli/host_rm_spec.rb +12 -12
- data/spec/lib/moose_inventory/cli/host_rmgroup_spec.rb +48 -51
- data/spec/lib/moose_inventory/cli/host_rmvar_spec.rb +136 -136
- data/spec/lib/moose_inventory/config/config_spec.rb +16 -3
- data/spec/lib/moose_inventory/db/db_spec.rb +386 -2
- data/spec/lib/moose_inventory/db/models_spec.rb +10 -11
- data/spec/lib/moose_inventory/operations/add_associations_spec.rb +77 -0
- data/spec/lib/moose_inventory/operations/add_groups_spec.rb +65 -0
- data/spec/lib/moose_inventory/operations/add_hosts_spec.rb +69 -0
- data/spec/lib/moose_inventory/operations/group_child_relations_spec.rb +76 -0
- data/spec/lib/moose_inventory/operations/remove_associations_spec.rb +78 -0
- data/spec/lib/moose_inventory/operations/remove_groups_spec.rb +57 -0
- data/spec/shared/shared_config_setup.rb +2 -2
- data/spec/spec_helper.rb +7 -8
- metadata +157 -105
- data/.coveralls.yml +0 -0
- data/Guardfile +0 -38
- data/config/dotfiles/coveralls.yml +0 -0
- data/config/dotfiles/gitignore +0 -20
- data/config/dotfiles/rubocop.yml +0 -793
- data/scripts/guard_quality.sh +0 -3
- data/scripts/guard_test.sh +0 -2
|
@@ -1,6 +1,26 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
|
+
require 'fileutils'
|
|
3
|
+
require 'tmpdir'
|
|
2
4
|
|
|
3
5
|
RSpec.describe 'Moose::Inventory::DB' do
|
|
6
|
+
def with_db_config(db_config)
|
|
7
|
+
saved_db = @db.instance_variable_get(:@db)
|
|
8
|
+
saved_settings = @config._settings.dup
|
|
9
|
+
|
|
10
|
+
begin
|
|
11
|
+
@db.instance_variable_set(:@db, nil)
|
|
12
|
+
@config._settings.clear
|
|
13
|
+
@config._settings[:config] = { db: db_config }
|
|
14
|
+
yield
|
|
15
|
+
ensure
|
|
16
|
+
current_db = @db.instance_variable_get(:@db)
|
|
17
|
+
current_db.disconnect if current_db.respond_to?(:disconnect)
|
|
18
|
+
@db.instance_variable_set(:@db, saved_db)
|
|
19
|
+
@config._settings.clear
|
|
20
|
+
@config._settings.merge!(saved_settings)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
4
24
|
#=============================
|
|
5
25
|
# Initialization
|
|
6
26
|
#
|
|
@@ -10,7 +30,7 @@ RSpec.describe 'Moose::Inventory::DB' do
|
|
|
10
30
|
@mockarg_parts = {
|
|
11
31
|
config: File.join(spec_root, 'config/config.yml'),
|
|
12
32
|
format: 'yaml',
|
|
13
|
-
env: 'test'
|
|
33
|
+
env: 'test',
|
|
14
34
|
}
|
|
15
35
|
|
|
16
36
|
@mockargs = []
|
|
@@ -22,7 +42,7 @@ RSpec.describe 'Moose::Inventory::DB' do
|
|
|
22
42
|
@config = Moose::Inventory::Config
|
|
23
43
|
@config.init(@mockargs)
|
|
24
44
|
|
|
25
|
-
@db
|
|
45
|
+
@db = Moose::Inventory::DB
|
|
26
46
|
end
|
|
27
47
|
|
|
28
48
|
#=============================
|
|
@@ -47,6 +67,322 @@ RSpec.describe 'Moose::Inventory::DB' do
|
|
|
47
67
|
|
|
48
68
|
expect(failed).to eq(false)
|
|
49
69
|
end
|
|
70
|
+
|
|
71
|
+
it 'raises a Moose DB exception for unsupported adapters' do
|
|
72
|
+
saved_db = @db.instance_variable_get(:@db)
|
|
73
|
+
saved_models = @db.instance_variable_get(:@models)
|
|
74
|
+
saved_exceptions = @db.instance_variable_get(:@exceptions)
|
|
75
|
+
saved_settings = @config._settings.dup
|
|
76
|
+
|
|
77
|
+
begin
|
|
78
|
+
@db.instance_variable_set(:@db, nil)
|
|
79
|
+
@db.instance_variable_set(:@models, nil)
|
|
80
|
+
@db.instance_variable_set(:@exceptions, nil)
|
|
81
|
+
@config._settings.clear
|
|
82
|
+
@config._settings[:config] = { db: { adapter: 'unsupported' } }
|
|
83
|
+
|
|
84
|
+
expect { @db.init }.to raise_error(
|
|
85
|
+
Moose::Inventory::DB::MooseDBException,
|
|
86
|
+
/database adapter unsupported is not yet supported/
|
|
87
|
+
)
|
|
88
|
+
expect(@db.exceptions[:moose]).to eq(Moose::Inventory::DB::MooseDBException)
|
|
89
|
+
ensure
|
|
90
|
+
@db.instance_variable_set(:@db, saved_db)
|
|
91
|
+
@db.instance_variable_set(:@models, saved_models)
|
|
92
|
+
@db.instance_variable_set(:@exceptions, saved_exceptions)
|
|
93
|
+
@config._settings.clear
|
|
94
|
+
@config._settings.merge!(saved_settings)
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
describe '.init_exceptions()' do
|
|
100
|
+
it 'is responsive' do
|
|
101
|
+
expect(@db.respond_to?(:init_exceptions)).to eq(true)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
describe '.connect()' do
|
|
106
|
+
it 'dispatches the documented sqlite3 adapter to the sqlite initializer' do
|
|
107
|
+
with_db_config(adapter: 'sqlite3') do
|
|
108
|
+
expect(@db).to receive(:init_sqlite3) do
|
|
109
|
+
@db.instance_variable_set(:@db, :sqlite_connection)
|
|
110
|
+
end
|
|
111
|
+
@db.connect
|
|
112
|
+
expect(@db.db).to eq(:sqlite_connection)
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
it 'dispatches the documented mysql adapter to the mysql initializer' do
|
|
117
|
+
with_db_config(adapter: 'mysql') do
|
|
118
|
+
expect(@db).to receive(:init_mysql) do
|
|
119
|
+
@db.instance_variable_set(:@db, :mysql_connection)
|
|
120
|
+
end
|
|
121
|
+
@db.connect
|
|
122
|
+
expect(@db.db).to eq(:mysql_connection)
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
it 'dispatches the documented postgresql adapter to the postgresql initializer' do
|
|
127
|
+
with_db_config(adapter: 'postgresql') do
|
|
128
|
+
expect(@db).to receive(:init_postgresql) do
|
|
129
|
+
@db.instance_variable_set(:@db, :postgresql_connection)
|
|
130
|
+
end
|
|
131
|
+
@db.connect
|
|
132
|
+
expect(@db.db).to eq(:postgresql_connection)
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
describe '.init_sqlite3()' do
|
|
138
|
+
it 'raises a Moose DB exception when the configured database file is missing' do
|
|
139
|
+
with_db_config(adapter: 'sqlite3') do
|
|
140
|
+
expect { @db.init_sqlite3 }.to raise_error(
|
|
141
|
+
Moose::Inventory::DB::MooseDBException,
|
|
142
|
+
/Expected key file missing in sqlite3 configuration/
|
|
143
|
+
)
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
it 'creates nested parent directories for configured database files' do
|
|
148
|
+
saved_db = @db.instance_variable_get(:@db)
|
|
149
|
+
saved_settings = @config._settings.dup
|
|
150
|
+
tmpdir = Dir.mktmpdir('moose-inventory-sqlite')
|
|
151
|
+
nested_dbfile = File.join(tmpdir, 'one', 'two', 'inventory.db')
|
|
152
|
+
|
|
153
|
+
begin
|
|
154
|
+
@db.instance_variable_set(:@db, nil)
|
|
155
|
+
@config._settings.clear
|
|
156
|
+
@config._settings[:config] = {
|
|
157
|
+
db: {
|
|
158
|
+
adapter: 'sqlite3',
|
|
159
|
+
file: nested_dbfile,
|
|
160
|
+
},
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
@db.init_sqlite3
|
|
164
|
+
|
|
165
|
+
expect(File.directory?(File.dirname(nested_dbfile))).to eq(true)
|
|
166
|
+
expect(File.file?(nested_dbfile)).to eq(true)
|
|
167
|
+
ensure
|
|
168
|
+
current_db = @db.instance_variable_get(:@db)
|
|
169
|
+
current_db.disconnect if current_db.respond_to?(:disconnect)
|
|
170
|
+
@db.instance_variable_set(:@db, saved_db)
|
|
171
|
+
@config._settings.clear
|
|
172
|
+
@config._settings.merge!(saved_settings)
|
|
173
|
+
FileUtils.remove_entry(tmpdir) if tmpdir && Dir.exist?(tmpdir)
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
describe '.init_mysql()' do
|
|
179
|
+
it 'raises a Moose DB exception when a required connection key is missing' do
|
|
180
|
+
with_db_config(
|
|
181
|
+
adapter: 'mysql',
|
|
182
|
+
database: 'moose_inventory_test',
|
|
183
|
+
user: 'moose',
|
|
184
|
+
password: 'secret'
|
|
185
|
+
) do
|
|
186
|
+
expect { @db.init_mysql }.to raise_error(
|
|
187
|
+
Moose::Inventory::DB::MooseDBException,
|
|
188
|
+
/Expected key host missing in mysql configuration/
|
|
189
|
+
)
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
it 'raises a Moose DB exception when password and password_env are missing' do
|
|
194
|
+
with_db_config(
|
|
195
|
+
adapter: 'mysql',
|
|
196
|
+
host: 'localhost',
|
|
197
|
+
database: 'moose_inventory_test',
|
|
198
|
+
user: 'moose'
|
|
199
|
+
) do
|
|
200
|
+
expect { @db.init_mysql }.to raise_error(
|
|
201
|
+
Moose::Inventory::DB::MooseDBException,
|
|
202
|
+
/Expected key password or password_env missing in mysql configuration/
|
|
203
|
+
)
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
it 'uses a mysql password from the configured environment variable' do
|
|
208
|
+
saved_db = @db.instance_variable_get(:@db)
|
|
209
|
+
saved_settings = @config._settings.dup
|
|
210
|
+
saved_password = ENV['MOOSE_INVENTORY_MYSQL_PASSWORD']
|
|
211
|
+
mysql_config = {
|
|
212
|
+
adapter: 'mysql',
|
|
213
|
+
host: 'localhost',
|
|
214
|
+
database: 'moose_inventory_test',
|
|
215
|
+
user: 'moose',
|
|
216
|
+
password_env: 'MOOSE_INVENTORY_MYSQL_PASSWORD',
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
begin
|
|
220
|
+
ENV['MOOSE_INVENTORY_MYSQL_PASSWORD'] = 'env-secret'
|
|
221
|
+
@db.instance_variable_set(:@db, nil)
|
|
222
|
+
@config._settings.clear
|
|
223
|
+
@config._settings[:config] = { db: mysql_config }
|
|
224
|
+
|
|
225
|
+
expect(Sequel).to receive(:mysql2).with(
|
|
226
|
+
user: 'moose',
|
|
227
|
+
password: 'env-secret',
|
|
228
|
+
host: 'localhost',
|
|
229
|
+
database: 'moose_inventory_test'
|
|
230
|
+
).and_return(:mysql2_connection)
|
|
231
|
+
|
|
232
|
+
@db.init_mysql
|
|
233
|
+
expect(@db.db).to eq(:mysql2_connection)
|
|
234
|
+
ensure
|
|
235
|
+
if saved_password.nil?
|
|
236
|
+
ENV.delete('MOOSE_INVENTORY_MYSQL_PASSWORD')
|
|
237
|
+
else
|
|
238
|
+
ENV['MOOSE_INVENTORY_MYSQL_PASSWORD'] = saved_password
|
|
239
|
+
end
|
|
240
|
+
@db.instance_variable_set(:@db, saved_db)
|
|
241
|
+
@config._settings.clear
|
|
242
|
+
@config._settings.merge!(saved_settings)
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
it 'uses the mysql2 Sequel adapter with configured connection settings' do
|
|
247
|
+
saved_db = @db.instance_variable_get(:@db)
|
|
248
|
+
saved_settings = @config._settings.dup
|
|
249
|
+
mysql_config = {
|
|
250
|
+
adapter: 'mysql',
|
|
251
|
+
host: 'localhost',
|
|
252
|
+
database: 'moose_inventory_test',
|
|
253
|
+
user: 'moose',
|
|
254
|
+
password: 'secret',
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
begin
|
|
258
|
+
@db.instance_variable_set(:@db, nil)
|
|
259
|
+
@config._settings.clear
|
|
260
|
+
@config._settings[:config] = { db: mysql_config }
|
|
261
|
+
|
|
262
|
+
expect(Sequel).to receive(:mysql2).with(
|
|
263
|
+
user: 'moose',
|
|
264
|
+
password: 'secret',
|
|
265
|
+
host: 'localhost',
|
|
266
|
+
database: 'moose_inventory_test'
|
|
267
|
+
).and_return(:mysql2_connection)
|
|
268
|
+
|
|
269
|
+
@db.init_mysql
|
|
270
|
+
expect(@db.db).to eq(:mysql2_connection)
|
|
271
|
+
ensure
|
|
272
|
+
@db.instance_variable_set(:@db, saved_db)
|
|
273
|
+
@config._settings.clear
|
|
274
|
+
@config._settings.merge!(saved_settings)
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
describe '.init_postgresql()' do
|
|
280
|
+
it 'raises a Moose DB exception when a required connection key is missing' do
|
|
281
|
+
with_db_config(
|
|
282
|
+
adapter: 'postgresql',
|
|
283
|
+
host: 'localhost',
|
|
284
|
+
database: 'moose_inventory_test',
|
|
285
|
+
password: 'secret'
|
|
286
|
+
) do
|
|
287
|
+
expect { @db.init_postgresql }.to raise_error(
|
|
288
|
+
Moose::Inventory::DB::MooseDBException,
|
|
289
|
+
/Expected key user missing in postgresql configuration/
|
|
290
|
+
)
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
it 'raises a Moose DB exception when password_env points to an unset variable' do
|
|
295
|
+
saved_password = ENV['MOOSE_INVENTORY_POSTGRES_PASSWORD']
|
|
296
|
+
ENV.delete('MOOSE_INVENTORY_POSTGRES_PASSWORD')
|
|
297
|
+
|
|
298
|
+
begin
|
|
299
|
+
with_db_config(
|
|
300
|
+
adapter: 'postgresql',
|
|
301
|
+
host: 'localhost',
|
|
302
|
+
database: 'moose_inventory_test',
|
|
303
|
+
user: 'moose',
|
|
304
|
+
password_env: 'MOOSE_INVENTORY_POSTGRES_PASSWORD'
|
|
305
|
+
) do
|
|
306
|
+
expect { @db.init_postgresql }.to raise_error(
|
|
307
|
+
Moose::Inventory::DB::MooseDBException,
|
|
308
|
+
/Environment variable MOOSE_INVENTORY_POSTGRES_PASSWORD is not set for postgresql password/
|
|
309
|
+
)
|
|
310
|
+
end
|
|
311
|
+
ensure
|
|
312
|
+
ENV['MOOSE_INVENTORY_POSTGRES_PASSWORD'] = saved_password unless saved_password.nil?
|
|
313
|
+
end
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
it 'uses a postgresql password from the configured environment variable' do
|
|
317
|
+
saved_db = @db.instance_variable_get(:@db)
|
|
318
|
+
saved_settings = @config._settings.dup
|
|
319
|
+
saved_password = ENV['MOOSE_INVENTORY_POSTGRES_PASSWORD']
|
|
320
|
+
postgresql_config = {
|
|
321
|
+
adapter: 'postgresql',
|
|
322
|
+
host: 'localhost',
|
|
323
|
+
database: 'moose_inventory_test',
|
|
324
|
+
user: 'moose',
|
|
325
|
+
password_env: 'MOOSE_INVENTORY_POSTGRES_PASSWORD',
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
begin
|
|
329
|
+
ENV['MOOSE_INVENTORY_POSTGRES_PASSWORD'] = 'env-secret'
|
|
330
|
+
@db.instance_variable_set(:@db, nil)
|
|
331
|
+
@config._settings.clear
|
|
332
|
+
@config._settings[:config] = { db: postgresql_config }
|
|
333
|
+
|
|
334
|
+
expect(Sequel).to receive(:postgres).with(
|
|
335
|
+
user: 'moose',
|
|
336
|
+
password: 'env-secret',
|
|
337
|
+
host: 'localhost',
|
|
338
|
+
database: 'moose_inventory_test'
|
|
339
|
+
).and_return(:postgresql_connection)
|
|
340
|
+
|
|
341
|
+
@db.init_postgresql
|
|
342
|
+
expect(@db.db).to eq(:postgresql_connection)
|
|
343
|
+
ensure
|
|
344
|
+
if saved_password.nil?
|
|
345
|
+
ENV.delete('MOOSE_INVENTORY_POSTGRES_PASSWORD')
|
|
346
|
+
else
|
|
347
|
+
ENV['MOOSE_INVENTORY_POSTGRES_PASSWORD'] = saved_password
|
|
348
|
+
end
|
|
349
|
+
@db.instance_variable_set(:@db, saved_db)
|
|
350
|
+
@config._settings.clear
|
|
351
|
+
@config._settings.merge!(saved_settings)
|
|
352
|
+
end
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
it 'uses the postgres Sequel adapter with configured connection settings' do
|
|
356
|
+
saved_db = @db.instance_variable_get(:@db)
|
|
357
|
+
saved_settings = @config._settings.dup
|
|
358
|
+
postgresql_config = {
|
|
359
|
+
adapter: 'postgresql',
|
|
360
|
+
host: 'localhost',
|
|
361
|
+
database: 'moose_inventory_test',
|
|
362
|
+
user: 'moose',
|
|
363
|
+
password: 'secret',
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
begin
|
|
367
|
+
@db.instance_variable_set(:@db, nil)
|
|
368
|
+
@config._settings.clear
|
|
369
|
+
@config._settings[:config] = { db: postgresql_config }
|
|
370
|
+
|
|
371
|
+
expect(Sequel).to receive(:postgres).with(
|
|
372
|
+
user: 'moose',
|
|
373
|
+
password: 'secret',
|
|
374
|
+
host: 'localhost',
|
|
375
|
+
database: 'moose_inventory_test'
|
|
376
|
+
).and_return(:postgresql_connection)
|
|
377
|
+
|
|
378
|
+
@db.init_postgresql
|
|
379
|
+
expect(@db.db).to eq(:postgresql_connection)
|
|
380
|
+
ensure
|
|
381
|
+
@db.instance_variable_set(:@db, saved_db)
|
|
382
|
+
@config._settings.clear
|
|
383
|
+
@config._settings.merge!(saved_settings)
|
|
384
|
+
end
|
|
385
|
+
end
|
|
50
386
|
end
|
|
51
387
|
|
|
52
388
|
describe '.db' do
|
|
@@ -180,5 +516,53 @@ RSpec.describe 'Moose::Inventory::DB' do
|
|
|
180
516
|
|
|
181
517
|
expect(count[:final]).to eq(count[:initial])
|
|
182
518
|
end
|
|
519
|
+
|
|
520
|
+
it 'prints concise Moose DB transaction errors by default' do
|
|
521
|
+
saved_trace = @config._confopts[:trace]
|
|
522
|
+
@config._confopts[:trace] = false
|
|
523
|
+
|
|
524
|
+
begin
|
|
525
|
+
actual = runner do
|
|
526
|
+
@db.transaction do
|
|
527
|
+
fail @db.exceptions[:moose], 'Trace regression target'
|
|
528
|
+
end
|
|
529
|
+
end
|
|
530
|
+
ensure
|
|
531
|
+
@config._confopts[:trace] = saved_trace
|
|
532
|
+
end
|
|
533
|
+
|
|
534
|
+
expect(actual[:unexpected]).to eq(false)
|
|
535
|
+
expect(actual[:aborted]).to eq(true)
|
|
536
|
+
expect(actual[:STDERR]).to eq(
|
|
537
|
+
"An error occurred during a transaction, any changes have been rolled back.\n" \
|
|
538
|
+
"ERROR: Trace regression target\n"
|
|
539
|
+
)
|
|
540
|
+
end
|
|
541
|
+
|
|
542
|
+
it 'prints the Moose DB exception backtrace when trace is enabled' do
|
|
543
|
+
saved_trace = @config._confopts[:trace]
|
|
544
|
+
@config._confopts[:trace] = true
|
|
545
|
+
|
|
546
|
+
begin
|
|
547
|
+
actual = runner do
|
|
548
|
+
@db.transaction do
|
|
549
|
+
fail @db.exceptions[:moose], 'Trace regression target'
|
|
550
|
+
end
|
|
551
|
+
end
|
|
552
|
+
ensure
|
|
553
|
+
@config._confopts[:trace] = saved_trace
|
|
554
|
+
end
|
|
555
|
+
|
|
556
|
+
expect(actual[:unexpected]).to eq(false)
|
|
557
|
+
expect(actual[:aborted]).to eq(true)
|
|
558
|
+
expect(actual[:STDERR]).to include(
|
|
559
|
+
"An error occurred during a transaction, any changes have been rolled back.\n"
|
|
560
|
+
)
|
|
561
|
+
expect(actual[:STDERR]).to include('Moose::Inventory::DB::MooseDBException')
|
|
562
|
+
expect(actual[:STDERR]).to include('Trace regression target')
|
|
563
|
+
expect(actual[:STDERR]).to include('spec/lib/moose_inventory/db/db_spec.rb')
|
|
564
|
+
expect(actual[:STDERR]).to include("ERROR: Trace regression target\n")
|
|
565
|
+
expect(actual[:STDERR]).not_to include('NoMethodError')
|
|
566
|
+
end
|
|
183
567
|
end
|
|
184
568
|
end
|
|
@@ -10,7 +10,7 @@ RSpec.describe 'models' do
|
|
|
10
10
|
@mockarg_parts = {
|
|
11
11
|
config: File.join(spec_root, 'config/config.yml'),
|
|
12
12
|
format: 'yaml',
|
|
13
|
-
env: 'test'
|
|
13
|
+
env: 'test',
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
@mockargs = []
|
|
@@ -128,45 +128,44 @@ RSpec.describe 'models' do
|
|
|
128
128
|
end
|
|
129
129
|
|
|
130
130
|
it 'should have a many-to-many self-referential relationship (i.e. GROUPS of GROUPS)' do
|
|
131
|
-
|
|
132
131
|
parent1 = @db.models[:group].create(name: 'parent1')
|
|
133
132
|
parent2 = @db.models[:group].create(name: 'parent2')
|
|
134
133
|
child1 = @db.models[:group].create(name: 'child1')
|
|
135
134
|
child2 = @db.models[:group].create(name: 'child2')
|
|
136
135
|
|
|
137
|
-
parent1.add_child(child1)
|
|
136
|
+
parent1.add_child(child1)
|
|
138
137
|
parent1.add_child(child2)
|
|
139
138
|
|
|
140
|
-
parent2.add_child(child1)
|
|
139
|
+
parent2.add_child(child1)
|
|
141
140
|
parent2.add_child(child2)
|
|
142
|
-
|
|
141
|
+
|
|
143
142
|
group = @db.models[:group].find(name: 'parent1')
|
|
144
143
|
children = group.children_dataset
|
|
145
144
|
|
|
146
145
|
expect(children).not_to be_nil
|
|
147
146
|
expect(children.count).to eq(2)
|
|
148
|
-
|
|
147
|
+
|
|
149
148
|
group = @db.models[:group].find(name: 'parent2')
|
|
150
149
|
children = group.children_dataset
|
|
151
150
|
|
|
152
151
|
expect(children).not_to be_nil
|
|
153
152
|
expect(children.count).to eq(2)
|
|
154
153
|
end
|
|
155
|
-
|
|
154
|
+
|
|
156
155
|
it 'should have relationships with Hostvars' do
|
|
157
156
|
groupname = 'group-test'
|
|
158
157
|
groupvarname = 'groupvar-test'
|
|
159
158
|
groupvarval = '1'
|
|
160
|
-
|
|
159
|
+
|
|
161
160
|
group = @db.models[:group].create(name: groupname)
|
|
162
161
|
groupvar = @db.models[:groupvar].create(name: groupvarname,
|
|
163
162
|
value: groupvarval)
|
|
164
|
-
|
|
163
|
+
|
|
165
164
|
group.add_groupvar(groupvar)
|
|
166
|
-
|
|
165
|
+
|
|
167
166
|
group = @db.models[:group].find(name: groupname)
|
|
168
167
|
groupvars = group.groupvars_dataset
|
|
169
|
-
|
|
168
|
+
|
|
170
169
|
expect(groupvars).not_to be_nil
|
|
171
170
|
expect(groupvars.count).to eq(1)
|
|
172
171
|
expect(groupvars.first[:name]).to eq(groupvarname)
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
require 'inventory_context'
|
|
5
|
+
require 'operations/add_associations'
|
|
6
|
+
|
|
7
|
+
RSpec.describe Moose::Inventory::Operations::AddAssociations do
|
|
8
|
+
before(:all) do
|
|
9
|
+
@mockargs = [
|
|
10
|
+
'--config', File.join(spec_root, 'config/config.yml'),
|
|
11
|
+
'--format', 'yaml',
|
|
12
|
+
'--env', 'test'
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
Moose::Inventory::Config.init(@mockargs)
|
|
16
|
+
@db = Moose::Inventory::DB
|
|
17
|
+
@db.init if @db.db.nil?
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
before(:each) do
|
|
21
|
+
@db.reset
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def operation
|
|
25
|
+
described_class.new(
|
|
26
|
+
context: Moose::Inventory::InventoryContext.new(db: @db)
|
|
27
|
+
)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it 'adds groups to an existing host and reports creation/duplicate events' do
|
|
31
|
+
host = @db.models[:host].create(name: 'host1')
|
|
32
|
+
ungrouped = @db.models[:group].find_or_create(name: 'ungrouped')
|
|
33
|
+
host.add_group(ungrouped)
|
|
34
|
+
existing_group = @db.models[:group].create(name: 'existing')
|
|
35
|
+
host.add_group(existing_group)
|
|
36
|
+
|
|
37
|
+
result = operation.host_to_groups(
|
|
38
|
+
host: host,
|
|
39
|
+
host_name: 'host1',
|
|
40
|
+
group_names: %w[existing created]
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
expect(result.warning_count).to eq(2)
|
|
44
|
+
expect(result.events.map(&:type)).to include(
|
|
45
|
+
:host_group_association_exists,
|
|
46
|
+
:group_missing_created,
|
|
47
|
+
:removing_automatic_group
|
|
48
|
+
)
|
|
49
|
+
expect(host.groups_dataset[name: 'created']).not_to be_nil
|
|
50
|
+
expect(host.groups_dataset[name: 'ungrouped']).to be_nil
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it 'adds hosts to an existing group and reports creation/duplicate events' do
|
|
54
|
+
group = @db.models[:group].create(name: 'group1')
|
|
55
|
+
duplicate_host = @db.models[:host].create(name: 'host1')
|
|
56
|
+
existing_host = @db.models[:host].create(name: 'host3')
|
|
57
|
+
ungrouped = @db.models[:group].find_or_create(name: 'ungrouped')
|
|
58
|
+
duplicate_host.add_group(ungrouped)
|
|
59
|
+
existing_host.add_group(ungrouped)
|
|
60
|
+
group.add_host(duplicate_host)
|
|
61
|
+
|
|
62
|
+
result = operation.group_to_hosts(
|
|
63
|
+
group: group,
|
|
64
|
+
group_name: 'group1',
|
|
65
|
+
host_names: %w[host1 host2 host3]
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
expect(result.warning_count).to eq(2)
|
|
69
|
+
expect(result.events.map(&:type)).to include(
|
|
70
|
+
:group_host_association_exists,
|
|
71
|
+
:host_missing_created,
|
|
72
|
+
:removing_automatic_group
|
|
73
|
+
)
|
|
74
|
+
expect(group.hosts_dataset[name: 'host2']).not_to be_nil
|
|
75
|
+
expect(existing_host.groups_dataset[name: 'ungrouped']).to be_nil
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
require 'inventory_context'
|
|
5
|
+
require 'operations/add_groups'
|
|
6
|
+
|
|
7
|
+
RSpec.describe Moose::Inventory::Operations::AddGroups do
|
|
8
|
+
before(:all) do
|
|
9
|
+
@mockargs = [
|
|
10
|
+
'--config', File.join(spec_root, 'config/config.yml'),
|
|
11
|
+
'--format', 'yaml',
|
|
12
|
+
'--env', 'test'
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
Moose::Inventory::Config.init(@mockargs)
|
|
16
|
+
@db = Moose::Inventory::DB
|
|
17
|
+
@db.init if @db.db.nil?
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
before(:each) do
|
|
21
|
+
@db.reset
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def operation
|
|
25
|
+
described_class.new(
|
|
26
|
+
context: Moose::Inventory::InventoryContext.new(db: @db)
|
|
27
|
+
)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it 'adds a group and returns structured events without rendering output' do
|
|
31
|
+
actual = runner do
|
|
32
|
+
@result = operation.call(names: ['testgroup'], hosts: [])
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
expected(actual, STDOUT: '', STDERR: '')
|
|
36
|
+
expect(@result.warning_count).to eq(0)
|
|
37
|
+
expect(@result.events.map(&:type)).to eq(%i[group_started creating_group ok group_complete])
|
|
38
|
+
|
|
39
|
+
group = @db.models[:group].find(name: 'testgroup')
|
|
40
|
+
expect(group).not_to be_nil
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it 'reports existing groups, created hosts, duplicate associations, and ungrouped removal as events' do
|
|
44
|
+
host = @db.models[:host].create(name: 'testhost')
|
|
45
|
+
ungrouped = @db.models[:group].find_or_create(name: 'ungrouped')
|
|
46
|
+
host.add_group(ungrouped)
|
|
47
|
+
group = @db.models[:group].create(name: 'testgroup')
|
|
48
|
+
group.add_host(host)
|
|
49
|
+
|
|
50
|
+
@result = operation.call(
|
|
51
|
+
names: ['testgroup'],
|
|
52
|
+
hosts: %w[testhost newhost]
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
expect(@result.warning_count).to eq(3)
|
|
56
|
+
expect(@result.events.map(&:type)).to include(
|
|
57
|
+
:group_exists,
|
|
58
|
+
:association_exists,
|
|
59
|
+
:host_missing_created,
|
|
60
|
+
:removing_automatic_group
|
|
61
|
+
)
|
|
62
|
+
expect(@db.models[:host].find(name: 'newhost')).not_to be_nil
|
|
63
|
+
expect(host.groups_dataset[name: 'ungrouped']).to be_nil
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe Moose::Inventory::Operations::AddHosts do
|
|
6
|
+
before(:all) do
|
|
7
|
+
@mockargs = [
|
|
8
|
+
'--config', File.join(spec_root, 'config/config.yml'),
|
|
9
|
+
'--format', 'yaml',
|
|
10
|
+
'--env', 'test'
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
Moose::Inventory::Config.init(@mockargs)
|
|
14
|
+
@db = Moose::Inventory::DB
|
|
15
|
+
@db.init if @db.db.nil?
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
before(:each) do
|
|
19
|
+
@db.reset
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def operation
|
|
23
|
+
described_class.new(
|
|
24
|
+
context: Moose::Inventory::InventoryContext.new(db: @db)
|
|
25
|
+
)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
describe '#call' do
|
|
29
|
+
it 'adds a host and returns structured events without rendering output' do
|
|
30
|
+
actual = runner do
|
|
31
|
+
@result = operation.call(names: ['testhost'], groups: [])
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
expected(actual, STDOUT: '', STDERR: '')
|
|
35
|
+
expect(@result.events.map(&:type)).to eq(
|
|
36
|
+
%i[host_started creating_host ok adding_automatic_group ok host_complete]
|
|
37
|
+
)
|
|
38
|
+
expect(@result.events[0].payload).to eq(name: 'testhost')
|
|
39
|
+
expect(@result.events[3].payload).to eq(host: 'testhost', group: 'ungrouped')
|
|
40
|
+
|
|
41
|
+
host = @db.models[:host].find(name: 'testhost')
|
|
42
|
+
expect(host).not_to be_nil
|
|
43
|
+
expect(host.groups_dataset[name: 'ungrouped']).not_to be_nil
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it 'reports existing hosts, missing groups, and duplicate associations as events' do
|
|
47
|
+
host = @db.models[:host].create(name: 'testhost')
|
|
48
|
+
group = @db.models[:group].create(name: 'existinggroup')
|
|
49
|
+
host.add_group(group)
|
|
50
|
+
|
|
51
|
+
@result = operation.call(
|
|
52
|
+
names: ['testhost'],
|
|
53
|
+
groups: %w[existinggroup missinggroup]
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
expect(@result.events.map(&:type)).to include(
|
|
57
|
+
:host_exists,
|
|
58
|
+
:association_exists,
|
|
59
|
+
:group_missing_created
|
|
60
|
+
)
|
|
61
|
+
expect(@result.events.find { |event| event.type == :host_exists }.payload).to eq(name: 'testhost')
|
|
62
|
+
expect(@result.events.find { |event| event.type == :association_exists }.payload).to eq(
|
|
63
|
+
host: 'testhost',
|
|
64
|
+
group: 'existinggroup'
|
|
65
|
+
)
|
|
66
|
+
expect(@db.models[:group].find(name: 'missinggroup')).not_to be_nil
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|