mirror of
https://github.com/kubevela/kubevela.git
synced 2026-08-18 20:17:04 +00:00
* feat: implement output resource existence validation in component, trait, and policy definitions Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> feat: add validation tests for ComponentDefinition and TraitDefinition outputs - Implement tests for ComponentDefinition with non-existent CRDs in outputs, ensuring they are rejected. - Add tests for valid outputs in ComponentDefinition, confirming acceptance. - Include tests for mixed valid and non-K8s outputs in ComponentDefinition, verifying they pass validation. - Test handling of empty outputs in ComponentDefinition, ensuring they are accepted. - Introduce tests for invalid apiVersion formats in ComponentDefinition, confirming rejection. - Add tests for TraitDefinition with mixed valid and invalid outputs, ensuring proper rejection. - Create YAML manifests for valid and invalid ComponentDefinitions and TraitDefinitions to support e2e tests. - Ensure comprehensive coverage of edge cases in output validation logic. Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> fix: handle errors in resource validation for component, trait, and policy definitions Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> fix: improve error handling in Go module tidy and resource validation Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> feat: add webhook debugging setup and validation tests for ComponentDefinition and TraitDefinition Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> feat: add VS Code launch configuration for debugging webhook validation Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> refactor: streamline error handling in Go module tidy and remove obsolete test manifests Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> feat: add mock context support for CUE template compilation Signed-off-by: Reetika Malhotra <malhotra.reetika25@gmail.com> Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> feat: enhance validation for WorkflowStepDefinition resources and improve output resource checks Signed-off-by: viskumar <viskumar@guidewire.com> Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> feat: implement resource validation for CUE templates and add unit tests Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> feat: enhance logging and validation for component, policy, and trait definitions Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> feat: improve error handling and logging in validation handlers for component, policy, trait, and workflow step definitions Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> Remove testUnknownResource folder from repository Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> feat: implement structured logging for validation handlers and remove deprecated request_logger Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> feat: enhance structured logging and error handling in admission validation handlers Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> feat: improve logging messages in validating handlers for better clarity Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> feat: refactor logging field definitions for consistency and improve error handling in resource validation Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> chore: add license header to invalid_resource_check.go and invalid_resource_check_test.go Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> feat: enhance validation tests for WorkflowStepDefinition and improve error messages Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> feat: add e2e-test-local target for k3d cluster setup and webhook validation Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> feat: add webhook configuration for workflow step definitions with validation rules Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> feat: update e2e-test-local configuration and improve Ingress API version compatibility Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> feat: add installation of FluxCD CRDs in pre-hook to prevent webhook validation errors Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> feat: add ValidateResourcesExist feature gate and enhance resource validation in webhook handlers Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> feat: enhance resource validation in e2e tests and improve addon definition checks Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> feat: enhance addon definition detection by using owner references for validation Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> feat: add ValidateResourcesExist feature gate and implement webhook validation for resource existence Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> feat: update Ingress API version to v1 and adjust service references in tests Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> chore: remove webhook test commands and related YAML files from makefiles and tests Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> chore: remove architecture section from webhook debugging guide Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> feat: update webhook setup script with k3d host gateway IP note and improve cluster creation logic Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> * Fix: Correct path in Ingress resource definition in template tests Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> * Chore: add empty line to re-trigger failing workflow Signed-off-by: Vaibhav Agrawal <vaibhav.agrawal0096@gmail.com> * Chore: remove space to re-trigger workflow Signed-off-by: Chaitanya Reddy Onteddu <co@guidewire.com> --------- Signed-off-by: Ayush Kumar <ayushshyamkumar888@gmail.com> Signed-off-by: Vaibhav Agrawal <vaibhav.agrawal0096@gmail.com> Signed-off-by: Chaitanya Reddy Onteddu <co@guidewire.com> Co-authored-by: Chaitanya Reddy Onteddu <chaitanyareddy0702@gmail.com> Co-authored-by: Amit Singh <amisingh@guidewire.com>
400 lines
11 KiB
Go
400 lines
11 KiB
Go
/*
|
|
Copyright 2022 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 model
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/kubevela/workflow/api/v1alpha1"
|
|
. "github.com/onsi/ginkgo/v2"
|
|
. "github.com/onsi/gomega"
|
|
appsv1 "k8s.io/api/apps/v1"
|
|
corev1 "k8s.io/api/core/v1"
|
|
"k8s.io/apimachinery/pkg/api/resource"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/apimachinery/pkg/runtime"
|
|
"k8s.io/client-go/rest"
|
|
"k8s.io/utils/ptr"
|
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
|
"sigs.k8s.io/controller-runtime/pkg/envtest"
|
|
|
|
common2 "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"
|
|
helmapi "github.com/oam-dev/kubevela/pkg/appfile/helm/flux2apis"
|
|
"github.com/oam-dev/kubevela/pkg/oam"
|
|
"github.com/oam-dev/kubevela/pkg/utils/common"
|
|
)
|
|
|
|
var cfg *rest.Config
|
|
var k8sClient client.Client
|
|
var testEnv *envtest.Environment
|
|
|
|
var _ = BeforeSuite(func() {
|
|
// env init
|
|
By("bootstrapping test environment")
|
|
testEnv = &envtest.Environment{
|
|
ControlPlaneStartTimeout: time.Minute * 3,
|
|
ControlPlaneStopTimeout: time.Minute,
|
|
UseExistingCluster: ptr.To(false),
|
|
CRDDirectoryPaths: []string{
|
|
"../../../../charts/vela-core/crds",
|
|
},
|
|
}
|
|
// env start
|
|
By("start kube test env")
|
|
var err error
|
|
cfg, err = testEnv.Start()
|
|
Expect(err).ShouldNot(HaveOccurred())
|
|
Expect(cfg).ToNot(BeNil())
|
|
// client start
|
|
By("new kube client")
|
|
cfg.Timeout = time.Minute * 2
|
|
k8sClient, err = client.New(cfg, client.Options{Scheme: common.Scheme})
|
|
Expect(err).Should(BeNil())
|
|
Expect(k8sClient).ToNot(BeNil())
|
|
|
|
// create namespace
|
|
By("create namespace")
|
|
_ = k8sClient.Create(context.Background(), &corev1.Namespace{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "default",
|
|
},
|
|
})
|
|
// create app
|
|
name, namespace := "first-vela-app", "default"
|
|
testApp := &v1beta1.Application{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: name,
|
|
Namespace: namespace,
|
|
},
|
|
Spec: v1beta1.ApplicationSpec{
|
|
Components: []common2.ApplicationComponent{
|
|
{
|
|
Name: "webservice-test",
|
|
Type: "webservice",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
err = k8sClient.Create(context.Background(), testApp)
|
|
Expect(err).Should(BeNil())
|
|
testApp.Status = common2.AppStatus{
|
|
Phase: common2.ApplicationRunning,
|
|
Workflow: &common2.WorkflowStatus{
|
|
AppRevision: "",
|
|
Mode: "DAG",
|
|
Phase: "",
|
|
Message: "",
|
|
Suspend: false,
|
|
SuspendState: "",
|
|
Terminated: false,
|
|
Finished: false,
|
|
ContextBackend: nil,
|
|
Steps: []v1alpha1.WorkflowStepStatus{},
|
|
StartTime: metav1.Time{},
|
|
EndTime: metav1.Time{},
|
|
},
|
|
AppliedResources: []common2.ClusterObjectReference{
|
|
{
|
|
Cluster: "",
|
|
ObjectReference: corev1.ObjectReference{
|
|
Kind: "Ingress",
|
|
Namespace: "default",
|
|
Name: "ingress-http",
|
|
APIVersion: "networking.k8s.io/v1",
|
|
},
|
|
},
|
|
{
|
|
Cluster: "",
|
|
ObjectReference: corev1.ObjectReference{
|
|
Kind: "Ingress",
|
|
Namespace: "default",
|
|
Name: "ingress-https",
|
|
APIVersion: "networking.k8s.io/v1",
|
|
},
|
|
},
|
|
{
|
|
Cluster: "",
|
|
ObjectReference: corev1.ObjectReference{
|
|
Kind: "Ingress",
|
|
Namespace: "default",
|
|
Name: "ingress-paths",
|
|
APIVersion: "networking.k8s.io/v1",
|
|
},
|
|
},
|
|
{
|
|
Cluster: "",
|
|
ObjectReference: corev1.ObjectReference{
|
|
Kind: "Service",
|
|
Namespace: "default",
|
|
Name: "nodeport",
|
|
APIVersion: "v1",
|
|
},
|
|
},
|
|
{
|
|
Cluster: "",
|
|
ObjectReference: corev1.ObjectReference{
|
|
Kind: "Service",
|
|
Namespace: "default",
|
|
Name: "loadbalancer",
|
|
APIVersion: "v1",
|
|
},
|
|
},
|
|
{
|
|
Cluster: "",
|
|
ObjectReference: corev1.ObjectReference{
|
|
Kind: helmapi.HelmReleaseGVK.Kind,
|
|
Namespace: "default",
|
|
Name: "helmRelease",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
err = k8sClient.Status().Update(context.Background(), testApp)
|
|
Expect(err).Should(BeNil())
|
|
// create service
|
|
svc := &corev1.Service{
|
|
TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "Service"},
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "service1",
|
|
Namespace: namespace,
|
|
},
|
|
Spec: corev1.ServiceSpec{
|
|
Ports: []corev1.ServicePort{{Port: 2002}},
|
|
},
|
|
}
|
|
svcRaw, err := json.Marshal(svc)
|
|
Expect(err).Should(Succeed())
|
|
Expect(k8sClient.Create(context.Background(), svc)).Should(BeNil())
|
|
// create deploy
|
|
dply := &appsv1.Deployment{
|
|
TypeMeta: metav1.TypeMeta{
|
|
Kind: "Deployment",
|
|
APIVersion: "apps/v1",
|
|
},
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "deploy1",
|
|
Namespace: namespace,
|
|
},
|
|
Spec: appsv1.DeploymentSpec{
|
|
Selector: &metav1.LabelSelector{
|
|
MatchLabels: map[string]string{"app": "test"},
|
|
},
|
|
Template: corev1.PodTemplateSpec{
|
|
ObjectMeta: metav1.ObjectMeta{Name: "pod", Namespace: namespace, Labels: map[string]string{"app": "test"}},
|
|
Spec: corev1.PodSpec{Containers: []corev1.Container{
|
|
{
|
|
Name: "vela-core-1",
|
|
Image: "vela",
|
|
},
|
|
}},
|
|
},
|
|
},
|
|
}
|
|
dplyRaw, err := json.Marshal(dply)
|
|
Expect(err).Should(Succeed())
|
|
Expect(k8sClient.Create(context.Background(), dply)).Should(BeNil())
|
|
//create replicaSet
|
|
var rsNum int32 = 2
|
|
rs := &appsv1.ReplicaSet{
|
|
TypeMeta: metav1.TypeMeta{
|
|
Kind: "ReplicaSet",
|
|
APIVersion: "apps/v1",
|
|
},
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "rs1",
|
|
Namespace: namespace,
|
|
Labels: map[string]string{"app": "test"},
|
|
},
|
|
Spec: appsv1.ReplicaSetSpec{
|
|
Replicas: &rsNum,
|
|
Selector: &metav1.LabelSelector{
|
|
MatchLabels: map[string]string{"app": "test"},
|
|
},
|
|
Template: corev1.PodTemplateSpec{
|
|
ObjectMeta: metav1.ObjectMeta{Name: "pod", Namespace: namespace, Labels: map[string]string{"app": "test"}},
|
|
Spec: corev1.PodSpec{Containers: []corev1.Container{
|
|
{
|
|
Name: "vela-core-1",
|
|
Image: "vela",
|
|
},
|
|
}},
|
|
},
|
|
},
|
|
}
|
|
rsRaw, err := json.Marshal(rs)
|
|
Expect(err).Should(Succeed())
|
|
Expect(k8sClient.Create(context.Background(), rs)).Should(BeNil())
|
|
// create pod
|
|
pod := &corev1.Pod{
|
|
TypeMeta: metav1.TypeMeta{
|
|
Kind: "Pod",
|
|
APIVersion: "v1",
|
|
},
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "pod1",
|
|
Namespace: namespace,
|
|
Labels: map[string]string{"app": "test"},
|
|
},
|
|
Spec: corev1.PodSpec{Containers: []corev1.Container{
|
|
{
|
|
Name: "vela-core-1",
|
|
Image: "vela",
|
|
},
|
|
}},
|
|
}
|
|
podRaw, err := json.Marshal(pod)
|
|
Expect(err).Should(Succeed())
|
|
Expect(k8sClient.Create(context.Background(), pod)).Should(BeNil())
|
|
// create resourceTracker
|
|
rt := &v1beta1.ResourceTracker{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: fmt.Sprintf("%s-v1-%s", name, namespace),
|
|
Labels: map[string]string{
|
|
oam.LabelAppName: name,
|
|
oam.LabelAppNamespace: namespace,
|
|
},
|
|
Annotations: map[string]string{
|
|
oam.AnnotationPublishVersion: "v1",
|
|
},
|
|
},
|
|
Spec: v1beta1.ResourceTrackerSpec{
|
|
ManagedResources: []v1beta1.ManagedResource{
|
|
{
|
|
ClusterObjectReference: common2.ClusterObjectReference{
|
|
Cluster: "",
|
|
ObjectReference: corev1.ObjectReference{
|
|
APIVersion: "v1",
|
|
Kind: "Service",
|
|
Namespace: namespace,
|
|
Name: "service1",
|
|
},
|
|
},
|
|
OAMObjectReference: common2.OAMObjectReference{
|
|
Component: "service1",
|
|
},
|
|
Data: &runtime.RawExtension{Raw: svcRaw},
|
|
},
|
|
{
|
|
ClusterObjectReference: common2.ClusterObjectReference{
|
|
Cluster: "",
|
|
ObjectReference: corev1.ObjectReference{
|
|
APIVersion: "apps/v1",
|
|
Kind: "Deployment",
|
|
Namespace: namespace,
|
|
Name: "deploy1",
|
|
},
|
|
},
|
|
OAMObjectReference: common2.OAMObjectReference{
|
|
Component: "deploy1",
|
|
},
|
|
Data: &runtime.RawExtension{Raw: dplyRaw},
|
|
},
|
|
{
|
|
ClusterObjectReference: common2.ClusterObjectReference{
|
|
Cluster: "",
|
|
ObjectReference: corev1.ObjectReference{
|
|
APIVersion: "apps/v1",
|
|
Kind: "ReplicaSet",
|
|
Namespace: namespace,
|
|
Name: "rs1",
|
|
},
|
|
},
|
|
OAMObjectReference: common2.OAMObjectReference{
|
|
Component: "rs1",
|
|
},
|
|
Data: &runtime.RawExtension{Raw: rsRaw},
|
|
},
|
|
{
|
|
ClusterObjectReference: common2.ClusterObjectReference{
|
|
Cluster: "",
|
|
ObjectReference: corev1.ObjectReference{
|
|
APIVersion: "v1",
|
|
Kind: "Pod",
|
|
Namespace: namespace,
|
|
Name: "pod1",
|
|
},
|
|
},
|
|
OAMObjectReference: common2.OAMObjectReference{
|
|
Component: "pod1",
|
|
},
|
|
Data: &runtime.RawExtension{Raw: podRaw},
|
|
},
|
|
},
|
|
Type: v1beta1.ResourceTrackerTypeVersioned,
|
|
},
|
|
}
|
|
Expect(k8sClient.Create(context.Background(), rt)).Should(BeNil())
|
|
|
|
err = k8sClient.Create(context.Background(), &corev1.Namespace{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: types.DefaultKubeVelaNS,
|
|
},
|
|
})
|
|
Expect(err).Should(BeNil())
|
|
|
|
quantityLimitsCPU, _ := resource.ParseQuantity("10m")
|
|
quantityLimitsMemory, _ := resource.ParseQuantity("10Mi")
|
|
quantityRequestsCPU, _ := resource.ParseQuantity("10m")
|
|
quantityRequestsMemory, _ := resource.ParseQuantity("10Mi")
|
|
|
|
pod1 := &corev1.Pod{
|
|
ObjectMeta: metav1.ObjectMeta{Name: "vela-core", Namespace: "vela-system", Labels: map[string]string{"app.kubernetes.io/name": "vela-core"}},
|
|
Spec: corev1.PodSpec{Containers: []corev1.Container{
|
|
{
|
|
Name: "vela-core-1",
|
|
Image: "vela",
|
|
Resources: corev1.ResourceRequirements{
|
|
Requests: map[corev1.ResourceName]resource.Quantity{"memory": quantityRequestsMemory, "cpu": quantityRequestsCPU},
|
|
Limits: map[corev1.ResourceName]resource.Quantity{"memory": quantityLimitsMemory, "cpu": quantityLimitsCPU},
|
|
},
|
|
},
|
|
}},
|
|
}
|
|
Expect(k8sClient.Create(context.Background(), pod1)).Should(BeNil())
|
|
pod2 := &corev1.Pod{
|
|
ObjectMeta: metav1.ObjectMeta{Name: "vela-core-cluster-gateway", Namespace: "vela-system", Labels: map[string]string{"app.kubernetes.io/name": "vela-core-cluster-gateway"}},
|
|
Spec: corev1.PodSpec{Containers: []corev1.Container{
|
|
{
|
|
Name: "vela-core-cluster-gateway-1",
|
|
Image: "vela",
|
|
Resources: corev1.ResourceRequirements{
|
|
Requests: map[corev1.ResourceName]resource.Quantity{"memory": quantityRequestsMemory, "cpu": quantityRequestsCPU},
|
|
Limits: map[corev1.ResourceName]resource.Quantity{"memory": quantityLimitsMemory, "cpu": quantityLimitsCPU},
|
|
},
|
|
},
|
|
}},
|
|
}
|
|
Expect(k8sClient.Create(context.Background(), pod2)).Should(BeNil())
|
|
})
|
|
|
|
var _ = AfterSuite(func() {
|
|
By("tearing down the test environment")
|
|
err := testEnv.Stop()
|
|
Expect(err).ToNot(HaveOccurred())
|
|
})
|
|
|
|
func TestModel(t *testing.T) {
|
|
RegisterFailHandler(Fail)
|
|
RunSpecs(t, "Model Suite")
|
|
}
|