hammer_cli_foreman 3.2.0 → 3.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/config/foreman.yml +4 -0
  3. data/doc/configuration.md +30 -0
  4. data/doc/release_notes.md +10 -0
  5. data/lib/hammer_cli_foreman/api/authenticator.rb +9 -0
  6. data/lib/hammer_cli_foreman/api/connection.rb +2 -0
  7. data/lib/hammer_cli_foreman/api/negotiate_auth.rb +36 -0
  8. data/lib/hammer_cli_foreman/api/session_authenticator_wrapper.rb +6 -2
  9. data/lib/hammer_cli_foreman/api.rb +2 -1
  10. data/lib/hammer_cli_foreman/auth.rb +13 -0
  11. data/lib/hammer_cli_foreman/commands.rb +5 -1
  12. data/lib/hammer_cli_foreman/exception_handler.rb +26 -0
  13. data/lib/hammer_cli_foreman/partition_table.rb +30 -0
  14. data/lib/hammer_cli_foreman/report_template.rb +15 -0
  15. data/lib/hammer_cli_foreman/smart_proxy.rb +11 -0
  16. data/lib/hammer_cli_foreman/template.rb +30 -0
  17. data/lib/hammer_cli_foreman/version.rb +1 -1
  18. data/locale/ca/LC_MESSAGES/hammer-cli-foreman.mo +0 -0
  19. data/locale/de/LC_MESSAGES/hammer-cli-foreman.mo +0 -0
  20. data/locale/en/LC_MESSAGES/hammer-cli-foreman.mo +0 -0
  21. data/locale/en_GB/LC_MESSAGES/hammer-cli-foreman.mo +0 -0
  22. data/locale/es/LC_MESSAGES/hammer-cli-foreman.mo +0 -0
  23. data/locale/fr/LC_MESSAGES/hammer-cli-foreman.mo +0 -0
  24. data/locale/it/LC_MESSAGES/hammer-cli-foreman.mo +0 -0
  25. data/locale/ja/LC_MESSAGES/hammer-cli-foreman.mo +0 -0
  26. data/locale/ko/LC_MESSAGES/hammer-cli-foreman.mo +0 -0
  27. data/locale/pt_BR/LC_MESSAGES/hammer-cli-foreman.mo +0 -0
  28. data/locale/ru/LC_MESSAGES/hammer-cli-foreman.mo +0 -0
  29. data/locale/zh_CN/LC_MESSAGES/hammer-cli-foreman.mo +0 -0
  30. data/locale/zh_TW/LC_MESSAGES/hammer-cli-foreman.mo +0 -0
  31. data/test/functional/partition_table_test.rb +63 -0
  32. data/test/functional/report_template_test.rb +24 -0
  33. data/test/functional/template_test.rb +60 -0
  34. metadata +49 -46
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 87407ba2c43be96a076220e9500050007447596f6d14024932fa85a7c9046f20
4
- data.tar.gz: 2987c54ab5fef04cc45629754a55c62d16a252b6cd950e7de461a989712a79ca
3
+ metadata.gz: 70a45953e142e7d3a67ee81e99bb5cc6fccaf179d2a61e44922f3b809196a178
4
+ data.tar.gz: 6c958ff14e311eef47ac379a41ceb45cbabe7f7ed34b3d28c64c40fe963f2ca5
5
5
  SHA512:
6
- metadata.gz: 030d7c3ff4d19fb767e771c123b8cb0de2a6166cec3ec2012b689f7d920d3049a234f7900ee43141c2af97ce0d5aaf403ea9a9f3962072bdffc181126de57e70
7
- data.tar.gz: 6acaf9a9b06c59b4c7db28b73bdc7dfe31170ac3b621adb2b85a5a501090e310a4fcfc703e2b6dc48170a693ff675507b8b9c478a8c344ff7793bfe778a8f3f3
6
+ metadata.gz: 6d436e24f99cc80f70aff4ad2c0436a92d63e8b60b5f1aa1ebb787e0fe202404c686fe78397ae16ae9bb3f2261834f8a02db39417a2511fd562c316344933d7a
7
+ data.tar.gz: 828772047e91923c3b6ac365fa942d381483988ed4c7303a1021d560e73d4f591d1656613ef45916cdc565fa3b7989a6b0f577c655c5624f5a5f8e9bdc82f24b
data/config/foreman.yml CHANGED
@@ -29,6 +29,10 @@
29
29
  #:oidc_client_id: example-client-id
30
30
  #:oidc_redirect_uri: urn:ietf:wg:oauth:2.0:oob
31
31
 
32
+ # Negotiate (Kerberos) Auth:
33
+ # User needs to run kinit before using hammer (or initiate kerberos keyring in another way).
34
+ #:default_auth_type: 'Negotiate_Auth'
35
+
32
36
  # Enable using sessions
