mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-20 02:11:09 +00:00
Merge pull request #116599 from justinsb/kubectl_applyset_e2e_test
kubectl prunev2: simple e2e/integration test
This commit is contained in:
commit
60be214af1
@ -38,6 +38,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
openapi_v2 "github.com/google/gnostic/openapiv2"
|
openapi_v2 "github.com/google/gnostic/openapiv2"
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
|
|
||||||
"sigs.k8s.io/yaml"
|
"sigs.k8s.io/yaml"
|
||||||
|
|
||||||
@ -45,9 +46,11 @@ import (
|
|||||||
rbacv1 "k8s.io/api/rbac/v1"
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
|
"k8s.io/apimachinery/pkg/api/meta"
|
||||||
"k8s.io/apimachinery/pkg/api/resource"
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
utilnet "k8s.io/apimachinery/pkg/util/net"
|
utilnet "k8s.io/apimachinery/pkg/util/net"
|
||||||
utilnettesting "k8s.io/apimachinery/pkg/util/net/testing"
|
utilnettesting "k8s.io/apimachinery/pkg/util/net/testing"
|
||||||
@ -846,6 +849,65 @@ metadata:
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
ginkgo.Describe("Kubectl prune with applyset", func() {
|
||||||
|
ginkgo.It("should apply and prune objects", func(ctx context.Context) {
|
||||||
|
framework.Logf("applying manifest1")
|
||||||
|
manifest1 := `
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: cm1
|
||||||
|
namespace: {{ns}}
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: cm2
|
||||||
|
namespace: {{ns}}
|
||||||
|
`
|
||||||
|
|
||||||
|
manifest1 = strings.ReplaceAll(manifest1, "{{ns}}", ns)
|
||||||
|
args := []string{"apply", "--prune", "--applyset=applyset1", "-f", "-"}
|
||||||
|
e2ekubectl.NewKubectlCommand(ns, args...).WithEnv([]string{"KUBECTL_APPLYSET=true"}).WithStdinData(manifest1).ExecOrDie(ns)
|
||||||
|
|
||||||
|
framework.Logf("checking which objects exist")
|
||||||
|
objects := mustListObjectsInNamespace(ctx, c, ns)
|
||||||
|
names := mustGetNames(objects)
|
||||||
|
if diff := cmp.Diff(names, []string{"cm1", "cm2"}); diff != "" {
|
||||||
|
framework.Failf("unexpected configmap names (-want +got):\n%s", diff)
|
||||||
|
}
|
||||||
|
|
||||||
|
framework.Logf("applying manifest2")
|
||||||
|
manifest2 := `
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: cm1
|
||||||
|
namespace: {{ns}}
|
||||||
|
`
|
||||||
|
manifest2 = strings.ReplaceAll(manifest2, "{{ns}}", ns)
|
||||||
|
|
||||||
|
e2ekubectl.NewKubectlCommand(ns, args...).WithEnv([]string{"KUBECTL_APPLYSET=true"}).WithStdinData(manifest2).ExecOrDie(ns)
|
||||||
|
|
||||||
|
framework.Logf("checking which objects exist")
|
||||||
|
objects = mustListObjectsInNamespace(ctx, c, ns)
|
||||||
|
names = mustGetNames(objects)
|
||||||
|
if diff := cmp.Diff(names, []string{"cm1"}); diff != "" {
|
||||||
|
framework.Failf("unexpected configmap names (-want +got):\n%s", diff)
|
||||||
|
}
|
||||||
|
|
||||||
|
framework.Logf("applying manifest2 (again)")
|
||||||
|
e2ekubectl.NewKubectlCommand(ns, args...).WithEnv([]string{"KUBECTL_APPLYSET=true"}).WithStdinData(manifest2).ExecOrDie(ns)
|
||||||
|
|
||||||
|
framework.Logf("checking which objects exist")
|
||||||
|
objects = mustListObjectsInNamespace(ctx, c, ns)
|
||||||
|
names = mustGetNames(objects)
|
||||||
|
if diff := cmp.Diff(names, []string{"cm1"}); diff != "" {
|
||||||
|
framework.Failf("unexpected configmap names (-want +got):\n%s", diff)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
ginkgo.Describe("Kubectl apply", func() {
|
ginkgo.Describe("Kubectl apply", func() {
|
||||||
ginkgo.It("should apply a new configuration to an existing RC", func(ctx context.Context) {
|
ginkgo.It("should apply a new configuration to an existing RC", func(ctx context.Context) {
|
||||||
controllerJSON := commonutils.SubstituteImageName(string(readTestFileOrDie(agnhostControllerFilename)))
|
controllerJSON := commonutils.SubstituteImageName(string(readTestFileOrDie(agnhostControllerFilename)))
|
||||||
@ -2370,3 +2432,38 @@ waitLoop:
|
|||||||
// Reaching here means that one of more checks failed multiple times. Assuming its not a race condition, something is broken.
|
// Reaching here means that one of more checks failed multiple times. Assuming its not a race condition, something is broken.
|
||||||
framework.Failf("Timed out after %v seconds waiting for %s pods to reach valid state", framework.PodStartTimeout.Seconds(), testname)
|
framework.Failf("Timed out after %v seconds waiting for %s pods to reach valid state", framework.PodStartTimeout.Seconds(), testname)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mustListObjectsInNamespace queries all the objects we use for testing in the given namespace.
|
||||||
|
// Currently this is just ConfigMaps.
|
||||||
|
// We filter our "system" configmaps, like "kube-root-ca.crt".
|
||||||
|
func mustListObjectsInNamespace(ctx context.Context, c clientset.Interface, ns string) []runtime.Object {
|
||||||
|
var objects []runtime.Object
|
||||||
|
configMaps, err := c.CoreV1().ConfigMaps(ns).List(ctx, metav1.ListOptions{})
|
||||||
|
if err != nil {
|
||||||
|
framework.Failf("error listing configmaps: %v", err)
|
||||||
|
}
|
||||||
|
for i := range configMaps.Items {
|
||||||
|
cm := &configMaps.Items[i]
|
||||||
|
if cm.Name == "kube-root-ca.crt" {
|
||||||
|
// Ignore system objects
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
objects = append(objects, cm)
|
||||||
|
}
|
||||||
|
return objects
|
||||||
|
}
|
||||||
|
|
||||||
|
// mustGetNames returns a slice containing the metadata.name for each object.
|
||||||
|
func mustGetNames(objects []runtime.Object) []string {
|
||||||
|
var names []string
|
||||||
|
for _, obj := range objects {
|
||||||
|
metaAccessor, err := meta.Accessor(obj)
|
||||||
|
if err != nil {
|
||||||
|
framework.Failf("error getting accessor for %T: %v", obj, err)
|
||||||
|
}
|
||||||
|
name := metaAccessor.GetName()
|
||||||
|
names = append(names, name)
|
||||||
|
}
|
||||||
|
sort.Strings(names)
|
||||||
|
return names
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user