hammer_cli_katello 0.14.1 → 0.15.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/lib/hammer_cli_katello/apipie_helper.rb +15 -0
  3. data/lib/hammer_cli_katello/associating_commands.rb +6 -2
  4. data/lib/hammer_cli_katello/commands.rb +7 -0
  5. data/lib/hammer_cli_katello/content_view_purge.rb +1 -1
  6. data/lib/hammer_cli_katello/content_view_version.rb +238 -2
  7. data/lib/hammer_cli_katello/erratum.rb +4 -0
  8. data/lib/hammer_cli_katello/file.rb +4 -6
  9. data/lib/hammer_cli_katello/foreman_search_options_creators.rb +1 -1
  10. data/lib/hammer_cli_katello/id_resolver.rb +2 -0
  11. data/lib/hammer_cli_katello/local_helper.rb +9 -0
  12. data/lib/hammer_cli_katello/module_stream.rb +69 -0
  13. data/lib/hammer_cli_katello/module_stream_profile.rb +0 -0
  14. data/lib/hammer_cli_katello/ostree_branch.rb +4 -0
  15. data/lib/hammer_cli_katello/package_group.rb +4 -0
  16. data/lib/hammer_cli_katello/puppet_module.rb +4 -0
  17. data/lib/hammer_cli_katello/repository.rb +21 -7
  18. data/lib/hammer_cli_katello/repository_scoped_to_product.rb +3 -3
  19. data/lib/hammer_cli_katello/search_options_creators.rb +10 -2
  20. data/lib/hammer_cli_katello/sync_plan.rb +6 -8
  21. data/lib/hammer_cli_katello/version.rb +1 -1
  22. data/lib/hammer_cli_katello.rb +9 -0
  23. data/test/data/3.8/foreman_api.json +1 -1
  24. data/test/data/3.9/foreman_api.json +1 -0
  25. data/test/functional/apipie_helper_test.rb +26 -0
  26. data/test/functional/content_view/publish_test.rb +20 -0
  27. data/test/functional/content_view/version/export_test.rb +87 -0
  28. data/test/functional/content_view/version/import_test.rb +111 -0
  29. data/test/functional/content_view/version/incremental_update_test.rb +0 -0
  30. data/test/functional/local_helper_test.rb +30 -0
  31. data/test/functional/module_stream/info_test.rb +58 -0
  32. data/test/functional/module_stream/list_test.rb +53 -0
  33. data/test/functional/package_group/list_test.rb +14 -9
  34. data/test/functional/sync_plan/create_test.rb +60 -0
  35. data/test/functional/sync_plan/delete_test.rb +46 -0
  36. data/test/functional/sync_plan/update_test.rb +44 -0
  37. data/test/test_helper.rb +1 -1
  38. data/test/unit/search_options_creators_test.rb +4 -1
  39. metadata +30 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 020a802118e1d02ce02183915e5d3c27d17fc9a5
4
- data.tar.gz: 1c481ed3adf302f0dd8162f133c4e14d87b1ccd7
3
+ metadata.gz: 81a158e8e77bef73123e89992746c3b24f9689ef
4
+ data.tar.gz: 417e144685491e014455d2c1eacb1d8caaba7d40
5
5
  SHA512:
6
- metadata.gz: 4af3a91c622735ba6df894b0bdcd1feeda752f063fdf0bc2b8902ba3de47908cf263f3918e52201f5da4378f677de02ee6608605f5e7b5b4dbcc80544023d1ed
7
- data.tar.gz: 818cac4835323c945ef06b618d9b510a427c2954df30cdd2250d5bf9e7857a827d7944ad819b53d7cee45d8359869ccb602e3c4d78e3860f6682540b5626450b
6
+ metadata.gz: 3c53985e39d45ba73ac11d19e1cf4ea3c40f60204ac98d9f86f01cb8d69c556df92889fd89965b35b93500a7d4a93b5123b48790ea3575a8f57866765b79d7ad
7
+ data.tar.gz: 64a6b70c343bafd39bb7bce8db5bd1b029a9bdb13769befb5ddd0441c33b3fdd443779a3859f8b9c1b1dc0e5f0c4db28b7c1a351f5a82103cd936a1e4a878c06
@@ -0,0 +1,15 @@
1
+ module HammerCLIKatello
2
+ module ApipieHelper
3
+ def show(resource, options = {})
4
+ call(:show, resource, options)
5
+ end
6
+
7
+ def index(resource, options = {})
8
+ call(:index, resource, options)['results']
9
+ end
10
+
11
+ def call(action, resource, options = {})
12
+ HammerCLIForeman.foreman_resource(resource).call(action, options)
13
+ end
14
+ end
15
+ end
@@ -23,8 +23,10 @@ module HammerCLIKatello
23
23
 
