Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add attachedcluater e2e test #594

Merged
merged 10 commits into from
Feb 2, 2024
33 changes: 33 additions & 0 deletions .github/workflows/e2e.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: E2E
on:
pull_request:
jobs:
e2e-test:
runs-on: ubuntu-22.04
name: E2E Test
timeout-minutes: 40
steps:
- name: Install Go
uses: actions/setup-go@v4
with:
go-version: 1.20.x
- name: Checkout code
uses: actions/checkout@v4
- name: Build Clusters
uses: helm/[email protected]
with:
version: v0.20.0
install_only: true
- name: Set Up Clusters
run: |
hack/e2e-test/build-clusters.sh
- name: Install Helm
uses: azure/setup-helm@v3
with:
version: v3.10.1
- name: Init kurator cluster
run: |
hack/e2e-test/install-kurator.sh
- name: fleet-clusters e2e test
run: |
hack/e2e-test/run-e2e.sh
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,8 @@ gen-chart: sync-crds

.PHONY: test
test: clean tidy
go test ./...
go test ./pkg/...
go test ./cmd/...

.PHONY: clean
clean:
Expand Down
86 changes: 86 additions & 0 deletions e2e/attachedcluster_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
Copyright Kurator 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 e2e

import (
"os"
"path/filepath"
"time"

"github.com/onsi/ginkgo/v2"
"github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"

"kurator.dev/kurator/e2e/resources"
clusterv1a1 "kurator.dev/kurator/pkg/apis/cluster/v1alpha1"
)

var _ = ginkgo.Describe("[AttachedClusters] AttachedClusters testing", func() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need to cleanup the resources created per test

var (
namespace string
fleetname string
memberClusterName string
kubeconfigPath string
secret *corev1.Secret
attachedcluster *clusterv1a1.AttachedCluster
)

ginkgo.BeforeEach(func() {
namespace = "default"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: use a random namespace for each test

fleetname = "e2etest"
memberClusterName = "kurator-member"
homeDir, err := os.UserHomeDir()
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
kubeconfigPath = filepath.Join(homeDir, ".kube/kurator-member.config")

// build secrets use member cluster kubeconfig
kubeconfig, readfileErr := os.ReadFile(kubeconfigPath)
gomega.Expect(readfileErr).ShouldNot(gomega.HaveOccurred())
data := make(map[string][]byte)
data[memberClusterName] = kubeconfig
secret = resources.NewSecret(namespace, memberClusterName, data)

// build two attachedclusters
secretKeyRef := clusterv1a1.SecretKeyRef{
Name: memberClusterName,
Key: memberClusterName,
}
attachedcluster = resources.NewAttachedCluster(namespace, memberClusterName, secretKeyRef)
})

ginkgo.It("Create Fleet", func() {
// step 1.create secrets
secretCreateErr := resources.CreateSecret(kubeClient, secret)
gomega.Expect(secretCreateErr).ShouldNot(gomega.HaveOccurred())

// step 2.create attachedclusters
attachedCreateErr := resources.CreateAttachedCluster(kuratorClient, attachedcluster)
gomega.Expect(attachedCreateErr).ShouldNot(gomega.HaveOccurred())

time.Sleep(5 * time.Second)
// step 3.create fleet
clusters := []*corev1.ObjectReference{
{
Name: memberClusterName,
Kind: "AttachedCluster",
},
}
fleet := resources.NewFleet(namespace, fleetname, clusters)
fleetCreateErr := resources.CreateFleet(kuratorClient, fleet)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't we need to check fleet status?

gomega.Expect(fleetCreateErr).ShouldNot(gomega.HaveOccurred())
})
})
44 changes: 44 additions & 0 deletions e2e/framework/cluster.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
Copyright Kurator 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 framework

import (
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/klog/v2"
)

// LoadRESTClientConfig creates a rest.Config using the passed kubeconfig. If context is empty, current context in kubeconfig will be used.
func LoadRESTClientConfig(kubeconfig string, context string) (*rest.Config, error) {
loader := &clientcmd.ClientConfigLoadingRules{ExplicitPath: kubeconfig}
loadedConfig, err := loader.Load()
if err != nil {
return nil, err
}

if context == "" {
context = loadedConfig.CurrentContext
}
klog.Infof("Use context %v", context)

return clientcmd.NewNonInteractiveClientConfig(
*loadedConfig,
context,
&clientcmd.ConfigOverrides{},
loader,
).ClientConfig()
}
65 changes: 65 additions & 0 deletions e2e/resources/attachedcluster.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
Copyright Kurator 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 resources

