hammer_cli_katello 0.1.3 → 0.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.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/lib/hammer_cli_katello.rb +1 -0
  3. data/lib/hammer_cli_katello/content_view.rb +1 -1
  4. data/lib/hammer_cli_katello/filter.rb +19 -0
  5. data/lib/hammer_cli_katello/filter_rule.rb +0 -10
  6. data/lib/hammer_cli_katello/host_extensions.rb +2 -0
  7. data/lib/hammer_cli_katello/id_name_options_validator.rb +73 -0
  8. data/lib/hammer_cli_katello/package.rb +2 -0
  9. data/lib/hammer_cli_katello/repository.rb +17 -5
  10. data/lib/hammer_cli_katello/version.rb +1 -1
  11. data/test/functional/content_view/create_test.rb +0 -3
  12. data/test/functional/content_view/filter/delete_test.rb +93 -0
  13. data/test/functional/content_view/filter/info_test.rb +92 -0
  14. data/test/functional/content_view/filter/list_test.rb +98 -0
  15. data/test/functional/content_view/filter/update_test.rb +93 -0
  16. data/test/functional/filter_rule/create_test.rb +0 -79
  17. data/test/functional/host/extensions/data/host.json +4 -2
  18. data/test/functional/host/extensions/info_test.rb +3 -1
  19. data/test/functional/lifecycle_environment/create_test.rb +14 -0
  20. data/test/functional/lifecycle_environment/list_test.rb +38 -0
  21. data/test/functional/lifecycle_environment/update_test.rb +14 -0
  22. data/test/functional/organization/organization_helpers.rb +2 -2
  23. data/test/functional/package/list_test.rb +48 -0
  24. data/test/functional/repository/delete_test.rb +101 -0
  25. data/test/functional/repository/upload_test.rb +43 -0
  26. data/test/unit/id_name_options_validator_test.rb +96 -0
  27. metadata +26 -13
  28. data/test/functional/filter_rule/delete_test.rb +0 -104
  29. data/test/functional/filter_rule/info_test.rb +0 -104
  30. data/test/functional/filter_rule/list_test.rb +0 -91
  31. data/test/functional/filter_rule/update_test.rb +0 -104
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d7777a95f65993c11aafcdf3e93bd4e62e05a71c
4
- data.tar.gz: 10751c77ff38e730bd28edf8a393387ae5ac4551
3
+ metadata.gz: 8ee67377eb8631f27bc3ac6fb8893aa4f3e19cd6
4
+ data.tar.gz: 3aa751e158e61a5e65854d7423c280ff9be55493
5
5
  SHA512:
6
- metadata.gz: 483606e3bfe638f29d98185eb2dc38f2a0704f3e16de14cc4e89aff942f1ad8ea7f5fd60a7939ea17a91a57b56449e3dd3618c9e2e009b92d048dc8774872342
7
- data.tar.gz: b043a18647859bba0dadfa79103085f23a3de85a2fb332cff57b082ed20efd3b1b86a69b705148110f0028d7b682dade57ef6fce691b27c681b147831b15be18
6
+ metadata.gz: 8af86a66650da765757af0c2ea262f08bbdeadfd27f88e5bb8dcac35f9318f7badfd7885bb0d844010d860bf636de433ffd032402de81e3774d635e4b6f86d76
7
+ data.tar.gz: b7db6c9f52337875421b12022cb1a2ea4dddfce2e88707c5035636395cfa8cfbe70ad1ef71430d2bf0dc6446e0cd22cfaf5eacfba16e6d58ec903125a80d78c5
@@ -25,6 +25,7 @@ module HammerCLIKatello
25
25
  require "hammer_cli_katello/version"
26
26
  require 'hammer_cli_katello/id_resolver'
27
27
  require 'hammer_cli_katello/capsule'
28
+ require 'hammer_cli_katello/id_name_options_validator'
28
29
 
29
30
  # commands
