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 }