github.com/wmuizelaar/kpt@v0.0.0-20221018115725-bd564717b2ed/pkg/api/kptfile/v1/types.go (about)

     1  // Copyright 2021 Google LLC
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Package defines Kptfile schema.
    16  // Version: v1
    17  // swagger:meta
    18  package v1
    19  
    20  import (
    21  	"fmt"
    22  
    23  	"k8s.io/apimachinery/pkg/runtime/schema"
    24  	"sigs.k8s.io/kustomize/kyaml/yaml"
    25  )
    26  
    27  const (
    28  	KptFileName = "Kptfile"
    29  
    30  	// Deprecated: prefer KptFileGVK
    31  	KptFileKind = "Kptfile"
    32  
    33  	// Deprecated: prefer KptFileGVK
    34  	KptFileGroup = "kpt.dev"
    35  
    36  	// Deprecated: prefer KptFileGVK
    37  	KptFileVersion = "v1"
    38  
    39  	// Deprecated: prefer KptFileGVK
    40  	KptFileAPIVersion = KptFileGroup + "/" + KptFileVersion
    41  )
    42  
    43  // KptFileGVK is the GroupVersionKind of Kptfile objects
    44  func KptFileGVK() schema.GroupVersionKind {
    45  	return schema.GroupVersionKind{
    46  		Group:   "kpt.dev",
    47  		Version: "v1",
    48  		Kind:    "Kptfile",
    49  	}
    50  }
    51  
    52  // TypeMeta is the TypeMeta for KptFile instances.
    53  var TypeMeta = yaml.ResourceMeta{
    54  	TypeMeta: yaml.TypeMeta{
    55  		APIVersion: KptFileAPIVersion,
    56  		Kind:       KptFileKind,
    57  	},
    58  }
    59  
    60  // KptFile contains information about a package managed with kpt.
    61  // swagger:model kptfile
    62  type KptFile struct {
    63  	yaml.ResourceMeta `yaml:",inline" json:",inline"`
    64  
    65  	Upstream *Upstream `yaml:"upstream,omitempty" json:"upstream,omitempty"`
    66  
    67  	// UpstreamLock is a resolved locator for the last fetch of the package.
    68  	UpstreamLock *UpstreamLock `yaml:"upstreamLock,omitempty" json:"upstreamLock,omitempty"`
    69  
    70  	// Info contains metadata such as license, documentation, etc.
    71  	Info *PackageInfo `yaml:"info,omitempty" json:"info,omitempty"`
    72  
    73  	// Pipeline declares the pipeline of functions.
    74  	Pipeline *Pipeline `yaml:"pipeline,omitempty" json:"pipeline,omitempty"`
    75  
    76  	// Inventory contains parameters for the inventory object used in apply.
    77  	Inventory *Inventory `yaml:"inventory,omitempty" json:"inventory,omitempty"`
    78  
    79  	Status *Status `yaml:"status,omitempty" json:"status,omitempty"`
    80  }
    81  
    82  // OriginType defines the type of origin for a package.
    83  type OriginType string
    84  
    85  const (
    86  	// GitOrigin specifies a package as having been cloned from a git repository.
    87  	GitOrigin OriginType = "git"
    88  )
    89  
    90  // UpdateStrategyType defines the strategy for updating a package from upstream.
    91  type UpdateStrategyType string
    92  
    93  // ToUpdateStrategy takes a string representing an update strategy and will
    94  // return the strategy as an UpdateStrategyType. If the provided string does
    95  // not match any known update strategies, an error will be returned.
    96  func ToUpdateStrategy(strategy string) (UpdateStrategyType, error) {
    97  	switch strategy {
    98  	case string(ResourceMerge):
    99  		return ResourceMerge, nil
   100  	case string(FastForward):
   101  		return FastForward, nil
   102  	case string(ForceDeleteReplace):
   103  		return ForceDeleteReplace, nil
   104  	default:
   105  		return "", fmt.Errorf("unknown update strategy %q", strategy)
   106  	}
   107  }
   108  
   109  const (
   110  	// ResourceMerge performs a structural schema-aware comparison and
   111  	// merges the changes into the local package.
   112  	ResourceMerge UpdateStrategyType = "resource-merge"
   113  	// FastForward fails without updating if the local package was modified
   114  	// since it was fetched.
   115  	FastForward UpdateStrategyType = "fast-forward"
   116  	// ForceDeleteReplace wipes all local changes to the package.
   117  	ForceDeleteReplace UpdateStrategyType = "force-delete-replace"
   118  )
   119  
   120  // UpdateStrategies is a slice with all the supported update strategies.
   121  var UpdateStrategies = []UpdateStrategyType{
   122  	ResourceMerge,
   123  	FastForward,
   124  	ForceDeleteReplace,
   125  }
   126  
   127  // UpdateStrategiesAsStrings returns a list of update strategies as strings.
   128  func UpdateStrategiesAsStrings() []string {
   129  	var strs []string
   130  	for _, s := range UpdateStrategies {
   131  		strs = append(strs, string(s))
   132  	}
   133  	return strs
   134  }
   135  
   136  // Upstream is a user-specified upstream locator for a package.
   137  type Upstream struct {
   138  	// Type is the type of origin.
   139  	Type OriginType `yaml:"type,omitempty" json:"type,omitempty"`
   140  
   141  	// Git is the locator for a package stored on Git.
   142  	Git *Git `yaml:"git,omitempty" json:"git,omitempty"`
   143  
   144  	// UpdateStrategy declares how a package will be updated from upstream.
   145  	UpdateStrategy UpdateStrategyType `yaml:"updateStrategy,omitempty" json:"updateStrategy,omitempty"`
   146  }
   147  
   148  // Git is the user-specified locator for a package on Git.
   149  type Git struct {
   150  	// Repo is the git repository the package.
   151  	// e.g. 'https://github.com/kubernetes/examples.git'
   152  	Repo string `yaml:"repo,omitempty" json:"repo,omitempty"`
   153  
   154  	// Directory is the sub directory of the git repository.
   155  	// e.g. 'staging/cockroachdb'
   156  	Directory string `yaml:"directory,omitempty" json:"directory,omitempty"`
   157  
   158  	// Ref can be a Git branch, tag, or a commit SHA-1.
   159  	Ref string `yaml:"ref,omitempty" json:"ref,omitempty"`
   160  }
   161  
   162  // UpstreamLock is a resolved locator for the last fetch of the package.
   163  type UpstreamLock struct {
   164  	// Type is the type of origin.
   165  	Type OriginType `yaml:"type,omitempty" json:"type,omitempty"`
   166  
   167  	// Git is the resolved locator for a package on Git.
   168  	Git *GitLock `yaml:"git,omitempty" json:"git,omitempty"`
   169  }
   170  
   171  // GitLock is the resolved locator for a package on Git.
   172  type GitLock struct {
   173  	// Repo is the git repository that was fetched.
   174  	// e.g. 'https://github.com/kubernetes/examples.git'
   175  	Repo string `yaml:"repo,omitempty" json:"repo,omitempty"`
   176  
   177  	// Directory is the sub directory of the git repository that was fetched.
   178  	// e.g. 'staging/cockroachdb'
   179  	Directory string `yaml:"directory,omitempty" json:"directory,omitempty"`
   180  
   181  	// Ref can be a Git branch, tag, or a commit SHA-1 that was fetched.
   182  	// e.g. 'master'
   183  	Ref string `yaml:"ref,omitempty" json:"ref,omitempty"`
   184  
   185  	// Commit is the SHA-1 for the last fetch of the package.
   186  	// This is set by kpt for bookkeeping purposes.
   187  	Commit string `yaml:"commit,omitempty" json:"commit,omitempty"`
   188  }
   189  
   190  // PackageInfo contains optional information about the package such as license, documentation, etc.
   191  // These fields are not consumed by any functionality in kpt and are simply passed through.
   192  // Note that like any other KRM resource, humans and automation can also use `metadata.labels` and
   193  // `metadata.annotations` as the extension mechanism.
   194  type PackageInfo struct {
   195  	// Site is the URL for package web page.
   196  	Site string `yaml:"site,omitempty" json:"site,omitempty"`
   197  
   198  	// Email is the list of emails for the package authors.
   199  	Emails []string `yaml:"emails,omitempty" json:"emails,omitempty"`
   200  
   201  	// SPDX license identifier (e.g. "Apache-2.0"). See: https://spdx.org/licenses/
   202  	License string `yaml:"license,omitempty" json:"license,omitempty"`
   203  
   204  	// Relative slash-delimited path to the license file (e.g. LICENSE.txt)
   205  	LicenseFile string `yaml:"licenseFile,omitempty" json:"licenseFile,omitempty"`
   206  
   207  	// Description contains a short description of the package.
   208  	Description string `yaml:"description,omitempty" json:"description,omitempty"`
   209  
   210  	// Keywords is a list of keywords for this package.
   211  	Keywords []string `yaml:"keywords,omitempty" json:"keywords,omitempty"`
   212  
   213  	// Man is the path to documentation about the package
   214  	Man string `yaml:"man,omitempty" json:"man,omitempty"`
   215  
   216  	ReadinessGates []ReadinessGate `yaml:"readinessGates,omitempty" json:"readinessGates,omitempty"`
   217  }
   218  
   219  type ReadinessGate struct {
   220  	ConditionType string `yaml:"conditionType" json:"conditionType"`
   221  }
   222  
   223  // Subpackages declares a local or remote subpackage.
   224  type Subpackage struct {
   225  	// Name of the immediate subdirectory relative to this Kptfile where the suppackage
   226  	// either exists (local subpackages) or will be fetched to (remote subpckages).
   227  	// This must be unique across all subpckages of a package.
   228  	LocalDir string `yaml:"localDir,omitempty" json:"localDir,omitempty"`
   229  
   230  	// Upstream is a reference to where the subpackage should be fetched from.
   231  	// Whether a subpackage is local or remote is determined by whether Upstream is specified.
   232  	Upstream *Upstream `yaml:"upstream,omitempty" json:"upstream,omitempty"`
   233  }
   234  
   235  // Pipeline declares a pipeline of functions used to mutate or validate resources.
   236  type Pipeline struct {
   237  	//  Sources defines the source packages to resolve as input to the pipeline. Possible values:
   238  	//  a) A slash-separated, OS-agnostic relative package path which may include '.' and '..' e.g. './base', '../foo'
   239  	//     The source package is resolved recursively.
   240  	//  b) Resources in this package using '.'. Meta resources such as the Kptfile, Pipeline, and function configs
   241  	//     are excluded.
   242  	//  c) Resources in this package AND all resolved subpackages using './*'
   243  	//
   244  	// Resultant list of resources are ordered:
   245  	// - According to the order of sources specified in this array.
   246  	// - When using './*': Subpackages are resolved in alphanumerical order before package resources.
   247  	//
   248  	// When omitted, defaults to './*'.
   249  	// Sources []string `yaml:"sources,omitempty"`
   250  
   251  	// Following fields define the sequence of functions in the pipeline.
   252  	// Input of the first function is the resolved sources.
   253  	// Input of the second function is the output of the first function, and so on.
   254  	// Order of operation: mutators, validators
   255  
   256  	// Mutators defines a list of of KRM functions that mutate resources.
   257  	Mutators []Function `yaml:"mutators,omitempty" json:"mutators,omitempty"`
   258  
   259  	// Validators defines a list of KRM functions that validate resources.
   260  	// Validators are not permitted to mutate resources.
   261  	Validators []Function `yaml:"validators,omitempty" json:"validators,omitempty"`
   262  }
   263  
   264  // String returns the string representation of Pipeline struct
   265  // The string returned is the struct content in Go default format.
   266  func (p *Pipeline) String() string {
   267  	return fmt.Sprintf("%+v", *p)
   268  }
   269  
   270  // IsEmpty returns true if the pipeline doesn't contain any functions in any of
   271  // the function chains (mutators, validators).
   272  func (p *Pipeline) IsEmpty() bool {
   273  	if p == nil {
   274  		return true
   275  	}
   276  	if len(p.Mutators) == 0 && len(p.Validators) == 0 {
   277  		return true
   278  	}
   279  	return false
   280  }
   281  
   282  // Function specifies a KRM function.
   283  type Function struct {
   284  	// `Image` specifies the function container image.
   285  	// It can either be fully qualified, e.g.:
   286  	//
   287  	//	image: gcr.io/kpt-fn/set-labels
   288  	//
   289  	// Optionally, kpt can be configured to use a image
   290  	// registry host-path that will be used to resolve the image path in case
   291  	// the image path is missing (Defaults to gcr.io/kpt-fn).
   292  	// e.g. The following resolves to gcr.io/kpt-fn/set-labels:
   293  	//
   294  	//	image: set-labels
   295  	Image string `yaml:"image,omitempty" json:"image,omitempty"`
   296  
   297  	// Exec specifies the function binary executable.
   298  	// The executable can be fully qualified or it must exists in the $PATH e.g:
   299  	//
   300  	// 	 exec: set-namespace
   301  	// 	 exec: /usr/local/bin/my-custom-fn
   302  	Exec string `yaml:"exec,omitempty" json:"exec,omitempty"`
   303  
   304  	// `ConfigPath` specifies a slash-delimited relative path to a file in the current directory
   305  	// containing a KRM resource used as the function config. This resource is
   306  	// excluded when resolving 'sources', and as a result cannot be operated on
   307  	// by the pipeline.
   308  	ConfigPath string `yaml:"configPath,omitempty" json:"configPath,omitempty"`
   309  
   310  	// `ConfigMap` is a convenient way to specify a function config of kind ConfigMap.
   311  	ConfigMap map[string]string `yaml:"configMap,omitempty" json:"configMap,omitempty"`
   312  
   313  	// `Name` is used to uniquely identify the function declaration
   314  	// this is primarily used for merging function declaration with upstream counterparts
   315  	Name string `yaml:"name,omitempty" json:"name,omitempty"`
   316  
   317  	// `Selectors` are used to specify resources on which the function should be executed
   318  	// if not specified, all resources are selected
   319  	Selectors []Selector `yaml:"selectors,omitempty" json:"selectors,omitempty"`
   320  
   321  	// `Exclude` are used to specify resources on which the function should NOT be executed.
   322  	// If not specified, all resources selected by `Selectors` are selected.
   323  	Exclusions []Selector `yaml:"exclude,omitempty" json:"exclude,omitempty"`
   324  }
   325  
   326  // Selector specifies the selection criteria
   327  // please update IsEmpty method if more properties are added
   328  type Selector struct {
   329  	// APIVersion of the target resources
   330  	APIVersion string `yaml:"apiVersion,omitempty" json:"apiVersion,omitempty"`
   331  	// Kind of the target resources
   332  	Kind string `yaml:"kind,omitempty" json:"kind,omitempty"`
   333  	// Name of the target resources
   334  	Name string `yaml:"name,omitempty" json:"name,omitempty"`
   335  	// Namespace of the target resources
   336  	Namespace string `yaml:"namespace,omitempty" json:"namespace,omitempty"`
   337  	// Labels on the target resources
   338  	Labels map[string]string `yaml:"labels,omitempty" json:"labels,omitempty"`
   339  	// Annotations on the target resources
   340  	Annotations map[string]string `yaml:"annotations,omitempty" json:"annotations,omitempty"`
   341  }
   342  
   343  // IsEmpty returns true of none of the selection criteria is specified
   344  func (s Selector) IsEmpty() bool {
   345  	return s.APIVersion == "" &&
   346  		s.Namespace == "" &&
   347  		s.Name == "" &&
   348  		s.Kind == "" &&
   349  		len(s.Labels) == 0 &&
   350  		len(s.Annotations) == 0
   351  }
   352  
   353  // Inventory encapsulates the parameters for the inventory resource applied to a cluster.
   354  // All of the the parameters are required if any are set.
   355  type Inventory struct {
   356  	// Namespace for the inventory resource.
   357  	Namespace string `yaml:"namespace,omitempty" json:"namespace,omitempty"`
   358  	// Name of the inventory resource.
   359  	Name string `yaml:"name,omitempty" json:"name,omitempty"`
   360  	// Unique label to identify inventory resource in cluster.
   361  	InventoryID string            `yaml:"inventoryID,omitempty" json:"inventoryID,omitempty"`
   362  	Labels      map[string]string `yaml:"labels,omitempty" json:"labels,omitempty"`
   363  	Annotations map[string]string `yaml:"annotations,omitempty" json:"annotations,omitempty"`
   364  }
   365  
   366  func (i Inventory) IsValid() bool {
   367  	// Name, Namespace InventoryID are required inventory fields, so we check these 3 fields.
   368  	return i.Name != "" && i.Namespace != "" && i.InventoryID != ""
   369  }
   370  
   371  type Status struct {
   372  	Conditions []Condition `yaml:"conditions,omitempty" json:"conditions,omitempty"`
   373  }
   374  
   375  type Condition struct {
   376  	Type string `yaml:"type" json:"type"`
   377  
   378  	Status ConditionStatus `yaml:"status" json:"status"`
   379  
   380  	Reason string `yaml:"reason,omitempty" json:"reason,omitempty"`
   381  
   382  	Message string `yaml:"message,omitempty" json:"message,omitempty"`
   383  }
   384  
   385  type ConditionStatus string
   386  
   387  const (
   388  	ConditionTrue    ConditionStatus = "True"
   389  	ConditionFalse   ConditionStatus = "False"
   390  	ConditionUnknown ConditionStatus = "Unknown"
   391  )