/
manifest.go
123 lines (105 loc) · 2.69 KB
/
manifest.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
package release
import (
"context"
"errors"
"io"
"os"
"strings"
"golang.org/x/xerrors"
"gopkg.in/yaml.v2"
"go.f110.dev/heimdallr/pkg/cmd"
)
type basic struct {
ApiVersion string `yaml:"apiVersion"`
Kind string `yaml:"kind"`
}
func finalizer(in io.Reader, out io.Writer, version string) error {
d := yaml.NewDecoder(in)
e := yaml.NewEncoder(out)
for {
v := make(map[interface{}]interface{})
err := d.Decode(v)
if err == io.EOF {
break
}
if err != nil {
return xerrors.Errorf(": %w", err)
}
kind, err := detectKind(v)
if err != nil {
return xerrors.Errorf(": %w", err)
}
switch kind {
case "CustomResourceDefinition":
editCustomResourceDefinition(v)
case "Deployment":
editDeployment(v, version)
}
if err := e.Encode(v); err != nil {
return xerrors.Errorf(": %w", err)
}
}
if err := e.Close(); err != nil {
return xerrors.Errorf(": %w", err)
}
return nil
}
func detectKind(v interface{}) (string, error) {
b, err := yaml.Marshal(v)
if err != nil {
return "", xerrors.Errorf(": %w", err)
}
bc := &basic{}
if err := yaml.Unmarshal(b, bc); err != nil {
return "", xerrors.Errorf(": %w", err)
}
if bc.Kind != "" {
return bc.Kind, nil
}
return "", errors.New("failed parse document")
}
func editCustomResourceDefinition(v map[interface{}]interface{}) {
delete(v, "status")
m := v["metadata"].(map[interface{}]interface{})
delete(m, "creationTimestamp")
delete(m, "annotations")
}
func editDeployment(v map[interface{}]interface{}, version string) {
containers := v["spec"].(map[interface{}]interface{})["template"].(map[interface{}]interface{})["spec"].(map[interface{}]interface{})["containers"].([]interface{})
for _, c := range containers {
v := c.(map[interface{}]interface{})
if i, ok := v["image"]; ok {
image := i.(string)
if strings.Contains(image, "heimdallr/operator") {
s := strings.Split(image, ":")
v["image"] = s[0] + ":" + version
}
}
}
}
func manifestCleaner(input, output, version string) error {
reader, err := os.Open(input)
if err != nil {
return xerrors.Errorf(": %w", err)
}
writer, err := os.Create(output)
if err != nil {
return xerrors.Errorf(": %w", err)
}
return finalizer(reader, writer, version)
}
func ManifestCleaner(rootCmd *cmd.Command) {
input := ""
output := ""
version := ""
cleaner := &cmd.Command{
Use: "manifest-cleaner",
Run: func(_ context.Context, _ *cmd.Command, _ []string) error {
return manifestCleaner(input, output, version)
},
}
cleaner.Flags().String("input", "Input file").Var(&input)
cleaner.Flags().String("output", "Output path").Var(&output)
cleaner.Flags().String("version", "Version string").Var(&version)
rootCmd.AddCommand(cleaner)
}