...
1
2
3
4 package command
5
6 import (
7 "bytes"
8 "fmt"
9 "io"
10 "os"
11 "path/filepath"
12
13 "github.com/spf13/cobra"
14
15 "sigs.k8s.io/kustomize/kyaml/errors"
16 "sigs.k8s.io/kustomize/kyaml/fn/framework"
17 "sigs.k8s.io/kustomize/kyaml/kio"
18 "sigs.k8s.io/kustomize/kyaml/yaml"
19 )
20
21 type CLIMode byte
22
23 const (
24 StandaloneEnabled CLIMode = iota
25 StandaloneDisabled
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 func Build(p framework.ResourceListProcessor, mode CLIMode, noPrintError bool) *cobra.Command {
51 cmd := cobra.Command{}
52
53 var printStack bool
54 cmd.Flags().BoolVar(&printStack, "stack", false, "print the stack trace on failure")
55 cmd.Args = cobra.MinimumNArgs(0)
56 cmd.SilenceErrors = true
57 cmd.SilenceUsage = true
58
59 cmd.RunE = func(cmd *cobra.Command, args []string) error {
60 var readers []io.Reader
61 rw := &kio.ByteReadWriter{
62 Writer: cmd.OutOrStdout(),
63 KeepReaderAnnotations: true,
64 }
65
66 if len(args) > 0 && mode == StandaloneEnabled {
67
68 rw.KeepReaderAnnotations = false
69
70
71 rw.NoWrap = true
72
73 for i := range args {
74
75 if i == 0 {
76 var err error
77 if rw.FunctionConfig, err = functionConfigFromFile(args[0]); err != nil {
78 return errors.Wrap(err)
79 }
80 continue
81 }
82 if args[i] == "-" {
83 readers = append([]io.Reader{cmd.InOrStdin()}, readers...)
84 } else {
85 readers = append(readers, &deferredFileReader{path: args[i]})
86 }
87 }
88 } else {
89
90 legacyPlugin := os.Getenv("KUSTOMIZE_PLUGIN_CONFIG_STRING")
91 if legacyPlugin != "" && rw.FunctionConfig != nil {
92 if err := yaml.Unmarshal([]byte(legacyPlugin), rw.FunctionConfig); err != nil {
93 return err
94 }
95 }
96 readers = append(readers, cmd.InOrStdin())
97 }
98 rw.Reader = io.MultiReader(readers...)
99
100 err := framework.Execute(p, rw)
101 if err != nil && !noPrintError {
102 _, _ = fmt.Fprintf(cmd.ErrOrStderr(), "%v", err)
103 }
104
105 if s := errors.GetStack(err); printStack && s != "" {
106 _, _ = fmt.Fprintln(cmd.ErrOrStderr(), s)
107 }
108 return err
109 }
110
111 return &cmd
112 }
113
114
115
116
117
118
119 func AddGenerateDockerfile(cmd *cobra.Command) {
120 gen := &cobra.Command{
121 Use: "gen [DIR]",
122 Args: cobra.ExactArgs(1),
123 RunE: func(cmd *cobra.Command, args []string) error {
124 if err := os.WriteFile(filepath.Join(args[0], "Dockerfile"), []byte(`FROM golang:1.21-alpine as builder
125 ENV CGO_ENABLED=0
126 WORKDIR /go/src/
127 COPY go.mod go.sum ./
128 RUN go mod download
129 COPY . .
130 RUN go build -ldflags '-w -s' -v -o /usr/local/bin/function ./
131
132 FROM alpine:latest
133 COPY --from=builder /usr/local/bin/function /usr/local/bin/function
134 ENTRYPOINT ["function"]
135 `), 0600); err != nil {
136 return fmt.Errorf("%w", err)
137 }
138 return nil
139 },
140 }
141 cmd.AddCommand(gen)
142 }
143
144 func functionConfigFromFile(file string) (*yaml.RNode, error) {
145 b, err := os.ReadFile(file)
146 if err != nil {
147 return nil, errors.WrapPrefixf(err, "unable to read configuration file %q", file)
148 }
149 fc, err := yaml.Parse(string(b))
150 if err != nil {
151 return nil, errors.WrapPrefixf(err, "unable to parse configuration file %q", file)
152 }
153 return fc, nil
154 }
155
156 type deferredFileReader struct {
157 path string
158 srcReader io.Reader
159 }
160
161 func (fr *deferredFileReader) Read(dest []byte) (int, error) {
162 if fr.srcReader == nil {
163 src, err := os.ReadFile(fr.path)
164 if err != nil {
165 return 0, errors.WrapPrefixf(err, "unable to read input file %s", fr.path)
166 }
167 fr.srcReader = bytes.NewReader(src)
168 }
169 return fr.srcReader.Read(dest)
170 }
171
View as plain text