24
24
  class AddRepositoryCommand < HammerCLIKatello::AddAssociatedCommand
25
25
  extend AddProductOptions
26
- include RepositoryScopedToProduct
26
+ extend RepositoryScopedToProduct
27
27
  include OrganizationOptions
28
+
29
+ validate_repo_name_requires_product_options
28
30
  command_name 'add-repository'
29
31
  associated_resource :repositories
30
32
 
@@ -39,8 +41,10 @@ module HammerCLIKatello
39
41
 
40
42
  class RemoveRepositoryCommand < HammerCLIKatello::RemoveAssociatedCommand
41
43
  extend AddProductOptions
42
- include RepositoryScopedToProduct
44
+ extend RepositoryScopedToProduct
43
45
  include OrganizationOptions
46
+
47
+ validate_repo_name_requires_product_options
44
48
  command_name 'remove-repository'
45
49
  associated_resource :repositories
46
50
 
@@ -43,6 +43,13 @@ module HammerCLIKatello
43
43
 
44
44
  class ListCommand < HammerCLIForeman::ListCommand
45
45
  include HammerCLIKatello::ResolverCommons
46
+
47
+ def self.build_options(builder_params = {}, &block)
48
+ # remove --sort-by and --sort-order in favor of the Foreman's --order
49
+ builder_params[:without] ||= []
50
+ builder_params[:without] += %i(sort_by sort_order)
51
+ super(builder_params, &block)
52
+ end
46
53
  end
47
54
 
48
55
  class InfoCommand < HammerCLIForeman::InfoCommand
@@ -53,7 +53,7 @@ module HammerCLIKatello
53
53
  end
54
54
 
55
55
  def execute
56
- if option_count < 0
56
+ if option_count.negative?
57
57
  output.print_error _("Invalid value for --count option: value must be 0 or greater.")
58
58
  return HammerCLI::EX_USAGE
59
59
  end
@@ -1,3 +1,5 @@
1
+ require 'fileutils'
2
+
1
3
  module HammerCLIKatello
2
4
  class ContentViewVersion < HammerCLIKatello::Command
3
5
  resource :content_view_versions
@@ -245,11 +247,12 @@ module HammerCLIKatello
245
247
  end
246
248
  end
247
249
 
248
- class ExportCommand < HammerCLIKatello::SingleResourceCommand
250
+ class LegacyExportCommand < HammerCLIKatello::SingleResourceCommand
249
251
  include HammerCLIForemanTasks::Async
252
+ desc _('Export a content view (deprecated)')
250
253
 
251
254
  action :export
252
- command_name "export"
255
+ command_name "export-legacy"
253
256
 
254
257
  success_message _("Content view is being exported in task %{id}.")
255
258
  failure_message _("Could not export the content view")
@@ -259,6 +262,239 @@ module HammerCLIKatello
259
262
  end
260
263
  end
261
264
 
