...

Source file src/sigs.k8s.io/cli-utils/pkg/object/mutation/types.go

Documentation: sigs.k8s.io/cli-utils/pkg/object/mutation

     1  // Copyright 2020 The Kubernetes Authors.
     2  // SPDX-License-Identifier: Apache-2.0
     3  
     4  package mutation
     5  
     6  import (
     7  	"fmt"
     8  
     9  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    10  	"k8s.io/apimachinery/pkg/runtime/schema"
    11  	"sigs.k8s.io/cli-utils/pkg/object"
    12  )
    13  
    14  // ApplyTimeMutation is a list of substitutions to perform in the target
    15  // object before applying, after waiting for the source objects to be
    16  // reconciled.
    17  // This most notibly allows status fields to be substituted into spec fields.
    18  type ApplyTimeMutation []FieldSubstitution
    19  
    20  // Equal returns true if the substitutions are equivalent, ignoring order.
    21  // Fulfills Equal interface from github.com/google/go-cmp
    22  func (a ApplyTimeMutation) Equal(b ApplyTimeMutation) bool {
    23  	if len(a) != len(b) {
    24  		return false
    25  	}
    26  
    27  	mapA := make(map[FieldSubstitution]struct{}, len(a))
    28  	for _, sub := range a {
    29  		mapA[sub] = struct{}{}
    30  	}
    31  	mapB := make(map[FieldSubstitution]struct{}, len(b))
    32  	for _, sub := range b {
    33  		mapB[sub] = struct{}{}
    34  	}
    35  	if len(mapA) != len(mapB) {
    36  		return false
    37  	}
    38  	for b := range mapB {
    39  		if _, exists := mapA[b]; !exists {
    40  			return false
    41  		}
    42  	}
    43  	return true
    44  }
    45  
    46  // FieldSubstitution specifies a substitution that will be performed at
    47  // apply-time. The source object field will be read and substituted into the
    48  // target object field, replacing the token.
    49  type FieldSubstitution struct {
    50  	// SourceRef is a reference to the object that contains the source field.
    51  	SourceRef ResourceReference `json:"sourceRef"`
    52  
    53  	// SourcePath is a JSONPath reference to a field in the source object.
    54  	// Example: "$.status.number"
    55  	SourcePath string `json:"sourcePath"`
    56  
    57  	// TargetPath is a JSONPath reference to a field in the target object.
    58  	// Example: "$.spec.member"
    59  	TargetPath string `json:"targetPath"`
    60  
    61  	// Token is the substring to replace in the value of the target field.
    62  	// If empty, the target field value will be set to the source field value.
    63  	// Example: "${project-number}"
    64  	// +optional
    65  	Token string `json:"token,omitempty"`
    66  }
    67  
    68  // ResourceReference is a reference to a KRM resource by name and kind.
    69  // One of APIVersion or Group is required.
    70  // Group is generally preferred, to avoid needing to update the version in lock
    71  // step with the referenced resource.
    72  // If neither is provided, the empty group is used.
    73  type ResourceReference struct {
    74  	// Kind is a string value representing the REST resource this object represents.
    75  	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
    76  	Kind string `json:"kind"`
    77  
    78  	// APIVersion defines the versioned schema of this representation of an object.
    79  	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
    80  	// +optional
    81  	APIVersion string `json:"apiVersion,omitempty"`
    82  
    83  	// Group is accepted as a version-less alternative to APIVersion
    84  	// More info: https://kubernetes.io/docs/reference/using-api/#api-groups
    85  	// +optional
    86  	Group string `json:"group,omitempty"`
    87  
    88  	// Name of the object.
    89  	// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
    90  	Name string `json:"name,omitempty"`
    91  
    92  	// Namespace is optional, defaults to the namespace of the target object.
    93  	// More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/
    94  	// +optional
    95  	Namespace string `json:"namespace,omitempty"`
    96  }
    97  
    98  // ResourceReferenceFromUnstructured returns the object as a ResourceReference
    99  func ResourceReferenceFromUnstructured(obj *unstructured.Unstructured) ResourceReference {
   100  	return ResourceReference{
   101  		Name:       obj.GetName(),
   102  		Namespace:  obj.GetNamespace(),
   103  		Kind:       obj.GetKind(),
   104  		APIVersion: obj.GetAPIVersion(),
   105  	}
   106  }
   107  
   108  // ResourceReferenceFromObjMetadata returns the object as a ResourceReference
   109  func ResourceReferenceFromObjMetadata(id object.ObjMetadata) ResourceReference {
   110  	return ResourceReference{
   111  		Name:      id.Name,
   112  		Namespace: id.Namespace,
   113  		Kind:      id.GroupKind.Kind,
   114  		Group:     id.GroupKind.Group,
   115  	}
   116  }
   117  
   118  // GroupVersionKind satisfies the ObjectKind interface for all objects that
   119  // embed TypeMeta. Prefers Group over APIVersion.
   120  func (r ResourceReference) GroupVersionKind() schema.GroupVersionKind {
   121  	if r.Group != "" {
   122  		return schema.GroupVersionKind{Group: r.Group, Kind: r.Kind}
   123  	}
   124  	return schema.FromAPIVersionAndKind(r.APIVersion, r.Kind)
   125  }
   126  
   127  // ToUnstructured returns the name, namespace, group, version, and kind of the
   128  // ResourceReference, wrapped in a new Unstructured object.
   129  // This is useful for performing operations with
   130  // sigs.k8s.io/controller-runtime/pkg/client's unstructured Client.
   131  func (r ResourceReference) ToUnstructured() *unstructured.Unstructured {
   132  	obj := &unstructured.Unstructured{}
   133  	obj.SetName(r.Name)
   134  	obj.SetNamespace(r.Namespace)
   135  	obj.SetGroupVersionKind(r.GroupVersionKind())
   136  	return obj
   137  }
   138  
   139  // ToUnstructured returns the name, namespace, group, and kind of the
   140  // ResourceReference, wrapped in a new ObjMetadata object.
   141  func (r ResourceReference) ToObjMetadata() object.ObjMetadata {
   142  	return object.ObjMetadata{
   143  		Namespace: r.Namespace,
   144  		Name:      r.Name,
   145  		GroupKind: r.GroupVersionKind().GroupKind(),
   146  	}
   147  }
   148  
   149  // String returns the format GROUP[/VERSION][/namespaces/NAMESPACE]/KIND/NAME
   150  func (r ResourceReference) String() string {
   151  	group := r.Group
   152  	if group == "" {
   153  		group = r.APIVersion
   154  	}
   155  	if r.Namespace != "" {
   156  		return fmt.Sprintf("%s/namespaces/%s/%s/%s", group, r.Namespace, r.Kind, r.Name)
   157  	}
   158  	return fmt.Sprintf("%s/%s/%s", group, r.Kind, r.Name)
   159  }
   160  
   161  // Equal returns true if the ResourceReference sets are equivalent, ignoring version.
   162  // Fulfills Equal interface from github.com/google/go-cmp
   163  func (r ResourceReference) Equal(b ResourceReference) bool {
   164  	return r.GroupVersionKind().GroupKind() == b.GroupVersionKind().GroupKind() &&
   165  		r.Name == b.Name &&
   166  		r.Namespace == b.Namespace
   167  }
   168  

View as plain text