...

Source file src/github.com/fluxcd/helm-controller/api/v2beta1/helmrelease_types.go

Documentation: github.com/fluxcd/helm-controller/api/v2beta1

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

View as plain text