265
+ class ExportCommand < HammerCLIForeman::Command
266
+ include HammerCLIKatello::LocalHelper
267
+ include HammerCLIKatello::ApipieHelper
268
+
269
+ PUBLISHED_REPOS_DIR = "/var/lib/pulp/published/yum/https/repos/".freeze
270
+
271
+ desc _('Export a content view version')
272
+
273
+ command_name "export"
274
+
275
+ success_message _("Content view export is available in %{directory}.")
276
+ failure_message _("Could not export the content view")
277
+
278
+ option "--id", "ID", _("Content View Version numeric identifier")
279
+ option '--export-dir', 'EXPORT_DIR', _("Directory to put content view version export into.")
280
+
281
+ validate_options do
282
+ option(:option_export_dir).required
283
+ option(:option_id).required
284
+ end
285
+
286
+ build_options
287
+
288
+ def execute
289
+ cvv = show(:content_view_versions, 'id' => options['option_id'])
290
+ repositories = cvv['repositories'].collect do |repo|
291
+ show(:repositories, 'id' => repo['id'], :full_result => true)
292
+ end
293
+
294
+ check_repo_download_policy(repositories)
295
+
296
+ repositories.each do |repo|
297
+ repo['packages'] = index(:packages, 'repository_id' => repo['id'], :full_result => true)
298
+ repo['errata'] = index(:errata, 'repository_id' => repo['id'], :full_result => true)
299
+ end
300
+
301
+ json = export_json(cvv, repositories)
302
+ create_tar(cvv, repositories, json)
303
+ return HammerCLI::EX_OK
304
+ end
305
+
306
+ def create_tar(cvv, repositories, json)
307
+ export_prefix = "export-#{cvv['id']}"
308
+ export_file = "#{export_prefix}.json"
309
+ export_repos_tar = "#{export_prefix}-repos.tar"
310
+ export_tar = "#{export_prefix}.tar"
311
+
312
+ Dir.mkdir("#{options['option_export_dir']}/#{export_prefix}")
313
+
314
+ Dir.chdir(PUBLISHED_REPOS_DIR) do
315
+ repo_tar = "#{options['option_export_dir']}/#{export_prefix}/#{export_repos_tar}"
316
+ repo_dirs = []
317
+
318
+ repositories.each do |repo|
319
+ repo_dirs.push(repo['relative_path'])
320
+ end
321
+
322
+ `tar cvfh #{repo_tar} #{repo_dirs.join(" ")}`
323
+ end
324
+
325
+ Dir.chdir("#{options['option_export_dir']}/#{export_prefix}") do
326
+ File.open(export_file, 'w') do |file|
327
+ file.write(JSON.pretty_generate(json))
328
+ end
329
+ end
330
+
331
+ Dir.chdir(options['option_export_dir']) do
332
+ `tar cf #{export_tar} #{export_prefix}`
333
+ FileUtils.rm_rf(export_prefix)
334
+ end
335
+ end
336
+
337
+ def check_repo_download_policy(repositories)
338
+ on_demand = repositories.select do |repo|
339
+ show(:repositories, 'id' => repo['library_instance_id'])['download_policy'] == 'on_demand'
340
+ end
341
+ return true if on_demand.empty?
342
+
343
+ on_demand_names = repositories.collect { |repo| repo['name'] }
344
+ msg = <<~MSG
345
+ All exported repositories must be set to an immediate download policy and re-synced.
346
+ The following repositories need action:
347
+ #{on_demand_names.join('\n')}
348
+ MSG
349
+ raise _(msg)
350
+ end
351
+
352
+ def export_json(content_view_version, repositories)
353
+ json = {
354
+ "name" => content_view_version['content_view']['name'],
355
+ "major" => content_view_version['major'],
356
+ "minor" => content_view_version['minor']
357
+ }
358
+
359
+ json["repositories"] = repositories.collect do |repo|
360
+ {
361
+ "id" => repo['id'],
362
+ "label" => repo['label'],
363
+ "content_type" => repo['content_type'],
364
+ "backend_identifier" => repo['backend_identifier'],
365
+ "relative_path" => repo['relative_path'],
366
+ "on_disk_path" => "#{PUBLISHED_REPOS_DIR}/#{repo['relative_path']}",
367
+ "rpm_filenames" => repo['packages'].collect { |package| package['filename'] },
368
+ "errata_ids" => repo['errata'].collect { |errata| errata['errata_id'] }
369
+ }
370
+ end
371
+
372
+ json
373
+ end
374
+ end
375
+
376
+ class ImportCommand < HammerCLIForeman::Command
377
+ include HammerCLIForemanTasks::Async
378
+ include HammerCLIKatello::LocalHelper
379
+ include HammerCLIKatello::ApipieHelper
380
+
381
+ attr_accessor :export_tar_dir, :export_tar_file, :export_tar_prefix
382
+
383
+ desc _('Import a content view version')
384
+
385
+ command_name "import"
386
+
387
+ success_message _("Content view imported.")
388
+ failure_message _("Could not import the content view.")
389
+
390
+ option "--organization-id", "ORGANIZATION_ID", _("Organization numeric identifier")
391
+ option(
392
+ '--export-tar',
393
+ 'EXPORT_TAR',
394
+ _("Location of export tar on disk")
395
+ )
396
+
397
+ validate_options do
398
+ option(:option_export_tar).required
399
+ option(:option_organization_id).required
400
+ end
401
+
402
+ build_options
403
+
404
+ def execute
405
+ unless File.exist?(options['option_export_tar'])
406
+ raise _("Export tar #{options['option_export_tar']} does not exist.")
407
+ end
408
+
409
+ self.export_tar_file = File.basename(options['option_export_tar'])
410
+ self.export_tar_prefix = @export_tar_file.gsub('.tar', '')
411
+ self.export_tar_dir = File.dirname(options['option_export_tar'])
412
+ untar_export
413
+
414
+ export_json = read_json
415
+
416
+ cv = content_view(export_json['name'], options['option_organization_id'])
417
+ sync_repositories(export_json['repositories'], options['option_organization_id'])
418
+
419
+ publish(
420
+ cv['id'],
421
+ export_json['major'],
422
+ export_json['minor'],
423
+ repos_units(export_json['repositories'])
424
+ )
425
+ return HammerCLI::EX_OK
426
+ end
427
+
428
+ def untar_export
429
+ Dir.chdir(@export_tar_dir) do
430
+ `tar -xf #{@export_tar_file}`
431
+ end
432
+
433
+ Dir.chdir("#{@export_tar_dir}/#{@export_tar_prefix}") do
434
+ if File.exist?(@export_tar_file.gsub('.tar', '-repos.tar'))
435
+ `tar -xf #{@export_tar_file.gsub('.tar', '-repos.tar')}`
436
+ else
437
+ raise _("Export repos tar file is missing.")
438
+ end
439
+ end
440
+ end
441
+
442
+ def read_json
443
+ json_file = @export_tar_file.gsub('tar', 'json')
444
+ json_file = "#{@export_tar_dir}/#{@export_tar_prefix}/#{json_file}"
445
+ json_file = File.read(json_file)
446
+ JSON.parse(json_file)
447
+ end
448
+
449
+ def sync_repositories(repositories, organization_id)
450
+ repositories.each do |repo|
451
+ library_repos = index(
452
+ :repositories,
453
+ 'organization_id' => organization_id,
454
+ 'library' => true
455
+ )
456
+
457
+ library_repo = library_repos.select do |candidate_repo|
458
+ candidate_repo['label'] == repo['label']
459
+ end
460
+
461
+ library_repo = library_repo.first
462
+
463
+ if library_repo.nil?
464
+ msg = _("Unable to sync repositories, no library repository found for %s")
465
+ raise msg % repo['label']
466
+ end
467
+
468
+ synchronize(
469
+ library_repo['id'],
470
+ "file://#{@export_tar_dir}/#{@export_tar_prefix}/#{repo['relative_path']}"
471
+ )
472
+ end
473
+ end
474
+
475
+ def repos_units(repositories)
476
+ repositories.collect do |repo|
477
+ {
478
+ 'label' => repo['label'],
479
+ 'rpm_filenames' => repo['rpm_filenames']
480
+ }
481
+ end
482
+ end
483
+
484
+ def content_view(name, organization_id)
485
+ index(:content_views, 'name' => name, 'organization_id' => organization_id).first
486
+ end
487
+
488
+ def synchronize(id, source_url)
489
+ task_progress(call(:sync, :repositories, 'id' => id, 'source_url' => source_url))
490
+ end
491
+
492
+ def publish(id, major, minor, repos_units)
493
+ params = {'id' => id, 'major' => major, 'minor' => minor, 'repos_units' => repos_units}
494
+ task_progress(call(:publish, :content_views, params))
495
+ end
496
+ end
497
+
262
498
  autoload_subcommands
