Skip to content
Permalink
Browse files

moved WriteFileViaContainer and ReadFileViaContainer to kubectl_utils

  • Loading branch information
MorrisLaw committed Nov 22, 2019
1 parent 08fe8ff commit 769e6e0e55a9d700be0a341e3bbafb81f2aa5598
Showing with 420 additions and 397 deletions.
  1. +30 −30 test/e2e/apimachinery/crd_publish_openapi.go
  2. +1 −1 test/e2e/apimachinery/webhook.go
  3. +7 −7 test/e2e/apps/statefulset.go
  4. +4 −6 test/e2e/auth/BUILD
  5. +5 −3 test/e2e/auth/service_accounts.go
  6. +9 −9 test/e2e/autoscaling/cluster_size_autoscaling.go
  7. +2 −2 test/e2e/autoscaling/custom_metrics_stackdriver_autoscaling.go
  8. +11 −7 test/e2e/cloud/gcp/cluster_upgrade.go
  9. +5 −5 test/e2e/examples.go
  10. +0 −78 test/e2e/framework/framework.go
  11. +4 −4 test/e2e/framework/ingress/ingress_utils.go
  12. +5 −1 test/e2e/framework/kubectl/BUILD
  13. +88 −2 test/e2e/framework/kubectl/kubectl_utils.go
  14. +2 −2 test/e2e/framework/network/utils.go
  15. +11 −11 test/e2e/framework/nodes_util.go
  16. +1 −1 test/e2e/framework/service/resource.go
  17. +24 −25 test/e2e/framework/util.go
  18. +1 −1 test/e2e/framework/volume/fixtures.go
  19. +10 −10 test/e2e/instrumentation/monitoring/custom_metrics_deployments.go
  20. +4 −4 test/e2e/instrumentation/monitoring/custom_metrics_stackdriver.go
  21. +149 −149 test/e2e/kubectl/kubectl.go
  22. +1 −1 test/e2e/kubectl/portforward.go
  23. +3 −3 test/e2e/network/example_cluster_dns.go
  24. +1 −1 test/e2e/network/service.go
  25. +2 −2 test/e2e/node/kubelet.go
  26. +1 −1 test/e2e/node/pods.go
  27. +5 −3 test/e2e/node/security_context.go
  28. +1 −0 test/e2e/storage/BUILD
  29. +12 −7 test/e2e/storage/pd.go
  30. +1 −1 test/e2e/storage/testsuites/subpath.go
  31. +3 −3 test/e2e/storage/vsphere/vsphere_utils.go
  32. +1 −1 test/e2e/upgrades/cassandra.go
  33. +1 −1 test/e2e/upgrades/etcd.go
  34. +1 −1 test/e2e/upgrades/mysql.go
  35. +8 −8 test/e2e/windows/gmsa_full.go
  36. +1 −1 test/e2e/windows/gmsa_kubelet.go
  37. +5 −5 test/e2e/windows/memory_limits.go
