Skip to content

Commit 8412394

Browse files
authored
Merge pull request #70 from helayoty/helayoty/kind-cluster-with-param
feat: Kind Cluster with Config
2 parents ebed032 + 7635793 commit 8412394

File tree

5 files changed

+201
-0
lines changed

5 files changed

+201
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
kind: Cluster
2+
apiVersion: kind.x-k8s.io/v1alpha4
3+
nodes:
4+
- role: control-plane
5+
- role: worker
6+
- role: worker
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
Copyright 2021 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package kind
18+
19+
import (
20+
"context"
21+
"testing"
22+
"time"
23+
24+
appsv1 "k8s.io/api/apps/v1"
25+
corev1 "k8s.io/api/core/v1"
26+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27+
"sigs.k8s.io/e2e-framework/pkg/envconf"
28+
"sigs.k8s.io/e2e-framework/pkg/features"
29+
)
30+
31+
func TestKindCluster(t *testing.T) {
32+
33+
deploymentFeature := features.New("appsv1/deployment").
34+
Setup(func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context {
35+
// start a deployment
36+
deployment := newDeployment(cfg.Namespace(), "test-deployment", 1)
37+
if err := cfg.Client().Resources().Create(ctx, deployment); err != nil {
38+
t.Fatal(err)
39+
}
40+
time.Sleep(2 * time.Second)
41+
return ctx
42+
}).
43+
Assess("deployment creation", func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context {
44+
var dep appsv1.Deployment
45+
if err := cfg.Client().Resources().Get(ctx, "test-deployment", cfg.Namespace(), &dep); err != nil {
46+
t.Fatal(err)
47+
}
48+
if &dep != nil {
49+
t.Logf("deployment found: %s", dep.Name)
50+
}
51+
return context.WithValue(ctx, "test-deployment", &dep)
52+
}).
53+
Teardown(func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context {
54+
dep := ctx.Value("test-deployment").(*appsv1.Deployment)
55+
if err := cfg.Client().Resources().Delete(ctx, dep); err != nil {
56+
t.Fatal(err)
57+
}
58+
return ctx
59+
}).Feature()
60+
61+
testenv.Test(t, deploymentFeature)
62+
}
63+
64+
func newDeployment(namespace string, name string, replicaCount int32) *appsv1.Deployment {
65+
return &appsv1.Deployment{
66+
ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: namespace, Labels: map[string]string{"app": "test-app"}},
67+
Spec: appsv1.DeploymentSpec{
68+
Replicas: &replicaCount,
69+
Selector: &metav1.LabelSelector{
70+
MatchLabels: map[string]string{"app": "test-app"},
71+
},
72+
Template: corev1.PodTemplateSpec{
73+
ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{"app": "test-app"}},
74+
Spec: corev1.PodSpec{Containers: []corev1.Container{{Name: "nginx", Image: "nginx"}}},
75+
},
76+
},
77+
}
78+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
Copyright 2021 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package kind
18+
19+
import (
20+
"os"
21+
"testing"
22+
23+
"sigs.k8s.io/e2e-framework/pkg/env"
24+
"sigs.k8s.io/e2e-framework/pkg/envconf"
25+
"sigs.k8s.io/e2e-framework/pkg/envfuncs"
26+
)
27+
28+
var (
29+
testenv env.Environment
30+
)
31+
32+
func TestMain(m *testing.M) {
33+
testenv = env.New()
34+
kindClusterName := envconf.RandomName("kind-with-config", 16)
35+
namespace := envconf.RandomName("kind-ns", 16)
36+
37+
testenv.Setup(
38+
envfuncs.CreateKindClusterWithConfig(kindClusterName, "kindest/node:v1.22.2", "kind-config.yaml"),
39+
envfuncs.CreateNamespace(namespace),
40+
)
41+
42+
testenv.Finish(
43+
envfuncs.DeleteNamespace(namespace),
44+
envfuncs.DestroyKindCluster(kindClusterName),
45+
)
46+
os.Exit(testenv.Run(m))
47+
}