263
499
  end
264
500
  end
@@ -3,6 +3,10 @@ module HammerCLIKatello
3
3
  resource :errata
4
4
 
5
5
  class ListCommand < HammerCLIKatello::ListCommand
6
+ extend RepositoryScopedToProduct
7
+
8
+ validate_repo_name_requires_product_options(:option_repository_name)
9
+
6
10
  output do
7
11
  field :id, _("ID")
8
12
  field :errata_id, _("Errata ID")
@@ -3,6 +3,10 @@ module HammerCLIKatello
3
3
  resource :file_units
4
4
 
5
5
  class ListCommand < HammerCLIKatello::ListCommand
6
+ extend RepositoryScopedToProduct
7
+
8
+ validate_repo_name_requires_product_options(:option_repository_name)
9
+
6
10
  output do
7
11
  field :id, _("ID")
8
12
  field :name, _("Name")
@@ -12,15 +16,9 @@ module HammerCLIKatello
12
16
  validate_options do
13
17
  organization_options = [:option_organization_id, :option_organization_name,
14
18
  :option_organization_label]
15
- product_options = [:option_product_id, :option_product_name]
16
-
17
19
  if any(:option_product_name, :option_content_view_name).exist?
18
20
  any(*organization_options).required
19
21
  end
20
-
21
- if option(:option_repository_name).exist?
22
- any(*product_options).required
23
- end
24
22
  end
