cli-utils/test/e2e/e2e_test.go

273 lines
8.3 KiB
Go

// Copyright 2020 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package e2e
import (
"context"
"fmt"
"time"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/format"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/klog/v2"
"k8s.io/kubectl/pkg/scheme"
"sigs.k8s.io/cli-utils/test/e2e/e2eutil"
"sigs.k8s.io/cli-utils/test/e2e/invconfig"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
)
const (
ConfigMapTypeInvConfig = "ConfigMap"
CustomTypeInvConfig = "Custom"
)
var inventoryConfigs = map[string]invconfig.InventoryConfig{}
var inventoryConfigTypes = []string{
ConfigMapTypeInvConfig,
CustomTypeInvConfig,
}
// Parse optional logging flags
// Ex: ginkgo ./test/e2e/... -- -v=5
// Allow init for e2e test (not imported by external code)
// nolint:gochecknoinits
func init() {
klog.InitFlags(nil)
klog.SetOutput(GinkgoWriter)
}
var defaultTestTimeout = 5 * time.Minute
var defaultBeforeTestTimeout = 30 * time.Second
var defaultAfterTestTimeout = 30 * time.Second
var c client.Client
var _ = BeforeSuite(func() {
// increase from 4000 to handle long event lists
format.MaxLength = 10000
cfg, err := ctrl.GetConfig()
Expect(err).NotTo(HaveOccurred())
cfg.UserAgent = e2eutil.UserAgent("test/e2e")
if e2eutil.IsFlowControlEnabled(cfg) {
// Disable client-side throttling.
klog.V(3).Infof("Client-side throttling disabled")
cfg.QPS = -1
cfg.Burst = -1
}
inventoryConfigs[ConfigMapTypeInvConfig] = invconfig.NewConfigMapTypeInvConfig(cfg)
inventoryConfigs[CustomTypeInvConfig] = invconfig.NewCustomTypeInvConfig(cfg)
mapper, err := apiutil.NewDynamicRESTMapper(cfg)
Expect(err).NotTo(HaveOccurred())
c, err = client.New(cfg, client.Options{
Scheme: scheme.Scheme,
Mapper: mapper,
})
Expect(err).NotTo(HaveOccurred())
ctx, cancel := context.WithTimeout(context.Background(), defaultBeforeTestTimeout)
defer cancel()
e2eutil.CreateInventoryCRD(ctx, c)
Expect(ctx.Err()).To(BeNil(), "BeforeSuite context cancelled or timed out")
})
var _ = AfterSuite(func() {
ctx, cancel := context.WithTimeout(context.Background(), defaultAfterTestTimeout)
defer cancel()
if c != nil {
// If BeforeSuite() failed, c might be nil. Skip deletion to avoid red herring panic.
e2eutil.DeleteInventoryCRD(ctx, c)
}
Expect(ctx.Err()).To(BeNil(), "AfterSuite context cancelled or timed out")
})
var _ = Describe("E2E", func() {
for i := range inventoryConfigTypes {
invType := inventoryConfigTypes[i]
Context(fmt.Sprintf("Inventory%s", invType), func() {
var invConfig invconfig.InventoryConfig
BeforeEach(func() {
invConfig = inventoryConfigs[invType]
})
Context("Basic", func() {
var namespace *v1.Namespace
var inventoryName string
var ctx context.Context
var cancel context.CancelFunc
BeforeEach(func() {
ctx, cancel = context.WithTimeout(context.Background(), defaultTestTimeout)
inventoryName = e2eutil.RandomString("test-inv-")
namespace = e2eutil.CreateRandomNamespace(ctx, c)
})
AfterEach(func() {
Expect(ctx.Err()).To(BeNil(), "test context cancelled or timed out")
cancel()
// new timeout for cleanup
ctx, cancel = context.WithTimeout(context.Background(), defaultAfterTestTimeout)
defer cancel()
// clean up resources created by the tests
fields := struct{ Namespace string }{Namespace: namespace.GetName()}
objs := []*unstructured.Unstructured{
e2eutil.ManifestToUnstructured(cr),
e2eutil.ManifestToUnstructured(crd),
e2eutil.WithNamespace(e2eutil.ManifestToUnstructured(pod1), namespace.GetName()),
e2eutil.WithNamespace(e2eutil.ManifestToUnstructured(pod2), namespace.GetName()),
e2eutil.WithNamespace(e2eutil.ManifestToUnstructured(pod3), namespace.GetName()),
e2eutil.TemplateToUnstructured(podATemplate, fields),
e2eutil.TemplateToUnstructured(podBTemplate, fields),
e2eutil.WithNamespace(e2eutil.ManifestToUnstructured(deployment1), namespace.GetName()),
e2eutil.ManifestToUnstructured(apiservice1),
}
for _, obj := range objs {
e2eutil.DeleteUnstructuredIfExists(ctx, c, obj)
}
e2eutil.DeleteNamespace(ctx, c, namespace)
})
It("ApplyDestroy", func() {
applyAndDestroyTest(ctx, c, invConfig, inventoryName, namespace.GetName())
})
It("DryRun", func() {
dryRunTest(ctx, c, invConfig, inventoryName, namespace.GetName())
})
It("EmptySet", func() {
emptySetTest(ctx, c, invConfig, inventoryName, namespace.GetName())
})
It("DeletionPrevention", func() {
deletionPreventionTest(ctx, c, invConfig, inventoryName, namespace.GetName())
})
It("CustomResource", func() {
crdTest(ctx, c, invConfig, inventoryName, namespace.GetName())
})
It("ContinueOnError", func() {
continueOnErrorTest(ctx, c, invConfig, inventoryName, namespace.GetName())
})
It("ServerSideApply", func() {
serversideApplyTest(ctx, c, invConfig, inventoryName, namespace.GetName())
})
It("DependsOn", func() {
dependsOnTest(ctx, c, invConfig, inventoryName, namespace.GetName())
})
It("ApplyTimeMutation", func() {
mutationTest(ctx, c, invConfig, inventoryName, namespace.GetName())
})
It("DependencyFilter", func() {
dependencyFilterTest(ctx, c, invConfig, inventoryName, namespace.GetName())
})
It("LocalNamespacesFilter", func() {
namespaceFilterTest(ctx, c, invConfig, inventoryName, namespace.GetName())
})
It("CurrentUIDFilter", func() {
currentUIDFilterTest(ctx, c, invConfig, inventoryName, namespace.GetName())
})
It("PruneRetrievalError", func() {
pruneRetrieveErrorTest(ctx, c, invConfig, inventoryName, namespace.GetName())
})
It("ReconciliationFailure", func() {
reconciliationFailed(ctx, invConfig, inventoryName, namespace.GetName())
})
It("ReconciliationTimeout", func() {
reconciliationTimeout(ctx, invConfig, inventoryName, namespace.GetName())
})
It("SkipInvalid", func() {
skipInvalidTest(ctx, c, invConfig, inventoryName, namespace.GetName())
})
It("ExitEarly", func() {
exitEarlyTest(ctx, c, invConfig, inventoryName, namespace.GetName())
})
})
Context("InventoryPolicy", func() {
var namespace *v1.Namespace
var ctx context.Context
var cancel context.CancelFunc
BeforeEach(func() {
ctx, cancel = context.WithTimeout(context.Background(), defaultTestTimeout)
namespace = e2eutil.CreateRandomNamespace(ctx, c)
})
AfterEach(func() {
Expect(ctx.Err()).To(BeNil(), "test context cancelled or timed out")
cancel()
// new timeout for cleanup
ctx, cancel = context.WithTimeout(context.Background(), defaultAfterTestTimeout)
defer cancel()
e2eutil.DeleteUnstructuredIfExists(ctx, c, e2eutil.WithNamespace(e2eutil.ManifestToUnstructured(deployment1), namespace.GetName()))
e2eutil.DeleteNamespace(ctx, c, namespace)
})
It("MustMatch", func() {
inventoryPolicyMustMatchTest(ctx, c, invConfig, namespace.GetName())
})
It("AdoptIfNoInventory", func() {
inventoryPolicyAdoptIfNoInventoryTest(ctx, c, invConfig, namespace.GetName())
})
It("AdoptAll", func() {
inventoryPolicyAdoptAllTest(ctx, c, invConfig, namespace.GetName())
})
})
})
}
Context("NameStrategy", func() {
var namespace *v1.Namespace
var inventoryName string
var ctx context.Context
var cancel context.CancelFunc
BeforeEach(func() {
ctx, cancel = context.WithTimeout(context.Background(), defaultTestTimeout)
inventoryName = e2eutil.RandomString("test-inv-")
namespace = e2eutil.CreateRandomNamespace(ctx, c)
})
AfterEach(func() {
Expect(ctx.Err()).To(BeNil(), "test context cancelled or timed out")
cancel()
// new timeout for cleanup
ctx, cancel = context.WithTimeout(context.Background(), defaultAfterTestTimeout)
defer cancel()
e2eutil.DeleteUnstructuredIfExists(ctx, c, e2eutil.WithNamespace(e2eutil.ManifestToUnstructured(deployment1), namespace.GetName()))
e2eutil.DeleteNamespace(ctx, c, namespace)
})
It("InventoryIDMismatch", func() {
applyWithExistingInvTest(ctx, c, inventoryConfigs[CustomTypeInvConfig], inventoryName, namespace.GetName())
})
})
})