pkg/envfuncs/kind_funcs.go

+25
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,31 @@ func CreateKindCluster(clusterName string) env.Func {
5353
}
5454
}
5555

56+
// CreateKindClusterWithConfig returns an env.Func that is used to
57+
// create a kind cluster that is then injected in the context
58+
// using the name as a key.
59+
//
60+
// NOTE: the returned function will update its env config with the
61+
// kubeconfig file for the config client.
62+
//
63+
func CreateKindClusterWithConfig(clusterName, image, configFilePath string) env.Func {
64+
return func(ctx context.Context, cfg *envconf.Config) (context.Context, error) {
65+
k := kind.NewCluster(clusterName)
66+
kubecfg, err := k.CreateWithConfig(image, configFilePath)
67+
if err != nil {
68+
return ctx, err
69+
}
70+
71+
// stall, wait for pods initializations
72+
time.Sleep(7 * time.Second)
73+
74+
// update envconfig with kubeconfig
75+
cfg.WithKubeconfigFile(kubecfg)
76+
// store entire cluster value in ctx for future access using the cluster name
77+
return context.WithValue(ctx, kindContextKey(clusterName), k), nil
78+
}
79+
}
80+
5681
// DestroyKindCluster returns an EnvFunc that
5782
// retrieves a previously saved kind Cluster in the context (using the name), then deletes it.
5883
//

support/kind/kind.go

+45
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,51 @@ func (k *Cluster) WithVersion(ver string) *Cluster {
4646
return k
4747
}
4848

49+
func (k *Cluster) CreateWithConfig(imageName, kindConfigFile string) (string, error) {
50+
log.Println("Creating kind cluster ", k.name)
51+
if err := k.findOrInstallKind(k.e); err != nil {
52+
return "", err
53+
}
54+
55+
if strings.Contains(k.e.Run("kind get clusters"), k.name) {
56+
log.Println("Skipping Kind Cluster.Create: cluster already created: ", k.name)
57+
return "", nil
58+
}
59+
60+
log.Println("launching: kind create cluster --name", k.name, "--image", imageName, "--config", kindConfigFile)
61+
p := k.e.RunProc(fmt.Sprintf(`kind create cluster --name %s --image %s --config %s`, k.name, imageName, kindConfigFile))
62+
if p.Err() != nil {
63+
return "", fmt.Errorf("failed to create kind cluster: %s : %s", p.Err(), p.Result())
64+
}
65+
66+
clusters := k.e.Run("kind get clusters")
67+
if !strings.Contains(clusters, k.name) {
68+
return "", fmt.Errorf("kind Cluster.Create: cluster %v still not in 'cluster list' after creation: %v", k.name, clusters)
69+
}
70+
log.Println("kind clusters available: ", clusters)
71+
72+
// Grab kubeconfig file for cluster.
73+
kubecfg := fmt.Sprintf("%s-kubecfg", k.name)
74+
p = k.e.RunProc(fmt.Sprintf(`kind get kubeconfig --name %s`, k.name))
75+
if p.Err() != nil {
76+
return "", fmt.Errorf("kind get kubeconfig: %s: %w", p.Result(), p.Err())
77+
}
78+
79+
file, err := ioutil.TempFile("", fmt.Sprintf("kind-cluser-%s", kubecfg))
80+
if err != nil {
81+
return "", fmt.Errorf("kind kubeconfig file: %w", err)
82+
}
83+
defer file.Close()
84+
85+
k.kubecfgFile = file.Name()
86+
87+
if n, err := io.Copy(file, strings.NewReader(p.Result())); n == 0 || err != nil {
88+
return "", fmt.Errorf("kind kubecfg file: bytes copied: %d: %w]", n, err)
89+
}
90+
91+
return file.Name(), nil
92+
}
93+
4994
func (k *Cluster) Create() (string, error) {
5095
log.Println("Creating kind cluster ", k.name)
5196
if err := k.findOrInstallKind(k.e); err != nil {

0 commit comments

Comments
 (0)