25
23
 
26
24
  build_options do |o|
@@ -76,7 +76,7 @@ module HammerCLIKatello
76
76
  create_search_options_without_katello_api(options, api.resource(:compute_resources), mode)
77
77
  end
78
78
 
79
- def create_image_search_options(options, mode = nil)
79
+ def create_images_search_options(options, mode = nil)
80
80
  create_search_options_without_katello_api(options, api.resource(:images), mode)
81
81
  end
82
82
  end
@@ -10,6 +10,8 @@ module HammerCLIKatello
10
10
  :file_unit => [s_name(_("File name to search by")),
11
11
  s("content_view_version_id", _("Content View Version ID")),
12
12
  s("repository_id", _("Repository ID"))],
13
+ :module_stream => [s_name(_("Module stream name to search by")),
14
+ s("repository_id", _("Repository ID"))],
13
15
  :gpg => [s_name(_("Gpg key name to search by"))],
14
16
  :host_collection => [s_name(_("Host collection name to search by"))],
15
17
  :lifecycle_environment => [s_name(_("Lifecycle environment name to search by"))],
@@ -0,0 +1,9 @@
1
+ module HammerCLIKatello
2
+ module LocalHelper
3
+ def parse_subcommand
4
+ return super if File.exist?('/usr/share/foreman')
5
+ raise "This command can only be run on the same server that Foreman is running on " \
6
+ "and cannot be run remotely."
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,69 @@
1
+ module HammerCLIKatello
2
+ class ModuleStreamCommand < HammerCLIKatello::Command
3
+ resource :module_streams
4
+
5
+ class ListCommand < HammerCLIKatello::ListCommand
6
+ extend RepositoryScopedToProduct
7
+
8
+ desc "List module streams"
9
+
10
+ validate_repo_name_requires_product_options(:option_repository_name)
11
+
12
+ output do
13
+ field :id, _("ID")
14
+ field :name, _("Module Stream Name")
15
+ field :stream, _("Stream")
16
+ field :uuid, _("UUID")
17
+ field :version, _("Version")
18
+ field :arch, _("Architecture")
19
+ field :context, _("Context")
20
+ end
21
+
22
+ build_options do |o|
23
+ o.expand.including(:products)
24
+ end
25
+ end
26
+
27
+ class InfoCommand < HammerCLIKatello::InfoCommand
28
+ extend RepositoryScopedToProduct
29
+
30
+ validate_repo_name_requires_product_options(:option_repository_name)
31
+
32
+ output do
33
+ field :id, _("ID")
34
+ field :name, _("Module Stream Name")
35
+ field :stream, _("Stream")
36
+ field :uuid, _("UUID")
37
+ field :version, _("Version")
38
+ field :arch, _("Architecture")
39
+ field :context, _("Context")
40
+
41
+ collection :repositories, _("Repositories") do
42
+ field :id, _("ID")
43
+ field :name, _("Name")
44
+ field :label, _("Label")
45
+ end
46
+
47
+ collection :artifacts, _("Artifacts") do
48
+ field :id, _("ID")
49
+ field :name, _("Name")
50
+ end
51
+
52
+ collection :profiles, _("Profiles") do
53
+ field :id, _("ID")
54
+ field :name, _("Name")
55
+ collection :rpms, _("RPMs") do
56
+ field :id, _("ID")
57
+ field :name, _("Name")
58
+ end
59
+ end
60
+ end
61
+
62
+ build_options do |o|
63
+ o.expand.including(:products, :organizations)
64
+ end
65
+ end
66
+
67
+ autoload_subcommands
68
+ end
69
+ end
File without changes
@@ -3,6 +3,10 @@ module HammerCLIKatello
3
3
  resource :ostree_branches
