diff --git a/examples/k8s/kindsupport.go b/examples/k8s/kindsupport.go deleted file mode 100644 index ed3736d9..00000000 --- a/examples/k8s/kindsupport.go +++ /dev/null @@ -1,77 +0,0 @@ -/* -Copyright 2021 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package k8s - -import ( - "fmt" - "io" - "io/ioutil" - "log" - "os" - - "github.com/vladimirvivien/gexe" -) - -var ( - e = gexe.New() - kindVersion = "v0.11.0" -) - -func createKindCluster(clusterName string) (string, error) { - if e.Prog().Avail("kind") == "" { - log.Println(`kind may not be installed, attempting to install...`) - p := e.SetEnv("GO111MODULE", "on").RunProc(fmt.Sprintf("go get sigs.k8s.io/kind@%s", kindVersion)) - if p.Err() != nil { - return "", fmt.Errorf("install kind failed: %s: %w", p.Result(), p.Err()) - } - e.SetEnv("PATH", e.Run("echo $PATH:$GOPATH/bin")) - } - - // create cluster - p := e.RunProc(fmt.Sprintf(`kind create cluster --name %s`, clusterName)) - if p.Err() != nil { - return "", fmt.Errorf("kind create cluster: %s: %w", p.Result(), p.Err()) - } - - // grab kubeconfig file for cluster - kubecfg := fmt.Sprintf("%s-kubecfg", clusterName) - p = e.StartProc(fmt.Sprintf(`kind get kubeconfig --name %s`, clusterName)) - if p.Err() != nil { - return "", fmt.Errorf("kind get kubeconfig: %s: %w", p.Result(), p.Err()) - } - - file, err := ioutil.TempFile("", fmt.Sprintf("kind-cluser-%s", kubecfg)) - if err != nil { - return "", fmt.Errorf("kind kubeconfig file: %w", err) - } - defer file.Close() - if n, err := io.Copy(file, p.Out()); n == 0 || err != nil { - return "", fmt.Errorf("kind kubecfg file: bytes copied: %d: %w]", n, err) - } - return file.Name(), nil -} - -func deleteKindCluster(clusterName, kubeconfig string) error { - p := e.RunProc(fmt.Sprintf(`kind delete cluster --name %s`, clusterName)) - if p.Err() != nil { - return fmt.Errorf("kind delete cluster: %s: %w", p.Result(), p.Err()) - } - if err := os.RemoveAll(kubeconfig); err != nil { - return fmt.Errorf("kind: remove kubefconfig failed: %w", err) - } - return nil -} diff --git a/examples/k8s/main_test.go b/examples/k8s/main_test.go index cd9b6275..91708739 100644 --- a/examples/k8s/main_test.go +++ b/examples/k8s/main_test.go @@ -17,11 +17,8 @@ limitations under the License. package k8s import ( - "context" - "fmt" "os" "testing" - "time" "sigs.k8s.io/e2e-framework/pkg/env" "sigs.k8s.io/e2e-framework/pkg/envconf" @@ -34,44 +31,9 @@ var ( func TestMain(m *testing.M) { testenv = env.New() - testenv.Setup(CreateKindFunc(envconf.RandomName("my-cluster", 16))).Finish(CleanupKindFunc()) + // Setup uses pre-defined func to create kind cluster + testenv.Setup(kindsupport.FuncCreate(envconf.RandomName("my-cluster", 16), true)) + // Finish uses pre-defined func to destroy kind cluster at end of package test + testenv.Finish(kindsupport.FuncDestroy()) os.Exit(testenv.Run(m)) } - -// CreateKindFunc returns an EnvFunc -// that creates kind cluster, and propagate -// the kind instance via the environment context -func CreateKindFunc(name string) env.Func { - return func(ctx context.Context, cfg *envconf.Config) (context.Context, error) { - kind := kindsupport.NewCluster(name) - kubecfg, err := kind.Create() - if err != nil { - return ctx, fmt.Errorf("kind setup: %w", err) - } - - // stall, give pods time - time.Sleep(7 * time.Second) - - // update envconfig with kubeconfig - if _, err := cfg.WithKubeconfigFile(kubecfg); err != nil { - return ctx, fmt.Errorf("kind setup: envconfig: %w", err) - } - - // forward cluster name and kubecfg file name (via context) - // for cleanup later - return context.WithValue(ctx, "kindcluster", kind), nil - } -} - -// CleanupKindFunc returns an EnvFunc that -// retrieves the kind cluster instance from the forwarded context -// then deletes the cluster. -func CleanupKindFunc() env.Func { - return func(ctx context.Context, cfg *envconf.Config) (context.Context, error) { - kind := ctx.Value("kindcluster").(*kindsupport.Cluster) - if err := kind.Destroy(); err != nil { - return ctx, fmt.Errorf("kind cleanup: %w", err) - } - return ctx, nil - } -} diff --git a/pkg/envconf/config.go b/pkg/envconf/config.go index 2f79b0e7..1a839ea2 100644 --- a/pkg/envconf/config.go +++ b/pkg/envconf/config.go @@ -158,19 +158,6 @@ func (c *Config) Labels() map[string]string { return c.labels } -// AutoCreateNamespace signals that a namespace should -// be automatically created for the environment -func (c *Config) AutoCreateNamespace() *Config { - c.autoCreateNS = true - return c -} - -// NamespaceShouldBeCreated indicates if a namespace -// should be created for the environment -func (c *Config) NamespaceShouldBeCreated() bool { - return c.autoCreateNS -} - func randNS() string { return RandomName("testns-", 32) } diff --git a/support/kind/kind_env_funcs.go b/support/kind/kind_env_funcs.go new file mode 100644 index 00000000..50d5b445 --- /dev/null +++ b/support/kind/kind_env_funcs.go @@ -0,0 +1,95 @@ +/* +Copyright 2021 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package kind + +import ( + "context" + "fmt" + "time" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/e2e-framework/pkg/env" + "sigs.k8s.io/e2e-framework/pkg/envconf" +) + +type contextKey string + +var ( + ContextKeyCluster contextKey = "kindcluster" + ContextKeyNamespace contextKey = "namespace" +) + +// FuncCreate returns a pkg/env/Func that is used to +// create a kind cluster and then generate a new cluster namespace (if autoNS=true). +// The kind cluster instance is then injected in the context key value ContextKeyCluster. +func FuncCreate(name string, autoNS bool) env.Func { + return func(ctx context.Context, cfg *envconf.Config) (context.Context, error) { + kind := NewCluster(name) + kubecfg, err := kind.Create() + if err != nil { + return ctx, fmt.Errorf("kind setup: %w", err) + } + + // stall, give pods time + time.Sleep(7 * time.Second) + + // update envconfig with kubeconfig + if _, err := cfg.WithKubeconfigFile(kubecfg); err != nil { + return ctx, fmt.Errorf("kind setup: envconfig: %w", err) + } + + // create a namespace + if autoNS { + name := cfg.WithRandomNamespace().Namespace() + namespace := corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: name}} + if err := cfg.Client().Resources().Create(ctx, &namespace); err != nil { + return ctx, fmt.Errorf("kind setup: auto-create namespace: %w", err) + } + // save namespace for cleanup + ctx = context.WithValue(ctx, ContextKeyNamespace, &namespace) + } + + // forward cluster name and kubecfg file name (via context) + // for cleanup later + return context.WithValue(ctx, ContextKeyCluster, kind), nil + } +} + +// FuncDestroy returns an EnvFunc that +// retrieves the kind cluster instance from the forwarded context +// then deletes the cluster. +func FuncDestroy() env.Func { + return func(ctx context.Context, cfg *envconf.Config) (context.Context, error) { + kind, ok := ctx.Value(ContextKeyCluster).(*Cluster) + if !ok { + return ctx, fmt.Errorf("kind destroy: unexpected type for cluster value") + } + + // delete namespace if found + if ns, ok := ctx.Value(ContextKeyCluster).(*corev1.Namespace); ok{ + if err := cfg.Client().Resources().Delete(ctx, ns); err != nil { + return ctx, fmt.Errorf("kind destroy: auto-create namespace: %w", err) + } + } + + if err := kind.Destroy(); err != nil { + return ctx, fmt.Errorf("kind destroy: %w", err) + } + return ctx, nil + } +}