33
37
  # When sessions are enabled, hammer ignores credentials stored in the config file
34
38
  # and asks for them interactively at the begining of each session.
data/doc/configuration.md CHANGED
@@ -49,3 +49,33 @@ Please note that when you turn sessions on, the credentials stored in your confi
49
49
 
50
50
  The default session timeout is 1 hour. This can be changed in the Foreman: `Settings > Authentication > Idle timeout`
51
51
  When the session expires hammer will prompt for username and password again.
52
+
53
+ ### Negotiate (Kerberos) auth
54
+
55
+ This implements Kerberos authentication, usually implemented in FreeIPA or Microsoft Active Directory.
56
+ For this to work, the host that we are trying to use hammer on, needs to have realm already configured on this host.
57
+ This can be achieved through `realm join`, please refer to that command for more info.
58
+
59
+ **Sessions needs to be enabled**
60
+
61
+ `~/.hammer/cli.modules.d/foreman.yml`
62
+ ```yaml
63
+ :foreman:
64
+ :default_auth_type: 'Negotiate_Auth'
65
+ :use_sessions: true
66
+ ```
67
+
68
+ ```bash
69
+ # To initiate the kerberos keyring (this might be already done on login)
70
+ $ kinit <kerb_user>
71
+ # Enter your password
72
+ $ klist
73
+ Ticket cache: KEYRING:persistent:1000:1000
74
+ Default principal: kerb_user@REALM.EXAMPLE.COM
75
+
76
+ # use hammer as usuall, it will negotiate your auth on the first request
77
+ hammer ...
78
+
79
+ # or if you do not have negotiate as default auth, initiate the auth manually
80
+ hammer auth login negotiate
81
+ ```
data/doc/release_notes.md CHANGED
@@ -1,5 +1,15 @@
1
1
  Release notes
2
2
  =============