30
31
  HammerCLI::MainCommand.lazy_subcommand("activation-key", _("Manipulate activation keys."),
@@ -207,7 +207,7 @@ module HammerCLIKatello
207
207
  success_message _("Content view objects are being removed task %{id}")
208
208
  failure_message _("Could not remove objects from content view")
209
209
 
210
- build_options :without => %w(content_view_version_ids environment_ids)
210
+ build_options :without => %w(content_view_version_ids environment_ids)
211
211
  end
212
212
 
213
213
  class AddContentViewVersionCommand < HammerCLIKatello::AddAssociatedCommand
@@ -7,6 +7,9 @@ module HammerCLIKatello
7
7
  desc 'View and manage filters'
8
8
 
9
9
  class ListCommand < HammerCLIKatello::ListCommand
10
+ include OrganizationOptions
11
+ extend IdNameOptionsValidator
12
+
10
13
  output do
11
14
  field :id, _("Filter ID")
12
15
  field :name, _("Name")
@@ -15,9 +18,13 @@ module HammerCLIKatello
15
18
  end
16
19
 
17
20
  build_options
21
+ validate_id_or_name_with_parent :content_view
18
22
  end
19
23
 
20
24
  class InfoCommand < HammerCLIKatello::InfoCommand
25
+ include OrganizationOptions
26
+ extend IdNameOptionsValidator
27
+
21
28
  output do
22
29
  field :id, _("Filter ID")
23
30
  field :name, _("Name")
@@ -47,6 +54,8 @@ module HammerCLIKatello
47
54
  end
48
55
 
49
56
  build_options :without => [:content_view_id]
57
+ validate_id_or_name_with_parent parent: :content_view
58
+ validate_id_or_name_with_parent :content_view, required: false
50
59
  end
51
60
 
52
61
  class CreateCommand < HammerCLIKatello::CreateCommand
@@ -68,17 +77,27 @@ module HammerCLIKatello
68
77
  end
69
78
 
70
79
  class UpdateCommand < HammerCLIKatello::UpdateCommand
80
+ include OrganizationOptions
81
+ extend IdNameOptionsValidator
82
+
71
83
  success_message _("Filter updated")
72
84
  failure_message _("Could not update the filter")
73
85
 
74
86
  build_options :without => [:content_view_id]
87
+ validate_id_or_name_with_parent parent: :content_view
88
+ validate_id_or_name_with_parent :content_view, required: false
75
89
  end
76
90
 
77
91
  class DeleteCommand < HammerCLIKatello::DeleteCommand
92
+ include OrganizationOptions
93
+ extend IdNameOptionsValidator
94
+
78
95
  success_message _("Filter deleted")
79
96
  failure_message _("Could not delete the filter")
80
97
 
81
98
  build_options :without => [:content_view_id]
99
+ validate_id_or_name_with_parent parent: :content_view
100
+ validate_id_or_name_with_parent :content_view, required: false
82
101
  end
83
102
 
84
103
  HammerCLIKatello::AssociatingCommands::Repository.extend_command(self)
@@ -5,8 +5,6 @@ module HammerCLIKatello
5
5
  desc 'View and manage filter rules'
6
6
 
7
7
  class ListCommand < HammerCLIKatello::ListCommand
8
- include OrganizationOptions
9
-
10
8
  output do
11
9
  field :id, _("Rule ID")
12
10
  field :content_view_filter_id, _("Filter ID")
@@ -24,8 +22,6 @@ module HammerCLIKatello
24
22
  end
25
23
 
26
24
  class InfoCommand < HammerCLIKatello::InfoCommand
27
- include OrganizationOptions
28
-
29
25
  output do
30
26
  field :id, _("Rule ID")
31
27
  field :content_view_filter_id, _("Filter ID")
@@ -47,8 +43,6 @@ module HammerCLIKatello
47
43
  end
48
44
 
49
45
  class CreateCommand < HammerCLIKatello::CreateCommand
50
- include OrganizationOptions
51
-
52
46
  success_message _("Filter rule created")
53
47
  failure_message _("Could not create the filter rule")
54
48
 
@@ -64,8 +58,6 @@ module HammerCLIKatello
64
58
  end
65
59
 
66
60
  class UpdateCommand < HammerCLIKatello::UpdateCommand
67
- include OrganizationOptions
68
-
69
61
  success_message _("Filter rule updated")
70
62
  failure_message _("Could not update the filter rule")
71
63
 
@@ -73,8 +65,6 @@ module HammerCLIKatello
73
65
  end
74
66
 
75
67
  class DeleteCommand < HammerCLIKatello::DeleteCommand
76
- include OrganizationOptions
77
-
78
68
  success_message _("Filter rule deleted")
79
69
  failure_message _("Could not delete the filter rule")
80
70
 
@@ -21,6 +21,8 @@ module HammerCLIKatello
21
21
  from :content_facet_attributes do
22
22
  field :content_view_name, _('Content View')
23
23
  field :lifecycle_environment_name, _('Lifecycle Environment')
24
+ field :applicable_package_count, _('Applicable Packages')
25
+ field :upgradable_package_count, _('Upgradable Packages')
24
26
 
25
27
  label _('Applicable Errata') do
26
28
  from :errata_counts do
@@ -0,0 +1,73 @@
1
+ module HammerCLIKatello
2
+ module IdNameOptionsValidator
3
+ # This is a method that requires:
4
+ # 1. either name or id has been supplied
5
+ # 2. if name is supplied, parent id/name/etc is also required
6
+ #
7
+ # Normally the parent will be organization as with products, content views,
8
+ # etc but this could also apply to repos for example whose names are unique
9
+ # per product
10
+ #
11
+ # Some examples:
12
+ #
13
+ # validate_id_or_name_with_parent
14
+ # validate_id_or_name_with_parent :content_view
15
+ # validate_id_or_name_with_parent :repository, parent: 'product', required: false
16
+ # validate_id_or_name_with_parent :content_view, parent: {organization: ['id', 'name']}
17
+ def validate_id_or_name_with_parent(record_name = nil, parent: 'organization', required: true)
18
+ child_options = IdNameOptionsValidator.build_child_options(record_name)
19
+ parent_options = IdNameOptionsValidator.build_parent_options(parent)
20
+
21
+ validate_options do
22
+ any(*child_options).required if required
23
+
24
+ if (name_option = child_options.detect { |opt| opt.end_with?('_name') }) &&
25
+ option(name_option).exist?
26
+ any(*parent_options).required
27
+ end
28
+ end
29
+ end
30
+
31
+ # This method simply checks that either id or name is supplied
32
+ #
33
+ # Some examples:
34
+ #
35
+ # # checks for a --id or --name option
36
+ # validate_id_or_name
37
+ # # checks for --content-view-id or --content-view-name
38
+ # validate_id_or_name :content_view
39
+ def validate_id_or_name(record_name = nil)
40
+ child_options = IdNameOptionsValidator.build_child_options(record_name)
41
+
42
+ validate_options do
43
+ any(*child_options).required
44
+ end
45
+ end
46
+
47
+ def self.build_child_options(record_name)
48
+ if record_name.nil?
49
+ %w(option_id option_name)
50
+ else
51
+ IdNameOptionsValidator.build_options(record_name, %w(id name))
52
+ end
53
+ end
54
+
55
+ def self.build_parent_options(parent)
56
+ if parent.is_a?(String) || parent.is_a?(Symbol)
57
+ opts = parent.to_s == 'organization' ? %w(id name label) : %w(id name)
58
+ elsif parent.is_a?(Hash)
59
+ parent, opts = parent.first.to_a
60
+ else
61
+ raise "Unkown parent class: #{parent.class} for #{parent}"
62
+ end
63
+
64
+ IdNameOptionsValidator.build_options(parent, opts)
65
+ end
66
+
67
+ def self.build_options(record_name, options)
68
+ options.map do |opt|
69
+ "option_#{record_name}_#{opt}"
70
+ end
71
+ end
72
+ end
73
+ end
@@ -9,6 +9,8 @@ module HammerCLIKatello
9
9
  end
10
10
 
11
11
  build_options do |o|
12
+ o.without(:repository_id)
13
+ o.expand.except(:repositories)
12
14
  o.expand.including(:products, :organizations, :content_views)
13
15
  end
14
16
  end
@@ -172,6 +172,7 @@ module HammerCLIKatello
172
172
 
173
173
  class DeleteCommand < HammerCLIKatello::DeleteCommand
174
174
  include RepositoryScopedToProduct
175
+ include OrganizationOptions
175
176
 
176
177
  success_message _("Repository deleted")
177
178
  failure_message _("Could not delete the Repository")
@@ -194,8 +195,10 @@ module HammerCLIKatello
194
195
 
195
196
  if File.directory?(fullpath)
196
197
  Dir["#{fullpath}/*"]
197
- else
198
+ elsif File.exist?(fullpath)
198
199
  [fullpath]
200
+ else
201
+ Dir[fullpath]
199
202
  end
200
203
  end
201
204
  end
@@ -206,7 +209,14 @@ module HammerCLIKatello
206
209
 
207
210
  def execute
208
211
  @failure = false
209
- option_content.each do |file_path|
212
+ files = option_content
213
+
214
+ if files.length.zero?
215
+ output.print_error _("Could not find any files matching PATH")
216
+ return HammerCLI::EX_NOINPUT
217
+ end
218
+
219
+ files.each do |file_path|
210
220
  File.open(file_path, 'rb') { |file| upload_file file }
211
221
  end
212
222
 
@@ -223,7 +233,9 @@ module HammerCLIKatello
223
233
  build_options(:without => [:content]) do |o|
224
234
  o.expand.including(:products, :organizations)
225
235
  end
226
- option "--path", "PATH", _("Upload file or directory of files as content for a repository"),
236
+ option "--path", "PATH", _("Upload file, directory of files, or glob of files " \
237
+ "as content for a repository.\n" \
238
+ "Globs must be escaped by single or double quotes."),
227
239
  :attribute_name => :option_content,
228
240
  :required => true, :format => BinaryPath.new
229
241
 
@@ -251,8 +263,8 @@ module HammerCLIKatello
251
263
  print_message _("Successfully uploaded file '%s'.") % filename
252
264
  rescue
253
265
  @failure = true
254
- print_message _("Failed to upload file '%s' to repository. Please check "\
255
- "the file and try again.") % filename
266
+ output.print_error _("Failed to upload file '%s' to repository. Please check "\
267
+ "the file and try again.") % filename
256
268
  ensure
257
269
  content_upload_resource.call(:destroy, :repository_id => get_identifier, :id => upload_id)
258
270
  end
@@ -1,5 +1,5 @@
1
1
  module HammerCLIKatello
2
2
  def self.version
3
- @version ||= Gem::Version.new('0.1.3')
3
+ @version ||= Gem::Version.new('0.2.0')
4
4
  end
5
5
  end
@@ -1,8 +1,5 @@
1
1
  require_relative '../test_helper'
2
2
 
3
- # Workaround for issue #14289
4
- require 'hammer_cli_katello/content_view_puppet_module'
5
-
6
3
  describe 'content-view create' do
7
4
  before do
8
5
  @cmd = %w(content-view create)
@@ -0,0 +1,93 @@
1
+ require File.join(File.dirname(__FILE__), '../../test_helper')
2
+ require File.join(File.dirname(__FILE__), '../content_view_helpers')
3
+ require File.join(File.dirname(__FILE__), '../../organization/organization_helpers')
4
+
5
+ module HammerCLIForeman
6
+ describe DeleteCommand do
7
+ include ContentViewHelpers
8
+ include OrganizationHelpers
9
+
10
+ before do
11
+ @cmd = %w(content-view filter delete)
12
+ end
13
+
14
+ it 'accepts filter id' do
15
+ params = ['--id=1']
16
+
17
+ api_expects(:content_view_filters, :destroy) do |par|
18
+ par['id'] == '1'
19
+ end
20
+
21
+ run_cmd(@cmd + params)
22
+ end
23
+
24
+ it 'accepts filter name, content view name, and org name' do
25
+ params = ['--name=scanner', '--content-view=darkly', '--organization=pkd']
26
+
27
+ expect_organization_search('pkd', 1)
28
+ expect_content_view_search(1, 'darkly', 1)
29
+ expect_content_view_search(1, 'darkly', 1) # redmine #15930
30
+
31
+ ex = api_expects(:content_view_filters, :index, 'Content view filters list') do |par|
32
+ par['content_view_id'] == 1 && par['name'] == 'scanner'
33
+ end
34
+ ex.returns(index_response([{'id' => '1'}]))
35
+
36
+ api_expects(:content_view_filters, :destroy) do |par|
37
+ par['id'] == '1'
38
+ end
39
+
40
+ run_cmd(@cmd + params)
41
+ end
42
+
43
+ it 'accepts filter name, content view name, and org label' do
44
+ params = ['--name=scanner', '--content-view=darkly', '--organization-label=pkd']
45
+
46
+ expect_organization_search('pkd', 1, field: 'label')
47
+ expect_content_view_search(1, 'darkly', 1)
48
+ expect_content_view_search(1, 'darkly', 1) # redmine #15930
49
+
50
+ ex = api_expects(:content_view_filters, :index, 'Content view filters list') do |par|
51
+ par['content_view_id'] == 1 && par['name'] == 'scanner'
52
+ end
53
+ ex.returns(index_response([{'id' => '1'}]))
54
+
55
+ api_expects(:content_view_filters, :destroy) do |par|
56
+ par['id'] == '1'
57
+ end
58
+
59
+ run_cmd(@cmd + params)
60
+ end
61
+
62
+ it 'accepts filter name, content view name, and org id' do
63
+ params = ['--name=scanner', '--content-view=darkly', '--organization-id=1']
64
+
65
+ expect_content_view_search('1', 'darkly', 1)
66
+ expect_content_view_search('1', 'darkly', 1) # redmine #15930
67
+
68
+ ex = api_expects(:content_view_filters, :index, 'Content view filters list') do |par|
69
+ par['content_view_id'] == 1 && par['name'] == 'scanner'
70
+ end
71
+ ex.returns(index_response([{'id' => '1'}]))
72
+
73
+ api_expects(:content_view_filters, :destroy) do |par|
74
+ par['id'] == '1'
75
+ end
76
+
77
+ run_cmd(@cmd + params)
78
+ end
79
+
80
+ it 'requires organization name or id if content view name is supplied' do
81
+ params = ["--name=high-castle", "--content-view=grasshopper"]
82
+ expected_result = usage_error_result(
83
+ @cmd,
84
+ 'At least one of options --organization-id, --organization, --organization-label ' \
85
+ 'is required',
86
+ 'Could not delete the filter'
87
+ )
88
+ api_expects_no_call
89
+ result = run_cmd(@cmd + params)
90
+ assert_cmd(expected_result, result)
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,92 @@
1
+ require File.join(File.dirname(__FILE__), '../../test_helper')
2
+ require File.join(File.dirname(__FILE__), '../content_view_helpers')
3
+ require File.join(File.dirname(__FILE__), '../../organization/organization_helpers')
4
+
5
+ module HammerCLIForeman
6
+ describe InfoCommand do
7
+ include ContentViewHelpers
8
+ include OrganizationHelpers
9
+
10
+ before do
11
+ @cmd = %w(content-view filter info)
12
+ end
13
+
14
+ it 'accepts filter id' do
15
+ params = ['--id=1']
16
+
17
+ api_expects(:content_view_filters, :show) do |par|
18
+ par['id'] == '1'
19
+ end
20
+
21
+ run_cmd(@cmd + params)
22
+ end
23
+
24
+ it 'accepts filter name, content view name, and org name' do
25
+ params = ['--name=scanner', '--content-view=darkly', '--organization=pkd']
26
+
27
+ expect_organization_search('pkd', 1)
28
+ expect_content_view_search(1, 'darkly', 1)
29
+ expect_content_view_search(1, 'darkly', 1) # redmine #15930
30
+
31
+ ex = api_expects(:content_view_filters, :index, 'Content view filters list') do |par|
32
+ par['content_view_id'] == 1 && par['name'] == 'scanner'
33
+ end
34
+ ex.returns(index_response([{'id' => '1'}]))
35
+
36
+ api_expects(:content_view_filters, :show) do |par|
37
+ par['id'] == '1'
38
+ end
39
+
40
+ run_cmd(@cmd + params)
41
+ end
42
+
43
+ it 'accepts filter name, content view name, and org label' do
44
+ params = ['--name=scanner', '--content-view=darkly', '--organization-label=pkd']
45
+
46
+ expect_organization_search('pkd', 1, field: 'label')
47
+ expect_content_view_search(1, 'darkly', 1)
48
+ expect_content_view_search(1, 'darkly', 1) # redmine #15930
49
+
50
+ ex = api_expects(:content_view_filters, :index, 'Content view filters list') do |par|
51
+ par['content_view_id'] == 1 && par['name'] == 'scanner'
52
+ end
53
+ ex.returns(index_response([{'id' => '1'}]))
54
+
55
+ api_expects(:content_view_filters, :show) do |par|
56
+ par['id'] == '1'
57
+ end
58
+
59
+ run_cmd(@cmd + params)
60
+ end
61
+
62
+ it 'accepts filter name, content view name, and org id' do
63
+ params = ['--name=scanner', '--content-view=darkly', '--organization-id=1']
64
+
65
+ expect_content_view_search('1', 'darkly', 1)
66
+ expect_content_view_search('1', 'darkly', 1) # redmine #15930
67
+
68
+ ex = api_expects(:content_view_filters, :index, 'Content view filters list') do |par|
69
+ par['content_view_id'] == 1 && par['name'] == 'scanner'
70
+ end
71
+ ex.returns(index_response([{'id' => '1'}]))
72
+
73
+ api_expects(:content_view_filters, :show) do |par|
74
+ par['id'] == '1'
75
+ end
76
+
77
+ run_cmd(@cmd + params)
78
+ end
79
+
80
+ it 'requires organization name or id if content view name is supplied' do
81
+ params = ["--name=high-castle", "--content-view=grasshopper"]
82
+ expected_result = usage_error_result(
83
+ @cmd,
84
+ 'At least one of options --organization-id, --organization, --organization-label ' \
85
+ 'is required'
86
+ )
87
+ api_expects_no_call
88
+ result = run_cmd(@cmd + params)
89
+ assert_cmd(expected_result, result)
90
+ end
91
+ end
92
+ end