mirror of
https://github.com/kubevela/kubevela.git
synced 2026-05-20 08:13:23 +00:00
* feat(env): Add comprehensive unit tests for environment management This commit introduces a comprehensive suite of unit tests for the environment management functions in `pkg/utils/env`. Key changes include: - Refactoring the test setup to use `TestMain` for better test environment control. - Adding new test cases for `CreateEnv`, `GetEnvByName`, `ListEnvs`, `SetCurrentEnv`, `SetEnvLabels`, and `DeleteEnv`. These tests improve the overall test coverage and ensure the correctness and reliability of environment-related operations. Signed-off-by: Ashvin Bambhaniya <ashvin.bambhaniya@improwised.com> * feat(errors): Add unit tests for error handling utilities This commit introduces new unit tests for the error handling utilities located in `pkg/utils/errors/`. Specifically, new test files have been added for: - `crd_test.go`: Tests for CRD-related error checks. - `list_test.go`: Tests for error list aggregation. - `reason_test.go`: Tests for specific error reasons like label conflicts and CUE path not found. - `resourcetracker_test.go`: Tests for resource tracker errors. These additions improve the test coverage and ensure the robustness of KubeVela's error handling mechanisms. Signed-off-by: Ashvin Bambhaniya <ashvin.bambhaniya@improwised.com> * refactor(schema): Refactor ui_schema_test.go to use testify/assert and add new test cases This commit refactors `pkg/utils/schema/ui_schema_test.go` to improve its readability and maintainability. Key changes include: - Migrating from Ginkgo/Gomega to testify/assert for assertions. - Restructuring `TestGetDefaultUIType` into a table-driven test. - Adding new comprehensive test cases for `Condition_Validate` function. These changes enhance the test suite for UI schema utilities, making it more robust and easier to extend. Signed-off-by: Ashvin Bambhaniya <ashvin.bambhaniya@improwised.com> * refactor(system): Refactor system_test.go and add comprehensive unit tests This commit refactors `pkg/utils/system/system_test.go` to improve its structure, readability, and test coverage. Key changes include: - Converting existing tests to a table-driven format using `testify/assert`. - Adding new comprehensive test cases for: - `CreateIfNotExist` - `GetVelaHomeDir` - `GetDirectoryFunctions` (e.g., `GetCapCenterDir`, `GetCapabilityDir`) - `InitFunctions` (e.g., `InitCapabilityDir`, `InitCapCenterDir`, `InitDirs`) - `BindEnvironmentVariables` These changes enhance the test suite for system utilities, ensuring their correctness and robustness. Signed-off-by: Ashvin Bambhaniya <ashvin.bambhaniya@improwised.com> * feat(types): Add unit tests for QL types This commit introduces new unit tests for the types defined in `pkg/utils/types`, specifically focusing on types related to KubeVela Query Language (QL). New test cases cover: - `ServiceEndpoint.String()`: Verifies the string representation of service endpoints, including various protocols, ports, and paths. - `AppliedResource.GroupVersionKind()`: Ensures correct extraction of GroupVersionKind from applied resources. - `ResourceTreeNode.GroupVersionKind()`: Verifies correct extraction of GroupVersionKind from resource tree nodes. These tests improve the coverage and reliability of core data structures used in KubeVela. Signed-off-by: Ashvin Bambhaniya <ashvin.bambhaniya@improwised.com> * feat(util): Add and refactor unit tests for utility functions This commit introduces new unit tests and refactors existing ones within the `pkg/utils/util` package. Key changes include: - **`pkg/utils/util/cmd_test.go`**: Adds comprehensive tests for `IOStreams` and its print functions, as well as `NewDefaultIOStreams` and `NewTestIOStreams`. - **`pkg/utils/util/factory_test.go`**: Refactors the `GenerateLeaderElectionID` test to a table-driven format and adds new tests for `computeDiscoverCacheDir` and `RestConfigGetter` methods, ensuring the correctness of Kubernetes client configuration and discovery. These additions and refactorings enhance the test coverage and reliability of core utility functions. Signed-off-by: Ashvin Bambhaniya <ashvin.bambhaniya@improwised.com> * feat(utils): Add and refactor unit tests for json, jwt, parse, and strings utilities This commit introduces new unit tests and refactors existing ones across several utility packages within `pkg/utils/`. Key changes include: - **`pkg/utils/json`**: Adds tests for `StrictUnmarshal` to ensure proper JSON unmarshaling. - **`pkg/utils/jwt`**: Adds tests for JWT token subject extraction and certificate subject retrieval. - **`pkg/utils/parse`**: Expands test coverage for URL parsing functions (`Parse`, `ParseGitlab`). - **`pkg/utils/strings`**: Refactors existing tests to a table-driven format and adds tests for box drawing string generation. These additions and refactorings significantly improve the test coverage and reliability of KubeVela's utility functions. Signed-off-by: Ashvin Bambhaniya <ashvin.bambhaniya@improwised.com> * fix(tests): Address test and error handling issues This commit addresses several issues identified in unit tests and error handling utilities, improving test reliability and code safety. Key fixes and improvements include: - **`pkg/utils/errors`**: - Added nil check to `IsCuePathNotFound` to prevent panics. - Corrected `fmt.Errorf` usage to `errors.New` in `reason_test.go` (SA1006 fix). - Used `assert.EqualError` for clearer error message comparisons in `resourcetracker_test.go`. - **`pkg/utils/jwt_test.go`**: Marked `generateTestCert` as a test helper using `t.Helper()` for better error reporting. - **`pkg/utils/system_test.go`**: - Removed unused `verifyCleanup` field. - Modified `TestGetVelaHomeDir` to use a temporary home directory, preventing destructive operations on the user's system. - **`pkg/utils/util/cmd_test.go`**: Swapped `assert.Equal` arguments to follow `expected, actual` convention. These changes enhance the robustness and correctness of the test suite and related utility functions. Signed-off-by: Ashvin Bambhaniya <ashvin.bambhaniya@improwised.com> * chore(tests): Apply gofmt and import ordering to test files This commit applies standard Go formatting (`gofmt`) and corrects import ordering in several test files. Affected files: - `pkg/utils/schema/ui_schema_test.go`: Added missing newline at EOF. - `pkg/utils/system/system_test.go`: Corrected import ordering. - `pkg/utils/util/factory_test.go`: Corrected import ordering. These changes ensure consistency with project coding standards. Signed-off-by: Ashvin Bambhaniya <ashvin.bambhaniya@improwised.com> --------- Signed-off-by: Ashvin Bambhaniya <ashvin.bambhaniya@improwised.com>
334 lines
9.6 KiB
Go
334 lines
9.6 KiB
Go
/*
|
|
Copyright 2021 The KubeVela 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 env
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/kubevela/pkg/util/singleton"
|
|
"github.com/stretchr/testify/assert"
|
|
v1 "k8s.io/api/core/v1"
|
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/apimachinery/pkg/runtime"
|
|
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
|
|
"k8s.io/client-go/rest"
|
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
|
"sigs.k8s.io/controller-runtime/pkg/envtest"
|
|
|
|
"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
|
|
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
|
|
"github.com/oam-dev/kubevela/apis/types"
|
|
"github.com/oam-dev/kubevela/pkg/oam"
|
|
"github.com/oam-dev/kubevela/pkg/utils/system"
|
|
)
|
|
|
|
var cfg *rest.Config
|
|
var k8sClient client.Client
|
|
var testScheme = runtime.NewScheme()
|
|
|
|
func TestMain(m *testing.M) {
|
|
testEnv := &envtest.Environment{
|
|
ControlPlaneStartTimeout: time.Minute,
|
|
ControlPlaneStopTimeout: time.Minute,
|
|
CRDDirectoryPaths: []string{
|
|
filepath.Join("../../..", "charts/vela-core/crds"),
|
|
},
|
|
}
|
|
|
|
var err error
|
|
cfg, err = testEnv.Start()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
if err := clientgoscheme.AddToScheme(testScheme); err != nil {
|
|
panic(err)
|
|
}
|
|
if err := v1beta1.AddToScheme(testScheme); err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
k8sClient, err = client.New(cfg, client.Options{Scheme: testScheme})
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
singleton.KubeClient.Set(k8sClient)
|
|
|
|
code := m.Run()
|
|
|
|
if err := testEnv.Stop(); err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
os.Exit(code)
|
|
}
|
|
|
|
func createTestNamespace(ctx context.Context, t *testing.T, nsName string) {
|
|
ns := &v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: nsName}}
|
|
err := k8sClient.Create(ctx, ns)
|
|
if err != nil && !apierrors.IsAlreadyExists(err) {
|
|
assert.NoError(t, err)
|
|
}
|
|
}
|
|
|
|
func TestCreateEnv(t *testing.T) {
|
|
ctx := context.Background()
|
|
t.Run("create a new env successfully", func(t *testing.T) {
|
|
nsName := "create-env-ns-1"
|
|
createTestNamespace(ctx, t, nsName)
|
|
envMeta := &types.EnvMeta{Name: "env-create-1", Namespace: nsName}
|
|
err := CreateEnv(envMeta)
|
|
assert.NoError(t, err)
|
|
|
|
var createdNs v1.Namespace
|
|
err = k8sClient.Get(ctx, client.ObjectKey{Name: nsName}, &createdNs)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "env-create-1", createdNs.Labels[oam.LabelNamespaceOfEnvName])
|
|
assert.Equal(t, oam.VelaNamespaceUsageEnv, createdNs.Labels[oam.LabelControlPlaneNamespaceUsage])
|
|
})
|
|
|
|
t.Run("create env with a name that already exists", func(t *testing.T) {
|
|
nsName1, nsName2 := "create-env-ns-2", "create-env-ns-3"
|
|
createTestNamespace(ctx, t, nsName1)
|
|
createTestNamespace(ctx, t, nsName2)
|
|
|
|
envMeta1 := &types.EnvMeta{Name: "env-exist", Namespace: nsName1}
|
|
err := CreateEnv(envMeta1)
|
|
assert.NoError(t, err)
|
|
|
|
envMeta2 := &types.EnvMeta{Name: "env-exist", Namespace: nsName2}
|
|
err = CreateEnv(envMeta2)
|
|
assert.Error(t, err)
|
|
assert.Equal(t, "env name env-exist already exists", err.Error())
|
|
})
|
|
|
|
t.Run("create env in a namespace that is already used by another env", func(t *testing.T) {
|
|
nsName := "create-env-ns-4"
|
|
createTestNamespace(ctx, t, nsName)
|
|
|
|
envMeta1 := &types.EnvMeta{Name: "env-ns-used-1", Namespace: nsName}
|
|
err := CreateEnv(envMeta1)
|
|
assert.NoError(t, err)
|
|
|
|
envMeta2 := &types.EnvMeta{Name: "env-ns-used-2", Namespace: nsName}
|
|
err = CreateEnv(envMeta2)
|
|
assert.Error(t, err)
|
|
assert.Equal(t, "the namespace create-env-ns-4 was already assigned to env env-ns-used-1", err.Error())
|
|
})
|
|
}
|
|
|
|
func TestGetEnvByName(t *testing.T) {
|
|
ctx := context.Background()
|
|
nsName := "get-env-ns"
|
|
envName := "test-get"
|
|
createTestNamespace(ctx, t, nsName)
|
|
assert.NoError(t, CreateEnv(&types.EnvMeta{Name: envName, Namespace: nsName}))
|
|
|
|
t.Run("get existing env", func(t *testing.T) {
|
|
env, err := GetEnvByName(envName)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, envName, env.Name)
|
|
assert.Equal(t, nsName, env.Namespace)
|
|
})
|
|
|
|
t.Run("get default env", func(t *testing.T) {
|
|
env, err := GetEnvByName("default")
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "default", env.Name)
|
|
assert.Equal(t, "default", env.Namespace)
|
|
})
|
|
|
|
t.Run("get non-existent env", func(t *testing.T) {
|
|
_, err := GetEnvByName("non-existent")
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "not exist")
|
|
})
|
|
}
|
|
|
|
func TestListAndCurrentEnvs(t *testing.T) {
|
|
ctx := context.Background()
|
|
// Setup a temp home for current env file
|
|
tmpDir, err := os.MkdirTemp("", "vela-home")
|
|
assert.NoError(t, err)
|
|
defer os.RemoveAll(tmpDir)
|
|
t.Setenv("HOME", tmpDir)
|
|
|
|
// Create test envs
|
|
nsList1, envList1 := "list-env-ns-1", "test-list-1"
|
|
createTestNamespace(ctx, t, nsList1)
|
|
assert.NoError(t, CreateEnv(&types.EnvMeta{Name: envList1, Namespace: nsList1}))
|
|
|
|
nsList2, envList2 := "list-env-ns-2", "test-list-2"
|
|
createTestNamespace(ctx, t, nsList2)
|
|
assert.NoError(t, CreateEnv(&types.EnvMeta{Name: envList2, Namespace: nsList2}))
|
|
|
|
t.Run("list specific env", func(t *testing.T) {
|
|
envs, err := ListEnvs(envList1)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 1, len(envs))
|
|
assert.Equal(t, envList1, envs[0].Name)
|
|
})
|
|
|
|
t.Run("list non-existent env", func(t *testing.T) {
|
|
_, err := ListEnvs("non-existent-list")
|
|
assert.Error(t, err)
|
|
})
|
|
|
|
t.Run("list all envs and check current marker", func(t *testing.T) {
|
|
envs, err := ListEnvs("")
|
|
assert.NoError(t, err)
|
|
found1, found2, current := false, false, false
|
|
for _, e := range envs {
|
|
if e.Name == envList1 {
|
|
found1 = true
|
|
}
|
|
if e.Name == envList2 {
|
|
found2 = true
|
|
}
|
|
if e.Current == "*" {
|
|
current = true
|
|
}
|
|
}
|
|
assert.True(t, found1)
|
|
assert.True(t, found2)
|
|
assert.True(t, current) // ListEnvs should set a default current env
|
|
})
|
|
|
|
t.Run("set and get current env", func(t *testing.T) {
|
|
testEnvForCurrent := &types.EnvMeta{Name: envList2, Namespace: nsList2}
|
|
err := SetCurrentEnv(testEnvForCurrent)
|
|
assert.NoError(t, err)
|
|
|
|
curEnv, err := GetCurrentEnv()
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, envList2, curEnv.Name)
|
|
|
|
// Verify ListEnvs reflects the new current env
|
|
envs, err := ListEnvs("")
|
|
assert.NoError(t, err)
|
|
for _, e := range envs {
|
|
if e.Name == envList2 {
|
|
assert.Equal(t, "*", e.Current)
|
|
} else {
|
|
assert.Equal(t, "", e.Current)
|
|
}
|
|
}
|
|
})
|
|
|
|
t.Run("get current env with legacy format", func(t *testing.T) {
|
|
envPath, err := system.GetCurrentEnvPath()
|
|
assert.NoError(t, err)
|
|
err = os.WriteFile(envPath, []byte(envList1), 0644)
|
|
assert.NoError(t, err)
|
|
|
|
curEnv, err := GetCurrentEnv()
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, envList1, curEnv.Name)
|
|
assert.Equal(t, nsList1, curEnv.Namespace)
|
|
|
|
// Check if the format was updated
|
|
data, err := os.ReadFile(filepath.Clean(envPath))
|
|
assert.NoError(t, err)
|
|
var envMeta types.EnvMeta
|
|
assert.NoError(t, json.Unmarshal(data, &envMeta))
|
|
assert.Equal(t, envList1, envMeta.Name)
|
|
})
|
|
}
|
|
|
|
func TestSetEnvLabels(t *testing.T) {
|
|
ctx := context.Background()
|
|
nsName := "set-labels-ns"
|
|
envName := "test-labels"
|
|
createTestNamespace(ctx, t, nsName)
|
|
assert.NoError(t, CreateEnv(&types.EnvMeta{Name: envName, Namespace: nsName}))
|
|
|
|
t.Run("set valid labels", func(t *testing.T) {
|
|
envMeta := &types.EnvMeta{Name: envName, Labels: "foo=bar,hello=world"}
|
|
err := SetEnvLabels(envMeta)
|
|
assert.NoError(t, err)
|
|
|
|
ns := &v1.Namespace{}
|
|
err = k8sClient.Get(ctx, client.ObjectKey{Name: nsName}, ns)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "bar", ns.Labels["foo"])
|
|
assert.Equal(t, "world", ns.Labels["hello"])
|
|
})
|
|
|
|
t.Run("set labels on non-existent env", func(t *testing.T) {
|
|
envMeta := &types.EnvMeta{Name: "non-existent-labels"}
|
|
err := SetEnvLabels(envMeta)
|
|
assert.Error(t, err)
|
|
})
|
|
|
|
t.Run("set invalid labels", func(t *testing.T) {
|
|
envMeta := &types.EnvMeta{Name: envName, Labels: "invalid-label"}
|
|
err := SetEnvLabels(envMeta)
|
|
assert.Error(t, err)
|
|
})
|
|
}
|
|
|
|
func TestDeleteEnv(t *testing.T) {
|
|
ctx := context.Background()
|
|
t.Run("delete env with application", func(t *testing.T) {
|
|
nsName := "delete-env-ns-with-app"
|
|
envName := "test-delete-with-app"
|
|
createTestNamespace(ctx, t, nsName)
|
|
assert.NoError(t, CreateEnv(&types.EnvMeta{Name: envName, Namespace: nsName}))
|
|
|
|
app := &v1beta1.Application{
|
|
ObjectMeta: metav1.ObjectMeta{Name: "test-app", Namespace: nsName},
|
|
Spec: v1beta1.ApplicationSpec{
|
|
Components: []common.ApplicationComponent{{Name: "c1", Type: "worker"}},
|
|
},
|
|
}
|
|
err := k8sClient.Create(ctx, app)
|
|
assert.NoError(t, err)
|
|
|
|
_, err = DeleteEnv(envName)
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "you can't delete this environment")
|
|
})
|
|
|
|
t.Run("delete empty env", func(t *testing.T) {
|
|
nsName := "delete-env-ns-empty"
|
|
envName := "test-delete-empty"
|
|
createTestNamespace(ctx, t, nsName)
|
|
assert.NoError(t, CreateEnv(&types.EnvMeta{Name: envName, Namespace: nsName}))
|
|
|
|
msg, err := DeleteEnv(envName)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "env "+envName+" deleted", msg)
|
|
|
|
ns := &v1.Namespace{}
|
|
err = k8sClient.Get(ctx, client.ObjectKey{Name: nsName}, ns)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "", ns.Labels[oam.LabelNamespaceOfEnvName])
|
|
assert.Equal(t, "", ns.Labels[oam.LabelControlPlaneNamespaceUsage])
|
|
})
|
|
|
|
t.Run("delete non-existent env", func(t *testing.T) {
|
|
_, err := DeleteEnv("non-existent-delete")
|
|
assert.Error(t, err)
|
|
})
|
|
}
|