mirror of https://github.com/fluxcd/cli-utils.git
131 lines
4.3 KiB
Go
131 lines
4.3 KiB
Go
// Copyright 2022 The Kubernetes Authors.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package stress
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
. "github.com/onsi/ginkgo/v2"
|
|
. "github.com/onsi/gomega"
|
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
|
"k8s.io/klog/v2"
|
|
"sigs.k8s.io/cli-utils/pkg/apply"
|
|
"sigs.k8s.io/cli-utils/pkg/apply/event"
|
|
"sigs.k8s.io/cli-utils/pkg/common"
|
|
"sigs.k8s.io/cli-utils/pkg/inventory"
|
|
"sigs.k8s.io/cli-utils/test/e2e/e2eutil"
|
|
"sigs.k8s.io/cli-utils/test/e2e/invconfig"
|
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
|
)
|
|
|
|
// thousandDeploymentsTest tests one pre-existing namespace with 1,000
|
|
// Deployments in it.
|
|
//
|
|
// The Deployments themselves are easy to get status on, but with the retrieval
|
|
// of generated resource status (ReplicaSets & Pods), this becomes expensive.
|
|
func thousandDeploymentsTest(ctx context.Context, c client.Client, invConfig invconfig.InventoryConfig, inventoryName, namespaceName string) {
|
|
By("Apply LOTS of resources")
|
|
applier := invConfig.ApplierFactoryFunc()
|
|
inventoryID := fmt.Sprintf("%s-%s", inventoryName, namespaceName)
|
|
|
|
inventoryInfo := invconfig.CreateInventoryInfo(invConfig, inventoryName, namespaceName, inventoryID)
|
|
|
|
resources := []*unstructured.Unstructured{}
|
|
|
|
labelKey := "created-for"
|
|
labelValue := "stress-test"
|
|
|
|
deploymentObjTemplate := e2eutil.ManifestToUnstructured([]byte(deploymentYaml))
|
|
deploymentObjTemplate.SetLabels(map[string]string{labelKey: labelValue})
|
|
|
|
objectCount := 1000
|
|
|
|
for i := 1; i <= objectCount; i++ {
|
|
deploymentObj := deploymentObjTemplate.DeepCopy()
|
|
deploymentObj.SetNamespace(namespaceName)
|
|
|
|
// change name & selector labels to avoid overlap between deployments
|
|
name := fmt.Sprintf("nginx-%d", i)
|
|
deploymentObj.SetName(name)
|
|
err := unstructured.SetNestedField(deploymentObj.Object, name, "spec", "selector", "matchLabels", "app")
|
|
Expect(err).ToNot(HaveOccurred())
|
|
err = unstructured.SetNestedField(deploymentObj.Object, name, "spec", "template", "metadata", "labels", "app")
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
resources = append(resources, deploymentObj)
|
|
}
|
|
|
|
defer func() {
|
|
By("Cleanup Deployments")
|
|
e2eutil.DeleteAllUnstructuredIfExists(ctx, c, deploymentObjTemplate)
|
|
}()
|
|
|
|
start := time.Now()
|
|
|
|
applierEvents := e2eutil.RunCollect(applier.Run(ctx, inventoryInfo, resources, apply.ApplierOptions{
|
|
// SSA reduces GET+PATCH to just PATCH, which is faster
|
|
ServerSideOptions: common.ServerSideOptions{
|
|
ServerSideApply: true,
|
|
ForceConflicts: true,
|
|
FieldManager: "cli-utils.kubernetes.io",
|
|
},
|
|
ReconcileTimeout: 30 * time.Minute,
|
|
EmitStatusEvents: false,
|
|
}))
|
|
|
|
duration := time.Since(start)
|
|
klog.Infof("Applier.Run execution time: %v", duration)
|
|
|
|
for _, e := range applierEvents {
|
|
Expect(e.ErrorEvent.Err).To(BeNil())
|
|
}
|
|
for _, e := range applierEvents {
|
|
Expect(e.ApplyEvent.Error).To(BeNil(), "ApplyEvent: %v", e.ApplyEvent)
|
|
}
|
|
for _, e := range applierEvents {
|
|
if e.Type == event.WaitType {
|
|
Expect(e.WaitEvent.Status).To(BeElementOf(event.ReconcilePending, event.ReconcileSuccessful), "WaitEvent: %v", e.WaitEvent)
|
|
}
|
|
}
|
|
|
|
By("Verify inventory created")
|
|
invConfig.InvSizeVerifyFunc(ctx, c, inventoryName, namespaceName, inventoryID, len(resources), len(resources))
|
|
|
|
By(fmt.Sprintf("Verify %d Deployments created", objectCount))
|
|
e2eutil.AssertUnstructuredCount(ctx, c, deploymentObjTemplate, objectCount)
|
|
|
|
By("Destroy LOTS of resources")
|
|
destroyer := invConfig.DestroyerFactoryFunc()
|
|
|
|
start = time.Now()
|
|
|
|
destroyerEvents := e2eutil.RunCollect(destroyer.Run(ctx, inventoryInfo, apply.DestroyerOptions{
|
|
InventoryPolicy: inventory.PolicyAdoptIfNoInventory,
|
|
DeleteTimeout: 30 * time.Minute,
|
|
}))
|
|
|
|
duration = time.Since(start)
|
|
klog.Infof("Destroyer.Run execution time: %v", duration)
|
|
|
|
for _, e := range destroyerEvents {
|
|
Expect(e.ErrorEvent.Err).To(BeNil())
|
|
}
|
|
for _, e := range destroyerEvents {
|
|
Expect(e.PruneEvent.Error).To(BeNil(), "PruneEvent: %v", e.PruneEvent)
|
|
}
|
|
for _, e := range destroyerEvents {
|
|
if e.Type == event.WaitType {
|
|
Expect(e.WaitEvent.Status).To(BeElementOf(event.ReconcilePending, event.ReconcileSuccessful), "WaitEvent: %v", e.WaitEvent)
|
|
}
|
|
}
|
|
|
|
By("Verify inventory deleted")
|
|
invConfig.InvNotExistsFunc(ctx, c, inventoryName, namespaceName, inventoryID)
|
|
|
|
By(fmt.Sprintf("Verify %d Deployments deleted", objectCount))
|
|
e2eutil.AssertUnstructuredCount(ctx, c, deploymentObjTemplate, 0)
|
|
}
|