-
Notifications
You must be signed in to change notification settings - Fork 6
/
convert_list.go
156 lines (138 loc) · 4.13 KB
/
convert_list.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package commands
import (
"bufio"
"fmt"
"os"
"strings"
"github.com/cnrancher/hangar/pkg/hangar/imagelist"
"github.com/cnrancher/hangar/pkg/utils"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
type convertListCmd struct {
*baseCmd
input string
output string
source string
destination string
autoYes bool
}
func newConvertListCmd() *convertListCmd {
cc := &convertListCmd{}
cc.baseCmd = newBaseCmd(&cobra.Command{
Use: "convert-list -i IMAGE_LIST.txt -o OUTPUT_IMAGE_LIST.txt",
Short: "Convert the image list format to mirror format (see example of this command).",
Example: `
# Prepare an image list file with default format:
docker.io/library/mysql:8
docker.io/library/nginx:latest
# Use following command to convert the image list format to 'mirror' format.
hangar convert-list \
--input IMAGE_LIST.txt \
--output OUTPUT_IMAGE_LIST.txt \
--source docker.io \
--destination registry.example.io
# The converted image list is:
docker.io/library/mysql registry.example.io/library/mysql 8
docker.io/library/nginx registry.example.io/library/nginx latest`,
PreRun: func(cmd *cobra.Command, args []string) {
if cc.debug {
logrus.SetLevel(logrus.DebugLevel)
logrus.Debugf("Debug output enabled")
}
},
RunE: func(cmd *cobra.Command, args []string) error {
if err := cc.setupFlags(); err != nil {
return err
}
if err := cc.run(); err != nil {
return err
}
return nil
},
})
flags := cc.cmd.Flags()
flags.StringVarP(&cc.input, "input", "i", "", "input image list file")
flags.SetAnnotation("input", cobra.BashCompFilenameExt, []string{"txt"})
flags.SetAnnotation("input", cobra.BashCompOneRequiredFlag, []string{""})
flags.StringVarP(&cc.output, "output", "o", "", "output image list (default \"[INPUT_FILE].converted\")")
flags.SetAnnotation("output", cobra.BashCompFilenameExt, []string{"txt"})
flags.StringVarP(&cc.source, "source", "s", "", "specify the source registry (optional)")
flags.StringVarP(&cc.destination, "destination", "d", "", "specify the destination registry (optional)")
flags.BoolVarP(&cc.autoYes, "auto-yes", "y", false, "answer yes automatically (used in shell script)")
return cc
}
func (cc *convertListCmd) setupFlags() error {
if cc.input == "" {
return fmt.Errorf("input file not specified")
}
if cc.output == "" {
cc.output = cc.input + ".converted"
}
return nil
}
func (cc *convertListCmd) run() error {
f, err := os.Open(cc.input)
if err != nil {
logrus.Fatal(err)
}
defer f.Close()
scanner := bufio.NewScanner(f)
scanner.Split(bufio.ScanLines)
convertedLines := []string{}
for scanner.Scan() {
l := scanner.Text()
if l == "" || strings.HasPrefix(l, "#") || strings.HasPrefix(l, "//") {
continue
}
switch imagelist.Detect(l) {
case imagelist.TypeMirror:
logrus.Infof("Skip line: %v", l)
continue
case imagelist.TypeDefault:
default:
// unknow format, continue
logrus.Warnf("Ignore line: %q: format unknow", l)
continue
}
spec := make([]string, 0, 2)
for _, v := range strings.Split(l, ":") {
if len(v) > 0 {
spec = append(spec, v)
}
}
if len(spec) != 2 {
if len(spec) == 1 {
spec = append(spec, "latest")
} else {
logrus.Warnf("Ignore line: %q: format unknow", l)
continue
}
}
var srcImage string
if cc.source == "" {
srcImage = spec[0]
} else {
srcImage = utils.ConstructRegistry(spec[0], cc.source)
}
dst := cc.destination
destImage := utils.ConstructRegistry(spec[0], dst)
outputLine := fmt.Sprintf("%s %s %s", srcImage, destImage, spec[1])
logrus.Debugf("converted %q => %q", l, outputLine)
convertedLines = append(convertedLines, outputLine)
}
if err := utils.CheckFileExistsPrompt(signalContext, cc.output, cc.autoYes); err != nil {
return err
}
file, err := os.OpenFile(cc.output, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil {
return fmt.Errorf("failed to save %q: %v", cc.output, err)
}
defer file.Close()
_, err = fmt.Fprintf(file, "%v", strings.Join(convertedLines, "\n"))
if err != nil {
return fmt.Errorf("failed to write %q: %v", cc.output, err)
}
logrus.Infof("Converted %q to %q", cc.input, cc.output)
return nil
}