hammer_cli_katello 0.23.2 → 0.24.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/hammer_cli_katello.rb +14 -2
- data/lib/hammer_cli_katello/content_export.rb +72 -0
- data/lib/hammer_cli_katello/content_export_complete.rb +25 -0
- data/lib/hammer_cli_katello/content_export_helper.rb +181 -0
- data/lib/hammer_cli_katello/content_export_incremental.rb +25 -0
- data/lib/hammer_cli_katello/content_import.rb +63 -0
- data/lib/hammer_cli_katello/content_view.rb +3 -1
- data/lib/hammer_cli_katello/content_view_version.rb +2 -1
- data/lib/hammer_cli_katello/id_resolver.rb +5 -1
- data/lib/hammer_cli_katello/ping.rb +10 -3
- data/lib/hammer_cli_katello/version.rb +1 -1
- data/test/data/3.17/foreman_api.json +1 -1
- data/test/data/3.18/foreman_api.json +1 -0
- data/test/functional/content_export/complete/library_test.rb +155 -0
- data/test/functional/content_export/complete/version_test.rb +217 -0
- data/test/functional/content_export/content_export_helpers.rb +26 -0
- data/test/functional/content_export/generate_metadata_test.rb +64 -0
- data/test/functional/content_export/incremental/library_test.rb +172 -0
- data/test/functional/content_export/incremental/version_test.rb +268 -0
- data/test/functional/content_export/list_test.rb +64 -0
- data/test/functional/content_import/library_test.rb +85 -0
- data/test/functional/content_import/metadata.json +1 -0
- data/test/functional/content_import/version_test.rb +85 -0
- data/test/functional/content_view/content_view_helpers.rb +3 -1
- data/test/functional/lifecycle_environment/lifecycle_environment_helpers.rb +1 -1
- data/test/functional/ping_test.rb +2 -1
- data/test/functional/search_helpers.rb +11 -0
- data/test/test_helper.rb +1 -1
- metadata +30 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1b1afcbfac0dd2680c3e26164a1068e6993bc276d9599441747ddd58f637f7d1
|
4
|
+
data.tar.gz: 4f7971c7d6e6145e800f055302d2420e0f37b1832044a0664c00c8061193376b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 91adf0f28b5056ca429c5449e02556635d6e1217279f53cf7551c3f7fab0309a57f002a620e7cf88384936919970f7aabffddf23613953adbd3727359351bcc0
|
7
|
+
data.tar.gz: 6049debd76cb92fcb3309438d7c79d976e5b5f252689d5578268f91196a421fb8d9d8a30ca782a489ed60a7692b556849521a1ef3c93a376f208148dd3aac517
|
data/lib/hammer_cli_katello.rb
CHANGED
@@ -31,6 +31,7 @@ module HammerCLIKatello
|
|
31
31
|
require 'hammer_cli_katello/local_helper'
|
32
32
|
require 'hammer_cli_katello/apipie_helper'
|
33
33
|
require 'hammer_cli_katello/cv_import_export_helper'
|
34
|
+
require 'hammer_cli_katello/content_export_helper'
|
34
35
|
|
35
36
|
# commands
|
36
37
|
HammerCLI::MainCommand.lazy_subcommand("activation-key", _("Manipulate activation keys"),
|
@@ -53,8 +54,7 @@ module HammerCLIKatello
|
|
53
54
|
)
|
54
55
|
|
55
56
|
HammerCLI::MainCommand.lazy_subcommand("content-credentials",
|
56
|
-
_("Manipulate content credentials
|
57
|
-
'on the server"),
|
57
|
+
_("Manipulate content credentials on the server"),
|
58
58
|
'HammerCLIKatello::ContentCredentialCommand',
|
59
59
|
'hammer_cli_katello/content_credential'
|
60
60
|
)
|
@@ -142,6 +142,18 @@ module HammerCLIKatello
|
|
142
142
|
'hammer_cli_katello/file'
|
143
143
|
)
|
144
144
|
|
145
|
+
HammerCLI::MainCommand.lazy_subcommand("content-export",
|
146
|
+
_("Prepare content for export to a disconnected Katello"),
|
147
|
+
'HammerCLIKatello::ContentExport',
|
148
|
+
'hammer_cli_katello/content_export'
|
149
|
+
)
|
150
|
+
|
151
|
+
HammerCLI::MainCommand.lazy_subcommand("content-import",
|
152
|
+
_("Import content from an upstream archive."),
|
153
|
+
'HammerCLIKatello::ContentImport',
|
154
|
+
'hammer_cli_katello/content_import'
|
155
|
+
)
|
156
|
+
|
145
157
|
HammerCLI::MainCommand.lazy_subcommand("module-stream", _("View Module Streams"),
|
146
158
|
'HammerCLIKatello::ModuleStreamCommand',
|
147
159
|
'hammer_cli_katello/module_stream'
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'hammer_cli_katello/content_export_complete'
|
2
|
+
require 'hammer_cli_katello/content_export_incremental'
|
3
|
+
|
4
|
+
module HammerCLIKatello
|
5
|
+
class ContentExport < HammerCLIKatello::Command
|
6
|
+
desc "Prepare content for export to a disconnected Katello"
|
7
|
+
resource :content_exports
|
8
|
+
|
9
|
+
class GenerateMetadataCommand < HammerCLIKatello::Command
|
10
|
+
desc _("Writes export metadata to disk for use by the importing Katello. This command "\
|
11
|
+
+ "only needs to be used if the export was performed asynchronously "\
|
12
|
+
+ "or if the metadata was lost")
|
13
|
+
|
14
|
+
command_name 'generate-metadata'
|
15
|
+
|
16
|
+
include ContentExportHelper
|
17
|
+
|
18
|
+
option "--task-id", "TASK_ID",
|
19
|
+
_("Generate metadata based on output of the specified export task"),
|
20
|
+
:attribute_name => :option_task_id,
|
21
|
+
:required => false
|
22
|
+
|
23
|
+
option "--id", "ID",
|
24
|
+
_("Generate metadata based on specified export history"),
|
25
|
+
:attribute_name => :option_export_id,
|
26
|
+
:required => false
|
27
|
+
|
28
|
+
def execute
|
29
|
+
export_history = if option_task_id
|
30
|
+
export_task = reload_task(option_task_id)
|
31
|
+
fetch_export_history_from_task(export_task)
|
32
|
+
else
|
33
|
+
fetch_export_history(option_export_id)
|
34
|
+
end
|
35
|
+
|
36
|
+
unless export_history
|
37
|
+
raise _("No export history was found. Verify the value given for "\
|
38
|
+
+ "--task-id or --id")
|
39
|
+
end
|
40
|
+
|
41
|
+
generate_metadata_json(export_history)
|
42
|
+
|
43
|
+
HammerCLI::EX_OK
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class ListCommand < HammerCLIKatello::ListCommand
|
48
|
+
desc "View content view export histories"
|
49
|
+
output do
|
50
|
+
field :id, _('ID')
|
51
|
+
field :destination_server, _('Destination Server')
|
52
|
+
field :path, _('Path')
|
53
|
+
field :content_view_version, _('Content View Version')
|
54
|
+
field :content_view_version_id, _('Content View Version ID')
|
55
|
+
field :created_at, _('Created at')
|
56
|
+
field :updated_at, _('Updated at'), Fields::Field, :hide_blank => true
|
57
|
+
end
|
58
|
+
|
59
|
+
build_options
|
60
|
+
end
|
61
|
+
|
62
|
+
autoload_subcommands
|
63
|
+
|
64
|
+
subcommand HammerCLIKatello::ContentExportComplete.command_name,
|
65
|
+
HammerCLIKatello::ContentExportComplete.desc,
|
66
|
+
HammerCLIKatello::ContentExportComplete
|
67
|
+
|
68
|
+
subcommand HammerCLIKatello::ContentExportIncremental.command_name,
|
69
|
+
HammerCLIKatello::ContentExportIncremental.desc,
|
70
|
+
HammerCLIKatello::ContentExportIncremental
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module HammerCLIKatello
|
2
|
+
class ContentExportComplete < HammerCLIKatello::Command
|
3
|
+
desc "Prepare content for a full export to a disconnected Katello"
|
4
|
+
resource :content_exports
|
5
|
+
command_name 'complete'
|
6
|
+
|
7
|
+
class VersionCommand < HammerCLIKatello::SingleResourceCommand
|
8
|
+
desc _('Performs a full export a content view version')
|
9
|
+
command_name "version"
|
10
|
+
|
11
|
+
include HammerCLIForemanTasks::Async
|
12
|
+
include ContentExportHelper
|
13
|
+
end
|
14
|
+
|
15
|
+
class LibraryCommand < HammerCLIKatello::SingleResourceCommand
|
16
|
+
desc _("Performs a full export of the organization's library environment")
|
17
|
+
command_name "library"
|
18
|
+
|
19
|
+
include HammerCLIForemanTasks::Async
|
20
|
+
include ContentExportHelper
|
21
|
+
end
|
22
|
+
|
23
|
+
autoload_subcommands
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,181 @@
|
|
1
|
+
require 'hammer_cli_katello/repository'
|
2
|
+
# rubocop:disable ModuleLength
|
3
|
+
module HammerCLIKatello
|
4
|
+
module ContentExportHelper
|
5
|
+
include ApipieHelper
|
6
|
+
|
7
|
+
def execute
|
8
|
+
warn_unexportable_repositories
|
9
|
+
response = super
|
10
|
+
if option_async?
|
11
|
+
output.print_message _("Once the task completes the export metadata must be generated "\
|
12
|
+
+ "with the command:")
|
13
|
+
output.print_message(" hammer content-export generate-metadata --task-id #{@task['id']}")
|
14
|
+
HammerCLI::EX_OK
|
15
|
+
elsif response != HammerCLI::EX_OK
|
16
|
+
response
|
17
|
+
else
|
18
|
+
export_history = fetch_export_history_from_task(reload_task(@task))
|
19
|
+
if export_history
|
20
|
+
generate_metadata_json(export_history)
|
21
|
+
HammerCLI::EX_OK
|
22
|
+
else
|
23
|
+
output.print_error _("Could not fetch the export history")
|
24
|
+
HammerCLI::EX_CANTCREAT
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def send_request
|
30
|
+
@task = super
|
31
|
+
end
|
32
|
+
|
33
|
+
def reload_task(task)
|
34
|
+
task_id = if task.is_a? Hash
|
35
|
+
task['id']
|
36
|
+
else
|
37
|
+
task
|
38
|
+
end
|
39
|
+
show(:foreman_tasks, id: task_id)
|
40
|
+
end
|
41
|
+
|
42
|
+
def fetch_export_history(export_history_id)
|
43
|
+
resource.call(:index, :id => export_history_id)["results"].first if export_history_id
|
44
|
+
end
|
45
|
+
|
46
|
+
def fetch_export_history_from_task(task)
|
47
|
+
# checking this here implies the task object was loaded recently
|
48
|
+
if %w(error warning).include?(task['result'])
|
49
|
+
raise _("Can not fetch export history from an unfinished task")
|
50
|
+
end
|
51
|
+
|
52
|
+
export_history_id = task.dig('output', 'export_history_id')
|
53
|
+
fetch_export_history(export_history_id)
|
54
|
+
end
|
55
|
+
|
56
|
+
def generate_metadata_json(export_history)
|
57
|
+
metadata_json = export_history["metadata"].to_json
|
58
|
+
begin
|
59
|
+
metadata_path = "#{export_history['path']}/metadata.json"
|
60
|
+
File.write(metadata_path, metadata_json)
|
61
|
+
output.print_message _("Generated #{metadata_path}")
|
62
|
+
rescue SystemCallError
|
63
|
+
filename = "metadata-#{export_history['id']}.json"
|
64
|
+
File.write(filename, metadata_json)
|
65
|
+
output.print_message _("Unable to access/write to '#{export_history['path']}'. "\
|
66
|
+
"Generated '#{Dir.pwd}/#{filename}' instead. "\
|
67
|
+
"This file is necessary to perform an import.")
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def version_command?
|
72
|
+
self.class.command_name.first.to_sym == :version
|
73
|
+
end
|
74
|
+
|
75
|
+
def fetch_repositories
|
76
|
+
repo_options = {
|
77
|
+
library: true,
|
78
|
+
content_type: 'yum',
|
79
|
+
search: 'download_policy != immediate'
|
80
|
+
}
|
81
|
+
if version_command?
|
82
|
+
repo_options[:content_view_version_id] = resolver.content_view_version_id(options)
|
83
|
+
else
|
84
|
+
repo_options[:organization_id] = options["option_organization_id"]
|
85
|
+
end
|
86
|
+
index(:repositories, repo_options)
|
87
|
+
end
|
88
|
+
|
89
|
+
def warn_unexportable_repositories
|
90
|
+
repos = fetch_repositories
|
91
|
+
unless repos.empty?
|
92
|
+
if version_command?
|
93
|
+
output.print_message _("NOTE: Unable to fully export this version because"\
|
94
|
+
" it contains repositories without the 'immediate' download policy."\
|
95
|
+
" Update the download policy and sync affected repositories."\
|
96
|
+
" Once synced republish the content view"\
|
97
|
+
" and export the generated version.")
|
98
|
+
else
|
99
|
+
output.print_message _("NOTE: Unable to fully export this organization's library because"\
|
100
|
+
" it contains repositories without the 'immediate' download policy."\
|
101
|
+
" Update the download policy and sync affected"\
|
102
|
+
" repositories to include them in the export.")
|
103
|
+
end
|
104
|
+
output.print_message _("Use the following command to update the "\
|
105
|
+
"download policy of these repositories.")
|
106
|
+
output.print_message "hammer repository update --id=<REPOSITORY_ID> "\
|
107
|
+
"--download-policy='immediate'"
|
108
|
+
output.print_message ""
|
109
|
+
print_record(::HammerCLIKatello::Repository::ListCommand.output_definition, repos)
|
110
|
+
exit(HammerCLI::EX_SOFTWARE) if option_fail_on_missing_content?
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def self.included(base)
|
115
|
+
if base.command_name.first.to_sym == :version
|
116
|
+
setup_version(base)
|
117
|
+
elsif base.command_name.first.to_sym == :library
|
118
|
+
setup_library(base)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def self.setup_library(base)
|
123
|
+
base.action(:library)
|
124
|
+
base.success_message _("Library environment is being exported in task %{id}.")
|
125
|
+
base.failure_message _("Could not export the library")
|
126
|
+
base.option "--fail-on-missing-content", :flag,
|
127
|
+
_("Fails if any of the repositories belonging"\
|
128
|
+
" to this organization are unexportable.")
|
129
|
+
|
130
|
+
base.build_options do |o|
|
131
|
+
o.expand(:all).including(:organizations)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def self.setup_version(base)
|
136
|
+
base.action(:version)
|
137
|
+
setup_version_options(base)
|
138
|
+
base.success_message _("Content view version is being exported in task %{id}.")
|
139
|
+
base.failure_message _("Could not export the content view version")
|
140
|
+
|
141
|
+
base.extend_with(
|
142
|
+
HammerCLIKatello::CommandExtensions::LifecycleEnvironments.new(only: :option_sources)
|
143
|
+
)
|
144
|
+
base.include(LifecycleEnvironmentNameMapping)
|
145
|
+
|
146
|
+
base.class_eval do
|
147
|
+
def request_params
|
148
|
+
super.tap do |opts|
|
149
|
+
opts["id"] = resolver.content_view_version_id(options)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def self.setup_version_options(base)
|
156
|
+
base.option "--fail-on-missing-content", :flag,
|
157
|
+
_("Fails if any of the repositories belonging"\
|
158
|
+
" to this version are unexportable.")
|
159
|
+
|
160
|
+
base.option "--version", "VERSION", _("Filter versions by version number."),
|
161
|
+
:attribute_name => :option_version,
|
162
|
+
:required => false
|
163
|
+
|
164
|
+
base.build_options do |o|
|
165
|
+
o.expand(:all).including(:content_views, :organizations, :environments)
|
166
|
+
o.without(:environment_ids, :environment_id)
|
167
|
+
end
|
168
|
+
|
169
|
+
base.validate_options do
|
170
|
+
unless option(:option_id).exist?
|
171
|
+
any(:option_id, :option_content_view_name, :option_content_view_id).required
|
172
|
+
any(:option_version, :option_environment_id, :option_environment_name).required
|
173
|
+
unless option(:option_content_view_id).exist?
|
174
|
+
any(:option_organization_id, :option_organization_name, \
|
175
|
+
:option_organization_label).required
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module HammerCLIKatello
|
2
|
+
class ContentExportIncremental < HammerCLIKatello::Command
|
3
|
+
desc "Prepare content for an incremental export to a disconnected Katello"
|
4
|
+
resource :content_export_incrementals
|
5
|
+
command_name 'incremental'
|
6
|
+
|
7
|
+
class VersionCommand < HammerCLIKatello::SingleResourceCommand
|
8
|
+
desc _('Performs an incremental export of a content view version')
|
9
|
+
command_name "version"
|
10
|
+
|
11
|
+
include HammerCLIForemanTasks::Async
|
12
|
+
include ContentExportHelper
|
13
|
+
end
|
14
|
+
|
15
|
+
class LibraryCommand < HammerCLIKatello::SingleResourceCommand
|
16
|
+
desc _("Performs an incremental export of the organization's library environment")
|
17
|
+
command_name "library"
|
18
|
+
|
19
|
+
include HammerCLIForemanTasks::Async
|
20
|
+
include ContentExportHelper
|
21
|
+
end
|
22
|
+
|
23
|
+
autoload_subcommands
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module HammerCLIKatello
|
2
|
+
class ContentImport < HammerCLIKatello::Command
|
3
|
+
desc "Import content from a content archive"
|
4
|
+
resource :content_imports
|
5
|
+
|
6
|
+
module ContentImportCommon
|
7
|
+
def self.included(base)
|
8
|
+
base.option "--metadata-file",
|
9
|
+
"METADATA_FILE", _("Location of the metadata.json file. "\
|
10
|
+
"This is not required if the metadata.json file"\
|
11
|
+
" is already in the archive directory."),
|
12
|
+
:attribute_name => :option_metadata_file,
|
13
|
+
:required => false
|
14
|
+
|
15
|
+
base.build_options do |o|
|
16
|
+
o.expand(:all).including(:content_views, :organizations).except(:metadata)
|
17
|
+
end
|
18
|
+
|
19
|
+
base.validate_options do
|
20
|
+
option(:option_path).required
|
21
|
+
|
22
|
+
metadata_file = option(:option_metadata_file).value ||
|
23
|
+
File.join(option(:option_path).value, "metadata.json")
|
24
|
+
unless File.exist?(metadata_file)
|
25
|
+
msg = _("Unable to find '#{metadata_file}'. "\
|
26
|
+
"If the metadata.json file is at a different location "\
|
27
|
+
"provide it to the --metadata-file option ")
|
28
|
+
raise HammerCLI::Options::Validators::ValidationError, msg
|
29
|
+
end
|
30
|
+
end
|
31
|
+
base.success_message _("Archive is being imported in task %{id}.")
|
32
|
+
base.failure_message _("Could not import the archive.")
|
33
|
+
end
|
34
|
+
|
35
|
+
def request_params
|
36
|
+
super.tap do |opts|
|
37
|
+
metadata_file = option_metadata_file || File.join(option_path, "metadata.json")
|
38
|
+
opts["metadata"] = JSON.parse(File.read(metadata_file))
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class VersionCommand < HammerCLIKatello::SingleResourceCommand
|
44
|
+
desc _('Imports a content archive to a content view version')
|
45
|
+
action :version
|
46
|
+
command_name "version"
|
47
|
+
|
48
|
+
include HammerCLIForemanTasks::Async
|
49
|
+
include ContentImportCommon
|
50
|
+
end
|
51
|
+
|
52
|
+
class LibraryCommand < HammerCLIKatello::SingleResourceCommand
|
53
|
+
desc _("Imports a content archive to an organization's library lifecycle environment")
|
54
|
+
action :library
|
55
|
+
command_name "library"
|
56
|
+
|
57
|
+
include HammerCLIForemanTasks::Async
|
58
|
+
include ContentImportCommon
|
59
|
+
end
|
60
|
+
|
61
|
+
autoload_subcommands
|
62
|
+
end
|
63
|
+
end
|
@@ -106,10 +106,12 @@ module HammerCLIKatello
|
|
106
106
|
failure_message _("Could not create the content view")
|
107
107
|
|
108
108
|
option ["--composite"], :flag, _("Create a composite content view")
|
109
|
-
|
109
|
+
option ["--import-only"], :flag, _("Designate this Content View for "\
|
110
|
+
"importing from upstream servers only.")
|
110
111
|
def request_params
|
111
112
|
super.tap do |opts|
|
112
113
|
opts['composite'] = option_composite? || false
|
114
|
+
opts['import_only'] = option_import_only? || false
|
113
115
|
end
|
114
116
|
end
|
115
117
|
|
@@ -494,7 +494,8 @@ module HammerCLIKatello
|
|
494
494
|
library_repos = index(
|
495
495
|
:repositories,
|
496
496
|
'organization_id' => organization_id,
|
497
|
-
'library' => true
|
497
|
+
'library' => true,
|
498
|
+
'label' => repo['label']
|
498
499
|
)
|
499
500
|
|
500
501
|
library_repo = library_repos.select do |candidate_repo|
|