1 package cmd
2
3 import (
4 "bytes"
5 "fmt"
6 "io"
7 "os"
8 "path"
9 "time"
10
11 "github.com/linkerd/linkerd2/jaeger/static"
12 "github.com/linkerd/linkerd2/pkg/charts"
13 partials "github.com/linkerd/linkerd2/pkg/charts/static"
14 pkgcmd "github.com/linkerd/linkerd2/pkg/cmd"
15 "github.com/linkerd/linkerd2/pkg/flags"
16 "github.com/linkerd/linkerd2/pkg/healthcheck"
17 "github.com/spf13/cobra"
18 "helm.sh/helm/v3/pkg/chart/loader"
19 "helm.sh/helm/v3/pkg/chartutil"
20 "helm.sh/helm/v3/pkg/cli/values"
21 "helm.sh/helm/v3/pkg/engine"
22 )
23
24 var (
25
26 templatesJaeger = []string{
27 "templates/namespace.yaml",
28 "templates/jaeger-injector.yaml",
29 "templates/jaeger-injector-policy.yaml",
30 "templates/rbac.yaml",
31 "templates/psp.yaml",
32 "templates/tracing.yaml",
33 "templates/tracing-policy.yaml",
34 }
35 )
36
37 func newCmdInstall() *cobra.Command {
38 var registry string
39 var cniEnabled bool
40 var skipChecks bool
41 var ignoreCluster bool
42 var wait time.Duration
43 var options values.Options
44
45
46
47 defaultDockerRegistry := pkgcmd.DefaultDockerRegistry
48 if regOverride := os.Getenv(flags.EnvOverrideDockerRegistry); regOverride != "" {
49 defaultDockerRegistry = regOverride
50 }
51
52 cmd := &cobra.Command{
53 Use: "install [flags]",
54 Args: cobra.NoArgs,
55 Short: "Output Kubernetes resources to install jaeger extension",
56 Long: `Output Kubernetes resources to install jaeger extension.`,
57 Example: ` # Default install.
58 linkerd jaeger install | kubectl apply -f -
59 # Install Jaeger extension into a non-default namespace.
60 linkerd jaeger install --namespace custom | kubectl apply -f -
61
62 The installation can be configured by using the --set, --values, --set-string and --set-file flags.
63 A full list of configurable values can be found at https://www.github.com/linkerd/linkerd2/tree/main/jaeger/charts/linkerd-jaeger/README.md
64 `,
65 RunE: func(cmd *cobra.Command, args []string) error {
66 if !skipChecks && !ignoreCluster {
67
68 hc := healthcheck.NewWithCoreChecks(&healthcheck.Options{
69 ControlPlaneNamespace: controlPlaneNamespace,
70 KubeConfig: kubeconfigPath,
71 KubeContext: kubeContext,
72 Impersonate: impersonate,
73 ImpersonateGroup: impersonateGroup,
74 APIAddr: apiAddr,
75 RetryDeadline: time.Now().Add(wait),
76 })
77 hc.RunWithExitOnError()
78 cniEnabled = hc.CNIEnabled
79 }
80
81 return install(os.Stdout, options, registry, cniEnabled)
82 },
83 }
84
85 cmd.Flags().StringVar(®istry, "registry", defaultDockerRegistry,
86 fmt.Sprintf("Docker registry to pull jaeger-webhook image from ($%s)", flags.EnvOverrideDockerRegistry))
87 cmd.Flags().BoolVar(&skipChecks, "skip-checks", false, `Skip checks for linkerd core control-plane existence`)
88 cmd.Flags().BoolVar(&ignoreCluster, "ignore-cluster", false,
89 "Ignore the current Kubernetes cluster when checking for existing cluster configuration (default false)")
90 cmd.Flags().DurationVar(&wait, "wait", 300*time.Second, "Wait for core control-plane components to be available")
91
92 flags.AddValueOptionsFlags(cmd.Flags(), &options)
93
94 return cmd
95 }
96
97 func install(w io.Writer, options values.Options, registry string, cniEnabled bool) error {
98
99
100 valuesOverrides, err := options.MergeValues(nil)
101 if err != nil {
102 return err
103 }
104
105 if cniEnabled {
106 valuesOverrides["cniEnabled"] = true
107 }
108
109
110
111 return render(w, valuesOverrides, registry)
112 }
113
114 func render(w io.Writer, valuesOverrides map[string]interface{}, registry string) error {
115
116 files := []*loader.BufferedFile{
117 {Name: chartutil.ChartfileName},
118 {Name: chartutil.ValuesfileName},
119 }
120
121 for _, template := range templatesJaeger {
122 files = append(files,
123 &loader.BufferedFile{Name: template},
124 )
125 }
126
127 var partialFiles []*loader.BufferedFile
128 for _, template := range charts.L5dPartials {
129 partialFiles = append(partialFiles,
130 &loader.BufferedFile{Name: template},
131 )
132 }
133
134
135 if err := charts.FilesReader(static.Templates, "linkerd-jaeger/", files); err != nil {
136 return err
137 }
138
139
140 if err := charts.FilesReader(partials.Templates, "", partialFiles); err != nil {
141 return err
142 }
143
144
145 chart, err := loader.LoadFiles(append(files, partialFiles...))
146 if err != nil {
147 return err
148 }
149
150 vals, err := chartutil.CoalesceValues(chart, valuesOverrides)
151 if err != nil {
152 return err
153 }
154
155 vals, err = charts.InsertVersionValues(vals)
156 if err != nil {
157 return err
158 }
159
160 regOrig := vals["webhook"].(map[string]interface{})["image"].(map[string]interface{})["name"].(string)
161
162
163
164
165
166 if registry != "" {
167 vals["webhook"].(map[string]interface{})["image"].(map[string]interface{})["name"] = pkgcmd.RegistryOverride(regOrig, registry)
168 }
169
170 fullValues := map[string]interface{}{
171 "Values": vals,
172 "Release": map[string]interface{}{
173 "Namespace": defaultJaegerNamespace,
174 "Service": "CLI",
175 },
176 }
177
178
179 renderedTemplates, err := engine.Render(chart, fullValues)
180 if err != nil {
181 return err
182 }
183
184
185 var buf bytes.Buffer
186 for _, tmpl := range chart.Templates {
187 t := path.Join(chart.Metadata.Name, tmpl.Name)
188 if _, err := buf.WriteString(renderedTemplates[t]); err != nil {
189 return err
190 }
191 }
192
193 _, err = w.Write(buf.Bytes())
194 return err
195 }
196
View as plain text