...

Source file src/github.com/fluxcd/helm-controller/api/v2beta2/snapshot_types.go

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

     1  /*
     2  Copyright 2023 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 v2beta2
    18  
    19  import (
    20  	"fmt"
    21  	"sort"
    22  
    23  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    24  )
    25  
    26  const (
    27  	// snapshotStatusDeployed indicates that the release the snapshot was taken
    28  	// from is currently deployed.
    29  	snapshotStatusDeployed = "deployed"
    30  	// snapshotStatusSuperseded indicates that the release the snapshot was taken
    31  	// from has been superseded by a newer release.
    32  	snapshotStatusSuperseded = "superseded"
    33  
    34  	// snapshotTestPhaseFailed indicates that the test of the release the snapshot
    35  	// was taken from has failed.
    36  	snapshotTestPhaseFailed = "Failed"
    37  )
    38  
    39  // Snapshots is a list of Snapshot objects.
    40  type Snapshots []*Snapshot
    41  
    42  // Len returns the number of Snapshots.
    43  func (in Snapshots) Len() int {
    44  	return len(in)
    45  }
    46  
    47  // SortByVersion sorts the Snapshots by version, in descending order.
    48  func (in Snapshots) SortByVersion() {
    49  	sort.Slice(in, func(i, j int) bool {
    50  		return in[i].Version > in[j].Version
    51  	})
    52  }
    53  
    54  // Latest returns the most recent Snapshot.
    55  func (in Snapshots) Latest() *Snapshot {
    56  	if len(in) == 0 {
    57  		return nil
    58  	}
    59  	in.SortByVersion()
    60  	return in[0]
    61  }
    62  
    63  // Previous returns the most recent Snapshot before the Latest that has a
    64  // status of "deployed" or "superseded", or nil if there is no such Snapshot.
    65  // Unless ignoreTests is true, Snapshots with a test in the "Failed" phase are
    66  // ignored.
    67  func (in Snapshots) Previous(ignoreTests bool) *Snapshot {
    68  	if len(in) < 2 {
    69  		return nil
    70  	}
    71  	in.SortByVersion()
    72  	for i := range in[1:] {
    73  		s := in[i+1]
    74  		if s.Status == snapshotStatusDeployed || s.Status == snapshotStatusSuperseded {
    75  			if ignoreTests || !s.HasTestInPhase(snapshotTestPhaseFailed) {
    76  				return s
    77  			}
    78  		}
    79  	}
    80  	return nil
    81  }
    82  
    83  // Truncate removes all Snapshots up to the Previous deployed Snapshot.
    84  // If there is no previous-deployed Snapshot, the most recent 5 Snapshots are
    85  // retained.
    86  func (in *Snapshots) Truncate(ignoreTests bool) {
    87  	if in.Len() < 2 {
    88  		return
    89  	}
    90  
    91  	in.SortByVersion()
    92  	for i := range (*in)[1:] {
    93  		s := (*in)[i+1]
    94  		if s.Status == snapshotStatusDeployed || s.Status == snapshotStatusSuperseded {
    95  			if ignoreTests || !s.HasTestInPhase(snapshotTestPhaseFailed) {
    96  				*in = (*in)[:i+2]
    97  				return
    98  			}
    99  		}
   100  	}
   101  
   102  	if in.Len() > defaultMaxHistory {
   103  		// If none of the Snapshots are deployed or superseded, and there
   104  		// are more than the defaultMaxHistory, truncate to the most recent
   105  		// Snapshots.
   106  		*in = (*in)[:defaultMaxHistory]
   107  	}
   108  }
   109  
   110  // Snapshot captures a point-in-time copy of the status information for a Helm release,
   111  // as managed by the controller.
   112  type Snapshot struct {
   113  	// APIVersion is the API version of the Snapshot.
   114  	// Provisional: when the calculation method of the Digest field is changed,
   115  	// this field will be used to distinguish between the old and new methods.
   116  	// +optional
   117  	APIVersion string `json:"apiVersion,omitempty"`
   118  	// Digest is the checksum of the release object in storage.
   119  	// It has the format of `<algo>:<checksum>`.
   120  	// +required
   121  	Digest string `json:"digest"`
   122  	// Name is the name of the release.
   123  	// +required
   124  	Name string `json:"name"`
   125  	// Namespace is the namespace the release is deployed to.
   126  	// +required
   127  	Namespace string `json:"namespace"`
   128  	// Version is the version of the release object in storage.
   129  	// +required
   130  	Version int `json:"version"`
   131  	// Status is the current state of the release.
   132  	// +required
   133  	Status string `json:"status"`
   134  	// ChartName is the chart name of the release object in storage.
   135  	// +required
   136  	ChartName string `json:"chartName"`
   137  	// ChartVersion is the chart version of the release object in
   138  	// storage.
   139  	// +required
   140  	ChartVersion string `json:"chartVersion"`
   141  	// ConfigDigest is the checksum of the config (better known as
   142  	// "values") of the release object in storage.
   143  	// It has the format of `<algo>:<checksum>`.
   144  	// +required
   145  	ConfigDigest string `json:"configDigest"`
   146  	// FirstDeployed is when the release was first deployed.
   147  	// +required
   148  	FirstDeployed metav1.Time `json:"firstDeployed"`
   149  	// LastDeployed is when the release was last deployed.
   150  	// +required
   151  	LastDeployed metav1.Time `json:"lastDeployed"`
   152  	// Deleted is when the release was deleted.
   153  	// +optional
   154  	Deleted metav1.Time `json:"deleted,omitempty"`
   155  	// TestHooks is the list of test hooks for the release as observed to be
   156  	// run by the controller.
   157  	// +optional
   158  	TestHooks *map[string]*TestHookStatus `json:"testHooks,omitempty"`
   159  	// OCIDigest is the digest of the OCI artifact associated with the release.
   160  	// +optional
   161  	OCIDigest string `json:"ociDigest,omitempty"`
   162  }
   163  
   164  // FullReleaseName returns the full name of the release in the format
   165  // of '<namespace>/<name>.<version>
   166  func (in *Snapshot) FullReleaseName() string {
   167  	if in == nil {
   168  		return ""
   169  	}
   170  	return fmt.Sprintf("%s/%s.v%d", in.Namespace, in.Name, in.Version)
   171  }
   172  
   173  // VersionedChartName returns the full name of the chart in the format of
   174  // '<name>@<version>'.
   175  func (in *Snapshot) VersionedChartName() string {
   176  	if in == nil {
   177  		return ""
   178  	}
   179  	return fmt.Sprintf("%s@%s", in.ChartName, in.ChartVersion)
   180  }
   181  
   182  // HasBeenTested returns true if TestHooks is not nil. This includes an empty
   183  // map, which indicates the chart has no tests.
   184  func (in *Snapshot) HasBeenTested() bool {
   185  	return in != nil && in.TestHooks != nil
   186  }
   187  
   188  // GetTestHooks returns the TestHooks for the release if not nil.
   189  func (in *Snapshot) GetTestHooks() map[string]*TestHookStatus {
   190  	if in == nil || in.TestHooks == nil {
   191  		return nil
   192  	}
   193  	return *in.TestHooks
   194  }
   195  
   196  // HasTestInPhase returns true if any of the TestHooks is in the given phase.
   197  func (in *Snapshot) HasTestInPhase(phase string) bool {
   198  	if in != nil {
   199  		for _, h := range in.GetTestHooks() {
   200  			if h.Phase == phase {
   201  				return true
   202  			}
   203  		}
   204  	}
   205  	return false
   206  }
   207  
   208  // SetTestHooks sets the TestHooks for the release.
   209  func (in *Snapshot) SetTestHooks(hooks map[string]*TestHookStatus) {
   210  	if in == nil || hooks == nil {
   211  		return
   212  	}
   213  	in.TestHooks = &hooks
   214  }
   215  
   216  // Targets returns true if the Snapshot targets the given release data.
   217  func (in *Snapshot) Targets(name, namespace string, version int) bool {
   218  	if in != nil {
   219  		return in.Name == name && in.Namespace == namespace && in.Version == version
   220  	}
   221  	return false
   222  }
   223  
   224  // TestHookStatus holds the status information for a test hook as observed
   225  // to be run by the controller.
   226  type TestHookStatus struct {
   227  	// LastStarted is the time the test hook was last started.
   228  	// +optional
   229  	LastStarted metav1.Time `json:"lastStarted,omitempty"`
   230  	// LastCompleted is the time the test hook last completed.
   231  	// +optional
   232  	LastCompleted metav1.Time `json:"lastCompleted,omitempty"`
   233  	// Phase the test hook was observed to be in.
   234  	// +optional
   235  	Phase string `json:"phase,omitempty"`
   236  }
   237  

View as plain text