@@ -72,55 +72,55 @@ var _ = SIGDescribe("CustomResourcePublishOpenAPI [Privileged:ClusterAdmin]", fu

ginkgo.By("client-side validation (kubectl create and apply) allows request with known and required properties")
validCR := fmt.Sprintf(`{%s,"spec":{"bars":[{"name":"test-bar"}]}}`, meta)
if _, err := framework.RunKubectlInput(validCR, ns, "create", "-f", "-"); err != nil {
if _, err := framework.RunKubectlInput(f.Namespace.Name, validCR, ns, "create", "-f", "-"); err != nil {
framework.Failf("failed to create valid CR %s: %v", validCR, err)
}
if _, err := framework.RunKubectl(ns, "delete", crd.Crd.Spec.Names.Plural, "test-foo"); err != nil {
if _, err := framework.RunKubectl(f.Namespace.Name, ns, "delete", crd.Crd.Spec.Names.Plural, "test-foo"); err != nil {
framework.Failf("failed to delete valid CR: %v", err)
}
if _, err := framework.RunKubectlInput(validCR, ns, "apply", "-f", "-"); err != nil {
if _, err := framework.RunKubectlInput(f.Namespace.Name, validCR, ns, "apply", "-f", "-"); err != nil {
framework.Failf("failed to apply valid CR %s: %v", validCR, err)
}
if _, err := framework.RunKubectl(ns, "delete", crd.Crd.Spec.Names.Plural, "test-foo"); err != nil {
if _, err := framework.RunKubectl(f.Namespace.Name, ns, "delete", crd.Crd.Spec.Names.Plural, "test-foo"); err != nil {
framework.Failf("failed to delete valid CR: %v", err)
}

ginkgo.By("client-side validation (kubectl create and apply) rejects request with unknown properties when disallowed by the schema")
unknownCR := fmt.Sprintf(`{%s,"spec":{"foo":true}}`, meta)
if _, err := framework.RunKubectlInput(unknownCR, ns, "create", "-f", "-"); err == nil || !strings.Contains(err.Error(), `unknown field "foo"`) {
if _, err := framework.RunKubectlInput(f.Namespace.Name, unknownCR, ns, "create", "-f", "-"); err == nil || !strings.Contains(err.Error(), `unknown field "foo"`) {
framework.Failf("unexpected no error when creating CR with unknown field: %v", err)
}
if _, err := framework.RunKubectlInput(unknownCR, ns, "apply", "-f", "-"); err == nil || !strings.Contains(err.Error(), `unknown field "foo"`) {
if _, err := framework.RunKubectlInput(f.Namespace.Name, unknownCR, ns, "apply", "-f", "-"); err == nil || !strings.Contains(err.Error(), `unknown field "foo"`) {
framework.Failf("unexpected no error when applying CR with unknown field: %v", err)
}

ginkgo.By("client-side validation (kubectl create and apply) rejects request without required properties")
noRequireCR := fmt.Sprintf(`{%s,"spec":{"bars":[{"age":"10"}]}}`, meta)
if _, err := framework.RunKubectlInput(noRequireCR, ns, "create", "-f", "-"); err == nil || !strings.Contains(err.Error(), `missing required field "name"`) {
if _, err := framework.RunKubectlInput(f.Namespace.Name, noRequireCR, ns, "create", "-f", "-"); err == nil || !strings.Contains(err.Error(), `missing required field "name"`) {
framework.Failf("unexpected no error when creating CR without required field: %v", err)
}
if _, err := framework.RunKubectlInput(noRequireCR, ns, "apply", "-f", "-"); err == nil || !strings.Contains(err.Error(), `missing required field "name"`) {
if _, err := framework.RunKubectlInput(f.Namespace.Name, noRequireCR, ns, "apply", "-f", "-"); err == nil || !strings.Contains(err.Error(), `missing required field "name"`) {
framework.Failf("unexpected no error when applying CR without required field: %v", err)
}

ginkgo.By("kubectl explain works to explain CR properties")
if err := verifyKubectlExplain(crd.Crd.Spec.Names.Plural, `(?s)DESCRIPTION:.*Foo CRD for Testing.*FIELDS:.*apiVersion.*<string>.*APIVersion defines.*spec.*<Object>.*Specification of Foo`); err != nil {
if err := verifyKubectlExplain(f.Namespace.Name, crd.Crd.Spec.Names.Plural, `(?s)DESCRIPTION:.*Foo CRD for Testing.*FIELDS:.*apiVersion.*<string>.*APIVersion defines.*spec.*<Object>.*Specification of Foo`); err != nil {
framework.Failf("%v", err)
}

ginkgo.By("kubectl explain works to explain CR properties recursively")
if err := verifyKubectlExplain(crd.Crd.Spec.Names.Plural+".metadata", `(?s)DESCRIPTION:.*Standard object's metadata.*FIELDS:.*creationTimestamp.*<string>.*CreationTimestamp is a timestamp`); err != nil {
if err := verifyKubectlExplain(f.Namespace.Name, crd.Crd.Spec.Names.Plural+".metadata", `(?s)DESCRIPTION:.*Standard object's metadata.*FIELDS:.*creationTimestamp.*<string>.*CreationTimestamp is a timestamp`); err != nil {
framework.Failf("%v", err)
}
if err := verifyKubectlExplain(crd.Crd.Spec.Names.Plural+".spec", `(?s)DESCRIPTION:.*Specification of Foo.*FIELDS:.*bars.*<\[\]Object>.*List of Bars and their specs`); err != nil {
if err := verifyKubectlExplain(f.Namespace.Name, crd.Crd.Spec.Names.Plural+".spec", `(?s)DESCRIPTION:.*Specification of Foo.*FIELDS:.*bars.*<\[\]Object>.*List of Bars and their specs`); err != nil {
framework.Failf("%v", err)
}
if err := verifyKubectlExplain(crd.Crd.Spec.Names.Plural+".spec.bars", `(?s)RESOURCE:.*bars.*<\[\]Object>.*DESCRIPTION:.*List of Bars and their specs.*FIELDS:.*bazs.*<\[\]string>.*List of Bazs.*name.*<string>.*Name of Bar`); err != nil {
if err := verifyKubectlExplain(f.Namespace.Name, crd.Crd.Spec.Names.Plural+".spec.bars", `(?s)RESOURCE:.*bars.*<\[\]Object>.*DESCRIPTION:.*List of Bars and their specs.*FIELDS:.*bazs.*<\[\]string>.*List of Bazs.*name.*<string>.*Name of Bar`); err != nil {
framework.Failf("%v", err)
}

ginkgo.By("kubectl explain works to return error when explain is called on property that doesn't exist")
if _, err := framework.RunKubectl("explain", crd.Crd.Spec.Names.Plural+".spec.bars2"); err == nil || !strings.Contains(err.Error(), `field "bars2" does not exist`) {
if _, err := framework.RunKubectl(f.Namespace.Name, "explain", crd.Crd.Spec.Names.Plural+".spec.bars2"); err == nil || !strings.Contains(err.Error(), `field "bars2" does not exist`) {
framework.Failf("unexpected no error when explaining property that doesn't exist: %v", err)
}

@@ -147,21 +147,21 @@ var _ = SIGDescribe("CustomResourcePublishOpenAPI [Privileged:ClusterAdmin]", fu

ginkgo.By("client-side validation (kubectl create and apply) allows request with any unknown properties")
randomCR := fmt.Sprintf(`{%s,"a":{"b":[{"c":"d"}]}}`, meta)
if _, err := framework.RunKubectlInput(randomCR, ns, "create", "-f", "-"); err != nil {
if _, err := framework.RunKubectlInput(f.Namespace.Name, randomCR, ns, "create", "-f", "-"); err != nil {
framework.Failf("failed to create random CR %s for CRD without schema: %v", randomCR, err)
}
if _, err := framework.RunKubectl(ns, "delete", crd.Crd.Spec.Names.Plural, "test-cr"); err != nil {
if _, err := framework.RunKubectl(f.Namespace.Name, ns, "delete", crd.Crd.Spec.Names.Plural, "test-cr"); err != nil {
framework.Failf("failed to delete random CR: %v", err)
}
if _, err := framework.RunKubectlInput(randomCR, ns, "apply", "-f", "-"); err != nil {
if _, err := framework.RunKubectlInput(f.Namespace.Name, randomCR, ns, "apply", "-f", "-"); err != nil {
framework.Failf("failed to apply random CR %s for CRD without schema: %v", randomCR, err)
}
if _, err := framework.RunKubectl(ns, "delete", crd.Crd.Spec.Names.Plural, "test-cr"); err != nil {
if _, err := framework.RunKubectl(f.Namespace.Name, ns, "delete", crd.Crd.Spec.Names.Plural, "test-cr"); err != nil {
framework.Failf("failed to delete random CR: %v", err)
}

ginkgo.By("kubectl explain works to explain CR without validation schema")
if err := verifyKubectlExplain(crd.Crd.Spec.Names.Plural, `(?s)DESCRIPTION:.*<empty>`); err != nil {
if err := verifyKubectlExplain(f.Namespace.Name, crd.Crd.Spec.Names.Plural, `(?s)DESCRIPTION:.*<empty>`); err != nil {
framework.Failf("%v", err)
}

@@ -188,21 +188,21 @@ var _ = SIGDescribe("CustomResourcePublishOpenAPI [Privileged:ClusterAdmin]", fu

ginkgo.By("client-side validation (kubectl create and apply) allows request with any unknown properties")
randomCR := fmt.Sprintf(`{%s,"a":{"b":[{"c":"d"}]}}`, meta)
if _, err := framework.RunKubectlInput(randomCR, ns, "create", "-f", "-"); err != nil {
if _, err := framework.RunKubectlInput(f.Namespace.Name, randomCR, ns, "create", "-f", "-"); err != nil {
framework.Failf("failed to create random CR %s for CRD that allows unknown properties at the root: %v", randomCR, err)
}
if _, err := framework.RunKubectl(ns, "delete", crd.Crd.Spec.Names.Plural, "test-cr"); err != nil {
if _, err := framework.RunKubectl(f.Namespace.Name, ns, "delete", crd.Crd.Spec.Names.Plural, "test-cr"); err != nil {
framework.Failf("failed to delete random CR: %v", err)
}
if _, err := framework.RunKubectlInput(randomCR, ns, "apply", "-f", "-"); err != nil {
if _, err := framework.RunKubectlInput(f.Namespace.Name, randomCR, ns, "apply", "-f", "-"); err != nil {
framework.Failf("failed to apply random CR %s for CRD without schema: %v", randomCR, err)
}
if _, err := framework.RunKubectl(ns, "delete", crd.Crd.Spec.Names.Plural, "test-cr"); err != nil {
if _, err := framework.RunKubectl(f.Namespace.Name, ns, "delete", crd.Crd.Spec.Names.Plural, "test-cr"); err != nil {
framework.Failf("failed to delete random CR: %v", err)
}

ginkgo.By("kubectl explain works to explain CR")
if err := verifyKubectlExplain(crd.Crd.Spec.Names.Plural, fmt.Sprintf(`(?s)KIND:.*%s`, crd.Crd.Spec.Names.Kind)); err != nil {
if err := verifyKubectlExplain(f.Namespace.Name, crd.Crd.Spec.Names.Plural, fmt.Sprintf(`(?s)KIND:.*%s`, crd.Crd.Spec.Names.Kind)); err != nil {
framework.Failf("%v", err)
}

@@ -230,21 +230,21 @@ var _ = SIGDescribe("CustomResourcePublishOpenAPI [Privileged:ClusterAdmin]", fu

ginkgo.By("client-side validation (kubectl create and apply) allows request with any unknown properties")
randomCR := fmt.Sprintf(`{%s,"spec":{"b":[{"c":"d"}]}}`, meta)
if _, err := framework.RunKubectlInput(randomCR, ns, "create", "-f", "-"); err != nil {
if _, err := framework.RunKubectlInput(f.Namespace.Name, randomCR, ns, "create", "-f", "-"); err != nil {
framework.Failf("failed to create random CR %s for CRD that allows unknown properties in a nested object: %v", randomCR, err)
}
if _, err := framework.RunKubectl(ns, "delete", crd.Crd.Spec.Names.Plural, "test-cr"); err != nil {
if _, err := framework.RunKubectl(f.Namespace.Name, ns, "delete", crd.Crd.Spec.Names.Plural, "test-cr"); err != nil {
framework.Failf("failed to delete random CR: %v", err)
}
if _, err := framework.RunKubectlInput(randomCR, ns, "apply", "-f", "-"); err != nil {
if _, err := framework.RunKubectlInput(f.Namespace.Name, randomCR, ns, "apply", "-f", "-"); err != nil {
framework.Failf("failed to apply random CR %s for CRD without schema: %v", randomCR, err)
}
if _, err := framework.RunKubectl(ns, "delete", crd.Crd.Spec.Names.Plural, "test-cr"); err != nil {
if _, err := framework.RunKubectl(f.Namespace.Name, ns, "delete", crd.Crd.Spec.Names.Plural, "test-cr"); err != nil {
framework.Failf("failed to delete random CR: %v", err)
}

ginkgo.By("kubectl explain works to explain CR")
if err := verifyKubectlExplain(crd.Crd.Spec.Names.Plural, `(?s)DESCRIPTION:.*preserve-unknown-properties in nested field for Testing`); err != nil {
if err := verifyKubectlExplain(f.Namespace.Name, crd.Crd.Spec.Names.Plural, `(?s)DESCRIPTION:.*preserve-unknown-properties in nested field for Testing`); err != nil {
framework.Failf("%v", err)
}

@@ -663,8 +663,8 @@ func dropDefaults(s *spec.Schema) {
delete(s.Extensions, "x-kubernetes-group-version-kind")
}

func verifyKubectlExplain(name, pattern string) error {
result, err := framework.RunKubectl("explain", name)
func verifyKubectlExplain(ns, name, pattern string) error {
result, err := framework.RunKubectl(ns, "explain", name)
if err != nil {
return fmt.Errorf("failed to explain %s: %v", name, err)
}
@@ -1229,7 +1229,7 @@ func testAttachingPodWebhook(f *framework.Framework) {
ginkgo.By("'kubectl attach' the pod, should be denied by the webhook")
timer := time.NewTimer(30 * time.Second)
defer timer.Stop()
_, err = framework.NewKubectlCommand("attach", fmt.Sprintf("--namespace=%v", f.Namespace.Name), pod.Name, "-i", "-c=container1").WithTimeout(timer.C).Exec()
_, err = framework.NewKubectlCommand(f.Namespace.Name, "attach", fmt.Sprintf("--namespace=%v", f.Namespace.Name), pod.Name, "-i", "-c=container1").WithTimeout(timer.C).Exec()
framework.ExpectError(err, "'kubectl attach' the pod, should be denied by the webhook")
if e, a := "attaching to pod 'to-be-attached-pod' is not allowed", err.Error(); !strings.Contains(a, e) {
framework.Failf("unexpected 'kubectl attach' error message. expected to contain %q, got %q", e, a)
@@ -848,10 +848,10 @@ var _ = SIGDescribe("StatefulSet", func() {
})
})

func kubectlExecWithRetries(args ...string) (out string) {
func kubectlExecWithRetries(ns string, args ...string) (out string) {
var err error
for i := 0; i < 3; i++ {
if out, err = framework.RunKubectl(args...); err == nil {
if out, err = framework.RunKubectl(ns, args...); err == nil {
return
}
framework.Logf("Retrying %v:\nerror %v\nstdout %v", args, err, out)
@@ -916,15 +916,15 @@ func (z *zookeeperTester) write(statefulPodIndex int, kv map[string]string) {
ns := fmt.Sprintf("--namespace=%v", z.ss.Namespace)
for k, v := range kv {
cmd := fmt.Sprintf("/opt/zookeeper/bin/zkCli.sh create /%v %v", k, v)
framework.Logf(framework.RunKubectlOrDie("exec", ns, name, "--", "/bin/sh", "-c", cmd))
framework.Logf(framework.RunKubectlOrDie(z.ss.Namespace, "exec", ns, name, "--", "/bin/sh", "-c", cmd))
}
}

func (z *zookeeperTester) read(statefulPodIndex int, key string) string {
name := fmt.Sprintf("%v-%d", z.ss.Name, statefulPodIndex)
ns := fmt.Sprintf("--namespace=%v", z.ss.Namespace)
cmd := fmt.Sprintf("/opt/zookeeper/bin/zkCli.sh get /%v", key)
return lastLine(framework.RunKubectlOrDie("exec", ns, name, "--", "/bin/sh", "-c", cmd))
return lastLine(framework.RunKubectlOrDie(z.ss.Namespace, "exec", ns, name, "--", "/bin/sh", "-c", cmd))
}

type mysqlGaleraTester struct {
@@ -941,7 +941,7 @@ func (m *mysqlGaleraTester) mysqlExec(cmd, ns, podName string) string {
// TODO: Find a readiness probe for mysql that guarantees writes will
// succeed and ditch retries. Current probe only reads, so there's a window
// for a race.
return kubectlExecWithRetries(fmt.Sprintf("--namespace=%v", ns), "exec", podName, "--", "/bin/sh", "-c", cmd)
return kubectlExecWithRetries(ns, fmt.Sprintf("--namespace=%v", ns), "exec", podName, "--", "/bin/sh", "-c", cmd)
}

func (m *mysqlGaleraTester) deploy(ns string) *appsv1.StatefulSet {
@@ -981,7 +981,7 @@ func (m *redisTester) name() string {

func (m *redisTester) redisExec(cmd, ns, podName string) string {
cmd = fmt.Sprintf("/opt/redis/redis-cli -h %v %v", podName, cmd)
return framework.RunKubectlOrDie(fmt.Sprintf("--namespace=%v", ns), "exec", podName, "--", "/bin/sh", "-c", cmd)
return framework.RunKubectlOrDie(ns, fmt.Sprintf("--namespace=%v", ns), "exec", podName, "--", "/bin/sh", "-c", cmd)
}

func (m *redisTester) deploy(ns string) *appsv1.StatefulSet {
@@ -1012,7 +1012,7 @@ func (c *cockroachDBTester) name() string {

func (c *cockroachDBTester) cockroachDBExec(cmd, ns, podName string) string {
cmd = fmt.Sprintf("/cockroach/cockroach sql --insecure --host %s.cockroachdb -e \"%v\"", podName, cmd)
return framework.RunKubectlOrDie(fmt.Sprintf("--namespace=%v", ns), "exec", podName, "--", "/bin/sh", "-c", cmd)
return framework.RunKubectlOrDie(ns, fmt.Sprintf("--namespace=%v", ns), "exec", podName, "--", "/bin/sh", "-c", cmd)
}

func (c *cockroachDBTester) deploy(ns string) *appsv1.StatefulSet {
@@ -1,9 +1,4 @@
package(default_visibility = ["//visibility:public"])

load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
load("@io_bazel_rules_go//go:def.bzl", "go_library")

go_library(
name = "go_default_library",
@@ -19,6 +14,7 @@ go_library(
"service_accounts.go",
],
importpath = "k8s.io/kubernetes/test/e2e/auth",
visibility = ["//visibility:public"],
deps = [
"//pkg/master/ports:go_default_library",
"//pkg/security/apparmor:go_default_library",
@@ -55,6 +51,7 @@ go_library(
"//test/e2e/framework/auth:go_default_library",
"//test/e2e/framework/deployment:go_default_library",
"//test/e2e/framework/job:go_default_library",
"//test/e2e/framework/kubectl:go_default_library",
"//test/e2e/framework/node:go_default_library",
"//test/e2e/framework/pod:go_default_library",
"//test/utils:go_default_library",
@@ -77,4 +74,5 @@ filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
@@ -32,6 +32,7 @@ import (
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/kubernetes/plugin/pkg/admission/serviceaccount"
"k8s.io/kubernetes/test/e2e/framework"
e2ekubectl "k8s.io/kubernetes/test/e2e/framework/kubectl"
e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
imageutils "k8s.io/kubernetes/test/utils/image"

@@ -224,11 +225,12 @@ var _ = SIGDescribe("ServiceAccounts", func() {
framework.ExpectNoError(err)
framework.ExpectNoError(e2epod.WaitForPodRunningInNamespace(f.ClientSet, pod))

mountedToken, err := f.ReadFileViaContainer(pod.Name, pod.Spec.Containers[0].Name, path.Join(serviceaccount.DefaultAPITokenMountPath, v1.ServiceAccountTokenKey))
tk := e2ekubectl.NewTestKubeconfig(framework.TestContext.CertDir, framework.TestContext.Host, framework.TestContext.KubeConfig, framework.TestContext.KubeContext, framework.TestContext.KubectlPath, f.Namespace.Name)
mountedToken, err := tk.ReadFileViaContainer(pod.Name, pod.Spec.Containers[0].Name, path.Join(serviceaccount.DefaultAPITokenMountPath, v1.ServiceAccountTokenKey))
framework.ExpectNoError(err)
mountedCA, err := f.ReadFileViaContainer(pod.Name, pod.Spec.Containers[0].Name, path.Join(serviceaccount.DefaultAPITokenMountPath, v1.ServiceAccountRootCAKey))
mountedCA, err := tk.ReadFileViaContainer(pod.Name, pod.Spec.Containers[0].Name, path.Join(serviceaccount.DefaultAPITokenMountPath, v1.ServiceAccountRootCAKey))
framework.ExpectNoError(err)
mountedNamespace, err := f.ReadFileViaContainer(pod.Name, pod.Spec.Containers[0].Name, path.Join(serviceaccount.DefaultAPITokenMountPath, v1.ServiceAccountNamespaceKey))
mountedNamespace, err := tk.ReadFileViaContainer(pod.Name, pod.Spec.Containers[0].Name, path.Join(serviceaccount.DefaultAPITokenMountPath, v1.ServiceAccountNamespaceKey))
framework.ExpectNoError(err)

// CA and namespace should be identical

0 comments on commit 769e6e0

Please sign in to comment.
You can’t perform that action at this time.