4
4
 
5
5
  class ListCommand < HammerCLIKatello::ListCommand
6
+ extend RepositoryScopedToProduct
7
+
8
+ validate_repo_name_requires_product_options(:option_repository_name)
9
+
6
10
  output do
7
11
  field :id, _("ID")
8
12
  field :name, _("Name")
@@ -3,6 +3,10 @@ module HammerCLIKatello
3
3
  resource :package_groups
4
4
 
5
5
  class ListCommand < HammerCLIKatello::ListCommand
6
+ extend RepositoryScopedToProduct
7
+
8
+ validate_repo_name_requires_product_options(:option_repository_name)
9
+
6
10
  output do
7
11
  field :id, _("ID")
8
12
  field :name, _("Package Group Name")
@@ -3,6 +3,10 @@ module HammerCLIKatello
3
3
  resource :puppet_modules
4
4
 
5
5
  class ListCommand < HammerCLIKatello::ListCommand
6
+ extend RepositoryScopedToProduct
7
+
8
+ validate_repo_name_requires_product_options(:option_repository_name)
9
+
6
10
  output do
7
11
  field :id, _("ID")
8
12
  field :name, _("Name")
@@ -18,7 +18,9 @@ module HammerCLIKatello
18
18
 
19
19
  # rubocop:disable ClassLength
20
20
  class InfoCommand < HammerCLIKatello::InfoCommand
21
- include RepositoryScopedToProduct
21
+ extend RepositoryScopedToProduct
22
+
23
+ validate_repo_name_requires_product_options
22
24
 
23
25
  output do
24
26
  field :id, _("ID")
@@ -42,6 +44,8 @@ module HammerCLIKatello
42
44
  Fields::Field, :hide_blank => true
43
45
  field :docker_upstream_name, _("Upstream Repository Name"),
44
46
  Fields::Field, :hide_blank => true
47
+ field :docker_tags_whitelist, _("Container Image Tags Filter"),
48
+ Fields::List, :hide_blank => true
45
49
  field :container_repository_name, _("Container Repository Name"),
46
50
  Fields::Field, :hide_blank => true
47
51
  field :ignorable_content, _("Ignorable Content Units"), Fields::List, :hide_blank => true
@@ -81,6 +85,7 @@ module HammerCLIKatello
81
85
  field :docker_tag_total, _("Container Image Tags"), Fields::Field, :hide_blank => true
82
86
  field :ostree_branch_total, _("OSTree Branches"), Fields::Field, :hide_blank => true
83
87
  field :file_total, _("Files"), Fields::Field, :hide_blank => true
88
+ field :module_stream_total, _("Module Streams"), Fields::Field, :hide_blank => true
84
89
  end
85
90
  end
86
91
 
@@ -118,6 +123,7 @@ module HammerCLIKatello
118
123
  data["srpm_total"] = content_counts["srpm"]
119
124
  data["package_group_total"] = content_counts["package_group"]
120
125
  data["errata_total"] = content_counts["erratum"]
126
+ data["module_stream_total"] = content_counts["module_stream"]
121
127
  when "docker"
122
128
  data["docker_manifest_list_total"] = content_counts["docker_manifest_list"]
123
129
  data["docker_manifest_total"] = content_counts["docker_manifest"]
@@ -156,7 +162,9 @@ module HammerCLIKatello
156
162
 
157
163
  class SyncCommand < HammerCLIKatello::SingleResourceCommand
158
164
  include HammerCLIForemanTasks::Async
159
- include RepositoryScopedToProduct
165
+ extend RepositoryScopedToProduct
166
+
167
+ validate_repo_name_requires_product_options
160
168
 
161
169
  action :sync
162
170
  command_name "synchronize"
@@ -181,7 +189,9 @@ module HammerCLIKatello
181
189
  end
182
190
 
183
191
  class UpdateCommand < HammerCLIKatello::UpdateCommand
184
- include RepositoryScopedToProduct
192
+ extend RepositoryScopedToProduct
193
+
194
+ validate_repo_name_requires_product_options
185
195
  include OrganizationOptions
