From e658d1ac2e30b414d741e6c6fbf0cb247e7fc91f Mon Sep 17 00:00:00 2001 From: Saeid Askari Date: Fri, 16 Aug 2024 20:05:56 -0400 Subject: [PATCH] Add ClusterClaim for IBU statuses Signed-off-by: Saeid Askari --- internal/common/clusterclaims.go | 77 ++++ internal/common/consts.go | 14 + vendor/modules.txt | 1 + ...uster-management.io_clusterclaims.crd.yaml | 54 +++ ...anagement.io_addonplacementscores.crd.yaml | 153 ++++++++ .../api/cluster/v1alpha1/doc.go | 7 + .../api/cluster/v1alpha1/register.go | 40 +++ .../api/cluster/v1alpha1/types.go | 61 ++++ .../v1alpha1/types_addonplacementscore.go | 75 ++++ .../cluster/v1alpha1/types_rolloutstrategy.go | 148 ++++++++ .../cluster/v1alpha1/zz_generated.deepcopy.go | 335 ++++++++++++++++++ .../zz_generated.swagger_doc_generated.go | 147 ++++++++ 12 files changed, 1112 insertions(+) create mode 100644 internal/common/clusterclaims.go create mode 100644 vendor/open-cluster-management.io/api/cluster/v1alpha1/0000_02_clusters.open-cluster-management.io_clusterclaims.crd.yaml create mode 100644 vendor/open-cluster-management.io/api/cluster/v1alpha1/0000_05_clusters.open-cluster-management.io_addonplacementscores.crd.yaml create mode 100644 vendor/open-cluster-management.io/api/cluster/v1alpha1/doc.go create mode 100644 vendor/open-cluster-management.io/api/cluster/v1alpha1/register.go create mode 100644 vendor/open-cluster-management.io/api/cluster/v1alpha1/types.go create mode 100644 vendor/open-cluster-management.io/api/cluster/v1alpha1/types_addonplacementscore.go create mode 100644 vendor/open-cluster-management.io/api/cluster/v1alpha1/types_rolloutstrategy.go create mode 100644 vendor/open-cluster-management.io/api/cluster/v1alpha1/zz_generated.deepcopy.go create mode 100644 vendor/open-cluster-management.io/api/cluster/v1alpha1/zz_generated.swagger_doc_generated.go diff --git a/internal/common/clusterclaims.go b/internal/common/clusterclaims.go new file mode 100644 index 000000000..05010eb3d --- /dev/null +++ b/internal/common/clusterclaims.go @@ -0,0 +1,77 @@ +package common + +import ( + "context" + "fmt" + "strings" + + "github.com/go-logr/logr" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + clusterv1 "open-cluster-management.io/api/cluster/v1alpha1" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +const ClusterClaimPrefix = "lcm.openshift.io/ibu-" + +func isClusterClaimCRDInstalled(ctx context.Context, client client.Client) (bool, error) { + crd := &apiextensionsv1.CustomResourceDefinition{} + if err := client.Get(ctx, types.NamespacedName{ + Name: "clusterclaims.cluster.open-cluster-management.io", + }, crd); err != nil { + if apierrors.IsNotFound(err) { + return false, nil + } + return false, fmt.Errorf("could not get ClusterClaim crd: %w", err) + } + return true, nil +} + +func CleanupClusterClaims(ctx context.Context, client client.Client, log *logr.Logger) error { + if installed, err := isClusterClaimCRDInstalled(ctx, client); err != nil { + return err + } else if !installed { + log.Info("ClusterClaim CRD not found; Skip creating ClusterClaim") + return nil + } + cl := &clusterv1.ClusterClaimList{} + err := client.List(ctx, cl) + if err != nil { + return fmt.Errorf("failed to list ClusterClaims: %w", err) + } + for _, cc := range cl.Items { + if strings.HasPrefix(cc.Name, ClusterClaimPrefix) { + err := client.Delete(ctx, &cc) + if err != nil { + return fmt.Errorf("failed to delete ClusterClaim: %w", err) + } + } + } + return nil +} + +func CreateClusterClaim(ctx context.Context, client client.Client, log *logr.Logger, stage string, status string) error { + if installed, err := isClusterClaimCRDInstalled(ctx, client); err != nil { + return err + } else if !installed { + log.Info("ClusterClaim CRD not found; Skip creating ClusterClaim") + return nil + } + cc := &clusterv1.ClusterClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: ClusterClaimPrefix + stage, + }, + Spec: clusterv1.ClusterClaimSpec{ + Value: status, + }, + } + err := client.Create(ctx, cc) + if apierrors.IsAlreadyExists(err) { + log.Info("ClusterClaim already exists") + } else if err != nil { + return fmt.Errorf("could not create ClusterClaim: %w", err) + } + return nil +} diff --git a/internal/common/consts.go b/internal/common/consts.go index 7852e08f4..3a7d32919 100644 --- a/internal/common/consts.go +++ b/internal/common/consts.go @@ -155,3 +155,17 @@ var CertPrefixes = []string{ } var TarOpts = []string{"--selinux", "--xattrs", "--xattrs-include=*", "--acls"} + +// status for ClusterClaims +const ( + Failed = "failed" + Completed = "completed" +) + +// actions for ClusterClaims +const ( + Prep = "prep" + Upgrade = "upgrade" + Finalize = "finalize" + Abort = "abort" +) diff --git a/vendor/modules.txt b/vendor/modules.txt index e53069e2f..9f690da38 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1138,6 +1138,7 @@ k8s.io/utils/trace # open-cluster-management.io/api v0.14.0 ## explicit; go 1.21 open-cluster-management.io/api/cluster/v1 +open-cluster-management.io/api/cluster/v1alpha1 # open-cluster-management.io/config-policy-controller v0.14.0 ## explicit; go 1.21 open-cluster-management.io/config-policy-controller/api/v1 diff --git a/vendor/open-cluster-management.io/api/cluster/v1alpha1/0000_02_clusters.open-cluster-management.io_clusterclaims.crd.yaml b/vendor/open-cluster-management.io/api/cluster/v1alpha1/0000_02_clusters.open-cluster-management.io_clusterclaims.crd.yaml new file mode 100644 index 000000000..5355bb16d --- /dev/null +++ b/vendor/open-cluster-management.io/api/cluster/v1alpha1/0000_02_clusters.open-cluster-management.io_clusterclaims.crd.yaml @@ -0,0 +1,54 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: clusterclaims.cluster.open-cluster-management.io +spec: + group: cluster.open-cluster-management.io + names: + kind: ClusterClaim + listKind: ClusterClaimList + plural: clusterclaims + singular: clusterclaim + preserveUnknownFields: false + scope: Cluster + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: "ClusterClaim represents cluster information that a managed cluster + claims ClusterClaims with well known names include, 1. id.k8s.io, it contains + a unique identifier for the cluster. 2. clusterset.k8s.io, it contains an + identifier that relates the cluster to the ClusterSet in which it belongs. + \n ClusterClaims created on a managed cluster will be collected and saved + into the status of the corresponding ManagedCluster on hub." + 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: Spec defines the attributes of the ClusterClaim. + properties: + value: + description: Value is a claim-dependent string + maxLength: 1024 + minLength: 1 + type: string + type: object + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/vendor/open-cluster-management.io/api/cluster/v1alpha1/0000_05_clusters.open-cluster-management.io_addonplacementscores.crd.yaml b/vendor/open-cluster-management.io/api/cluster/v1alpha1/0000_05_clusters.open-cluster-management.io_addonplacementscores.crd.yaml new file mode 100644 index 000000000..1cfba5564 --- /dev/null +++ b/vendor/open-cluster-management.io/api/cluster/v1alpha1/0000_05_clusters.open-cluster-management.io_addonplacementscores.crd.yaml @@ -0,0 +1,153 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: addonplacementscores.cluster.open-cluster-management.io +spec: + group: cluster.open-cluster-management.io + names: + kind: AddOnPlacementScore + listKind: AddOnPlacementScoreList + plural: addonplacementscores + singular: addonplacementscore + preserveUnknownFields: false + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: AddOnPlacementScore represents a bundle of scores of one managed + cluster, which could be used by placement. AddOnPlacementScore is a namespace + scoped resource. The namespace of the resource is the cluster namespace. + 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 + status: + description: Status represents the status of the AddOnPlacementScore. + properties: + conditions: + description: Conditions contain the different condition statuses for + this AddOnPlacementScore. + 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 + scores: + description: Scores contain a list of score name and value of this + managed cluster. + items: + description: AddOnPlacementScoreItem represents the score name and + value. + properties: + name: + description: Name is the name of the score + type: string + value: + description: Value is the value of the score. The score range + is from -100 to 100. + format: int32 + maximum: 100 + minimum: -100 + type: integer + required: + - name + - value + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + validUntil: + description: ValidUntil defines the valid time of the scores. After + this time, the scores are considered to be invalid by placement. + nil means never expire. The controller owning this resource should + keep the scores up-to-date. + format: date-time + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/vendor/open-cluster-management.io/api/cluster/v1alpha1/doc.go b/vendor/open-cluster-management.io/api/cluster/v1alpha1/doc.go new file mode 100644 index 000000000..93f37581c --- /dev/null +++ b/vendor/open-cluster-management.io/api/cluster/v1alpha1/doc.go @@ -0,0 +1,7 @@ +// Package v1alpha1 contains API Schema definitions for the cluster v1alpha1 API group +// +k8s:deepcopy-gen=package,register +// +k8s:openapi-gen=true + +// +kubebuilder:validation:Optional +// +groupName=cluster.open-cluster-management.io +package v1alpha1 diff --git a/vendor/open-cluster-management.io/api/cluster/v1alpha1/register.go b/vendor/open-cluster-management.io/api/cluster/v1alpha1/register.go new file mode 100644 index 000000000..36b73ce2f --- /dev/null +++ b/vendor/open-cluster-management.io/api/cluster/v1alpha1/register.go @@ -0,0 +1,40 @@ +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +var ( + GroupName = "cluster.open-cluster-management.io" + GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"} + schemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + // Install is a function which adds this version to a scheme + Install = schemeBuilder.AddToScheme + + // SchemeGroupVersion generated code relies on this name + // Deprecated + SchemeGroupVersion = GroupVersion + // AddToScheme exists solely to keep the old generators creating valid code + // DEPRECATED + AddToScheme = schemeBuilder.AddToScheme +) + +// Resource generated code relies on this being here, but it logically belongs to the group +// DEPRECATED +func Resource(resource string) schema.GroupResource { + return schema.GroupResource{Group: GroupName, Resource: resource} +} + +// Adds the list of known types to api.Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(GroupVersion, + &AddOnPlacementScore{}, + &AddOnPlacementScoreList{}, + &ClusterClaim{}, + &ClusterClaimList{}, + ) + metav1.AddToGroupVersion(scheme, GroupVersion) + return nil +} diff --git a/vendor/open-cluster-management.io/api/cluster/v1alpha1/types.go b/vendor/open-cluster-management.io/api/cluster/v1alpha1/types.go new file mode 100644 index 000000000..6cb57bc3b --- /dev/null +++ b/vendor/open-cluster-management.io/api/cluster/v1alpha1/types.go @@ -0,0 +1,61 @@ +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +genclient +// +genclient:nonNamespaced +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:resource:scope="Cluster" + +// ClusterClaim represents cluster information that a managed cluster claims +// ClusterClaims with well known names include, +// 1. id.k8s.io, it contains a unique identifier for the cluster. +// 2. clusterset.k8s.io, it contains an identifier that relates the cluster +// to the ClusterSet in which it belongs. +// +// ClusterClaims created on a managed cluster will be collected and saved into +// the status of the corresponding ManagedCluster on hub. +type ClusterClaim struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec defines the attributes of the ClusterClaim. + Spec ClusterClaimSpec `json:"spec,omitempty"` +} + +type ClusterClaimSpec struct { + // Value is a claim-dependent string + // +kubebuilder:validation:MaxLength=1024 + // +kubebuilder:validation:MinLength=1 + Value string `json:"value,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ClusterClaimList is a collection of ClusterClaim. +type ClusterClaimList struct { + metav1.TypeMeta `json:",inline"` + // Standard list metadata. + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds + // +optional + metav1.ListMeta `json:"metadata,omitempty"` + + // Items is a list of ClusterClaim. + Items []ClusterClaim `json:"items"` +} + +// ReservedClusterClaimNames includes a list of reserved names for ClusterNames. +// When exposing ClusterClaims created on managed cluster, the registration agent gives high +// priority to the reserved ClusterClaims. +var ReservedClusterClaimNames = [...]string{ + // unique identifier for the cluster + "id.k8s.io", + // kubernetes version + "kubeversion.open-cluster-management.io", + // platform the managed cluster is running on, like AWS, GCE, and Equinix Metal + "platform.open-cluster-management.io", + // product name, like OpenShift, Anthos, EKS and GKE + "product.open-cluster-management.io", +} diff --git a/vendor/open-cluster-management.io/api/cluster/v1alpha1/types_addonplacementscore.go b/vendor/open-cluster-management.io/api/cluster/v1alpha1/types_addonplacementscore.go new file mode 100644 index 000000000..1ce73580b --- /dev/null +++ b/vendor/open-cluster-management.io/api/cluster/v1alpha1/types_addonplacementscore.go @@ -0,0 +1,75 @@ +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:resource:scope="Namespaced" +// +kubebuilder:subresource:status + +// AddOnPlacementScore represents a bundle of scores of one managed cluster, which could be used by placement. +// AddOnPlacementScore is a namespace scoped resource. The namespace of the resource is the cluster namespace. +type AddOnPlacementScore struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Status represents the status of the AddOnPlacementScore. + // +optional + Status AddOnPlacementScoreStatus `json:"status,omitempty"` +} + +// AddOnPlacementScoreStatus represents the current status of AddOnPlacementScore. +type AddOnPlacementScoreStatus struct { + // Conditions contain the different condition statuses for this AddOnPlacementScore. + // +patchMergeKey=type + // +patchStrategy=merge + // +listType=map + // +listMapKey=type + // +optional + Conditions []metav1.Condition `json:"conditions,omitempty"` + + // Scores contain a list of score name and value of this managed cluster. + // +listType=map + // +listMapKey=name + // +optional + Scores []AddOnPlacementScoreItem `json:"scores,omitempty"` + + // ValidUntil defines the valid time of the scores. + // After this time, the scores are considered to be invalid by placement. nil means never expire. + // The controller owning this resource should keep the scores up-to-date. + // +kubebuilder:validation:Type=string + // +kubebuilder:validation:Format=date-time + // +optional + ValidUntil *metav1.Time `json:"validUntil"` +} + +// AddOnPlacementScoreItem represents the score name and value. +type AddOnPlacementScoreItem struct { + // Name is the name of the score + // +kubebuilder:validation:Required + // +required + Name string `json:"name"` + + // Value is the value of the score. The score range is from -100 to 100. + // +kubebuilder:validation:Required + // +kubebuilder:validation:Minimum:=-100 + // +kubebuilder:validation:Maximum:=100 + // +required + Value int32 `json:"value"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// AddOnPlacementScoreList is a collection of AddOnPlacementScore. +type AddOnPlacementScoreList struct { + metav1.TypeMeta `json:",inline"` + // Standard list metadata. + // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds + // +optional + metav1.ListMeta `json:"metadata,omitempty"` + + // Items is a list of AddOnPlacementScore + Items []AddOnPlacementScore `json:"items"` +} diff --git a/vendor/open-cluster-management.io/api/cluster/v1alpha1/types_rolloutstrategy.go b/vendor/open-cluster-management.io/api/cluster/v1alpha1/types_rolloutstrategy.go new file mode 100644 index 000000000..2c863bb50 --- /dev/null +++ b/vendor/open-cluster-management.io/api/cluster/v1alpha1/types_rolloutstrategy.go @@ -0,0 +1,148 @@ +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" +) + +// +k8s:deepcopy-gen=true + +// RolloutStrategy API used by workload applier APIs to define how the workload will be applied to +// the selected clusters by the Placement and DecisionStrategy. + +type RolloutType string + +const ( + //All means apply the workload to all clusters in the decision groups at once. + All RolloutType = "All" + //Progressive means apply the workload to the selected clusters progressively per cluster. + Progressive RolloutType = "Progressive" + //ProgressivePerGroup means apply the workload to the selected clusters progressively per group. + ProgressivePerGroup RolloutType = "ProgressivePerGroup" +) + +// Rollout strategy to apply workload to the selected clusters by Placement and DecisionStrategy. +type RolloutStrategy struct { + // Rollout strategy Types are All, Progressive and ProgressivePerGroup + // 1) All means apply the workload to all clusters in the decision groups at once. + // 2) Progressive means apply the workload to the selected clusters progressively per cluster. The + // workload will not be applied to the next cluster unless one of the current applied clusters + // reach the successful state and haven't breached the MaxFailures configuration. + // 3) ProgressivePerGroup means apply the workload to decisionGroup clusters progressively per + // group. The workload will not be applied to the next decisionGroup unless all clusters in the + // current group reach the successful state and haven't breached the MaxFailures configuration. + + // +kubebuilder:validation:Enum=All;Progressive;ProgressivePerGroup + // +kubebuilder:default:=All + // +optional + Type RolloutType `json:"type,omitempty"` + + // All defines required fields for RolloutStrategy type All + // +optional + All *RolloutAll `json:"all,omitempty"` + + // Progressive defines required fields for RolloutStrategy type Progressive + // +optional + Progressive *RolloutProgressive `json:"progressive,omitempty"` + + // ProgressivePerGroup defines required fields for RolloutStrategy type ProgressivePerGroup + // +optional + ProgressivePerGroup *RolloutProgressivePerGroup `json:"progressivePerGroup,omitempty"` +} + +// Timeout to consider while applying the workload. +type RolloutConfig struct { + // MinSuccessTime is a "soak" time. In other words, the minimum amount of time the workload + // applier controller will wait from the start of each rollout before proceeding (assuming a + // successful state has been reached and MaxFailures wasn't breached). + // MinSuccessTime is only considered for rollout types Progressive and ProgressivePerGroup. + // The default value is 0 meaning the workload applier proceeds immediately after a successful + // state is reached. + // MinSuccessTime must be defined in [0-9h]|[0-9m]|[0-9s] format examples; 2h , 90m , 360s + // +kubebuilder:default:="0" + // +optional + MinSuccessTime metav1.Duration `json:"minSuccessTime,omitempty"` + // ProgressDeadline defines how long workload applier controller will wait for the workload to + // reach a successful state in the cluster. + // If the workload does not reach a successful state after ProgressDeadline, will stop waiting + // and workload will be treated as "timeout" and be counted into MaxFailures. Once the MaxFailures + // is breached, the rollout will stop. + // ProgressDeadline default value is "None", meaning the workload applier will wait for a + // successful state indefinitely. + // ProgressDeadline must be defined in [0-9h]|[0-9m]|[0-9s] format examples; 2h , 90m , 360s + // +kubebuilder:validation:Pattern="^(([0-9])+[h|m|s])|None$" + // +kubebuilder:default:="None" + // +optional + ProgressDeadline string `json:"progressDeadline,omitempty"` + // MaxFailures is a percentage or number of clusters in the current rollout that can fail before + // proceeding to the next rollout. Fail means the cluster has a failed status or timeout status + // (does not reach successful status after ProgressDeadline). + // Once the MaxFailures is breached, the rollout will stop. + // MaxFailures is only considered for rollout types Progressive and ProgressivePerGroup. For + // Progressive, this is considered over the total number of clusters. For ProgressivePerGroup, + // this is considered according to the size of the current group. For both Progressive and + // ProgressivePerGroup, the MaxFailures does not apply for MandatoryDecisionGroups, which tolerate + // no failures. + // Default is that no failures are tolerated. + // +kubebuilder:validation:Pattern="^((100|[0-9]{1,2})%|[0-9]+)$" + // +kubebuilder:validation:XIntOrString + // +kubebuilder:default=0 + // +optional + MaxFailures intstr.IntOrString `json:"maxFailures,omitempty"` +} + +// MandatoryDecisionGroup set the decision group name or group index. +// GroupName is considered first to select the decisionGroups then GroupIndex. +type MandatoryDecisionGroup struct { + // GroupName of the decision group should match the placementDecisions label value with label key + // cluster.open-cluster-management.io/decision-group-name + // +optional + GroupName string `json:"groupName,omitempty"` + + // GroupIndex of the decision group should match the placementDecisions label value with label key + // cluster.open-cluster-management.io/decision-group-index + // +optional + GroupIndex int32 `json:"groupIndex,omitempty"` +} + +// MandatoryDecisionGroups +type MandatoryDecisionGroups struct { + // List of the decision groups names or indexes to apply the workload first and fail if workload + // did not reach successful state. + // GroupName or GroupIndex must match with the decisionGroups defined in the placement's + // decisionStrategy + // +optional + MandatoryDecisionGroups []MandatoryDecisionGroup `json:"mandatoryDecisionGroups,omitempty"` +} + +// RolloutAll is a RolloutStrategy Type +type RolloutAll struct { + // +optional + RolloutConfig `json:",inline"` +} + +// RolloutProgressivePerGroup is a RolloutStrategy Type +type RolloutProgressivePerGroup struct { + // +optional + RolloutConfig `json:",inline"` + + // +optional + MandatoryDecisionGroups `json:",inline"` +} + +// RolloutProgressive is a RolloutStrategy Type +type RolloutProgressive struct { + // +optional + RolloutConfig `json:",inline"` + + // +optional + MandatoryDecisionGroups `json:",inline"` + + // MaxConcurrency is the max number of clusters to deploy workload concurrently. The default value + // for MaxConcurrency is determined from the clustersPerDecisionGroup defined in the + // placement->DecisionStrategy. + // +kubebuilder:validation:Pattern="^((100|[0-9]{1,2})%|[0-9]+)$" + // +kubebuilder:validation:XIntOrString + // +optional + MaxConcurrency intstr.IntOrString `json:"maxConcurrency,omitempty"` +} diff --git a/vendor/open-cluster-management.io/api/cluster/v1alpha1/zz_generated.deepcopy.go b/vendor/open-cluster-management.io/api/cluster/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 000000000..e40f74e4d --- /dev/null +++ b/vendor/open-cluster-management.io/api/cluster/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,335 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AddOnPlacementScore) DeepCopyInto(out *AddOnPlacementScore) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddOnPlacementScore. +func (in *AddOnPlacementScore) DeepCopy() *AddOnPlacementScore { + if in == nil { + return nil + } + out := new(AddOnPlacementScore) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *AddOnPlacementScore) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AddOnPlacementScoreItem) DeepCopyInto(out *AddOnPlacementScoreItem) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddOnPlacementScoreItem. +func (in *AddOnPlacementScoreItem) DeepCopy() *AddOnPlacementScoreItem { + if in == nil { + return nil + } + out := new(AddOnPlacementScoreItem) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AddOnPlacementScoreList) DeepCopyInto(out *AddOnPlacementScoreList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]AddOnPlacementScore, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddOnPlacementScoreList. +func (in *AddOnPlacementScoreList) DeepCopy() *AddOnPlacementScoreList { + if in == nil { + return nil + } + out := new(AddOnPlacementScoreList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *AddOnPlacementScoreList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AddOnPlacementScoreStatus) DeepCopyInto(out *AddOnPlacementScoreStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]v1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Scores != nil { + in, out := &in.Scores, &out.Scores + *out = make([]AddOnPlacementScoreItem, len(*in)) + copy(*out, *in) + } + if in.ValidUntil != nil { + in, out := &in.ValidUntil, &out.ValidUntil + *out = (*in).DeepCopy() + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddOnPlacementScoreStatus. +func (in *AddOnPlacementScoreStatus) DeepCopy() *AddOnPlacementScoreStatus { + if in == nil { + return nil + } + out := new(AddOnPlacementScoreStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterClaim) DeepCopyInto(out *ClusterClaim) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterClaim. +func (in *ClusterClaim) DeepCopy() *ClusterClaim { + if in == nil { + return nil + } + out := new(ClusterClaim) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ClusterClaim) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterClaimList) DeepCopyInto(out *ClusterClaimList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ClusterClaim, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterClaimList. +func (in *ClusterClaimList) DeepCopy() *ClusterClaimList { + if in == nil { + return nil + } + out := new(ClusterClaimList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ClusterClaimList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterClaimSpec) DeepCopyInto(out *ClusterClaimSpec) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterClaimSpec. +func (in *ClusterClaimSpec) DeepCopy() *ClusterClaimSpec { + if in == nil { + return nil + } + out := new(ClusterClaimSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MandatoryDecisionGroup) DeepCopyInto(out *MandatoryDecisionGroup) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MandatoryDecisionGroup. +func (in *MandatoryDecisionGroup) DeepCopy() *MandatoryDecisionGroup { + if in == nil { + return nil + } + out := new(MandatoryDecisionGroup) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MandatoryDecisionGroups) DeepCopyInto(out *MandatoryDecisionGroups) { + *out = *in + if in.MandatoryDecisionGroups != nil { + in, out := &in.MandatoryDecisionGroups, &out.MandatoryDecisionGroups + *out = make([]MandatoryDecisionGroup, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MandatoryDecisionGroups. +func (in *MandatoryDecisionGroups) DeepCopy() *MandatoryDecisionGroups { + if in == nil { + return nil + } + out := new(MandatoryDecisionGroups) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RolloutAll) DeepCopyInto(out *RolloutAll) { + *out = *in + out.RolloutConfig = in.RolloutConfig + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RolloutAll. +func (in *RolloutAll) DeepCopy() *RolloutAll { + if in == nil { + return nil + } + out := new(RolloutAll) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RolloutConfig) DeepCopyInto(out *RolloutConfig) { + *out = *in + out.MinSuccessTime = in.MinSuccessTime + out.MaxFailures = in.MaxFailures + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RolloutConfig. +func (in *RolloutConfig) DeepCopy() *RolloutConfig { + if in == nil { + return nil + } + out := new(RolloutConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RolloutProgressive) DeepCopyInto(out *RolloutProgressive) { + *out = *in + out.RolloutConfig = in.RolloutConfig + in.MandatoryDecisionGroups.DeepCopyInto(&out.MandatoryDecisionGroups) + out.MaxConcurrency = in.MaxConcurrency + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RolloutProgressive. +func (in *RolloutProgressive) DeepCopy() *RolloutProgressive { + if in == nil { + return nil + } + out := new(RolloutProgressive) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RolloutProgressivePerGroup) DeepCopyInto(out *RolloutProgressivePerGroup) { + *out = *in + out.RolloutConfig = in.RolloutConfig + in.MandatoryDecisionGroups.DeepCopyInto(&out.MandatoryDecisionGroups) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RolloutProgressivePerGroup. +func (in *RolloutProgressivePerGroup) DeepCopy() *RolloutProgressivePerGroup { + if in == nil { + return nil + } + out := new(RolloutProgressivePerGroup) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RolloutStrategy) DeepCopyInto(out *RolloutStrategy) { + *out = *in + if in.All != nil { + in, out := &in.All, &out.All + *out = new(RolloutAll) + **out = **in + } + if in.Progressive != nil { + in, out := &in.Progressive, &out.Progressive + *out = new(RolloutProgressive) + (*in).DeepCopyInto(*out) + } + if in.ProgressivePerGroup != nil { + in, out := &in.ProgressivePerGroup, &out.ProgressivePerGroup + *out = new(RolloutProgressivePerGroup) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RolloutStrategy. +func (in *RolloutStrategy) DeepCopy() *RolloutStrategy { + if in == nil { + return nil + } + out := new(RolloutStrategy) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/open-cluster-management.io/api/cluster/v1alpha1/zz_generated.swagger_doc_generated.go b/vendor/open-cluster-management.io/api/cluster/v1alpha1/zz_generated.swagger_doc_generated.go new file mode 100644 index 000000000..64c51d246 --- /dev/null +++ b/vendor/open-cluster-management.io/api/cluster/v1alpha1/zz_generated.swagger_doc_generated.go @@ -0,0 +1,147 @@ +package v1alpha1 + +// This file contains a collection of methods that can be used from go-restful to +// generate Swagger API documentation for its models. Please read this PR for more +// information on the implementation: https://github.com/emicklei/go-restful/pull/215 +// +// TODOs are ignored from the parser (e.g. TODO(andronat):... || TODO:...) if and only if +// they are on one line! For multiple line or blocks that you want to ignore use ---. +// Any context after a --- is ignored. +// +// Those methods can be generated by using hack/update-swagger-docs.sh + +// AUTO-GENERATED FUNCTIONS START HERE +var map_ClusterClaim = map[string]string{ + "": "ClusterClaim represents cluster information that a managed cluster claims ClusterClaims with well known names include,\n 1. id.k8s.io, it contains a unique identifier for the cluster.\n 2. clusterset.k8s.io, it contains an identifier that relates the cluster\n to the ClusterSet in which it belongs.\n\nClusterClaims created on a managed cluster will be collected and saved into the status of the corresponding ManagedCluster on hub.", + "spec": "Spec defines the attributes of the ClusterClaim.", +} + +func (ClusterClaim) SwaggerDoc() map[string]string { + return map_ClusterClaim +} + +var map_ClusterClaimList = map[string]string{ + "": "ClusterClaimList is a collection of ClusterClaim.", + "metadata": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "items": "Items is a list of ClusterClaim.", +} + +func (ClusterClaimList) SwaggerDoc() map[string]string { + return map_ClusterClaimList +} + +var map_ClusterClaimSpec = map[string]string{ + "value": "Value is a claim-dependent string", +} + +func (ClusterClaimSpec) SwaggerDoc() map[string]string { + return map_ClusterClaimSpec +} + +var map_AddOnPlacementScore = map[string]string{ + "": "AddOnPlacementScore represents a bundle of scores of one managed cluster, which could be used by placement. AddOnPlacementScore is a namespace scoped resource. The namespace of the resource is the cluster namespace.", + "status": "Status represents the status of the AddOnPlacementScore.", +} + +func (AddOnPlacementScore) SwaggerDoc() map[string]string { + return map_AddOnPlacementScore +} + +var map_AddOnPlacementScoreItem = map[string]string{ + "": "AddOnPlacementScoreItem represents the score name and value.", + "name": "Name is the name of the score", + "value": "Value is the value of the score. The score range is from -100 to 100.", +} + +func (AddOnPlacementScoreItem) SwaggerDoc() map[string]string { + return map_AddOnPlacementScoreItem +} + +var map_AddOnPlacementScoreList = map[string]string{ + "": "AddOnPlacementScoreList is a collection of AddOnPlacementScore.", + "metadata": "Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds", + "items": "Items is a list of AddOnPlacementScore", +} + +func (AddOnPlacementScoreList) SwaggerDoc() map[string]string { + return map_AddOnPlacementScoreList +} + +var map_AddOnPlacementScoreStatus = map[string]string{ + "": "AddOnPlacementScoreStatus represents the current status of AddOnPlacementScore.", + "conditions": "Conditions contain the different condition statuses for this AddOnPlacementScore.", + "scores": "Scores contain a list of score name and value of this managed cluster.", + "validUntil": "ValidUntil defines the valid time of the scores. After this time, the scores are considered to be invalid by placement. nil means never expire. The controller owning this resource should keep the scores up-to-date.", +} + +func (AddOnPlacementScoreStatus) SwaggerDoc() map[string]string { + return map_AddOnPlacementScoreStatus +} + +var map_MandatoryDecisionGroup = map[string]string{ + "": "MandatoryDecisionGroup set the decision group name or group index. GroupName is considered first to select the decisionGroups then GroupIndex.", + "groupName": "GroupName of the decision group should match the placementDecisions label value with label key cluster.open-cluster-management.io/decision-group-name", + "groupIndex": "GroupIndex of the decision group should match the placementDecisions label value with label key cluster.open-cluster-management.io/decision-group-index", +} + +func (MandatoryDecisionGroup) SwaggerDoc() map[string]string { + return map_MandatoryDecisionGroup +} + +var map_MandatoryDecisionGroups = map[string]string{ + "": "MandatoryDecisionGroups", + "mandatoryDecisionGroups": "List of the decision groups names or indexes to apply the workload first and fail if workload did not reach successful state. GroupName or GroupIndex must match with the decisionGroups defined in the placement's decisionStrategy", +} + +func (MandatoryDecisionGroups) SwaggerDoc() map[string]string { + return map_MandatoryDecisionGroups +} + +var map_RolloutAll = map[string]string{ + "": "RolloutAll is a RolloutStrategy Type", +} + +func (RolloutAll) SwaggerDoc() map[string]string { + return map_RolloutAll +} + +var map_RolloutConfig = map[string]string{ + "": "Timeout to consider while applying the workload.", + "minSuccessTime": "MinSuccessTime is a \"soak\" time. In other words, the minimum amount of time the workload applier controller will wait from the start of each rollout before proceeding (assuming a successful state has been reached and MaxFailures wasn't breached). MinSuccessTime is only considered for rollout types Progressive and ProgressivePerGroup. The default value is 0 meaning the workload applier proceeds immediately after a successful state is reached. MinSuccessTime must be defined in [0-9h]|[0-9m]|[0-9s] format examples; 2h , 90m , 360s", + "progressDeadline": "ProgressDeadline defines how long workload applier controller will wait for the workload to reach a successful state in the cluster. If the workload does not reach a successful state after ProgressDeadline, will stop waiting and workload will be treated as \"timeout\" and be counted into MaxFailures. Once the MaxFailures is breached, the rollout will stop. ProgressDeadline default value is \"None\", meaning the workload applier will wait for a successful state indefinitely. ProgressDeadline must be defined in [0-9h]|[0-9m]|[0-9s] format examples; 2h , 90m , 360s", + "maxFailures": "MaxFailures is a percentage or number of clusters in the current rollout that can fail before proceeding to the next rollout. Fail means the cluster has a failed status or timeout status (does not reach successful status after ProgressDeadline). Once the MaxFailures is breached, the rollout will stop. MaxFailures is only considered for rollout types Progressive and ProgressivePerGroup. For Progressive, this is considered over the total number of clusters. For ProgressivePerGroup, this is considered according to the size of the current group. For both Progressive and ProgressivePerGroup, the MaxFailures does not apply for MandatoryDecisionGroups, which tolerate no failures. Default is that no failures are tolerated.", +} + +func (RolloutConfig) SwaggerDoc() map[string]string { + return map_RolloutConfig +} + +var map_RolloutProgressive = map[string]string{ + "": "RolloutProgressive is a RolloutStrategy Type", + "maxConcurrency": "MaxConcurrency is the max number of clusters to deploy workload concurrently. The default value for MaxConcurrency is determined from the clustersPerDecisionGroup defined in the placement->DecisionStrategy.", +} + +func (RolloutProgressive) SwaggerDoc() map[string]string { + return map_RolloutProgressive +} + +var map_RolloutProgressivePerGroup = map[string]string{ + "": "RolloutProgressivePerGroup is a RolloutStrategy Type", +} + +func (RolloutProgressivePerGroup) SwaggerDoc() map[string]string { + return map_RolloutProgressivePerGroup +} + +var map_RolloutStrategy = map[string]string{ + "": "Rollout strategy to apply workload to the selected clusters by Placement and DecisionStrategy.", + "all": "All defines required fields for RolloutStrategy type All", + "progressive": "Progressive defines required fields for RolloutStrategy type Progressive", + "progressivePerGroup": "ProgressivePerGroup defines required fields for RolloutStrategy type ProgressivePerGroup", +} + +func (RolloutStrategy) SwaggerDoc() map[string]string { + return map_RolloutStrategy +} + +// AUTO-GENERATED FUNCTIONS END HERE