3
+ ### 3.3.0 (2022-05-10)
4
+ * Add kerberos negotiate auth support ([PR #555](https://github.com/theforeman/hammer-cli-foreman/pull/555)), [#8923](http://projects.theforeman.org/issues/8923)
5
+ * Pin mocha gem to < 1.14.0
6
+ * Force api docs checksum check, [#28283](http://projects.theforeman.org/issues/28283)
7
+ * Add template report-remplate and partition-table export command ([PR #595](https://github.com/theforeman/hammer-cli-foreman/pull/595)), [#34503](http://projects.theforeman.org/issues/34503)
8
+ * Add template import and partition-table import commands ([PR #596](https://github.com/theforeman/hammer-cli-foreman/pull/596)), [#22692](http://projects.theforeman.org/issues/22692)
9
+ * Add resource information to download command ([PR #598](https://github.com/theforeman/hammer-cli-foreman/pull/598)), [#34621](http://projects.theforeman.org/issues/34621)
10
+ * Add command to import ipv4 subnet from smart proxy ([PR #593](https://github.com/theforeman/hammer-cli-foreman/pull/593)), [#33255](http://projects.theforeman.org/issues/33255)
11
+ * Bump to 3.3.0-develop
12
+
3
13
  ### 3.2.0 (2022-02-10)
4
14
  * Domain update doesn't reset dns implicitly ([PR #591](https://github.com/theforeman/hammer-cli-foreman/pull/591)), [#34177](http://projects.theforeman.org/issues/34177)
5
15
  * Send filter's tax params only when required ([PR #592](https://github.com/theforeman/hammer-cli-foreman/pull/592)), [#34199](http://projects.theforeman.org/issues/34199)
@@ -13,6 +13,8 @@ module HammerCLIForeman
13
13
  void_auth
14
14
  elsif auth_type == AUTH_TYPES[:basic_auth]
15
15
  basic_auth
16
+ elsif auth_type == AUTH_TYPES[:negotiate]
17
+ negotiate_auth
16
18
  elsif auth_type == AUTH_TYPES[:oauth_password_grant]
17
19
  oauth_password_grant
18
20
  elsif auth_type == AUTH_TYPES[:oauth_authentication_code_grant]
@@ -43,6 +45,13 @@ module HammerCLIForeman
43
45
  end
44
46
  end
45
47
 
48
+ def negotiate_auth
49
+ return unless HammerCLIForeman::Sessions.enabled?
50
+
51
+ authenticator = NegotiateAuth.new(uri)
52
+ SessionAuthenticatorWrapper.new(authenticator, uri, auth_type)
53
+ end
54
+
46
55
  def oauth_password_grant
47
56
  return unless HammerCLIForeman::Sessions.enabled?
48
57
 
@@ -1,6 +1,7 @@
1
1
  require 'hammer_cli_foreman/api/session_authenticator_wrapper'
2
2
  require 'hammer_cli_foreman/api/authenticator'
3
3
  require 'hammer_cli_foreman/api/interactive_basic_auth'
4
+ require 'hammer_cli_foreman/api/negotiate_auth'
4
5
  require 'hammer_cli_foreman/api/oauth/authentication_code_grant'
5
6
  require 'hammer_cli_foreman/api/oauth/password_grant'
6
7
  require 'hammer_cli_foreman/api/void_auth'
@@ -10,6 +11,7 @@ module HammerCLIForeman
10
11
  CONNECTION_NAME = 'foreman'
11
12
  AUTH_TYPES = {
12
13
  basic_auth: 'Basic_Auth',
14
+ negotiate: 'Negotiate_Auth',
13
15
  oauth_authentication_code_grant: 'Oauth_Authentication_Code_Grant',
14
16
  oauth_password_grant: 'Oauth_Password_Grant'
15
17
  }.freeze
@@ -0,0 +1,36 @@
1
+ module HammerCLIForeman
2
+ module Api
3
+ class NegotiateAuth < ApipieBindings::Authenticators::Negotiate
4
+ def initialize(foreman_url, **options)
5
+ super("#{foreman_url}/users/extlogin", HammerCLI::SSLOptions.new.get_options(foreman_url).merge(options))
6
+ end
7
+
8
+ def user
9
+ _('current Kerberos user')
10
+ end
11
+
12
+ def session_id
13
+ auth_cookie&.delete_prefix('_session_id=')
14
+ end
15
+
16
+ def status
17
+ if system('klist')
18
+ _('No session, but there is an active Kerberos session, that will be used for negotiate login.')
19
+ else
20
+ _('There is no active Kerberos session. Have you run %s?') % 'kinit'
21
+ end
22
+ end
23
+
24
+ def error(ex)
25
+ super unless ex.is_a?(RestClient::Unauthorized)
26
+
27
+ message = _('Invalid username or password.')
28
+ begin
29
+ message = JSON.parse(ex.response.body)['error']['message']
30
+ rescue
31
+ end
32
+ UnauthorizedError.new(message)
33
+ end
34
+ end
35
+ end
36
+ end
@@ -24,6 +24,8 @@ module HammerCLIForeman
24
24
  def status
25
25
  if session.valid?
26
26
  _("Session exists, currently logged in as '%s'.") % session.user_name
27
+ elsif @authenticator.respond_to?(:status)
28
+ @authenticator.status
27
29
  else
28
30
  _('Using sessions, you are currently not logged in.')
29
31
  end
@@ -66,8 +68,10 @@ module HammerCLIForeman
66
68
  end
67
69
 
68
70
  def response(r)
69
- if (r.cookies['_session_id'] && r.code != 401)
70
- session.id = r.cookies['_session_id']
71
+ session_id = @authenticator.session_id if @authenticator.respond_to?(:session_id)
72
+ session_id ||= r.cookies['_session_id']
73
+ if session_id && r.code != 401
74
+ session.id = session_id
71
75
  session.user_name = @authenticator.user
72
76
  session.store
73
77
  end
@@ -7,4 +7,5 @@ module HammerCLIForeman
7
7
  end
8
8
  end
9
9
 
10
- HammerCLIForeman.init_api_connection
10
+ api = HammerCLIForeman.init_api_connection.api
11
+ api.update_cache(api.check_cache)
@@ -28,6 +28,19 @@ module HammerCLIForeman
28
28
  end
29
29
  end
30
30
 
31
+ class Negotiate < HammerCLI::AbstractCommand
32
+ extend HammerCLIForeman::Authenticate::Login
33
+
34
+ command_name('negotiate')
35
+ desc('negotiate the login credentials from the auth ticket (Kerberos)')
36
+
37
+ def execute
38
+ Negotiate.execute_with_params(AUTH_TYPES[:negotiate])
39
+ print_message(_("Successfully authenticated using negotiate auth, using the KEYRING principal."))
40
+ HammerCLI::EX_OK
41
+ end
42
+ end
43
+
31
44
  class Oauth < HammerCLI::AbstractCommand
32
45
  extend HammerCLIForeman::Authenticate::Login
33
46
 
@@ -744,13 +744,17 @@ module HammerCLIForeman
744
744
  response = send_request
745
745
  if option_path
746
746
  filepath = store_response(response)
747
- print_message(_('The response has been saved to %{path}s.'), {:path => filepath})
747
+ print_message(saved_response_message(filepath))
748
748
  else
749
749
  puts response.body
750
750
  end
751
751
  return HammerCLI::EX_OK
752
752
  end
753
753
 
754
+ def saved_response_message(filepath)
755
+ _("The response has been saved to %{path}.") % { path: filepath }
756
+ end
757
+
754
758
  def default_filename
755
759
  "Downloaded-#{Time.new.strftime("%Y-%m-%d")}.txt"
756
760
  end
@@ -12,6 +12,7 @@ module HammerCLIForeman
12
12
  [RestClient::UnprocessableEntity, :handle_unprocessable_entity],
13
13
  [RestClient::MovedPermanently, :handle_moved_permanently],
14
14
  [RestClient::BadRequest, :handle_bad_request],
15
+ [ApipieBindings::AuthenticatorError, :handle_authenticator_error],
15
16
  [HammerCLIForeman::Api::UnauthorizedError, :handle_foreman_unauthorized],
16
17
  [HammerCLIForeman::Api::SessionExpired, :handle_sesion_expired],
17
18
  [ArgumentError, :handle_argument_error],
@@ -112,6 +113,12 @@ module HammerCLIForeman
112
113
  HammerCLI::EX_DATAERR
113
114
  end
114
115
 
116
+ def handle_authenticator_error(e)
117
+ print_error authenticator_error_message(e)
118
+ log_full_error e.original_error
119
+ HammerCLI::EX_USAGE
120
+ end
121
+
115
122
  def ssl_cert_instructions
116
123
  host_url = HammerCLI::Settings.get(:_params, :host) || HammerCLI::Settings.get(:foreman, :host)
117
124
  uri = URI.parse(host_url)
@@ -147,6 +154,25 @@ module HammerCLIForeman
147
154
 
148
155
  private
149
156
 
157
+ def authenticator_error_message(e)
158
+ case e.type
159
+ when :negotiate then negotiation_error_message(e)
160
+ end
161
+ end
162
+
163
+ def negotiation_error_message(e)
164
+ case e.cause
165
+ when :configuration
166
+ _('Server misconfiguration detected') + "\n - " +
167
+ _('have you run installer with option %s?') % '--foreman-ipa-authentication=true' + "\n - " +
168
+ _('the user might come from a different authentication source') + "\n"
169
+ else
170
+ _('Could not authenticate using negotiation protocol') + "\n - " +
171
+ _('have you run %s (for Kerberos)?') % 'kinit' + "\n - " +
172
+ _('is the server down?') + "\n"
173
+ end
174
+ end
175
+
150
176
  def response_message(response)
151
177
  message = JSON.parse(response)["error"]["message"]
152
178
  "\n #{message}"
@@ -71,6 +71,36 @@ module HammerCLIForeman
71
71
  build_options
72
72
  end
73
73
 
74
+ class ImportCommand < HammerCLIForeman::Command
75
+ command_name "import"
76
+ action :import
77
+ option '--file', 'PATH', _('Path to a file that contains the template content including metadata'),
78
+ :attribute_name => :option_template, :format => HammerCLI::Options::Normalizers::File.new
79
+
80
+ validate_options do
81
+ all(:option_name, :option_template).required
82
+ end
83
+
84
+ success_message _("Import partition table template succeeded.")
85
+ failure_message _("Could not import partition table template")
86
+
87
+ build_options :without => [:template]
88
+ end
89
+
90
+ class ExportCommand < HammerCLIForeman::DownloadCommand
91
+ command_name "export"
92
+ action :export
93
+
94
+ def default_filename
95
+ "Partition Table Template-#{Time.new.strftime("%Y-%m-%d")}.txt"
96
+ end
97
+
98
+ def saved_response_message(filepath)
99
+ _("The partition table template has been saved to %{path}.") % { path: filepath }
100
+ end
101
+
102
+ build_options
103
+ end
74
104
 
75
105
  HammerCLIForeman::AssociatingCommands::OperatingSystem.extend_command(self)
76
106
 
@@ -148,6 +148,21 @@ module HammerCLIForeman
148
148
  build_options :without => [:template]
149
149
  end
150
150
 
151
+ class ExportCommand < HammerCLIForeman::DownloadCommand
152
+ command_name "export"
153
+ action :export
154
+
155
+ def default_filename
156
+ "Report Template-#{Time.new.strftime("%Y-%m-%d")}.txt"
157
+ end
158
+
159
+ def saved_response_message(filepath)
160
+ _("The report template has been saved to %{path}.") % { path: filepath }
161
+ end
162
+
163
+ build_options
164
+ end
165
+
151
166
  class ReportDataCommand < HammerCLIForeman::DownloadCommand
152
167
  command_name "report-data"
153
168
  action :report_data
@@ -73,6 +73,17 @@ module HammerCLIForeman
73
73
  build_options
74
74
  end
75
75
 
76
+ class ImportSubnetsCommand < HammerCLIForeman::Command
77
+
78
+ action :import_subnets
79
+
80
+ command_name "import-subnets"
81
+ success_message _("Import subnets succeeded.")
82
+ failure_message _("Could not import subnets")
83
+
84
+ build_options
85
+ end
86
+
76
87
  autoload_subcommands
77
88
  end
78
89
 
@@ -142,7 +142,37 @@ module HammerCLIForeman
142
142
  build_options
143
143
  end
144
144
 
145
+ class ImportCommand < HammerCLIForeman::Command
146
+ command_name "import"
147
+ action :import
148
+ option '--file', 'PATH', _('Path to a file that contains the template content including metadata'),
149
+ :attribute_name => :option_template, :format => HammerCLI::Options::Normalizers::File.new
145
150
 
151
+ validate_options do
152
+ all(:option_name, :option_template).required
153
+ end
154
+
155
+ success_message _("Import provisioning template succeeded.")
156
+ failure_message _("Could not import provisioning template")
157
+
158
+ build_options :without => [:template]
159
+ end
160
+
161
+ class ExportCommand < HammerCLIForeman::DownloadCommand
162
+ command_name "export"
163
+ action :export
164
+
165
+ def default_filename
166
+ "Template-#{Time.new.strftime("%Y-%m-%d")}.txt"
167
+ end
168
+
169
+ def saved_response_message(filepath)
170
+ _("The provisioning template has been saved to %{path}.") % { path: filepath }
171
+ end
172
+
173
+ build_options
174
+ end
175
+
146
176
  class BuildPXEDefaultCommand < HammerCLIForeman::Command
147
177
 
148
178
  action :build_pxe_default
@@ -1,5 +1,5 @@
1
1
  module HammerCLIForeman
2
2
  def self.version
3
- @version ||= Gem::Version.new "3.2.0"
3
+ @version ||= Gem::Version.new "3.3.0"
4
4
  end
5
5
  end
@@ -0,0 +1,63 @@
1
+ require File.join(File.dirname(__FILE__), 'test_helper')
2
+
3
+ describe 'partition-table' do
4
+ describe 'import' do
5
+ let(:template) do
6
+ {
7
+ 'id' => 1,
8
+ 'template' => 'Template content'
9
+ }
10
+ end
11
+ let(:cmd) { %w(partition-table import) }
12
+ let(:tempfile) { Tempfile.new('template') }
13
+
14
+ it 'requires --name and --file' do
15
+ params = ['--name=test']
16
+ api_expects_no_call
17
+ expected_result = usage_error_result(
18
+ cmd,
19
+ 'Options --name, --file are required.',
20
+ 'Could not import partition table template')
21
+ result = run_cmd(cmd + params)
22
+ assert_cmd(expected_result, result)
23
+ end
24
+
25
+ it 'import template' do
26
+ params = ['--name=test', "--file=#{tempfile.path}"]
27
+ tempfile.write('Template content')
28
+ tempfile.rewind
29
+ api_expects(:ptables, :import, 'Import partition table template').with_params(
30
+ 'ptable' => {
31
+ 'name' => 'test',
32
+ 'template' => 'Template content'
33
+ }).returns(template)
34
+
35
+ result = run_cmd(cmd + params)
36
+ assert_cmd(success_result("Import partition table template succeeded.\n"), result)
37
+ end
38
+ end
39
+
40
+ describe 'export' do
41
+ let(:cmd) { %w(partition-table export) }
42
+ let(:tempfile) { Tempfile.new('template', '/tmp') }
43
+ let(:params) { ['--id=1', '--path=/tmp'] }
44
+ let(:template_response) do
45
+ response = mock('TemplateResponse')
46
+ response.stubs(:code).returns(200)
47
+ response.stubs(:body).returns('Template content')
48
+ response.stubs(:headers).returns({:content_disposition => "filename=\"#{File.basename(tempfile.path)}\""})
49
+ response
50
+ end
51
+
52
+ it 'download template' do
53
+ api_expects(:ptables, :export, 'Export partition table template').with_params(
54
+ 'id' => '1').returns(template_response)
55
+
56
+ output = OutputMatcher.new("The partition table template has been saved to #{tempfile.path}")
57
+ expected_result = success_result(output)
58
+ result = run_cmd(cmd + params)
59
+ assert_cmd(expected_result, result)
60
+ assert_equal('Template content', tempfile.read)
61
+ end
62
+ end
63
+ end
@@ -384,6 +384,30 @@ describe 'report-template' do
384
384
  end
385
385
  end
386
386
 
387
+ describe 'export' do
388
+ let(:cmd) { %w(report-template export) }
389
+ let(:tempfile) { Tempfile.new('template', '/tmp') }
390
+ let(:params) { ['--id=1', '--path=/tmp'] }
391
+ let(:template_response) do
392
+ response = mock('TemplateResponse')
393
+ response.stubs(:code).returns(200)
394
+ response.stubs(:body).returns('Template content')
395
+ response.stubs(:headers).returns({:content_disposition => "filename=\"#{File.basename(tempfile.path)}\""})
396
+ response
397
+ end
398
+
399
+ it 'download template' do
400
+ api_expects(:report_templates, :export, 'Export report template').with_params(
401
+ 'id' => '1').returns(template_response)
402
+
403
+ output = OutputMatcher.new("The report template has been saved to #{tempfile.path}")
404
+ expected_result = success_result(output)
405
+ result = run_cmd(cmd + params)
406
+ assert_cmd(expected_result, result)
407
+ assert_equal('Template content', tempfile.read)
408
+ end
409
+ end
410
+
387
411
  describe 'report-data' do
388
412
  let(:cmd) { %w(report-template report-data) }
389
413
  let(:tempfile) { Tempfile.new('template', '/tmp') }
@@ -77,6 +77,66 @@ describe 'template' do
77
77
  end
78
78
  end
79
79
 
80
+ describe 'import' do
81
+ let(:template) do
82
+ {
83
+ 'id' => 1,
84
+ 'template' => 'Template content'
85
+ }
86
+ end
87
+ let(:cmd) { %w(template import) }
88
+ let(:tempfile) { Tempfile.new('template') }
89
+
90
+ it 'requires --name and --file' do
91
+ params = ['--name=test']
92
+ api_expects_no_call
93
+ expected_result = usage_error_result(
94
+ cmd,
95
+ 'Options --name, --file are required.',
96
+ 'Could not import provisioning template')
97
+ result = run_cmd(cmd + params)
98
+ assert_cmd(expected_result, result)
99
+ end
100
+
101
+ it 'import template' do
102
+ params = ['--name=test', "--file=#{tempfile.path}"]
103
+ tempfile.write('Template content')
104
+ tempfile.rewind
105
+ api_expects(:provisioning_templates, :import, 'Import template').with_params(
106
+ 'provisioning_template' => {
107
+ 'name' => 'test',
108
+ 'template' => 'Template content'
109
+ }).returns(template)
110
+
111
+ result = run_cmd(cmd + params)
112
+ assert_cmd(success_result("Import provisioning template succeeded.\n"), result)
113
+ end
114
+ end
115
+
116
+ describe 'export' do
117
+ let(:cmd) { %w(template export) }
118
+ let(:tempfile) { Tempfile.new('template', '/tmp') }
119
+ let(:params) { ['--id=1', '--path=/tmp'] }
120
+ let(:template_response) do
121
+ response = mock('TemplateResponse')
122
+ response.stubs(:code).returns(200)
123
+ response.stubs(:body).returns('Template content')
124
+ response.stubs(:headers).returns({:content_disposition => "filename=\"#{File.basename(tempfile.path)}\""})
125
+ response
126
+ end
127
+
128
+ it 'download template' do
129
+ api_expects(:provisioning_templates, :export, 'Export template').with_params(
130
+ 'id' => '1').returns(template_response)
131
+
132
+ output = OutputMatcher.new("The provisioning template has been saved to #{tempfile.path}")
133
+ expected_result = success_result(output)
134
+ result = run_cmd(cmd + params)
135
+ assert_cmd(expected_result, result)
136
+ assert_equal('Template content', tempfile.read)
137
+ end
138
+ end
139
+
80
140
  describe 'update' do
81
141
  before do
82
142
  @cmd = %w(template update)
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hammer_cli_foreman
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.2.0
4
+ version: 3.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tomáš Strachota
8
8
  - Martin Bačovský
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2022-02-10 00:00:00.000000000 Z
12
+ date: 2022-05-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: hammer_cli
@@ -17,28 +17,28 @@ dependencies:
17
17
  requirements:
18
18
  - - ">="
19
19
  - !ruby/object:Gem::Version
20
- version: 3.1.0
20
+ version: 3.3.0
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
25
  - - ">="
26
26
  - !ruby/object:Gem::Version
27
- version: 3.1.0
27
+ version: 3.3.0
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: apipie-bindings
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
32
  - - ">="
33
33
  - !ruby/object:Gem::Version
34
- version: 0.4.0
34
+ version: 0.5.0
35
35
  type: :runtime
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
39
  - - ">="
40
40
  - !ruby/object:Gem::Version
41
- version: 0.4.0
41
+ version: 0.5.0
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: rest-client
44
44
  requirement: !ruby/object:Gem::Requirement
@@ -75,12 +75,11 @@ dependencies:
75
75
  version: 2.2.1
76
76
  description: 'Foreman commands for Hammer CLI
77
77
 
78
- '
78
+ '
79
79
  email: tstracho@redhat.com
80
80
  executables: []
81
81
  extensions: []
82
82
  extra_rdoc_files:
83
- - doc/configuration.md
84
83
  - doc/name_id_resolution.md
85
84
  - doc/option_builder.md
86
85
  - doc/using_hammer_cli_foreman_command.md
@@ -88,6 +87,7 @@ extra_rdoc_files:
88
87
  - doc/host_create.md
89
88
  - doc/plugin.md
90
89
  - doc/testing.md
90
+ - doc/configuration.md
91
91
  - doc/release_notes.md
92
92
  - README.md
93
93
  files:
@@ -108,6 +108,7 @@ files:
108
108
  - lib/hammer_cli_foreman/api/authenticator.rb
109
109
  - lib/hammer_cli_foreman/api/connection.rb
110
110
  - lib/hammer_cli_foreman/api/interactive_basic_auth.rb
111
+ - lib/hammer_cli_foreman/api/negotiate_auth.rb
111
112
  - lib/hammer_cli_foreman/api/oauth/authentication_code_grant.rb
112
113
  - lib/hammer_cli_foreman/api/oauth/password_grant.rb
113
114
  - lib/hammer_cli_foreman/api/session_authenticator_wrapper.rb
@@ -267,6 +268,7 @@ files:
267
268
  - test/functional/model_test.rb
268
269
  - test/functional/operating_system_test.rb
269
270
  - test/functional/organization_test.rb
271
+ - test/functional/partition_table_test.rb
270
272
  - test/functional/personal_access_token_test.rb
271
273
  - test/functional/ping_test.rb
272
274
  - test/functional/realm_test.rb
@@ -345,7 +347,7 @@ homepage: https://github.com/theforeman/hammer-cli-foreman
345
347
  licenses:
346
348
  - GPL-3.0+
347
349
  metadata: {}
348
- post_install_message:
350
+ post_install_message:
349
351
  rdoc_options: []
350
352
  require_paths:
351
353
  - lib
@@ -361,7 +363,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
361
363
  version: '0'
362
364
  requirements: []
363
365
  rubygems_version: 3.1.2
364
- signing_key:
366
+ signing_key:
365
367
  specification_version: 4
366
368
  summary: Foreman commands for Hammer
367
369
  test_files:
@@ -379,61 +381,63 @@ test_files:
379
381
  - test/data/1.24/foreman_api.json
380
382
  - test/data/2.0/foreman_api.json
381
383
  - test/data/2.1/foreman_api.json
384
+ - test/data/README.md
382
385
  - test/data/2.4/foreman_api.json
383
386
  - test/data/2.5/foreman_api.json
384
- - test/data/README.md
385
387
  - test/data/3.1/foreman_api.json
386
388
  - test/functional/auth_source_test.rb
387
389
  - test/functional/commands/list_test.rb
388
- - test/functional/usergroup_test.rb
389
390
  - test/functional/hostgroup/create_test.rb
390
391
  - test/functional/hostgroup/update_test.rb
391
- - test/functional/personal_access_token_test.rb
392
- - test/functional/template_test.rb
392
+ - test/functional/architecture_test.rb
393
393
  - test/functional/compute_attribute_test.rb
394
- - test/functional/model_test.rb
394
+ - test/functional/ping_test.rb
395
+ - test/functional/user_test.rb
395
396
  - test/functional/ssh_keys_test.rb
396
397
  - test/functional/subnet/update_test.rb
397
398
  - test/functional/subnet/create_test.rb
398
399
  - test/functional/test_helper.rb
399
- - test/functional/filter_test.rb
400
- - test/functional/http_proxy_test.rb
400
+ - test/functional/location_test.rb
401
401
  - test/functional/media_test.rb
402
- - test/functional/registration_test.rb
402
+ - test/functional/partition_table_test.rb
403
+ - test/functional/personal_access_token_test.rb
404
+ - test/functional/report_template_test.rb
405
+ - test/functional/settings_test.rb
406
+ - test/functional/status_test.rb
403
407
  - test/functional/user_mail_notification_test.rb
404
- - test/functional/domain/create_test.rb
405
- - test/functional/domain/update_test.rb
406
- - test/functional/operating_system_test.rb
407
- - test/functional/compute_resource_test.rb
408
+ - test/functional/compute_profile_test.rb
409
+ - test/functional/realm_test.rb
410
+ - test/functional/usergroup_test.rb
408
411
  - test/functional/organization_test.rb
409
- - test/functional/report_template_test.rb
410
- - test/functional/user_test.rb
411
412
  - test/functional/virtual_machine_test.rb
413
+ - test/functional/compute_resource_test.rb
414
+ - test/functional/domain/create_test.rb
415
+ - test/functional/domain/update_test.rb
416
+ - test/functional/filter_test.rb
412
417
  - test/functional/host_test.rb
418
+ - test/functional/http_proxy_test.rb
413
419
  - test/functional/mail_notification_test.rb
414
- - test/functional/bookmark_test.rb
415
- - test/functional/location_test.rb
420
+ - test/functional/operating_system_test.rb
421
+ - test/functional/template_test.rb
416
422
  - test/functional/associating_commands_test.rb
417
423
  - test/functional/audit_test.rb
418
- - test/functional/ping_test.rb
419
- - test/functional/realm_test.rb
420
424
  - test/functional/role_test.rb
421
- - test/functional/status_test.rb
422
- - test/functional/architecture_test.rb
423
- - test/functional/compute_profile_test.rb
424
- - test/functional/settings_test.rb
425
+ - test/functional/bookmark_test.rb
426
+ - test/functional/model_test.rb
427
+ - test/functional/registration_test.rb
425
428
  - test/unit/api/void_auth_test.rb
426
429
  - test/unit/api/interactive_basic_auth_test.rb
427
430
  - test/unit/api/oauth/oauth_authentication_code_grant_test.rb
428
431
  - test/unit/api/oauth/oauth_password_grant_test.rb
429
432
  - test/unit/api/session_authenticator_wrapper_test.rb
430
433
  - test/unit/test_output_adapter.rb
431
- - test/unit/settings_test.rb
434
+ - test/unit/host_test.rb
432
435
  - test/unit/auth_source_ldap_test.rb
433
436
  - test/unit/config_report_test.rb
434
437
  - test/unit/compute_resource_test.rb
435
438
  - test/unit/data/test_api.json
436
439
  - test/unit/defaults_test.rb
440
+ - test/unit/id_resolver_test.rb
437
441
  - test/unit/external_usergroup_test.rb
438
442
  - test/unit/fact_test.rb
439
443
  - test/unit/helpers/fake_searchables.rb
@@ -442,26 +446,25 @@ test_files:
442
446
  - test/unit/image_test.rb
443
447
  - test/unit/location_test.rb
444
448
  - test/unit/messages_test.rb
449
+ - test/unit/mail_notification_test.rb
445
450
  - test/unit/option_sources/id_params_test.rb
446
451
  - test/unit/option_sources/ids_params_test.rb
447
452
  - test/unit/organization_test.rb
448
453
  - test/unit/output/formatters_test.rb
449
454
  - test/unit/common_parameter_test.rb
450
455
  - test/unit/realm_test.rb
451
- - test/unit/compute_profile_test.rb
452
- - test/unit/host_test.rb
456
+ - test/unit/settings_test.rb
457
+ - test/unit/usergroup_test.rb
453
458
  - test/unit/subnet_test.rb
454
459
  - test/unit/test_helper.rb
455
460
  - test/unit/user_test.rb
456
461
  - test/unit/param_filters_test.rb
457
- - test/unit/partition_table_test.rb
458
462
  - test/unit/role_test.rb
459
- - test/unit/hostgroup_test.rb
460
- - test/unit/id_resolver_test.rb
461
- - test/unit/mail_notification_test.rb
462
463
  - test/unit/model_test.rb
463
464
  - test/unit/operating_system_test.rb
464
465
  - test/unit/option_builders_test.rb
466
+ - test/unit/architecture_test.rb
467
+ - test/unit/commands_test.rb
465
468
  - test/unit/audit_test.rb
466
469
  - test/unit/auth_source_external.rb
467
470
  - test/unit/dependency_resolver_test.rb
@@ -469,13 +472,13 @@ test_files:
469
472
  - test/unit/filter_test.rb
470
473
  - test/unit/media_test.rb
471
474
  - test/unit/sessions_test.rb
472
- - test/unit/apipie_resource_mock.rb
473
- - test/unit/commands_test.rb
475
+ - test/unit/bookmark_test.rb
476
+ - test/unit/hostgroup_test.rb
474
477
  - test/unit/api_test.rb
475
- - test/unit/architecture_test.rb
476
- - test/unit/smart_proxy_test.rb
477
- - test/unit/usergroup_test.rb
478
+ - test/unit/apipie_resource_mock.rb
479
+ - test/unit/compute_profile_test.rb
480
+ - test/unit/partition_table_test.rb
478
481
  - test/unit/template_test.rb
479
- - test/unit/bookmark_test.rb
482
+ - test/unit/smart_proxy_test.rb
480
483
  - test/unit/domain_test.rb
481
484
  - test/test_helper.rb