sigs.k8s.io/cluster-api@v1.7.1/exp/addons/api/v1beta1/clusterresourcesetbinding_types.go (about)

     1  /*
     2  Copyright 2021 The Kubernetes 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 v1beta1
    18  
    19  import (
    20  	"reflect"
    21  
    22  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    23  	"k8s.io/apimachinery/pkg/runtime/schema"
    24  )
    25  
    26  // ANCHOR: ResourceBinding
    27  
    28  // ResourceBinding shows the status of a resource that belongs to a ClusterResourceSet matched by the owner cluster of the ClusterResourceSetBinding object.
    29  type ResourceBinding struct {
    30  	// ResourceRef specifies a resource.
    31  	ResourceRef `json:",inline"`
    32  
    33  	// Hash is the hash of a resource's data. This can be used to decide if a resource is changed.
    34  	// For "ApplyOnce" ClusterResourceSet.spec.strategy, this is no-op as that strategy does not act on change.
    35  	// +optional
    36  	Hash string `json:"hash,omitempty"`
    37  
    38  	// LastAppliedTime identifies when this resource was last applied to the cluster.
    39  	// +optional
    40  	LastAppliedTime *metav1.Time `json:"lastAppliedTime,omitempty"`
    41  
    42  	// Applied is to track if a resource is applied to the cluster or not.
    43  	Applied bool `json:"applied"`
    44  }
    45  
    46  // ANCHOR_END: ResourceBinding
    47  
    48  // ResourceSetBinding keeps info on all of the resources in a ClusterResourceSet.
    49  type ResourceSetBinding struct {
    50  	// ClusterResourceSetName is the name of the ClusterResourceSet that is applied to the owner cluster of the binding.
    51  	ClusterResourceSetName string `json:"clusterResourceSetName"`
    52  
    53  	// Resources is a list of resources that the ClusterResourceSet has.
    54  	// +optional
    55  	Resources []ResourceBinding `json:"resources,omitempty"`
    56  }
    57  
    58  // IsApplied returns true if the resource is applied to the cluster by checking the cluster's binding.
    59  func (r *ResourceSetBinding) IsApplied(resourceRef ResourceRef) bool {
    60  	resourceBinding := r.GetResource(resourceRef)
    61  	return resourceBinding != nil && resourceBinding.Applied
    62  }
    63  
    64  // GetResource returns a ResourceBinding for a resource ref if present.
    65  func (r *ResourceSetBinding) GetResource(resourceRef ResourceRef) *ResourceBinding {
    66  	for _, resource := range r.Resources {
    67  		if reflect.DeepEqual(resource.ResourceRef, resourceRef) {
    68  			return &resource
    69  		}
    70  	}
    71  	return nil
    72  }
    73  
    74  // SetBinding sets resourceBinding for a resource in resourceSetbinding either by updating the existing one or
    75  // creating a new one.
    76  func (r *ResourceSetBinding) SetBinding(resourceBinding ResourceBinding) {
    77  	for i := range r.Resources {
    78  		if reflect.DeepEqual(r.Resources[i].ResourceRef, resourceBinding.ResourceRef) {
    79  			r.Resources[i] = resourceBinding
    80  			return
    81  		}
    82  	}
    83  	r.Resources = append(r.Resources, resourceBinding)
    84  }
    85  
    86  // GetOrCreateBinding returns the ResourceSetBinding for a given ClusterResourceSet if exists,
    87  // otherwise creates one and updates ClusterResourceSet with it.
    88  func (c *ClusterResourceSetBinding) GetOrCreateBinding(clusterResourceSet *ClusterResourceSet) *ResourceSetBinding {
    89  	for _, binding := range c.Spec.Bindings {
    90  		if binding.ClusterResourceSetName == clusterResourceSet.Name {
    91  			return binding
    92  		}
    93  	}
    94  	binding := &ResourceSetBinding{ClusterResourceSetName: clusterResourceSet.Name, Resources: []ResourceBinding{}}
    95  	c.Spec.Bindings = append(c.Spec.Bindings, binding)
    96  	return binding
    97  }
    98  
    99  // RemoveBinding removes the ClusterResourceSet from the ClusterResourceSetBinding Bindings list.
   100  func (c *ClusterResourceSetBinding) RemoveBinding(clusterResourceSet *ClusterResourceSet) {
   101  	for i, binding := range c.Spec.Bindings {
   102  		if binding.ClusterResourceSetName == clusterResourceSet.Name {
   103  			copy(c.Spec.Bindings[i:], c.Spec.Bindings[i+1:])
   104  			c.Spec.Bindings = c.Spec.Bindings[:len(c.Spec.Bindings)-1]
   105  			break
   106  		}
   107  	}
   108  }
   109  
   110  // DeleteBinding removes the ClusterResourceSet from the ClusterResourceSetBinding Bindings list.
   111  //
   112  // Deprecated: This function is deprecated and will be removed in an upcoming release of Cluster API.
   113  func (c *ClusterResourceSetBinding) DeleteBinding(clusterResourceSet *ClusterResourceSet) {
   114  	for i, binding := range c.Spec.Bindings {
   115  		if binding.ClusterResourceSetName == clusterResourceSet.Name {
   116  			copy(c.Spec.Bindings[i:], c.Spec.Bindings[i+1:])
   117  			c.Spec.Bindings = c.Spec.Bindings[:len(c.Spec.Bindings)-1]
   118  			break
   119  		}
   120  	}
   121  	c.OwnerReferences = removeOwnerRef(c.GetOwnerReferences(), metav1.OwnerReference{
   122  		APIVersion: GroupVersion.String(),
   123  		Kind:       "ClusterResourceSet",
   124  		Name:       clusterResourceSet.Name,
   125  	})
   126  }
   127  
   128  // removeOwnerRef returns the slice of owner references after removing the supplied owner ref.
   129  // Note: removeOwnerRef ignores apiVersion and UID. It will remove the passed ownerReference where it matches Name, Group and Kind.
   130  //
   131  // Deprecated: This function is deprecated and will be removed in an upcoming release of Cluster API.
   132  func removeOwnerRef(ownerReferences []metav1.OwnerReference, inputRef metav1.OwnerReference) []metav1.OwnerReference {
   133  	if index := indexOwnerRef(ownerReferences, inputRef); index != -1 {
   134  		return append(ownerReferences[:index], ownerReferences[index+1:]...)
   135  	}
   136  	return ownerReferences
   137  }
   138  
   139  // indexOwnerRef returns the index of the owner reference in the slice if found, or -1.
   140  //
   141  // Deprecated: This function is deprecated and will be removed in an upcoming release of Cluster API.
   142  func indexOwnerRef(ownerReferences []metav1.OwnerReference, ref metav1.OwnerReference) int {
   143  	for index, r := range ownerReferences {
   144  		if referSameObject(r, ref) {
   145  			return index
   146  		}
   147  	}
   148  	return -1
   149  }
   150  
   151  // Returns true if a and b point to the same object based on Group, Kind and Name.
   152  //
   153  // Deprecated: This function is deprecated and will be removed in an upcoming release of Cluster API.
   154  func referSameObject(a, b metav1.OwnerReference) bool {
   155  	aGV, err := schema.ParseGroupVersion(a.APIVersion)
   156  	if err != nil {
   157  		return false
   158  	}
   159  
   160  	bGV, err := schema.ParseGroupVersion(b.APIVersion)
   161  	if err != nil {
   162  		return false
   163  	}
   164  
   165  	return aGV.Group == bGV.Group && a.Kind == b.Kind && a.Name == b.Name
   166  }
   167  
   168  // +kubebuilder:object:root=true
   169  // +kubebuilder:resource:path=clusterresourcesetbindings,scope=Namespaced,categories=cluster-api
   170  // +kubebuilder:subresource:status
   171  // +kubebuilder:storageversion
   172  // +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Time duration since creation of ClusterResourceSetBinding"
   173  
   174  // ClusterResourceSetBinding lists all matching ClusterResourceSets with the cluster it belongs to.
   175  type ClusterResourceSetBinding struct {
   176  	metav1.TypeMeta   `json:",inline"`
   177  	metav1.ObjectMeta `json:"metadata,omitempty"`
   178  	Spec              ClusterResourceSetBindingSpec `json:"spec,omitempty"`
   179  }
   180  
   181  // ANCHOR: ClusterResourceSetBindingSpec
   182  
   183  // ClusterResourceSetBindingSpec defines the desired state of ClusterResourceSetBinding.
   184  type ClusterResourceSetBindingSpec struct {
   185  	// Bindings is a list of ClusterResourceSets and their resources.
   186  	// +optional
   187  	Bindings []*ResourceSetBinding `json:"bindings,omitempty"`
   188  
   189  	// ClusterName is the name of the Cluster this binding applies to.
   190  	// Note: this field mandatory in v1beta2.
   191  	// +optional
   192  	ClusterName string `json:"clusterName,omitempty"`
   193  }
   194  
   195  // ANCHOR_END: ClusterResourceSetBindingSpec
   196  
   197  // +kubebuilder:object:root=true
   198  
   199  // ClusterResourceSetBindingList contains a list of ClusterResourceSetBinding.
   200  type ClusterResourceSetBindingList struct {
   201  	metav1.TypeMeta `json:",inline"`
   202  	metav1.ListMeta `json:"metadata,omitempty"`
   203  	Items           []ClusterResourceSetBinding `json:"items"`
   204  }
   205  
   206  func init() {
   207  	objectTypes = append(objectTypes, &ClusterResourceSetBinding{}, &ClusterResourceSetBindingList{})
   208  }