1 /* 2 Copyright 2024 The Flux authors 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 v2 18 19 import ( 20 "strings" 21 "time" 22 23 apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" 24 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 "k8s.io/apimachinery/pkg/types" 26 "sigs.k8s.io/yaml" 27 28 "github.com/fluxcd/pkg/apis/kustomize" 29 "github.com/fluxcd/pkg/apis/meta" 30 ) 31 32 const ( 33 // HelmReleaseKind is the kind in string format. 34 HelmReleaseKind = "HelmRelease" 35 // HelmReleaseFinalizer is set on a HelmRelease when it is first handled by 36 // the controller, and removed when this object is deleted. 37 HelmReleaseFinalizer = "finalizers.fluxcd.io" 38 ) 39 40 const ( 41 // defaultMaxHistory is the default number of Helm release versions to keep. 42 defaultMaxHistory = 5 43 ) 44 45 // Kustomize Helm PostRenderer specification. 46 type Kustomize struct { 47 // Strategic merge and JSON patches, defined as inline YAML objects, 48 // capable of targeting objects based on kind, label and annotation selectors. 49 // +optional 50 Patches []kustomize.Patch `json:"patches,omitempty"` 51 52 // Images is a list of (image name, new name, new tag or digest) 53 // for changing image names, tags or digests. This can also be achieved with a 54 // patch, but this operator is simpler to specify. 55 // +optional 56 Images []kustomize.Image `json:"images,omitempty" json:"images,omitempty"` 57 } 58 59 // PostRenderer contains a Helm PostRenderer specification. 60 type PostRenderer struct { 61 // Kustomization to apply as PostRenderer. 62 // +optional 63 Kustomize *Kustomize `json:"kustomize,omitempty"` 64 } 65 66 // HelmReleaseSpec defines the desired state of a Helm release. 67 // +kubebuilder:validation:XValidation:rule="(has(self.chart) && !has(self.chartRef)) || (!has(self.chart) && has(self.chartRef))", message="either chart or chartRef must be set" 68 type HelmReleaseSpec struct { 69 // Chart defines the template of the v1.HelmChart that should be created 70 // for this HelmRelease. 71 // +optional 72 Chart *HelmChartTemplate `json:"chart,omitempty"` 73 74 // ChartRef holds a reference to a source controller resource containing the 75 // Helm chart artifact. 76 // +optional 77 ChartRef *CrossNamespaceSourceReference `json:"chartRef,omitempty"` 78 79 // Interval at which to reconcile the Helm release. 80 // +kubebuilder:validation:Type=string 81 // +kubebuilder:validation:Pattern="^([0-9]+(\\.[0-9]+)?(ms|s|m|h))+$" 82 // +required 83 Interval metav1.Duration `json:"interval"` 84 85 // KubeConfig for reconciling the HelmRelease on a remote cluster. 86 // When used in combination with HelmReleaseSpec.ServiceAccountName, 87 // forces the controller to act on behalf of that Service Account at the 88 // target cluster. 89 // If the --default-service-account flag is set, its value will be used as 90 // a controller level fallback for when HelmReleaseSpec.ServiceAccountName 91 // is empty. 92 // +optional 93 KubeConfig *meta.KubeConfigReference `json:"kubeConfig,omitempty"` 94 95 // Suspend tells the controller to suspend reconciliation for this HelmRelease, 96 // it does not apply to already started reconciliations. Defaults to false. 97 // +optional 98 Suspend bool `json:"suspend,omitempty"` 99 100 // ReleaseName used for the Helm release. Defaults to a composition of 101 // '[TargetNamespace-]Name'. 102 // +kubebuilder:validation:MinLength=1 103 // +kubebuilder:validation:MaxLength=53 104 // +kubebuilder:validation:Optional 105 // +optional 106 ReleaseName string `json:"releaseName,omitempty"` 107 108 // TargetNamespace to target when performing operations for the HelmRelease. 109 // Defaults to the namespace of the HelmRelease. 110 // +kubebuilder:validation:MinLength=1 111 // +kubebuilder:validation:MaxLength=63 112 // +kubebuilder:validation:Optional 113 // +optional 114 TargetNamespace string `json:"targetNamespace,omitempty"` 115 116 // StorageNamespace used for the Helm storage. 117 // Defaults to the namespace of the HelmRelease. 118 // +kubebuilder:validation:MinLength=1 119 // +kubebuilder:validation:MaxLength=63 120 // +kubebuilder:validation:Optional 121 // +optional 122 StorageNamespace string `json:"storageNamespace,omitempty"` 123 124 // DependsOn may contain a meta.NamespacedObjectReference slice with 125 // references to HelmRelease resources that must be ready before this HelmRelease 126 // can be reconciled. 127 // +optional 128 DependsOn []meta.NamespacedObjectReference `json:"dependsOn,omitempty"` 129 130 // Timeout is the time to wait for any individual Kubernetes operation (like Jobs 131 // for hooks) during the performance of a Helm action. Defaults to '5m0s'. 132 // +kubebuilder:validation:Type=string 133 // +kubebuilder:validation:Pattern="^([0-9]+(\\.[0-9]+)?(ms|s|m|h))+$" 134 // +optional 135 Timeout *metav1.Duration `json:"timeout,omitempty"` 136 137 // MaxHistory is the number of revisions saved by Helm for this HelmRelease. 138 // Use '0' for an unlimited number of revisions; defaults to '5'. 139 // +optional 140 MaxHistory *int `json:"maxHistory,omitempty"` 141 142 // The name of the Kubernetes service account to impersonate 143 // when reconciling this HelmRelease. 144 // +kubebuilder:validation:MinLength=1 145 // +kubebuilder:validation:MaxLength=253 146 // +optional 147 ServiceAccountName string `json:"serviceAccountName,omitempty"` 148 149 // PersistentClient tells the controller to use a persistent Kubernetes 150 // client for this release. When enabled, the client will be reused for the 151 // duration of the reconciliation, instead of being created and destroyed 152 // for each (step of a) Helm action. 153 // 154 // This can improve performance, but may cause issues with some Helm charts 155 // that for example do create Custom Resource Definitions during installation 156 // outside Helm's CRD lifecycle hooks, which are then not observed to be 157 // available by e.g. post-install hooks. 158 // 159 // If not set, it defaults to true. 160 // 161 // +optional 162 PersistentClient *bool `json:"persistentClient,omitempty"` 163 164 // DriftDetection holds the configuration for detecting and handling 165 // differences between the manifest in the Helm storage and the resources 166 // currently existing in the cluster. 167 // +optional 168 DriftDetection *DriftDetection `json:"driftDetection,omitempty"` 169 170 // Install holds the configuration for Helm install actions for this HelmRelease. 171 // +optional 172 Install *Install `json:"install,omitempty"` 173 174 // Upgrade holds the configuration for Helm upgrade actions for this HelmRelease. 175 // +optional 176 Upgrade *Upgrade `json:"upgrade,omitempty"` 177 178 // Test holds the configuration for Helm test actions for this HelmRelease. 179 // +optional 180 Test *Test `json:"test,omitempty"` 181 182 // Rollback holds the configuration for Helm rollback actions for this HelmRelease. 183 // +optional 184 Rollback *Rollback `json:"rollback,omitempty"` 185 186 // Uninstall holds the configuration for Helm uninstall actions for this HelmRelease. 187 // +optional 188 Uninstall *Uninstall `json:"uninstall,omitempty"` 189 190 // ValuesFrom holds references to resources containing Helm values for this HelmRelease, 191 // and information about how they should be merged. 192 ValuesFrom []ValuesReference `json:"valuesFrom,omitempty"` 193 194 // Values holds the values for this Helm release. 195 // +optional 196 Values *apiextensionsv1.JSON `json:"values,omitempty"` 197 198 // PostRenderers holds an array of Helm PostRenderers, which will be applied in order 199 // of their definition. 200 // +optional 201 PostRenderers []PostRenderer `json:"postRenderers,omitempty"` 202 } 203 204 // DriftDetectionMode represents the modes in which a controller can detect and 205 // handle differences between the manifest in the Helm storage and the resources 206 // currently existing in the cluster. 207 type DriftDetectionMode string 208 209 var ( 210 // DriftDetectionEnabled instructs the controller to actively detect any 211 // changes between the manifest in the Helm storage and the resources 212 // currently existing in the cluster. 213 // If any differences are detected, the controller will automatically 214 // correct the cluster state by performing a Helm upgrade. 215 DriftDetectionEnabled DriftDetectionMode = "enabled" 216 217 // DriftDetectionWarn instructs the controller to actively detect any 218 // changes between the manifest in the Helm storage and the resources 219 // currently existing in the cluster. 220 // If any differences are detected, the controller will emit a warning 221 // without automatically correcting the cluster state. 222 DriftDetectionWarn DriftDetectionMode = "warn" 223 224 // DriftDetectionDisabled instructs the controller to skip detection of 225 // differences entirely. 226 // This is the default behavior, and the controller will not actively 227 // detect or respond to differences between the manifest in the Helm 228 // storage and the resources currently existing in the cluster. 229 DriftDetectionDisabled DriftDetectionMode = "disabled" 230 ) 231 232 var ( 233 // DriftDetectionMetadataKey is the label or annotation key used to disable 234 // the diffing of an object. 235 DriftDetectionMetadataKey = GroupVersion.Group + "/driftDetection" 236 // DriftDetectionDisabledValue is the value used to disable the diffing of 237 // an object using DriftDetectionMetadataKey. 238 DriftDetectionDisabledValue = "disabled" 239 ) 240 241 // IgnoreRule defines a rule to selectively disregard specific changes during 242 // the drift detection process. 243 type IgnoreRule struct { 244 // Paths is a list of JSON Pointer (RFC 6901) paths to be excluded from 245 // consideration in a Kubernetes object. 246 // +required 247 Paths []string `json:"paths"` 248 249 // Target is a selector for specifying Kubernetes objects to which this 250 // rule applies. 251 // If Target is not set, the Paths will be ignored for all Kubernetes 252 // objects within the manifest of the Helm release. 253 // +optional 254 Target *kustomize.Selector `json:"target,omitempty"` 255 } 256 257 // DriftDetection defines the strategy for performing differential analysis and 258 // provides a way to define rules for ignoring specific changes during this 259 // process. 260 type DriftDetection struct { 261 // Mode defines how differences should be handled between the Helm manifest 262 // and the manifest currently applied to the cluster. 263 // If not explicitly set, it defaults to DiffModeDisabled. 264 // +kubebuilder:validation:Enum=enabled;warn;disabled 265 // +optional 266 Mode DriftDetectionMode `json:"mode,omitempty"` 267 268 // Ignore contains a list of rules for specifying which changes to ignore 269 // during diffing. 270 // +optional 271 Ignore []IgnoreRule `json:"ignore,omitempty"` 272 } 273 274 // GetMode returns the DiffMode set on the Diff, or DiffModeDisabled if not 275 // set. 276 func (d DriftDetection) GetMode() DriftDetectionMode { 277 if d.Mode == "" { 278 return DriftDetectionDisabled 279 } 280 return d.Mode 281 } 282 283 // MustDetectChanges returns true if the DiffMode is set to DiffModeEnabled or 284 // DiffModeWarn. 285 func (d DriftDetection) MustDetectChanges() bool { 286 return d.GetMode() == DriftDetectionEnabled || d.GetMode() == DriftDetectionWarn 287 } 288 289 // HelmChartTemplate defines the template from which the controller will 290 // generate a v1.HelmChart object in the same namespace as the referenced 291 // v1.Source. 292 type HelmChartTemplate struct { 293 // ObjectMeta holds the template for metadata like labels and annotations. 294 // +optional 295 ObjectMeta *HelmChartTemplateObjectMeta `json:"metadata,omitempty"` 296 297 // Spec holds the template for the v1.HelmChartSpec for this HelmRelease. 298 // +required 299 Spec HelmChartTemplateSpec `json:"spec"` 300 } 301 302 // HelmChartTemplateObjectMeta defines the template for the ObjectMeta of a 303 // v1.HelmChart. 304 type HelmChartTemplateObjectMeta struct { 305 // Map of string keys and values that can be used to organize and categorize 306 // (scope and select) objects. 307 // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ 308 // +optional 309 Labels map[string]string `json:"labels,omitempty"` 310 311 // Annotations is an unstructured key value map stored with a resource that may be 312 // set by external tools to store and retrieve arbitrary metadata. They are not 313 // queryable and should be preserved when modifying objects. 314 // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ 315 // +optional 316 Annotations map[string]string `json:"annotations,omitempty"` 317 } 318 319 // HelmChartTemplateSpec defines the template from which the controller will 320 // generate a v1.HelmChartSpec object. 321 type HelmChartTemplateSpec struct { 322 // The name or path the Helm chart is available at in the SourceRef. 323 // +kubebuilder:validation:MinLength=1 324 // +kubebuilder:validation:MaxLength=2048 325 // +required 326 Chart string `json:"chart"` 327 328 // Version semver expression, ignored for charts from v1.GitRepository and 329 // v1beta2.Bucket sources. Defaults to latest when omitted. 330 // +kubebuilder:default:=* 331 // +optional 332 Version string `json:"version,omitempty"` 333 334 // The name and namespace of the v1.Source the chart is available at. 335 // +required 336 SourceRef CrossNamespaceObjectReference `json:"sourceRef"` 337 338 // Interval at which to check the v1.Source for updates. Defaults to 339 // 'HelmReleaseSpec.Interval'. 340 // +kubebuilder:validation:Type=string 341 // +kubebuilder:validation:Pattern="^([0-9]+(\\.[0-9]+)?(ms|s|m|h))+$" 342 // +optional 343 Interval *metav1.Duration `json:"interval,omitempty"` 344 345 // Determines what enables the creation of a new artifact. Valid values are 346 // ('ChartVersion', 'Revision'). 347 // See the documentation of the values for an explanation on their behavior. 348 // Defaults to ChartVersion when omitted. 349 // +kubebuilder:validation:Enum=ChartVersion;Revision 350 // +kubebuilder:default:=ChartVersion 351 // +optional 352 ReconcileStrategy string `json:"reconcileStrategy,omitempty"` 353 354 // Alternative list of values files to use as the chart values (values.yaml 355 // is not included by default), expected to be a relative path in the SourceRef. 356 // Values files are merged in the order of this list with the last file overriding 357 // the first. Ignored when omitted. 358 // +optional 359 ValuesFiles []string `json:"valuesFiles,omitempty"` 360 361 // IgnoreMissingValuesFiles controls whether to silently ignore missing values files rather than failing. 362 // +optional 363 IgnoreMissingValuesFiles bool `json:"ignoreMissingValuesFiles,omitempty"` 364 365 // Verify contains the secret name containing the trusted public keys 366 // used to verify the signature and specifies which provider to use to check 367 // whether OCI image is authentic. 368 // This field is only supported for OCI sources. 369 // Chart dependencies, which are not bundled in the umbrella chart artifact, 370 // are not verified. 371 // +optional 372 Verify *HelmChartTemplateVerification `json:"verify,omitempty"` 373 } 374 375 // GetInterval returns the configured interval for the v1.HelmChart, 376 // or the given default. 377 func (in HelmChartTemplate) GetInterval(defaultInterval metav1.Duration) metav1.Duration { 378 if in.Spec.Interval == nil { 379 return defaultInterval 380 } 381 return *in.Spec.Interval 382 } 383 384 // GetNamespace returns the namespace targeted namespace for the 385 // v1.HelmChart, or the given default. 386 func (in HelmChartTemplate) GetNamespace(defaultNamespace string) string { 387 if in.Spec.SourceRef.Namespace == "" { 388 return defaultNamespace 389 } 390 return in.Spec.SourceRef.Namespace 391 } 392 393 // HelmChartTemplateVerification verifies the authenticity of an OCI Helm chart. 394 type HelmChartTemplateVerification struct { 395 // Provider specifies the technology used to sign the OCI Helm chart. 396 // +kubebuilder:validation:Enum=cosign;notation 397 // +kubebuilder:default:=cosign 398 Provider string `json:"provider"` 399 400 // SecretRef specifies the Kubernetes Secret containing the 401 // trusted public keys. 402 // +optional 403 SecretRef *meta.LocalObjectReference `json:"secretRef,omitempty"` 404 } 405 406 // Remediation defines a consistent interface for InstallRemediation and 407 // UpgradeRemediation. 408 // +kubebuilder:object:generate=false 409 type Remediation interface { 410 GetRetries() int 411 MustIgnoreTestFailures(bool) bool 412 MustRemediateLastFailure() bool 413 GetStrategy() RemediationStrategy 414 GetFailureCount(hr *HelmRelease) int64 415 IncrementFailureCount(hr *HelmRelease) 416 RetriesExhausted(hr *HelmRelease) bool 417 } 418 419 // Install holds the configuration for Helm install actions performed for this 420 // HelmRelease. 421 type Install struct { 422 // Timeout is the time to wait for any individual Kubernetes operation (like 423 // Jobs for hooks) during the performance of a Helm install action. Defaults to 424 // 'HelmReleaseSpec.Timeout'. 425 // +kubebuilder:validation:Type=string 426 // +kubebuilder:validation:Pattern="^([0-9]+(\\.[0-9]+)?(ms|s|m|h))+$" 427 // +optional 428 Timeout *metav1.Duration `json:"timeout,omitempty"` 429 430 // Remediation holds the remediation configuration for when the Helm install 431 // action for the HelmRelease fails. The default is to not perform any action. 432 // +optional 433 Remediation *InstallRemediation `json:"remediation,omitempty"` 434 435 // DisableWait disables the waiting for resources to be ready after a Helm 436 // install has been performed. 437 // +optional 438 DisableWait bool `json:"disableWait,omitempty"` 439 440 // DisableWaitForJobs disables waiting for jobs to complete after a Helm 441 // install has been performed. 442 // +optional 443 DisableWaitForJobs bool `json:"disableWaitForJobs,omitempty"` 444 445 // DisableHooks prevents hooks from running during the Helm install action. 446 // +optional 447 DisableHooks bool `json:"disableHooks,omitempty"` 448 449 // DisableOpenAPIValidation prevents the Helm install action from validating 450 // rendered templates against the Kubernetes OpenAPI Schema. 451 // +optional 452 DisableOpenAPIValidation bool `json:"disableOpenAPIValidation,omitempty"` 453 454 // DisableSchemaValidation prevents the Helm install action from validating 455 // the values against the JSON Schema. 456 // +optional 457 DisableSchemaValidation bool `json:"disableSchemaValidation,omitempty"` 458 459 // Replace tells the Helm install action to re-use the 'ReleaseName', but only 460 // if that name is a deleted release which remains in the history. 461 // +optional 462 Replace bool `json:"replace,omitempty"` 463 464 // SkipCRDs tells the Helm install action to not install any CRDs. By default, 465 // CRDs are installed if not already present. 466 // 467 // Deprecated use CRD policy (`crds`) attribute with value `Skip` instead. 468 // 469 // +deprecated 470 // +optional 471 SkipCRDs bool `json:"skipCRDs,omitempty"` 472 473 // CRDs upgrade CRDs from the Helm Chart's crds directory according 474 // to the CRD upgrade policy provided here. Valid values are `Skip`, 475 // `Create` or `CreateReplace`. Default is `Create` and if omitted 476 // CRDs are installed but not updated. 477 // 478 // Skip: do neither install nor replace (update) any CRDs. 479 // 480 // Create: new CRDs are created, existing CRDs are neither updated nor deleted. 481 // 482 // CreateReplace: new CRDs are created, existing CRDs are updated (replaced) 483 // but not deleted. 484 // 485 // By default, CRDs are applied (installed) during Helm install action. 486 // With this option users can opt in to CRD replace existing CRDs on Helm 487 // install actions, which is not (yet) natively supported by Helm. 488 // https://helm.sh/docs/chart_best_practices/custom_resource_definitions. 489 // 490 // +kubebuilder:validation:Enum=Skip;Create;CreateReplace 491 // +optional 492 CRDs CRDsPolicy `json:"crds,omitempty"` 493 494 // CreateNamespace tells the Helm install action to create the 495 // HelmReleaseSpec.TargetNamespace if it does not exist yet. 496 // On uninstall, the namespace will not be garbage collected. 497 // +optional 498 CreateNamespace bool `json:"createNamespace,omitempty"` 499 } 500 501 // GetTimeout returns the configured timeout for the Helm install action, 502 // or the given default. 503 func (in Install) GetTimeout(defaultTimeout metav1.Duration) metav1.Duration { 504 if in.Timeout == nil { 505 return defaultTimeout 506 } 507 return *in.Timeout 508 } 509 510 // GetRemediation returns the configured Remediation for the Helm install action. 511 func (in Install) GetRemediation() Remediation { 512 if in.Remediation == nil { 513 return InstallRemediation{} 514 } 515 return *in.Remediation 516 } 517 518 // InstallRemediation holds the configuration for Helm install remediation. 519 type InstallRemediation struct { 520 // Retries is the number of retries that should be attempted on failures before 521 // bailing. Remediation, using an uninstall, is performed between each attempt. 522 // Defaults to '0', a negative integer equals to unlimited retries. 523 // +optional 524 Retries int `json:"retries,omitempty"` 525 526 // IgnoreTestFailures tells the controller to skip remediation when the Helm 527 // tests are run after an install action but fail. Defaults to 528 // 'Test.IgnoreFailures'. 529 // +optional 530 IgnoreTestFailures *bool `json:"ignoreTestFailures,omitempty"` 531 532 // RemediateLastFailure tells the controller to remediate the last failure, when 533 // no retries remain. Defaults to 'false'. 534 // +optional 535 RemediateLastFailure *bool `json:"remediateLastFailure,omitempty"` 536 } 537 538 // GetRetries returns the number of retries that should be attempted on 539 // failures. 540 func (in InstallRemediation) GetRetries() int { 541 return in.Retries 542 } 543 544 // MustIgnoreTestFailures returns the configured IgnoreTestFailures or the given 545 // default. 546 func (in InstallRemediation) MustIgnoreTestFailures(def bool) bool { 547 if in.IgnoreTestFailures == nil { 548 return def 549 } 550 return *in.IgnoreTestFailures 551 } 552 553 // MustRemediateLastFailure returns whether to remediate the last failure when 554 // no retries remain. 555 func (in InstallRemediation) MustRemediateLastFailure() bool { 556 if in.RemediateLastFailure == nil { 557 return false 558 } 559 return *in.RemediateLastFailure 560 } 561 562 // GetStrategy returns the strategy to use for failure remediation. 563 func (in InstallRemediation) GetStrategy() RemediationStrategy { 564 return UninstallRemediationStrategy 565 } 566 567 // GetFailureCount gets the failure count. 568 func (in InstallRemediation) GetFailureCount(hr *HelmRelease) int64 { 569 return hr.Status.InstallFailures 570 } 571 572 // IncrementFailureCount increments the failure count. 573 func (in InstallRemediation) IncrementFailureCount(hr *HelmRelease) { 574 hr.Status.InstallFailures++ 575 } 576 577 // RetriesExhausted returns true if there are no remaining retries. 578 func (in InstallRemediation) RetriesExhausted(hr *HelmRelease) bool { 579 return in.Retries >= 0 && in.GetFailureCount(hr) > int64(in.Retries) 580 } 581 582 // CRDsPolicy defines the install/upgrade approach to use for CRDs when 583 // installing or upgrading a HelmRelease. 584 type CRDsPolicy string 585 586 const ( 587 // Skip CRDs do neither install nor replace (update) any CRDs. 588 Skip CRDsPolicy = "Skip" 589 // Create CRDs which do not already exist, do not replace (update) already existing 590 // CRDs and keep (do not delete) CRDs which no longer exist in the current release. 591 Create CRDsPolicy = "Create" 592 // Create CRDs which do not already exist, Replace (update) already existing CRDs 593 // and keep (do not delete) CRDs which no longer exist in the current release. 594 CreateReplace CRDsPolicy = "CreateReplace" 595 ) 596 597 // Upgrade holds the configuration for Helm upgrade actions for this 598 // HelmRelease. 599 type Upgrade struct { 600 // Timeout is the time to wait for any individual Kubernetes operation (like 601 // Jobs for hooks) during the performance of a Helm upgrade action. Defaults to 602 // 'HelmReleaseSpec.Timeout'. 603 // +kubebuilder:validation:Type=string 604 // +kubebuilder:validation:Pattern="^([0-9]+(\\.[0-9]+)?(ms|s|m|h))+$" 605 // +optional 606 Timeout *metav1.Duration `json:"timeout,omitempty"` 607 608 // Remediation holds the remediation configuration for when the Helm upgrade 609 // action for the HelmRelease fails. The default is to not perform any action. 610 // +optional 611 Remediation *UpgradeRemediation `json:"remediation,omitempty"` 612 613 // DisableWait disables the waiting for resources to be ready after a Helm 614 // upgrade has been performed. 615 // +optional 616 DisableWait bool `json:"disableWait,omitempty"` 617 618 // DisableWaitForJobs disables waiting for jobs to complete after a Helm 619 // upgrade has been performed. 620 // +optional 621 DisableWaitForJobs bool `json:"disableWaitForJobs,omitempty"` 622 623 // DisableHooks prevents hooks from running during the Helm upgrade action. 624 // +optional 625 DisableHooks bool `json:"disableHooks,omitempty"` 626 627 // DisableOpenAPIValidation prevents the Helm upgrade action from validating 628 // rendered templates against the Kubernetes OpenAPI Schema. 629 // +optional 630 DisableOpenAPIValidation bool `json:"disableOpenAPIValidation,omitempty"` 631 632 // DisableSchemaValidation prevents the Helm upgrade action from validating 633 // the values against the JSON Schema. 634 // +optional 635 DisableSchemaValidation bool `json:"disableSchemaValidation,omitempty"` 636 637 // Force forces resource updates through a replacement strategy. 638 // +optional 639 Force bool `json:"force,omitempty"` 640 641 // PreserveValues will make Helm reuse the last release's values and merge in 642 // overrides from 'Values'. Setting this flag makes the HelmRelease 643 // non-declarative. 644 // +optional 645 PreserveValues bool `json:"preserveValues,omitempty"` 646 647 // CleanupOnFail allows deletion of new resources created during the Helm 648 // upgrade action when it fails. 649 // +optional 650 CleanupOnFail bool `json:"cleanupOnFail,omitempty"` 651 652 // CRDs upgrade CRDs from the Helm Chart's crds directory according 653 // to the CRD upgrade policy provided here. Valid values are `Skip`, 654 // `Create` or `CreateReplace`. Default is `Skip` and if omitted 655 // CRDs are neither installed nor upgraded. 656 // 657 // Skip: do neither install nor replace (update) any CRDs. 658 // 659 // Create: new CRDs are created, existing CRDs are neither updated nor deleted. 660 // 661 // CreateReplace: new CRDs are created, existing CRDs are updated (replaced) 662 // but not deleted. 663 // 664 // By default, CRDs are not applied during Helm upgrade action. With this 665 // option users can opt-in to CRD upgrade, which is not (yet) natively supported by Helm. 666 // https://helm.sh/docs/chart_best_practices/custom_resource_definitions. 667 // 668 // +kubebuilder:validation:Enum=Skip;Create;CreateReplace 669 // +optional 670 CRDs CRDsPolicy `json:"crds,omitempty"` 671 } 672 673 // GetTimeout returns the configured timeout for the Helm upgrade action, or the 674 // given default. 675 func (in Upgrade) GetTimeout(defaultTimeout metav1.Duration) metav1.Duration { 676 if in.Timeout == nil { 677 return defaultTimeout 678 } 679 return *in.Timeout 680 } 681 682 // GetRemediation returns the configured Remediation for the Helm upgrade 683 // action. 684 func (in Upgrade) GetRemediation() Remediation { 685 if in.Remediation == nil { 686 return UpgradeRemediation{} 687 } 688 return *in.Remediation 689 } 690 691 // UpgradeRemediation holds the configuration for Helm upgrade remediation. 692 type UpgradeRemediation struct { 693 // Retries is the number of retries that should be attempted on failures before 694 // bailing. Remediation, using 'Strategy', is performed between each attempt. 695 // Defaults to '0', a negative integer equals to unlimited retries. 696 // +optional 697 Retries int `json:"retries,omitempty"` 698 699 // IgnoreTestFailures tells the controller to skip remediation when the Helm 700 // tests are run after an upgrade action but fail. 701 // Defaults to 'Test.IgnoreFailures'. 702 // +optional 703 IgnoreTestFailures *bool `json:"ignoreTestFailures,omitempty"` 704 705 // RemediateLastFailure tells the controller to remediate the last failure, when 706 // no retries remain. Defaults to 'false' unless 'Retries' is greater than 0. 707 // +optional 708 RemediateLastFailure *bool `json:"remediateLastFailure,omitempty"` 709 710 // Strategy to use for failure remediation. Defaults to 'rollback'. 711 // +kubebuilder:validation:Enum=rollback;uninstall 712 // +optional 713 Strategy *RemediationStrategy `json:"strategy,omitempty"` 714 } 715 716 // GetRetries returns the number of retries that should be attempted on 717 // failures. 718 func (in UpgradeRemediation) GetRetries() int { 719 return in.Retries 720 } 721 722 // MustIgnoreTestFailures returns the configured IgnoreTestFailures or the given 723 // default. 724 func (in UpgradeRemediation) MustIgnoreTestFailures(def bool) bool { 725 if in.IgnoreTestFailures == nil { 726 return def 727 } 728 return *in.IgnoreTestFailures 729 } 730 731 // MustRemediateLastFailure returns whether to remediate the last failure when 732 // no retries remain. 733 func (in UpgradeRemediation) MustRemediateLastFailure() bool { 734 if in.RemediateLastFailure == nil { 735 return in.Retries > 0 736 } 737 return *in.RemediateLastFailure 738 } 739 740 // GetStrategy returns the strategy to use for failure remediation. 741 func (in UpgradeRemediation) GetStrategy() RemediationStrategy { 742 if in.Strategy == nil { 743 return RollbackRemediationStrategy 744 } 745 return *in.Strategy 746 } 747 748 // GetFailureCount gets the failure count. 749 func (in UpgradeRemediation) GetFailureCount(hr *HelmRelease) int64 { 750 return hr.Status.UpgradeFailures 751 } 752 753 // IncrementFailureCount increments the failure count. 754 func (in UpgradeRemediation) IncrementFailureCount(hr *HelmRelease) { 755 hr.Status.UpgradeFailures++ 756 } 757 758 // RetriesExhausted returns true if there are no remaining retries. 759 func (in UpgradeRemediation) RetriesExhausted(hr *HelmRelease) bool { 760 return in.Retries >= 0 && in.GetFailureCount(hr) > int64(in.Retries) 761 } 762 763 // RemediationStrategy returns the strategy to use to remediate a failed install 764 // or upgrade. 765 type RemediationStrategy string 766 767 const ( 768 // RollbackRemediationStrategy represents a Helm remediation strategy of Helm 769 // rollback. 770 RollbackRemediationStrategy RemediationStrategy = "rollback" 771 772 // UninstallRemediationStrategy represents a Helm remediation strategy of Helm 773 // uninstall. 774 UninstallRemediationStrategy RemediationStrategy = "uninstall" 775 ) 776 777 // Test holds the configuration for Helm test actions for this HelmRelease. 778 type Test struct { 779 // Enable enables Helm test actions for this HelmRelease after an Helm install 780 // or upgrade action has been performed. 781 // +optional 782 Enable bool `json:"enable,omitempty"` 783 784 // Timeout is the time to wait for any individual Kubernetes operation during 785 // the performance of a Helm test action. Defaults to 'HelmReleaseSpec.Timeout'. 786 // +kubebuilder:validation:Type=string 787 // +kubebuilder:validation:Pattern="^([0-9]+(\\.[0-9]+)?(ms|s|m|h))+$" 788 // +optional 789 Timeout *metav1.Duration `json:"timeout,omitempty"` 790 791 // IgnoreFailures tells the controller to skip remediation when the Helm tests 792 // are run but fail. Can be overwritten for tests run after install or upgrade 793 // actions in 'Install.IgnoreTestFailures' and 'Upgrade.IgnoreTestFailures'. 794 // +optional 795 IgnoreFailures bool `json:"ignoreFailures,omitempty"` 796 797 // Filters is a list of tests to run or exclude from running. 798 Filters *[]Filter `json:"filters,omitempty"` 799 } 800 801 // GetTimeout returns the configured timeout for the Helm test action, 802 // or the given default. 803 func (in Test) GetTimeout(defaultTimeout metav1.Duration) metav1.Duration { 804 if in.Timeout == nil { 805 return defaultTimeout 806 } 807 return *in.Timeout 808 } 809 810 // Filter holds the configuration for individual Helm test filters. 811 type Filter struct { 812 // Name is the name of the test. 813 // +kubebuilder:validation:MinLength=1 814 // +kubebuilder:validation:MaxLength=253 815 // +required 816 Name string `json:"name"` 817 // Exclude specifies whether the named test should be excluded. 818 // +optional 819 Exclude bool `json:"exclude,omitempty"` 820 } 821 822 // GetFilters returns the configured filters for the Helm test action/ 823 func (in Test) GetFilters() []Filter { 824 if in.Filters == nil { 825 var filters []Filter 826 return filters 827 } 828 return *in.Filters 829 } 830 831 // Rollback holds the configuration for Helm rollback actions for this 832 // HelmRelease. 833 type Rollback struct { 834 // Timeout is the time to wait for any individual Kubernetes operation (like 835 // Jobs for hooks) during the performance of a Helm rollback action. Defaults to 836 // 'HelmReleaseSpec.Timeout'. 837 // +kubebuilder:validation:Type=string 838 // +kubebuilder:validation:Pattern="^([0-9]+(\\.[0-9]+)?(ms|s|m|h))+$" 839 // +optional 840 Timeout *metav1.Duration `json:"timeout,omitempty"` 841 842 // DisableWait disables the waiting for resources to be ready after a Helm 843 // rollback has been performed. 844 // +optional 845 DisableWait bool `json:"disableWait,omitempty"` 846 847 // DisableWaitForJobs disables waiting for jobs to complete after a Helm 848 // rollback has been performed. 849 // +optional 850 DisableWaitForJobs bool `json:"disableWaitForJobs,omitempty"` 851 852 // DisableHooks prevents hooks from running during the Helm rollback action. 853 // +optional 854 DisableHooks bool `json:"disableHooks,omitempty"` 855 856 // Recreate performs pod restarts for the resource if applicable. 857 // +optional 858 Recreate bool `json:"recreate,omitempty"` 859 860 // Force forces resource updates through a replacement strategy. 861 // +optional 862 Force bool `json:"force,omitempty"` 863 864 // CleanupOnFail allows deletion of new resources created during the Helm 865 // rollback action when it fails. 866 // +optional 867 CleanupOnFail bool `json:"cleanupOnFail,omitempty"` 868 } 869 870 // GetTimeout returns the configured timeout for the Helm rollback action, or 871 // the given default. 872 func (in Rollback) GetTimeout(defaultTimeout metav1.Duration) metav1.Duration { 873 if in.Timeout == nil { 874 return defaultTimeout 875 } 876 return *in.Timeout 877 } 878 879 // Uninstall holds the configuration for Helm uninstall actions for this 880 // HelmRelease. 881 type Uninstall struct { 882 // Timeout is the time to wait for any individual Kubernetes operation (like 883 // Jobs for hooks) during the performance of a Helm uninstall action. Defaults 884 // to 'HelmReleaseSpec.Timeout'. 885 // +kubebuilder:validation:Type=string 886 // +kubebuilder:validation:Pattern="^([0-9]+(\\.[0-9]+)?(ms|s|m|h))+$" 887 // +optional 888 Timeout *metav1.Duration `json:"timeout,omitempty"` 889 890 // DisableHooks prevents hooks from running during the Helm rollback action. 891 // +optional 892 DisableHooks bool `json:"disableHooks,omitempty"` 893 894 // KeepHistory tells Helm to remove all associated resources and mark the 895 // release as deleted, but retain the release history. 896 // +optional 897 KeepHistory bool `json:"keepHistory,omitempty"` 898 899 // DisableWait disables waiting for all the resources to be deleted after 900 // a Helm uninstall is performed. 901 // +optional 902 DisableWait bool `json:"disableWait,omitempty"` 903 904 // DeletionPropagation specifies the deletion propagation policy when 905 // a Helm uninstall is performed. 906 // +kubebuilder:default=background 907 // +kubebuilder:validation:Enum=background;foreground;orphan 908 // +optional 909 DeletionPropagation *string `json:"deletionPropagation,omitempty"` 910 } 911 912 // GetTimeout returns the configured timeout for the Helm uninstall action, or 913 // the given default. 914 func (in Uninstall) GetTimeout(defaultTimeout metav1.Duration) metav1.Duration { 915 if in.Timeout == nil { 916 return defaultTimeout 917 } 918 return *in.Timeout 919 } 920 921 // GetDeletionPropagation returns the configured deletion propagation policy 922 // for the Helm uninstall action, or 'background'. 923 func (in Uninstall) GetDeletionPropagation() string { 924 if in.DeletionPropagation == nil { 925 return "background" 926 } 927 return *in.DeletionPropagation 928 } 929 930 // ReleaseAction is the action to perform a Helm release. 931 type ReleaseAction string 932 933 const ( 934 // ReleaseActionInstall represents a Helm install action. 935 ReleaseActionInstall ReleaseAction = "install" 936 // ReleaseActionUpgrade represents a Helm upgrade action. 937 ReleaseActionUpgrade ReleaseAction = "upgrade" 938 ) 939 940 // HelmReleaseStatus defines the observed state of a HelmRelease. 941 type HelmReleaseStatus struct { 942 // ObservedGeneration is the last observed generation. 943 // +optional 944 ObservedGeneration int64 `json:"observedGeneration,omitempty"` 945 946 // ObservedPostRenderersDigest is the digest for the post-renderers of 947 // the last successful reconciliation attempt. 948 // +optional 949 ObservedPostRenderersDigest string `json:"observedPostRenderersDigest,omitempty"` 950 951 // LastAttemptedGeneration is the last generation the controller attempted 952 // to reconcile. 953 // +optional 954 LastAttemptedGeneration int64 `json:"lastAttemptedGeneration,omitempty"` 955 956 // Conditions holds the conditions for the HelmRelease. 957 // +optional 958 Conditions []metav1.Condition `json:"conditions,omitempty"` 959 960 // HelmChart is the namespaced name of the HelmChart resource created by 961 // the controller for the HelmRelease. 962 // +optional 963 HelmChart string `json:"helmChart,omitempty"` 964 965 // StorageNamespace is the namespace of the Helm release storage for the 966 // current release. 967 // +kubebuilder:validation:MaxLength=63 968 // +kubebuilder:validation:MinLength=1 969 // +kubebuilder:validation:Optional 970 // +optional 971 StorageNamespace string `json:"storageNamespace,omitempty"` 972 973 // History holds the history of Helm releases performed for this HelmRelease 974 // up to the last successfully completed release. 975 // +optional 976 History Snapshots `json:"history,omitempty"` 977 978 // LastAttemptedReleaseAction is the last release action performed for this 979 // HelmRelease. It is used to determine the active remediation strategy. 980 // +kubebuilder:validation:Enum=install;upgrade 981 // +optional 982 LastAttemptedReleaseAction ReleaseAction `json:"lastAttemptedReleaseAction,omitempty"` 983 984 // Failures is the reconciliation failure count against the latest desired 985 // state. It is reset after a successful reconciliation. 986 // +optional 987 Failures int64 `json:"failures,omitempty"` 988 989 // InstallFailures is the install failure count against the latest desired 990 // state. It is reset after a successful reconciliation. 991 // +optional 992 InstallFailures int64 `json:"installFailures,omitempty"` 993 994 // UpgradeFailures is the upgrade failure count against the latest desired 995 // state. It is reset after a successful reconciliation. 996 // +optional 997 UpgradeFailures int64 `json:"upgradeFailures,omitempty"` 998 999 // LastAttemptedRevision is the Source revision of the last reconciliation 1000 // attempt. For OCIRepository sources, the 12 first characters of the digest are 1001 // appended to the chart version e.g. "1.2.3+1234567890ab". 1002 // +optional 1003 LastAttemptedRevision string `json:"lastAttemptedRevision,omitempty"` 1004 1005 // LastAttemptedRevisionDigest is the digest of the last reconciliation attempt. 1006 // This is only set for OCIRepository sources. 1007 // +optional 1008 LastAttemptedRevisionDigest string `json:"lastAttemptedRevisionDigest,omitempty"` 1009 1010 // LastAttemptedValuesChecksum is the SHA1 checksum for the values of the last 1011 // reconciliation attempt. 1012 // Deprecated: Use LastAttemptedConfigDigest instead. 1013 // +optional 1014 LastAttemptedValuesChecksum string `json:"lastAttemptedValuesChecksum,omitempty"` 1015 1016 // LastReleaseRevision is the revision of the last successful Helm release. 1017 // Deprecated: Use History instead. 1018 // +optional 1019 LastReleaseRevision int `json:"lastReleaseRevision,omitempty"` 1020 1021 // LastAttemptedConfigDigest is the digest for the config (better known as 1022 // "values") of the last reconciliation attempt. 1023 // +optional 1024 LastAttemptedConfigDigest string `json:"lastAttemptedConfigDigest,omitempty"` 1025 1026 // LastHandledForceAt holds the value of the most recent force request 1027 // value, so a change of the annotation value can be detected. 1028 // +optional 1029 LastHandledForceAt string `json:"lastHandledForceAt,omitempty"` 1030 1031 // LastHandledResetAt holds the value of the most recent reset request 1032 // value, so a change of the annotation value can be detected. 1033 // +optional 1034 LastHandledResetAt string `json:"lastHandledResetAt,omitempty"` 1035 1036 meta.ReconcileRequestStatus `json:",inline"` 1037 } 1038 1039 // ClearHistory clears the History. 1040 func (in *HelmReleaseStatus) ClearHistory() { 1041 in.History = nil 1042 } 1043 1044 // ClearFailures clears the failure counters. 1045 func (in *HelmReleaseStatus) ClearFailures() { 1046 in.Failures = 0 1047 in.InstallFailures = 0 1048 in.UpgradeFailures = 0 1049 } 1050 1051 // GetHelmChart returns the namespace and name of the HelmChart. 1052 func (in HelmReleaseStatus) GetHelmChart() (string, string) { 1053 if in.HelmChart == "" { 1054 return "", "" 1055 } 1056 if split := strings.Split(in.HelmChart, string(types.Separator)); len(split) > 1 { 1057 return split[0], split[1] 1058 } 1059 return "", "" 1060 } 1061 1062 func (in *HelmReleaseStatus) GetLastAttemptedRevision() string { 1063 return in.LastAttemptedRevision 1064 } 1065 1066 const ( 1067 // SourceIndexKey is the key used for indexing HelmReleases based on 1068 // their sources. 1069 SourceIndexKey string = ".metadata.source" 1070 ) 1071 1072 // +genclient 1073 // +kubebuilder:object:root=true 1074 // +kubebuilder:resource:shortName=hr 1075 // +kubebuilder:storageversion 1076 // +kubebuilder:subresource:status 1077 // +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="" 1078 // +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].status",description="" 1079 // +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].message",description="" 1080 1081 // HelmRelease is the Schema for the helmreleases API 1082 type HelmRelease struct { 1083 metav1.TypeMeta `json:",inline"` 1084 metav1.ObjectMeta `json:"metadata,omitempty"` 1085 1086 Spec HelmReleaseSpec `json:"spec,omitempty"` 1087 // +kubebuilder:default:={"observedGeneration":-1} 1088 Status HelmReleaseStatus `json:"status,omitempty"` 1089 } 1090 1091 // GetDriftDetection returns the configuration for detecting and handling 1092 // differences between the manifest in the Helm storage and the resources 1093 // currently existing in the cluster. 1094 func (in *HelmRelease) GetDriftDetection() DriftDetection { 1095 if in.Spec.DriftDetection == nil { 1096 return DriftDetection{} 1097 } 1098 return *in.Spec.DriftDetection 1099 } 1100 1101 // GetInstall returns the configuration for Helm install actions for the 1102 // HelmRelease. 1103 func (in *HelmRelease) GetInstall() Install { 1104 if in.Spec.Install == nil { 1105 return Install{} 1106 } 1107 return *in.Spec.Install 1108 } 1109 1110 // GetUpgrade returns the configuration for Helm upgrade actions for this 1111 // HelmRelease. 1112 func (in *HelmRelease) GetUpgrade() Upgrade { 1113 if in.Spec.Upgrade == nil { 1114 return Upgrade{} 1115 } 1116 return *in.Spec.Upgrade 1117 } 1118 1119 // GetTest returns the configuration for Helm test actions for this HelmRelease. 1120 func (in *HelmRelease) GetTest() Test { 1121 if in.Spec.Test == nil { 1122 return Test{} 1123 } 1124 return *in.Spec.Test 1125 } 1126 1127 // GetRollback returns the configuration for Helm rollback actions for this 1128 // HelmRelease. 1129 func (in *HelmRelease) GetRollback() Rollback { 1130 if in.Spec.Rollback == nil { 1131 return Rollback{} 1132 } 1133 return *in.Spec.Rollback 1134 } 1135 1136 // GetUninstall returns the configuration for Helm uninstall actions for this 1137 // HelmRelease. 1138 func (in *HelmRelease) GetUninstall() Uninstall { 1139 if in.Spec.Uninstall == nil { 1140 return Uninstall{} 1141 } 1142 return *in.Spec.Uninstall 1143 } 1144 1145 // GetActiveRemediation returns the active Remediation configuration for the 1146 // HelmRelease. 1147 func (in HelmRelease) GetActiveRemediation() Remediation { 1148 switch in.Status.LastAttemptedReleaseAction { 1149 case ReleaseActionInstall: 1150 return in.GetInstall().GetRemediation() 1151 case ReleaseActionUpgrade: 1152 return in.GetUpgrade().GetRemediation() 1153 default: 1154 return nil 1155 } 1156 } 1157 1158 // GetRequeueAfter returns the duration after which the HelmRelease 1159 // must be reconciled again. 1160 func (in HelmRelease) GetRequeueAfter() time.Duration { 1161 return in.Spec.Interval.Duration 1162 } 1163 1164 // GetValues unmarshals the raw values to a map[string]interface{} and returns 1165 // the result. 1166 func (in HelmRelease) GetValues() map[string]interface{} { 1167 var values map[string]interface{} 1168 if in.Spec.Values != nil { 1169 _ = yaml.Unmarshal(in.Spec.Values.Raw, &values) 1170 } 1171 return values 1172 } 1173 1174 // GetReleaseName returns the configured release name, or a composition of 1175 // '[TargetNamespace-]Name'. 1176 func (in HelmRelease) GetReleaseName() string { 1177 if in.Spec.ReleaseName != "" { 1178 return in.Spec.ReleaseName 1179 } 1180 if in.Spec.TargetNamespace != "" { 1181 return strings.Join([]string{in.Spec.TargetNamespace, in.Name}, "-") 1182 } 1183 return in.Name 1184 } 1185 1186 // GetReleaseNamespace returns the configured TargetNamespace, or the namespace 1187 // of the HelmRelease. 1188 func (in HelmRelease) GetReleaseNamespace() string { 1189 if in.Spec.TargetNamespace != "" { 1190 return in.Spec.TargetNamespace 1191 } 1192 return in.Namespace 1193 } 1194 1195 // GetStorageNamespace returns the configured StorageNamespace for helm, or the namespace 1196 // of the HelmRelease. 1197 func (in HelmRelease) GetStorageNamespace() string { 1198 if in.Spec.StorageNamespace != "" { 1199 return in.Spec.StorageNamespace 1200 } 1201 return in.Namespace 1202 } 1203 1204 // GetHelmChartName returns the name used by the controller for the HelmChart creation. 1205 func (in HelmRelease) GetHelmChartName() string { 1206 return strings.Join([]string{in.Namespace, in.Name}, "-") 1207 } 1208 1209 // GetTimeout returns the configured Timeout, or the default of 300s. 1210 func (in HelmRelease) GetTimeout() metav1.Duration { 1211 if in.Spec.Timeout == nil { 1212 return metav1.Duration{Duration: 300 * time.Second} 1213 } 1214 return *in.Spec.Timeout 1215 } 1216 1217 // GetMaxHistory returns the configured MaxHistory, or the default of 5. 1218 func (in HelmRelease) GetMaxHistory() int { 1219 if in.Spec.MaxHistory == nil { 1220 return defaultMaxHistory 1221 } 1222 return *in.Spec.MaxHistory 1223 } 1224 1225 // UsePersistentClient returns the configured PersistentClient, or the default 1226 // of true. 1227 func (in HelmRelease) UsePersistentClient() bool { 1228 if in.Spec.PersistentClient == nil { 1229 return true 1230 } 1231 return *in.Spec.PersistentClient 1232 } 1233 1234 // GetDependsOn returns the list of dependencies across-namespaces. 1235 func (in HelmRelease) GetDependsOn() []meta.NamespacedObjectReference { 1236 return in.Spec.DependsOn 1237 } 1238 1239 // GetConditions returns the status conditions of the object. 1240 func (in HelmRelease) GetConditions() []metav1.Condition { 1241 return in.Status.Conditions 1242 } 1243 1244 // SetConditions sets the status conditions on the object. 1245 func (in *HelmRelease) SetConditions(conditions []metav1.Condition) { 1246 in.Status.Conditions = conditions 1247 } 1248 1249 // HasChartRef returns true if the HelmRelease has a ChartRef. 1250 func (in *HelmRelease) HasChartRef() bool { 1251 return in.Spec.ChartRef != nil 1252 } 1253 1254 // HasChartTemplate returns true if the HelmRelease has a ChartTemplate. 1255 func (in *HelmRelease) HasChartTemplate() bool { 1256 return in.Spec.Chart != nil 1257 } 1258 1259 // +kubebuilder:object:root=true 1260 1261 // HelmReleaseList contains a list of HelmRelease objects. 1262 type HelmReleaseList struct { 1263 metav1.TypeMeta `json:",inline"` 1264 metav1.ListMeta `json:"metadata,omitempty"` 1265 Items []HelmRelease `json:"items"` 1266 } 1267 1268 func init() { 1269 SchemeBuilder.Register(&HelmRelease{}, &HelmReleaseList{}) 1270 } 1271