1 package pallet
2
3 import (
4 "context"
5 "flag"
6 "os"
7 "path"
8 "strings"
9
10 v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
11 ktypes "sigs.k8s.io/kustomize/api/types"
12 "sigs.k8s.io/yaml"
13
14 "edge-infra.dev/pkg/f8n/warehouse/capability"
15 "edge-infra.dev/pkg/f8n/warehouse/cluster"
16 "edge-infra.dev/pkg/f8n/warehouse/lift/pack/types"
17 "edge-infra.dev/pkg/lib/cli/rags"
18 "edge-infra.dev/pkg/lib/cli/sink"
19 )
20
21
22
23
24
25
26
27 var (
28 initCmd *sink.Command
29 )
30
31 const (
32
33 palletFilename = "pallet.yaml"
34
35 kustomizationFilename = "kustomization.yaml"
36
37 defaultPath = "config/pallets"
38
39 gcpProjectIDAnnotation = "cnrm.cloud.google.com/project-id"
40
41 edgePlatformLabel = "platform.edge.ncr.com/component"
42 )
43
44
45 func NewInitCmd() *sink.Command {
46 var (
47 name string
48 namespace string
49 outputPath string
50 providers cluster.Providers
51 capabilities capability.Capabilities
52 team string
53 vendor string
54 description string
55 kustomization bool
56 kustomizationResources string
57 kustomizationComponents string
58 )
59
60 fs := rags.New("lift pallet init", flag.ContinueOnError)
61 fs.StringVar(&name, "name", "",
62 "the name of the pallet")
63 fs.StringVar(&namespace, "namespace", "",
64 "the namespace of the pallet")
65 fs.StringVar(&outputPath, "output", defaultPath,
66 "the output location to create the pallet file")
67 fs.Var(&providers, "cluster-providers",
68 "comma separated list of cluster providers the Pallet will define variants "+
69 "for. accumulates values if provided multiple times")
70 fs.Var(&capabilities, "runtime-capabilities",
71 "comma separated list of runtime capabilities by package name the Pallet "+
72 "will integrate with accumulates values if provided multiple times.")
73 fs.StringVar(&team, "team", "",
74 "the team responsible for the pallet")
75 fs.StringVar(&vendor, "vendor", "",
76 "the pallet vendor")
77 fs.StringVar(&description, "description", "",
78 "the pallet description")
79 fs.BoolVar(&kustomization, "create-kustomization", false,
80 "should a companion kustomization file be created")
81 fs.StringVar(&kustomizationResources, "resources", "",
82 "the comma separated list of kustomization resources")
83 fs.StringVar(&kustomizationComponents, "components", "",
84 "the comma separated list of kustomization components")
85
86 initCmd = &sink.Command{
87 Use: "init <flags>",
88 Short: "Scaffold the source for a Warehouse package",
89 Flags: fs.Rags(),
90 Exec: func(_ context.Context, _ sink.Run) error {
91 resources := parseResources(kustomizationResources)
92 components := parseResources(kustomizationComponents)
93 pllet := &types.Pallet{
94 TypeMeta: v1.TypeMeta{
95 Kind: types.PalletKind,
96 APIVersion: types.APIVersion,
97 },
98 ObjectMeta: v1.ObjectMeta{
99 Name: name,
100 },
101 PalletSpec: types.PalletSpec{
102 Capabilities: capabilities,
103 Description: description,
104 Providers: providers,
105 Team: team,
106 Vendor: vendor,
107 },
108 }
109 palletYAML, err := yaml.Marshal(pllet)
110 if err != nil {
111 return err
112 }
113 if _, err := os.Stat(path.Join(outputPath, name)); os.IsNotExist(err) {
114 err := os.MkdirAll(path.Join(outputPath, name), 0755)
115 if err != nil {
116 return err
117 }
118 }
119 if err := writeFile(outputPath, name, palletFilename, palletYAML); err != nil {
120 return err
121 }
122 if kustomization {
123 yaml, err := createKustomization(name, namespace, resources, components)
124 if err != nil {
125 return err
126 }
127 return writeFile(outputPath, name, kustomizationFilename, yaml)
128 }
129 return nil
130 },
131 }
132 return initCmd
133 }
134
135
136 func createKustomization(name, namespace string, resources, components []string) ([]byte, error) {
137 kusto := &ktypes.Kustomization{
138 TypeMeta: ktypes.TypeMeta{
139 Kind: ktypes.KustomizationKind,
140 APIVersion: ktypes.KustomizationVersion,
141 },
142
143 CommonAnnotations: map[string]string{
144 gcpProjectIDAnnotation: "${gcp_project_id}",
145 },
146 CommonLabels: map[string]string{
147 edgePlatformLabel: name,
148 },
149 Namespace: namespace,
150
151 Resources: resources,
152 Components: components,
153 }
154 kustoYaml, err := yaml.Marshal(kusto)
155 if err != nil {
156 return nil, err
157 }
158 return kustoYaml, nil
159 }
160
161
162 func writeFile(outDir, name, fileName string, yamlData []byte) error {
163 err := os.WriteFile(path.Join(outDir, name, fileName), yamlData, 0644)
164 return err
165 }
166
167
168 func parseResources(value string) []string {
169 return strings.Split(value, ",")
170 }
171
View as plain text