diff --git a/apis/v1/binding_types.go b/apis/placement/v1beta1/binding_types.go similarity index 99% rename from apis/v1/binding_types.go rename to apis/placement/v1beta1/binding_types.go index 340d36596..cdefbb892 100644 --- a/apis/v1/binding_types.go +++ b/apis/placement/v1beta1/binding_types.go @@ -3,7 +3,7 @@ Copyright (c) Microsoft Corporation. Licensed under the MIT license. */ -package v1 +package v1beta1 import ( "k8s.io/apimachinery/pkg/api/meta" diff --git a/apis/v1/clusterresourceplacement_types.go b/apis/placement/v1beta1/clusterresourceplacement_types.go similarity index 99% rename from apis/v1/clusterresourceplacement_types.go rename to apis/placement/v1beta1/clusterresourceplacement_types.go index bcfba88d9..f46042271 100644 --- a/apis/v1/clusterresourceplacement_types.go +++ b/apis/placement/v1beta1/clusterresourceplacement_types.go @@ -3,7 +3,7 @@ Copyright (c) Microsoft Corporation. Licensed under the MIT license. */ -package v1 +package v1beta1 import ( "k8s.io/apimachinery/pkg/api/meta" diff --git a/apis/v1/commons.go b/apis/placement/v1beta1/commons.go similarity index 95% rename from apis/v1/commons.go rename to apis/placement/v1beta1/commons.go index 5a4335291..9b59e1646 100644 --- a/apis/v1/commons.go +++ b/apis/placement/v1beta1/commons.go @@ -3,7 +3,7 @@ Copyright (c) Microsoft Corporation. Licensed under the MIT license. */ -package v1 +package v1beta1 import ( v1 "k8s.io/api/core/v1" @@ -14,9 +14,9 @@ type ClusterState string const ( // Unprefixed labels/annotations are reserved for end-users - // we will add a fleet.azure.com to designate these labels/annotations as official fleet labels/annotations. + // we will add a placement.karavel.io to designate these labels/annotations as official fleet labels/annotations. // See https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#label-selector-and-annotation-conventions - fleetPrefix = "fleet.azure.com/" + fleetPrefix = "placement.karavel.io/" // CRPTrackingLabel is the label that points to the cluster resource policy that creates a resource binding. CRPTrackingLabel = fleetPrefix + "parentCRP" diff --git a/apis/v1/doc.go b/apis/placement/v1beta1/doc.go similarity index 82% rename from apis/v1/doc.go rename to apis/placement/v1beta1/doc.go index a958c08f2..9880df354 100644 --- a/apis/v1/doc.go +++ b/apis/placement/v1beta1/doc.go @@ -7,5 +7,5 @@ Licensed under the MIT license. // +kubebuilder:object:generate=true // +k8s:deepcopy-gen=package,register -// +groupName=fleet.azure.com -package v1 +// +groupName=placement.karavel.io +package v1beta1 diff --git a/apis/v1/groupversion_info.go b/apis/placement/v1beta1/groupversion_info.go similarity index 79% rename from apis/v1/groupversion_info.go rename to apis/placement/v1beta1/groupversion_info.go index ce15d4374..e49225716 100644 --- a/apis/v1/groupversion_info.go +++ b/apis/placement/v1beta1/groupversion_info.go @@ -4,8 +4,8 @@ Licensed under the MIT license. */ // +kubebuilder:object:generate=true -// +groupName=fleet.azure.com -package v1 +// +groupName=placement.karavel.io +package v1beta1 import ( "k8s.io/apimachinery/pkg/runtime/schema" @@ -14,7 +14,7 @@ import ( var ( // GroupVersion is group version used to register these objects - GroupVersion = schema.GroupVersion{Group: "fleet.azure.com", Version: "v1"} + GroupVersion = schema.GroupVersion{Group: "placement.karavel.io", Version: "v1alpha1"} // SchemeBuilder is used to add go types to the GroupVersionKind scheme SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} diff --git a/apis/v1/internalmembercluster_types.go b/apis/placement/v1beta1/internalmembercluster_types.go similarity index 99% rename from apis/v1/internalmembercluster_types.go rename to apis/placement/v1beta1/internalmembercluster_types.go index c96d0e110..b7c877578 100644 --- a/apis/v1/internalmembercluster_types.go +++ b/apis/placement/v1beta1/internalmembercluster_types.go @@ -3,7 +3,7 @@ Copyright (c) Microsoft Corporation. Licensed under the MIT license. */ -package v1 +package v1beta1 import ( "k8s.io/apimachinery/pkg/api/meta" diff --git a/apis/v1/membercluster_types.go b/apis/placement/v1beta1/membercluster_types.go similarity index 99% rename from apis/v1/membercluster_types.go rename to apis/placement/v1beta1/membercluster_types.go index 46b60e9e5..5677eae27 100644 --- a/apis/v1/membercluster_types.go +++ b/apis/placement/v1beta1/membercluster_types.go @@ -3,7 +3,7 @@ Copyright (c) Microsoft Corporation. Licensed under the MIT license. */ -package v1 +package v1beta1 import ( rbacv1 "k8s.io/api/rbac/v1" diff --git a/apis/v1/policysnapshot_types.go b/apis/placement/v1beta1/policysnapshot_types.go similarity index 99% rename from apis/v1/policysnapshot_types.go rename to apis/placement/v1beta1/policysnapshot_types.go index cf78b3bfa..07eb2e597 100644 --- a/apis/v1/policysnapshot_types.go +++ b/apis/placement/v1beta1/policysnapshot_types.go @@ -3,7 +3,7 @@ Copyright (c) Microsoft Corporation. Licensed under the MIT license. */ -package v1 +package v1beta1 import ( "k8s.io/apimachinery/pkg/api/meta" diff --git a/apis/v1/resourcesnapshot_types.go b/apis/placement/v1beta1/resourcesnapshot_types.go similarity index 99% rename from apis/v1/resourcesnapshot_types.go rename to apis/placement/v1beta1/resourcesnapshot_types.go index 978021aff..7caf14d42 100644 --- a/apis/v1/resourcesnapshot_types.go +++ b/apis/placement/v1beta1/resourcesnapshot_types.go @@ -3,7 +3,7 @@ Copyright (c) Microsoft Corporation. Licensed under the MIT license. */ -package v1 +package v1beta1 import ( "k8s.io/apimachinery/pkg/api/meta" diff --git a/apis/v1/zz_generated.deepcopy.go b/apis/placement/v1beta1/zz_generated.deepcopy.go similarity index 98% rename from apis/v1/zz_generated.deepcopy.go rename to apis/placement/v1beta1/zz_generated.deepcopy.go index b957c4de7..eb12e1242 100644 --- a/apis/v1/zz_generated.deepcopy.go +++ b/apis/placement/v1beta1/zz_generated.deepcopy.go @@ -8,11 +8,11 @@ Licensed under the MIT license. // Code generated by controller-gen. DO NOT EDIT. -package v1 +package v1beta1 import ( corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" ) @@ -41,7 +41,7 @@ func (in *AgentStatus) DeepCopyInto(out *AgentStatus) { *out = *in if in.Conditions != nil { in, out := &in.Conditions, &out.Conditions - *out = make([]metav1.Condition, len(*in)) + *out = make([]v1.Condition, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } @@ -315,7 +315,7 @@ func (in *ClusterResourcePlacementStatus) DeepCopyInto(out *ClusterResourcePlace *out = *in if in.Conditions != nil { in, out := &in.Conditions, &out.Conditions - *out = make([]metav1.Condition, len(*in)) + *out = make([]v1.Condition, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } @@ -354,7 +354,7 @@ func (in *ClusterResourceSelector) DeepCopyInto(out *ClusterResourceSelector) { *out = *in if in.LabelSelector != nil { in, out := &in.LabelSelector, &out.LabelSelector - *out = new(metav1.LabelSelector) + *out = new(v1.LabelSelector) (*in).DeepCopyInto(*out) } } @@ -685,7 +685,7 @@ func (in *MemberClusterStatus) DeepCopyInto(out *MemberClusterStatus) { *out = *in if in.Conditions != nil { in, out := &in.Conditions, &out.Conditions - *out = make([]metav1.Condition, len(*in)) + *out = make([]v1.Condition, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } @@ -777,7 +777,7 @@ func (in *PolicySnapshotStatus) DeepCopyInto(out *PolicySnapshotStatus) { *out = *in if in.Conditions != nil { in, out := &in.Conditions, &out.Conditions - *out = make([]metav1.Condition, len(*in)) + *out = make([]v1.Condition, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } @@ -837,7 +837,7 @@ func (in *ResourceBindingStatus) DeepCopyInto(out *ResourceBindingStatus) { *out = *in if in.Conditions != nil { in, out := &in.Conditions, &out.Conditions - *out = make([]metav1.Condition, len(*in)) + *out = make([]v1.Condition, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } @@ -912,7 +912,7 @@ func (in *ResourceSnapshotStatus) DeepCopyInto(out *ResourceSnapshotStatus) { *out = *in if in.Conditions != nil { in, out := &in.Conditions, &out.Conditions - *out = make([]metav1.Condition, len(*in)) + *out = make([]v1.Condition, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } diff --git a/apis/v1alpha1/clusterresourceplacement_types.go b/apis/v1alpha1/clusterresourceplacement_types.go index 8551f8a07..53fe714cc 100644 --- a/apis/v1alpha1/clusterresourceplacement_types.go +++ b/apis/v1alpha1/clusterresourceplacement_types.go @@ -14,7 +14,6 @@ import ( // +genclient:nonNamespaced // +kubebuilder:object:root=true // +kubebuilder:resource:scope="Cluster",shortName=crp,categories={fleet-workload} -// +kubebuilder:storageversion // +kubebuilder:subresource:status // +kubebuilder:printcolumn:JSONPath=`.metadata.generation`,name="Gen",type=string // +kubebuilder:printcolumn:JSONPath=`.status.conditions[?(@.type=="Scheduled")].status`,name="Scheduled",type=string diff --git a/apis/v1alpha1/internalmembercluster_types.go b/apis/v1alpha1/internalmembercluster_types.go index 433be9f0f..6ba336176 100644 --- a/apis/v1alpha1/internalmembercluster_types.go +++ b/apis/v1alpha1/internalmembercluster_types.go @@ -11,7 +11,6 @@ import ( ) // +kubebuilder:object:root=true -// +kubebuilder:storageversion // +kubebuilder:resource:scope=Namespaced,categories={fleet},shortName=imc // +kubebuilder:subresource:status // +kubebuilder:printcolumn:JSONPath=`.metadata.creationTimestamp`,name="Age",type=date diff --git a/apis/v1alpha1/membercluster_types.go b/apis/v1alpha1/membercluster_types.go index f121699c4..4bbf81288 100644 --- a/apis/v1alpha1/membercluster_types.go +++ b/apis/v1alpha1/membercluster_types.go @@ -12,7 +12,6 @@ import ( ) // +kubebuilder:object:root=true -// +kubebuilder:storageversion // +kubebuilder:resource:scope=Cluster,categories={fleet},shortName=mc // +kubebuilder:subresource:status // +kubebuilder:printcolumn:JSONPath=`.status.conditions[?(@.type=="Joined")].status`,name="Joined",type=string diff --git a/config/crd/bases/fleet.azure.com_clusterresourceplacements.yaml b/config/crd/bases/fleet.azure.com_clusterresourceplacements.yaml index ae82593c7..a09b0a5b2 100644 --- a/config/crd/bases/fleet.azure.com_clusterresourceplacements.yaml +++ b/config/crd/bases/fleet.azure.com_clusterresourceplacements.yaml @@ -18,595 +18,6 @@ spec: singular: clusterresourceplacement scope: Cluster versions: - - additionalPrinterColumns: - - jsonPath: .metadata.generation - name: Gen - type: string - - jsonPath: .status.conditions[?(@.type=="Scheduled")].status - name: Scheduled - type: string - - jsonPath: .status.conditions[?(@.type=="Scheduled")].observedGeneration - name: ScheduledGen - type: string - - jsonPath: .status.conditions[?(@.type=="Applied")].status - name: Applied - type: string - - jsonPath: .status.conditions[?(@.type=="Applied")].observedGeneration - name: AppliedGen - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1 - schema: - openAPIV3Schema: - description: 'ClusterResourcePlacement is used to select cluster scoped resources, - including built-in resources and custom resources, and placement them onto - selected member clusters in a fleet. If a namespace is selected, ALL the - resources under the namespace are placed to the target clusters. Note that - you can''t select the following resources: - reserved namespaces including: - default, kube-* (reserved for Kubernetes system namespaces), fleet-* (reserved - for fleet system namespaces). - reserved fleet resource types including: - MemberCluster, InternalMemberCluster, ClusterResourcePlacement, MultiClusterService, - ServiceImport, etc. The `ClusterResourceBinding` will be created and it - represents a scheduling decision that binds a group of resources to a cluster.' - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: The desired state of ClusterResourcePlacement. - properties: - policy: - description: Policy defines how to select member clusters to place - the selected resources. If unspecified, all the joined member clusters - are selected. - properties: - affinity: - description: Affinity contains cluster affinity scheduling rules. - Defines which member clusters to place the selected resources. - properties: - clusterAffinity: - description: ClusterAffinity contains cluster affinity scheduling - rules for the selected resources. - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler computes a score for each cluster - at schedule time by iterating through the elements of - this field and adding "weight" to the sum if the cluster - matches the corresponding matchExpression. The scheduler - then chooses the first `N` clusters with the highest - sum to satisfy the placement. This field is ignored - if the placement type is "PickAll". If the cluster score - changes at some point after the placement (e.g. due - to an update), the system may or may not try to eventually - move the resource from a cluster with a lower score - to a cluster with higher score. - items: - properties: - preference: - description: A cluster selector term, associated - with the corresponding weight. - properties: - labelSelector: - description: LabelSelector is a label query - over all the joined member clusters. Clusters - matching the query are selected. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The requirements - are ANDed. - items: - description: A label selector requirement - is a selector that contains values, - a key, and an operator that relates - the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: operator represents a - key's relationship to a set of values. - Valid operators are In, NotIn, Exists - and DoesNotExist. - type: string - values: - description: values is an array of - string values. If the operator is - In or NotIn, the values array must - be non-empty. If the operator is - Exists or DoesNotExist, the values - array must be empty. This array - is replaced during a strategic merge - patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: matchLabels is a map of {key,value} - pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, - whose key field is "key", the operator - is "In", and the values array contains - only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - required: - - labelSelector - type: object - weight: - description: Weight associated with matching the - corresponding clusterSelectorTerm, in the range - [-100, 100]. - format: int32 - type: integer - required: - - preference - - weight - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - description: If the affinity requirements specified by - this field are not met at scheduling time, the resource - will not be scheduled onto the cluster. If the affinity - requirements specified by this field cease to be met - at some point after the placement (e.g. due to an update), - the system may or may not try to eventually remove the - resource from the cluster. - properties: - clusterSelectorTerms: - description: ClusterSelectorTerms is a list of cluster - selector terms. The terms are `ORed`. - items: - description: ClusterSelectorTerm contains the requirements - to select clusters. - properties: - labelSelector: - description: LabelSelector is a label query - over all the joined member clusters. Clusters - matching the query are selected. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The requirements - are ANDed. - items: - description: A label selector requirement - is a selector that contains values, - a key, and an operator that relates - the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: operator represents a - key's relationship to a set of values. - Valid operators are In, NotIn, Exists - and DoesNotExist. - type: string - values: - description: values is an array of - string values. If the operator is - In or NotIn, the values array must - be non-empty. If the operator is - Exists or DoesNotExist, the values - array must be empty. This array - is replaced during a strategic merge - patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: matchLabels is a map of {key,value} - pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, - whose key field is "key", the operator - is "In", and the values array contains - only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - required: - - labelSelector - type: object - maxItems: 10 - type: array - required: - - clusterSelectorTerms - type: object - type: object - type: object - clusterNames: - description: ClusterNames contains a list of names of MemberCluster - to place the selected resources. If the list is not empty, `PlacementType`, - `NumberOfClusters`, `Affinity`, and `TopologySpreadConstraints` - are ignored. - items: - type: string - maxItems: 100 - type: array - numberOfClusters: - description: NumberOfClusters of placement. Only valid if the - placement type is "PickN". - format: int32 - type: integer - placementType: - description: Type of placement. Can be "PickAll" or "PickN". Default - is PickAll. - type: string - topologySpreadConstraints: - description: TopologySpreadConstraints describes how a group of - resources ought to spread across multiple topology domains. - Scheduler will schedule resources in a way which abides by the - constraints. All topologySpreadConstraints are ANDed. - items: - description: TopologySpreadConstraint specifies how to spread - resources among the given cluster topology. - properties: - maxSkew: - description: MaxSkew describes the degree to which resources - may be unevenly distributed. When `whenUnsatisfiable=DoNotSchedule`, - it is the maximum permitted difference between the number - of resource copies in the target topology and the global - minimum. The global minimum is the minimum number of resource - copies in a domain. When `whenUnsatisfiable=ScheduleAnyway`, - it is used to give higher precedence to topologies that - satisfy it. It's an optional field. Default value is 1 - and 0 is not allowed. - format: int32 - type: integer - topologyKey: - description: TopologyKey is the key of cluster labels. Clusters - that have a label with this key and identical values are - considered to be in the same topology. We consider each - as a "bucket", and try to put balanced number - of replicas of the resource into each bucket honor the - `MaxSkew` value. It's a required field. - type: string - whenUnsatisfiable: - description: WhenUnsatisfiable indicates how to deal with - the resource if it doesn't satisfy the spread constraint. - - DoNotSchedule (default) tells the scheduler not to schedule - it. - ScheduleAnyway tells the scheduler to schedule the - resource in any cluster, but giving higher precedence - to topologies that would help reduce the skew. It's an - optional field. - type: string - required: - - topologyKey - type: object - type: array - type: object - resourceSelectors: - description: ResourceSelectors is an array of selectors used to select - cluster scoped resources. The selectors are `ORed`. You can have - 1-100 selectors. - items: - description: ClusterResourceSelector is used to select cluster scoped - resources as the target resources to be placed. If a namespace - is selected, ALL the resources under the namespace are selected - automatically. All the fields are `ANDed`. In other words, a resource - must match all the fields to be selected. - properties: - group: - description: Group name of the cluster-scoped resource. Use - an empty string to select resources under the core API group - (e.g., namespaces). - type: string - kind: - description: 'Kind of the cluster-scoped resource. Note: When - `Kind` is `namespace`, ALL the resources under the selected - namespaces are selected.' - type: string - labelSelector: - description: A label query over all the cluster-scoped resources. - Resources matching the query are selected. Note that namespace-scoped - resources can't be selected even if they match the query. - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: A label selector requirement is a selector - that contains values, a key, and an operator that relates - the key and values. - properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: operator represents a key's relationship - to a set of values. Valid operators are In, NotIn, - Exists and DoesNotExist. - type: string - values: - description: values is an array of string values. - If the operator is In or NotIn, the values array - must be non-empty. If the operator is Exists or - DoesNotExist, the values array must be empty. This - array is replaced during a strategic merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: matchLabels is a map of {key,value} pairs. - A single {key,value} in the matchLabels map is equivalent - to an element of matchExpressions, whose key field is - "key", the operator is "In", and the values array contains - only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - name: - description: Name of the cluster-scoped resource. - type: string - version: - description: Version of the cluster-scoped resource. - type: string - required: - - group - - kind - - version - type: object - maxItems: 100 - minItems: 1 - type: array - required: - - resourceSelectors - type: object - status: - description: The observed status of ClusterResourcePlacement. - properties: - conditions: - description: Conditions is an array of current observed conditions - for ClusterResourcePlacement. - items: - description: "Condition contains details for one aspect of the current - state of this API Resource. --- This struct is intended for direct - use as an array at the field path .status.conditions. For example, - \n type FooStatus struct{ // Represents the observations of a - foo's current state. // Known .status.conditions.type are: \"Available\", - \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge - // +listType=map // +listMapKey=type Conditions []metav1.Condition - `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" - protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" - properties: - lastTransitionTime: - description: lastTransitionTime is the last time the condition - transitioned from one status to another. This should be when - the underlying condition changed. If that is not known, then - using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: message is a human readable message indicating - details about the transition. This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: observedGeneration represents the .metadata.generation - that the condition was set based upon. For instance, if .metadata.generation - is currently 12, but the .status.conditions[x].observedGeneration - is 9, the condition is out of date with respect to the current - state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: reason contains a programmatic identifier indicating - the reason for the condition's last transition. Producers - of specific condition types may define expected values and - meanings for this field, and whether the values are considered - a guaranteed API. The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - --- Many .condition.type values are consistent across resources - like Available, but because arbitrary conditions can be useful - (see .node.status.conditions), the ability to deconflict is - important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - failedPlacements: - description: FailedResourcePlacements is a list of all the resources - failed to be placed to the given clusters. Note that we only include - 1000 failed resource placements even if there are more than 1000. - items: - description: FailedResourcePlacement contains the failure details - of a failed resource placement. - properties: - clusterName: - description: Name of the member cluster that the resource is - placed to. - type: string - condition: - description: The failed condition status. - properties: - lastTransitionTime: - description: lastTransitionTime is the last time the condition - transitioned from one status to another. This should be - when the underlying condition changed. If that is not - known, then using the time when the API field changed - is acceptable. - format: date-time - type: string - message: - description: message is a human readable message indicating - details about the transition. This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: observedGeneration represents the .metadata.generation - that the condition was set based upon. For instance, if - .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration - is 9, the condition is out of date with respect to the - current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: reason contains a programmatic identifier indicating - the reason for the condition's last transition. Producers - of specific condition types may define expected values - and meanings for this field, and whether the values are - considered a guaranteed API. The value should be a CamelCase - string. This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, - Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - --- Many .condition.type values are consistent across - resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability - to deconflict is important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - group: - description: Group is the group name of the selected resource. - type: string - kind: - description: Kind represents the Kind of the selected resources. - type: string - name: - description: Name of the target resource. - type: string - namespace: - description: Namespace is the namespace of the resource. Empty - if the resource is cluster scoped. - type: string - version: - description: Version is the version of the selected resource. - type: string - required: - - clusterName - - condition - - kind - - name - - version - type: object - maxItems: 1000 - type: array - selectedResources: - description: SelectedResources contains a list of resources selected - by ResourceSelectors. - items: - description: ResourceIdentifier identifies one Kubernetes resource. - properties: - group: - description: Group is the group name of the selected resource. - type: string - kind: - description: Kind represents the Kind of the selected resources. - type: string - name: - description: Name of the target resource. - type: string - namespace: - description: Namespace is the namespace of the resource. Empty - if the resource is cluster scoped. - type: string - version: - description: Version is the version of the selected resource. - type: string - required: - - kind - - name - - version - type: object - type: array - targetClusters: - description: TargetClusters contains a list of names of member clusters - selected by PlacementPolicy. Note that the clusters must be both - joined and meeting PlacementPolicy. - items: - type: string - type: array - type: object - required: - - spec - type: object - served: true - storage: false - subresources: - status: {} - additionalPrinterColumns: - jsonPath: .metadata.generation name: Gen diff --git a/config/crd/bases/fleet.azure.com_internalmemberclusters.yaml b/config/crd/bases/fleet.azure.com_internalmemberclusters.yaml index b18ab094a..7765494bb 100644 --- a/config/crd/bases/fleet.azure.com_internalmemberclusters.yaml +++ b/config/crd/bases/fleet.azure.com_internalmemberclusters.yaml @@ -18,185 +18,6 @@ spec: singular: internalmembercluster scope: Namespaced versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1 - schema: - openAPIV3Schema: - description: InternalMemberCluster is used by hub agent to notify the member - agents about the member cluster state changes, and is used by the member - agents to report their status. - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: The desired state of InternalMemberCluster. - properties: - heartbeatPeriodSeconds: - default: 60 - description: 'How often (in seconds) for the member cluster to send - a heartbeat to the hub cluster. Default: 60 seconds. Min: 1 second. - Max: 10 minutes.' - format: int32 - maximum: 600 - minimum: 1 - type: integer - state: - description: 'The desired state of the member cluster. Possible values: - Join, Leave.' - type: string - required: - - state - type: object - status: - description: The observed status of InternalMemberCluster. - properties: - agentStatus: - description: AgentStatus is an array of current observed status, each - corresponding to one member agent running in the member cluster. - items: - description: AgentStatus defines the observed status of the member - agent of the given type. - properties: - conditions: - description: Conditions is an array of current observed conditions - for the member agent. - items: - description: "Condition contains details for one aspect of - the current state of this API Resource. --- This struct - is intended for direct use as an array at the field path - .status.conditions. For example, \n type FooStatus struct{ - // Represents the observations of a foo's current state. - // Known .status.conditions.type are: \"Available\", \"Progressing\", - and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge - // +listType=map // +listMapKey=type Conditions []metav1.Condition - `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" - protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields - }" - properties: - lastTransitionTime: - description: lastTransitionTime is the last time the condition - transitioned from one status to another. This should - be when the underlying condition changed. If that is - not known, then using the time when the API field changed - is acceptable. - format: date-time - type: string - message: - description: message is a human readable message indicating - details about the transition. This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: observedGeneration represents the .metadata.generation - that the condition was set based upon. For instance, - if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration - is 9, the condition is out of date with respect to the - current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: reason contains a programmatic identifier - indicating the reason for the condition's last transition. - Producers of specific condition types may define expected - values and meanings for this field, and whether the - values are considered a guaranteed API. The value should - be a CamelCase string. This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, - Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - --- Many .condition.type values are consistent across - resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability - to deconflict is important. The regex it matches is - (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - lastReceivedHeartbeat: - description: Last time we received a heartbeat from the member - agent. - format: date-time - type: string - type: - description: Type of the member agent. - type: string - required: - - type - type: object - type: array - resourceUsage: - description: The current observed resource usage of the member cluster. - It is populated by the member agent. - properties: - allocatable: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: Allocatable represents the total resources of all - the nodes on a member cluster that are available for scheduling. - type: object - capacity: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: Capacity represents the total resource capacity of - all the nodes on a member cluster. - type: object - observationTime: - description: When the resource usage is observed. - format: date-time - type: string - type: object - type: object - required: - - spec - type: object - served: true - storage: false - subresources: - status: {} - additionalPrinterColumns: - jsonPath: .metadata.creationTimestamp name: Age diff --git a/config/crd/bases/fleet.azure.com_memberclusters.yaml b/config/crd/bases/fleet.azure.com_memberclusters.yaml index de46eac9a..7a59388e7 100644 --- a/config/crd/bases/fleet.azure.com_memberclusters.yaml +++ b/config/crd/bases/fleet.azure.com_memberclusters.yaml @@ -18,291 +18,6 @@ spec: singular: membercluster scope: Cluster versions: - - additionalPrinterColumns: - - jsonPath: .status.conditions[?(@.type=="Joined")].status - name: Joined - type: string - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1 - schema: - openAPIV3Schema: - description: MemberCluster is a resource created in the hub cluster to represent - a member cluster within a fleet. - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: The desired state of MemberCluster. - properties: - heartbeatPeriodSeconds: - default: 60 - description: 'How often (in seconds) for the member cluster to send - a heartbeat to the hub cluster. Default: 60 seconds. Min: 1 second. - Max: 10 minutes.' - format: int32 - maximum: 600 - minimum: 1 - type: integer - identity: - description: The identity used by the member cluster to access the - hub cluster. The hub agents deployed on the hub cluster will automatically - grant the minimal required permissions to this identity for the - member agents deployed on the member cluster to access the hub cluster. - properties: - apiGroup: - description: APIGroup holds the API group of the referenced subject. - Defaults to "" for ServiceAccount subjects. Defaults to "rbac.authorization.k8s.io" - for User and Group subjects. - type: string - kind: - description: Kind of object being referenced. Values defined by - this API group are "User", "Group", and "ServiceAccount". If - the Authorizer does not recognized the kind value, the Authorizer - should report an error. - type: string - name: - description: Name of the object being referenced. - type: string - namespace: - description: Namespace of the referenced object. If the object - kind is non-namespace, such as "User" or "Group", and this value - is not empty the Authorizer should report an error. - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - state: - description: 'The desired state of the member cluster. Possible values: - Join, Leave.' - type: string - required: - - identity - - state - type: object - status: - description: The observed status of MemberCluster. - properties: - agentStatus: - description: AgentStatus is an array of current observed status, each - corresponding to one member agent running in the member cluster. - items: - description: AgentStatus defines the observed status of the member - agent of the given type. - properties: - conditions: - description: Conditions is an array of current observed conditions - for the member agent. - items: - description: "Condition contains details for one aspect of - the current state of this API Resource. --- This struct - is intended for direct use as an array at the field path - .status.conditions. For example, \n type FooStatus struct{ - // Represents the observations of a foo's current state. - // Known .status.conditions.type are: \"Available\", \"Progressing\", - and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge - // +listType=map // +listMapKey=type Conditions []metav1.Condition - `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" - protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields - }" - properties: - lastTransitionTime: - description: lastTransitionTime is the last time the condition - transitioned from one status to another. This should - be when the underlying condition changed. If that is - not known, then using the time when the API field changed - is acceptable. - format: date-time - type: string - message: - description: message is a human readable message indicating - details about the transition. This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: observedGeneration represents the .metadata.generation - that the condition was set based upon. For instance, - if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration - is 9, the condition is out of date with respect to the - current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: reason contains a programmatic identifier - indicating the reason for the condition's last transition. - Producers of specific condition types may define expected - values and meanings for this field, and whether the - values are considered a guaranteed API. The value should - be a CamelCase string. This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, - Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - --- Many .condition.type values are consistent across - resources like Available, but because arbitrary conditions - can be useful (see .node.status.conditions), the ability - to deconflict is important. The regex it matches is - (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - lastReceivedHeartbeat: - description: Last time we received a heartbeat from the member - agent. - format: date-time - type: string - type: - description: Type of the member agent. - type: string - required: - - type - type: object - type: array - conditions: - description: Conditions is an array of current observed conditions - for the member cluster. - items: - description: "Condition contains details for one aspect of the current - state of this API Resource. --- This struct is intended for direct - use as an array at the field path .status.conditions. For example, - \n type FooStatus struct{ // Represents the observations of a - foo's current state. // Known .status.conditions.type are: \"Available\", - \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge - // +listType=map // +listMapKey=type Conditions []metav1.Condition - `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" - protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" - properties: - lastTransitionTime: - description: lastTransitionTime is the last time the condition - transitioned from one status to another. This should be when - the underlying condition changed. If that is not known, then - using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: message is a human readable message indicating - details about the transition. This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: observedGeneration represents the .metadata.generation - that the condition was set based upon. For instance, if .metadata.generation - is currently 12, but the .status.conditions[x].observedGeneration - is 9, the condition is out of date with respect to the current - state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: reason contains a programmatic identifier indicating - the reason for the condition's last transition. Producers - of specific condition types may define expected values and - meanings for this field, and whether the values are considered - a guaranteed API. The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - --- Many .condition.type values are consistent across resources - like Available, but because arbitrary conditions can be useful - (see .node.status.conditions), the ability to deconflict is - important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - resourceUsage: - description: The current observed resource usage of the member cluster. - It is copied from the corresponding InternalMemberCluster object. - properties: - allocatable: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: Allocatable represents the total resources of all - the nodes on a member cluster that are available for scheduling. - type: object - capacity: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: Capacity represents the total resource capacity of - all the nodes on a member cluster. - type: object - observationTime: - description: When the resource usage is observed. - format: date-time - type: string - type: object - type: object - required: - - spec - type: object - served: true - storage: false - subresources: - status: {} - additionalPrinterColumns: - jsonPath: .status.conditions[?(@.type=="Joined")].status name: Joined diff --git a/config/crd/bases/fleet.azure.com_clusterpolicysnapshots.yaml b/config/crd/bases/placement.karavel.io_clusterpolicysnapshots.yaml similarity index 99% rename from config/crd/bases/fleet.azure.com_clusterpolicysnapshots.yaml rename to config/crd/bases/placement.karavel.io_clusterpolicysnapshots.yaml index 33c35d013..017b0be72 100644 --- a/config/crd/bases/fleet.azure.com_clusterpolicysnapshots.yaml +++ b/config/crd/bases/placement.karavel.io_clusterpolicysnapshots.yaml @@ -4,9 +4,9 @@ kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.11.4 - name: clusterpolicysnapshots.fleet.azure.com + name: clusterpolicysnapshots.placement.karavel.io spec: - group: fleet.azure.com + group: placement.karavel.io names: categories: - fleet-workload @@ -25,7 +25,7 @@ spec: - jsonPath: .metadata.creationTimestamp name: Age type: date - name: v1 + name: v1beta1 schema: openAPIV3Schema: description: 'ClusterPolicySnapshot is used to store a snapshot of cluster diff --git a/config/crd/bases/fleet.azure.com_clusterresourcebindings.yaml b/config/crd/bases/placement.karavel.io_clusterresourcebindings.yaml similarity index 98% rename from config/crd/bases/fleet.azure.com_clusterresourcebindings.yaml rename to config/crd/bases/placement.karavel.io_clusterresourcebindings.yaml index 8dd31c16d..87fbee0be 100644 --- a/config/crd/bases/fleet.azure.com_clusterresourcebindings.yaml +++ b/config/crd/bases/placement.karavel.io_clusterresourcebindings.yaml @@ -4,9 +4,9 @@ kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.11.4 - name: clusterresourcebindings.fleet.azure.com + name: clusterresourcebindings.placement.karavel.io spec: - group: fleet.azure.com + group: placement.karavel.io names: categories: - fleet @@ -25,7 +25,7 @@ spec: - jsonPath: .metadata.creationTimestamp name: Age type: date - name: v1 + name: v1beta1 schema: openAPIV3Schema: description: ClusterResourceBinding represents a scheduling decision that diff --git a/config/crd/bases/placement.karavel.io_clusterresourceplacements.yaml b/config/crd/bases/placement.karavel.io_clusterresourceplacements.yaml new file mode 100644 index 000000000..3eb633d7d --- /dev/null +++ b/config/crd/bases/placement.karavel.io_clusterresourceplacements.yaml @@ -0,0 +1,609 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.11.4 + name: clusterresourceplacements.placement.karavel.io +spec: + group: placement.karavel.io + names: + categories: + - fleet-workload + kind: ClusterResourcePlacement + listKind: ClusterResourcePlacementList + plural: clusterresourceplacements + shortNames: + - crp + singular: clusterresourceplacement + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.generation + name: Gen + type: string + - jsonPath: .status.conditions[?(@.type=="Scheduled")].status + name: Scheduled + type: string + - jsonPath: .status.conditions[?(@.type=="Scheduled")].observedGeneration + name: ScheduledGen + type: string + - jsonPath: .status.conditions[?(@.type=="Applied")].status + name: Applied + type: string + - jsonPath: .status.conditions[?(@.type=="Applied")].observedGeneration + name: AppliedGen + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + description: 'ClusterResourcePlacement is used to select cluster scoped resources, + including built-in resources and custom resources, and placement them onto + selected member clusters in a fleet. If a namespace is selected, ALL the + resources under the namespace are placed to the target clusters. Note that + you can''t select the following resources: - reserved namespaces including: + default, kube-* (reserved for Kubernetes system namespaces), fleet-* (reserved + for fleet system namespaces). - reserved fleet resource types including: + MemberCluster, InternalMemberCluster, ClusterResourcePlacement, MultiClusterService, + ServiceImport, etc. The `ClusterResourceBinding` will be created and it + represents a scheduling decision that binds a group of resources to a cluster.' + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: The desired state of ClusterResourcePlacement. + properties: + policy: + description: Policy defines how to select member clusters to place + the selected resources. If unspecified, all the joined member clusters + are selected. + properties: + affinity: + description: Affinity contains cluster affinity scheduling rules. + Defines which member clusters to place the selected resources. + properties: + clusterAffinity: + description: ClusterAffinity contains cluster affinity scheduling + rules for the selected resources. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler computes a score for each cluster + at schedule time by iterating through the elements of + this field and adding "weight" to the sum if the cluster + matches the corresponding matchExpression. The scheduler + then chooses the first `N` clusters with the highest + sum to satisfy the placement. This field is ignored + if the placement type is "PickAll". If the cluster score + changes at some point after the placement (e.g. due + to an update), the system may or may not try to eventually + move the resource from a cluster with a lower score + to a cluster with higher score. + items: + properties: + preference: + description: A cluster selector term, associated + with the corresponding weight. + properties: + labelSelector: + description: LabelSelector is a label query + over all the joined member clusters. Clusters + matching the query are selected. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - labelSelector + type: object + weight: + description: Weight associated with matching the + corresponding clusterSelectorTerm, in the range + [-100, 100]. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the resource + will not be scheduled onto the cluster. If the affinity + requirements specified by this field cease to be met + at some point after the placement (e.g. due to an update), + the system may or may not try to eventually remove the + resource from the cluster. + properties: + clusterSelectorTerms: + description: ClusterSelectorTerms is a list of cluster + selector terms. The terms are `ORed`. + items: + description: ClusterSelectorTerm contains the requirements + to select clusters. + properties: + labelSelector: + description: LabelSelector is a label query + over all the joined member clusters. Clusters + matching the query are selected. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - labelSelector + type: object + maxItems: 10 + type: array + required: + - clusterSelectorTerms + type: object + type: object + type: object + clusterNames: + description: ClusterNames contains a list of names of MemberCluster + to place the selected resources. If the list is not empty, `PlacementType`, + `NumberOfClusters`, `Affinity`, and `TopologySpreadConstraints` + are ignored. + items: + type: string + maxItems: 100 + type: array + numberOfClusters: + description: NumberOfClusters of placement. Only valid if the + placement type is "PickN". + format: int32 + type: integer + placementType: + description: Type of placement. Can be "PickAll" or "PickN". Default + is PickAll. + type: string + topologySpreadConstraints: + description: TopologySpreadConstraints describes how a group of + resources ought to spread across multiple topology domains. + Scheduler will schedule resources in a way which abides by the + constraints. All topologySpreadConstraints are ANDed. + items: + description: TopologySpreadConstraint specifies how to spread + resources among the given cluster topology. + properties: + maxSkew: + description: MaxSkew describes the degree to which resources + may be unevenly distributed. When `whenUnsatisfiable=DoNotSchedule`, + it is the maximum permitted difference between the number + of resource copies in the target topology and the global + minimum. The global minimum is the minimum number of resource + copies in a domain. When `whenUnsatisfiable=ScheduleAnyway`, + it is used to give higher precedence to topologies that + satisfy it. It's an optional field. Default value is 1 + and 0 is not allowed. + format: int32 + type: integer + topologyKey: + description: TopologyKey is the key of cluster labels. Clusters + that have a label with this key and identical values are + considered to be in the same topology. We consider each + as a "bucket", and try to put balanced number + of replicas of the resource into each bucket honor the + `MaxSkew` value. It's a required field. + type: string + whenUnsatisfiable: + description: WhenUnsatisfiable indicates how to deal with + the resource if it doesn't satisfy the spread constraint. + - DoNotSchedule (default) tells the scheduler not to schedule + it. - ScheduleAnyway tells the scheduler to schedule the + resource in any cluster, but giving higher precedence + to topologies that would help reduce the skew. It's an + optional field. + type: string + required: + - topologyKey + type: object + type: array + type: object + resourceSelectors: + description: ResourceSelectors is an array of selectors used to select + cluster scoped resources. The selectors are `ORed`. You can have + 1-100 selectors. + items: + description: ClusterResourceSelector is used to select cluster scoped + resources as the target resources to be placed. If a namespace + is selected, ALL the resources under the namespace are selected + automatically. All the fields are `ANDed`. In other words, a resource + must match all the fields to be selected. + properties: + group: + description: Group name of the cluster-scoped resource. Use + an empty string to select resources under the core API group + (e.g., namespaces). + type: string + kind: + description: 'Kind of the cluster-scoped resource. Note: When + `Kind` is `namespace`, ALL the resources under the selected + namespaces are selected.' + type: string + labelSelector: + description: A label query over all the cluster-scoped resources. + Resources matching the query are selected. Note that namespace-scoped + resources can't be selected even if they match the query. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, NotIn, + Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. + If the operator is In or NotIn, the values array + must be non-empty. If the operator is Exists or + DoesNotExist, the values array must be empty. This + array is replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. + A single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field is + "key", the operator is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + name: + description: Name of the cluster-scoped resource. + type: string + version: + description: Version of the cluster-scoped resource. + type: string + required: + - group + - kind + - version + type: object + maxItems: 100 + minItems: 1 + type: array + required: + - resourceSelectors + type: object + status: + description: The observed status of ClusterResourcePlacement. + properties: + conditions: + description: Conditions is an array of current observed conditions + for ClusterResourcePlacement. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + failedPlacements: + description: FailedResourcePlacements is a list of all the resources + failed to be placed to the given clusters. Note that we only include + 1000 failed resource placements even if there are more than 1000. + items: + description: FailedResourcePlacement contains the failure details + of a failed resource placement. + properties: + clusterName: + description: Name of the member cluster that the resource is + placed to. + type: string + condition: + description: The failed condition status. + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be + when the underlying condition changed. If that is not + known, then using the time when the API field changed + is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if + .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the + current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values + and meanings for this field, and whether the values are + considered a guaranteed API. The value should be a CamelCase + string. This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, + Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across + resources like Available, but because arbitrary conditions + can be useful (see .node.status.conditions), the ability + to deconflict is important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + group: + description: Group is the group name of the selected resource. + type: string + kind: + description: Kind represents the Kind of the selected resources. + type: string + name: + description: Name of the target resource. + type: string + namespace: + description: Namespace is the namespace of the resource. Empty + if the resource is cluster scoped. + type: string + version: + description: Version is the version of the selected resource. + type: string + required: + - clusterName + - condition + - kind + - name + - version + type: object + maxItems: 1000 + type: array + selectedResources: + description: SelectedResources contains a list of resources selected + by ResourceSelectors. + items: + description: ResourceIdentifier identifies one Kubernetes resource. + properties: + group: + description: Group is the group name of the selected resource. + type: string + kind: + description: Kind represents the Kind of the selected resources. + type: string + name: + description: Name of the target resource. + type: string + namespace: + description: Namespace is the namespace of the resource. Empty + if the resource is cluster scoped. + type: string + version: + description: Version is the version of the selected resource. + type: string + required: + - kind + - name + - version + type: object + type: array + targetClusters: + description: TargetClusters contains a list of names of member clusters + selected by PlacementPolicy. Note that the clusters must be both + joined and meeting PlacementPolicy. + items: + type: string + type: array + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/crd/bases/fleet.azure.com_clusterresourcesnapshots.yaml b/config/crd/bases/placement.karavel.io_clusterresourcesnapshots.yaml similarity index 98% rename from config/crd/bases/fleet.azure.com_clusterresourcesnapshots.yaml rename to config/crd/bases/placement.karavel.io_clusterresourcesnapshots.yaml index 9bd402ebe..4e0bbe656 100644 --- a/config/crd/bases/fleet.azure.com_clusterresourcesnapshots.yaml +++ b/config/crd/bases/placement.karavel.io_clusterresourcesnapshots.yaml @@ -4,9 +4,9 @@ kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.11.4 - name: clusterresourcesnapshots.fleet.azure.com + name: clusterresourcesnapshots.placement.karavel.io spec: - group: fleet.azure.com + group: placement.karavel.io names: categories: - fleet-workload @@ -25,7 +25,7 @@ spec: - jsonPath: .metadata.creationTimestamp name: Age type: date - name: v1 + name: v1beta1 schema: openAPIV3Schema: description: "ClusterResourceSnapshot is used to store a snapshot of selected diff --git a/config/crd/bases/placement.karavel.io_internalmemberclusters.yaml b/config/crd/bases/placement.karavel.io_internalmemberclusters.yaml new file mode 100644 index 000000000..615a70b3b --- /dev/null +++ b/config/crd/bases/placement.karavel.io_internalmemberclusters.yaml @@ -0,0 +1,199 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.11.4 + name: internalmemberclusters.placement.karavel.io +spec: + group: placement.karavel.io + names: + categories: + - fleet + kind: InternalMemberCluster + listKind: InternalMemberClusterList + plural: internalmemberclusters + shortNames: + - imc + singular: internalmembercluster + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + description: InternalMemberCluster is used by hub agent to notify the member + agents about the member cluster state changes, and is used by the member + agents to report their status. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: The desired state of InternalMemberCluster. + properties: + heartbeatPeriodSeconds: + default: 60 + description: 'How often (in seconds) for the member cluster to send + a heartbeat to the hub cluster. Default: 60 seconds. Min: 1 second. + Max: 10 minutes.' + format: int32 + maximum: 600 + minimum: 1 + type: integer + state: + description: 'The desired state of the member cluster. Possible values: + Join, Leave.' + type: string + required: + - state + type: object + status: + description: The observed status of InternalMemberCluster. + properties: + agentStatus: + description: AgentStatus is an array of current observed status, each + corresponding to one member agent running in the member cluster. + items: + description: AgentStatus defines the observed status of the member + agent of the given type. + properties: + conditions: + description: Conditions is an array of current observed conditions + for the member agent. + items: + description: "Condition contains details for one aspect of + the current state of this API Resource. --- This struct + is intended for direct use as an array at the field path + .status.conditions. For example, \n type FooStatus struct{ + // Represents the observations of a foo's current state. + // Known .status.conditions.type are: \"Available\", \"Progressing\", + and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields + }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should + be when the underlying condition changed. If that is + not known, then using the time when the API field changed + is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, + if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the + current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier + indicating the reason for the condition's last transition. + Producers of specific condition types may define expected + values and meanings for this field, and whether the + values are considered a guaranteed API. The value should + be a CamelCase string. This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, + Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across + resources like Available, but because arbitrary conditions + can be useful (see .node.status.conditions), the ability + to deconflict is important. The regex it matches is + (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + lastReceivedHeartbeat: + description: Last time we received a heartbeat from the member + agent. + format: date-time + type: string + type: + description: Type of the member agent. + type: string + required: + - type + type: object + type: array + resourceUsage: + description: The current observed resource usage of the member cluster. + It is populated by the member agent. + properties: + allocatable: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Allocatable represents the total resources of all + the nodes on a member cluster that are available for scheduling. + type: object + capacity: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Capacity represents the total resource capacity of + all the nodes on a member cluster. + type: object + observationTime: + description: When the resource usage is observed. + format: date-time + type: string + type: object + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/crd/bases/placement.karavel.io_memberclusters.yaml b/config/crd/bases/placement.karavel.io_memberclusters.yaml new file mode 100644 index 000000000..fa1305ee1 --- /dev/null +++ b/config/crd/bases/placement.karavel.io_memberclusters.yaml @@ -0,0 +1,305 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.11.4 + name: memberclusters.placement.karavel.io +spec: + group: placement.karavel.io + names: + categories: + - fleet + kind: MemberCluster + listKind: MemberClusterList + plural: memberclusters + shortNames: + - mc + singular: membercluster + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="Joined")].status + name: Joined + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + description: MemberCluster is a resource created in the hub cluster to represent + a member cluster within a fleet. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: The desired state of MemberCluster. + properties: + heartbeatPeriodSeconds: + default: 60 + description: 'How often (in seconds) for the member cluster to send + a heartbeat to the hub cluster. Default: 60 seconds. Min: 1 second. + Max: 10 minutes.' + format: int32 + maximum: 600 + minimum: 1 + type: integer + identity: + description: The identity used by the member cluster to access the + hub cluster. The hub agents deployed on the hub cluster will automatically + grant the minimal required permissions to this identity for the + member agents deployed on the member cluster to access the hub cluster. + properties: + apiGroup: + description: APIGroup holds the API group of the referenced subject. + Defaults to "" for ServiceAccount subjects. Defaults to "rbac.authorization.k8s.io" + for User and Group subjects. + type: string + kind: + description: Kind of object being referenced. Values defined by + this API group are "User", "Group", and "ServiceAccount". If + the Authorizer does not recognized the kind value, the Authorizer + should report an error. + type: string + name: + description: Name of the object being referenced. + type: string + namespace: + description: Namespace of the referenced object. If the object + kind is non-namespace, such as "User" or "Group", and this value + is not empty the Authorizer should report an error. + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + state: + description: 'The desired state of the member cluster. Possible values: + Join, Leave.' + type: string + required: + - identity + - state + type: object + status: + description: The observed status of MemberCluster. + properties: + agentStatus: + description: AgentStatus is an array of current observed status, each + corresponding to one member agent running in the member cluster. + items: + description: AgentStatus defines the observed status of the member + agent of the given type. + properties: + conditions: + description: Conditions is an array of current observed conditions + for the member agent. + items: + description: "Condition contains details for one aspect of + the current state of this API Resource. --- This struct + is intended for direct use as an array at the field path + .status.conditions. For example, \n type FooStatus struct{ + // Represents the observations of a foo's current state. + // Known .status.conditions.type are: \"Available\", \"Progressing\", + and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields + }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should + be when the underlying condition changed. If that is + not known, then using the time when the API field changed + is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, + if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the + current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier + indicating the reason for the condition's last transition. + Producers of specific condition types may define expected + values and meanings for this field, and whether the + values are considered a guaranteed API. The value should + be a CamelCase string. This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, + Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across + resources like Available, but because arbitrary conditions + can be useful (see .node.status.conditions), the ability + to deconflict is important. The regex it matches is + (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + lastReceivedHeartbeat: + description: Last time we received a heartbeat from the member + agent. + format: date-time + type: string + type: + description: Type of the member agent. + type: string + required: + - type + type: object + type: array + conditions: + description: Conditions is an array of current observed conditions + for the member cluster. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + resourceUsage: + description: The current observed resource usage of the member cluster. + It is copied from the corresponding InternalMemberCluster object. + properties: + allocatable: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Allocatable represents the total resources of all + the nodes on a member cluster that are available for scheduling. + type: object + capacity: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: Capacity represents the total resource capacity of + all the nodes on a member cluster. + type: object + observationTime: + description: When the resource usage is observed. + format: date-time + type: string + type: object + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} diff --git a/pkg/controllers/clusterresourceplacement/placement_controller.go b/pkg/controllers/clusterresourceplacement/placement_controller.go index b5e765d22..a77f4058d 100644 --- a/pkg/controllers/clusterresourceplacement/placement_controller.go +++ b/pkg/controllers/clusterresourceplacement/placement_controller.go @@ -25,7 +25,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - fleetv1 "go.goms.io/fleet/apis/v1" + fleetv1beta1 "go.goms.io/fleet/apis/placement/v1beta1" fleetv1alpha1 "go.goms.io/fleet/apis/v1alpha1" "go.goms.io/fleet/pkg/metrics" "go.goms.io/fleet/pkg/utils" @@ -345,7 +345,7 @@ func (r *Reconciler) updatePlacementAppliedCondition(placement *fleetv1alpha1.Cl // It creates corresponding clusterPolicySnapshot and clusterResourceSnapshot if needed and updates the status based on // clusterPolicySnapshot status and work status. // If the error type is ErrUnexpectedBehavior, the controller will skip the reconciling. -func (r *Reconciler) handleUpdate(ctx context.Context, crp *fleetv1.ClusterResourcePlacement) (ctrl.Result, error) { +func (r *Reconciler) handleUpdate(ctx context.Context, crp *fleetv1beta1.ClusterResourcePlacement) (ctrl.Result, error) { crpKObj := klog.KObj(crp) policyHash, err := generatePolicyHash(crp.Spec.Policy) if err != nil { @@ -361,9 +361,9 @@ func (r *Reconciler) handleUpdate(ctx context.Context, crp *fleetv1.ClusterResou // mark the last policy snapshot as inactive if it is different from what we have now if latestPolicySnapshot != nil && string(latestPolicySnapshot.Spec.PolicyHash) != policyHash && - latestPolicySnapshot.Labels[fleetv1.IsLatestSnapshotLabel] == strconv.FormatBool(true) { + latestPolicySnapshot.Labels[fleetv1beta1.IsLatestSnapshotLabel] == strconv.FormatBool(true) { // set the latest label to false first to make sure there is only one or none active policy snapshot - latestPolicySnapshot.Labels[fleetv1.IsLatestSnapshotLabel] = strconv.FormatBool(false) + latestPolicySnapshot.Labels[fleetv1beta1.IsLatestSnapshotLabel] = strconv.FormatBool(false) if err := r.Client.Update(ctx, latestPolicySnapshot); err != nil { klog.ErrorS(err, "Failed to set the isLatestSnapshot label to false", "clusterPolicySnapshot", klog.KObj(latestPolicySnapshot)) return ctrl.Result{}, controller.NewAPIServerError(err) @@ -372,16 +372,16 @@ func (r *Reconciler) handleUpdate(ctx context.Context, crp *fleetv1.ClusterResou if latestPolicySnapshot == nil || string(latestPolicySnapshot.Spec.PolicyHash) != policyHash { // create a new policy snapshot latestPolicySnapshotIndex++ - latestPolicySnapshot = &fleetv1.ClusterPolicySnapshot{ + latestPolicySnapshot = &fleetv1beta1.ClusterPolicySnapshot{ ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf(fleetv1.PolicySnapshotNameFmt, crp.Name, latestPolicySnapshotIndex), + Name: fmt.Sprintf(fleetv1beta1.PolicySnapshotNameFmt, crp.Name, latestPolicySnapshotIndex), Labels: map[string]string{ - fleetv1.CRPTrackingLabel: crp.Name, - fleetv1.IsLatestSnapshotLabel: strconv.FormatBool(true), - fleetv1.PolicyIndexLabel: strconv.Itoa(latestPolicySnapshotIndex), + fleetv1beta1.CRPTrackingLabel: crp.Name, + fleetv1beta1.IsLatestSnapshotLabel: strconv.FormatBool(true), + fleetv1beta1.PolicyIndexLabel: strconv.Itoa(latestPolicySnapshotIndex), }, }, - Spec: fleetv1.PolicySnapshotSpec{ + Spec: fleetv1beta1.PolicySnapshotSpec{ Policy: crp.Spec.Policy, PolicyHash: []byte(policyHash), }, @@ -395,14 +395,14 @@ func (r *Reconciler) handleUpdate(ctx context.Context, crp *fleetv1.ClusterResou klog.ErrorS(err, "Failed to create new clusterPolicySnapshot", "clusterPolicySnapshot", klog.KObj(latestPolicySnapshot)) return ctrl.Result{}, controller.NewAPIServerError(err) } - } else if latestPolicySnapshot.Labels[fleetv1.IsLatestSnapshotLabel] != strconv.FormatBool(true) { + } else if latestPolicySnapshot.Labels[fleetv1beta1.IsLatestSnapshotLabel] != strconv.FormatBool(true) { // When latestPolicySnapshot.Spec.PolicyHash == policyHash, // It could happen when the controller just sets the latest label to false for the old snapshot, and fails to // create a new policy snapshot. // And then the customers revert back their policy to the old one again. // In this case, the "latest" snapshot without isLatest label has the same policy hash as the current policy. - latestPolicySnapshot.Labels[fleetv1.IsLatestSnapshotLabel] = strconv.FormatBool(true) + latestPolicySnapshot.Labels[fleetv1beta1.IsLatestSnapshotLabel] = strconv.FormatBool(true) if err := r.Client.Update(ctx, latestPolicySnapshot); err != nil { klog.ErrorS(err, "Failed to set the isLatestSnapshot label to true", "clusterPolicySnapshot", klog.KObj(latestPolicySnapshot)) return ctrl.Result{}, controller.NewAPIServerError(err) @@ -422,11 +422,11 @@ func (r *Reconciler) handleUpdate(ctx context.Context, crp *fleetv1.ClusterResou // Return error when 1) cannot list the snapshots 2) there are more than one active policy snapshots 3) snapshot has the // invalid label value. // 2 & 3 should never happen. -func (r *Reconciler) lookupLatestClusterPolicySnapshot(ctx context.Context, crp *fleetv1.ClusterResourcePlacement) (*fleetv1.ClusterPolicySnapshot, int, error) { - snapshotList := &fleetv1.ClusterPolicySnapshotList{} +func (r *Reconciler) lookupLatestClusterPolicySnapshot(ctx context.Context, crp *fleetv1beta1.ClusterResourcePlacement) (*fleetv1beta1.ClusterPolicySnapshot, int, error) { + snapshotList := &fleetv1beta1.ClusterPolicySnapshotList{} latestSnapshotLabelMatcher := client.MatchingLabels{ - fleetv1.CRPTrackingLabel: crp.Name, - fleetv1.IsLatestSnapshotLabel: strconv.FormatBool(true), + fleetv1beta1.CRPTrackingLabel: crp.Name, + fleetv1beta1.IsLatestSnapshotLabel: strconv.FormatBool(true), } crpKObj := klog.KObj(crp) if err := r.Client.List(ctx, snapshotList, latestSnapshotLabelMatcher); err != nil { @@ -446,7 +446,7 @@ func (r *Reconciler) lookupLatestClusterPolicySnapshot(ctx context.Context, crp return nil, -1, controller.NewUnexpectedBehaviorError(err) } // When there are no active snapshots, find the one who has the largest policy index. - if err := r.Client.List(ctx, snapshotList, client.MatchingLabels{fleetv1.CRPTrackingLabel: crp.Name}); err != nil { + if err := r.Client.List(ctx, snapshotList, client.MatchingLabels{fleetv1beta1.CRPTrackingLabel: crp.Name}); err != nil { klog.ErrorS(err, "Failed to list all clusterPolicySnapshots", "clusterResourcePlacement", crpKObj) return nil, -1, controller.NewAPIServerError(err) } @@ -469,8 +469,8 @@ func (r *Reconciler) lookupLatestClusterPolicySnapshot(ctx context.Context, crp return &snapshotList.Items[index], lastPolicyIndex, nil } -func parsePolicyIndexFromLabel(s *fleetv1.ClusterPolicySnapshot) (int, error) { - indexLabel := s.Labels[fleetv1.PolicyIndexLabel] +func parsePolicyIndexFromLabel(s *fleetv1beta1.ClusterPolicySnapshot) (int, error) { + indexLabel := s.Labels[fleetv1beta1.PolicyIndexLabel] v, err := strconv.Atoi(indexLabel) if err != nil { klog.ErrorS(err, "Failed to parse the policy index label", "clusterPolicySnapshot", klog.KObj(s), "policyIndexLabel", indexLabel) @@ -480,7 +480,7 @@ func parsePolicyIndexFromLabel(s *fleetv1.ClusterPolicySnapshot) (int, error) { return v, nil } -func generatePolicyHash(policy *fleetv1.PlacementPolicy) (string, error) { +func generatePolicyHash(policy *fleetv1beta1.PlacementPolicy) (string, error) { jsonBytes, err := json.Marshal(policy) if err != nil { return "", err diff --git a/pkg/controllers/clusterresourceplacement/placement_controller_test.go b/pkg/controllers/clusterresourceplacement/placement_controller_test.go index c2ab0622e..554efcc40 100644 --- a/pkg/controllers/clusterresourceplacement/placement_controller_test.go +++ b/pkg/controllers/clusterresourceplacement/placement_controller_test.go @@ -17,31 +17,34 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/fake" - fleetv1 "go.goms.io/fleet/apis/v1" + fleetv1beta1 "go.goms.io/fleet/apis/placement/v1beta1" "go.goms.io/fleet/pkg/utils/controller" ) const ( - testName = "my-crp" - fleetAPIVersion = "fleet.azure.com/v1" + testName = "my-crp" +) + +var ( + fleetAPIVersion = fleetv1beta1.GroupVersion.String() ) func serviceScheme(t *testing.T) *runtime.Scheme { scheme := runtime.NewScheme() - if err := fleetv1.AddToScheme(scheme); err != nil { + if err := fleetv1beta1.AddToScheme(scheme); err != nil { t.Fatalf("failed to add scheme: %v", err) } return scheme } -func placementPolicyForTest() *fleetv1.PlacementPolicy { - return &fleetv1.PlacementPolicy{ - PlacementType: fleetv1.PickNPlacementType, +func placementPolicyForTest() *fleetv1beta1.PlacementPolicy { + return &fleetv1beta1.PlacementPolicy{ + PlacementType: fleetv1beta1.PickNPlacementType, NumberOfClusters: pointer.Int32(3), - Affinity: &fleetv1.Affinity{ - ClusterAffinity: &fleetv1.ClusterAffinity{ - RequiredDuringSchedulingIgnoredDuringExecution: &fleetv1.ClusterSelector{ - ClusterSelectorTerms: []fleetv1.ClusterSelectorTerm{ + Affinity: &fleetv1beta1.Affinity{ + ClusterAffinity: &fleetv1beta1.ClusterAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &fleetv1beta1.ClusterSelector{ + ClusterSelectorTerms: []fleetv1beta1.ClusterSelectorTerm{ { LabelSelector: metav1.LabelSelector{ MatchLabels: map[string]string{ @@ -56,12 +59,12 @@ func placementPolicyForTest() *fleetv1.PlacementPolicy { } } -func clusterResourcePlacementForTest() *fleetv1.ClusterResourcePlacement { - return &fleetv1.ClusterResourcePlacement{ +func clusterResourcePlacementForTest() *fleetv1beta1.ClusterResourcePlacement { + return &fleetv1beta1.ClusterResourcePlacement{ ObjectMeta: metav1.ObjectMeta{ Name: testName, }, - Spec: fleetv1.ClusterResourcePlacementSpec{ + Spec: fleetv1beta1.ClusterResourcePlacementSpec{ Policy: placementPolicyForTest(), }, } @@ -80,42 +83,42 @@ func TestHandleUpdate(t *testing.T) { unspecifiedPolicyHash := []byte(fmt.Sprintf("%x", sha256.Sum256(jsonBytes))) tests := []struct { name string - policySnapshots []fleetv1.ClusterPolicySnapshot - wantPolicySnapshots []fleetv1.ClusterPolicySnapshot + policySnapshots []fleetv1beta1.ClusterPolicySnapshot + wantPolicySnapshots []fleetv1beta1.ClusterPolicySnapshot }{ { name: "new clusterResourcePolicy and no existing policy snapshots owned by my-crp", - policySnapshots: []fleetv1.ClusterPolicySnapshot{ + policySnapshots: []fleetv1beta1.ClusterPolicySnapshot{ { ObjectMeta: metav1.ObjectMeta{ Name: "another-crp-1", Labels: map[string]string{ - fleetv1.PolicyIndexLabel: "1", - fleetv1.IsLatestSnapshotLabel: "true", - fleetv1.CRPTrackingLabel: "another-crp", + fleetv1beta1.PolicyIndexLabel: "1", + fleetv1beta1.IsLatestSnapshotLabel: "true", + fleetv1beta1.CRPTrackingLabel: "another-crp", }, }, }, }, - wantPolicySnapshots: []fleetv1.ClusterPolicySnapshot{ + wantPolicySnapshots: []fleetv1beta1.ClusterPolicySnapshot{ { ObjectMeta: metav1.ObjectMeta{ Name: "another-crp-1", Labels: map[string]string{ - fleetv1.PolicyIndexLabel: "1", - fleetv1.IsLatestSnapshotLabel: "true", - fleetv1.CRPTrackingLabel: "another-crp", + fleetv1beta1.PolicyIndexLabel: "1", + fleetv1beta1.IsLatestSnapshotLabel: "true", + fleetv1beta1.CRPTrackingLabel: "another-crp", }, }, }, // new policy snapshot owned by the my-crp { ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf(fleetv1.PolicySnapshotNameFmt, testName, 0), + Name: fmt.Sprintf(fleetv1beta1.PolicySnapshotNameFmt, testName, 0), Labels: map[string]string{ - fleetv1.PolicyIndexLabel: "0", - fleetv1.IsLatestSnapshotLabel: "true", - fleetv1.CRPTrackingLabel: testName, + fleetv1beta1.PolicyIndexLabel: "0", + fleetv1beta1.IsLatestSnapshotLabel: "true", + fleetv1beta1.CRPTrackingLabel: testName, }, OwnerReferences: []metav1.OwnerReference{ { @@ -127,7 +130,7 @@ func TestHandleUpdate(t *testing.T) { }, }, }, - Spec: fleetv1.PolicySnapshotSpec{ + Spec: fleetv1beta1.PolicySnapshotSpec{ Policy: placementPolicyForTest(), PolicyHash: policyHash, }, @@ -136,14 +139,14 @@ func TestHandleUpdate(t *testing.T) { }, { name: "crp policy has no change", - policySnapshots: []fleetv1.ClusterPolicySnapshot{ + policySnapshots: []fleetv1beta1.ClusterPolicySnapshot{ { ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf(fleetv1.PolicySnapshotNameFmt, testName, 0), + Name: fmt.Sprintf(fleetv1beta1.PolicySnapshotNameFmt, testName, 0), Labels: map[string]string{ - fleetv1.PolicyIndexLabel: "0", - fleetv1.IsLatestSnapshotLabel: "true", - fleetv1.CRPTrackingLabel: testName, + fleetv1beta1.PolicyIndexLabel: "0", + fleetv1beta1.IsLatestSnapshotLabel: "true", + fleetv1beta1.CRPTrackingLabel: testName, }, OwnerReferences: []metav1.OwnerReference{ { @@ -155,20 +158,20 @@ func TestHandleUpdate(t *testing.T) { }, }, }, - Spec: fleetv1.PolicySnapshotSpec{ + Spec: fleetv1beta1.PolicySnapshotSpec{ Policy: placementPolicyForTest(), PolicyHash: policyHash, }, }, }, - wantPolicySnapshots: []fleetv1.ClusterPolicySnapshot{ + wantPolicySnapshots: []fleetv1beta1.ClusterPolicySnapshot{ { ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf(fleetv1.PolicySnapshotNameFmt, testName, 0), + Name: fmt.Sprintf(fleetv1beta1.PolicySnapshotNameFmt, testName, 0), Labels: map[string]string{ - fleetv1.PolicyIndexLabel: "0", - fleetv1.IsLatestSnapshotLabel: "true", - fleetv1.CRPTrackingLabel: testName, + fleetv1beta1.PolicyIndexLabel: "0", + fleetv1beta1.IsLatestSnapshotLabel: "true", + fleetv1beta1.CRPTrackingLabel: testName, }, OwnerReferences: []metav1.OwnerReference{ { @@ -180,7 +183,7 @@ func TestHandleUpdate(t *testing.T) { }, }, }, - Spec: fleetv1.PolicySnapshotSpec{ + Spec: fleetv1beta1.PolicySnapshotSpec{ Policy: placementPolicyForTest(), PolicyHash: policyHash, }, @@ -191,14 +194,14 @@ func TestHandleUpdate(t *testing.T) { name: "crp policy has changed and there is no active snapshot", // It happens when last reconcile loop fails after setting the latest label to false and // before creating a new policy snapshot. - policySnapshots: []fleetv1.ClusterPolicySnapshot{ + policySnapshots: []fleetv1beta1.ClusterPolicySnapshot{ { ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf(fleetv1.PolicySnapshotNameFmt, testName, 0), + Name: fmt.Sprintf(fleetv1beta1.PolicySnapshotNameFmt, testName, 0), Labels: map[string]string{ - fleetv1.PolicyIndexLabel: "0", - fleetv1.IsLatestSnapshotLabel: "false", - fleetv1.CRPTrackingLabel: testName, + fleetv1beta1.PolicyIndexLabel: "0", + fleetv1beta1.IsLatestSnapshotLabel: "false", + fleetv1beta1.CRPTrackingLabel: testName, }, OwnerReferences: []metav1.OwnerReference{ { @@ -210,18 +213,18 @@ func TestHandleUpdate(t *testing.T) { }, }, }, - Spec: fleetv1.PolicySnapshotSpec{ + Spec: fleetv1beta1.PolicySnapshotSpec{ // Policy is not specified. PolicyHash: unspecifiedPolicyHash, }, }, { ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf(fleetv1.PolicySnapshotNameFmt, testName, 3), + Name: fmt.Sprintf(fleetv1beta1.PolicySnapshotNameFmt, testName, 3), Labels: map[string]string{ - fleetv1.PolicyIndexLabel: "3", - fleetv1.IsLatestSnapshotLabel: "false", - fleetv1.CRPTrackingLabel: testName, + fleetv1beta1.PolicyIndexLabel: "3", + fleetv1beta1.IsLatestSnapshotLabel: "false", + fleetv1beta1.CRPTrackingLabel: testName, }, OwnerReferences: []metav1.OwnerReference{ { @@ -233,20 +236,20 @@ func TestHandleUpdate(t *testing.T) { }, }, }, - Spec: fleetv1.PolicySnapshotSpec{ + Spec: fleetv1beta1.PolicySnapshotSpec{ // Policy is not specified. PolicyHash: unspecifiedPolicyHash, }, }, }, - wantPolicySnapshots: []fleetv1.ClusterPolicySnapshot{ + wantPolicySnapshots: []fleetv1beta1.ClusterPolicySnapshot{ { ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf(fleetv1.PolicySnapshotNameFmt, testName, 0), + Name: fmt.Sprintf(fleetv1beta1.PolicySnapshotNameFmt, testName, 0), Labels: map[string]string{ - fleetv1.PolicyIndexLabel: "0", - fleetv1.IsLatestSnapshotLabel: "false", - fleetv1.CRPTrackingLabel: testName, + fleetv1beta1.PolicyIndexLabel: "0", + fleetv1beta1.IsLatestSnapshotLabel: "false", + fleetv1beta1.CRPTrackingLabel: testName, }, OwnerReferences: []metav1.OwnerReference{ { @@ -258,18 +261,18 @@ func TestHandleUpdate(t *testing.T) { }, }, }, - Spec: fleetv1.PolicySnapshotSpec{ + Spec: fleetv1beta1.PolicySnapshotSpec{ // Policy is not specified. PolicyHash: unspecifiedPolicyHash, }, }, { ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf(fleetv1.PolicySnapshotNameFmt, testName, 3), + Name: fmt.Sprintf(fleetv1beta1.PolicySnapshotNameFmt, testName, 3), Labels: map[string]string{ - fleetv1.PolicyIndexLabel: "3", - fleetv1.IsLatestSnapshotLabel: "false", - fleetv1.CRPTrackingLabel: testName, + fleetv1beta1.PolicyIndexLabel: "3", + fleetv1beta1.IsLatestSnapshotLabel: "false", + fleetv1beta1.CRPTrackingLabel: testName, }, OwnerReferences: []metav1.OwnerReference{ { @@ -281,18 +284,18 @@ func TestHandleUpdate(t *testing.T) { }, }, }, - Spec: fleetv1.PolicySnapshotSpec{ + Spec: fleetv1beta1.PolicySnapshotSpec{ // Policy is not specified. PolicyHash: unspecifiedPolicyHash, }, }, { ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf(fleetv1.PolicySnapshotNameFmt, testName, 4), + Name: fmt.Sprintf(fleetv1beta1.PolicySnapshotNameFmt, testName, 4), Labels: map[string]string{ - fleetv1.PolicyIndexLabel: "4", - fleetv1.IsLatestSnapshotLabel: "true", - fleetv1.CRPTrackingLabel: testName, + fleetv1beta1.PolicyIndexLabel: "4", + fleetv1beta1.IsLatestSnapshotLabel: "true", + fleetv1beta1.CRPTrackingLabel: testName, }, OwnerReferences: []metav1.OwnerReference{ { @@ -304,7 +307,7 @@ func TestHandleUpdate(t *testing.T) { }, }, }, - Spec: fleetv1.PolicySnapshotSpec{ + Spec: fleetv1beta1.PolicySnapshotSpec{ Policy: placementPolicyForTest(), PolicyHash: policyHash, }, @@ -313,14 +316,14 @@ func TestHandleUpdate(t *testing.T) { }, { name: "crp policy has changed and there is an active snapshot", - policySnapshots: []fleetv1.ClusterPolicySnapshot{ + policySnapshots: []fleetv1beta1.ClusterPolicySnapshot{ { ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf(fleetv1.PolicySnapshotNameFmt, testName, 0), + Name: fmt.Sprintf(fleetv1beta1.PolicySnapshotNameFmt, testName, 0), Labels: map[string]string{ - fleetv1.PolicyIndexLabel: "0", - fleetv1.IsLatestSnapshotLabel: "true", - fleetv1.CRPTrackingLabel: testName, + fleetv1beta1.PolicyIndexLabel: "0", + fleetv1beta1.IsLatestSnapshotLabel: "true", + fleetv1beta1.CRPTrackingLabel: testName, }, OwnerReferences: []metav1.OwnerReference{ { @@ -332,20 +335,20 @@ func TestHandleUpdate(t *testing.T) { }, }, }, - Spec: fleetv1.PolicySnapshotSpec{ + Spec: fleetv1beta1.PolicySnapshotSpec{ // Policy is not specified. PolicyHash: unspecifiedPolicyHash, }, }, }, - wantPolicySnapshots: []fleetv1.ClusterPolicySnapshot{ + wantPolicySnapshots: []fleetv1beta1.ClusterPolicySnapshot{ { ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf(fleetv1.PolicySnapshotNameFmt, testName, 0), + Name: fmt.Sprintf(fleetv1beta1.PolicySnapshotNameFmt, testName, 0), Labels: map[string]string{ - fleetv1.PolicyIndexLabel: "0", - fleetv1.IsLatestSnapshotLabel: "false", - fleetv1.CRPTrackingLabel: testName, + fleetv1beta1.PolicyIndexLabel: "0", + fleetv1beta1.IsLatestSnapshotLabel: "false", + fleetv1beta1.CRPTrackingLabel: testName, }, OwnerReferences: []metav1.OwnerReference{ { @@ -357,18 +360,18 @@ func TestHandleUpdate(t *testing.T) { }, }, }, - Spec: fleetv1.PolicySnapshotSpec{ + Spec: fleetv1beta1.PolicySnapshotSpec{ // Policy is not specified. PolicyHash: unspecifiedPolicyHash, }, }, { ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf(fleetv1.PolicySnapshotNameFmt, testName, 1), + Name: fmt.Sprintf(fleetv1beta1.PolicySnapshotNameFmt, testName, 1), Labels: map[string]string{ - fleetv1.PolicyIndexLabel: "1", - fleetv1.IsLatestSnapshotLabel: "true", - fleetv1.CRPTrackingLabel: testName, + fleetv1beta1.PolicyIndexLabel: "1", + fleetv1beta1.IsLatestSnapshotLabel: "true", + fleetv1beta1.CRPTrackingLabel: testName, }, OwnerReferences: []metav1.OwnerReference{ { @@ -380,7 +383,7 @@ func TestHandleUpdate(t *testing.T) { }, }, }, - Spec: fleetv1.PolicySnapshotSpec{ + Spec: fleetv1beta1.PolicySnapshotSpec{ Policy: placementPolicyForTest(), PolicyHash: policyHash, }, @@ -389,14 +392,14 @@ func TestHandleUpdate(t *testing.T) { }, { name: "crp policy has been changed and reverted back and there is no active snapshot", - policySnapshots: []fleetv1.ClusterPolicySnapshot{ + policySnapshots: []fleetv1beta1.ClusterPolicySnapshot{ { ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf(fleetv1.PolicySnapshotNameFmt, testName, 0), + Name: fmt.Sprintf(fleetv1beta1.PolicySnapshotNameFmt, testName, 0), Labels: map[string]string{ - fleetv1.PolicyIndexLabel: "0", - fleetv1.IsLatestSnapshotLabel: "false", - fleetv1.CRPTrackingLabel: testName, + fleetv1beta1.PolicyIndexLabel: "0", + fleetv1beta1.IsLatestSnapshotLabel: "false", + fleetv1beta1.CRPTrackingLabel: testName, }, OwnerReferences: []metav1.OwnerReference{ { @@ -408,17 +411,17 @@ func TestHandleUpdate(t *testing.T) { }, }, }, - Spec: fleetv1.PolicySnapshotSpec{ + Spec: fleetv1beta1.PolicySnapshotSpec{ // Policy is not specified. PolicyHash: unspecifiedPolicyHash, }, }, { ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf(fleetv1.PolicySnapshotNameFmt, testName, 1), + Name: fmt.Sprintf(fleetv1beta1.PolicySnapshotNameFmt, testName, 1), Labels: map[string]string{ - fleetv1.PolicyIndexLabel: "1", - fleetv1.CRPTrackingLabel: testName, + fleetv1beta1.PolicyIndexLabel: "1", + fleetv1beta1.CRPTrackingLabel: testName, }, OwnerReferences: []metav1.OwnerReference{ { @@ -430,20 +433,20 @@ func TestHandleUpdate(t *testing.T) { }, }, }, - Spec: fleetv1.PolicySnapshotSpec{ + Spec: fleetv1beta1.PolicySnapshotSpec{ Policy: placementPolicyForTest(), PolicyHash: policyHash, }, }, }, - wantPolicySnapshots: []fleetv1.ClusterPolicySnapshot{ + wantPolicySnapshots: []fleetv1beta1.ClusterPolicySnapshot{ { ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf(fleetv1.PolicySnapshotNameFmt, testName, 0), + Name: fmt.Sprintf(fleetv1beta1.PolicySnapshotNameFmt, testName, 0), Labels: map[string]string{ - fleetv1.PolicyIndexLabel: "0", - fleetv1.IsLatestSnapshotLabel: "false", - fleetv1.CRPTrackingLabel: testName, + fleetv1beta1.PolicyIndexLabel: "0", + fleetv1beta1.IsLatestSnapshotLabel: "false", + fleetv1beta1.CRPTrackingLabel: testName, }, OwnerReferences: []metav1.OwnerReference{ { @@ -455,18 +458,18 @@ func TestHandleUpdate(t *testing.T) { }, }, }, - Spec: fleetv1.PolicySnapshotSpec{ + Spec: fleetv1beta1.PolicySnapshotSpec{ // Policy is not specified. PolicyHash: unspecifiedPolicyHash, }, }, { ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf(fleetv1.PolicySnapshotNameFmt, testName, 1), + Name: fmt.Sprintf(fleetv1beta1.PolicySnapshotNameFmt, testName, 1), Labels: map[string]string{ - fleetv1.PolicyIndexLabel: "1", - fleetv1.IsLatestSnapshotLabel: "true", - fleetv1.CRPTrackingLabel: testName, + fleetv1beta1.PolicyIndexLabel: "1", + fleetv1beta1.IsLatestSnapshotLabel: "true", + fleetv1beta1.CRPTrackingLabel: testName, }, OwnerReferences: []metav1.OwnerReference{ { @@ -478,7 +481,7 @@ func TestHandleUpdate(t *testing.T) { }, }, }, - Spec: fleetv1.PolicySnapshotSpec{ + Spec: fleetv1beta1.PolicySnapshotSpec{ Policy: placementPolicyForTest(), PolicyHash: policyHash, }, @@ -508,7 +511,7 @@ func TestHandleUpdate(t *testing.T) { if !cmp.Equal(got, want) { t.Errorf("handleUpdate() = %+v, want %+v", got, want) } - clusterPolicySnapshotList := &fleetv1.ClusterPolicySnapshotList{} + clusterPolicySnapshotList := &fleetv1beta1.ClusterPolicySnapshotList{} if err := fakeClient.List(ctx, clusterPolicySnapshotList); err != nil { t.Fatalf("clusterPolicySnapshot List() got error %v, want no error", err) } @@ -525,18 +528,18 @@ func TestHandleUpdate(t *testing.T) { func TestHandleUpdate_failure(t *testing.T) { tests := []struct { name string - policySnapshots []fleetv1.ClusterPolicySnapshot + policySnapshots []fleetv1beta1.ClusterPolicySnapshot }{ { // Should never hit this case unless there is a bug in the controller or customers manually modify the clusterPolicySnapshot. name: "existing active policy snapshot does not have policyIndex label", - policySnapshots: []fleetv1.ClusterPolicySnapshot{ + policySnapshots: []fleetv1beta1.ClusterPolicySnapshot{ { ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf(fleetv1.PolicySnapshotNameFmt, testName, 0), + Name: fmt.Sprintf(fleetv1beta1.PolicySnapshotNameFmt, testName, 0), Labels: map[string]string{ - fleetv1.IsLatestSnapshotLabel: "true", - fleetv1.CRPTrackingLabel: testName, + fleetv1beta1.IsLatestSnapshotLabel: "true", + fleetv1beta1.CRPTrackingLabel: testName, }, OwnerReferences: []metav1.OwnerReference{ { @@ -552,14 +555,14 @@ func TestHandleUpdate_failure(t *testing.T) { { // Should never hit this case unless there is a bug in the controller or customers manually modify the clusterPolicySnapshot. name: "existing active policy snapshot has an invalid policyIndex label", - policySnapshots: []fleetv1.ClusterPolicySnapshot{ + policySnapshots: []fleetv1beta1.ClusterPolicySnapshot{ { ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf(fleetv1.PolicySnapshotNameFmt, testName, 0), + Name: fmt.Sprintf(fleetv1beta1.PolicySnapshotNameFmt, testName, 0), Labels: map[string]string{ - fleetv1.PolicyIndexLabel: "0bc", - fleetv1.IsLatestSnapshotLabel: "true", - fleetv1.CRPTrackingLabel: testName, + fleetv1beta1.PolicyIndexLabel: "0bc", + fleetv1beta1.IsLatestSnapshotLabel: "true", + fleetv1beta1.CRPTrackingLabel: testName, }, OwnerReferences: []metav1.OwnerReference{ { @@ -575,13 +578,13 @@ func TestHandleUpdate_failure(t *testing.T) { { // Should never hit this case unless there is a bug in the controller or customers manually modify the clusterPolicySnapshot. name: "no active policy snapshot exists and policySnapshot with invalid policyIndex label", - policySnapshots: []fleetv1.ClusterPolicySnapshot{ + policySnapshots: []fleetv1beta1.ClusterPolicySnapshot{ { ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf(fleetv1.PolicySnapshotNameFmt, testName, 0), + Name: fmt.Sprintf(fleetv1beta1.PolicySnapshotNameFmt, testName, 0), Labels: map[string]string{ - fleetv1.PolicyIndexLabel: "abc", - fleetv1.CRPTrackingLabel: testName, + fleetv1beta1.PolicyIndexLabel: "abc", + fleetv1beta1.CRPTrackingLabel: testName, }, OwnerReferences: []metav1.OwnerReference{ { @@ -597,14 +600,14 @@ func TestHandleUpdate_failure(t *testing.T) { { // Should never hit this case unless there is a bug in the controller or customers manually modify the clusterPolicySnapshot. name: "multiple active policy snapshot exist", - policySnapshots: []fleetv1.ClusterPolicySnapshot{ + policySnapshots: []fleetv1beta1.ClusterPolicySnapshot{ { ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf(fleetv1.PolicySnapshotNameFmt, testName, 0), + Name: fmt.Sprintf(fleetv1beta1.PolicySnapshotNameFmt, testName, 0), Labels: map[string]string{ - fleetv1.PolicyIndexLabel: "0", - fleetv1.CRPTrackingLabel: testName, - fleetv1.IsLatestSnapshotLabel: "true", + fleetv1beta1.PolicyIndexLabel: "0", + fleetv1beta1.CRPTrackingLabel: testName, + fleetv1beta1.IsLatestSnapshotLabel: "true", }, OwnerReferences: []metav1.OwnerReference{ { @@ -617,11 +620,11 @@ func TestHandleUpdate_failure(t *testing.T) { }, { ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf(fleetv1.PolicySnapshotNameFmt, testName, 1), + Name: fmt.Sprintf(fleetv1beta1.PolicySnapshotNameFmt, testName, 1), Labels: map[string]string{ - fleetv1.PolicyIndexLabel: "1", - fleetv1.CRPTrackingLabel: testName, - fleetv1.IsLatestSnapshotLabel: "true", + fleetv1beta1.PolicyIndexLabel: "1", + fleetv1beta1.CRPTrackingLabel: testName, + fleetv1beta1.IsLatestSnapshotLabel: "true", }, OwnerReferences: []metav1.OwnerReference{ { diff --git a/pkg/scheduler/framework/interface.go b/pkg/scheduler/framework/interface.go index fc6255661..882906a0c 100644 --- a/pkg/scheduler/framework/interface.go +++ b/pkg/scheduler/framework/interface.go @@ -8,7 +8,7 @@ package framework import ( "context" - fleetv1 "go.goms.io/fleet/apis/v1" + fleetv1beta1 "go.goms.io/fleet/apis/placement/v1beta1" ) // Plugin is the interface which all scheduler plugins should implement. @@ -27,7 +27,7 @@ type PostBatchPlugin interface { // * A Success status with a new batch size; or // * A Skip status, if no changes in batch size is needed; or // * An InternalError status, if an expected error has occurred - PostBatch(ctx context.Context, state CycleStatePluginReadWriter, policy *fleetv1.ClusterPolicySnapshot) (size int, status *Status) + PostBatch(ctx context.Context, state CycleStatePluginReadWriter, policy *fleetv1beta1.ClusterPolicySnapshot) (size int, status *Status) } // PreFilterPlugin is the interface which all plugins that would like to run at the PreFilter @@ -44,7 +44,7 @@ type PreFilterPlugin interface { // * A Success status, if the plugin should run at the Filter stage; or // * A Skip status, if the plugin should be skipped at the Filter stage; or // * An InternalError status, if an expected error has occurred - PreFilter(ctx context.Context, state CycleStatePluginReadWriter, policy *fleetv1.ClusterPolicySnapshot) (status *Status) + PreFilter(ctx context.Context, state CycleStatePluginReadWriter, policy *fleetv1beta1.ClusterPolicySnapshot) (status *Status) } // FilterPlugin is the interface which all plugins that would like to run at the Filter @@ -57,7 +57,7 @@ type FilterPlugin interface { // * A Success status, if the placement can be bound to the cluster; or // * A ClusterUnschedulable status, if the placement cannot be bound to the cluster; or // * An InternalError status, if an expected error has occurred - Filter(ctx context.Context, state CycleStatePluginReadWriter, policy *fleetv1.ClusterPolicySnapshot, cluster *fleetv1.MemberCluster) (status *Status) + Filter(ctx context.Context, state CycleStatePluginReadWriter, policy *fleetv1beta1.ClusterPolicySnapshot, cluster *fleetv1beta1.MemberCluster) (status *Status) } // PreScorePlugin is the interface which all plugins that would like to run at the PreScore @@ -74,7 +74,7 @@ type PreScorePlugin interface { // * A Success status, if the plugin should run at the Score stage; or // * A Skip status, if the plugin should be skipped at the Score stage; or // * An InternalError status, if an expected error has occurred - PreScore(ctx context.Context, state CycleStatePluginReadWriter, policy *fleetv1.ClusterPolicySnapshot) (status *Status) + PreScore(ctx context.Context, state CycleStatePluginReadWriter, policy *fleetv1beta1.ClusterPolicySnapshot) (status *Status) } // ScorePlugin is the interface which all plugins that would like to run at the Score @@ -86,5 +86,5 @@ type ScorePlugin interface { // A plugin which registers at this extension point must return one of the follows: // * A Success status, with the score for the cluster; or // * An InternalError status, if an expected error has occurred - Score(ctx context.Context, state CycleStatePluginReadWriter, policy *fleetv1.ClusterPolicySnapshot, cluster *fleetv1.MemberCluster) (score *ClusterScore, status *Status) + Score(ctx context.Context, state CycleStatePluginReadWriter, policy *fleetv1beta1.ClusterPolicySnapshot, cluster *fleetv1beta1.MemberCluster) (score *ClusterScore, status *Status) } diff --git a/pkg/scheduler/framework/profile_test.go b/pkg/scheduler/framework/profile_test.go index 614e47c50..2e39c69ce 100644 --- a/pkg/scheduler/framework/profile_test.go +++ b/pkg/scheduler/framework/profile_test.go @@ -10,7 +10,7 @@ import ( "testing" "github.com/google/go-cmp/cmp" - fleetv1 "go.goms.io/fleet/apis/v1" + fleetv1beta1 "go.goms.io/fleet/apis/placement/v1beta1" ) const ( @@ -27,27 +27,27 @@ func (p *DummyAllPurposePlugin) Name() string { } // PostBatch implements the PostBatch interface for the dummy plugin. -func (p *DummyAllPurposePlugin) PostBatch(ctx context.Context, state CycleStatePluginReadWriter, policy *fleetv1.ClusterPolicySnapshot) (size int, status *Status) { //nolint:revive +func (p *DummyAllPurposePlugin) PostBatch(ctx context.Context, state CycleStatePluginReadWriter, policy *fleetv1beta1.ClusterPolicySnapshot) (size int, status *Status) { //nolint:revive return 1, nil } // PreFilter implements the PreFilter interface for the dummy plugin. -func (p *DummyAllPurposePlugin) PreFilter(ctx context.Context, state CycleStatePluginReadWriter, policy *fleetv1.ClusterPolicySnapshot) (status *Status) { //nolint:revive +func (p *DummyAllPurposePlugin) PreFilter(ctx context.Context, state CycleStatePluginReadWriter, policy *fleetv1beta1.ClusterPolicySnapshot) (status *Status) { //nolint:revive return nil } // Filter implements the Filter interface for the dummy plugin. -func (p *DummyAllPurposePlugin) Filter(ctx context.Context, state CycleStatePluginReadWriter, policy *fleetv1.ClusterPolicySnapshot, cluster *fleetv1.MemberCluster) (status *Status) { //nolint:revive +func (p *DummyAllPurposePlugin) Filter(ctx context.Context, state CycleStatePluginReadWriter, policy *fleetv1beta1.ClusterPolicySnapshot, cluster *fleetv1beta1.MemberCluster) (status *Status) { //nolint:revive return nil } // PreScore implements the PreScore interface for the dummy plugin. -func (p *DummyAllPurposePlugin) PreScore(ctx context.Context, state CycleStatePluginReadWriter, policy *fleetv1.ClusterPolicySnapshot) (status *Status) { //nolint:revive +func (p *DummyAllPurposePlugin) PreScore(ctx context.Context, state CycleStatePluginReadWriter, policy *fleetv1beta1.ClusterPolicySnapshot) (status *Status) { //nolint:revive return nil } // Score implements the Score interface for the dummy plugin. -func (p *DummyAllPurposePlugin) Score(ctx context.Context, state CycleStatePluginReadWriter, policy *fleetv1.ClusterPolicySnapshot, cluster *fleetv1.MemberCluster) (score *ClusterScore, status *Status) { //nolint:revive +func (p *DummyAllPurposePlugin) Score(ctx context.Context, state CycleStatePluginReadWriter, policy *fleetv1beta1.ClusterPolicySnapshot, cluster *fleetv1beta1.MemberCluster) (score *ClusterScore, status *Status) { //nolint:revive return &ClusterScore{}, nil } diff --git a/pkg/scheduler/framework/score.go b/pkg/scheduler/framework/score.go index b8b4b5996..718143cf1 100644 --- a/pkg/scheduler/framework/score.go +++ b/pkg/scheduler/framework/score.go @@ -6,7 +6,7 @@ Licensed under the MIT license. package framework import ( - fleetv1 "go.goms.io/fleet/apis/v1" + fleetv1beta1 "go.goms.io/fleet/apis/placement/v1beta1" ) // ClusterScore is the scores the scheduler assigns to a cluster. @@ -36,7 +36,7 @@ func (s1 *ClusterScore) Less(s2 *ClusterScore) bool { // ScoredCluster is a cluster with a score. type ScoredCluster struct { - Cluster *fleetv1.MemberCluster + Cluster *fleetv1beta1.MemberCluster Score *ClusterScore } diff --git a/pkg/scheduler/framework/score_test.go b/pkg/scheduler/framework/score_test.go index ead61139c..123579f5e 100644 --- a/pkg/scheduler/framework/score_test.go +++ b/pkg/scheduler/framework/score_test.go @@ -11,7 +11,7 @@ import ( "github.com/google/go-cmp/cmp" - fleetv1 "go.goms.io/fleet/apis/v1" + fleetv1beta1 "go.goms.io/fleet/apis/placement/v1beta1" ) func TestClusterScoreAdd(t *testing.T) { @@ -98,10 +98,10 @@ func TestClusterScoreEqual(t *testing.T) { } func TestScoredClustersSort(t *testing.T) { - clusterA := &fleetv1.MemberCluster{} - clusterB := &fleetv1.MemberCluster{} - clusterC := &fleetv1.MemberCluster{} - clusterD := &fleetv1.MemberCluster{} + clusterA := &fleetv1beta1.MemberCluster{} + clusterB := &fleetv1beta1.MemberCluster{} + clusterC := &fleetv1beta1.MemberCluster{} + clusterD := &fleetv1beta1.MemberCluster{} testCases := []struct { name string