diff --git a/Makefile b/Makefile index 9357d28d9..6925a87c8 100644 --- a/Makefile +++ b/Makefile @@ -233,7 +233,7 @@ CRD_OPTIONS ?= "crd" .PHONY: manifests manifests: $(CONTROLLER_GEN) $(CONTROLLER_GEN) \ - $(CRD_OPTIONS) rbac:roleName=manager-role webhook paths="./..." output:crd:artifacts:config=config/crd/bases + $(CRD_OPTIONS) rbac:roleName=manager-role webhook paths="./apis/..." output:crd:artifacts:config=config/crd/bases # Generate code generate: $(CONTROLLER_GEN) diff --git a/examples/test-cro1.yaml b/examples/test-cro1.yaml index 322406ead..0e70f065b 100644 --- a/examples/test-cro1.yaml +++ b/examples/test-cro1.yaml @@ -6,7 +6,7 @@ spec: clusterResourceSelectors: - group: apiextensions.k8s.io kind: CustomResourceDefinition - name: clonesets.apps.kruise.io + name: testresources.test.kubernetes-fleet.io version: v1 policy: overrideRules: diff --git a/examples/test-crp1.yaml b/examples/test-crp1.yaml index 641868d91..a7fe31e62 100644 --- a/examples/test-crp1.yaml +++ b/examples/test-crp1.yaml @@ -6,7 +6,7 @@ spec: resourceSelectors: - group: apiextensions.k8s.io kind: CustomResourceDefinition - name: clonesets.apps.kruise.io + name: testresources.test.kubernetes-fleet.io version: v1 policy: placementType: PickN diff --git a/examples/test-crp2.yaml b/examples/test-crp2.yaml index 45da5af2e..2ebb9b7dc 100644 --- a/examples/test-crp2.yaml +++ b/examples/test-crp2.yaml @@ -6,7 +6,7 @@ spec: resourceSelectors: - group: apiextensions.k8s.io kind: CustomResourceDefinition - name: clonesets.apps.kruise.io + name: testresources.test.kubernetes-fleet.io version: v1 policy: placementType: PickN diff --git a/examples/test-crp3.yaml b/examples/test-crp3.yaml index c504db891..1f285ef27 100644 --- a/examples/test-crp3.yaml +++ b/examples/test-crp3.yaml @@ -6,7 +6,7 @@ spec: resourceSelectors: - group: apiextensions.k8s.io kind: CustomResourceDefinition - name: clonesets.apps.kruise.io + name: testresources.test.kubernetes-fleet.io version: v1 policy: placementType: PickN diff --git a/examples/test-crp4.yaml b/examples/test-crp4.yaml index 125cc72f8..c3447db5a 100644 --- a/examples/test-crp4.yaml +++ b/examples/test-crp4.yaml @@ -6,7 +6,7 @@ spec: resourceSelectors: - group: apiextensions.k8s.io kind: CustomResourceDefinition - name: clonesets.apps.kruise.io + name: testresources.test.kubernetes-fleet.io version: v1 policy: placementType: PickN diff --git a/examples/test-crp5.yaml b/examples/test-crp5.yaml index ecb0746b8..30cac4094 100644 --- a/examples/test-crp5.yaml +++ b/examples/test-crp5.yaml @@ -6,7 +6,7 @@ spec: resourceSelectors: - group: apiextensions.k8s.io kind: CustomResourceDefinition - name: clonesets.apps.kruise.io + name: testresources.test.kubernetes-fleet.io version: v1 policy: placementType: PickN diff --git a/examples/test-crp6.yaml b/examples/test-crp6.yaml index 8afc5a318..ffbeff116 100644 --- a/examples/test-crp6.yaml +++ b/examples/test-crp6.yaml @@ -6,7 +6,7 @@ spec: resourceSelectors: - group: apiextensions.k8s.io kind: CustomResourceDefinition - name: clonesets.apps.kruise.io + name: testresources.test.kubernetes-fleet.io version: v1 policy: placementType: PickAll diff --git a/examples/test-crp8.yaml b/examples/test-crp8.yaml index caeecb43e..c80221581 100644 --- a/examples/test-crp8.yaml +++ b/examples/test-crp8.yaml @@ -6,7 +6,7 @@ spec: resourceSelectors: - group: apiextensions.k8s.io kind: CustomResourceDefinition - name: clonesets.apps.kruise.io + name: testresources.test.kubernetes-fleet.io version: v1 policy: placementType: PickN diff --git a/go.mod b/go.mod index 948252f50..76ab6e0ae 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,6 @@ require ( github.com/google/go-cmp v0.6.0 github.com/onsi/ginkgo/v2 v2.17.2 github.com/onsi/gomega v1.33.1 - github.com/openkruise/kruise v1.4.0 github.com/prometheus/client_golang v1.19.1 github.com/prometheus/client_model v0.6.1 github.com/spf13/cobra v1.8.0 diff --git a/go.sum b/go.sum index d6aad4cfa..cd5ae7143 100644 --- a/go.sum +++ b/go.sum @@ -153,8 +153,6 @@ github.com/onsi/ginkgo/v2 v2.17.2 h1:7eMhcy3GimbsA3hEnVKdw/PQM9XN9krpKVXsZdph0/g github.com/onsi/ginkgo/v2 v2.17.2/go.mod h1:nP2DPOQoNsQmsVyv5rDA8JkXQoCs6goXIvr/PRJ1eCc= github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= -github.com/openkruise/kruise v1.4.0 h1:1OTosvEat+2sE59jaj3sqicdkHqMkTrafq0mSaHBLYs= -github.com/openkruise/kruise v1.4.0/go.mod h1:b6DHo7c3d8pDyIoT13/dCDiuAn6F8fZR1644c9Dui1I= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= diff --git a/hack/loadtest/README.md b/hack/loadtest/README.md index 4721e8d39..3809f3e3c 100644 --- a/hack/loadtest/README.md +++ b/hack/loadtest/README.md @@ -27,7 +27,7 @@ Create any resources you would like to place and/or a crp file to use. > > group: apiextensions.k8s.io > kind: CustomResourceDefinition -> name: clonesets.apps.kruise.io +> name: testresources.test.kubernetes-fleet.io > version: v1 - `max-current-placement`: The number of current placement load. Default value is `20`. @@ -36,7 +36,7 @@ Create any resources you would like to place and/or a crp file to use. - `poll-interval-millisecond`: The poll interval for verification (in milli-second). Default value is `250`. - `use-test-resources`: Boolean to include all test resources in the test. Default value is `false`. > **_NOTE:_** If this option is true, the test will create resources and add them to the crp for them to be placed. The following resources are added: -> `Namespace` that contains all the resources, `PodDisruptionBudget`, 2 `ConfigMap`'s, `Secret`, `Service`, `Cloneset`, `Role`, and `RoleBinding`. +> `Namespace` that contains all the resources, `PodDisruptionBudget`, 2 `ConfigMap`'s, `Secret`, `Service`, `TestResource`, `Role`, and `RoleBinding`. > If this option is false, the test will only use the resources specified in the crp file. ### Run the Load Test: diff --git a/hack/loadtest/manifests/test-cloneset.yaml b/hack/loadtest/manifests/test-cloneset.yaml deleted file mode 100644 index ef6c5efc5..000000000 --- a/hack/loadtest/manifests/test-cloneset.yaml +++ /dev/null @@ -1,25 +0,0 @@ -apiVersion: apps.kruise.io/v1alpha1 -kind: CloneSet -metadata: - name: guestbook-clone - namespace: app -spec: - replicas: 20 - selector: - matchLabels: - app.kubernetes.io/name: guestbook-clone - template: - metadata: - labels: - app.kubernetes.io/name: guestbook-clone - spec: - containers: - - name: guestbook - image: openkruise/guestbook:v1 - imagePullPolicy: Always - ports: - - name: http-server - containerPort: 3000 - updateStrategy: - type: InPlaceIfPossible - maxUnavailable: 3 \ No newline at end of file diff --git a/hack/loadtest/manifests/test-resource.yaml b/hack/loadtest/manifests/test-resource.yaml new file mode 100644 index 000000000..8eb8a2170 --- /dev/null +++ b/hack/loadtest/manifests/test-resource.yaml @@ -0,0 +1,10 @@ +apiVersion: test.kubernetes-fleet.io/v1alpha1 +kind: TestResource +metadata: + name: random-test-resource + namespace: app +spec: + foo: foo1 + items: + - a + - b \ No newline at end of file diff --git a/hack/loadtest/manifests/test_clonesets_crd.yaml b/hack/loadtest/manifests/test_clonesets_crd.yaml deleted file mode 100644 index 747fbc045..000000000 --- a/hack/loadtest/manifests/test_clonesets_crd.yaml +++ /dev/null @@ -1,506 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.7.0 - labels: - fleet.azure.com/name: test-placement - creationTimestamp: null - name: clonesets.apps.kruise.io -spec: - group: apps.kruise.io - names: - kind: CloneSet - listKind: CloneSetList - plural: clonesets - shortNames: - - clone - singular: cloneset - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: The desired number of pods. - jsonPath: .spec.replicas - name: DESIRED - type: integer - - description: The number of pods updated. - jsonPath: .status.updatedReplicas - name: UPDATED - type: integer - - description: The number of pods updated and ready. - jsonPath: .status.updatedReadyReplicas - name: UPDATED_READY - type: integer - - description: The number of pods ready. - jsonPath: .status.readyReplicas - name: READY - type: integer - - description: The number of currently all pods. - jsonPath: .status.replicas - name: TOTAL - type: integer - - description: CreationTimestamp is a timestamp representing the server time when - this object was created. It is not guaranteed to be set in happens-before - order across separate operations. Clients may not set this value. It is represented - in RFC3339 form and is in UTC. - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - description: The containers of currently cloneset. - jsonPath: .spec.template.spec.containers[*].name - name: CONTAINERS - priority: 1 - type: string - - description: The images of currently cloneset. - jsonPath: .spec.template.spec.containers[*].image - name: IMAGES - priority: 1 - type: string - - description: The selector of currently cloneset. - jsonPath: .status.labelSelector - name: SELECTOR - priority: 1 - type: string - name: v1alpha1 - schema: - openAPIV3Schema: - description: CloneSet is the Schema for the clonesets API - 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: CloneSetSpec defines the desired state of CloneSet - properties: - lifecycle: - description: Lifecycle defines the lifecycle hooks for Pods pre-delete, - in-place update. - properties: - inPlaceUpdate: - description: InPlaceUpdate is the hook before Pod to update and - after Pod has been updated. - properties: - finalizersHandler: - items: - type: string - type: array - labelsHandler: - additionalProperties: - type: string - type: object - markPodNotReady: - description: 'MarkPodNotReady = true means: - Pod will be - set to ''NotReady'' at preparingDelete/preparingUpdate state. - - Pod will be restored to ''Ready'' at Updated state if - it was set to ''NotReady'' at preparingUpdate state. Default - to false.' - type: boolean - type: object - preDelete: - description: PreDelete is the hook before Pod to be deleted. - properties: - finalizersHandler: - items: - type: string - type: array - labelsHandler: - additionalProperties: - type: string - type: object - markPodNotReady: - description: 'MarkPodNotReady = true means: - Pod will be - set to ''NotReady'' at preparingDelete/preparingUpdate state. - - Pod will be restored to ''Ready'' at Updated state if - it was set to ''NotReady'' at preparingUpdate state. Default - to false.' - type: boolean - type: object - type: object - minReadySeconds: - description: Minimum number of seconds for which a newly created pod - should be ready without any of its container crashing, for it to - be considered available. Defaults to 0 (pod will be considered available - as soon as it is ready) - format: int32 - type: integer - replicas: - description: Replicas is the desired number of replicas of the given - Template. These are replicas in the sense that they are instantiations - of the same Template. If unspecified, defaults to 1. - format: int32 - type: integer - revisionHistoryLimit: - description: RevisionHistoryLimit is the maximum number of revisions - that will be maintained in the CloneSet's revision history. The - revision history consists of all revisions not represented by a - currently applied CloneSetSpec version. The default value is 10. - format: int32 - type: integer - scaleStrategy: - description: ScaleStrategy indicates the ScaleStrategy that will be - employed to create and delete Pods in the CloneSet. - properties: - maxUnavailable: - anyOf: - - type: integer - - type: string - description: The maximum number of pods that can be unavailable - for scaled pods. This field can control the changes rate of - replicas for CloneSet so as to minimize the impact for users' - service. The scale will fail if the number of unavailable pods - were greater than this MaxUnavailable at scaling up. MaxUnavailable - works only when scaling up. - x-kubernetes-int-or-string: true - podsToDelete: - description: PodsToDelete is the names of Pod should be deleted. - Note that this list will be truncated for non-existing pod names. - items: - type: string - type: array - type: object - selector: - description: 'Selector is a label query over pods that should match - the replica count. It must match the pod template''s labels. More - info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors' - 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 - template: - description: Template describes the pods that will be created. - x-kubernetes-preserve-unknown-fields: true - updateStrategy: - description: UpdateStrategy indicates the UpdateStrategy that will - be employed to update Pods in the CloneSet when a revision is made - to Template. - properties: - inPlaceUpdateStrategy: - description: InPlaceUpdateStrategy contains strategies for in-place - update. - properties: - gracePeriodSeconds: - description: GracePeriodSeconds is the timespan between set - Pod status to not-ready and update images in Pod spec when - in-place update a Pod. - format: int32 - type: integer - type: object - maxSurge: - anyOf: - - type: integer - - type: string - description: 'The maximum number of pods that can be scheduled - above the desired replicas during update or specified delete. - Value can be an absolute number (ex: 5) or a percentage of desired - pods (ex: 10%). Absolute number is calculated from percentage - by rounding up. Defaults to 0.' - x-kubernetes-int-or-string: true - maxUnavailable: - anyOf: - - type: integer - - type: string - description: 'The maximum number of pods that can be unavailable - during update or scale. Value can be an absolute number (ex: - 5) or a percentage of desired pods (ex: 10%). Absolute number - is calculated from percentage by rounding up by default. When - maxSurge > 0, absolute number is calculated from percentage - by rounding down. Defaults to 20%.' - x-kubernetes-int-or-string: true - partition: - anyOf: - - type: integer - - type: string - description: 'Partition is the desired number of pods in old revisions. - Value can be an absolute number (ex: 5) or a percentage of desired - pods (ex: 10%). Absolute number is calculated from percentage - by rounding up by default. It means when partition is set during - pods updating, (replicas - partition value) number of pods will - be updated. Default value is 0.' - x-kubernetes-int-or-string: true - paused: - description: Paused indicates that the CloneSet is paused. Default - value is false - type: boolean - priorityStrategy: - description: Priorities are the rules for calculating the priority - of updating pods. Each pod to be updated, will pass through - these terms and get a sum of weights. - properties: - orderPriority: - description: 'Order priority terms, pods will be sorted by - the value of orderedKey. For example: ``` orderPriority: - - orderedKey: key1 - orderedKey: key2 ``` First, all pods - which have key1 in labels will be sorted by the value of - key1. Then, the left pods which have no key1 but have key2 - in labels will be sorted by the value of key2 and put behind - those pods have key1.' - items: - description: UpdatePriorityOrder defines order priority. - properties: - orderedKey: - description: Calculate priority by value of this key. - Values of this key, will be sorted by GetInt(val). - GetInt method will find the last int in value, such - as getting 5 in value '5', getting 10 in value 'sts-10'. - type: string - required: - - orderedKey - type: object - type: array - weightPriority: - description: Weight priority terms, pods will be sorted by - the sum of all terms weight. - items: - description: UpdatePriorityWeightTerm defines weight priority. - properties: - matchSelector: - description: MatchSelector is used to select by pod's - labels. - 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 - weight: - description: Weight associated with matching the corresponding - matchExpressions, in the range 1-100. - format: int32 - type: integer - required: - - matchSelector - - weight - type: object - type: array - type: object - scatterStrategy: - description: ScatterStrategy defines the scatter rules to make - pods been scattered when update. This will avoid pods with the - same key-value to be updated in one batch. - Note that pods - will be scattered after priority sort. So, although priority - strategy and scatter strategy can be applied together, we suggest - to use either one of them. - If scatterStrategy is used, we - suggest to just use one term. Otherwise, the update order can - be hard to understand. - items: - properties: - key: - type: string - value: - type: string - required: - - key - - value - type: object - type: array - type: - description: Type indicates the type of the CloneSetUpdateStrategy. - Default is ReCreate. - type: string - type: object - volumeClaimTemplates: - description: VolumeClaimTemplates is a list of claims that pods are - allowed to reference. Note that PVC will be deleted when its pod - has been deleted. - x-kubernetes-preserve-unknown-fields: true - required: - - selector - - template - type: object - status: - description: CloneSetStatus defines the observed state of CloneSet - properties: - availableReplicas: - description: AvailableReplicas is the number of Pods created by the - CloneSet controller that have a Ready Condition for at least minReadySeconds. - format: int32 - type: integer - collisionCount: - description: CollisionCount is the count of hash collisions for the - CloneSet. The CloneSet controller uses this field as a collision - avoidance mechanism when it needs to create the name for the newest - ControllerRevision. - format: int32 - type: integer - conditions: - description: Conditions represents the latest available observations - of a CloneSet's current state. - items: - description: CloneSetCondition describes the state of a CloneSet - at a certain point. - properties: - lastTransitionTime: - description: Last time the condition transitioned from one status - to another. - format: date-time - type: string - message: - description: A human readable message indicating details about - the transition. - type: string - reason: - description: The reason for the condition's last transition. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: Type of CloneSet condition. - type: string - required: - - status - - type - type: object - type: array - currentRevision: - description: currentRevision, if not empty, indicates the current - revision version of the CloneSet. - type: string - expectedUpdatedReplicas: - description: ExpectedUpdatedReplicas is the number of Pods that should - be updated by CloneSet controller. This field is calculated via - Replicas - Partition. - format: int32 - type: integer - labelSelector: - description: LabelSelector is label selectors for query over pods - that should match the replica count used by HPA. - type: string - observedGeneration: - description: ObservedGeneration is the most recent generation observed - for this CloneSet. It corresponds to the CloneSet's generation, - which is updated on mutation by the API Server. - format: int64 - type: integer - readyReplicas: - description: ReadyReplicas is the number of Pods created by the CloneSet - controller that have a Ready Condition. - format: int32 - type: integer - replicas: - description: Replicas is the number of Pods created by the CloneSet - controller. - format: int32 - type: integer - updateRevision: - description: UpdateRevision, if not empty, indicates the latest revision - of the CloneSet. - type: string - updatedReadyReplicas: - description: UpdatedReadyReplicas is the number of Pods created by - the CloneSet controller from the CloneSet version indicated by updateRevision - and have a Ready Condition. - format: int32 - type: integer - updatedReplicas: - description: UpdatedReplicas is the number of Pods created by the - CloneSet controller from the CloneSet version indicated by updateRevision. - format: int32 - type: integer - required: - - availableReplicas - - readyReplicas - - replicas - - updatedReadyReplicas - - updatedReplicas - type: object - type: object - served: true - storage: true - subresources: - scale: - labelSelectorPath: .status.labelSelector - specReplicasPath: .spec.replicas - statusReplicasPath: .status.replicas - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] diff --git a/hack/loadtest/manifests/test_testresources_crd.yaml b/hack/loadtest/manifests/test_testresources_crd.yaml new file mode 100644 index 000000000..d8e762069 --- /dev/null +++ b/hack/loadtest/manifests/test_testresources_crd.yaml @@ -0,0 +1,111 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + labels: + fleet.azure.com/name: test-placement + annotations: + controller-gen.kubebuilder.io/version: v0.15.0 + name: testresources.test.kubernetes-fleet.io +spec: + group: test.kubernetes-fleet.io + names: + kind: TestResource + listKind: TestResourceList + plural: testresources + singular: testresource + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: TestResource is the Schema for the testresources API + 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: TestResourceSpec defines the desired state of TestResource + properties: + bar: + type: string + foo: + type: string + items: + items: + type: string + type: array + labelSelector: + description: |- + A label selector is a label query over a set of resources. The result of matchLabels and + matchExpressions are ANDed. An empty label selector matches all objects. A null + label selector matches no objects. + 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 + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + 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 + type: object + status: + description: TestResourceStatus defines the observed state of TestResource + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} diff --git a/hack/loadtest/test-crp.yaml b/hack/loadtest/test-crp.yaml index 974c99f47..8228c2814 100644 --- a/hack/loadtest/test-crp.yaml +++ b/hack/loadtest/test-crp.yaml @@ -6,7 +6,7 @@ spec: resourceSelectors: - group: apiextensions.k8s.io kind: CustomResourceDefinition - name: clonesets.apps.kruise.io + name: testresources.test.kubernetes-fleet.io version: v1 strategy: type: RollingUpdate diff --git a/hack/loadtest/test-crp1.yaml b/hack/loadtest/test-crp1.yaml index b85421133..754607cb0 100644 --- a/hack/loadtest/test-crp1.yaml +++ b/hack/loadtest/test-crp1.yaml @@ -6,7 +6,7 @@ spec: resourceSelectors: - group: apiextensions.k8s.io kind: CustomResourceDefinition - name: clonesets.apps.kruise.io + name: testresources.test.kubernetes-fleet.io version: v1 policy: placementType: PickFixed diff --git a/hack/loadtest/test-crp2.yaml b/hack/loadtest/test-crp2.yaml index e2852f569..eb3d1f214 100644 --- a/hack/loadtest/test-crp2.yaml +++ b/hack/loadtest/test-crp2.yaml @@ -6,7 +6,7 @@ spec: resourceSelectors: - group: apiextensions.k8s.io kind: CustomResourceDefinition - name: clonesets.apps.kruise.io + name: testresources.test.kubernetes-fleet.io version: v1 policy: placementType: PickN diff --git a/hack/loadtest/test-crp3.yaml b/hack/loadtest/test-crp3.yaml index 083068b6e..efa5436e2 100644 --- a/hack/loadtest/test-crp3.yaml +++ b/hack/loadtest/test-crp3.yaml @@ -6,7 +6,7 @@ spec: resourceSelectors: - group: apiextensions.k8s.io kind: CustomResourceDefinition - name: clonesets.apps.kruise.io + name: testresources.test.kubernetes-fleet.io version: v1 policy: placementType: PickAll diff --git a/hack/loadtest/test-crp4.yaml b/hack/loadtest/test-crp4.yaml index 4a349d3a4..bceefc202 100644 --- a/hack/loadtest/test-crp4.yaml +++ b/hack/loadtest/test-crp4.yaml @@ -6,7 +6,7 @@ spec: resourceSelectors: - group: apiextensions.k8s.io kind: CustomResourceDefinition - name: clonesets.apps.kruise.io + name: testresources.test.kubernetes-fleet.io version: v1 policy: placementType: PickN diff --git a/hack/loadtest/util/help.go b/hack/loadtest/util/help.go index a0e039201..96edfbc57 100644 --- a/hack/loadtest/util/help.go +++ b/hack/loadtest/util/help.go @@ -82,7 +82,7 @@ func readObjFromFile(relativeFilePath string, namespaceName string) (*unstructur } func ApplyClusterScopeManifests(ctx context.Context, hubClient client.Client) error { - if err := applyObjectFromManifest(ctx, hubClient, "", "hack/loadtest/manifests/test_clonesets_crd.yaml"); err != nil { + if err := applyObjectFromManifest(ctx, hubClient, "", "hack/loadtest/manifests/test_testresources_crd.yaml"); err != nil { if !apierrors.IsAlreadyExists(err) { return err } @@ -120,7 +120,7 @@ func applyTestManifests(ctx context.Context, hubClient client.Client, namespaceN if err := applyObjectFromManifest(ctx, hubClient, namespaceName, "hack/loadtest/manifests/test-service.yaml"); err != nil { return err } - if err := applyObjectFromManifest(ctx, hubClient, namespaceName, "hack/loadtest/manifests/test-cloneset.yaml"); err != nil { + if err := applyObjectFromManifest(ctx, hubClient, namespaceName, "hack/loadtest/manifests/test-resource.yaml"); err != nil { return err } if err := applyObjectFromManifest(ctx, hubClient, namespaceName, "hack/loadtest/manifests/test-configmap-2.yaml"); err != nil { @@ -146,7 +146,7 @@ func deleteTestManifests(ctx context.Context, hubClient client.Client, namespace if err := deleteObjectFromManifest(ctx, hubClient, namespaceName, "hack/loadtest/manifests/test-service.yaml"); err != nil { return err } - if err := deleteObjectFromManifest(ctx, hubClient, namespaceName, "hack/loadtest/manifests/test-cloneset.yaml"); err != nil { + if err := deleteObjectFromManifest(ctx, hubClient, namespaceName, "hack/loadtest/manifests/test-resource.yaml"); err != nil { return err } if err := deleteObjectFromManifest(ctx, hubClient, namespaceName, "hack/loadtest/manifests/test-configmap-2.yaml"); err != nil { diff --git a/pkg/controllers/rollout/controller_integration_test.go b/pkg/controllers/rollout/controller_integration_test.go index 8e311f93e..e7bbdb45c 100644 --- a/pkg/controllers/rollout/controller_integration_test.go +++ b/pkg/controllers/rollout/controller_integration_test.go @@ -611,7 +611,7 @@ func generateResourceSnapshot(testCRPName string, resourceIndex int, isLatest bo }, } rawContents := [][]byte{ - testClonesetCRD, testNameSpace, testCloneset, testConfigMap, testPdb, + testResourceCRD, testNameSpace, testResource, testConfigMap, testPdb, } for _, rawContent := range rawContents { clusterResourceSnapshot.Spec.SelectedResources = append(clusterResourceSnapshot.Spec.SelectedResources, diff --git a/pkg/controllers/rollout/manifests/test-cloneset.yaml b/pkg/controllers/rollout/manifests/test-cloneset.yaml deleted file mode 100644 index ef6c5efc5..000000000 --- a/pkg/controllers/rollout/manifests/test-cloneset.yaml +++ /dev/null @@ -1,25 +0,0 @@ -apiVersion: apps.kruise.io/v1alpha1 -kind: CloneSet -metadata: - name: guestbook-clone - namespace: app -spec: - replicas: 20 - selector: - matchLabels: - app.kubernetes.io/name: guestbook-clone - template: - metadata: - labels: - app.kubernetes.io/name: guestbook-clone - spec: - containers: - - name: guestbook - image: openkruise/guestbook:v1 - imagePullPolicy: Always - ports: - - name: http-server - containerPort: 3000 - updateStrategy: - type: InPlaceIfPossible - maxUnavailable: 3 \ No newline at end of file diff --git a/pkg/controllers/rollout/manifests/test-resource.yaml b/pkg/controllers/rollout/manifests/test-resource.yaml new file mode 100644 index 000000000..8eb8a2170 --- /dev/null +++ b/pkg/controllers/rollout/manifests/test-resource.yaml @@ -0,0 +1,10 @@ +apiVersion: test.kubernetes-fleet.io/v1alpha1 +kind: TestResource +metadata: + name: random-test-resource + namespace: app +spec: + foo: foo1 + items: + - a + - b \ No newline at end of file diff --git a/pkg/controllers/rollout/manifests/test_clonesets_crd.yaml b/pkg/controllers/rollout/manifests/test_clonesets_crd.yaml deleted file mode 100644 index 1cb0b93c2..000000000 --- a/pkg/controllers/rollout/manifests/test_clonesets_crd.yaml +++ /dev/null @@ -1,498 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.7.0 - labels: - fleet.azure.com/name: test-placement - name: clonesets.apps.kruise.io -spec: - group: apps.kruise.io - names: - kind: CloneSet - listKind: CloneSetList - plural: clonesets - shortNames: - - clone - singular: cloneset - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: The desired number of pods. - jsonPath: .spec.replicas - name: DESIRED - type: integer - - description: The number of pods updated. - jsonPath: .status.updatedReplicas - name: UPDATED - type: integer - - description: The number of pods updated and ready. - jsonPath: .status.updatedReadyReplicas - name: UPDATED_READY - type: integer - - description: The number of pods ready. - jsonPath: .status.readyReplicas - name: READY - type: integer - - description: The number of currently all pods. - jsonPath: .status.replicas - name: TOTAL - type: integer - - description: CreationTimestamp is a timestamp representing the server time when - this object was created. It is not guaranteed to be set in happens-before - order across separate operations. Clients may not set this value. It is represented - in RFC3339 form and is in UTC. - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - description: The containers of currently cloneset. - jsonPath: .spec.template.spec.containers[*].name - name: CONTAINERS - priority: 1 - type: string - - description: The images of currently cloneset. - jsonPath: .spec.template.spec.containers[*].image - name: IMAGES - priority: 1 - type: string - - description: The selector of currently cloneset. - jsonPath: .status.labelSelector - name: SELECTOR - priority: 1 - type: string - name: v1alpha1 - schema: - openAPIV3Schema: - description: CloneSet is the Schema for the clonesets API - 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: CloneSetSpec defines the desired state of CloneSet - properties: - lifecycle: - description: Lifecycle defines the lifecycle hooks for Pods pre-delete, - in-place update. - properties: - inPlaceUpdate: - description: InPlaceUpdate is the hook before Pod to update and - after Pod has been updated. - properties: - finalizersHandler: - items: - type: string - type: array - labelsHandler: - additionalProperties: - type: string - type: object - markPodNotReady: - description: 'MarkPodNotReady = true means: - Pod will be - set to ''NotReady'' at preparingDelete/preparingUpdate state. - - Pod will be restored to ''Ready'' at Updated state if - it was set to ''NotReady'' at preparingUpdate state. Default - to false.' - type: boolean - type: object - preDelete: - description: PreDelete is the hook before Pod to be deleted. - properties: - finalizersHandler: - items: - type: string - type: array - labelsHandler: - additionalProperties: - type: string - type: object - markPodNotReady: - description: 'MarkPodNotReady = true means: - Pod will be - set to ''NotReady'' at preparingDelete/preparingUpdate state. - - Pod will be restored to ''Ready'' at Updated state if - it was set to ''NotReady'' at preparingUpdate state. Default - to false.' - type: boolean - type: object - type: object - minReadySeconds: - description: Minimum number of seconds for which a newly created pod - should be ready without any of its container crashing, for it to - be considered available. Defaults to 0 (pod will be considered available - as soon as it is ready) - format: int32 - type: integer - replicas: - description: Replicas is the desired number of replicas of the given - Template. These are replicas in the sense that they are instantiations - of the same Template. If unspecified, defaults to 1. - format: int32 - type: integer - revisionHistoryLimit: - description: RevisionHistoryLimit is the maximum number of revisions - that will be maintained in the CloneSet's revision history. The - revision history consists of all revisions not represented by a - currently applied CloneSetSpec version. The default value is 10. - format: int32 - type: integer - scaleStrategy: - description: ScaleStrategy indicates the ScaleStrategy that will be - employed to create and delete Pods in the CloneSet. - properties: - maxUnavailable: - anyOf: - - type: integer - - type: string - description: The maximum number of pods that can be unavailable - for scaled pods. This field can control the changes rate of - replicas for CloneSet so as to minimize the impact for users' - service. The scale will fail if the number of unavailable pods - were greater than this MaxUnavailable at scaling up. MaxUnavailable - works only when scaling up. - x-kubernetes-int-or-string: true - podsToDelete: - description: PodsToDelete is the names of Pod should be deleted. - Note that this list will be truncated for non-existing pod names. - items: - type: string - type: array - type: object - selector: - description: 'Selector is a label query over pods that should match - the replica count. It must match the pod template''s labels. More - info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors' - 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 - template: - description: Template describes the pods that will be created. - x-kubernetes-preserve-unknown-fields: true - updateStrategy: - description: UpdateStrategy indicates the UpdateStrategy that will - be employed to update Pods in the CloneSet when a revision is made - to Template. - properties: - inPlaceUpdateStrategy: - description: InPlaceUpdateStrategy contains strategies for in-place - update. - properties: - gracePeriodSeconds: - description: GracePeriodSeconds is the timespan between set - Pod status to not-ready and update images in Pod spec when - in-place update a Pod. - format: int32 - type: integer - type: object - maxSurge: - anyOf: - - type: integer - - type: string - description: 'The maximum number of pods that can be scheduled - above the desired replicas during update or specified delete. - Value can be an absolute number (ex: 5) or a percentage of desired - pods (ex: 10%). Absolute number is calculated from percentage - by rounding up. Defaults to 0.' - x-kubernetes-int-or-string: true - maxUnavailable: - anyOf: - - type: integer - - type: string - description: 'The maximum number of pods that can be unavailable - during update or scale. Value can be an absolute number (ex: - 5) or a percentage of desired pods (ex: 10%). Absolute number - is calculated from percentage by rounding up by default. When - maxSurge > 0, absolute number is calculated from percentage - by rounding down. Defaults to 20%.' - x-kubernetes-int-or-string: true - partition: - anyOf: - - type: integer - - type: string - description: 'Partition is the desired number of pods in old revisions. - Value can be an absolute number (ex: 5) or a percentage of desired - pods (ex: 10%). Absolute number is calculated from percentage - by rounding up by default. It means when partition is set during - pods updating, (replicas - partition value) number of pods will - be updated. Default value is 0.' - x-kubernetes-int-or-string: true - paused: - description: Paused indicates that the CloneSet is paused. Default - value is false - type: boolean - priorityStrategy: - description: Priorities are the rules for calculating the priority - of updating pods. Each pod to be updated, will pass through - these terms and get a sum of weights. - properties: - orderPriority: - description: 'Order priority terms, pods will be sorted by - the value of orderedKey. For example: ``` orderPriority: - - orderedKey: key1 - orderedKey: key2 ``` First, all pods - which have key1 in labels will be sorted by the value of - key1. Then, the left pods which have no key1 but have key2 - in labels will be sorted by the value of key2 and put behind - those pods have key1.' - items: - description: UpdatePriorityOrder defines order priority. - properties: - orderedKey: - description: Calculate priority by value of this key. - Values of this key, will be sorted by GetInt(val). - GetInt method will find the last int in value, such - as getting 5 in value '5', getting 10 in value 'sts-10'. - type: string - required: - - orderedKey - type: object - type: array - weightPriority: - description: Weight priority terms, pods will be sorted by - the sum of all terms weight. - items: - description: UpdatePriorityWeightTerm defines weight priority. - properties: - matchSelector: - description: MatchSelector is used to select by pod's - labels. - 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 - weight: - description: Weight associated with matching the corresponding - matchExpressions, in the range 1-100. - format: int32 - type: integer - required: - - matchSelector - - weight - type: object - type: array - type: object - scatterStrategy: - description: ScatterStrategy defines the scatter rules to make - pods been scattered when update. This will avoid pods with the - same key-value to be updated in one batch. - Note that pods - will be scattered after priority sort. So, although priority - strategy and scatter strategy can be applied together, we suggest - to use either one of them. - If scatterStrategy is used, we - suggest to just use one term. Otherwise, the update order can - be hard to understand. - items: - properties: - key: - type: string - value: - type: string - required: - - key - - value - type: object - type: array - type: - description: Type indicates the type of the CloneSetUpdateStrategy. - Default is ReCreate. - type: string - type: object - volumeClaimTemplates: - description: VolumeClaimTemplates is a list of claims that pods are - allowed to reference. Note that PVC will be deleted when its pod - has been deleted. - x-kubernetes-preserve-unknown-fields: true - required: - - selector - - template - type: object - status: - description: CloneSetStatus defines the observed state of CloneSet - properties: - availableReplicas: - description: AvailableReplicas is the number of Pods created by the - CloneSet controller that have a Ready Condition for at least minReadySeconds. - format: int32 - type: integer - collisionCount: - description: CollisionCount is the count of hash collisions for the - CloneSet. The CloneSet controller uses this field as a collision - avoidance mechanism when it needs to create the name for the newest - ControllerRevision. - format: int32 - type: integer - conditions: - description: Conditions represents the latest available observations - of a CloneSet's current state. - items: - description: CloneSetCondition describes the state of a CloneSet - at a certain point. - properties: - lastTransitionTime: - description: Last time the condition transitioned from one status - to another. - format: date-time - type: string - message: - description: A human readable message indicating details about - the transition. - type: string - reason: - description: The reason for the condition's last transition. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: Type of CloneSet condition. - type: string - required: - - status - - type - type: object - type: array - currentRevision: - description: currentRevision, if not empty, indicates the current - revision version of the CloneSet. - type: string - expectedUpdatedReplicas: - description: ExpectedUpdatedReplicas is the number of Pods that should - be updated by CloneSet controller. This field is calculated via - Replicas - Partition. - format: int32 - type: integer - labelSelector: - description: LabelSelector is label selectors for query over pods - that should match the replica count used by HPA. - type: string - observedGeneration: - description: ObservedGeneration is the most recent generation observed - for this CloneSet. It corresponds to the CloneSet's generation, - which is updated on mutation by the API Server. - format: int64 - type: integer - readyReplicas: - description: ReadyReplicas is the number of Pods created by the CloneSet - controller that have a Ready Condition. - format: int32 - type: integer - replicas: - description: Replicas is the number of Pods created by the CloneSet - controller. - format: int32 - type: integer - updateRevision: - description: UpdateRevision, if not empty, indicates the latest revision - of the CloneSet. - type: string - updatedReadyReplicas: - description: UpdatedReadyReplicas is the number of Pods created by - the CloneSet controller from the CloneSet version indicated by updateRevision - and have a Ready Condition. - format: int32 - type: integer - updatedReplicas: - description: UpdatedReplicas is the number of Pods created by the - CloneSet controller from the CloneSet version indicated by updateRevision. - format: int32 - type: integer - required: - - availableReplicas - - readyReplicas - - replicas - - updatedReadyReplicas - - updatedReplicas - type: object - type: object - served: true - storage: true - subresources: - scale: - labelSelectorPath: .status.labelSelector - specReplicasPath: .spec.replicas - statusReplicasPath: .status.replicas diff --git a/pkg/controllers/rollout/manifests/test_testresources_crd.yaml b/pkg/controllers/rollout/manifests/test_testresources_crd.yaml new file mode 100644 index 000000000..d8e762069 --- /dev/null +++ b/pkg/controllers/rollout/manifests/test_testresources_crd.yaml @@ -0,0 +1,111 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + labels: + fleet.azure.com/name: test-placement + annotations: + controller-gen.kubebuilder.io/version: v0.15.0 + name: testresources.test.kubernetes-fleet.io +spec: + group: test.kubernetes-fleet.io + names: + kind: TestResource + listKind: TestResourceList + plural: testresources + singular: testresource + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: TestResource is the Schema for the testresources API + 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: TestResourceSpec defines the desired state of TestResource + properties: + bar: + type: string + foo: + type: string + items: + items: + type: string + type: array + labelSelector: + description: |- + A label selector is a label query over a set of resources. The result of matchLabels and + matchExpressions are ANDed. An empty label selector matches all objects. A null + label selector matches no objects. + 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 + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + 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 + type: object + status: + description: TestResourceStatus defines the observed state of TestResource + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} diff --git a/pkg/controllers/rollout/suite_test.go b/pkg/controllers/rollout/suite_test.go index 09a54198a..315d41d26 100644 --- a/pkg/controllers/rollout/suite_test.go +++ b/pkg/controllers/rollout/suite_test.go @@ -15,7 +15,6 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - kruisev1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1" "k8s.io/apimachinery/pkg/util/yaml" "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/rest" @@ -41,7 +40,7 @@ var ( cancel context.CancelFunc // pre loaded test manifests - testClonesetCRD, testNameSpace, testCloneset, testConfigMap, testPdb []byte + testResourceCRD, testNameSpace, testResource, testConfigMap, testPdb []byte ) func TestAPIs(t *testing.T) { @@ -75,7 +74,6 @@ var _ = BeforeSuite(func() { By("Set all the customized scheme") Expect(fleetv1beta1.AddToScheme(scheme.Scheme)).Should(Succeed()) Expect(workv1alpha1.AddToScheme(scheme.Scheme)).Should(Succeed()) - Expect(kruisev1alpha1.AddToScheme(scheme.Scheme)).Should(Succeed()) Expect(placementv1alpha1.AddToScheme(scheme.Scheme)).Should(Succeed()) By("starting the controller manager") @@ -119,10 +117,10 @@ var _ = AfterSuite(func() { }) func readTestManifests() { - By("Read testCloneset CRD") - rawByte, err := os.ReadFile("manifests/test_clonesets_crd.yaml") + By("Read testResource CRD") + rawByte, err := os.ReadFile("manifests/test_testresources_crd.yaml") Expect(err).Should(Succeed()) - testClonesetCRD, err = yaml.ToJSON(rawByte) + testResourceCRD, err = yaml.ToJSON(rawByte) Expect(err).Should(Succeed()) By("Read namespace") @@ -131,10 +129,10 @@ func readTestManifests() { testNameSpace, err = yaml.ToJSON(rawByte) Expect(err).Should(Succeed()) - By("Read clonesetCR") - rawByte, err = os.ReadFile("manifests/test-cloneset.yaml") + By("Read testResource CR") + rawByte, err = os.ReadFile("manifests/test-resource.yaml") Expect(err).Should(Succeed()) - testCloneset, err = yaml.ToJSON(rawByte) + testResource, err = yaml.ToJSON(rawByte) Expect(err).Should(Succeed()) By("Read testConfigMap resource") diff --git a/pkg/controllers/work/applied_work_syncer_integration_test.go b/pkg/controllers/work/applied_work_syncer_integration_test.go index 1c5f61cc1..0cc21a387 100644 --- a/pkg/controllers/work/applied_work_syncer_integration_test.go +++ b/pkg/controllers/work/applied_work_syncer_integration_test.go @@ -27,7 +27,6 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - kruisev1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -36,6 +35,7 @@ import ( utilrand "k8s.io/apimachinery/pkg/util/rand" fleetv1beta1 "go.goms.io/fleet/apis/placement/v1beta1" + testv1alpha1 "go.goms.io/fleet/test/apis/v1alpha1" ) var _ = Describe("Work Status Reconciler", func() { @@ -228,22 +228,20 @@ var _ = Describe("Work Status Reconciler", func() { Expect(len(appliedWork.Status.AppliedResources)).Should(Equal(2)) By("replace configMap with a bad object from the work") - broadcastJob := &kruisev1alpha1.BroadcastJob{ + testResource := &testv1alpha1.TestResource{ TypeMeta: metav1.TypeMeta{ - APIVersion: kruisev1alpha1.SchemeGroupVersion.String(), - Kind: "BroadcastJob", + APIVersion: testv1alpha1.GroupVersion.String(), + Kind: "TestResource", }, ObjectMeta: metav1.ObjectMeta{ - Name: "broadcastjob-" + utilrand.String(5), - Namespace: testWorkNamespace, - }, - Spec: kruisev1alpha1.BroadcastJobSpec{ - Paused: true, + Name: "testresource-" + utilrand.String(5), + // to ensure the resource is not applied. + Namespace: "random-test-namespace", }, } currentWork.Spec.Workload.Manifests = []fleetv1beta1.Manifest{ { - RawExtension: runtime.RawExtension{Object: broadcastJob}, + RawExtension: runtime.RawExtension{Object: testResource}, }, } Expect(k8sClient.Update(context.Background(), currentWork)).Should(Succeed()) diff --git a/pkg/controllers/work/apply_controller_integration_test.go b/pkg/controllers/work/apply_controller_integration_test.go index 0f0651b8c..2b9f41f2e 100644 --- a/pkg/controllers/work/apply_controller_integration_test.go +++ b/pkg/controllers/work/apply_controller_integration_test.go @@ -30,18 +30,16 @@ import ( "github.com/google/go-cmp/cmp" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - kruisev1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/intstr" utilrand "k8s.io/apimachinery/pkg/util/rand" - "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" fleetv1beta1 "go.goms.io/fleet/apis/placement/v1beta1" + testv1alpha1 "go.goms.io/fleet/test/apis/v1alpha1" "go.goms.io/fleet/test/utils/controller" ) @@ -347,19 +345,21 @@ var _ = Describe("Work Controller", func() { }) It("Should pick up the crd change correctly", func() { - cloneName := "testcloneset" - cloneNamespace := defaultNS - cloneSet := &kruisev1alpha1.CloneSet{ + testResourceName := "test-resource-name" + testResourceNamespace := defaultNS + testResource := &testv1alpha1.TestResource{ TypeMeta: metav1.TypeMeta{ - APIVersion: kruisev1alpha1.SchemeGroupVersion.String(), - Kind: "CloneSet", + APIVersion: testv1alpha1.GroupVersion.String(), + Kind: "TestResource", }, ObjectMeta: metav1.ObjectMeta{ - Name: cloneName, - Namespace: cloneNamespace, + Name: testResourceName, + Namespace: testResourceNamespace, }, - Spec: kruisev1alpha1.CloneSetSpec{ - Selector: &metav1.LabelSelector{ + Spec: testv1alpha1.TestResourceSpec{ + Foo: "foo", + Bar: "bar", + LabelSelector: &metav1.LabelSelector{ MatchExpressions: []metav1.LabelSelectorRequirement{ { Key: "region", @@ -376,23 +376,23 @@ var _ = Describe("Work Controller", func() { } By("create the work") - work = createWorkWithManifest(testWorkNamespace, cloneSet) + work = createWorkWithManifest(testWorkNamespace, testResource) err := k8sClient.Create(context.Background(), work) Expect(err).ToNot(HaveOccurred()) By("wait for the work to be applied") waitForWorkToBeAvailable(work.GetName(), work.GetNamespace()) - By("Check applied CloneSet") - var appliedCloneSet kruisev1alpha1.CloneSet - Expect(k8sClient.Get(context.Background(), types.NamespacedName{Name: cloneName, Namespace: cloneNamespace}, &appliedCloneSet)).Should(Succeed()) + By("Check applied TestResource") + var appliedTestResource testv1alpha1.TestResource + Expect(k8sClient.Get(context.Background(), types.NamespacedName{Name: testResourceName, Namespace: testResourceNamespace}, &appliedTestResource)).Should(Succeed()) - By("verify the CloneSet spec") - Expect(cmp.Diff(appliedCloneSet.Spec, cloneSet.Spec)).Should(BeEmpty()) + By("verify the TestResource spec") + Expect(cmp.Diff(appliedTestResource.Spec, testResource.Spec)).Should(BeEmpty()) - By("Modify and update the applied CloneSet") + By("Modify and update the applied TestResource") // add/modify/remove a match - appliedCloneSet.Spec.Selector.MatchExpressions = []metav1.LabelSelectorRequirement{ + appliedTestResource.Spec.LabelSelector.MatchExpressions = []metav1.LabelSelectorRequirement{ { Key: "region", Operator: metav1.LabelSelectorOpNotIn, @@ -403,47 +403,43 @@ var _ = Describe("Work Controller", func() { Operator: metav1.LabelSelectorOpExists, }, } - appliedCloneSet.Spec.ScaleStrategy.PodsToDelete = []string{"a", "b"} - appliedCloneSet.Spec.MinReadySeconds = 10 - Expect(k8sClient.Update(context.Background(), &appliedCloneSet)).Should(Succeed()) - - By("Verify applied CloneSet modified") - var modifiedCloneSet kruisev1alpha1.CloneSet - Expect(k8sClient.Get(context.Background(), types.NamespacedName{Name: cloneName, Namespace: cloneNamespace}, &modifiedCloneSet)).Should(Succeed()) - Expect(cmp.Diff(appliedCloneSet.Spec, modifiedCloneSet.Spec)).Should(BeEmpty()) - - By("Modify the cloneset") - cloneSet.Spec.Selector.MatchExpressions = []metav1.LabelSelectorRequirement{ + appliedTestResource.Spec.Items = []string{"a", "b"} + appliedTestResource.Spec.Foo = "foo1" + appliedTestResource.Spec.Bar = "bar1" + Expect(k8sClient.Update(context.Background(), &appliedTestResource)).Should(Succeed()) + + By("Verify applied TestResource modified") + var modifiedTestResource testv1alpha1.TestResource + Expect(k8sClient.Get(context.Background(), types.NamespacedName{Name: testResourceName, Namespace: testResourceNamespace}, &modifiedTestResource)).Should(Succeed()) + Expect(cmp.Diff(appliedTestResource.Spec, modifiedTestResource.Spec)).Should(BeEmpty()) + + By("Modify the TestResource") + testResource.Spec.LabelSelector.MatchExpressions = []metav1.LabelSelectorRequirement{ { Key: "region", Operator: metav1.LabelSelectorOpNotIn, Values: []string{"us", "asia", "eu"}, }, } - cloneSet.Spec.Replicas = ptr.To(int32(10)) - cloneSet.Spec.MinReadySeconds = 1 - maxuavail := intstr.FromInt(10) - cloneSet.Spec.ScaleStrategy.MaxUnavailable = &maxuavail + testResource.Spec.Foo = "foo2" + testResource.Spec.Bar = "bar2" By("update the work") resultWork := waitForWorkToApply(work.GetName(), work.GetNamespace()) - rawCM, err := json.Marshal(cloneSet) + rawTR, err := json.Marshal(testResource) Expect(err).Should(Succeed()) - resultWork.Spec.Workload.Manifests[0].Raw = rawCM + resultWork.Spec.Workload.Manifests[0].Raw = rawTR Expect(k8sClient.Update(context.Background(), resultWork)).Should(Succeed()) waitForWorkToApply(work.GetName(), work.GetNamespace()) - By("Get the last applied cloneset") - Expect(k8sClient.Get(context.Background(), types.NamespacedName{Name: cloneName, Namespace: cloneNamespace}, &appliedCloneSet)).Should(Succeed()) + By("Get the last applied TestResource") + Expect(k8sClient.Get(context.Background(), types.NamespacedName{Name: testResourceName, Namespace: testResourceNamespace}, &appliedTestResource)).Should(Succeed()) - By("Check the cloneset spec, its an overide for arrays") - expectStrategy := kruisev1alpha1.CloneSetScaleStrategy{ - PodsToDelete: []string{"a", "b"}, - MaxUnavailable: &maxuavail, - } - Expect(cmp.Diff(appliedCloneSet.Spec.ScaleStrategy, expectStrategy)).Should(BeEmpty()) - Expect(cmp.Diff(appliedCloneSet.Spec.Selector, cloneSet.Spec.Selector)).Should(BeEmpty()) - Expect(cmp.Diff(appliedCloneSet.Spec.Replicas, ptr.To(int32(10)))).Should(BeEmpty()) - Expect(cmp.Diff(appliedCloneSet.Spec.MinReadySeconds, int32(1))).Should(BeEmpty()) + By("Check the TestResource spec, its an override for arrays") + expectedItems := []string{"a", "b"} + Expect(cmp.Diff(appliedTestResource.Spec.Items, expectedItems)).Should(BeEmpty()) + Expect(cmp.Diff(appliedTestResource.Spec.LabelSelector, testResource.Spec.LabelSelector)).Should(BeEmpty()) + Expect(cmp.Diff(appliedTestResource.Spec.Foo, "foo2")).Should(BeEmpty()) + Expect(cmp.Diff(appliedTestResource.Spec.Bar, "bar2")).Should(BeEmpty()) Expect(k8sClient.Delete(ctx, work)).Should(Succeed(), "Failed to deleted the work") }) @@ -563,26 +559,27 @@ var _ = Describe("Work Controller", func() { }) It("Check that failed to apply manifest has the proper identification", func() { - broadcastName := "testfail" - namespace := defaultNS - broadcastJob := &kruisev1alpha1.BroadcastJob{ + testResourceName := "test-resource-name-failed" + // to ensure apply fails. + namespace := "random-test-namespace" + testResource := &testv1alpha1.TestResource{ TypeMeta: metav1.TypeMeta{ - APIVersion: kruisev1alpha1.SchemeGroupVersion.String(), - Kind: "BroadcastJob", + APIVersion: testv1alpha1.GroupVersion.String(), + Kind: "TestResource", }, ObjectMeta: metav1.ObjectMeta{ - Name: broadcastName, + Name: testResourceName, Namespace: namespace, }, - Spec: kruisev1alpha1.BroadcastJobSpec{ - Paused: true, + Spec: testv1alpha1.TestResourceSpec{ + Foo: "foo", }, } - work = createWorkWithManifest(testWorkNamespace, broadcastJob) + work = createWorkWithManifest(testWorkNamespace, testResource) err := k8sClient.Create(context.Background(), work) Expect(err).ToNot(HaveOccurred()) - By("wait for the work to be applied") + By("wait for the work to be applied, apply condition set to failed") var resultWork fleetv1beta1.Work Eventually(func() bool { err := k8sClient.Get(context.Background(), types.NamespacedName{Name: work.Name, Namespace: work.GetNamespace()}, &resultWork) @@ -600,11 +597,12 @@ var _ = Describe("Work Controller", func() { }, timeout, interval).Should(BeTrue()) expectedResourceID := fleetv1beta1.WorkResourceIdentifier{ Ordinal: 0, - Group: "apps.kruise.io", - Version: "v1alpha1", - Kind: "BroadcastJob", - Namespace: broadcastJob.GetNamespace(), - Name: broadcastJob.GetName(), + Group: testv1alpha1.GroupVersion.Group, + Version: testv1alpha1.GroupVersion.Version, + Resource: "testresources", + Kind: testResource.Kind, + Namespace: testResource.GetNamespace(), + Name: testResource.GetName(), } Expect(cmp.Diff(resultWork.Status.ManifestConditions[0].Identifier, expectedResourceID)).Should(BeEmpty()) }) diff --git a/pkg/controllers/work/suite_test.go b/pkg/controllers/work/suite_test.go index 859b88397..eeb7bb683 100644 --- a/pkg/controllers/work/suite_test.go +++ b/pkg/controllers/work/suite_test.go @@ -31,7 +31,6 @@ import ( "github.com/go-logr/logr" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - kruisev1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/dynamic" @@ -46,6 +45,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/manager" fleetv1beta1 "go.goms.io/fleet/apis/placement/v1beta1" + testv1alpha1 "go.goms.io/fleet/test/apis/v1alpha1" ) // These tests use Ginkgo (BDD-style Go testing framework). Refer to @@ -159,7 +159,7 @@ var _ = BeforeSuite(func() { err = fleetv1beta1.AddToScheme(scheme.Scheme) Expect(err).NotTo(HaveOccurred()) - err = kruisev1alpha1.AddToScheme(scheme.Scheme) + err = testv1alpha1.AddToScheme(scheme.Scheme) Expect(err).NotTo(HaveOccurred()) opts := ctrl.Options{ Scheme: scheme.Scheme, diff --git a/pkg/controllers/workgenerator/controller_integration_test.go b/pkg/controllers/workgenerator/controller_integration_test.go index 9450c7da0..276c4cc0c 100644 --- a/pkg/controllers/workgenerator/controller_integration_test.go +++ b/pkg/controllers/workgenerator/controller_integration_test.go @@ -118,7 +118,7 @@ var _ = Describe("Test Work Generator Controller", func() { It("Should not create work for the binding with state scheduled", func() { // create master resource snapshot with 2 number of resources masterSnapshot := generateResourceSnapshot(1, 1, 0, [][]byte{ - testClonesetCRD, testNameSpace, testCloneset, + testResourceCRD, testNameSpace, testResource, }) Expect(k8sClient.Create(ctx, masterSnapshot)).Should(Succeed()) // create a scheduled binding @@ -154,7 +154,7 @@ var _ = Describe("Test Work Generator Controller", func() { It("Should only creat work after all the resource snapshots are created", func() { // create master resource snapshot with 1 number of resources masterSnapshot := generateResourceSnapshot(1, 2, 0, [][]byte{ - testClonesetCRD, testNameSpace, testCloneset, + testResourceCRD, testNameSpace, testResource, }) Expect(k8sClient.Create(ctx, masterSnapshot)).Should(Succeed()) By(fmt.Sprintf("master resource snapshot `%s` created", masterSnapshot.Name)) @@ -190,7 +190,7 @@ var _ = Describe("Test Work Generator Controller", func() { Expect(binding.GetCondition(string(placementv1beta1.ResourceBindingOverridden)).Message).Should(ContainSubstring("resource snapshots are still being created for the masterResourceSnapshot")) // create the second resource snapshot secondSnapshot := generateResourceSnapshot(1, 2, 1, [][]byte{ - testClonesetCRD, testNameSpace, testCloneset, + testResourceCRD, testNameSpace, testResource, }) Expect(k8sClient.Create(ctx, secondSnapshot)).Should(Succeed()) By(fmt.Sprintf("secondSnapshot resource snapshot `%s` created", secondSnapshot.Name)) @@ -207,7 +207,7 @@ var _ = Describe("Test Work Generator Controller", func() { It("Should handle the case that the snapshot is deleted", func() { // generate master resource snapshot masterSnapshot := generateResourceSnapshot(1, 1, 0, [][]byte{ - testClonesetCRD, testNameSpace, testCloneset, + testResourceCRD, testNameSpace, testResource, }) Expect(k8sClient.Create(ctx, masterSnapshot)).Should(Succeed()) By(fmt.Sprintf("master resource snapshot `%s` created", masterSnapshot.Name)) @@ -249,7 +249,7 @@ var _ = Describe("Test Work Generator Controller", func() { BeforeEach(func() { masterSnapshot = generateResourceSnapshot(1, 1, 0, [][]byte{ - testClonesetCRD, testNameSpace, testCloneset, + testResourceCRD, testNameSpace, testResource, }) Expect(k8sClient.Create(ctx, masterSnapshot)).Should(Succeed()) By(fmt.Sprintf("master resource snapshot %s created", masterSnapshot.Name)) @@ -307,9 +307,9 @@ var _ = Describe("Test Work Generator Controller", func() { Spec: placementv1beta1.WorkSpec{ Workload: placementv1beta1.WorkloadTemplate{ Manifests: []placementv1beta1.Manifest{ - {RawExtension: runtime.RawExtension{Raw: testClonesetCRD}}, + {RawExtension: runtime.RawExtension{Raw: testResourceCRD}}, {RawExtension: runtime.RawExtension{Raw: testNameSpace}}, - {RawExtension: runtime.RawExtension{Raw: testCloneset}}, + {RawExtension: runtime.RawExtension{Raw: testResource}}, }, }, }, @@ -345,9 +345,9 @@ var _ = Describe("Test Work Generator Controller", func() { }, duration, interval).Should(Succeed(), "controller should not remove work in hub cluster for unscheduled binding") //inspect the work manifest to make sure it still has the same content expectedManifest := []placementv1beta1.Manifest{ - {RawExtension: runtime.RawExtension{Raw: testClonesetCRD}}, + {RawExtension: runtime.RawExtension{Raw: testResourceCRD}}, {RawExtension: runtime.RawExtension{Raw: testNameSpace}}, - {RawExtension: runtime.RawExtension{Raw: testCloneset}}, + {RawExtension: runtime.RawExtension{Raw: testResource}}, } diff := cmp.Diff(expectedManifest, work.Spec.Workload.Manifests) Expect(diff).Should(BeEmpty(), fmt.Sprintf("work manifest(%s) mismatch (-want +got):\n%s", work.Name, diff)) @@ -394,9 +394,9 @@ var _ = Describe("Test Work Generator Controller", func() { Spec: placementv1beta1.WorkSpec{ Workload: placementv1beta1.WorkloadTemplate{ Manifests: []placementv1beta1.Manifest{ - {RawExtension: runtime.RawExtension{Raw: testClonesetCRD}}, + {RawExtension: runtime.RawExtension{Raw: testResourceCRD}}, {RawExtension: runtime.RawExtension{Raw: testNameSpace}}, - {RawExtension: runtime.RawExtension{Raw: testCloneset}}, + {RawExtension: runtime.RawExtension{Raw: testResource}}, }, }, }, @@ -458,9 +458,9 @@ var _ = Describe("Test Work Generator Controller", func() { Spec: placementv1beta1.WorkSpec{ Workload: placementv1beta1.WorkloadTemplate{ Manifests: []placementv1beta1.Manifest{ - {RawExtension: runtime.RawExtension{Raw: testClonesetCRD}}, + {RawExtension: runtime.RawExtension{Raw: testResourceCRD}}, {RawExtension: runtime.RawExtension{Raw: testNameSpace}}, - {RawExtension: runtime.RawExtension{Raw: testCloneset}}, + {RawExtension: runtime.RawExtension{Raw: testResource}}, }, }, }, @@ -485,7 +485,7 @@ var _ = Describe("Test Work Generator Controller", func() { BeforeEach(func() { masterSnapshot = generateResourceSnapshot(1, 1, 0, [][]byte{ - testConfigMap, testEnvelopConfigMap, testClonesetCRD, testNameSpace, + testConfigMap, testEnvelopConfigMap, testResourceCRD, testNameSpace, }) Expect(k8sClient.Create(ctx, masterSnapshot)).Should(Succeed()) By(fmt.Sprintf("master resource snapshot %s created", masterSnapshot.Name)) @@ -535,7 +535,7 @@ var _ = Describe("Test Work Generator Controller", func() { Workload: placementv1beta1.WorkloadTemplate{ Manifests: []placementv1beta1.Manifest{ {RawExtension: runtime.RawExtension{Raw: testConfigMap}}, - {RawExtension: runtime.RawExtension{Raw: testClonesetCRD}}, + {RawExtension: runtime.RawExtension{Raw: testResourceCRD}}, {RawExtension: runtime.RawExtension{Raw: testNameSpace}}, }, }, @@ -599,7 +599,7 @@ var _ = Describe("Test Work Generator Controller", func() { fetchEnvelopedWork(&workList, binding) // create a second snapshot with a modified enveloped object masterSnapshot = generateResourceSnapshot(2, 1, 0, [][]byte{ - testEnvelopConfigMap2, testClonesetCRD, testNameSpace, + testEnvelopConfigMap2, testResourceCRD, testNameSpace, }) Expect(k8sClient.Create(ctx, masterSnapshot)).Should(Succeed()) By(fmt.Sprintf("another master resource snapshot %s created", masterSnapshot.Name)) @@ -650,7 +650,7 @@ var _ = Describe("Test Work Generator Controller", func() { Spec: placementv1beta1.WorkSpec{ Workload: placementv1beta1.WorkloadTemplate{ Manifests: []placementv1beta1.Manifest{ - {RawExtension: runtime.RawExtension{Raw: testClonesetCRD}}, + {RawExtension: runtime.RawExtension{Raw: testResourceCRD}}, {RawExtension: runtime.RawExtension{Raw: testNameSpace}}, }, }, @@ -704,7 +704,7 @@ var _ = Describe("Test Work Generator Controller", func() { By("create a second snapshot without an enveloped object") // create a second snapshot without an enveloped object masterSnapshot = generateResourceSnapshot(2, 1, 0, [][]byte{ - testClonesetCRD, testNameSpace, + testResourceCRD, testNameSpace, }) Expect(k8sClient.Create(ctx, masterSnapshot)).Should(Succeed()) By(fmt.Sprintf("another master resource snapshot %s created", masterSnapshot.Name)) @@ -752,7 +752,7 @@ var _ = Describe("Test Work Generator Controller", func() { BeforeEach(func() { masterSnapshot = generateResourceSnapshot(2, 2, 0, [][]byte{ - testClonesetCRD, testNameSpace, testCloneset, + testResourceCRD, testNameSpace, testResource, }) Expect(k8sClient.Create(ctx, masterSnapshot)).Should(Succeed()) By(fmt.Sprintf("master resource snapshot %s created", masterSnapshot.Name)) @@ -794,9 +794,9 @@ var _ = Describe("Test Work Generator Controller", func() { By(fmt.Sprintf("first work %s is created in %s", work.Name, work.Namespace)) //inspect the work manifest expectedManifest := []placementv1beta1.Manifest{ - {RawExtension: runtime.RawExtension{Raw: testClonesetCRD}}, + {RawExtension: runtime.RawExtension{Raw: testResourceCRD}}, {RawExtension: runtime.RawExtension{Raw: testNameSpace}}, - {RawExtension: runtime.RawExtension{Raw: testCloneset}}, + {RawExtension: runtime.RawExtension{Raw: testResource}}, } diff := cmp.Diff(expectedManifest, work.Spec.Workload.Manifests) Expect(diff).Should(BeEmpty(), fmt.Sprintf("work manifest(%s) mismatch (-want +got):\n%s", work.Name, diff)) @@ -864,9 +864,9 @@ var _ = Describe("Test Work Generator Controller", func() { By(fmt.Sprintf("first work %s is created in %s", work.Name, work.Namespace)) //inspect the work manifest expectedManifest := []placementv1beta1.Manifest{ - {RawExtension: runtime.RawExtension{Raw: testClonesetCRD}}, + {RawExtension: runtime.RawExtension{Raw: testResourceCRD}}, {RawExtension: runtime.RawExtension{Raw: testNameSpace}}, - {RawExtension: runtime.RawExtension{Raw: testCloneset}}, + {RawExtension: runtime.RawExtension{Raw: testResource}}, } diff := cmp.Diff(expectedManifest, work.Spec.Workload.Manifests) Expect(diff).Should(BeEmpty(), fmt.Sprintf("work manifest(%s) mismatch (-want +got):\n%s", work.Name, diff)) @@ -937,7 +937,7 @@ var _ = Describe("Test Work Generator Controller", func() { By(fmt.Sprintf("second work %s is created in %s", work.Name, work.Namespace)) // update the master resource snapshot with 3 resources in it masterSnapshot = generateResourceSnapshot(3, 3, 0, [][]byte{ - testClonesetCRD, testNameSpace, + testResourceCRD, testNameSpace, }) Expect(k8sClient.Create(ctx, masterSnapshot)).Should(Succeed()) By(fmt.Sprintf("new master resource snapshot %s created", masterSnapshot.Name)) @@ -948,7 +948,7 @@ var _ = Describe("Test Work Generator Controller", func() { By(fmt.Sprintf("resource binding %s updated", binding.Name)) // Now create the second resource snapshot secondSnapshot = generateResourceSnapshot(3, 3, 1, [][]byte{ - testCloneset, testConfigMap, + testResource, testConfigMap, }) Expect(k8sClient.Create(ctx, secondSnapshot)).Should(Succeed()) By(fmt.Sprintf("new secondary resource snapshot %s created", secondSnapshot.Name)) @@ -960,7 +960,7 @@ var _ = Describe("Test Work Generator Controller", func() { By(fmt.Sprintf("third resource snapshot %s created", secondSnapshot.Name)) // check the work for the master resource snapshot is created expectedManifest := []placementv1beta1.Manifest{ - {RawExtension: runtime.RawExtension{Raw: testClonesetCRD}}, + {RawExtension: runtime.RawExtension{Raw: testResourceCRD}}, {RawExtension: runtime.RawExtension{Raw: testNameSpace}}, } Eventually(func() error { @@ -977,7 +977,7 @@ var _ = Describe("Test Work Generator Controller", func() { By(fmt.Sprintf("first work %s is updated in %s", work.Name, work.Namespace)) // check the work for the secondary resource snapshot is created, it's name is crp-subindex expectedManifest = []placementv1beta1.Manifest{ - {RawExtension: runtime.RawExtension{Raw: testCloneset}}, + {RawExtension: runtime.RawExtension{Raw: testResource}}, {RawExtension: runtime.RawExtension{Raw: testConfigMap}}, } Eventually(func() error { @@ -1028,7 +1028,7 @@ var _ = Describe("Test Work Generator Controller", func() { By(fmt.Sprintf("second work %s is created in %s", work.Name, work.Namespace)) // update the master resource snapshot with only 1 resource snapshot that contains everything in it masterSnapshot = generateResourceSnapshot(3, 1, 0, [][]byte{ - testClonesetCRD, testNameSpace, testCloneset, testConfigMap, testPdb, + testResourceCRD, testNameSpace, testResource, testConfigMap, testPdb, }) Expect(k8sClient.Create(ctx, masterSnapshot)).Should(Succeed()) By(fmt.Sprintf("new master resource snapshot %s created", masterSnapshot.Name)) @@ -1039,9 +1039,9 @@ var _ = Describe("Test Work Generator Controller", func() { By(fmt.Sprintf("resource binding %s updated", binding.Name)) //inspect the work manifest that should have been updated to contain all expectedManifest := []placementv1beta1.Manifest{ - {RawExtension: runtime.RawExtension{Raw: testClonesetCRD}}, + {RawExtension: runtime.RawExtension{Raw: testResourceCRD}}, {RawExtension: runtime.RawExtension{Raw: testNameSpace}}, - {RawExtension: runtime.RawExtension{Raw: testCloneset}}, + {RawExtension: runtime.RawExtension{Raw: testResource}}, {RawExtension: runtime.RawExtension{Raw: testConfigMap}}, {RawExtension: runtime.RawExtension{Raw: testPdb}}, } @@ -1121,7 +1121,7 @@ var _ = Describe("Test Work Generator Controller", func() { BeforeEach(func() { masterSnapshot = generateResourceSnapshot(1, 1, 0, [][]byte{ - testClonesetCRD, testNameSpace, testCloneset, + testResourceCRD, testNameSpace, testResource, }) Expect(k8sClient.Create(ctx, masterSnapshot)).Should(Succeed()) By(fmt.Sprintf("master resource snapshot %s created", masterSnapshot.Name)) @@ -1188,9 +1188,9 @@ var _ = Describe("Test Work Generator Controller", func() { Spec: placementv1beta1.WorkSpec{ Workload: placementv1beta1.WorkloadTemplate{ Manifests: []placementv1beta1.Manifest{ - {RawExtension: runtime.RawExtension{Raw: testClonesetCRD}}, + {RawExtension: runtime.RawExtension{Raw: testResourceCRD}}, {RawExtension: runtime.RawExtension{Raw: testNameSpace}}, - {RawExtension: runtime.RawExtension{Raw: wantOverriddenTestCloneSet}}, + {RawExtension: runtime.RawExtension{Raw: wantOverriddenTestResource}}, }, }, }, @@ -1226,9 +1226,9 @@ var _ = Describe("Test Work Generator Controller", func() { }, duration, interval).Should(Succeed(), "controller should not remove work in hub cluster for unscheduled binding") //inspect the work manifest to make sure it still has the same content expectedManifest := []placementv1beta1.Manifest{ - {RawExtension: runtime.RawExtension{Raw: testClonesetCRD}}, + {RawExtension: runtime.RawExtension{Raw: testResourceCRD}}, {RawExtension: runtime.RawExtension{Raw: testNameSpace}}, - {RawExtension: runtime.RawExtension{Raw: wantOverriddenTestCloneSet}}, + {RawExtension: runtime.RawExtension{Raw: wantOverriddenTestResource}}, } diff := cmp.Diff(expectedManifest, work.Spec.Workload.Manifests) Expect(diff).Should(BeEmpty(), fmt.Sprintf("work manifest(%s) mismatch (-want +got):\n%s", work.Name, diff)) @@ -1242,7 +1242,7 @@ var _ = Describe("Test Work Generator Controller", func() { BeforeEach(func() { masterSnapshot = generateResourceSnapshot(1, 1, 0, [][]byte{ - testClonesetCRD, testNameSpace, testCloneset, + testResourceCRD, testNameSpace, testResource, }) Expect(k8sClient.Create(ctx, masterSnapshot)).Should(Succeed()) By(fmt.Sprintf("master resource snapshot %s created", masterSnapshot.Name)) @@ -1297,7 +1297,7 @@ var _ = Describe("Test Work Generator Controller", func() { BeforeEach(func() { masterSnapshot = generateResourceSnapshot(1, 1, 0, [][]byte{ - testClonesetCRD, testNameSpace, testCloneset, + testResourceCRD, testNameSpace, testResource, }) Expect(k8sClient.Create(ctx, masterSnapshot)).Should(Succeed()) By(fmt.Sprintf("master resource snapshot %s created", masterSnapshot.Name)) diff --git a/pkg/controllers/workgenerator/manifests/test-cloneset-overridden.yaml b/pkg/controllers/workgenerator/manifests/test-cloneset-overridden.yaml deleted file mode 100644 index 1829f5526..000000000 --- a/pkg/controllers/workgenerator/manifests/test-cloneset-overridden.yaml +++ /dev/null @@ -1,25 +0,0 @@ -apiVersion: apps.kruise.io/v1alpha1 -kind: CloneSet -metadata: - name: guestbook-clone - namespace: app -spec: - replicas: 30 - selector: - matchLabels: - app.kubernetes.io/name: guestbook-clone - template: - metadata: - labels: - app.kubernetes.io/name: guestbook-clone - spec: - containers: - - name: guestbook - image: openkruise/guestbook:v1 - imagePullPolicy: Always - ports: - - name: http-server - containerPort: 3000 - updateStrategy: - type: InPlaceIfPossible - maxUnavailable: 3 \ No newline at end of file diff --git a/pkg/controllers/workgenerator/manifests/test-cloneset.yaml b/pkg/controllers/workgenerator/manifests/test-cloneset.yaml deleted file mode 100644 index ef6c5efc5..000000000 --- a/pkg/controllers/workgenerator/manifests/test-cloneset.yaml +++ /dev/null @@ -1,25 +0,0 @@ -apiVersion: apps.kruise.io/v1alpha1 -kind: CloneSet -metadata: - name: guestbook-clone - namespace: app -spec: - replicas: 20 - selector: - matchLabels: - app.kubernetes.io/name: guestbook-clone - template: - metadata: - labels: - app.kubernetes.io/name: guestbook-clone - spec: - containers: - - name: guestbook - image: openkruise/guestbook:v1 - imagePullPolicy: Always - ports: - - name: http-server - containerPort: 3000 - updateStrategy: - type: InPlaceIfPossible - maxUnavailable: 3 \ No newline at end of file diff --git a/pkg/controllers/workgenerator/manifests/test-resource-overriden.yaml b/pkg/controllers/workgenerator/manifests/test-resource-overriden.yaml new file mode 100644 index 000000000..48887ec47 --- /dev/null +++ b/pkg/controllers/workgenerator/manifests/test-resource-overriden.yaml @@ -0,0 +1,10 @@ +apiVersion: test.kubernetes-fleet.io/v1alpha1 +kind: TestResource +metadata: + name: random-test-resource + namespace: app +spec: + foo: foo2 + items: + - a + - b \ No newline at end of file diff --git a/pkg/controllers/workgenerator/manifests/test-resource.yaml b/pkg/controllers/workgenerator/manifests/test-resource.yaml new file mode 100644 index 000000000..8eb8a2170 --- /dev/null +++ b/pkg/controllers/workgenerator/manifests/test-resource.yaml @@ -0,0 +1,10 @@ +apiVersion: test.kubernetes-fleet.io/v1alpha1 +kind: TestResource +metadata: + name: random-test-resource + namespace: app +spec: + foo: foo1 + items: + - a + - b \ No newline at end of file diff --git a/pkg/controllers/workgenerator/manifests/test_clonesets_crd.yaml b/pkg/controllers/workgenerator/manifests/test_clonesets_crd.yaml deleted file mode 100644 index 1cb0b93c2..000000000 --- a/pkg/controllers/workgenerator/manifests/test_clonesets_crd.yaml +++ /dev/null @@ -1,498 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.7.0 - labels: - fleet.azure.com/name: test-placement - name: clonesets.apps.kruise.io -spec: - group: apps.kruise.io - names: - kind: CloneSet - listKind: CloneSetList - plural: clonesets - shortNames: - - clone - singular: cloneset - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: The desired number of pods. - jsonPath: .spec.replicas - name: DESIRED - type: integer - - description: The number of pods updated. - jsonPath: .status.updatedReplicas - name: UPDATED - type: integer - - description: The number of pods updated and ready. - jsonPath: .status.updatedReadyReplicas - name: UPDATED_READY - type: integer - - description: The number of pods ready. - jsonPath: .status.readyReplicas - name: READY - type: integer - - description: The number of currently all pods. - jsonPath: .status.replicas - name: TOTAL - type: integer - - description: CreationTimestamp is a timestamp representing the server time when - this object was created. It is not guaranteed to be set in happens-before - order across separate operations. Clients may not set this value. It is represented - in RFC3339 form and is in UTC. - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - description: The containers of currently cloneset. - jsonPath: .spec.template.spec.containers[*].name - name: CONTAINERS - priority: 1 - type: string - - description: The images of currently cloneset. - jsonPath: .spec.template.spec.containers[*].image - name: IMAGES - priority: 1 - type: string - - description: The selector of currently cloneset. - jsonPath: .status.labelSelector - name: SELECTOR - priority: 1 - type: string - name: v1alpha1 - schema: - openAPIV3Schema: - description: CloneSet is the Schema for the clonesets API - 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: CloneSetSpec defines the desired state of CloneSet - properties: - lifecycle: - description: Lifecycle defines the lifecycle hooks for Pods pre-delete, - in-place update. - properties: - inPlaceUpdate: - description: InPlaceUpdate is the hook before Pod to update and - after Pod has been updated. - properties: - finalizersHandler: - items: - type: string - type: array - labelsHandler: - additionalProperties: - type: string - type: object - markPodNotReady: - description: 'MarkPodNotReady = true means: - Pod will be - set to ''NotReady'' at preparingDelete/preparingUpdate state. - - Pod will be restored to ''Ready'' at Updated state if - it was set to ''NotReady'' at preparingUpdate state. Default - to false.' - type: boolean - type: object - preDelete: - description: PreDelete is the hook before Pod to be deleted. - properties: - finalizersHandler: - items: - type: string - type: array - labelsHandler: - additionalProperties: - type: string - type: object - markPodNotReady: - description: 'MarkPodNotReady = true means: - Pod will be - set to ''NotReady'' at preparingDelete/preparingUpdate state. - - Pod will be restored to ''Ready'' at Updated state if - it was set to ''NotReady'' at preparingUpdate state. Default - to false.' - type: boolean - type: object - type: object - minReadySeconds: - description: Minimum number of seconds for which a newly created pod - should be ready without any of its container crashing, for it to - be considered available. Defaults to 0 (pod will be considered available - as soon as it is ready) - format: int32 - type: integer - replicas: - description: Replicas is the desired number of replicas of the given - Template. These are replicas in the sense that they are instantiations - of the same Template. If unspecified, defaults to 1. - format: int32 - type: integer - revisionHistoryLimit: - description: RevisionHistoryLimit is the maximum number of revisions - that will be maintained in the CloneSet's revision history. The - revision history consists of all revisions not represented by a - currently applied CloneSetSpec version. The default value is 10. - format: int32 - type: integer - scaleStrategy: - description: ScaleStrategy indicates the ScaleStrategy that will be - employed to create and delete Pods in the CloneSet. - properties: - maxUnavailable: - anyOf: - - type: integer - - type: string - description: The maximum number of pods that can be unavailable - for scaled pods. This field can control the changes rate of - replicas for CloneSet so as to minimize the impact for users' - service. The scale will fail if the number of unavailable pods - were greater than this MaxUnavailable at scaling up. MaxUnavailable - works only when scaling up. - x-kubernetes-int-or-string: true - podsToDelete: - description: PodsToDelete is the names of Pod should be deleted. - Note that this list will be truncated for non-existing pod names. - items: - type: string - type: array - type: object - selector: - description: 'Selector is a label query over pods that should match - the replica count. It must match the pod template''s labels. More - info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors' - 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 - template: - description: Template describes the pods that will be created. - x-kubernetes-preserve-unknown-fields: true - updateStrategy: - description: UpdateStrategy indicates the UpdateStrategy that will - be employed to update Pods in the CloneSet when a revision is made - to Template. - properties: - inPlaceUpdateStrategy: - description: InPlaceUpdateStrategy contains strategies for in-place - update. - properties: - gracePeriodSeconds: - description: GracePeriodSeconds is the timespan between set - Pod status to not-ready and update images in Pod spec when - in-place update a Pod. - format: int32 - type: integer - type: object - maxSurge: - anyOf: - - type: integer - - type: string - description: 'The maximum number of pods that can be scheduled - above the desired replicas during update or specified delete. - Value can be an absolute number (ex: 5) or a percentage of desired - pods (ex: 10%). Absolute number is calculated from percentage - by rounding up. Defaults to 0.' - x-kubernetes-int-or-string: true - maxUnavailable: - anyOf: - - type: integer - - type: string - description: 'The maximum number of pods that can be unavailable - during update or scale. Value can be an absolute number (ex: - 5) or a percentage of desired pods (ex: 10%). Absolute number - is calculated from percentage by rounding up by default. When - maxSurge > 0, absolute number is calculated from percentage - by rounding down. Defaults to 20%.' - x-kubernetes-int-or-string: true - partition: - anyOf: - - type: integer - - type: string - description: 'Partition is the desired number of pods in old revisions. - Value can be an absolute number (ex: 5) or a percentage of desired - pods (ex: 10%). Absolute number is calculated from percentage - by rounding up by default. It means when partition is set during - pods updating, (replicas - partition value) number of pods will - be updated. Default value is 0.' - x-kubernetes-int-or-string: true - paused: - description: Paused indicates that the CloneSet is paused. Default - value is false - type: boolean - priorityStrategy: - description: Priorities are the rules for calculating the priority - of updating pods. Each pod to be updated, will pass through - these terms and get a sum of weights. - properties: - orderPriority: - description: 'Order priority terms, pods will be sorted by - the value of orderedKey. For example: ``` orderPriority: - - orderedKey: key1 - orderedKey: key2 ``` First, all pods - which have key1 in labels will be sorted by the value of - key1. Then, the left pods which have no key1 but have key2 - in labels will be sorted by the value of key2 and put behind - those pods have key1.' - items: - description: UpdatePriorityOrder defines order priority. - properties: - orderedKey: - description: Calculate priority by value of this key. - Values of this key, will be sorted by GetInt(val). - GetInt method will find the last int in value, such - as getting 5 in value '5', getting 10 in value 'sts-10'. - type: string - required: - - orderedKey - type: object - type: array - weightPriority: - description: Weight priority terms, pods will be sorted by - the sum of all terms weight. - items: - description: UpdatePriorityWeightTerm defines weight priority. - properties: - matchSelector: - description: MatchSelector is used to select by pod's - labels. - 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 - weight: - description: Weight associated with matching the corresponding - matchExpressions, in the range 1-100. - format: int32 - type: integer - required: - - matchSelector - - weight - type: object - type: array - type: object - scatterStrategy: - description: ScatterStrategy defines the scatter rules to make - pods been scattered when update. This will avoid pods with the - same key-value to be updated in one batch. - Note that pods - will be scattered after priority sort. So, although priority - strategy and scatter strategy can be applied together, we suggest - to use either one of them. - If scatterStrategy is used, we - suggest to just use one term. Otherwise, the update order can - be hard to understand. - items: - properties: - key: - type: string - value: - type: string - required: - - key - - value - type: object - type: array - type: - description: Type indicates the type of the CloneSetUpdateStrategy. - Default is ReCreate. - type: string - type: object - volumeClaimTemplates: - description: VolumeClaimTemplates is a list of claims that pods are - allowed to reference. Note that PVC will be deleted when its pod - has been deleted. - x-kubernetes-preserve-unknown-fields: true - required: - - selector - - template - type: object - status: - description: CloneSetStatus defines the observed state of CloneSet - properties: - availableReplicas: - description: AvailableReplicas is the number of Pods created by the - CloneSet controller that have a Ready Condition for at least minReadySeconds. - format: int32 - type: integer - collisionCount: - description: CollisionCount is the count of hash collisions for the - CloneSet. The CloneSet controller uses this field as a collision - avoidance mechanism when it needs to create the name for the newest - ControllerRevision. - format: int32 - type: integer - conditions: - description: Conditions represents the latest available observations - of a CloneSet's current state. - items: - description: CloneSetCondition describes the state of a CloneSet - at a certain point. - properties: - lastTransitionTime: - description: Last time the condition transitioned from one status - to another. - format: date-time - type: string - message: - description: A human readable message indicating details about - the transition. - type: string - reason: - description: The reason for the condition's last transition. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: Type of CloneSet condition. - type: string - required: - - status - - type - type: object - type: array - currentRevision: - description: currentRevision, if not empty, indicates the current - revision version of the CloneSet. - type: string - expectedUpdatedReplicas: - description: ExpectedUpdatedReplicas is the number of Pods that should - be updated by CloneSet controller. This field is calculated via - Replicas - Partition. - format: int32 - type: integer - labelSelector: - description: LabelSelector is label selectors for query over pods - that should match the replica count used by HPA. - type: string - observedGeneration: - description: ObservedGeneration is the most recent generation observed - for this CloneSet. It corresponds to the CloneSet's generation, - which is updated on mutation by the API Server. - format: int64 - type: integer - readyReplicas: - description: ReadyReplicas is the number of Pods created by the CloneSet - controller that have a Ready Condition. - format: int32 - type: integer - replicas: - description: Replicas is the number of Pods created by the CloneSet - controller. - format: int32 - type: integer - updateRevision: - description: UpdateRevision, if not empty, indicates the latest revision - of the CloneSet. - type: string - updatedReadyReplicas: - description: UpdatedReadyReplicas is the number of Pods created by - the CloneSet controller from the CloneSet version indicated by updateRevision - and have a Ready Condition. - format: int32 - type: integer - updatedReplicas: - description: UpdatedReplicas is the number of Pods created by the - CloneSet controller from the CloneSet version indicated by updateRevision. - format: int32 - type: integer - required: - - availableReplicas - - readyReplicas - - replicas - - updatedReadyReplicas - - updatedReplicas - type: object - type: object - served: true - storage: true - subresources: - scale: - labelSelectorPath: .status.labelSelector - specReplicasPath: .spec.replicas - statusReplicasPath: .status.replicas diff --git a/pkg/controllers/workgenerator/manifests/test_testresources_crd.yaml b/pkg/controllers/workgenerator/manifests/test_testresources_crd.yaml new file mode 100644 index 000000000..d8e762069 --- /dev/null +++ b/pkg/controllers/workgenerator/manifests/test_testresources_crd.yaml @@ -0,0 +1,111 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + labels: + fleet.azure.com/name: test-placement + annotations: + controller-gen.kubebuilder.io/version: v0.15.0 + name: testresources.test.kubernetes-fleet.io +spec: + group: test.kubernetes-fleet.io + names: + kind: TestResource + listKind: TestResourceList + plural: testresources + singular: testresource + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: TestResource is the Schema for the testresources API + 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: TestResourceSpec defines the desired state of TestResource + properties: + bar: + type: string + foo: + type: string + items: + items: + type: string + type: array + labelSelector: + description: |- + A label selector is a label query over a set of resources. The result of matchLabels and + matchExpressions are ANDed. An empty label selector matches all objects. A null + label selector matches no objects. + 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 + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + 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 + type: object + status: + description: TestResourceStatus defines the observed state of TestResource + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} diff --git a/pkg/controllers/workgenerator/suite_test.go b/pkg/controllers/workgenerator/suite_test.go index f256b33bd..75c0f1125 100644 --- a/pkg/controllers/workgenerator/suite_test.go +++ b/pkg/controllers/workgenerator/suite_test.go @@ -16,7 +16,6 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - kruisev1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1" corev1 "k8s.io/api/core/v1" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -49,10 +48,10 @@ var ( cancel context.CancelFunc // pre loaded test manifests - testClonesetCRD, testNameSpace, testCloneset, testConfigMap, testEnvelopConfigMap, testEnvelopConfigMap2, testPdb []byte + testResourceCRD, testNameSpace, testResource, testConfigMap, testEnvelopConfigMap, testEnvelopConfigMap2, testPdb []byte // want overridden manifest which is overridden by cro-1 and ro-1 - wantOverriddenTestCloneSet []byte + wantOverriddenTestResource []byte // the content of the enveloped resources testEnvelopeWebhook, testEnvelopeResourceQuota []byte @@ -87,7 +86,6 @@ var _ = BeforeSuite(func() { By("Set all the customized scheme") Expect(placementv1beta1.AddToScheme(scheme.Scheme)).Should(Succeed()) Expect(workv1alpha1.AddToScheme(scheme.Scheme)).Should(Succeed()) - Expect(kruisev1alpha1.AddToScheme(scheme.Scheme)).Should(Succeed()) Expect(clusterv1beta1.AddToScheme(scheme.Scheme)).Should(Succeed()) Expect(placementv1alpha1.AddToScheme(scheme.Scheme)).Should(Succeed()) @@ -214,10 +212,10 @@ func createOverrides() { OverrideSpec: placementv1alpha1.ResourceOverrideSpec{ ResourceSelectors: []placementv1alpha1.ResourceSelector{ { - Group: "apps.kruise.io", + Group: "test.kubernetes-fleet.io", Version: "v1alpha1", - Kind: "CloneSet", - Name: "guestbook-clone", + Kind: "TestResource", + Name: "random-test-resource", }, }, Policy: &placementv1alpha1.OverridePolicy{ @@ -229,8 +227,8 @@ func createOverrides() { JSONPatchOverrides: []placementv1alpha1.JSONPatchOverride{ { Operator: placementv1alpha1.JSONPatchOverrideOpReplace, - Path: "/spec/replicas", - Value: apiextensionsv1.JSON{Raw: []byte("30")}, + Path: "/spec/foo", + Value: apiextensionsv1.JSON{Raw: []byte(`"foo2"`)}, }, }, }, @@ -308,10 +306,10 @@ var _ = AfterSuite(func() { }) func readTestManifests() { - By("Read testCloneset CRD") - rawByte, err := os.ReadFile("manifests/test_clonesets_crd.yaml") + By("Read testResource CRD") + rawByte, err := os.ReadFile("manifests/test_testresources_crd.yaml") Expect(err).Should(Succeed()) - testClonesetCRD, err = yaml.ToJSON(rawByte) + testResourceCRD, err = yaml.ToJSON(rawByte) Expect(err).Should(Succeed()) By("Read namespace") @@ -320,16 +318,16 @@ func readTestManifests() { testNameSpace, err = yaml.ToJSON(rawByte) Expect(err).Should(Succeed()) - By("Read clonesetCR") - rawByte, err = os.ReadFile("manifests/test-cloneset.yaml") + By("Read TestResource CR") + rawByte, err = os.ReadFile("manifests/test-resource.yaml") Expect(err).Should(Succeed()) - testCloneset, err = yaml.ToJSON(rawByte) + testResource, err = yaml.ToJSON(rawByte) Expect(err).Should(Succeed()) - By("Read want overridden clonesetCR") - rawByte, err = os.ReadFile("manifests/test-cloneset-overridden.yaml") + By("Read want overridden TestResource CR") + rawByte, err = os.ReadFile("manifests/test-resource-overriden.yaml") Expect(err).Should(Succeed()) - wantOverriddenTestCloneSet, err = yaml.ToJSON(rawByte) + wantOverriddenTestResource, err = yaml.ToJSON(rawByte) Expect(err).Should(Succeed()) By("Read testConfigMap resource") diff --git a/pkg/controllers/workv1alpha1/applied_work_syncer_integration_test.go b/pkg/controllers/workv1alpha1/applied_work_syncer_integration_test.go index bf53e0a5a..b486bb5de 100644 --- a/pkg/controllers/workv1alpha1/applied_work_syncer_integration_test.go +++ b/pkg/controllers/workv1alpha1/applied_work_syncer_integration_test.go @@ -27,7 +27,6 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - kruisev1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -36,6 +35,8 @@ import ( utilrand "k8s.io/apimachinery/pkg/util/rand" workv1alpha1 "sigs.k8s.io/work-api/pkg/apis/v1alpha1" + + testv1alpha1 "go.goms.io/fleet/test/apis/v1alpha1" ) var _ = Describe("Work Status Reconciler", func() { @@ -243,22 +244,20 @@ var _ = Describe("Work Status Reconciler", func() { Expect(len(appliedWork.Status.AppliedResources)).Should(Equal(2)) By("replace configMap with a bad object from the work") - broadcastJob := &kruisev1alpha1.BroadcastJob{ + testResource := &testv1alpha1.TestResource{ TypeMeta: metav1.TypeMeta{ - APIVersion: kruisev1alpha1.SchemeGroupVersion.String(), - Kind: "BroadcastJob", + APIVersion: testv1alpha1.GroupVersion.String(), + Kind: "TestResource", }, ObjectMeta: metav1.ObjectMeta{ - Name: "broadcastjob-" + utilrand.String(5), - Namespace: workNamespace, - }, - Spec: kruisev1alpha1.BroadcastJobSpec{ - Paused: true, + Name: "testresource-" + utilrand.String(5), + // to ensure the resource is not applied. + Namespace: "random-test-namespace", }, } currentWork.Spec.Workload.Manifests = []workv1alpha1.Manifest{ { - RawExtension: runtime.RawExtension{Object: broadcastJob}, + RawExtension: runtime.RawExtension{Object: testResource}, }, } Expect(k8sClient.Update(context.Background(), currentWork)).Should(Succeed()) diff --git a/pkg/controllers/workv1alpha1/apply_controller_integration_test.go b/pkg/controllers/workv1alpha1/apply_controller_integration_test.go index 32b2d2beb..aba76fa3d 100644 --- a/pkg/controllers/workv1alpha1/apply_controller_integration_test.go +++ b/pkg/controllers/workv1alpha1/apply_controller_integration_test.go @@ -30,18 +30,16 @@ import ( "github.com/google/go-cmp/cmp" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - kruisev1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/intstr" utilrand "k8s.io/apimachinery/pkg/util/rand" - "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - workv1alpha1 "sigs.k8s.io/work-api/pkg/apis/v1alpha1" + + testv1alpha1 "go.goms.io/fleet/test/apis/v1alpha1" ) const timeout = time.Second * 10 @@ -337,19 +335,21 @@ var _ = Describe("Work Controller", func() { }) It("Should pick up the crd change correctly", func() { - cloneName := "testcloneset" - cloneNamespace := defaultNS - cloneSet := &kruisev1alpha1.CloneSet{ + testResourceName := "test-resource-name" + testResourceNamespace := defaultNS + testResource := &testv1alpha1.TestResource{ TypeMeta: metav1.TypeMeta{ - APIVersion: kruisev1alpha1.SchemeGroupVersion.String(), - Kind: "CloneSet", + APIVersion: testv1alpha1.GroupVersion.String(), + Kind: "TestResource", }, ObjectMeta: metav1.ObjectMeta{ - Name: cloneName, - Namespace: cloneNamespace, + Name: testResourceName, + Namespace: testResourceNamespace, }, - Spec: kruisev1alpha1.CloneSetSpec{ - Selector: &metav1.LabelSelector{ + Spec: testv1alpha1.TestResourceSpec{ + Foo: "foo", + Bar: "bar", + LabelSelector: &metav1.LabelSelector{ MatchExpressions: []metav1.LabelSelectorRequirement{ { Key: "region", @@ -366,23 +366,23 @@ var _ = Describe("Work Controller", func() { } By("create the work") - work = createWorkWithManifest(workNamespace, cloneSet) + work = createWorkWithManifest(workNamespace, testResource) err := k8sClient.Create(context.Background(), work) Expect(err).ToNot(HaveOccurred()) By("wait for the work to be applied") waitForWorkToApply(work.GetName(), work.GetNamespace()) - By("Check applied CloneSet") - var appliedCloneSet kruisev1alpha1.CloneSet - Expect(k8sClient.Get(context.Background(), types.NamespacedName{Name: cloneName, Namespace: cloneNamespace}, &appliedCloneSet)).Should(Succeed()) + By("Check applied TestResource") + var appliedTestResource testv1alpha1.TestResource + Expect(k8sClient.Get(context.Background(), types.NamespacedName{Name: testResourceName, Namespace: testResourceNamespace}, &appliedTestResource)).Should(Succeed()) - By("verify the CloneSet spec") - Expect(cmp.Diff(appliedCloneSet.Spec, cloneSet.Spec)).Should(BeEmpty()) + By("verify the TestResource spec") + Expect(cmp.Diff(appliedTestResource.Spec, testResource.Spec)).Should(BeEmpty()) - By("Modify and update the applied CloneSet") + By("Modify and update the applied TestResource") // add/modify/remove a match - appliedCloneSet.Spec.Selector.MatchExpressions = []metav1.LabelSelectorRequirement{ + appliedTestResource.Spec.LabelSelector.MatchExpressions = []metav1.LabelSelectorRequirement{ { Key: "region", Operator: metav1.LabelSelectorOpNotIn, @@ -393,47 +393,45 @@ var _ = Describe("Work Controller", func() { Operator: metav1.LabelSelectorOpExists, }, } - appliedCloneSet.Spec.ScaleStrategy.PodsToDelete = []string{"a", "b"} - appliedCloneSet.Spec.MinReadySeconds = 10 - Expect(k8sClient.Update(context.Background(), &appliedCloneSet)).Should(Succeed()) - - By("Verify applied CloneSet modified") - var modifiedCloneSet kruisev1alpha1.CloneSet - Expect(k8sClient.Get(context.Background(), types.NamespacedName{Name: cloneName, Namespace: cloneNamespace}, &modifiedCloneSet)).Should(Succeed()) - Expect(cmp.Diff(appliedCloneSet.Spec, modifiedCloneSet.Spec)).Should(BeEmpty()) - - By("Modify the cloneset") - cloneSet.Spec.Selector.MatchExpressions = []metav1.LabelSelectorRequirement{ + appliedTestResource.Spec.Items = []string{"a", "b"} + appliedTestResource.Spec.Foo = "foo1" + appliedTestResource.Spec.Bar = "bar1" + Expect(k8sClient.Update(context.Background(), &appliedTestResource)).Should(Succeed()) + + By("Verify applied TestResource modified") + var modifiedTestResource testv1alpha1.TestResource + Expect(k8sClient.Get(context.Background(), types.NamespacedName{Name: testResourceName, Namespace: testResourceNamespace}, &modifiedTestResource)).Should(Succeed()) + Expect(cmp.Diff(appliedTestResource.Spec, modifiedTestResource.Spec)).Should(BeEmpty()) + + By("Modify the TestResource") + testResource.Spec.LabelSelector.MatchExpressions = []metav1.LabelSelectorRequirement{ { Key: "region", Operator: metav1.LabelSelectorOpNotIn, Values: []string{"us", "asia", "eu"}, }, } - cloneSet.Spec.Replicas = ptr.To(int32(10)) - cloneSet.Spec.MinReadySeconds = 1 - maxuavail := intstr.FromInt(10) - cloneSet.Spec.ScaleStrategy.MaxUnavailable = &maxuavail + testResource.Spec.Foo = "foo2" + testResource.Spec.Bar = "bar2" By("update the work") resultWork := waitForWorkToApply(work.GetName(), work.GetNamespace()) - rawCM, err := json.Marshal(cloneSet) + rawTR, err := json.Marshal(testResource) Expect(err).Should(Succeed()) - resultWork.Spec.Workload.Manifests[0].Raw = rawCM + resultWork.Spec.Workload.Manifests[0].Raw = rawTR Expect(k8sClient.Update(context.Background(), resultWork)).Should(Succeed()) waitForWorkToApply(work.GetName(), work.GetNamespace()) - By("Get the last applied cloneset") - Expect(k8sClient.Get(context.Background(), types.NamespacedName{Name: cloneName, Namespace: cloneNamespace}, &appliedCloneSet)).Should(Succeed()) + By("Get the last applied TestResource") + Expect(k8sClient.Get(context.Background(), types.NamespacedName{Name: testResourceName, Namespace: testResourceNamespace}, &appliedTestResource)).Should(Succeed()) - By("Check the cloneset spec, its an overide for arrays") - expectStrategy := kruisev1alpha1.CloneSetScaleStrategy{ - PodsToDelete: []string{"a", "b"}, - MaxUnavailable: &maxuavail, - } - Expect(cmp.Diff(appliedCloneSet.Spec.ScaleStrategy, expectStrategy)).Should(BeEmpty()) - Expect(cmp.Diff(appliedCloneSet.Spec.Selector, cloneSet.Spec.Selector)).Should(BeEmpty()) - Expect(cmp.Diff(appliedCloneSet.Spec.Replicas, ptr.To(int32(10)))).Should(BeEmpty()) - Expect(cmp.Diff(appliedCloneSet.Spec.MinReadySeconds, int32(1))).Should(BeEmpty()) + By("Check the TestResource spec, its an override for arrays") + expectedItems := []string{"a", "b"} + Expect(cmp.Diff(appliedTestResource.Spec.Items, expectedItems)).Should(BeEmpty()) + Expect(cmp.Diff(appliedTestResource.Spec.LabelSelector, testResource.Spec.LabelSelector)).Should(BeEmpty()) + Expect(cmp.Diff(appliedTestResource.Spec.Foo, "foo2")).Should(BeEmpty()) + Expect(cmp.Diff(appliedTestResource.Spec.Bar, "bar2")).Should(BeEmpty()) + + Expect(k8sClient.Delete(ctx, work)).Should(Succeed(), "Failed to deleted the work") }) It("Check that owner references is merged instead of override", func() { @@ -546,26 +544,27 @@ var _ = Describe("Work Controller", func() { }) It("Check that failed to apply manifest has the proper identification", func() { - broadcastName := "testfail" - namespace := defaultNS - broadcastJob := &kruisev1alpha1.BroadcastJob{ + testResourceName := "test-resource-name-failed" + // to ensure apply fails. + namespace := "random-test-namespace" + testResource := &testv1alpha1.TestResource{ TypeMeta: metav1.TypeMeta{ - APIVersion: kruisev1alpha1.SchemeGroupVersion.String(), - Kind: "BroadcastJob", + APIVersion: testv1alpha1.GroupVersion.String(), + Kind: "TestResource", }, ObjectMeta: metav1.ObjectMeta{ - Name: broadcastName, + Name: testResourceName, Namespace: namespace, }, - Spec: kruisev1alpha1.BroadcastJobSpec{ - Paused: true, + Spec: testv1alpha1.TestResourceSpec{ + Foo: "foo", }, } - work = createWorkWithManifest(workNamespace, broadcastJob) + work = createWorkWithManifest(workNamespace, testResource) err := k8sClient.Create(context.Background(), work) Expect(err).ToNot(HaveOccurred()) - By("wait for the work to be applied") + By("wait for the work to be applied, apply condition set to failed") var resultWork workv1alpha1.Work Eventually(func() bool { err := k8sClient.Get(context.Background(), types.NamespacedName{Name: work.Name, Namespace: work.GetNamespace()}, &resultWork) @@ -583,11 +582,12 @@ var _ = Describe("Work Controller", func() { }, timeout, interval).Should(BeTrue()) expectedResourceID := workv1alpha1.ResourceIdentifier{ Ordinal: 0, - Group: "apps.kruise.io", - Version: "v1alpha1", - Kind: "BroadcastJob", - Namespace: broadcastJob.GetNamespace(), - Name: broadcastJob.GetName(), + Group: testv1alpha1.GroupVersion.Group, + Version: testv1alpha1.GroupVersion.Version, + Resource: "testresources", + Kind: testResource.Kind, + Namespace: testResource.GetNamespace(), + Name: testResource.GetName(), } Expect(cmp.Diff(resultWork.Status.ManifestConditions[0].Identifier, expectedResourceID)).Should(BeEmpty()) }) diff --git a/pkg/controllers/workv1alpha1/suite_test.go b/pkg/controllers/workv1alpha1/suite_test.go index 1f009707b..57a5965dd 100644 --- a/pkg/controllers/workv1alpha1/suite_test.go +++ b/pkg/controllers/workv1alpha1/suite_test.go @@ -30,7 +30,6 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - kruisev1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1" "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/rest" "k8s.io/klog/v2" @@ -38,8 +37,9 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/envtest" "sigs.k8s.io/controller-runtime/pkg/manager" - workv1alpha1 "sigs.k8s.io/work-api/pkg/apis/v1alpha1" + + testv1alpha1 "go.goms.io/fleet/test/apis/v1alpha1" ) // These tests use Ginkgo (BDD-style Go testing framework). Refer to @@ -81,7 +81,7 @@ var _ = BeforeSuite(func() { err = workv1alpha1.AddToScheme(scheme.Scheme) Expect(err).NotTo(HaveOccurred()) - err = kruisev1alpha1.AddToScheme(scheme.Scheme) + err = testv1alpha1.AddToScheme(scheme.Scheme) Expect(err).NotTo(HaveOccurred()) opts := ctrl.Options{ Scheme: scheme.Scheme, diff --git a/test/apis/v1alpha1/groupversion_info.go b/test/apis/v1alpha1/groupversion_info.go new file mode 100644 index 000000000..5dd65916c --- /dev/null +++ b/test/apis/v1alpha1/groupversion_info.go @@ -0,0 +1,25 @@ +/* +Copyright (c) Microsoft Corporation. +Licensed under the MIT license. +*/ + +// Package v1alpha1 contains API Schema definitions for the test v1alpha1 API group +// +kubebuilder:object:generate=true +// +groupName=test.kubernetes-fleet.io +package v1alpha1 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // GroupVersion is group version used to register these objects + GroupVersion = schema.GroupVersion{Group: "test.kubernetes-fleet.io", Version: "v1alpha1"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) diff --git a/test/apis/v1alpha1/testresource_types.go b/test/apis/v1alpha1/testresource_types.go new file mode 100644 index 000000000..01fde4dbf --- /dev/null +++ b/test/apis/v1alpha1/testresource_types.go @@ -0,0 +1,58 @@ +/* +Copyright (c) Microsoft Corporation. +Licensed under the MIT license. +*/ + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// TestResourceSpec defines the desired state of TestResource +type TestResourceSpec struct { + // +optional + Foo string `json:"foo,omitempty"` + + // +optional + Bar string `json:"bar,omitempty"` + + // +optional + Items []string `json:"items,omitempty"` + + // +optional + LabelSelector *metav1.LabelSelector `json:"labelSelector,omitempty"` +} + +// TestResourceStatus defines the observed state of TestResource +type TestResourceStatus struct { + // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster + // Important: Run "make" to regenerate code after modifying this file +} + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status + +// TestResource is the Schema for the testresources API +type TestResource struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // +required + Spec TestResourceSpec `json:"spec"` + // +optional + Status TestResourceStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// TestResourceList contains a list of TestResource +type TestResourceList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []TestResource `json:"items"` +} + +func init() { + SchemeBuilder.Register(&TestResource{}, &TestResourceList{}) +} diff --git a/test/apis/v1alpha1/zz_generated.deepcopy.go b/test/apis/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 000000000..ef7e4433a --- /dev/null +++ b/test/apis/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,114 @@ +//go:build !ignore_autogenerated + +/* +Copyright (c) Microsoft Corporation. +Licensed under the MIT license. +*/ + +// Code generated by controller-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 *TestResource) DeepCopyInto(out *TestResource) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + out.Status = in.Status +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestResource. +func (in *TestResource) DeepCopy() *TestResource { + if in == nil { + return nil + } + out := new(TestResource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *TestResource) 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 *TestResourceList) DeepCopyInto(out *TestResourceList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]TestResource, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestResourceList. +func (in *TestResourceList) DeepCopy() *TestResourceList { + if in == nil { + return nil + } + out := new(TestResourceList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *TestResourceList) 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 *TestResourceSpec) DeepCopyInto(out *TestResourceSpec) { + *out = *in + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.LabelSelector != nil { + in, out := &in.LabelSelector, &out.LabelSelector + *out = new(v1.LabelSelector) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestResourceSpec. +func (in *TestResourceSpec) DeepCopy() *TestResourceSpec { + if in == nil { + return nil + } + out := new(TestResourceSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TestResourceStatus) DeepCopyInto(out *TestResourceStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestResourceStatus. +func (in *TestResourceStatus) DeepCopy() *TestResourceStatus { + if in == nil { + return nil + } + out := new(TestResourceStatus) + in.DeepCopyInto(out) + return out +} diff --git a/test/e2e/resources/test-cloneset.yaml b/test/e2e/resources/test-cloneset.yaml deleted file mode 100644 index ef6c5efc5..000000000 --- a/test/e2e/resources/test-cloneset.yaml +++ /dev/null @@ -1,25 +0,0 @@ -apiVersion: apps.kruise.io/v1alpha1 -kind: CloneSet -metadata: - name: guestbook-clone - namespace: app -spec: - replicas: 20 - selector: - matchLabels: - app.kubernetes.io/name: guestbook-clone - template: - metadata: - labels: - app.kubernetes.io/name: guestbook-clone - spec: - containers: - - name: guestbook - image: openkruise/guestbook:v1 - imagePullPolicy: Always - ports: - - name: http-server - containerPort: 3000 - updateStrategy: - type: InPlaceIfPossible - maxUnavailable: 3 \ No newline at end of file diff --git a/test/e2e/resources/test_clonesets_crd.yaml b/test/e2e/resources/test_clonesets_crd.yaml deleted file mode 100644 index 1cb0b93c2..000000000 --- a/test/e2e/resources/test_clonesets_crd.yaml +++ /dev/null @@ -1,498 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.7.0 - labels: - fleet.azure.com/name: test-placement - name: clonesets.apps.kruise.io -spec: - group: apps.kruise.io - names: - kind: CloneSet - listKind: CloneSetList - plural: clonesets - shortNames: - - clone - singular: cloneset - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: The desired number of pods. - jsonPath: .spec.replicas - name: DESIRED - type: integer - - description: The number of pods updated. - jsonPath: .status.updatedReplicas - name: UPDATED - type: integer - - description: The number of pods updated and ready. - jsonPath: .status.updatedReadyReplicas - name: UPDATED_READY - type: integer - - description: The number of pods ready. - jsonPath: .status.readyReplicas - name: READY - type: integer - - description: The number of currently all pods. - jsonPath: .status.replicas - name: TOTAL - type: integer - - description: CreationTimestamp is a timestamp representing the server time when - this object was created. It is not guaranteed to be set in happens-before - order across separate operations. Clients may not set this value. It is represented - in RFC3339 form and is in UTC. - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - description: The containers of currently cloneset. - jsonPath: .spec.template.spec.containers[*].name - name: CONTAINERS - priority: 1 - type: string - - description: The images of currently cloneset. - jsonPath: .spec.template.spec.containers[*].image - name: IMAGES - priority: 1 - type: string - - description: The selector of currently cloneset. - jsonPath: .status.labelSelector - name: SELECTOR - priority: 1 - type: string - name: v1alpha1 - schema: - openAPIV3Schema: - description: CloneSet is the Schema for the clonesets API - 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: CloneSetSpec defines the desired state of CloneSet - properties: - lifecycle: - description: Lifecycle defines the lifecycle hooks for Pods pre-delete, - in-place update. - properties: - inPlaceUpdate: - description: InPlaceUpdate is the hook before Pod to update and - after Pod has been updated. - properties: - finalizersHandler: - items: - type: string - type: array - labelsHandler: - additionalProperties: - type: string - type: object - markPodNotReady: - description: 'MarkPodNotReady = true means: - Pod will be - set to ''NotReady'' at preparingDelete/preparingUpdate state. - - Pod will be restored to ''Ready'' at Updated state if - it was set to ''NotReady'' at preparingUpdate state. Default - to false.' - type: boolean - type: object - preDelete: - description: PreDelete is the hook before Pod to be deleted. - properties: - finalizersHandler: - items: - type: string - type: array - labelsHandler: - additionalProperties: - type: string - type: object - markPodNotReady: - description: 'MarkPodNotReady = true means: - Pod will be - set to ''NotReady'' at preparingDelete/preparingUpdate state. - - Pod will be restored to ''Ready'' at Updated state if - it was set to ''NotReady'' at preparingUpdate state. Default - to false.' - type: boolean - type: object - type: object - minReadySeconds: - description: Minimum number of seconds for which a newly created pod - should be ready without any of its container crashing, for it to - be considered available. Defaults to 0 (pod will be considered available - as soon as it is ready) - format: int32 - type: integer - replicas: - description: Replicas is the desired number of replicas of the given - Template. These are replicas in the sense that they are instantiations - of the same Template. If unspecified, defaults to 1. - format: int32 - type: integer - revisionHistoryLimit: - description: RevisionHistoryLimit is the maximum number of revisions - that will be maintained in the CloneSet's revision history. The - revision history consists of all revisions not represented by a - currently applied CloneSetSpec version. The default value is 10. - format: int32 - type: integer - scaleStrategy: - description: ScaleStrategy indicates the ScaleStrategy that will be - employed to create and delete Pods in the CloneSet. - properties: - maxUnavailable: - anyOf: - - type: integer - - type: string - description: The maximum number of pods that can be unavailable - for scaled pods. This field can control the changes rate of - replicas for CloneSet so as to minimize the impact for users' - service. The scale will fail if the number of unavailable pods - were greater than this MaxUnavailable at scaling up. MaxUnavailable - works only when scaling up. - x-kubernetes-int-or-string: true - podsToDelete: - description: PodsToDelete is the names of Pod should be deleted. - Note that this list will be truncated for non-existing pod names. - items: - type: string - type: array - type: object - selector: - description: 'Selector is a label query over pods that should match - the replica count. It must match the pod template''s labels. More - info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors' - 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 - template: - description: Template describes the pods that will be created. - x-kubernetes-preserve-unknown-fields: true - updateStrategy: - description: UpdateStrategy indicates the UpdateStrategy that will - be employed to update Pods in the CloneSet when a revision is made - to Template. - properties: - inPlaceUpdateStrategy: - description: InPlaceUpdateStrategy contains strategies for in-place - update. - properties: - gracePeriodSeconds: - description: GracePeriodSeconds is the timespan between set - Pod status to not-ready and update images in Pod spec when - in-place update a Pod. - format: int32 - type: integer - type: object - maxSurge: - anyOf: - - type: integer - - type: string - description: 'The maximum number of pods that can be scheduled - above the desired replicas during update or specified delete. - Value can be an absolute number (ex: 5) or a percentage of desired - pods (ex: 10%). Absolute number is calculated from percentage - by rounding up. Defaults to 0.' - x-kubernetes-int-or-string: true - maxUnavailable: - anyOf: - - type: integer - - type: string - description: 'The maximum number of pods that can be unavailable - during update or scale. Value can be an absolute number (ex: - 5) or a percentage of desired pods (ex: 10%). Absolute number - is calculated from percentage by rounding up by default. When - maxSurge > 0, absolute number is calculated from percentage - by rounding down. Defaults to 20%.' - x-kubernetes-int-or-string: true - partition: - anyOf: - - type: integer - - type: string - description: 'Partition is the desired number of pods in old revisions. - Value can be an absolute number (ex: 5) or a percentage of desired - pods (ex: 10%). Absolute number is calculated from percentage - by rounding up by default. It means when partition is set during - pods updating, (replicas - partition value) number of pods will - be updated. Default value is 0.' - x-kubernetes-int-or-string: true - paused: - description: Paused indicates that the CloneSet is paused. Default - value is false - type: boolean - priorityStrategy: - description: Priorities are the rules for calculating the priority - of updating pods. Each pod to be updated, will pass through - these terms and get a sum of weights. - properties: - orderPriority: - description: 'Order priority terms, pods will be sorted by - the value of orderedKey. For example: ``` orderPriority: - - orderedKey: key1 - orderedKey: key2 ``` First, all pods - which have key1 in labels will be sorted by the value of - key1. Then, the left pods which have no key1 but have key2 - in labels will be sorted by the value of key2 and put behind - those pods have key1.' - items: - description: UpdatePriorityOrder defines order priority. - properties: - orderedKey: - description: Calculate priority by value of this key. - Values of this key, will be sorted by GetInt(val). - GetInt method will find the last int in value, such - as getting 5 in value '5', getting 10 in value 'sts-10'. - type: string - required: - - orderedKey - type: object - type: array - weightPriority: - description: Weight priority terms, pods will be sorted by - the sum of all terms weight. - items: - description: UpdatePriorityWeightTerm defines weight priority. - properties: - matchSelector: - description: MatchSelector is used to select by pod's - labels. - 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 - weight: - description: Weight associated with matching the corresponding - matchExpressions, in the range 1-100. - format: int32 - type: integer - required: - - matchSelector - - weight - type: object - type: array - type: object - scatterStrategy: - description: ScatterStrategy defines the scatter rules to make - pods been scattered when update. This will avoid pods with the - same key-value to be updated in one batch. - Note that pods - will be scattered after priority sort. So, although priority - strategy and scatter strategy can be applied together, we suggest - to use either one of them. - If scatterStrategy is used, we - suggest to just use one term. Otherwise, the update order can - be hard to understand. - items: - properties: - key: - type: string - value: - type: string - required: - - key - - value - type: object - type: array - type: - description: Type indicates the type of the CloneSetUpdateStrategy. - Default is ReCreate. - type: string - type: object - volumeClaimTemplates: - description: VolumeClaimTemplates is a list of claims that pods are - allowed to reference. Note that PVC will be deleted when its pod - has been deleted. - x-kubernetes-preserve-unknown-fields: true - required: - - selector - - template - type: object - status: - description: CloneSetStatus defines the observed state of CloneSet - properties: - availableReplicas: - description: AvailableReplicas is the number of Pods created by the - CloneSet controller that have a Ready Condition for at least minReadySeconds. - format: int32 - type: integer - collisionCount: - description: CollisionCount is the count of hash collisions for the - CloneSet. The CloneSet controller uses this field as a collision - avoidance mechanism when it needs to create the name for the newest - ControllerRevision. - format: int32 - type: integer - conditions: - description: Conditions represents the latest available observations - of a CloneSet's current state. - items: - description: CloneSetCondition describes the state of a CloneSet - at a certain point. - properties: - lastTransitionTime: - description: Last time the condition transitioned from one status - to another. - format: date-time - type: string - message: - description: A human readable message indicating details about - the transition. - type: string - reason: - description: The reason for the condition's last transition. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: Type of CloneSet condition. - type: string - required: - - status - - type - type: object - type: array - currentRevision: - description: currentRevision, if not empty, indicates the current - revision version of the CloneSet. - type: string - expectedUpdatedReplicas: - description: ExpectedUpdatedReplicas is the number of Pods that should - be updated by CloneSet controller. This field is calculated via - Replicas - Partition. - format: int32 - type: integer - labelSelector: - description: LabelSelector is label selectors for query over pods - that should match the replica count used by HPA. - type: string - observedGeneration: - description: ObservedGeneration is the most recent generation observed - for this CloneSet. It corresponds to the CloneSet's generation, - which is updated on mutation by the API Server. - format: int64 - type: integer - readyReplicas: - description: ReadyReplicas is the number of Pods created by the CloneSet - controller that have a Ready Condition. - format: int32 - type: integer - replicas: - description: Replicas is the number of Pods created by the CloneSet - controller. - format: int32 - type: integer - updateRevision: - description: UpdateRevision, if not empty, indicates the latest revision - of the CloneSet. - type: string - updatedReadyReplicas: - description: UpdatedReadyReplicas is the number of Pods created by - the CloneSet controller from the CloneSet version indicated by updateRevision - and have a Ready Condition. - format: int32 - type: integer - updatedReplicas: - description: UpdatedReplicas is the number of Pods created by the - CloneSet controller from the CloneSet version indicated by updateRevision. - format: int32 - type: integer - required: - - availableReplicas - - readyReplicas - - replicas - - updatedReadyReplicas - - updatedReplicas - type: object - type: object - served: true - storage: true - subresources: - scale: - labelSelectorPath: .status.labelSelector - specReplicasPath: .spec.replicas - statusReplicasPath: .status.replicas diff --git a/test/e2e/v1alpha1/webhook_test.go b/test/e2e/v1alpha1/webhook_test.go index df780efb2..0bd12217b 100644 --- a/test/e2e/v1alpha1/webhook_test.go +++ b/test/e2e/v1alpha1/webhook_test.go @@ -600,12 +600,12 @@ var _ = Describe("Fleet's CRD Resource Handler webhook tests", func() { It("should allow CREATE operation on Other CRDs", func() { var crd apiextensionsv1.CustomResourceDefinition - Expect(utils.GetObjectFromManifest("./test/integration/manifests/resources/test_clonesets_crd.yaml", &crd)).Should(Succeed()) + Expect(utils.GetObjectFromManifest("./test/integration/manifests/resources/test_testresources_crd.yaml", &crd)).Should(Succeed()) - By("expecting error to be nil") + By("create test resource CRD") Expect(HubCluster.KubeClient.Create(ctx, &crd)).To(Succeed()) - By("delete clone set CRD") + By("delete test resource CRD") Expect(HubCluster.KubeClient.Delete(ctx, &crd)).To(Succeed()) }) }) diff --git a/test/integration/cluster_placement_test.go b/test/integration/cluster_placement_test.go index 6d2fba76d..6a3191bb4 100644 --- a/test/integration/cluster_placement_test.go +++ b/test/integration/cluster_placement_test.go @@ -14,7 +14,6 @@ import ( "github.com/google/go-cmp/cmp/cmpopts" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - kruisev1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1" adminv1 "k8s.io/api/admissionregistration/v1" coordv1 "k8s.io/api/coordination/v1" corev1 "k8s.io/api/core/v1" @@ -33,6 +32,7 @@ import ( "go.goms.io/fleet/pkg/controllers/clusterresourceplacement" workv1alpha1controller "go.goms.io/fleet/pkg/controllers/workv1alpha1" "go.goms.io/fleet/pkg/utils" + testv1alpha1 "go.goms.io/fleet/test/apis/v1alpha1" ) const ClusterRoleKind = "ClusterRole" @@ -145,7 +145,7 @@ var _ = Describe("Test Cluster Resource Placement Controller", func() { Group: apiextensionsv1.GroupName, Version: "v1", Kind: "CustomResourceDefinition", - Name: "clonesets.apps.kruise.io", + Name: "testresources.test.kubernetes-fleet.io", }, }, }, @@ -587,34 +587,34 @@ var _ = Describe("Test Cluster Resource Placement Controller", func() { By("Select all the resources in a namespace clusterResourcePlacement created") By("Create a new namespace") - newSpace := corev1.Namespace{ + newNamespace := corev1.Namespace{ ObjectMeta: metav1.ObjectMeta{ Name: "test-delete-namespace" + utilrand.String(10), Labels: nsLabel, }, } - Expect(k8sClient.Create(ctx, &newSpace)).Should(Succeed()) - By(fmt.Sprintf("Create a new namespace %s clusterResourcePlacement will select", newSpace.Name)) + Expect(k8sClient.Create(ctx, &newNamespace)).Should(Succeed()) + By(fmt.Sprintf("Create a new namespace %s clusterResourcePlacement will select", newNamespace.Name)) By("Create a new Pdb in the new namespace") newPdb := testPdb.DeepCopy() - newPdb.Namespace = newSpace.Name + newPdb.Namespace = newNamespace.Name newPdb.SetResourceVersion("") newPdb.SetGeneration(0) Expect(k8sClient.Create(ctx, newPdb)).Should(Succeed()) - By("Create a new CloneSet in the new namespace") - newCloneSet := testCloneset.DeepCopy() - newCloneSet.Namespace = newSpace.Name - newCloneSet.SetResourceVersion("") - newCloneSet.SetGeneration(0) - Expect(k8sClient.Create(ctx, newCloneSet)).Should(Succeed()) + By("Create a new TestResource in the new namespace") + newTestResource := testResource.DeepCopy() + newTestResource.Namespace = newNamespace.Name + newTestResource.SetResourceVersion("") + newTestResource.SetGeneration(0) + Expect(k8sClient.Create(ctx, newTestResource)).Should(Succeed()) By("Verify that we pick up the clusterRole and all the resources we created in the new namespace") - verifyPartialWorkObjects(crp, []string{"PodDisruptionBudget", "CloneSet", ClusterRoleKind}, 4, []*fleetv1alpha1.MemberCluster{&clusterA, &clusterB}) + verifyPartialWorkObjects(crp, []string{"PodDisruptionBudget", "TestResource", ClusterRoleKind}, 4, []*fleetv1alpha1.MemberCluster{&clusterA, &clusterB}) By("Remove the namespace resource") - Expect(k8sClient.Delete(ctx, &newSpace)).Should(Succeed()) + Expect(k8sClient.Delete(ctx, &newNamespace)).Should(Succeed()) By("Verify that we pick up the namespace delete") verifyWorkObjects(crp, []string{ClusterRoleKind}, []*fleetv1alpha1.MemberCluster{&clusterA, &clusterB}) @@ -806,7 +806,7 @@ var _ = Describe("Test Cluster Resource Placement Controller", func() { Group: apiextensionsv1.GroupName, Version: "v1", Kind: "CustomResourceDefinition", - Name: "clonesets.apps.kruise.io", + Name: "testresources.test.kubernetes-fleet.io", }, }, Policy: &fleetv1alpha1.PlacementPolicy{ @@ -1620,25 +1620,20 @@ var _ = Describe("Test Cluster Resource Placement Controller", func() { }, } Expect(k8sClient.Create(ctx, ns)).Should(Succeed(), "Failed to create %s namespace", ns.Name) - By("create clone set") - cs := &kruisev1alpha1.CloneSet{ + By("create test resource") + tr := &testv1alpha1.TestResource{ ObjectMeta: metav1.ObjectMeta{ - Name: "test-cloneset", + Name: "test-resource-name", Namespace: ns.Name, }, - Spec: kruisev1alpha1.CloneSetSpec{ - Replicas: ptr.To(int32(20)), - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{"app.kubernetes.io/name": "test-clone-set"}, - }, - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{"app.kubernetes.io/name": "test-clone-set"}, - }, + Spec: testv1alpha1.TestResourceSpec{ + Foo: "foo", + LabelSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{"app.kubernetes.io/name": "test-resource-name"}, }, }, } - Expect(k8sClient.Create(ctx, cs)).Should(Succeed(), "Failed to create %s clone set", cs.Name) + Expect(k8sClient.Create(ctx, tr)).Should(Succeed(), "Failed to create %s test resource", tr.Name) By("create clusterResourcePlacement CR") crp = &fleetv1alpha1.ClusterResourcePlacement{ ObjectMeta: metav1.ObjectMeta{ @@ -1662,13 +1657,13 @@ var _ = Describe("Test Cluster Resource Placement Controller", func() { var clusterWork workv1alpha1.Work workResourceIdentifier1 := workv1alpha1.ResourceIdentifier{ - Group: kruisev1alpha1.GroupVersion.Group, - Kind: "CloneSet", - Name: cs.Name, - Namespace: cs.Namespace, + Group: testv1alpha1.GroupVersion.Group, + Kind: "TestResource", + Name: tr.Name, + Namespace: tr.Namespace, Ordinal: 0, - Resource: "clonesets", - Version: kruisev1alpha1.GroupVersion.Version, + Resource: "testresources", + Version: testv1alpha1.GroupVersion.Version, } workResourceIdentifier2 := workv1alpha1.ResourceIdentifier{ Group: corev1.GroupName, @@ -1676,7 +1671,7 @@ var _ = Describe("Test Cluster Resource Placement Controller", func() { Name: ns.Name, Ordinal: 1, Resource: "namespaces", - Version: "v1", + Version: corev1.SchemeGroupVersion.Version, } Eventually(func() error { @@ -1720,11 +1715,11 @@ var _ = Describe("Test Cluster Resource Placement Controller", func() { Expect(k8sClient.Status().Update(ctx, &clusterWork)).Should(Succeed(), "Failed to update %s work status", clusterWork.Name) fleetResourceIdentifier1 := fleetv1alpha1.ResourceIdentifier{ - Group: kruisev1alpha1.GroupVersion.Group, - Version: kruisev1alpha1.GroupVersion.Version, - Kind: "CloneSet", - Name: cs.Name, - Namespace: cs.Namespace, + Group: testv1alpha1.GroupVersion.Group, + Version: testv1alpha1.GroupVersion.Version, + Kind: "TestResource", + Name: tr.Name, + Namespace: tr.Namespace, } fleetResourceIdentifier2 := fleetv1alpha1.ResourceIdentifier{ Group: corev1.GroupName, @@ -1785,7 +1780,7 @@ var _ = Describe("Test Cluster Resource Placement Controller", func() { Group: apiextensionsv1.GroupName, Version: "v1", Kind: "CustomResourceDefinition", - Name: "clonesets.apps.kruise.io", + Name: "testresources.test.kubernetes-fleet.io", }, { Group: corev1.GroupName, @@ -1805,7 +1800,7 @@ var _ = Describe("Test Cluster Resource Placement Controller", func() { workResourceIdentifier2 = workv1alpha1.ResourceIdentifier{ Group: apiextensionsv1.GroupName, Kind: "CustomResourceDefinition", - Name: "clonesets.apps.kruise.io", + Name: "testresources.test.kubernetes-fleet.io", Ordinal: 1, Resource: "customresourcedefinitions", Version: "v1", @@ -1834,7 +1829,7 @@ var _ = Describe("Test Cluster Resource Placement Controller", func() { Group: apiextensionsv1.GroupName, Version: "v1", Kind: "CustomResourceDefinition", - Name: "clonesets.apps.kruise.io", + Name: "testresources.test.kubernetes-fleet.io", } wantCRPStatus = fleetv1alpha1.ClusterResourcePlacementStatus{ diff --git a/test/integration/manifests/placement/select-named-resource.yaml b/test/integration/manifests/placement/select-named-resource.yaml deleted file mode 100644 index e6f4a4998..000000000 --- a/test/integration/manifests/placement/select-named-resource.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: fleet.azure.com/v1alpha1 -kind: ClusterResourcePlacement -metadata: - name: test-list-resource -spec: - resourceSelectors: - - group: rbac.authorization.k8s.io - version: v1 - kind: ClusterRole - name: test-cluster-role - - group: apiextensions.k8s.io - version: v1 - kind: CustomResourceDefinition - name: clonesets.apps.kruise.io \ No newline at end of file diff --git a/test/integration/manifests/placement/select-or-cluster.yaml b/test/integration/manifests/placement/select-or-cluster.yaml deleted file mode 100644 index 6f73e1a9b..000000000 --- a/test/integration/manifests/placement/select-or-cluster.yaml +++ /dev/null @@ -1,20 +0,0 @@ -apiVersion: fleet.azure.com/v1alpha1 -kind: ClusterResourcePlacement -metadata: - name: test-select-or-cluster -spec: - resourceSelectors: - - group: apiextensions.k8s.io - version: v1 - kind: CustomResourceDefinition - name: clonesets.apps.kruise.io - policy: - affinity: - clusterAffinity: - clusterSelectorTerms: - - labelSelector: - matchLabels: - fleet.azure.com/region: eu - - labelSelector: - matchLabels: - env: prod diff --git a/test/integration/manifests/resources/test-cloneset.yaml b/test/integration/manifests/resources/test-cloneset.yaml deleted file mode 100644 index ef6c5efc5..000000000 --- a/test/integration/manifests/resources/test-cloneset.yaml +++ /dev/null @@ -1,25 +0,0 @@ -apiVersion: apps.kruise.io/v1alpha1 -kind: CloneSet -metadata: - name: guestbook-clone - namespace: app -spec: - replicas: 20 - selector: - matchLabels: - app.kubernetes.io/name: guestbook-clone - template: - metadata: - labels: - app.kubernetes.io/name: guestbook-clone - spec: - containers: - - name: guestbook - image: openkruise/guestbook:v1 - imagePullPolicy: Always - ports: - - name: http-server - containerPort: 3000 - updateStrategy: - type: InPlaceIfPossible - maxUnavailable: 3 \ No newline at end of file diff --git a/test/integration/manifests/resources/test-resource.yaml b/test/integration/manifests/resources/test-resource.yaml new file mode 100644 index 000000000..8eb8a2170 --- /dev/null +++ b/test/integration/manifests/resources/test-resource.yaml @@ -0,0 +1,10 @@ +apiVersion: test.kubernetes-fleet.io/v1alpha1 +kind: TestResource +metadata: + name: random-test-resource + namespace: app +spec: + foo: foo1 + items: + - a + - b \ No newline at end of file diff --git a/test/integration/manifests/resources/test_clonesets_crd.yaml b/test/integration/manifests/resources/test_clonesets_crd.yaml deleted file mode 100644 index 747fbc045..000000000 --- a/test/integration/manifests/resources/test_clonesets_crd.yaml +++ /dev/null @@ -1,506 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.7.0 - labels: - fleet.azure.com/name: test-placement - creationTimestamp: null - name: clonesets.apps.kruise.io -spec: - group: apps.kruise.io - names: - kind: CloneSet - listKind: CloneSetList - plural: clonesets - shortNames: - - clone - singular: cloneset - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: The desired number of pods. - jsonPath: .spec.replicas - name: DESIRED - type: integer - - description: The number of pods updated. - jsonPath: .status.updatedReplicas - name: UPDATED - type: integer - - description: The number of pods updated and ready. - jsonPath: .status.updatedReadyReplicas - name: UPDATED_READY - type: integer - - description: The number of pods ready. - jsonPath: .status.readyReplicas - name: READY - type: integer - - description: The number of currently all pods. - jsonPath: .status.replicas - name: TOTAL - type: integer - - description: CreationTimestamp is a timestamp representing the server time when - this object was created. It is not guaranteed to be set in happens-before - order across separate operations. Clients may not set this value. It is represented - in RFC3339 form and is in UTC. - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - - description: The containers of currently cloneset. - jsonPath: .spec.template.spec.containers[*].name - name: CONTAINERS - priority: 1 - type: string - - description: The images of currently cloneset. - jsonPath: .spec.template.spec.containers[*].image - name: IMAGES - priority: 1 - type: string - - description: The selector of currently cloneset. - jsonPath: .status.labelSelector - name: SELECTOR - priority: 1 - type: string - name: v1alpha1 - schema: - openAPIV3Schema: - description: CloneSet is the Schema for the clonesets API - 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: CloneSetSpec defines the desired state of CloneSet - properties: - lifecycle: - description: Lifecycle defines the lifecycle hooks for Pods pre-delete, - in-place update. - properties: - inPlaceUpdate: - description: InPlaceUpdate is the hook before Pod to update and - after Pod has been updated. - properties: - finalizersHandler: - items: - type: string - type: array - labelsHandler: - additionalProperties: - type: string - type: object - markPodNotReady: - description: 'MarkPodNotReady = true means: - Pod will be - set to ''NotReady'' at preparingDelete/preparingUpdate state. - - Pod will be restored to ''Ready'' at Updated state if - it was set to ''NotReady'' at preparingUpdate state. Default - to false.' - type: boolean - type: object - preDelete: - description: PreDelete is the hook before Pod to be deleted. - properties: - finalizersHandler: - items: - type: string - type: array - labelsHandler: - additionalProperties: - type: string - type: object - markPodNotReady: - description: 'MarkPodNotReady = true means: - Pod will be - set to ''NotReady'' at preparingDelete/preparingUpdate state. - - Pod will be restored to ''Ready'' at Updated state if - it was set to ''NotReady'' at preparingUpdate state. Default - to false.' - type: boolean - type: object - type: object - minReadySeconds: - description: Minimum number of seconds for which a newly created pod - should be ready without any of its container crashing, for it to - be considered available. Defaults to 0 (pod will be considered available - as soon as it is ready) - format: int32 - type: integer - replicas: - description: Replicas is the desired number of replicas of the given - Template. These are replicas in the sense that they are instantiations - of the same Template. If unspecified, defaults to 1. - format: int32 - type: integer - revisionHistoryLimit: - description: RevisionHistoryLimit is the maximum number of revisions - that will be maintained in the CloneSet's revision history. The - revision history consists of all revisions not represented by a - currently applied CloneSetSpec version. The default value is 10. - format: int32 - type: integer - scaleStrategy: - description: ScaleStrategy indicates the ScaleStrategy that will be - employed to create and delete Pods in the CloneSet. - properties: - maxUnavailable: - anyOf: - - type: integer - - type: string - description: The maximum number of pods that can be unavailable - for scaled pods. This field can control the changes rate of - replicas for CloneSet so as to minimize the impact for users' - service. The scale will fail if the number of unavailable pods - were greater than this MaxUnavailable at scaling up. MaxUnavailable - works only when scaling up. - x-kubernetes-int-or-string: true - podsToDelete: - description: PodsToDelete is the names of Pod should be deleted. - Note that this list will be truncated for non-existing pod names. - items: - type: string - type: array - type: object - selector: - description: 'Selector is a label query over pods that should match - the replica count. It must match the pod template''s labels. More - info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors' - 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 - template: - description: Template describes the pods that will be created. - x-kubernetes-preserve-unknown-fields: true - updateStrategy: - description: UpdateStrategy indicates the UpdateStrategy that will - be employed to update Pods in the CloneSet when a revision is made - to Template. - properties: - inPlaceUpdateStrategy: - description: InPlaceUpdateStrategy contains strategies for in-place - update. - properties: - gracePeriodSeconds: - description: GracePeriodSeconds is the timespan between set - Pod status to not-ready and update images in Pod spec when - in-place update a Pod. - format: int32 - type: integer - type: object - maxSurge: - anyOf: - - type: integer - - type: string - description: 'The maximum number of pods that can be scheduled - above the desired replicas during update or specified delete. - Value can be an absolute number (ex: 5) or a percentage of desired - pods (ex: 10%). Absolute number is calculated from percentage - by rounding up. Defaults to 0.' - x-kubernetes-int-or-string: true - maxUnavailable: - anyOf: - - type: integer - - type: string - description: 'The maximum number of pods that can be unavailable - during update or scale. Value can be an absolute number (ex: - 5) or a percentage of desired pods (ex: 10%). Absolute number - is calculated from percentage by rounding up by default. When - maxSurge > 0, absolute number is calculated from percentage - by rounding down. Defaults to 20%.' - x-kubernetes-int-or-string: true - partition: - anyOf: - - type: integer - - type: string - description: 'Partition is the desired number of pods in old revisions. - Value can be an absolute number (ex: 5) or a percentage of desired - pods (ex: 10%). Absolute number is calculated from percentage - by rounding up by default. It means when partition is set during - pods updating, (replicas - partition value) number of pods will - be updated. Default value is 0.' - x-kubernetes-int-or-string: true - paused: - description: Paused indicates that the CloneSet is paused. Default - value is false - type: boolean - priorityStrategy: - description: Priorities are the rules for calculating the priority - of updating pods. Each pod to be updated, will pass through - these terms and get a sum of weights. - properties: - orderPriority: - description: 'Order priority terms, pods will be sorted by - the value of orderedKey. For example: ``` orderPriority: - - orderedKey: key1 - orderedKey: key2 ``` First, all pods - which have key1 in labels will be sorted by the value of - key1. Then, the left pods which have no key1 but have key2 - in labels will be sorted by the value of key2 and put behind - those pods have key1.' - items: - description: UpdatePriorityOrder defines order priority. - properties: - orderedKey: - description: Calculate priority by value of this key. - Values of this key, will be sorted by GetInt(val). - GetInt method will find the last int in value, such - as getting 5 in value '5', getting 10 in value 'sts-10'. - type: string - required: - - orderedKey - type: object - type: array - weightPriority: - description: Weight priority terms, pods will be sorted by - the sum of all terms weight. - items: - description: UpdatePriorityWeightTerm defines weight priority. - properties: - matchSelector: - description: MatchSelector is used to select by pod's - labels. - 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 - weight: - description: Weight associated with matching the corresponding - matchExpressions, in the range 1-100. - format: int32 - type: integer - required: - - matchSelector - - weight - type: object - type: array - type: object - scatterStrategy: - description: ScatterStrategy defines the scatter rules to make - pods been scattered when update. This will avoid pods with the - same key-value to be updated in one batch. - Note that pods - will be scattered after priority sort. So, although priority - strategy and scatter strategy can be applied together, we suggest - to use either one of them. - If scatterStrategy is used, we - suggest to just use one term. Otherwise, the update order can - be hard to understand. - items: - properties: - key: - type: string - value: - type: string - required: - - key - - value - type: object - type: array - type: - description: Type indicates the type of the CloneSetUpdateStrategy. - Default is ReCreate. - type: string - type: object - volumeClaimTemplates: - description: VolumeClaimTemplates is a list of claims that pods are - allowed to reference. Note that PVC will be deleted when its pod - has been deleted. - x-kubernetes-preserve-unknown-fields: true - required: - - selector - - template - type: object - status: - description: CloneSetStatus defines the observed state of CloneSet - properties: - availableReplicas: - description: AvailableReplicas is the number of Pods created by the - CloneSet controller that have a Ready Condition for at least minReadySeconds. - format: int32 - type: integer - collisionCount: - description: CollisionCount is the count of hash collisions for the - CloneSet. The CloneSet controller uses this field as a collision - avoidance mechanism when it needs to create the name for the newest - ControllerRevision. - format: int32 - type: integer - conditions: - description: Conditions represents the latest available observations - of a CloneSet's current state. - items: - description: CloneSetCondition describes the state of a CloneSet - at a certain point. - properties: - lastTransitionTime: - description: Last time the condition transitioned from one status - to another. - format: date-time - type: string - message: - description: A human readable message indicating details about - the transition. - type: string - reason: - description: The reason for the condition's last transition. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: Type of CloneSet condition. - type: string - required: - - status - - type - type: object - type: array - currentRevision: - description: currentRevision, if not empty, indicates the current - revision version of the CloneSet. - type: string - expectedUpdatedReplicas: - description: ExpectedUpdatedReplicas is the number of Pods that should - be updated by CloneSet controller. This field is calculated via - Replicas - Partition. - format: int32 - type: integer - labelSelector: - description: LabelSelector is label selectors for query over pods - that should match the replica count used by HPA. - type: string - observedGeneration: - description: ObservedGeneration is the most recent generation observed - for this CloneSet. It corresponds to the CloneSet's generation, - which is updated on mutation by the API Server. - format: int64 - type: integer - readyReplicas: - description: ReadyReplicas is the number of Pods created by the CloneSet - controller that have a Ready Condition. - format: int32 - type: integer - replicas: - description: Replicas is the number of Pods created by the CloneSet - controller. - format: int32 - type: integer - updateRevision: - description: UpdateRevision, if not empty, indicates the latest revision - of the CloneSet. - type: string - updatedReadyReplicas: - description: UpdatedReadyReplicas is the number of Pods created by - the CloneSet controller from the CloneSet version indicated by updateRevision - and have a Ready Condition. - format: int32 - type: integer - updatedReplicas: - description: UpdatedReplicas is the number of Pods created by the - CloneSet controller from the CloneSet version indicated by updateRevision. - format: int32 - type: integer - required: - - availableReplicas - - readyReplicas - - replicas - - updatedReadyReplicas - - updatedReplicas - type: object - type: object - served: true - storage: true - subresources: - scale: - labelSelectorPath: .status.labelSelector - specReplicasPath: .spec.replicas - statusReplicasPath: .status.replicas - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] diff --git a/test/integration/manifests/resources/test_testresources_crd.yaml b/test/integration/manifests/resources/test_testresources_crd.yaml new file mode 100644 index 000000000..d8e762069 --- /dev/null +++ b/test/integration/manifests/resources/test_testresources_crd.yaml @@ -0,0 +1,111 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + labels: + fleet.azure.com/name: test-placement + annotations: + controller-gen.kubebuilder.io/version: v0.15.0 + name: testresources.test.kubernetes-fleet.io +spec: + group: test.kubernetes-fleet.io + names: + kind: TestResource + listKind: TestResourceList + plural: testresources + singular: testresource + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: TestResource is the Schema for the testresources API + 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: TestResourceSpec defines the desired state of TestResource + properties: + bar: + type: string + foo: + type: string + items: + items: + type: string + type: array + labelSelector: + description: |- + A label selector is a label query over a set of resources. The result of matchLabels and + matchExpressions are ANDed. An empty label selector matches all objects. A null + label selector matches no objects. + 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 + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + 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 + type: object + status: + description: TestResourceStatus defines the observed state of TestResource + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} diff --git a/test/integration/suite_test.go b/test/integration/suite_test.go index fe3f8f118..e4c7096f4 100644 --- a/test/integration/suite_test.go +++ b/test/integration/suite_test.go @@ -11,11 +11,8 @@ import ( "path/filepath" "testing" - fleetv1beta1 "go.goms.io/fleet/apis/placement/v1beta1" - . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - kruisev1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1" "k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/client-go/kubernetes/scheme" "k8s.io/klog/v2" @@ -25,12 +22,12 @@ import ( "sigs.k8s.io/controller-runtime/pkg/manager" workv1alpha1 "sigs.k8s.io/work-api/pkg/apis/v1alpha1" - // +kubebuilder:scaffold:imports - + fleetv1beta1 "go.goms.io/fleet/apis/placement/v1beta1" fleetv1alpha1 "go.goms.io/fleet/apis/v1alpha1" "go.goms.io/fleet/cmd/hubagent/options" "go.goms.io/fleet/cmd/hubagent/workload" mcv1alpha1 "go.goms.io/fleet/pkg/controllers/membercluster/v1alpha1" + testv1alpha1 "go.goms.io/fleet/test/apis/v1alpha1" ) // These tests use Ginkgo (BDD-style Go testing framework). Refer to @@ -40,7 +37,7 @@ var ( mgr manager.Manager // pre loaded test manifests - namespacedResource = []string{"Namespace", "PodDisruptionBudget", "CloneSet", "ConfigMap", "Secret", "Service"} + namespacedResource = []string{"Namespace", "PodDisruptionBudget", "TestResource", "ConfigMap", "Secret", "Service"} ) func TestAPIs(t *testing.T) { @@ -61,7 +58,7 @@ var _ = BeforeSuite(func() { By("Set all the customized scheme") Expect(fleetv1alpha1.AddToScheme(scheme.Scheme)).Should(Succeed()) Expect(workv1alpha1.AddToScheme(scheme.Scheme)).Should(Succeed()) - Expect(kruisev1alpha1.AddToScheme(scheme.Scheme)).Should(Succeed()) + Expect(testv1alpha1.AddToScheme(scheme.Scheme)).Should(Succeed()) Expect(fleetv1beta1.AddToScheme(scheme.Scheme)).Should(Succeed()) // get the codec with the all the scheme @@ -99,7 +96,7 @@ var _ = BeforeSuite(func() { }).SetupWithManager(mgr) Expect(err).Should(Succeed()) - By("Create all the test manifest resources") + By("Create/Get all the test manifest resources") applyTestManifests() By("Setup custom controllers") diff --git a/test/integration/utils_test.go b/test/integration/utils_test.go index 4ac3fd3b1..b294a8ea8 100644 --- a/test/integration/utils_test.go +++ b/test/integration/utils_test.go @@ -13,7 +13,6 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" omegatypes "github.com/onsi/gomega/types" - kruisev1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1" "golang.org/x/exp/slices" corev1 "k8s.io/api/core/v1" policyv1 "k8s.io/api/policy/v1" @@ -31,6 +30,7 @@ import ( fleetv1alpha1 "go.goms.io/fleet/apis/v1alpha1" "go.goms.io/fleet/pkg/utils" + testv1alpha1 "go.goms.io/fleet/test/apis/v1alpha1" ) const ( @@ -47,10 +47,10 @@ var ( genericCodec runtime.Decoder // pre loaded test manifests - testClonesetCRD apiextensionsv1.CustomResourceDefinition testClusterRole rbacv1.ClusterRole testNameSpace corev1.Namespace - testCloneset kruisev1alpha1.CloneSet + testResourceCRD apiextensionsv1.CustomResourceDefinition + testResource testv1alpha1.TestResource testConfigMap corev1.ConfigMap testSecret corev1.Secret testService corev1.Service @@ -60,14 +60,14 @@ var ( // applyTestManifests creates the test manifests in the hub cluster. // Here is the list, please do NOT change this list unless you know what you are doing. // ClusterScoped resource: -// Cloneset CRD, ClusterRole, Namespace +// TestResource CRD, ClusterRole, Namespace // Namespaced resources: -// Cloneset CR, Pdb, Configmap, Secret, Service. +// TestResource CR, Pdb, Configmap, Secret, Service. func applyTestManifests() { - By("Create testCloneset CRD") - err := utils.GetObjectFromManifest("manifests/resources/test_clonesets_crd.yaml", &testClonesetCRD) + By("Create testResource CRD") + err := utils.GetObjectFromManifest("manifests/resources/test_testresources_crd.yaml", &testResourceCRD) Expect(err).Should(Succeed()) - Expect(k8sClient.Create(ctx, &testClonesetCRD)).Should(Succeed()) + Expect(k8sClient.Create(ctx, &testResourceCRD)).Should(Succeed()) // TODO: replace the rest objects with programmatic definition By("Create testClusterRole resource") @@ -100,10 +100,10 @@ func applyTestManifests() { Expect(err).Should(Succeed()) Expect(k8sClient.Create(ctx, &testService)).Should(Succeed()) - By("Create testCloneset resource") - err = utils.GetObjectFromManifest("manifests/resources/test-cloneset.yaml", &testCloneset) + By("Create testResource resource") + err = utils.GetObjectFromManifest("manifests/resources/test-resource.yaml", &testResource) Expect(err).Should(Succeed()) - Expect(k8sClient.Create(ctx, &testCloneset)).Should(Succeed()) + Expect(k8sClient.Create(ctx, &testResource)).Should(Succeed()) } func deleteTestManifests() { @@ -123,11 +123,11 @@ func deleteTestManifests() { By("Delete testService resource") Expect(k8sClient.Delete(ctx, &testService)).Should(SatisfyAny(Succeed(), utils.NotFoundMatcher{})) - By("Delete testCloneset resource") - Expect(k8sClient.Delete(ctx, &testCloneset)).Should(SatisfyAny(Succeed(), utils.NotFoundMatcher{})) + By("Delete testResource resource") + Expect(k8sClient.Delete(ctx, &testResource)).Should(SatisfyAny(Succeed(), utils.NotFoundMatcher{})) - By("Delete testCloneset CRD") - Expect(k8sClient.Delete(ctx, &testClonesetCRD)).Should(SatisfyAny(Succeed(), utils.NotFoundMatcher{})) + By("Delete testResource CRD") + Expect(k8sClient.Delete(ctx, &testResourceCRD)).Should(SatisfyAny(Succeed(), utils.NotFoundMatcher{})) // delete the namespace the last as there is no GC By("Delete namespace") @@ -145,10 +145,10 @@ func verifyManifest(manifest unstructured.Unstructured) { // compare with the original switch manifest.GetObjectKind().GroupVersionKind().Kind { case "CustomResourceDefinition": - var workClonesetCRD apiextensionsv1.CustomResourceDefinition - Expect(runtime.DefaultUnstructuredConverter.FromUnstructured(manifest.Object, &workClonesetCRD)).Should(Succeed()) - Expect(workClonesetCRD.GetName()).Should(Equal(testClonesetCRD.GetName())) - Expect(workClonesetCRD.Spec.Versions[0]).Should(Equal(testClonesetCRD.Spec.Versions[0])) + var workTestResource apiextensionsv1.CustomResourceDefinition + Expect(runtime.DefaultUnstructuredConverter.FromUnstructured(manifest.Object, &workTestResource)).Should(Succeed()) + Expect(workTestResource.GetName()).Should(Equal(testResourceCRD.Name)) + Expect(workTestResource.Spec.Versions[0]).Should(Equal(testResourceCRD.Spec.Versions[0])) case "ClusterRole": var workClusterRole rbacv1.ClusterRole @@ -161,11 +161,11 @@ func verifyManifest(manifest unstructured.Unstructured) { Expect(runtime.DefaultUnstructuredConverter.FromUnstructured(manifest.Object, &workNameSpace)).Should(Succeed()) Expect(workNameSpace.GetName()).Should(Equal(testNameSpace.GetName())) - case "CloneSet": - var workCloneset kruisev1alpha1.CloneSet - Expect(runtime.DefaultUnstructuredConverter.FromUnstructured(manifest.Object, &workCloneset)).Should(Succeed()) - Expect(workCloneset.GetName()).Should(Equal(testCloneset.GetName())) - Expect(workCloneset.Spec).Should(Equal(testCloneset.Spec)) + case "TestResource": + var workTestResource testv1alpha1.TestResource + Expect(runtime.DefaultUnstructuredConverter.FromUnstructured(manifest.Object, &workTestResource)).Should(Succeed()) + Expect(workTestResource.GetName()).Should(Equal(workTestResource.GetName())) + Expect(workTestResource.Spec).Should(Equal(workTestResource.Spec)) case "ConfigMap": var workConfigMap corev1.ConfigMap