<|start_filename|>examples/every_test_custom_ns/main_test.go<|end_filename|>
/*
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 every_test_custom_ns

import (
	"context"
	"fmt"
	"os"
	"testing"
	"time"

	v1 "k8s.io/api/core/v1"
	"sigs.k8s.io/e2e-framework/pkg/env"
	"sigs.k8s.io/e2e-framework/pkg/envconf"
	"sigs.k8s.io/e2e-framework/support/kind"
)

var testenv env.Environment

func TestMain(m *testing.M) {
	testenv = env.New()

	// Specifying a run ID so that multiple runs wouldn't collide.
	runID := envconf.RandomName("ns", 4)

	testenv.Setup(
		// Step: creates kind cluster, propagate kind cluster object
		func(ctx context.Context, cfg *envconf.Config) (context.Context, error) {
			name := envconf.RandomName("my-cluster", 16)
			cluster := kind.NewCluster(name)
			kubeconfig, err := cluster.Create()
			if err != nil {
				return ctx, err
			}
			// stall a bit to allow most pods to come up
			time.Sleep(time.Second * 10)

			// update environment with kubecofig file
			cfg.WithKubeconfigFile(kubeconfig)

			// propagate cluster value
			return context.WithValue(ctx, "cluster", cluster), nil
		}).Finish(
		// Teardown func: delete kind cluster
		func(ctx context.Context, cfg *envconf.Config) (context.Context, error) {
			cluster := ctx.Value("cluster").(*kind.Cluster) // nil should be tested
			if err := cluster.Destroy(); err != nil {
				return ctx, err
			}
			return ctx, nil
		},
	)

	testenv.BeforeEachTest(func(ctx context.Context, cfg *envconf.Config, t *testing.T) (context.Context, error) {
		return createNSForTest(ctx, cfg, t, runID)
	})
	testenv.AfterEachTest(func(ctx context.Context, cfg *envconf.Config, t *testing.T) (context.Context, error) {
		return deleteNSForTest(ctx, cfg, t, runID)
	})

	os.Exit(testenv.Run(m))
}

// CreateNSForTest creates a random namespace with the runID as a prefix. It is stored in the context
// so that the deleteNSForTest routine can look it up and delete it.
func createNSForTest(ctx context.Context, cfg *envconf.Config, t *testing.T, runID string) (context.Context, error) {
	ns := envconf.RandomName(runID, 10)
	ctx = context.WithValue(ctx, nsKey(t), ns)

	t.Logf("Creating NS %v for test %v", ns, t.Name())
	nsObj := v1.Namespace{}
	nsObj.Name = ns
	return ctx, cfg.Client().Resources().Create(ctx, &nsObj)
}

// DeleteNSForTest looks up the namespace corresponding to the given test and deletes it.
func deleteNSForTest(ctx context.Context, cfg *envconf.Config, t *testing.T, runID string) (context.Context, error) {
	ns := fmt.Sprint(ctx.Value(nsKey(t)))
	t.Logf("Deleting NS %v for test %v", ns, t.Name())

	nsObj := v1.Namespace{}
	nsObj.Name = ns
	return ctx, cfg.Client().Resources().Delete(ctx, &nsObj)
}

func nsKey(t *testing.T) string {
	return "NS-for-%v" + t.Name()
}


<|start_filename|>examples/skip_flags/k8s_test.go<|end_filename|>
/*
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 skip_funcs

import (
	"context"
	"testing"
	"time"

	appsv1 "k8s.io/api/apps/v1"
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"sigs.k8s.io/e2e-framework/pkg/envconf"
	"sigs.k8s.io/e2e-framework/pkg/features"
)

func TestSkipFlags(t *testing.T) {
	podFeature := features.New("pod list").WithLabel("env", "prod").
		Assess("pods from kube-system", func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context {
			var pods corev1.PodList
			client, err := cfg.NewClient()
			if err != nil {
				t.Fatal(err)
			}
			err = client.Resources("kube-system").List(context.TODO(), &pods)
			if err != nil {
				t.Fatal(err)
			}
			t.Logf("found %d pods", len(pods.Items))
			if len(pods.Items) == 0 {
				t.Fatal("no pods in namespace kube-system")
			}
			return ctx
		}).Feature()

	// feature uses pre-generated namespace (see TestMain)
	depFeature := features.New("appsv1/deployment").WithLabel("env", "dev").
		Setup(func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context {
			// insert a deployment
			deployment := newDeployment(cfg.Namespace(), "test-deployment", 1)
			client, err := cfg.NewClient()
			if err != nil {
				t.Fatal(err)
			}

			if err := client.Resources().Create(ctx, deployment); err != nil {
				t.Fatal(err)
			}
			time.Sleep(2 * time.Second)
			return ctx
		}).
		Assess("deployment creation", func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context {
			var dep appsv1.Deployment
			client, err := cfg.NewClient()
			if err != nil {
				t.Fatal(err)
			}

			if err := client.Resources().Get(ctx, "test-deployment", cfg.Namespace(), &dep); err != nil {
				t.Fatal(err)
			}
			if &dep != nil {
				t.Logf("deployment found: %s", dep.Name)
			}

			return ctx
		}).Feature()

	test.Test(t, podFeature, depFeature)
}

func newDeployment(namespace string, name string, replicas int32) *appsv1.Deployment {
	return &appsv1.Deployment{
		ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: namespace, Labels: map[string]string{"app": "test-skip-label"}},
		Spec: appsv1.DeploymentSpec{
			Replicas: &replicas,
			Selector: &metav1.LabelSelector{
				MatchLabels: map[string]string{"app": "test-skip-label"},
			},
			Template: corev1.PodTemplateSpec{
				ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{"app": "test-skip-label"}},
				Spec:       corev1.PodSpec{Containers: []corev1.Container{{Name: "scratch", Image: "scratch"}}},
			},
		},
	}
}


<|start_filename|>klient/k8s/object.go<|end_filename|>
/*
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 (
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/types"
)

// Object is a union type that can represent either typed objects
// of type metav1.Object or dynamic objects of type runtime.object.
type Object interface {
	metav1.Object
	runtime.Object
}

// ObjectList is a Kubernetes object list, allows functions to work
// with any resource that implements both runtime.Object and
// metav1.ListInterface interfaces.
type ObjectList interface {
	metav1.ListInterface
	runtime.Object
}

// Patch is a patch that can be applied to a Kubernetes object.
type Patch struct {
	// PatchType is the type of the patch.
	PatchType types.PatchType
	// Data is the raw data representing the patch.
	Data []byte
}


<|start_filename|>examples/suites/featureset_test.go<|end_filename|>
/*
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 suites

import (
	"context"
	"testing"

	"sigs.k8s.io/e2e-framework/pkg/envconf"
	"sigs.k8s.io/e2e-framework/pkg/features"
)

// TestFeatureSet shows how Environment.Test can be used to
// test a collections of features (feature set). The example
// also shows the before/after feature actions which causes
// callbacks functions to be executed during the feature tests.
func TestFeatureSet(t *testing.T) {
	f1 := features.New("bazz test").
		Assess("Hello Bazz", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context {
			result := Hello("bazz")
			if result != "Hello bazz" {
				t.Error("unexpected message")
			}
			return ctx
		}).Feature()

	f2 := features.New("batt test").
		Assess("Hello Batt", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context {
			result := Hello("batt")
			if result != "Hello batt" {
				t.Error("unexpected message")
			}
			return ctx
		}).Feature()

	testenv.Test(t, f1, f2)
}


<|start_filename|>examples/custom_env_funcs/k8s_test.go<|end_filename|>
/*
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 custom_env_funcs

import (
	"context"
	"testing"

	corev1 "k8s.io/api/core/v1"
	"sigs.k8s.io/e2e-framework/pkg/envconf"
	"sigs.k8s.io/e2e-framework/pkg/features"
)

func TestListPods(t *testing.T) {
	f := features.New("pod list").
		Assess("pods from kube-system", func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context {
			client, err := cfg.NewClient()
			if err != nil {
				t.Fatal(err)
			}
			var pods corev1.PodList
			err = client.Resources("kube-system").List(context.TODO(), &pods)
			if err != nil {
				t.Fatal(err)
			}
			t.Logf("found %d pods", len(pods.Items))
			if len(pods.Items) == 0 {
				t.Fatal("no pods in namespace kube-system")
			}
			return ctx
		})

	testenv.Test(t, f.Feature())
}


<|start_filename|>examples/simple/hello_test.go<|end_filename|>
/*
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 simple

import (
	"context"
	"fmt"
	"testing"

	"sigs.k8s.io/e2e-framework/pkg/env"
	"sigs.k8s.io/e2e-framework/pkg/envconf"
	"sigs.k8s.io/e2e-framework/pkg/features"
)

func Hello(name string) string {
	return fmt.Sprintf("Hello %s", name)
}

// TestHello shows an example of a test environment
// that uses a simple setup to assess a feature (test)
// in a test function directly (outside of test suite TestMain)
func TestHello(t *testing.T) {
	e := env.NewWithConfig(envconf.New())
	feat := features.New("Hello Feature").
		WithLabel("type", "simple").
		Assess("test message", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context {
			result := Hello("foo")
			if result != "Hello foo" {
				t.Error("unexpected message")
			}
			return ctx
		})

	e.Test(t, feat.Feature())
}

// The following shows an example of a simple
// test function that uses feature with a setup
// step.
func TestHello_WithSetup(t *testing.T) {
	e := env.NewWithConfig(envconf.New())
	var name string
	feat := features.New("Hello Feature").
		WithLabel("type", "simple").
		Setup(func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context {
			name = "foobar"
			return ctx
		}).
		Assess("test message", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context {
			result := Hello(name)
			if result != "Hello foobar" {
				t.Error("unexpected message")
			}
			return ctx
		}).Feature()

	e.Test(t, feat)
}


<|start_filename|>klient/client.go<|end_filename|>
/*
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 klient

import (
	"k8s.io/client-go/rest"
	"sigs.k8s.io/e2e-framework/klient/conf"
	"sigs.k8s.io/e2e-framework/klient/k8s/resources"
)

// Client stores values to interact with the
// API-server.
type Client interface {
	// RESTConfig returns the *rest.Config associated with this client.
	RESTConfig() *rest.Config
	// Resources returns a *Resources type to access resource CRUD operations.
	// This method takes zero or at most 1 namespace (more will panic) that
	// can be used in List operations.
	Resources(...string) *resources.Resources
}

type client struct {
	cfg       *rest.Config
	resources *resources.Resources
}

// New returns a new Client value
func New(cfg *rest.Config) (Client, error) {
	res, err := resources.New(cfg)
	if err != nil {
		return nil, err
	}
	return &client{cfg: cfg, resources: res}, nil
}

// NewWithKubeConfigFile creates a client using the kubeconfig filePath
func NewWithKubeConfigFile(filePath string) (Client, error) {
	cfg, err := conf.New(filePath)
	if err != nil {
		return nil, err
	}
	return New(cfg)
}

// RESTConfig returns the *rest.Config value associated
// with this client.
func (c *client) RESTConfig() *rest.Config {
	return c.cfg
}

// Resources returns *Resources value to access CRUD object
// operations. It takes 0 or, at most, 1 namespace, or panics.
func (c *client) Resources(namespace ...string) *resources.Resources {
	switch len(namespace) {
	case 0:
		return c.resources.WithNamespace("")
	case 1:
		return c.resources.WithNamespace(namespace[0])
	default:
		panic("too many namespaces provided")
	}
}


<|start_filename|>examples/suites/hello_test.go<|end_filename|>
/*
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 suites

import (
	"context"
	"fmt"
	"testing"

	"sigs.k8s.io/e2e-framework/pkg/envconf"
	"sigs.k8s.io/e2e-framework/pkg/features"
)

func Hello(name string) string {
	return fmt.Sprintf("Hello %s", name)
}

// TestHello shows a simple test with a suite
// setup. The stuite is configured in main_test.go
// which creates test environment `testenv` as a global
// package variable so that it can be accessed here.
func TestHello(t *testing.T) {
	feat := features.New("Hello Feature").
		WithLabel("type", "simple").
		Assess("test message", func(ctx context.Context, t *testing.T, _ *envconf.Config) context.Context {
			name := ctx.Value(1).(string)
			result := Hello(name)
			if result != "Hello bazz" {
				t.Error("unexpected message")
			}
			return ctx
		}).Feature()

	testenv.Test(t, feat)
}
