Skip to content

Commit 46a03e9

Browse files
committed
refactor(storage/import): extract content type mapping to package level
- Move supportedContentTypes map to package level for reusability - Add getSupportedExtensionsText() to list all supported file extensions - Add getSupportedContentTypesText() to list all supported content types - Update --source-location help to show supported extensions dynamically - Update --content-type help to show supported types dynamically - Simplify getContentType() to use the package-level map - Help text now automatically reflects all supported formats
1 parent ac92674 commit 46a03e9

File tree

1 file changed

+70
-18
lines changed

1 file changed

+70
-18
lines changed

internal/commands/storage/import.go

Lines changed: 70 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,73 @@ import (
2525
"github.com/spf13/pflag"
2626
)
2727

28+
// supportedContentTypes maps file extensions to IANA-registered content types
29+
// based on UpCloud Storage Import API documentation
30+
var supportedContentTypes = map[string]string{
31+
".gz": "application/gzip",
32+
".xz": "application/x-xz",
33+
".iso": "application/octet-stream",
34+
".img": "application/octet-stream",
35+
".raw": "application/octet-stream",
36+
".qcow2": "application/octet-stream",
37+
".tar": "application/x-tar",
38+
".bz2": "application/x-bzip2",
39+
".7z": "application/x-7z-compressed",
40+
".zip": "application/zip",
41+
}
42+
43+
// getSupportedExtensionsText returns a formatted string of supported file extensions
44+
func getSupportedExtensionsText() string {
45+
var extensions []string
46+
for ext := range supportedContentTypes {
47+
extensions = append(extensions, ext)
48+
}
49+
// Sort for consistent output
50+
for i := 0; i < len(extensions); i++ {
51+
for j := i + 1; j < len(extensions); j++ {
52+
if extensions[i] > extensions[j] {
53+
extensions[i], extensions[j] = extensions[j], extensions[i]
54+
}
55+
}
56+
}
57+
var result string
58+
for i, ext := range extensions {
59+
if i > 0 {
60+
result += ", "
61+
}
62+
result += ext
63+
}
64+
return result
65+
}
66+
67+
// getSupportedContentTypesText returns a formatted string of supported content types
68+
func getSupportedContentTypesText() string {
69+
seen := make(map[string]bool)
70+
var types []string
71+
for _, ct := range supportedContentTypes {
72+
if !seen[ct] {
73+
types = append(types, ct)
74+
seen[ct] = true
75+
}
76+
}
77+
// Sort for consistent output
78+
for i := 0; i < len(types); i++ {
79+
for j := i + 1; j < len(types); j++ {
80+
if types[i] > types[j] {
81+
types[i], types[j] = types[j], types[i]
82+
}
83+
}
84+
}
85+
var result string
86+
for i, ct := range types {
87+
if i > 0 {
88+
result += ", "
89+
}
90+
result += ct
91+
}
92+
return result
93+
}
94+
2895
// ImportCommand creates the "storage import" command
2996
func ImportCommand() commands.Command {
3097
return &importCommand{
@@ -70,9 +137,9 @@ type importCommand struct {
70137
// InitCommand implements Command.InitCommand
71138
func (s *importCommand) InitCommand() {
72139
flagSet := &pflag.FlagSet{}
73-
flagSet.StringVar(&s.sourceLocation, "source-location", "", "Location of the source of the import. Can be a file or a URL.")
140+
flagSet.StringVar(&s.sourceLocation, "source-location", "", fmt.Sprintf("Location of the source of the import. Can be a file or a URL. Supported file extensions: %s", getSupportedExtensionsText()))
74141
flagSet.StringVar(&s.existingStorageUUIDOrName, "storage", "", "Import to an existing storage. Storage must be large enough and must be undetached or the server where the storage is attached must be in shutdown state.")
75-
flagSet.StringVar(&s.contentType, "content-type", "", "Content type of the file being imported. If not specified, it will be automatically detected based on file extension. Supported types: application/gzip, application/x-xz, application/x-tar, application/x-bzip2, application/x-7z-compressed, application/zip, application/octet-stream")
142+
flagSet.StringVar(&s.contentType, "content-type", "", fmt.Sprintf("Content type of the file being imported. If not specified, it will be automatically detected based on file extension. Supported types: %s", getSupportedContentTypesText()))
76143
config.AddToggleFlag(flagSet, &s.noWait, "no-wait", false, "When importing from remote url, do not wait until the import finishes or storage is in online state. If set, command will exit after import process has been initialized.")
77144
config.AddToggleFlag(flagSet, &s.wait, "wait", false, "Wait for storage to be in online state before returning.")
78145
applyCreateFlags(flagSet, &s.createParams, defaultCreateParams)
@@ -354,23 +421,8 @@ func pollStorageImportStatus(exec commands.Executor, uuid string, statusChan cha
354421
}
355422

356423
func getContentType(filename string) string {
357-
// Map file extensions to their IANA-registered content types
358-
// Based on UpCloud Storage Import API documentation
359-
contentTypes := map[string]string{
360-
".gz": "application/gzip",
361-
".xz": "application/x-xz",
362-
".iso": "application/octet-stream",
363-
".img": "application/octet-stream",
364-
".raw": "application/octet-stream",
365-
".qcow2": "application/octet-stream",
366-
".tar": "application/x-tar",
367-
".bz2": "application/x-bzip2",
368-
".7z": "application/x-7z-compressed",
369-
".zip": "application/zip",
370-
}
371-
372424
ext := filepath.Ext(filename)
373-
if contentType, exists := contentTypes[ext]; exists {
425+
if contentType, exists := supportedContentTypes[ext]; exists {
374426
return contentType
375427
}
376428

0 commit comments

Comments
 (0)