186
196
 
187
197
  success_message _("Repository updated.")
@@ -265,9 +275,10 @@ module HammerCLIKatello
265
275
  end
266
276
 
267
277
  class DeleteCommand < HammerCLIKatello::DeleteCommand
268
- include RepositoryScopedToProduct
278
+ extend RepositoryScopedToProduct
269
279
  include OrganizationOptions
270
280
 
281
+ validate_repo_name_requires_product_options
271
282
  success_message _("Repository deleted.")
272
283
  failure_message _("Could not delete the Repository")
273
284
 
@@ -278,9 +289,10 @@ module HammerCLIKatello
278
289
 
279
290
  # rubocop:disable ClassLength
280
291
  class UploadContentCommand < HammerCLIKatello::InfoCommand
281
- include RepositoryScopedToProduct
292
+ extend RepositoryScopedToProduct
282
293
  include HammerCLIForemanTasks::Helper
283
294
 
295
+ validate_repo_name_requires_product_options
284
296
  resource :repositories, :upload_content
285
297
  command_name "upload-content"
286
298
  CONTENT_CHUNK_SIZE = 2_500_000 # bytes to make sure it's lower than django's default 2621440
@@ -461,9 +473,10 @@ module HammerCLIKatello
461
473
  # rubocop:enable ClassLength
462
474
 
463
475
  class RemoveContentCommand < HammerCLIKatello::SingleResourceCommand
464
- include RepositoryScopedToProduct
476
+ extend RepositoryScopedToProduct
465
477
  include OrganizationOptions
466
478
 
479
+ validate_repo_name_requires_product_options
467
480
  action :remove_content
468
481
  command_name "remove-content"
469
482
  desc _("Remove content from a repository")
@@ -487,9 +500,10 @@ module HammerCLIKatello
487
500
 
488
501
  class ExportCommand < HammerCLIKatello::SingleResourceCommand
489
502
  include HammerCLIForemanTasks::Async
490
- include RepositoryScopedToProduct
491
503
  include OrganizationOptions
504
+ extend RepositoryScopedToProduct
492
505
 
506
+ validate_repo_name_requires_product_options
493
507
  action :export
494
508
  command_name "export"
495
509
  desc _("Export content from a repository to the configured directory")
@@ -1,8 +1,8 @@
1
1
  module HammerCLIKatello
2
2
  module RepositoryScopedToProduct
3
- def self.included(base)
4
- base.validate_options do
5
- any(:option_product_name, :option_product_id).required if option(:option_name).exist?
3
+ def validate_repo_name_requires_product_options(name_option = :option_name)
4
+ validate_options do
5
+ any(:option_product_name, :option_product_id).required if option(name_option).exist?
6
6
  end
7
7
  end
8
8
  end
@@ -4,6 +4,11 @@ module HammerCLIKatello
4
4
  module SearchOptionsCreators
5
5
  include HammerCLIKatello::ForemanSearchOptionsCreators
6
6
 
7
+ def create_module_streams_search_options(options, mode = nil)
8
+ create_search_options_without_katello_api(options, api.resource(:module_streams), mode)
9
+ .merge(create_search_options(options, api.resource(:module_streams), mode))
10
+ end
11
+
7
12
  def create_file_units_search_options(options, mode = nil)
8
13
  create_search_options_without_katello_api(options, api.resource(:file_units), mode)
9
14
  .merge(create_search_options(options, api.resource(:file_units), mode))
@@ -87,12 +92,15 @@ module HammerCLIKatello
87
92
  search_options
88
93
  end
89
94
 
90
- def create_search_options_with_katello_api(options, resource, _mode = nil)
95
+ def create_search_options_with_katello_api(options, resource, mode = nil)
91
96
  search_options = {}
92
97
  searchables(resource).each do |s|
93
98
  value = options[HammerCLI.option_accessor_name(s.name.to_s)]
94
- if value
99
+ values = options[HammerCLI.option_accessor_name(s.plural_name.to_s)]
100
+ if value && [:single, nil].include?(mode)
95
101
  search_options.update(s.name.to_s => value.to_s)
102
+ elsif values && [:multi, nil].include?(mode)
103
+ values.each { |v| search_options.update(s.name.to_s => v.to_s) }
96
104
  end
97
105
  end
98
106
  search_options