...
1 package values
2
3 import (
4 "errors"
5 "fmt"
6
7 "github.com/imdario/mergo"
8 "github.com/linkerd/linkerd2/pkg/charts"
9 "github.com/linkerd/linkerd2/pkg/charts/static"
10 "github.com/linkerd/linkerd2/pkg/k8s"
11 "github.com/linkerd/linkerd2/pkg/version"
12 "helm.sh/helm/v3/pkg/chart/loader"
13 corev1 "k8s.io/api/core/v1"
14 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
15 "sigs.k8s.io/yaml"
16 )
17
18 const (
19
20 HelmChartDirCP = "linkerd-control-plane"
21 )
22
23 type (
24
25 Values struct {
26 ControllerImage string `json:"controllerImage"`
27 ControllerReplicas uint `json:"controllerReplicas"`
28 ControllerUID int64 `json:"controllerUID"`
29 ControllerGID int64 `json:"controllerGID"`
30 EnableH2Upgrade bool `json:"enableH2Upgrade"`
31 EnablePodAntiAffinity bool `json:"enablePodAntiAffinity"`
32 NodeAffinity map[string]interface{} `json:"nodeAffinity"`
33 EnablePodDisruptionBudget bool `json:"enablePodDisruptionBudget"`
34 DisableIPv6 bool `json:"disableIPv6"`
35 Controller *Controller `json:"controller"`
36 WebhookFailurePolicy string `json:"webhookFailurePolicy"`
37 DeploymentStrategy map[string]interface{} `json:"deploymentStrategy,omitempty"`
38 DisableHeartBeat bool `json:"disableHeartBeat"`
39 HeartbeatSchedule string `json:"heartbeatSchedule"`
40 Configs ConfigJSONs `json:"configs"`
41 ClusterDomain string `json:"clusterDomain"`
42 ClusterNetworks string `json:"clusterNetworks"`
43 ImagePullPolicy string `json:"imagePullPolicy"`
44 RevisionHistoryLimit int64 `json:"revisionHistoryLimit"`
45 CliVersion string `json:"cliVersion"`
46 ControllerLogLevel string `json:"controllerLogLevel"`
47 ControllerLogFormat string `json:"controllerLogFormat"`
48 ProxyContainerName string `json:"proxyContainerName"`
49 HighAvailability bool `json:"highAvailability"`
50 CNIEnabled bool `json:"cniEnabled"`
51 EnableEndpointSlices bool `json:"enableEndpointSlices"`
52 ControlPlaneTracing bool `json:"controlPlaneTracing"`
53 ControlPlaneTracingNamespace string `json:"controlPlaneTracingNamespace"`
54 IdentityTrustAnchorsPEM string `json:"identityTrustAnchorsPEM"`
55 IdentityTrustDomain string `json:"identityTrustDomain"`
56 PrometheusURL string `json:"prometheusUrl"`
57 ImagePullSecrets []map[string]string `json:"imagePullSecrets"`
58 LinkerdVersion string `json:"linkerdVersion"`
59
60 PodAnnotations map[string]string `json:"podAnnotations"`
61 PodLabels map[string]string `json:"podLabels"`
62 PriorityClassName string `json:"priorityClassName"`
63
64 PodMonitor *PodMonitor `json:"podMonitor"`
65 PolicyController *PolicyController `json:"policyController"`
66 Proxy *Proxy `json:"proxy"`
67 ProxyInit *ProxyInit `json:"proxyInit"`
68 NetworkValidator *NetworkValidator `json:"networkValidator"`
69 Identity *Identity `json:"identity"`
70 DebugContainer *DebugContainer `json:"debugContainer"`
71 ProxyInjector *Webhook `json:"proxyInjector"`
72 ProfileValidator *Webhook `json:"profileValidator"`
73 PolicyValidator *Webhook `json:"policyValidator"`
74 NodeSelector map[string]string `json:"nodeSelector"`
75 Tolerations []interface{} `json:"tolerations"`
76
77 DestinationResources *Resources `json:"destinationResources"`
78 HeartbeatResources *Resources `json:"heartbeatResources"`
79 IdentityResources *Resources `json:"identityResources"`
80 ProxyInjectorResources *Resources `json:"proxyInjectorResources"`
81
82 DestinationProxyResources *Resources `json:"destinationProxyResources"`
83 IdentityProxyResources *Resources `json:"identityProxyResources"`
84 ProxyInjectorProxyResources *Resources `json:"proxyInjectorProxyResources"`
85 }
86
87
88 ConfigJSONs struct {
89 Global string `json:"global"`
90 Proxy string `json:"proxy"`
91 Install string `json:"install"`
92 }
93
94
95 Proxy struct {
96 Capabilities *Capabilities `json:"capabilities"`
97
98 Cores int64 `json:"cores,omitempty"`
99 EnableExternalProfiles bool `json:"enableExternalProfiles"`
100 Image *Image `json:"image"`
101 LogLevel string `json:"logLevel"`
102 LogFormat string `json:"logFormat"`
103 SAMountPath *VolumeMountPath `json:"saMountPath"`
104 Ports *Ports `json:"ports"`
105 Resources *Resources `json:"resources"`
106 UID int64 `json:"uid"`
107 GID int64 `json:"gid"`
108 WaitBeforeExitSeconds uint64 `json:"waitBeforeExitSeconds"`
109 IsGateway bool `json:"isGateway"`
110 IsIngress bool `json:"isIngress"`
111 RequireIdentityOnInboundPorts string `json:"requireIdentityOnInboundPorts"`
112 OutboundConnectTimeout string `json:"outboundConnectTimeout"`
113 InboundConnectTimeout string `json:"inboundConnectTimeout"`
114 OutboundDiscoveryCacheUnusedTimeout string `json:"outboundDiscoveryCacheUnusedTimeout"`
115 InboundDiscoveryCacheUnusedTimeout string `json:"inboundDiscoveryCacheUnusedTimeout"`
116 DisableOutboundProtocolDetectTimeout bool `json:"disableOutboundProtocolDetectTimeout"`
117 DisableInboundProtocolDetectTimeout bool `json:"disableInboundProtocolDetectTimeout"`
118 PodInboundPorts string `json:"podInboundPorts"`
119 OpaquePorts string `json:"opaquePorts"`
120 Await bool `json:"await"`
121 DefaultInboundPolicy string `json:"defaultInboundPolicy"`
122 AccessLog string `json:"accessLog"`
123 ShutdownGracePeriod string `json:"shutdownGracePeriod"`
124 NativeSidecar bool `json:"nativeSidecar"`
125 StartupProbe *StartupProbe `json:"startupProbe"`
126 ReadinessProbe *Probe `json:"readinessProbe"`
127 LivenessProbe *Probe `json:"livenessProbe"`
128 Control *ProxyControl `json:"control"`
129 Inbound *ProxyEndpoint `json:"inbound"`
130 Outbound *ProxyEndpoint `json:"outbound"`
131 AdditionalEnv []corev1.EnvVar `json:"additionalEnv"`
132 ExperimentalEnv []corev1.EnvVar `json:"experimentalEnv"`
133 }
134
135 ProxyControl struct {
136 Streams *ProxyControlStreams `json:"streams"`
137 }
138
139 ProxyControlStreams struct {
140 InitialTimeout string `json:"initialTimeout"`
141 IdleTimeout string `json:"idleTimeout"`
142 Lifetime string `json:"lifetime"`
143 }
144
145 ProxyEndpoint struct {
146 Server *ServerConfig `json:"server"`
147 }
148
149 ServerConfig struct {
150 HTTP2 *HTTP2Settings `json:"http2"`
151 }
152
153 HTTP2Settings struct {
154 KeepAliveInterval string `json:"keepAliveInterval"`
155 KeepAliveTimeout string `json:"keepAliveTimeout"`
156 }
157
158
159 ProxyInit struct {
160 Capabilities *Capabilities `json:"capabilities"`
161 IgnoreInboundPorts string `json:"ignoreInboundPorts"`
162 IgnoreOutboundPorts string `json:"ignoreOutboundPorts"`
163 KubeAPIServerPorts string `json:"kubeAPIServerPorts"`
164 SkipSubnets string `json:"skipSubnets"`
165 LogLevel string `json:"logLevel"`
166 LogFormat string `json:"logFormat"`
167 Image *Image `json:"image"`
168 SAMountPath *VolumeMountPath `json:"saMountPath"`
169 XTMountPath *VolumeMountPath `json:"xtMountPath"`
170 Resources *Resources `json:"resources"`
171 CloseWaitTimeoutSecs int64 `json:"closeWaitTimeoutSecs"`
172 Privileged bool `json:"privileged"`
173 RunAsRoot bool `json:"runAsRoot"`
174 RunAsUser int64 `json:"runAsUser"`
175 RunAsGroup int64 `json:"runAsGroup"`
176 IptablesMode string `json:"iptablesMode"`
177 }
178
179 NetworkValidator struct {
180 LogLevel string `json:"logLevel"`
181 LogFormat string `json:"logFormat"`
182 ConnectAddr string `json:"connectAddr"`
183 ListenAddr string `json:"listenAddr"`
184 Timeout string `json:"timeout"`
185 EnableSecurityContext bool `json:"enableSecurityContext"`
186 }
187
188
189 DebugContainer struct {
190 Image *Image `json:"image"`
191 }
192
193
194 PodMonitor struct {
195 Enabled bool `json:"enabled"`
196 ScrapeInterval string `json:"scrapeInterval"`
197 ScrapeTimeout string `json:"scrapeTimeout"`
198 Controller *PodMonitorController `json:"controller"`
199 ServiceMirror *PodMonitorComponent `json:"serviceMirror"`
200 Proxy *PodMonitorComponent `json:"proxy"`
201 }
202
203
204 PodMonitorController struct {
205 Enabled bool `json:"enabled"`
206 NamespaceSelector string `json:"namespaceSelector"`
207 }
208
209
210 PodMonitorComponent struct {
211 Enabled bool `json:"enabled"`
212 }
213
214
215 PolicyController struct {
216 Image *Image `json:"image"`
217 Resources *Resources `json:"resources"`
218 LogLevel string `json:"logLevel"`
219 ProbeNetworks []string `json:"probeNetworks"`
220 }
221
222
223 Image struct {
224 Name string `json:"name"`
225 PullPolicy string `json:"pullPolicy"`
226 Version string `json:"version"`
227 }
228
229
230 Ports struct {
231 Admin int32 `json:"admin"`
232 Control int32 `json:"control"`
233 Inbound int32 `json:"inbound"`
234 Outbound int32 `json:"outbound"`
235 }
236
237 Probe struct {
238 InitialDelaySeconds uint `json:"initialDelaySeconds"`
239 TimeoutSeconds uint `json:"timeoutSeconds"`
240 }
241
242
243 Constraints struct {
244 Limit string `json:"limit"`
245 Request string `json:"request"`
246 }
247
248
249
250 Capabilities struct {
251 Add []string `json:"add"`
252 Drop []string `json:"drop"`
253 }
254
255
256 VolumeMountPath struct {
257 Name string `json:"name"`
258 MountPath string `json:"mountPath"`
259 ReadOnly bool `json:"readOnly"`
260 }
261
262
263 Resources struct {
264 CPU Constraints `json:"cpu"`
265 Memory Constraints `json:"memory"`
266 EphemeralStorage Constraints `json:"ephemeral-storage"`
267 }
268
269
270 StartupProbe struct {
271 InitialDelaySeconds uint `json:"initialDelaySeconds"`
272 PeriodSeconds uint `json:"periodSeconds"`
273 FailureThreshold uint `json:"failureThreshold"`
274 }
275
276
277
278 Identity struct {
279 ExternalCA bool `json:"externalCA"`
280 ServiceAccountTokenProjection bool `json:"serviceAccountTokenProjection"`
281 Issuer *Issuer `json:"issuer"`
282 KubeAPI *KubeAPI `json:"kubeAPI"`
283 }
284
285
286 Issuer struct {
287 Scheme string `json:"scheme"`
288 ClockSkewAllowance string `json:"clockSkewAllowance"`
289 IssuanceLifetime string `json:"issuanceLifetime"`
290 TLS *IssuerTLS `json:"tls"`
291 }
292
293
294 KubeAPI struct {
295 ClientQPS float32 `json:"clientQPS"`
296 ClientBurst int `json:"clientBurst"`
297 }
298
299
300 Webhook struct {
301 *TLS
302 NamespaceSelector *metav1.LabelSelector `json:"namespaceSelector"`
303 }
304
305
306
307 TLS struct {
308 ExternalSecret bool `json:"externalSecret"`
309 KeyPEM string `json:"keyPEM"`
310 CrtPEM string `json:"crtPEM"`
311 CaBundle string `json:"caBundle"`
312 InjectCaFrom string `json:"injectCaFrom"`
313 InjectCaFromSecret string `json:"injectCaFromSecret"`
314 }
315
316
317
318 IssuerTLS struct {
319 KeyPEM string `json:"keyPEM"`
320 CrtPEM string `json:"crtPEM"`
321 }
322
323 Controller struct {
324 PodDistruptionBudget *PodDistruptionBudget `json:"podDistruptionBudget"`
325 }
326
327 PodDistruptionBudget struct {
328 MaxUnavailable int64 `json:"maxUnavailable"`
329 }
330
331 DestinationController struct {
332 MeshedHTTP2ClientProtobuf *MeshedHTTP2ClientProtobuf `json:"meshedHttp2ClientProtobuf"`
333 }
334
335 MeshedHTTP2ClientProtobuf struct {
336 KeepAlive *ProtobufKeepAlive `json:"keep_alive"`
337 }
338
339 ProtobufKeepAlive struct {
340 Interval *DurationSeconds `json:"interval"`
341 Timeout *DurationSeconds `json:"timeout"`
342 WhileIdle bool `json:"while_idle"`
343 }
344
345 DurationSeconds struct {
346 Seconds int64 `json:"seconds"`
347 }
348 )
349
350
351 func NewValues() (*Values, error) {
352 v, err := readDefaults(HelmChartDirCP + "/values.yaml")
353 if err != nil {
354 return nil, err
355 }
356
357 v.DebugContainer.Image.Version = version.Version
358 v.CliVersion = k8s.CreatedByAnnotationValue()
359 v.ProfileValidator.TLS = &TLS{}
360 v.ProxyInjector.TLS = &TLS{}
361 v.ProxyContainerName = k8s.ProxyContainerName
362
363 return v, nil
364 }
365
366
367
368 func FromConfigMap(cm *corev1.ConfigMap) (*Values, error) {
369 raw, ok := cm.Data["values"]
370 if !ok {
371 return nil, errors.New("Linkerd values not found in ConfigMap")
372 }
373 v := &Values{}
374 err := yaml.Unmarshal([]byte(raw), &v)
375 return v, err
376 }
377
378
379 func MergeHAValues(values *Values) error {
380 haValues, err := readDefaults(HelmChartDirCP + "/values-ha.yaml")
381 if err != nil {
382 return err
383 }
384 *values, err = values.Merge(*haValues)
385 return err
386 }
387
388
389 func readDefaults(filename string) (*Values, error) {
390 valuesFile := &loader.BufferedFile{Name: filename}
391 if err := charts.ReadFile(static.Templates, "/", valuesFile); err != nil {
392 return nil, err
393 }
394
395 var values Values
396 err := yaml.Unmarshal(charts.InsertVersion(valuesFile.Data), &values)
397
398 return &values, err
399 }
400
401
402
403
404 func (v Values) Merge(src Values) (Values, error) {
405
406
407
408
409 if err := mergo.Merge(&src, v); err != nil {
410 return Values{}, err
411 }
412
413 return src, nil
414 }
415
416
417 func (v *Values) ToMap() (map[string]interface{}, error) {
418 var valuesMap map[string]interface{}
419 rawValues, err := yaml.Marshal(v)
420 if err != nil {
421 return nil, fmt.Errorf("Failed to marshal the values struct: %w", err)
422 }
423
424 err = yaml.Unmarshal(rawValues, &valuesMap)
425 if err != nil {
426 return nil, fmt.Errorf("Failed to Unmarshal Values into a map: %w", err)
427 }
428
429 return valuesMap, nil
430 }
431
432
433
434 func (v *Values) DeepCopy() (*Values, error) {
435 dst := Values{}
436 bytes, err := yaml.Marshal(v)
437 if err != nil {
438 return nil, err
439 }
440 err = yaml.Unmarshal(bytes, &dst)
441 if err != nil {
442 return nil, err
443 }
444 return &dst, nil
445 }
446
447 func (v *Values) String() string {
448 bytes, _ := yaml.Marshal(v)
449 return string(bytes)
450 }
451
View as plain text