import (
"context"

apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

clusterv1a1 "kurator.dev/kurator/pkg/apis/cluster/v1alpha1"
kurator "kurator.dev/kurator/pkg/client-go/generated/clientset/versioned"
)

func NewAttachedCluster(namespace string, name string, config clusterv1a1.SecretKeyRef) *clusterv1a1.AttachedCluster {
return &clusterv1a1.AttachedCluster{
TypeMeta: metav1.TypeMeta{
APIVersion: "cluster.kurator.dev/v1alpha1",
Kind: "AttachedCluster",
},
ObjectMeta: metav1.ObjectMeta{
Namespace: namespace,
Name: name,
},
Spec: clusterv1a1.AttachedClusterSpec{
Kubeconfig: config,
},
}
}

// CreateAttachedCluster create AttachedCluster.
func CreateAttachedCluster(client kurator.Interface, attachedCluster *clusterv1a1.AttachedCluster) error {
_, err := client.ClusterV1alpha1().AttachedClusters(attachedCluster.Namespace).Create(context.TODO(), attachedCluster, metav1.CreateOptions{})
if err != nil {
if apierrors.IsAlreadyExists(err) {
return UpdateAttachedCluster(client, attachedCluster)
} else {
return err
}
}
return nil
}

// UpdateAttachedCluster update AttachedCluster
func UpdateAttachedCluster(client kurator.Interface, attachedCluster *clusterv1a1.AttachedCluster) error {
_, err := client.ClusterV1alpha1().AttachedClusters(attachedCluster.Namespace).Update(context.TODO(), attachedCluster, metav1.UpdateOptions{})
if err != nil {
return err
}
return nil
}
66 changes: 66 additions & 0 deletions e2e/resources/fleet.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
Copyright Kurator 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 resources

import (
"context"

corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

fleetv1a1 "kurator.dev/kurator/pkg/apis/fleet/v1alpha1"
kurator "kurator.dev/kurator/pkg/client-go/generated/clientset/versioned"
)

func NewFleet(namespace string, name string, clusters []*corev1.ObjectReference) *fleetv1a1.Fleet {
return &fleetv1a1.Fleet{
TypeMeta: metav1.TypeMeta{
APIVersion: "fleet.kurator.dev/v1alpha1",
Kind: "Fleet",
},
ObjectMeta: metav1.ObjectMeta{
Namespace: namespace,
Name: name,
},
Spec: fleetv1a1.FleetSpec{
Clusters: clusters,
},
}
}

// CreateAttachedCluster create AttachedCluster.
func CreateFleet(client kurator.Interface, fleet *fleetv1a1.Fleet) error {
_, err := client.FleetV1alpha1().Fleets(fleet.Namespace).Create(context.TODO(), fleet, metav1.CreateOptions{})
if err != nil {
if apierrors.IsAlreadyExists(err) {
return UpdateFleet(client, fleet)
} else {
return err
}
}
return nil
}

// UpdateAttachedCluster update AttachedCluster
func UpdateFleet(client kurator.Interface, fleet *fleetv1a1.Fleet) error {
_, err := client.FleetV1alpha1().Fleets(fleet.Namespace).Update(context.TODO(), fleet, metav1.UpdateOptions{})
if err != nil {
return err
}
return nil
}
63 changes: 63 additions & 0 deletions e2e/resources/secret.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
Copyright Kurator 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 resources

import (
"context"

corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
)

// NewSecret will build a secret object.
func NewSecret(namespace string, name string, data map[string][]byte) *corev1.Secret {
return &corev1.Secret{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Secret",
},
ObjectMeta: metav1.ObjectMeta{
Namespace: namespace,
Name: name,
},
Data: data,
}
}

// CreateSecret create Secret.
func CreateSecret(client kubernetes.Interface, secret *corev1.Secret) error {
_, err := client.CoreV1().Secrets(secret.Namespace).Create(context.TODO(), secret, metav1.CreateOptions{})
if err != nil {
if apierrors.IsAlreadyExists(err) {
return UpdateSecret(client, secret)
} else {
return err
}
}
return nil
}

// UpdateSecret update Secret
func UpdateSecret(client kubernetes.Interface, secret *corev1.Secret) error {
_, err := client.CoreV1().Secrets(secret.Namespace).Update(context.TODO(), secret, metav1.UpdateOptions{})
if err != nil {
return err
}
return nil
}
17 changes: 17 additions & 0 deletions e2e/suite.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
Copyright Kurator 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 e2e
Loading
Loading