github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/apis/extensions/v1alpha1/addon_types.go (about) 1 /* 2 Copyright (C) 2022-2023 ApeCloud Co., Ltd 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package v1alpha1 18 19 import ( 20 "fmt" 21 "regexp" 22 "strings" 23 24 corev1 "k8s.io/api/core/v1" 25 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 26 "k8s.io/apimachinery/pkg/version" 27 28 "github.com/1aal/kubeblocks/pkg/constant" 29 viper "github.com/1aal/kubeblocks/pkg/viperx" 30 ) 31 32 // AddonSpec defines the desired state of an add-on. 33 // +kubebuilder:validation:XValidation:rule="has(self.type) && self.type == 'Helm' ? has(self.helm) : !has(self.helm)",message="spec.helm is required when spec.type is Helm, and forbidden otherwise" 34 type AddonSpec struct { 35 // Addon description. 36 // +optional 37 Description string `json:"description,omitempty"` 38 39 // Add-on type. The valid value is helm. 40 // +unionDiscriminator 41 // +kubebuilder:validation:Required 42 Type AddonType `json:"type"` 43 44 // Helm installation spec. It's processed only when type=helm. 45 // +optional 46 Helm *HelmTypeInstallSpec `json:"helm,omitempty"` 47 48 // Default installation parameters. 49 // +kubebuilder:validation:Required 50 // +kubebuilder:validation:MinItems=1 51 DefaultInstallValues []AddonDefaultInstallSpecItem `json:"defaultInstallValues"` 52 53 // Installation parameters. 54 // +optional 55 InstallSpec *AddonInstallSpec `json:"install,omitempty"` 56 57 // Addon installable spec. It provides selector and auto-install settings. 58 // +optional 59 Installable *InstallableSpec `json:"installable,omitempty"` 60 61 // Plugin installation spec. 62 // +optional 63 CliPlugins []CliPlugin `json:"cliPlugins,omitempty"` 64 } 65 66 // AddonStatus defines the observed state of an add-on. 67 type AddonStatus struct { 68 // Add-on installation phases. Valid values are Disabled, Enabled, Failed, Enabling, Disabling. 69 // +kubebuilder:validation:Enum={Disabled,Enabled,Failed,Enabling,Disabling} 70 Phase AddonPhase `json:"phase,omitempty"` 71 72 // Describes the current state of add-on API installation conditions. 73 // +optional 74 Conditions []metav1.Condition `json:"conditions,omitempty"` 75 76 // observedGeneration is the most recent generation observed for this 77 // add-on. It corresponds to the add-on's generation, which is 78 // updated on mutation by the API Server. 79 // +optional 80 ObservedGeneration int64 `json:"observedGeneration,omitempty"` 81 } 82 83 type InstallableSpec struct { 84 // Add-on installable selectors. If multiple selectors are provided, 85 // all selectors must evaluate to true. 86 // +optional 87 Selectors []SelectorRequirement `json:"selectors,omitempty"` 88 89 // autoInstall defines an add-on should be installed automatically. 90 // +kubebuilder:default=false 91 AutoInstall bool `json:"autoInstall"` 92 } 93 94 type SelectorRequirement struct { 95 // The selector key. Valid values are KubeVersion, KubeGitVersion and KubeProvider. 96 // "KubeVersion" the semver expression of Kubernetes versions, i.e., v1.24. 97 // "KubeGitVersion" may contain distro. info., i.e., v1.24.4+eks. 98 // "KubeProvider" the Kubernetes provider, i.e., aws,gcp,azure,huaweiCloud,tencentCloud etc. 99 // +kubebuilder:validation:Required 100 Key AddonSelectorKey `json:"key"` 101 102 // Represents a key's relationship to a set of values. 103 // Valid operators are Contains, NotIn, DoesNotContain, MatchRegex, and DoesNoteMatchRegex. 104 // 105 // Possible enum values: 106 // `"Contains"` line contains a string. 107 // `"DoesNotContain"` line does not contain a string. 108 // `"MatchRegex"` line contains a match to the regular expression. 109 // `"DoesNotMatchRegex"` line does not contain a match to the regular expression. 110 // +kubebuilder:validation:Required 111 Operator LineSelectorOperator `json:"operator"` 112 113 // An array of string values. It serves as an "OR" expression to the operator. 114 // +optional 115 Values []string `json:"values,omitempty" protobuf:"bytes,3,rep,name=values"` 116 } 117 118 // HelmTypeInstallSpec defines the Helm installation spec. 119 // +kubebuilder:validation:XValidation:rule="self.chartLocationURL.startsWith('file://') ? has(self.chartsImage) : true",message="chartsImage is required when chartLocationURL starts with 'file://'" 120 type HelmTypeInstallSpec struct { 121 // A Helm Chart location URL. 122 // +kubebuilder:validation:Required 123 ChartLocationURL string `json:"chartLocationURL"` 124 125 // installOptions defines Helm release installation options. 126 // +optional 127 InstallOptions HelmInstallOptions `json:"installOptions,omitempty"` 128 129 // HelmInstallValues defines Helm release installation set values. 130 // +optional 131 InstallValues HelmInstallValues `json:"installValues,omitempty"` 132 133 // valuesMapping defines add-on normalized resources parameters mapped to Helm values' keys. 134 // +optional 135 ValuesMapping HelmValuesMapping `json:"valuesMapping,omitempty"` 136 137 // chartsImage defines the image of Helm charts. 138 // +optional 139 ChartsImage string `json:"chartsImage,omitempty"` 140 141 // chartsPathInImage defines the path of Helm charts in the image. It's used to copy 142 // Helm charts from the image to the shared volume. 143 // +kubeBuilder:default="/charts" 144 // +optional 145 ChartsPathInImage string `json:"chartsPathInImage,omitempty"` 146 } 147 148 type HelmInstallOptions map[string]string 149 150 type HelmInstallValues struct { 151 // +optional 152 URLs []string `json:"urls,omitempty"` 153 154 // Selects a key of a ConfigMap item list. The value of ConfigMap can be 155 // a JSON or YAML string content. Use a key name with ".json" or ".yaml" or ".yml" 156 // extension name to specify a content type. 157 // +optional 158 ConfigMapRefs []DataObjectKeySelector `json:"configMapRefs,omitempty"` 159 160 // Selects a key of a Secrets item list. The value of Secrets can be 161 // a JSON or YAML string content. Use a key name with ".json" or ".yaml" or ".yml" 162 // extension name to specify a content type. 163 // +optional 164 SecretRefs []DataObjectKeySelector `json:"secretRefs,omitempty"` 165 166 // Helm install set values. It can specify multiple or separate values with commas(key1=val1,key2=val2). 167 // +optional 168 SetValues []string `json:"setValues,omitempty"` 169 170 // Helm install set JSON values. It can specify multiple or separate values with commas(key1=jsonval1,key2=jsonval2). 171 // +optional 172 SetJSONValues []string `json:"setJSONValues,omitempty"` 173 } 174 175 type HelmValuesMapping struct { 176 HelmValuesMappingItem `json:",inline"` 177 178 // Helm value mapping items for extra items. 179 // +patchMergeKey=name 180 // +patchStrategy=merge,retainKeys 181 // +listType=map 182 // +listMapKey=name 183 // +optional 184 ExtraItems []HelmValuesMappingExtraItem `json:"extras,omitempty"` 185 } 186 187 type HelmValuesMappingExtraItem struct { 188 HelmValuesMappingItem `json:",inline"` 189 190 // Name of the item. 191 // +kubebuilder:validation:Required 192 Name string `json:"name"` 193 } 194 195 type HelmValueMapType struct { 196 // replicaCount sets the replicaCount value mapping key. 197 // +optional 198 ReplicaCount string `json:"replicaCount,omitempty"` 199 200 // persistentVolumeEnabled sets the persistent volume enabled mapping key. 201 // +optional 202 PVEnabled string `json:"persistentVolumeEnabled,omitempty"` 203 204 // storageClass sets the storageClass mapping key. 205 // +optional 206 StorageClass string `json:"storageClass,omitempty"` 207 } 208 209 type HelmJSONValueMapType struct { 210 // tolerations sets the toleration mapping key. 211 // +optional 212 Tolerations string `json:"tolerations,omitempty"` 213 } 214 215 type HelmValuesMappingItem struct { 216 // valueMap define the "key" mapping values. Valid keys are replicaCount, 217 // persistentVolumeEnabled, and storageClass. Enum values explained: 218 // `"replicaCount"` sets the replicaCount value mapping key. 219 // `"persistentVolumeEnabled"` sets the persistent volume enabled mapping key. 220 // `"storageClass"` sets the storageClass mapping key. 221 // +optional 222 HelmValueMap HelmValueMapType `json:"valueMap,omitempty"` 223 224 // jsonMap defines the "key" mapping values. The valid key is tolerations. 225 // Enum values explained: 226 // `"tolerations"` sets the toleration mapping key. 227 // +optional 228 HelmJSONMap HelmJSONValueMapType `json:"jsonMap,omitempty"` 229 230 // resources sets resources related mapping keys. 231 // +optional 232 ResourcesMapping *ResourceMappingItem `json:"resources,omitempty"` 233 } 234 235 type ResourceMappingItem struct { 236 237 // storage sets the storage size value mapping key. 238 // +optional 239 Storage string `json:"storage,omitempty"` 240 241 // cpu sets CPU requests and limits mapping keys. 242 // +optional 243 CPU *ResourceReqLimItem `json:"cpu,omitempty"` 244 245 // memory sets Memory requests and limits mapping keys. 246 // +optional 247 Memory *ResourceReqLimItem `json:"memory,omitempty"` 248 } 249 250 type CliPlugin struct { 251 // Name of the plugin. 252 // +kubebuilder:validation:Required 253 Name string `json:"name"` 254 255 // The index repository of the plugin. 256 // +kubebuilder:validation:Required 257 IndexRepository string `json:"indexRepository"` 258 259 // The description of the plugin. 260 // +optional 261 Description string `json:"description,omitempty"` 262 } 263 264 func (r *ResourceMappingItem) HasStorageMapping() bool { 265 return !(r == nil || r.Storage == "") 266 } 267 268 func (r *ResourceMappingItem) HasCPUReqMapping() bool { 269 return !(r == nil || r.CPU == nil || r.CPU.Requests == "") 270 } 271 272 func (r *ResourceMappingItem) HasMemReqMapping() bool { 273 return !(r == nil || r.CPU == nil || r.Memory.Requests == "") 274 } 275 276 func (r *ResourceMappingItem) HasCPULimMapping() bool { 277 return !(r == nil || r.CPU == nil || r.CPU.Limits == "") 278 } 279 280 func (r *ResourceMappingItem) HasMemLimMapping() bool { 281 return !(r == nil || r.CPU == nil || r.Memory.Limits == "") 282 } 283 284 type ResourceReqLimItem struct { 285 // Requests value mapping key. 286 // +optional 287 Requests string `json:"requests,omitempty"` 288 289 // Limits value mapping key. 290 // +optional 291 Limits string `json:"limits,omitempty"` 292 } 293 294 type DataObjectKeySelector struct { 295 // Object name of the referent. 296 // +kubebuilder:validation:Required 297 // +kubebuilder:validation:Pattern:=`^[a-z0-9]([a-z0-9\.\-]*[a-z0-9])?$` 298 Name string `json:"name"` // need corev1.LocalObjectReference 299 300 // The key to select. 301 // +kubebuilder:validation:Required 302 Key string `json:"key"` 303 } 304 305 type AddonDefaultInstallSpecItem struct { 306 AddonInstallSpec `json:",inline"` 307 308 // Addon installs parameters selectors by default. If multiple selectors are provided, 309 // all selectors must evaluate to true. 310 // +optional 311 Selectors []SelectorRequirement `json:"selectors,omitempty"` 312 } 313 314 type AddonInstallSpec struct { 315 AddonInstallSpecItem `json:",inline"` 316 317 // enabled can be set if there are no specific installation attributes to be set. 318 // +optional 319 Enabled bool `json:"enabled,omitempty"` 320 321 // Installs spec. for extra items. 322 // +patchMergeKey=name 323 // +patchStrategy=merge,retainKeys 324 // +listType=map 325 // +listMapKey=name 326 // +optional 327 ExtraItems []AddonInstallExtraItem `json:"extras,omitempty"` 328 } 329 330 func (r *AddonInstallSpec) IsDisabled() bool { 331 return r == nil || !r.Enabled 332 } 333 334 func (r *AddonInstallSpec) HasSetValues() bool { 335 if r == nil { 336 return false 337 } 338 339 if !r.AddonInstallSpecItem.IsEmpty() { 340 return true 341 } 342 for _, i := range r.ExtraItems { 343 if !i.IsEmpty() { 344 return true 345 } 346 } 347 return false 348 } 349 350 type AddonInstallExtraItem struct { 351 AddonInstallSpecItem `json:",inline"` 352 353 // Name of the item. 354 // +kubebuilder:validation:Required 355 Name string `json:"name"` 356 } 357 358 type AddonInstallSpecItem struct { 359 // Replicas value. 360 // +optional 361 Replicas *int32 `json:"replicas,omitempty"` 362 363 // Persistent Volume Enabled value. 364 // +optional 365 PVEnabled *bool `json:"persistentVolumeEnabled,omitempty"` 366 367 // Storage class name. 368 // +optional 369 StorageClass string `json:"storageClass,omitempty"` 370 371 // Tolerations JSON array string value. 372 // +optional 373 Tolerations string `json:"tolerations,omitempty"` 374 375 // Resource requirements. 376 // +optional 377 Resources ResourceRequirements `json:"resources,omitempty"` 378 } 379 380 func (r AddonInstallSpecItem) IsEmpty() bool { 381 return r.Replicas == nil && 382 r.PVEnabled == nil && 383 r.StorageClass == "" && 384 r.Tolerations == "" && 385 len(r.Resources.Requests) == 0 386 } 387 388 type ResourceRequirements struct { 389 // Limits describes the maximum amount of compute resources allowed. 390 // More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/. 391 // +optional 392 Limits corev1.ResourceList `json:"limits,omitempty"` 393 // Requests describes the minimum amount of compute resources required. 394 // If Requests is omitted for a container, it defaults to Limits if that is explicitly specified; 395 // otherwise, it defaults to an implementation-defined value. 396 // More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/. 397 // +optional 398 Requests corev1.ResourceList `json:"requests,omitempty"` 399 } 400 401 // +genclient 402 // +genclient:nonNamespaced 403 // +k8s:openapi-gen=true 404 // +kubebuilder:object:root=true 405 // +kubebuilder:subresource:status 406 // +kubebuilder:resource:categories={kubeblocks},scope=Cluster 407 // +kubebuilder:printcolumn:name="TYPE",type="string",JSONPath=".spec.type",description="addon types" 408 // +kubebuilder:printcolumn:name="STATUS",type="string",JSONPath=".status.phase",description="status phase" 409 // +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp" 410 411 // Addon is the Schema for the add-ons API. 412 type Addon struct { 413 metav1.TypeMeta `json:",inline"` 414 metav1.ObjectMeta `json:"metadata,omitempty"` 415 416 Spec AddonSpec `json:"spec,omitempty"` 417 Status AddonStatus `json:"status,omitempty"` 418 } 419 420 // +kubebuilder:object:root=true 421 422 // AddonList contains a list of add-ons. 423 type AddonList struct { 424 metav1.TypeMeta `json:",inline"` 425 metav1.ListMeta `json:"metadata,omitempty"` 426 Items []Addon `json:"items"` 427 } 428 429 func init() { 430 SchemeBuilder.Register(&Addon{}, &AddonList{}) 431 } 432 433 // GetExtraNames extracts extra items' name. 434 func (r *Addon) GetExtraNames() []string { 435 if r == nil { 436 return nil 437 } 438 switch r.Spec.Type { 439 case HelmType: 440 if r.Spec.Helm == nil || len(r.Spec.Helm.ValuesMapping.ExtraItems) == 0 { 441 return nil 442 } 443 // r.Spec.DefaultInstallValues has minItem=1 constraint 444 names := make([]string, 0, len(r.Spec.Helm.ValuesMapping.ExtraItems)) 445 for _, i := range r.Spec.Helm.ValuesMapping.ExtraItems { 446 names = append(names, i.Name) 447 } 448 return names 449 default: 450 return nil 451 } 452 453 } 454 455 func buildSelectorStrings(selectors []SelectorRequirement) []string { 456 l := len(selectors) 457 if l == 0 { 458 return nil 459 } 460 sl := make([]string, 0, l) 461 for _, req := range selectors { 462 sl = append(sl, req.String()) 463 } 464 return sl 465 } 466 467 // GetSelectorsStrings extracts selectors to string representations. 468 func (r AddonDefaultInstallSpecItem) GetSelectorsStrings() []string { 469 return buildSelectorStrings(r.Selectors) 470 } 471 472 // GetSelectorsStrings extracts selectors to string representations. 473 func (r *InstallableSpec) GetSelectorsStrings() []string { 474 if r == nil { 475 return nil 476 } 477 return buildSelectorStrings(r.Selectors) 478 } 479 480 func (r SelectorRequirement) String() string { 481 return fmt.Sprintf("{key=%s,op=%s,values=%v}", 482 r.Key, r.Operator, r.Values) 483 } 484 485 // MatchesFromConfig matches the selector requirement value. 486 func (r SelectorRequirement) MatchesFromConfig() bool { 487 verIf := viper.Get(constant.CfgKeyServerInfo) 488 ver, ok := verIf.(version.Info) 489 if !ok { 490 return false 491 } 492 var l string 493 switch r.Key { 494 case KubeGitVersion: 495 l = ver.GitVersion 496 case KubeVersion: 497 l = fmt.Sprintf("%s.%s", ver.Major, ver.Minor) 498 case KubeProvider: 499 l = viper.GetString(constant.CfgKeyProvider) 500 } 501 return r.matchesLine(l) 502 } 503 504 func (r SelectorRequirement) matchesLine(line string) bool { 505 processor := func(op bool, predicate func(string) bool) bool { 506 if len(r.Values) == 0 { 507 return !op 508 } 509 for _, v := range r.Values { 510 m := predicate(v) 511 if op && m { 512 return true 513 } else if !op { 514 if m { 515 return false 516 } 517 continue 518 } 519 } 520 return !op 521 } 522 523 containsProcessor := func(op bool) bool { 524 return processor(op, func(v string) bool { 525 return strings.Contains(line, v) 526 }) 527 } 528 529 matchRegexProcessor := func(op bool) bool { 530 return processor(op, func(v string) bool { 531 regex, err := regexp.Compile(v) 532 if err != nil { 533 return false 534 } 535 return regex.Match([]byte(line)) 536 }) 537 } 538 539 switch r.Operator { 540 case Contains: 541 return containsProcessor(true) 542 case DoesNotContain: 543 return containsProcessor(false) 544 case MatchRegex: 545 return matchRegexProcessor(true) 546 case DoesNotMatchRegex: 547 return matchRegexProcessor(false) 548 default: 549 return false 550 } 551 } 552 553 // GetEnabled provides the Enabled property getter. 554 func (r *AddonInstallSpec) GetEnabled() bool { 555 if r == nil { 556 return false 557 } 558 return r.Enabled 559 } 560 561 // BuildMergedValues merges values from a AddonInstallSpec and pre-set values. 562 func (r *HelmTypeInstallSpec) BuildMergedValues(installSpec *AddonInstallSpec) HelmInstallValues { 563 if r == nil { 564 return HelmInstallValues{} 565 } 566 installValues := r.InstallValues 567 processor := func(installSpecItem AddonInstallSpecItem, valueMapping HelmValuesMappingItem) { 568 var pvEnabled *bool 569 defer func() { 570 if v := valueMapping.HelmValueMap.PVEnabled; v != "" && pvEnabled != nil { 571 installValues.SetValues = append(installValues.SetValues, 572 fmt.Sprintf("%s=%v", v, *pvEnabled)) 573 } 574 }() 575 576 if installSpecItem.PVEnabled != nil { 577 b := *installSpecItem.PVEnabled 578 pvEnabled = &b 579 } 580 581 if installSpecItem.Replicas != nil && *installSpecItem.Replicas >= 0 { 582 if v := valueMapping.HelmValueMap.ReplicaCount; v != "" { 583 installValues.SetValues = append(installValues.SetValues, 584 fmt.Sprintf("%s=%v", v, *installSpecItem.Replicas)) 585 } 586 } 587 588 if installSpecItem.StorageClass != "" { 589 if v := valueMapping.HelmValueMap.StorageClass; v != "" { 590 if installSpecItem.StorageClass == "-" { 591 installValues.SetValues = append(installValues.SetValues, 592 fmt.Sprintf("%s=null", v)) 593 } else { 594 installValues.SetValues = append(installValues.SetValues, 595 fmt.Sprintf("%s=%v", v, installSpecItem.StorageClass)) 596 } 597 } 598 } 599 600 if installSpecItem.Tolerations != "" { 601 if v := valueMapping.HelmJSONMap.Tolerations; v != "" { 602 installValues.SetJSONValues = append(installValues.SetJSONValues, 603 fmt.Sprintf("%s=%s", v, installSpecItem.Tolerations)) 604 } 605 } 606 607 if valueMapping.ResourcesMapping == nil { 608 return 609 } 610 611 for k, v := range installSpecItem.Resources.Requests { 612 switch k { 613 case corev1.ResourceStorage: 614 if valueMapping.ResourcesMapping.HasStorageMapping() { 615 installValues.SetValues = append(installValues.SetValues, 616 fmt.Sprintf("%s=%v", valueMapping.ResourcesMapping.Storage, v.ToUnstructured())) 617 } 618 case corev1.ResourceCPU: 619 if valueMapping.ResourcesMapping.HasCPUReqMapping() { 620 installValues.SetValues = append(installValues.SetValues, 621 fmt.Sprintf("%s=%v", valueMapping.ResourcesMapping.CPU.Requests, v.ToUnstructured())) 622 } 623 case corev1.ResourceMemory: 624 if valueMapping.ResourcesMapping.HasMemReqMapping() { 625 installValues.SetValues = append(installValues.SetValues, 626 fmt.Sprintf("%s=%v", valueMapping.ResourcesMapping.Memory.Requests, v.ToUnstructured())) 627 } 628 } 629 } 630 631 for k, v := range installSpecItem.Resources.Limits { 632 switch k { 633 case corev1.ResourceCPU: 634 if valueMapping.ResourcesMapping.HasCPULimMapping() { 635 installValues.SetValues = append(installValues.SetValues, 636 fmt.Sprintf("%s=%v", valueMapping.ResourcesMapping.CPU.Limits, v.ToUnstructured())) 637 } 638 case corev1.ResourceMemory: 639 if valueMapping.ResourcesMapping.HasMemLimMapping() { 640 installValues.SetValues = append(installValues.SetValues, 641 fmt.Sprintf("%s=%v", valueMapping.ResourcesMapping.Memory.Limits, v.ToUnstructured())) 642 } 643 } 644 } 645 646 } 647 processor(installSpec.AddonInstallSpecItem, r.ValuesMapping.HelmValuesMappingItem) 648 for _, ei := range installSpec.ExtraItems { 649 for _, mei := range r.ValuesMapping.ExtraItems { 650 if ei.Name != mei.Name { 651 continue 652 } 653 processor(ei.AddonInstallSpecItem, mei.HelmValuesMappingItem) 654 break 655 } 656 } 657 return installValues 658 } 659 660 // BuildContainerArgs derives helm container args. 661 func (r *HelmTypeInstallSpec) BuildContainerArgs(helmContainer *corev1.Container, installValues HelmInstallValues) error { 662 // Add extra helm installation option flags 663 for k, v := range r.InstallOptions { 664 helmContainer.Args = append(helmContainer.Args, fmt.Sprintf("--%s", k)) 665 if v != "" { 666 helmContainer.Args = append(helmContainer.Args, v) 667 } 668 } 669 670 // Sets values from URL. 671 for _, urlValue := range installValues.URLs { 672 helmContainer.Args = append(helmContainer.Args, "--values", urlValue) 673 } 674 675 // Sets key1=val1,key2=val2 value. 676 if len(installValues.SetValues) > 0 { 677 helmContainer.Args = append(helmContainer.Args, "--set", 678 strings.Join(installValues.SetValues, ",")) 679 } 680 681 // Sets key1=jsonval1,key2=jsonval2 JSON value. It can be applied to multiple. 682 for _, v := range installValues.SetJSONValues { 683 helmContainer.Args = append(helmContainer.Args, "--set-json", v) 684 } 685 return nil 686 } 687 688 // GetSortedDefaultInstallValues returns DefaultInstallValues items with items that have 689 // a provided selector first. 690 func (r AddonSpec) GetSortedDefaultInstallValues() []AddonDefaultInstallSpecItem { 691 values := make([]AddonDefaultInstallSpecItem, 0, len(r.DefaultInstallValues)) 692 nvalues := make([]AddonDefaultInstallSpecItem, 0, len(r.DefaultInstallValues)) 693 for _, i := range r.DefaultInstallValues { 694 if len(i.Selectors) > 0 { 695 values = append(values, i) 696 } else { 697 nvalues = append(nvalues, i) 698 } 699 } 700 if len(nvalues) > 0 { 701 values = append(values, nvalues...) 702 } 703 return values 704 } 705 706 // NewAddonInstallSpecItem creates an initialized AddonInstallSpecItem object. 707 func NewAddonInstallSpecItem() AddonInstallSpecItem { 708 return AddonInstallSpecItem{ 709 Resources: ResourceRequirements{ 710 Requests: corev1.ResourceList{}, 711 Limits: corev1.ResourceList{}, 712 }, 713 } 714 }