mirror of
https://github.com/kubevela/kubevela.git
synced 2026-05-19 15:56:54 +00:00
Some checks failed
CodeQL / Analyze (go) (push) Failing after 6m23s
Definition-Lint / definition-doc (push) Failing after 3m8s
E2E MultiCluster Test / detect-noop (push) Successful in 6s
E2E Test / detect-noop (push) Successful in 3s
Go / detect-noop (push) Successful in 2s
license / Check for unapproved licenses (push) Failing after 18s
Registry / publish-core-images (push) Failing after 1m4s
Unit-Test / detect-noop (push) Successful in 20s
Sync SDK / sync_sdk (push) Failing after 3m9s
Go / staticcheck (push) Successful in 6m17s
Go / check-diff (push) Failing after 19m4s
Go / check-core-image-build (push) Failing after 5m44s
Go / check-cli-image-build (push) Failing after 3m31s
Unit-Test / unit-tests (push) Failing after 13m54s
Go / lint (push) Failing after 1h53m27s
Scorecards supply-chain security / Scorecards analysis (push) Failing after 1m27s
E2E MultiCluster Test / e2e-multi-cluster-tests (v1.29) (push) Has been cancelled
E2E Test / e2e-tests (v1.29) (push) Has been cancelled
Go / check-windows (push) Has been cancelled
* chore: update k8s to 1.29 Signed-off-by: phantomnat <w.nattadej@gmail.com> * fix: unit test Signed-off-by: phantomnat <w.nattadej@gmail.com> * fix: lint Signed-off-by: phantomnat <w.nattadej@gmail.com> * fix: lint Signed-off-by: phantomnat <w.nattadej@gmail.com> * fix: e2e Signed-off-by: phantomnat <w.nattadej@gmail.com> * fix: lint and e2e test Signed-off-by: phantomnat <w.nattadej@gmail.com> * test(e2e): increase timeout Signed-off-by: phantomnat <w.nattadej@gmail.com> * fix e2e and scripts Signed-off-by: AiRanthem <zhongtianyun.zty@alibaba-inc.com> * make reviewable Signed-off-by: AiRanthem <zhongtianyun.zty@alibaba-inc.com> * rollback a unnecessary ut change Signed-off-by: AiRanthem <zhongtianyun.zty@alibaba-inc.com> * update go.mod to import merged workflow Signed-off-by: AiRanthem <zhongtianyun.zty@alibaba-inc.com> --------- Signed-off-by: phantomnat <w.nattadej@gmail.com> Signed-off-by: AiRanthem <zhongtianyun.zty@alibaba-inc.com> Co-authored-by: phantomnat <w.nattadej@gmail.com>
1922 lines
51 KiB
Go
1922 lines
51 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 query
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
. "github.com/onsi/ginkgo/v2"
|
|
. "github.com/onsi/gomega"
|
|
|
|
"github.com/fluxcd/helm-controller/api/v2beta1"
|
|
"github.com/fluxcd/source-controller/api/v1beta2"
|
|
"github.com/stretchr/testify/assert"
|
|
v12 "k8s.io/api/apps/v1"
|
|
batchv1 "k8s.io/api/batch/v1"
|
|
v1 "k8s.io/api/core/v1"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
|
"k8s.io/apimachinery/pkg/labels"
|
|
"k8s.io/apimachinery/pkg/runtime"
|
|
"k8s.io/apimachinery/pkg/runtime/serializer/yaml"
|
|
types2 "k8s.io/apimachinery/pkg/types"
|
|
"k8s.io/utils/ptr"
|
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
|
|
|
"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
|
|
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
|
|
types3 "github.com/oam-dev/kubevela/apis/types"
|
|
"github.com/oam-dev/kubevela/pkg/oam"
|
|
"github.com/oam-dev/kubevela/pkg/oam/util"
|
|
"github.com/oam-dev/kubevela/pkg/utils/types"
|
|
oamprovidertypes "github.com/oam-dev/kubevela/pkg/workflow/providers/types"
|
|
)
|
|
|
|
func TestPodStatus(t *testing.T) {
|
|
succeedPod := v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: "default", Name: "Pod"}, Status: v1.PodStatus{
|
|
Phase: v1.PodSucceeded,
|
|
}}
|
|
|
|
runningReadyPod := v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: "default", Name: "Pod"},
|
|
Spec: v1.PodSpec{
|
|
RestartPolicy: v1.RestartPolicyAlways,
|
|
},
|
|
Status: v1.PodStatus{
|
|
Conditions: []v1.PodCondition{
|
|
{
|
|
Type: v1.PodReady,
|
|
Status: v1.ConditionTrue,
|
|
},
|
|
},
|
|
Phase: v1.PodRunning,
|
|
}}
|
|
|
|
runningUnHealthyPod := v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: "default", Name: "Pod"},
|
|
Spec: v1.PodSpec{
|
|
RestartPolicy: v1.RestartPolicyAlways,
|
|
},
|
|
Status: v1.PodStatus{
|
|
ContainerStatuses: []v1.ContainerStatus{
|
|
{
|
|
LastTerminationState: v1.ContainerState{
|
|
Terminated: &v1.ContainerStateTerminated{
|
|
ExitCode: 127,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Phase: v1.PodRunning,
|
|
}}
|
|
|
|
runningProgressingPod := v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: "default", Name: "Pod"},
|
|
Spec: v1.PodSpec{
|
|
RestartPolicy: v1.RestartPolicyAlways,
|
|
},
|
|
Status: v1.PodStatus{
|
|
Phase: v1.PodRunning,
|
|
Reason: "ContainerCreating",
|
|
}}
|
|
|
|
restartNeverPod := v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: "default", Name: "Pod"},
|
|
Spec: v1.PodSpec{
|
|
RestartPolicy: v1.RestartPolicyNever,
|
|
},
|
|
Status: v1.PodStatus{
|
|
Phase: v1.PodRunning,
|
|
}}
|
|
|
|
pendingPod := v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: "default", Name: "Pod"},
|
|
Spec: v1.PodSpec{
|
|
RestartPolicy: v1.RestartPolicyNever,
|
|
}, Status: v1.PodStatus{Phase: v1.PodPending},
|
|
}
|
|
|
|
failedWithMessagePod := v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: "default", Name: "Pod"},
|
|
Status: v1.PodStatus{Phase: v1.PodFailed, Message: "some message"},
|
|
}
|
|
|
|
failedWithOOMKillPod := v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: "default", Name: "Pod"},
|
|
Status: v1.PodStatus{Phase: v1.PodFailed, ContainerStatuses: []v1.ContainerStatus{
|
|
{
|
|
State: v1.ContainerState{
|
|
Terminated: &v1.ContainerStateTerminated{
|
|
Reason: "OOMKilled",
|
|
},
|
|
},
|
|
},
|
|
}},
|
|
}
|
|
|
|
failedWithExistCodePod := v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: "default", Name: "Pod"},
|
|
Status: v1.PodStatus{Phase: v1.PodFailed, ContainerStatuses: []v1.ContainerStatus{
|
|
{
|
|
Name: "nginx",
|
|
State: v1.ContainerState{
|
|
Terminated: &v1.ContainerStateTerminated{
|
|
ExitCode: 189,
|
|
},
|
|
},
|
|
},
|
|
}},
|
|
}
|
|
|
|
testCases := map[string]struct {
|
|
intput v1.Pod
|
|
result types.HealthStatus
|
|
}{
|
|
"succeedPod": {
|
|
intput: succeedPod,
|
|
result: types.HealthStatus{Status: types.HealthStatusHealthy},
|
|
},
|
|
"runningReadyPod": {
|
|
intput: runningReadyPod,
|
|
result: types.HealthStatus{Status: types.HealthStatusHealthy, Reason: "all containers are ready"},
|
|
},
|
|
"runningUnHealthyPod": {
|
|
intput: runningUnHealthyPod,
|
|
result: types.HealthStatus{Status: types.HealthStatusUnHealthy},
|
|
},
|
|
"runningProgressingPod": {
|
|
intput: runningProgressingPod,
|
|
result: types.HealthStatus{Status: types.HealthStatusProgressing, Reason: "ContainerCreating"},
|
|
},
|
|
"restartNeverPod": {
|
|
intput: restartNeverPod,
|
|
result: types.HealthStatus{Status: types.HealthStatusProgressing},
|
|
},
|
|
"pendingPod": {
|
|
intput: pendingPod,
|
|
result: types.HealthStatus{Status: types.HealthStatusProgressing},
|
|
},
|
|
"failedWithMessagePod": {
|
|
intput: failedWithMessagePod,
|
|
result: types.HealthStatus{Status: types.HealthStatusUnHealthy, Message: "some message"},
|
|
},
|
|
"failedWithOOMKillPod": {
|
|
intput: failedWithOOMKillPod,
|
|
result: types.HealthStatus{Status: types.HealthStatusUnHealthy, Message: "OOMKilled"},
|
|
},
|
|
"failedWithExistCodePod": {
|
|
intput: failedWithExistCodePod,
|
|
result: types.HealthStatus{Status: types.HealthStatusUnHealthy, Message: "container \"nginx\" failed with exit code 189"},
|
|
},
|
|
}
|
|
for _, s := range testCases {
|
|
pod := s.intput.DeepCopy()
|
|
p, err := runtime.DefaultUnstructuredConverter.ToUnstructured(pod)
|
|
assert.NoError(t, err)
|
|
res, err := checkPodStatus(unstructured.Unstructured{Object: p})
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, res)
|
|
assert.Equal(t, *res, s.result)
|
|
}
|
|
}
|
|
|
|
func TestService2EndpointOption(t *testing.T) {
|
|
labels := map[string]string{
|
|
"service-name": "test",
|
|
"uid": "test-uid",
|
|
}
|
|
u := unstructured.Unstructured{}
|
|
u.SetAPIVersion("v1")
|
|
u.SetKind("Service")
|
|
u.SetLabels(labels)
|
|
l, err := service2EndpointListOption(u)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "service-name=test,uid=test-uid", l.LabelSelector.String())
|
|
}
|
|
|
|
func TestConvertLabel2Selector(t *testing.T) {
|
|
cronJob1 := `
|
|
apiVersion: batch/v1
|
|
kind: CronJob
|
|
metadata:
|
|
name: cronjob1
|
|
labels:
|
|
app: cronjob1
|
|
spec:
|
|
schedule: "* * * * *"
|
|
jobTemplate:
|
|
metadata:
|
|
labels:
|
|
app: cronJob1
|
|
spec:
|
|
template:
|
|
spec:
|
|
containers:
|
|
- name: cronjob
|
|
image: busybox
|
|
command: ["/bin/sh","-c","date"]
|
|
restartPolicy: Never
|
|
`
|
|
obj := unstructured.Unstructured{}
|
|
dec := yaml.NewDecodingSerializer(unstructured.UnstructuredJSONScheme)
|
|
_, _, err := dec.Decode([]byte(cronJob1), nil, &obj)
|
|
assert.NoError(t, err)
|
|
workload1 := WorkloadUnstructured{obj}
|
|
selector1, err := workload1.convertLabel2Selector("not", "exist")
|
|
assert.Equal(t, selector1, labels.Everything())
|
|
assert.NoError(t, err)
|
|
|
|
selector2, err := workload1.convertLabel2Selector()
|
|
assert.Equal(t, selector2, nil)
|
|
assert.Error(t, err)
|
|
|
|
_, _, err = dec.Decode([]byte(cronJob1), nil, &obj)
|
|
assert.NoError(t, err)
|
|
workload2 := WorkloadUnstructured{obj}
|
|
selector3, err := workload2.convertLabel2Selector("apiVersion")
|
|
assert.Equal(t, selector3, labels.Everything())
|
|
assert.NoError(t, err)
|
|
|
|
_, _, err = dec.Decode([]byte(cronJob1), nil, &obj)
|
|
assert.NoError(t, err)
|
|
workload3 := WorkloadUnstructured{obj}
|
|
selector4, err := workload3.convertLabel2Selector("spec", "jobTemplate", "metadata", "labels")
|
|
assert.Equal(t, selector4.String(), "app=cronJob1")
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
func TestCronJobLabelListOption(t *testing.T) {
|
|
cronJob := `
|
|
apiVersion: batch/v1
|
|
kind: CronJob
|
|
metadata:
|
|
name: cronjob1
|
|
labels:
|
|
app: cronjob1
|
|
spec:
|
|
schedule: "* * * * *"
|
|
jobTemplate:
|
|
metadata:
|
|
labels:
|
|
app: cronJob1
|
|
spec:
|
|
template:
|
|
spec:
|
|
containers:
|
|
- name: cronjob
|
|
image: busybox
|
|
command: ["/bin/sh","-c","date"]
|
|
restartPolicy: Never
|
|
`
|
|
|
|
// convert yaml to unstructured
|
|
obj := unstructured.Unstructured{}
|
|
dec := yaml.NewDecodingSerializer(unstructured.UnstructuredJSONScheme)
|
|
_, _, err := dec.Decode([]byte(cronJob), nil, &obj)
|
|
assert.NoError(t, err)
|
|
l, err := cronJobLabelListOption(obj)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "app=cronJob1", l.LabelSelector.String())
|
|
}
|
|
|
|
func TestServiceStatus(t *testing.T) {
|
|
lbHealthSvc := v1.Service{Spec: v1.ServiceSpec{Type: v1.ServiceTypeLoadBalancer}, Status: v1.ServiceStatus{
|
|
LoadBalancer: v1.LoadBalancerStatus{
|
|
Ingress: []v1.LoadBalancerIngress{
|
|
{
|
|
IP: "198.1.1.1",
|
|
},
|
|
},
|
|
},
|
|
}}
|
|
lbProgressingSvc := v1.Service{Spec: v1.ServiceSpec{Type: v1.ServiceTypeLoadBalancer}, Status: v1.ServiceStatus{}}
|
|
testCases := map[string]struct {
|
|
input v1.Service
|
|
res types.HealthStatus
|
|
}{
|
|
"health": {
|
|
input: lbHealthSvc,
|
|
res: types.HealthStatus{Status: types.HealthStatusHealthy},
|
|
},
|
|
"progressing": {
|
|
input: lbProgressingSvc,
|
|
res: types.HealthStatus{Status: types.HealthStatusProgressing},
|
|
},
|
|
}
|
|
for _, s := range testCases {
|
|
svc := s.input.DeepCopy()
|
|
u, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&svc)
|
|
assert.NoError(t, err)
|
|
res, err := checkServiceStatus(unstructured.Unstructured{Object: u})
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, res)
|
|
assert.Equal(t, s.res, *res)
|
|
}
|
|
}
|
|
|
|
func TestPVCStatus(t *testing.T) {
|
|
heathyPVC := v1.PersistentVolumeClaim{Status: v1.PersistentVolumeClaimStatus{Phase: v1.ClaimBound}}
|
|
unHeathyPVC := v1.PersistentVolumeClaim{Status: v1.PersistentVolumeClaimStatus{Phase: v1.ClaimLost}}
|
|
progressingPVC := v1.PersistentVolumeClaim{Status: v1.PersistentVolumeClaimStatus{Phase: v1.ClaimPending}}
|
|
heathyUnkown := v1.PersistentVolumeClaim{Status: v1.PersistentVolumeClaimStatus{}}
|
|
testCases := map[string]struct {
|
|
input v1.PersistentVolumeClaim
|
|
res types.HealthStatus
|
|
}{
|
|
"health": {
|
|
input: heathyPVC,
|
|
res: types.HealthStatus{Status: types.HealthStatusHealthy},
|
|
},
|
|
"progressing": {
|
|
input: progressingPVC,
|
|
res: types.HealthStatus{Status: types.HealthStatusProgressing},
|
|
},
|
|
"unHealthy": {
|
|
input: unHeathyPVC,
|
|
res: types.HealthStatus{Status: types.HealthStatusUnHealthy},
|
|
},
|
|
"unknown": {
|
|
input: heathyUnkown,
|
|
res: types.HealthStatus{Status: types.HealthStatusUnKnown},
|
|
},
|
|
}
|
|
for _, s := range testCases {
|
|
pvc := s.input.DeepCopy()
|
|
u, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&pvc)
|
|
assert.NoError(t, err)
|
|
res, err := checkPVCHealthStatus(unstructured.Unstructured{Object: u})
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, res)
|
|
assert.Equal(t, s.res, *res)
|
|
}
|
|
}
|
|
|
|
func TestGetReplicaSetCondition(t *testing.T) {
|
|
rs := v12.ReplicaSet{Status: v12.ReplicaSetStatus{
|
|
Conditions: []v12.ReplicaSetCondition{{
|
|
Type: v12.ReplicaSetReplicaFailure,
|
|
}},
|
|
}}
|
|
c := getAppsv1ReplicaSetCondition(rs.Status, v12.ReplicaSetReplicaFailure)
|
|
assert.NotNil(t, c)
|
|
}
|
|
|
|
func TestReplicaSetStatus(t *testing.T) {
|
|
unhealthyReplicaSet := v12.ReplicaSet{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Generation: 2,
|
|
},
|
|
Status: v12.ReplicaSetStatus{ObservedGeneration: 2,
|
|
Conditions: []v12.ReplicaSetCondition{{
|
|
Type: v12.ReplicaSetReplicaFailure,
|
|
Status: v1.ConditionTrue,
|
|
}}},
|
|
}
|
|
progressingPodReplicaSet := v12.ReplicaSet{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Generation: 2,
|
|
},
|
|
Spec: v12.ReplicaSetSpec{Replicas: ptr.To(int32(3))},
|
|
Status: v12.ReplicaSetStatus{
|
|
ObservedGeneration: 2,
|
|
ReadyReplicas: 2,
|
|
AvailableReplicas: 2,
|
|
},
|
|
}
|
|
progressingRollingReplicaSet := v12.ReplicaSet{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Generation: 2,
|
|
},
|
|
Spec: v12.ReplicaSetSpec{Replicas: ptr.To(int32(3))},
|
|
Status: v12.ReplicaSetStatus{
|
|
ObservedGeneration: 1,
|
|
},
|
|
}
|
|
testCases := map[string]struct {
|
|
input v12.ReplicaSet
|
|
res types.HealthStatus
|
|
}{
|
|
"unHealth": {
|
|
input: unhealthyReplicaSet,
|
|
res: types.HealthStatus{Status: types.HealthStatusUnHealthy},
|
|
},
|
|
"progressing": {
|
|
input: progressingPodReplicaSet,
|
|
res: types.HealthStatus{Status: types.HealthStatusProgressing, Message: "Waiting for rollout to finish: 2 out of 3 new replicas are available..."},
|
|
},
|
|
"rolling": {
|
|
input: progressingRollingReplicaSet,
|
|
res: types.HealthStatus{Status: types.HealthStatusProgressing, Message: "Waiting for rollout to finish: observed replica set generation less then desired generation"},
|
|
},
|
|
}
|
|
for _, s := range testCases {
|
|
rs := s.input.DeepCopy()
|
|
u, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&rs)
|
|
assert.NoError(t, err)
|
|
res, err := checkReplicaSetStatus(unstructured.Unstructured{Object: u})
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, res)
|
|
assert.Equal(t, s.res, *res)
|
|
}
|
|
}
|
|
|
|
func TestHelmResourceStatus(t *testing.T) {
|
|
tm := metav1.TypeMeta{APIVersion: "helm.toolkit.fluxcd.io/v2beta1", Kind: "HelmRelease"}
|
|
healthHr := v2beta1.HelmRelease{TypeMeta: tm, Status: v2beta1.HelmReleaseStatus{Conditions: []metav1.Condition{
|
|
{
|
|
Type: "Ready",
|
|
Status: metav1.ConditionTrue,
|
|
},
|
|
}}}
|
|
unHealthyHr := v2beta1.HelmRelease{TypeMeta: tm, Status: v2beta1.HelmReleaseStatus{Conditions: []metav1.Condition{
|
|
{
|
|
Type: "Ready",
|
|
Status: metav1.ConditionFalse,
|
|
Message: "some reason",
|
|
},
|
|
}}}
|
|
unKnowHealthyHr := v2beta1.HelmRelease{TypeMeta: tm, Status: v2beta1.HelmReleaseStatus{Conditions: []metav1.Condition{
|
|
{
|
|
Type: "OtherType",
|
|
Status: metav1.ConditionFalse,
|
|
},
|
|
}}}
|
|
testCases := map[string]struct {
|
|
hr v2beta1.HelmRelease
|
|
res *types.HealthStatus
|
|
}{
|
|
"healthHr": {
|
|
hr: healthHr,
|
|
res: &types.HealthStatus{Status: types.HealthStatusHealthy},
|
|
},
|
|
"unHealthyHr": {
|
|
hr: unHealthyHr,
|
|
res: &types.HealthStatus{Status: types.HealthStatusUnHealthy, Message: "some reason"},
|
|
},
|
|
"unKnowHealthyHr": {
|
|
hr: unKnowHealthyHr,
|
|
res: &types.HealthStatus{Status: types.HealthStatusUnKnown},
|
|
},
|
|
}
|
|
for _, s := range testCases {
|
|
obj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(s.hr.DeepCopy())
|
|
assert.NoError(t, err)
|
|
res, err := CheckResourceStatus(unstructured.Unstructured{Object: obj})
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, res, s.res)
|
|
}
|
|
}
|
|
|
|
func TestHelmRepoResourceStatus(t *testing.T) {
|
|
tm := metav1.TypeMeta{APIVersion: "source.toolkit.fluxcd.io/v1beta2", Kind: "HelmRepository"}
|
|
healthHr := v1beta2.HelmRepository{TypeMeta: tm, Status: v1beta2.HelmRepositoryStatus{Conditions: []metav1.Condition{
|
|
{
|
|
Type: "Ready",
|
|
Status: metav1.ConditionTrue,
|
|
},
|
|
}}}
|
|
unHealthyHr := v1beta2.HelmRepository{TypeMeta: tm, Status: v1beta2.HelmRepositoryStatus{Conditions: []metav1.Condition{
|
|
{
|
|
Type: "Ready",
|
|
Status: metav1.ConditionFalse,
|
|
Message: "some reason",
|
|
},
|
|
}}}
|
|
unKnowHealthyHr := v1beta2.HelmRepository{TypeMeta: tm, Status: v1beta2.HelmRepositoryStatus{Conditions: []metav1.Condition{
|
|
{
|
|
Type: "OtherType",
|
|
Status: metav1.ConditionFalse,
|
|
},
|
|
}}}
|
|
testCases := map[string]struct {
|
|
hr v1beta2.HelmRepository
|
|
res *types.HealthStatus
|
|
}{
|
|
"healthHr": {
|
|
hr: healthHr,
|
|
res: &types.HealthStatus{Status: types.HealthStatusHealthy},
|
|
},
|
|
"unHealthyHr": {
|
|
hr: unHealthyHr,
|
|
res: &types.HealthStatus{Status: types.HealthStatusUnHealthy, Message: "some reason"},
|
|
},
|
|
"unKnowHealthyHr": {
|
|
hr: unKnowHealthyHr,
|
|
res: &types.HealthStatus{Status: types.HealthStatusUnKnown},
|
|
},
|
|
}
|
|
for _, s := range testCases {
|
|
obj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(s.hr.DeepCopy())
|
|
assert.NoError(t, err)
|
|
res, err := CheckResourceStatus(unstructured.Unstructured{Object: obj})
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, res, s.res)
|
|
}
|
|
}
|
|
|
|
func TestGenListOption(t *testing.T) {
|
|
resLabel, err := metav1.LabelSelectorAsSelector(&metav1.LabelSelector{MatchLabels: map[string]string{"testKey": "testVal"}})
|
|
assert.NoError(t, err)
|
|
listOption := client.ListOptions{LabelSelector: resLabel, Namespace: "test"}
|
|
|
|
deploy := v12.Deployment{ObjectMeta: metav1.ObjectMeta{Namespace: "test"}, Spec: v12.DeploymentSpec{Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"testKey": "testVal"}}}}
|
|
du, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&deploy)
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, du)
|
|
dls, err := defaultWorkloadLabelListOption(unstructured.Unstructured{Object: du})
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, listOption, dls)
|
|
|
|
rs := v12.ReplicaSet{ObjectMeta: metav1.ObjectMeta{Namespace: "test"}, Spec: v12.ReplicaSetSpec{Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"testKey": "testVal"}}}}
|
|
rsu, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&rs)
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, du)
|
|
rsls, err := defaultWorkloadLabelListOption(unstructured.Unstructured{Object: rsu})
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, listOption, rsls)
|
|
|
|
sts := v12.StatefulSet{ObjectMeta: metav1.ObjectMeta{Namespace: "test"}, Spec: v12.StatefulSetSpec{Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"testKey": "testVal"}}}}
|
|
stsu, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&sts)
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, stsu)
|
|
stsls, err := defaultWorkloadLabelListOption(unstructured.Unstructured{Object: stsu})
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, listOption, stsls)
|
|
|
|
helmRelease := unstructured.Unstructured{}
|
|
helmRelease.SetName("test-helm")
|
|
helmRelease.SetNamespace("test-ns")
|
|
hrll, err := metav1.LabelSelectorAsSelector(&metav1.LabelSelector{MatchLabels: map[string]string{"helm.toolkit.fluxcd.io/name": "test-helm", "helm.toolkit.fluxcd.io/namespace": "test-ns"}})
|
|
assert.NoError(t, err)
|
|
|
|
hrls, err := helmRelease2AnyListOption(helmRelease)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, hrls, client.ListOptions{LabelSelector: hrll})
|
|
}
|
|
|
|
func TestPodAdditionalInfo(t *testing.T) {
|
|
typeMeta := metav1.TypeMeta{APIVersion: "v1", Kind: "Pod"}
|
|
|
|
type testCase struct {
|
|
pod v1.Pod
|
|
res map[string]interface{}
|
|
}
|
|
|
|
case1 := testCase{
|
|
pod: v1.Pod{TypeMeta: typeMeta,
|
|
ObjectMeta: metav1.ObjectMeta{DeletionTimestamp: &metav1.Time{Time: time.Now()}},
|
|
Status: v1.PodStatus{
|
|
InitContainerStatuses: []v1.ContainerStatus{
|
|
{
|
|
State: v1.ContainerState{
|
|
Terminated: &v1.ContainerStateTerminated{
|
|
ExitCode: 0,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Reason: "NodeLost"},
|
|
},
|
|
res: map[string]interface{}{
|
|
"Ready": "0/0",
|
|
"Status": "Unknown",
|
|
"Restarts": 0,
|
|
"Age": "<unknown>",
|
|
},
|
|
}
|
|
|
|
case2 := testCase{
|
|
pod: v1.Pod{TypeMeta: typeMeta,
|
|
Status: v1.PodStatus{
|
|
InitContainerStatuses: []v1.ContainerStatus{
|
|
{
|
|
State: v1.ContainerState{
|
|
Terminated: &v1.ContainerStateTerminated{
|
|
ExitCode: 127,
|
|
},
|
|
},
|
|
},
|
|
}},
|
|
},
|
|
res: map[string]interface{}{
|
|
"Ready": "0/0",
|
|
"Status": "Init:ExitCode:127",
|
|
"Restarts": 0,
|
|
"Age": "<unknown>",
|
|
},
|
|
}
|
|
|
|
case3 := testCase{
|
|
pod: v1.Pod{TypeMeta: typeMeta,
|
|
Status: v1.PodStatus{
|
|
InitContainerStatuses: []v1.ContainerStatus{
|
|
{
|
|
State: v1.ContainerState{
|
|
Terminated: &v1.ContainerStateTerminated{
|
|
ExitCode: 127,
|
|
Signal: 32,
|
|
},
|
|
},
|
|
},
|
|
}},
|
|
},
|
|
res: map[string]interface{}{
|
|
"Ready": "0/0",
|
|
"Status": "Init:Signal:32",
|
|
"Restarts": 0,
|
|
"Age": "<unknown>",
|
|
},
|
|
}
|
|
|
|
case4 := testCase{
|
|
pod: v1.Pod{TypeMeta: typeMeta,
|
|
Status: v1.PodStatus{
|
|
InitContainerStatuses: []v1.ContainerStatus{
|
|
{
|
|
State: v1.ContainerState{
|
|
Terminated: &v1.ContainerStateTerminated{
|
|
Reason: "OOMKill",
|
|
ExitCode: 127,
|
|
},
|
|
},
|
|
},
|
|
}},
|
|
},
|
|
res: map[string]interface{}{
|
|
"Ready": "0/0",
|
|
"Status": "Init:OOMKill",
|
|
"Restarts": 0,
|
|
"Age": "<unknown>",
|
|
},
|
|
}
|
|
|
|
case5 := testCase{
|
|
pod: v1.Pod{TypeMeta: typeMeta,
|
|
Status: v1.PodStatus{
|
|
InitContainerStatuses: []v1.ContainerStatus{
|
|
{
|
|
State: v1.ContainerState{
|
|
Terminated: &v1.ContainerStateTerminated{
|
|
Reason: "OOMKill",
|
|
ExitCode: 127,
|
|
},
|
|
},
|
|
},
|
|
}},
|
|
},
|
|
res: map[string]interface{}{
|
|
"Ready": "0/0",
|
|
"Status": "Init:OOMKill",
|
|
"Restarts": 0,
|
|
"Age": "<unknown>",
|
|
},
|
|
}
|
|
|
|
case6 := testCase{
|
|
pod: v1.Pod{TypeMeta: typeMeta,
|
|
Status: v1.PodStatus{
|
|
InitContainerStatuses: []v1.ContainerStatus{
|
|
{
|
|
State: v1.ContainerState{
|
|
Waiting: &v1.ContainerStateWaiting{
|
|
Reason: "ContainerCreating",
|
|
},
|
|
},
|
|
},
|
|
}},
|
|
},
|
|
res: map[string]interface{}{
|
|
"Ready": "0/0",
|
|
"Status": "Init:ContainerCreating",
|
|
"Restarts": 0,
|
|
"Age": "<unknown>",
|
|
},
|
|
}
|
|
|
|
case7 := testCase{
|
|
pod: v1.Pod{TypeMeta: typeMeta,
|
|
Spec: v1.PodSpec{
|
|
InitContainers: []v1.Container{
|
|
{Name: "test"},
|
|
}},
|
|
Status: v1.PodStatus{
|
|
InitContainerStatuses: []v1.ContainerStatus{
|
|
{
|
|
State: v1.ContainerState{
|
|
Waiting: &v1.ContainerStateWaiting{},
|
|
},
|
|
},
|
|
}},
|
|
},
|
|
res: map[string]interface{}{
|
|
"Ready": "0/0",
|
|
"Status": "Init:0/1",
|
|
"Restarts": 0,
|
|
"Age": "<unknown>",
|
|
},
|
|
}
|
|
|
|
case8 := testCase{
|
|
pod: v1.Pod{TypeMeta: typeMeta,
|
|
Status: v1.PodStatus{
|
|
ContainerStatuses: []v1.ContainerStatus{
|
|
{
|
|
State: v1.ContainerState{
|
|
Waiting: &v1.ContainerStateWaiting{
|
|
Reason: "ContainerCreating",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
res: map[string]interface{}{
|
|
"Ready": "0/0",
|
|
"Status": "ContainerCreating",
|
|
"Restarts": 0,
|
|
"Age": "<unknown>",
|
|
},
|
|
}
|
|
|
|
case9 := testCase{
|
|
pod: v1.Pod{TypeMeta: typeMeta,
|
|
Status: v1.PodStatus{
|
|
ContainerStatuses: []v1.ContainerStatus{
|
|
{
|
|
State: v1.ContainerState{
|
|
Terminated: &v1.ContainerStateTerminated{
|
|
Reason: "OOMKilled",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
res: map[string]interface{}{
|
|
"Ready": "0/0",
|
|
"Status": "OOMKilled",
|
|
"Restarts": 0,
|
|
"Age": "<unknown>",
|
|
},
|
|
}
|
|
|
|
case10 := testCase{
|
|
pod: v1.Pod{TypeMeta: typeMeta,
|
|
Status: v1.PodStatus{
|
|
ContainerStatuses: []v1.ContainerStatus{
|
|
{
|
|
State: v1.ContainerState{
|
|
Terminated: &v1.ContainerStateTerminated{
|
|
Signal: 2,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
res: map[string]interface{}{
|
|
"Ready": "0/0",
|
|
"Status": "Signal:2",
|
|
"Restarts": 0,
|
|
"Age": "<unknown>",
|
|
},
|
|
}
|
|
|
|
case11 := testCase{
|
|
pod: v1.Pod{TypeMeta: typeMeta,
|
|
Status: v1.PodStatus{
|
|
ContainerStatuses: []v1.ContainerStatus{
|
|
{
|
|
State: v1.ContainerState{
|
|
Terminated: &v1.ContainerStateTerminated{
|
|
ExitCode: 127,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
res: map[string]interface{}{
|
|
"Ready": "0/0",
|
|
"Status": "ExitCode:127",
|
|
"Restarts": 0,
|
|
"Age": "<unknown>",
|
|
},
|
|
}
|
|
|
|
case12 := testCase{
|
|
pod: v1.Pod{TypeMeta: typeMeta,
|
|
Spec: v1.PodSpec{
|
|
Containers: []v1.Container{{
|
|
Name: "nginx",
|
|
}},
|
|
},
|
|
Status: v1.PodStatus{
|
|
ContainerStatuses: []v1.ContainerStatus{
|
|
{
|
|
State: v1.ContainerState{
|
|
Running: &v1.ContainerStateRunning{
|
|
StartedAt: metav1.Now(),
|
|
},
|
|
},
|
|
Ready: true,
|
|
},
|
|
},
|
|
Phase: "Running",
|
|
},
|
|
},
|
|
res: map[string]interface{}{
|
|
"Ready": "1/1",
|
|
"Status": "Running",
|
|
"Restarts": 0,
|
|
"Age": "<unknown>",
|
|
},
|
|
}
|
|
|
|
case13 := testCase{
|
|
pod: v1.Pod{TypeMeta: typeMeta,
|
|
Spec: v1.PodSpec{
|
|
Containers: []v1.Container{{
|
|
Name: "nginx",
|
|
}},
|
|
},
|
|
Status: v1.PodStatus{
|
|
ContainerStatuses: []v1.ContainerStatus{
|
|
{
|
|
State: v1.ContainerState{
|
|
Running: &v1.ContainerStateRunning{
|
|
StartedAt: metav1.Now(),
|
|
},
|
|
},
|
|
Ready: true,
|
|
},
|
|
},
|
|
Phase: "Completed",
|
|
Conditions: []v1.PodCondition{
|
|
{
|
|
Type: v1.PodReady,
|
|
Status: v1.ConditionTrue,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
res: map[string]interface{}{
|
|
"Ready": "1/1",
|
|
"Status": "Running",
|
|
"Restarts": 0,
|
|
"Age": "<unknown>",
|
|
},
|
|
}
|
|
|
|
case14 := testCase{
|
|
pod: v1.Pod{TypeMeta: typeMeta,
|
|
Spec: v1.PodSpec{
|
|
Containers: []v1.Container{{
|
|
Name: "nginx",
|
|
}},
|
|
},
|
|
Status: v1.PodStatus{
|
|
ContainerStatuses: []v1.ContainerStatus{
|
|
{
|
|
State: v1.ContainerState{
|
|
Running: &v1.ContainerStateRunning{
|
|
StartedAt: metav1.Now(),
|
|
},
|
|
},
|
|
Ready: true,
|
|
},
|
|
},
|
|
Phase: "Completed",
|
|
},
|
|
},
|
|
res: map[string]interface{}{
|
|
"Ready": "1/1",
|
|
"Status": "NotReady",
|
|
"Restarts": 0,
|
|
"Age": "<unknown>",
|
|
},
|
|
}
|
|
|
|
case15 := testCase{
|
|
pod: v1.Pod{TypeMeta: typeMeta,
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
DeletionTimestamp: &metav1.Time{Time: time.Now()},
|
|
},
|
|
},
|
|
res: map[string]interface{}{
|
|
"Ready": "0/0",
|
|
"Status": "Terminating",
|
|
"Restarts": 0,
|
|
"Age": "<unknown>",
|
|
},
|
|
}
|
|
|
|
testCases := map[string]testCase{
|
|
"pod1": case1,
|
|
"pod2": case2,
|
|
"pod3": case3,
|
|
"pod4": case4,
|
|
"pod5": case5,
|
|
"pod6": case6,
|
|
"pod7": case7,
|
|
"pod8": case8,
|
|
"pod9": case9,
|
|
"pod10": case10,
|
|
"pod11": case11,
|
|
"pod12": case12,
|
|
"pod13": case13,
|
|
"pod14": case14,
|
|
"pod15": case15,
|
|
}
|
|
|
|
for _, t2 := range testCases {
|
|
u, err := runtime.DefaultUnstructuredConverter.ToUnstructured(t2.pod.DeepCopy())
|
|
assert.NoError(t, err)
|
|
res, err := additionalInfo(unstructured.Unstructured{Object: u})
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, t2.res, res)
|
|
}
|
|
}
|
|
|
|
func TestDeploymentAdditionalInfo(t *testing.T) {
|
|
typeMeta := metav1.TypeMeta{APIVersion: "apps/v1", Kind: "Deployment"}
|
|
|
|
type testCase struct {
|
|
Deployment v12.Deployment
|
|
res map[string]interface{}
|
|
}
|
|
|
|
case1 := testCase{
|
|
Deployment: v12.Deployment{
|
|
TypeMeta: typeMeta,
|
|
Spec: v12.DeploymentSpec{Replicas: ptr.To(int32(1))},
|
|
Status: v12.DeploymentStatus{
|
|
ReadyReplicas: 1,
|
|
UpdatedReplicas: 1,
|
|
AvailableReplicas: 1,
|
|
},
|
|
},
|
|
res: map[string]interface{}{
|
|
"Ready": "1/1",
|
|
"Update": int32(1),
|
|
"Available": int32(1),
|
|
"Age": "<unknown>",
|
|
},
|
|
}
|
|
|
|
testCases := map[string]testCase{
|
|
"deployment1": case1,
|
|
}
|
|
|
|
for _, t2 := range testCases {
|
|
u, err := runtime.DefaultUnstructuredConverter.ToUnstructured(t2.Deployment.DeepCopy())
|
|
assert.NoError(t, err)
|
|
res, err := additionalInfo(unstructured.Unstructured{Object: u})
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, t2.res, res)
|
|
}
|
|
}
|
|
|
|
func TestStatefulSetAdditionalInfo(t *testing.T) {
|
|
typeMeta := metav1.TypeMeta{APIVersion: "apps/v1", Kind: "StatefulSet"}
|
|
|
|
type testCase struct {
|
|
StatefulSet v12.StatefulSet
|
|
res map[string]interface{}
|
|
}
|
|
|
|
case1 := testCase{
|
|
StatefulSet: v12.StatefulSet{
|
|
TypeMeta: typeMeta,
|
|
Spec: v12.StatefulSetSpec{Replicas: ptr.To(int32(1))},
|
|
Status: v12.StatefulSetStatus{
|
|
ReadyReplicas: 1,
|
|
},
|
|
},
|
|
res: map[string]interface{}{
|
|
"Ready": "1/1",
|
|
"Age": "<unknown>",
|
|
},
|
|
}
|
|
|
|
testCases := map[string]testCase{
|
|
"statefulSet1": case1,
|
|
}
|
|
|
|
for _, t2 := range testCases {
|
|
u, err := runtime.DefaultUnstructuredConverter.ToUnstructured(t2.StatefulSet.DeepCopy())
|
|
assert.NoError(t, err)
|
|
res, err := additionalInfo(unstructured.Unstructured{Object: u})
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, t2.res, res)
|
|
}
|
|
}
|
|
|
|
func TestSvcAdditionalInfo(t *testing.T) {
|
|
typeMeta := metav1.TypeMeta{APIVersion: "v1", Kind: "Service"}
|
|
|
|
type testCase struct {
|
|
svc v1.Service
|
|
res map[string]interface{}
|
|
}
|
|
|
|
case1 := testCase{
|
|
svc: v1.Service{TypeMeta: typeMeta, Spec: v1.ServiceSpec{
|
|
Type: v1.ServiceTypeLoadBalancer,
|
|
},
|
|
Status: v1.ServiceStatus{LoadBalancer: v1.LoadBalancerStatus{Ingress: []v1.LoadBalancerIngress{{IP: "145.2.2.1"}}}}},
|
|
res: map[string]interface{}{
|
|
"EIP": "145.2.2.1",
|
|
},
|
|
}
|
|
|
|
case2 := testCase{
|
|
svc: v1.Service{TypeMeta: typeMeta, Spec: v1.ServiceSpec{
|
|
Type: v1.ServiceTypeLoadBalancer,
|
|
},
|
|
Status: v1.ServiceStatus{}},
|
|
res: map[string]interface{}{
|
|
"EIP": "pending",
|
|
},
|
|
}
|
|
|
|
testCases := map[string]testCase{
|
|
"svc1": case1,
|
|
"svc2": case2,
|
|
}
|
|
|
|
for _, t2 := range testCases {
|
|
u, err := runtime.DefaultUnstructuredConverter.ToUnstructured(t2.svc.DeepCopy())
|
|
assert.NoError(t, err)
|
|
res, err := additionalInfo(unstructured.Unstructured{Object: u})
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, t2.res, res)
|
|
}
|
|
}
|
|
|
|
var _ = Describe("unit-test to e2e test", func() {
|
|
deploy1 := v12.Deployment{
|
|
TypeMeta: metav1.TypeMeta{
|
|
APIVersion: "apps/v1",
|
|
Kind: "Deployment",
|
|
},
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "deploy1",
|
|
Namespace: "test-namespace",
|
|
},
|
|
Spec: v12.DeploymentSpec{
|
|
Selector: &metav1.LabelSelector{
|
|
MatchLabels: map[string]string{
|
|
"app": "deploy1",
|
|
},
|
|
},
|
|
Template: v1.PodTemplateSpec{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Labels: map[string]string{
|
|
"app": "deploy1",
|
|
},
|
|
},
|
|
Spec: v1.PodSpec{
|
|
Containers: []v1.Container{
|
|
{
|
|
Image: "nginx",
|
|
Name: "nginx",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
deploy2 := v12.Deployment{
|
|
TypeMeta: metav1.TypeMeta{
|
|
APIVersion: "apps/v1",
|
|
Kind: "Deployment",
|
|
},
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "deploy2",
|
|
Namespace: "test-namespace",
|
|
},
|
|
Spec: v12.DeploymentSpec{
|
|
Selector: &metav1.LabelSelector{
|
|
MatchLabels: map[string]string{
|
|
"app": "deploy2",
|
|
},
|
|
},
|
|
Template: v1.PodTemplateSpec{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Labels: map[string]string{
|
|
"app": "deploy2",
|
|
},
|
|
},
|
|
Spec: v1.PodSpec{
|
|
Containers: []v1.Container{
|
|
{
|
|
Image: "nginx",
|
|
Name: "nginx",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
rs1 := v12.ReplicaSet{
|
|
TypeMeta: metav1.TypeMeta{
|
|
APIVersion: "apps/v1",
|
|
Kind: "ReplicaSet",
|
|
},
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "rs1",
|
|
Namespace: "test-namespace",
|
|
Labels: map[string]string{
|
|
"app": "deploy1",
|
|
},
|
|
},
|
|
Spec: v12.ReplicaSetSpec{
|
|
Selector: &metav1.LabelSelector{
|
|
MatchLabels: map[string]string{
|
|
"app": "deploy1",
|
|
"rs": "rs1",
|
|
},
|
|
},
|
|
Template: v1.PodTemplateSpec{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Labels: map[string]string{
|
|
"app": "deploy1",
|
|
"rs": "rs1",
|
|
},
|
|
},
|
|
Spec: v1.PodSpec{
|
|
Containers: []v1.Container{
|
|
{
|
|
Image: "nginx",
|
|
Name: "nginx",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
rs2 := v12.ReplicaSet{
|
|
TypeMeta: metav1.TypeMeta{
|
|
APIVersion: "apps/v1",
|
|
Kind: "ReplicaSet",
|
|
},
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "rs2",
|
|
Namespace: "test-namespace",
|
|
Labels: map[string]string{
|
|
"app": "deploy1",
|
|
},
|
|
},
|
|
Spec: v12.ReplicaSetSpec{
|
|
Selector: &metav1.LabelSelector{
|
|
MatchLabels: map[string]string{
|
|
"app": "deploy1",
|
|
"rs": "rs2",
|
|
},
|
|
},
|
|
Template: v1.PodTemplateSpec{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Labels: map[string]string{
|
|
"app": "deploy1",
|
|
"rs": "rs2",
|
|
},
|
|
},
|
|
Spec: v1.PodSpec{
|
|
Containers: []v1.Container{
|
|
{
|
|
Image: "nginx",
|
|
Name: "nginx",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
rs3 := v12.ReplicaSet{
|
|
TypeMeta: metav1.TypeMeta{
|
|
APIVersion: "apps/v1",
|
|
Kind: "ReplicaSet",
|
|
},
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "rs3",
|
|
Namespace: "test-namespace",
|
|
Labels: map[string]string{
|
|
"app": "deploy2",
|
|
},
|
|
},
|
|
Spec: v12.ReplicaSetSpec{
|
|
Selector: &metav1.LabelSelector{
|
|
MatchLabels: map[string]string{
|
|
"app": "deploy2",
|
|
"rs": "rs3",
|
|
},
|
|
},
|
|
Template: v1.PodTemplateSpec{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Labels: map[string]string{
|
|
"app": "deploy2",
|
|
"rs": "rs3",
|
|
},
|
|
},
|
|
Spec: v1.PodSpec{
|
|
Containers: []v1.Container{
|
|
{
|
|
Image: "nginx",
|
|
Name: "nginx",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
pod1 := v1.Pod{
|
|
TypeMeta: metav1.TypeMeta{
|
|
APIVersion: "v1",
|
|
Kind: "Pod",
|
|
},
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "pod1",
|
|
Namespace: "test-namespace",
|
|
Labels: map[string]string{
|
|
"app": "deploy1",
|
|
"rs": "rs1",
|
|
},
|
|
},
|
|
Spec: v1.PodSpec{
|
|
Containers: []v1.Container{
|
|
{
|
|
Image: "nginx",
|
|
Name: "nginx",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
pod2 := v1.Pod{
|
|
TypeMeta: metav1.TypeMeta{
|
|
APIVersion: "v1",
|
|
Kind: "Pod",
|
|
},
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "pod2",
|
|
Namespace: "test-namespace",
|
|
Labels: map[string]string{
|
|
"app": "deploy1",
|
|
"rs": "rs2",
|
|
},
|
|
},
|
|
Spec: v1.PodSpec{
|
|
Containers: []v1.Container{
|
|
{
|
|
Image: "nginx",
|
|
Name: "nginx",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
pod3 := v1.Pod{
|
|
TypeMeta: metav1.TypeMeta{
|
|
APIVersion: "v1",
|
|
Kind: "Pod",
|
|
},
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "pod3",
|
|
Namespace: "test-namespace",
|
|
Labels: map[string]string{
|
|
"app": "deploy2",
|
|
"rs": "rs3",
|
|
},
|
|
},
|
|
Spec: v1.PodSpec{
|
|
Containers: []v1.Container{
|
|
{
|
|
Image: "nginx",
|
|
Name: "nginx",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
rs4 := v12.ReplicaSet{
|
|
TypeMeta: metav1.TypeMeta{
|
|
APIVersion: "apps/v1",
|
|
Kind: "ReplicaSet",
|
|
},
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "rs4",
|
|
Namespace: "test-namespace",
|
|
Labels: map[string]string{
|
|
"app": "deploy3",
|
|
},
|
|
},
|
|
Spec: v12.ReplicaSetSpec{
|
|
Selector: &metav1.LabelSelector{
|
|
MatchLabels: map[string]string{
|
|
"app": "deploy3",
|
|
"rs": "rs4",
|
|
},
|
|
},
|
|
Template: v1.PodTemplateSpec{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Labels: map[string]string{
|
|
"app": "deploy3",
|
|
"rs": "rs4",
|
|
},
|
|
},
|
|
Spec: v1.PodSpec{
|
|
Containers: []v1.Container{
|
|
{
|
|
Image: "nginx",
|
|
Name: "nginx",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
pod4 := v1.Pod{
|
|
TypeMeta: metav1.TypeMeta{
|
|
APIVersion: "v1",
|
|
Kind: "Pod",
|
|
},
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "pod4",
|
|
Namespace: "test-namespace",
|
|
Labels: map[string]string{
|
|
"app": "deploy3",
|
|
"rs": "rs4",
|
|
},
|
|
},
|
|
Spec: v1.PodSpec{
|
|
Containers: []v1.Container{
|
|
{
|
|
Image: "nginx",
|
|
Name: "nginx",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
pod5 := v1.Pod{
|
|
TypeMeta: metav1.TypeMeta{
|
|
APIVersion: "v1",
|
|
Kind: "Pod",
|
|
},
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "pod5",
|
|
Namespace: "test-namespace",
|
|
Labels: map[string]string{
|
|
"job-name": "job2",
|
|
},
|
|
},
|
|
Spec: v1.PodSpec{
|
|
Containers: []v1.Container{
|
|
{
|
|
Image: "nginx",
|
|
Name: "nginx",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
job1 := batchv1.Job{
|
|
TypeMeta: metav1.TypeMeta{
|
|
APIVersion: "batch/v1",
|
|
Kind: "Job",
|
|
},
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "job1",
|
|
Namespace: "test-namespace",
|
|
Labels: map[string]string{
|
|
"app": "cronJob1",
|
|
},
|
|
},
|
|
Spec: batchv1.JobSpec{
|
|
Template: v1.PodTemplateSpec{
|
|
Spec: v1.PodSpec{
|
|
RestartPolicy: "OnFailure",
|
|
Containers: []v1.Container{
|
|
{
|
|
Image: "nginx",
|
|
Name: "nginx",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
manualSelector := true
|
|
job2 := batchv1.Job{
|
|
TypeMeta: metav1.TypeMeta{
|
|
APIVersion: "batch/v1",
|
|
Kind: "Job",
|
|
},
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "job2",
|
|
Namespace: "test-namespace",
|
|
Labels: map[string]string{
|
|
"job-name": "job2",
|
|
},
|
|
},
|
|
Spec: batchv1.JobSpec{
|
|
ManualSelector: &manualSelector,
|
|
Selector: &metav1.LabelSelector{
|
|
MatchLabels: map[string]string{
|
|
"job-name": "job2",
|
|
},
|
|
},
|
|
Template: v1.PodTemplateSpec{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Labels: map[string]string{
|
|
"job-name": "job2",
|
|
},
|
|
},
|
|
Spec: v1.PodSpec{
|
|
RestartPolicy: "OnFailure",
|
|
Containers: []v1.Container{
|
|
{
|
|
Image: "nginx",
|
|
Name: "nginx",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
cronJob1 := batchv1.CronJob{
|
|
TypeMeta: metav1.TypeMeta{
|
|
APIVersion: "batch/v1",
|
|
Kind: "CronJob",
|
|
},
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "cronjob1",
|
|
Namespace: "test-namespace",
|
|
Labels: map[string]string{
|
|
"app": "cronJob1",
|
|
},
|
|
},
|
|
Spec: batchv1.CronJobSpec{
|
|
Schedule: "* * * * *",
|
|
JobTemplate: batchv1.JobTemplateSpec{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Labels: map[string]string{
|
|
"app": "cronJob1",
|
|
},
|
|
},
|
|
Spec: batchv1.JobSpec{
|
|
Template: v1.PodTemplateSpec{
|
|
Spec: v1.PodSpec{
|
|
RestartPolicy: "OnFailure",
|
|
Containers: []v1.Container{
|
|
{
|
|
Image: "nginx",
|
|
Name: "nginx",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
var objectList []client.Object
|
|
objectList = append(objectList, &deploy1, &deploy1, &rs1, &rs2, &rs3, &rs4, &pod1, &pod2, &pod3, &rs4, &pod4, &pod5, &job1, &job2, &cronJob1)
|
|
BeforeEach(func() {
|
|
Expect(k8sClient.Create(ctx, &v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "test-namespace"}})).Should(SatisfyAny(BeNil(), util.AlreadyExistMatcher{}))
|
|
Expect(k8sClient.Create(ctx, deploy1.DeepCopy())).Should(SatisfyAny(BeNil(), util.AlreadyExistMatcher{}))
|
|
Expect(k8sClient.Create(ctx, deploy2.DeepCopy())).Should(SatisfyAny(BeNil(), util.AlreadyExistMatcher{}))
|
|
Expect(k8sClient.Create(ctx, rs1.DeepCopy())).Should(SatisfyAny(BeNil(), util.AlreadyExistMatcher{}))
|
|
Expect(k8sClient.Create(ctx, rs2.DeepCopy())).Should(SatisfyAny(BeNil(), util.AlreadyExistMatcher{}))
|
|
Expect(k8sClient.Create(ctx, rs3.DeepCopy())).Should(SatisfyAny(BeNil(), util.AlreadyExistMatcher{}))
|
|
Expect(k8sClient.Create(ctx, pod1.DeepCopy())).Should(SatisfyAny(BeNil(), util.AlreadyExistMatcher{}))
|
|
Expect(k8sClient.Create(ctx, pod2.DeepCopy())).Should(SatisfyAny(BeNil(), util.AlreadyExistMatcher{}))
|
|
Expect(k8sClient.Create(ctx, pod3.DeepCopy())).Should(SatisfyAny(BeNil(), util.AlreadyExistMatcher{}))
|
|
cRs4 := rs4.DeepCopy()
|
|
Expect(k8sClient.Create(ctx, cRs4)).Should(SatisfyAny(BeNil(), util.AlreadyExistMatcher{}))
|
|
cPod4 := pod4.DeepCopy()
|
|
cPod4.SetOwnerReferences([]metav1.OwnerReference{
|
|
{
|
|
APIVersion: "apps/v1",
|
|
Kind: "ReplicaSet",
|
|
Name: cRs4.Name,
|
|
UID: cRs4.UID,
|
|
},
|
|
})
|
|
Expect(k8sClient.Create(ctx, cPod4)).Should(SatisfyAny(BeNil(), util.AlreadyExistMatcher{}))
|
|
cCronJob1 := cronJob1.DeepCopy()
|
|
Expect(k8sClient.Create(ctx, cCronJob1)).Should(SatisfyAny(BeNil(), util.AlreadyExistMatcher{}))
|
|
cJob1 := job1.DeepCopy()
|
|
Expect(k8sClient.Create(ctx, cJob1)).Should(SatisfyAny(BeNil(), util.AlreadyExistMatcher{}))
|
|
cJob2 := job2.DeepCopy()
|
|
Expect(k8sClient.Create(ctx, cJob2)).Should(SatisfyAny(BeNil(), util.AlreadyExistMatcher{}))
|
|
cPod5 := pod5.DeepCopy()
|
|
Expect(k8sClient.Create(ctx, cPod5)).Should(SatisfyAny(BeNil(), util.AlreadyExistMatcher{}))
|
|
})
|
|
|
|
AfterEach(func() {
|
|
for _, object := range objectList {
|
|
Expect(k8sClient.Delete(ctx, object))
|
|
}
|
|
})
|
|
|
|
It("test fetchObjectWithResourceTreeNode func", func() {
|
|
rtn := types.ResourceTreeNode{
|
|
Name: "deploy1",
|
|
Namespace: "test-namespace",
|
|
APIVersion: "apps/v1",
|
|
Kind: "Deployment",
|
|
}
|
|
u, err := fetchObjectWithResourceTreeNode(ctx, "", k8sClient, rtn)
|
|
Expect(err).Should(BeNil())
|
|
Expect(u).ShouldNot(BeNil())
|
|
Expect(u.GetName()).Should(BeEquivalentTo("deploy1"))
|
|
})
|
|
|
|
It("test list item by rule", func() {
|
|
u, err := runtime.DefaultUnstructuredConverter.ToUnstructured(deploy1.DeepCopy())
|
|
Expect(err).Should(BeNil())
|
|
items, err := listItemByRule(ctx, k8sClient, ResourceType{APIVersion: "apps/v1", Kind: "ReplicaSet"}, unstructured.Unstructured{Object: u},
|
|
defaultWorkloadLabelListOption, nil, true)
|
|
Expect(err).Should(BeNil())
|
|
Expect(len(items)).Should(BeEquivalentTo(2))
|
|
|
|
u2, err := runtime.DefaultUnstructuredConverter.ToUnstructured(deploy2.DeepCopy())
|
|
Expect(err).Should(BeNil())
|
|
items2, err := listItemByRule(ctx, k8sClient, ResourceType{APIVersion: "apps/v1", Kind: "ReplicaSet"}, unstructured.Unstructured{Object: u2},
|
|
nil, defaultWorkloadLabelListOption, true)
|
|
Expect(len(items2)).Should(BeEquivalentTo(1))
|
|
|
|
// test use ownerReference UId to filter
|
|
u3 := unstructured.Unstructured{}
|
|
u3.SetNamespace(rs4.Namespace)
|
|
u3.SetName(rs4.Name)
|
|
u3.SetAPIVersion("apps/v1")
|
|
u3.SetKind("ReplicaSet")
|
|
Expect(k8sClient.Get(ctx, types2.NamespacedName{Namespace: u3.GetNamespace(), Name: u3.GetName()}, &u3))
|
|
Expect(err).Should(BeNil())
|
|
items3, err := listItemByRule(ctx, k8sClient, ResourceType{APIVersion: "v1", Kind: "Pod"}, u3,
|
|
nil, nil, true)
|
|
Expect(err).Should(BeNil())
|
|
Expect(len(items3)).Should(BeEquivalentTo(1))
|
|
|
|
u4 := unstructured.Unstructured{}
|
|
u4.SetNamespace(cronJob1.Namespace)
|
|
u4.SetName(cronJob1.Name)
|
|
u4.SetAPIVersion("batch/v1")
|
|
u4.SetKind("CronJob")
|
|
Expect(k8sClient.Get(ctx, types2.NamespacedName{Namespace: u4.GetNamespace(), Name: u4.GetName()}, &u4))
|
|
Expect(err).Should(BeNil())
|
|
item4, err := listItemByRule(ctx, k8sClient, ResourceType{APIVersion: "batch/v1", Kind: "Job"}, u4,
|
|
cronJobLabelListOption, nil, true)
|
|
Expect(err).Should(BeNil())
|
|
Expect(len(item4)).Should(BeEquivalentTo(1))
|
|
})
|
|
|
|
It("iterate resource", func() {
|
|
tn, err := iterateListSubResources(ctx, "", k8sClient, types.ResourceTreeNode{
|
|
Cluster: "",
|
|
Namespace: "test-namespace",
|
|
Name: "deploy1",
|
|
APIVersion: "apps/v1",
|
|
Kind: "Deployment",
|
|
}, 1, func(node types.ResourceTreeNode) bool {
|
|
return true
|
|
})
|
|
Expect(err).Should(BeNil())
|
|
Expect(len(tn)).Should(BeEquivalentTo(2))
|
|
Expect(len(tn[0].LeafNodes)).Should(BeEquivalentTo(1))
|
|
Expect(len(tn[1].LeafNodes)).Should(BeEquivalentTo(1))
|
|
|
|
tn, err = iterateListSubResources(ctx, "", k8sClient, types.ResourceTreeNode{
|
|
Cluster: "",
|
|
Namespace: "test-namespace",
|
|
Name: "cronjob1",
|
|
APIVersion: "batch/v1",
|
|
Kind: "CronJob",
|
|
}, 1, func(node types.ResourceTreeNode) bool {
|
|
return true
|
|
})
|
|
Expect(err).Should(BeNil())
|
|
Expect(len(tn)).Should(BeEquivalentTo(1))
|
|
|
|
tn, err = iterateListSubResources(ctx, "", k8sClient, types.ResourceTreeNode{
|
|
Cluster: "",
|
|
Namespace: "test-namespace",
|
|
Name: "job2",
|
|
APIVersion: "batch/v1",
|
|
Kind: "Job",
|
|
}, 1, func(node types.ResourceTreeNode) bool {
|
|
return true
|
|
})
|
|
Expect(err).Should(BeNil())
|
|
Expect(len(tn)).Should(BeEquivalentTo(1))
|
|
})
|
|
|
|
It("test provider handler func", func() {
|
|
app := v1beta1.Application{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "app",
|
|
Namespace: "test-namespace",
|
|
},
|
|
Spec: v1beta1.ApplicationSpec{
|
|
Components: []common.ApplicationComponent{},
|
|
},
|
|
}
|
|
|
|
rt := v1beta1.ResourceTracker{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "app-test-v1-namespace",
|
|
Labels: map[string]string{
|
|
oam.LabelAppName: "app",
|
|
oam.LabelAppNamespace: "test-namespace",
|
|
},
|
|
Annotations: map[string]string{
|
|
oam.AnnotationPublishVersion: "v1",
|
|
},
|
|
},
|
|
Spec: v1beta1.ResourceTrackerSpec{
|
|
Type: v1beta1.ResourceTrackerTypeVersioned,
|
|
ManagedResources: []v1beta1.ManagedResource{
|
|
{
|
|
ClusterObjectReference: common.ClusterObjectReference{
|
|
Cluster: "",
|
|
ObjectReference: v1.ObjectReference{
|
|
APIVersion: "apps/v1",
|
|
Kind: "Deployment",
|
|
Namespace: "test-namespace",
|
|
Name: "deploy1",
|
|
},
|
|
},
|
|
OAMObjectReference: common.OAMObjectReference{
|
|
Component: "deploy1",
|
|
},
|
|
},
|
|
{
|
|
ClusterObjectReference: common.ClusterObjectReference{
|
|
Cluster: "",
|
|
ObjectReference: v1.ObjectReference{
|
|
APIVersion: "apps/v1",
|
|
Kind: "Deployment",
|
|
Namespace: "test-namespace",
|
|
Name: "deploy2",
|
|
},
|
|
},
|
|
OAMObjectReference: common.OAMObjectReference{
|
|
Component: "deploy2",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
Expect(k8sClient.Create(ctx, &app)).Should(BeNil())
|
|
Expect(k8sClient.Create(ctx, &rt)).Should(BeNil())
|
|
|
|
res, err := ListAppliedResources(context.Background(), &ListParams{
|
|
Params: ListVars{
|
|
App: Option{
|
|
Name: "app",
|
|
Namespace: "test-namespace",
|
|
WithTree: true,
|
|
},
|
|
},
|
|
RuntimeParams: oamprovidertypes.RuntimeParams{
|
|
KubeClient: k8sClient,
|
|
},
|
|
})
|
|
Expect(err).Should(BeNil())
|
|
Expect(len((*res).Returns.List)).Should(Equal(2))
|
|
})
|
|
|
|
It("Test not exist api don't break whole process", func() {
|
|
notExistRuleStr := `
|
|
- parentResourceType:
|
|
group: apps
|
|
kind: Deployment
|
|
childrenResourceType:
|
|
- apiVersion: v2
|
|
kind: Pod
|
|
`
|
|
notExistParentResourceStr := `
|
|
- parentResourceType:
|
|
group: badgroup
|
|
kind: Deployment
|
|
childrenResourceType:
|
|
- apiVersion: v2
|
|
kind: Pod
|
|
`
|
|
Expect(k8sClient.Create(ctx, &v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "vela-system"}})).Should(SatisfyAny(BeNil(), util.AlreadyExistMatcher{}))
|
|
badRuleConfigMap := v1.ConfigMap{TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "ConfigMap"},
|
|
ObjectMeta: metav1.ObjectMeta{Namespace: types3.DefaultKubeVelaNS, Name: "bad-rule", Labels: map[string]string{oam.LabelResourceRules: "true"}},
|
|
Data: map[string]string{relationshipKey: notExistRuleStr},
|
|
}
|
|
Expect(k8sClient.Create(ctx, &badRuleConfigMap)).Should(BeNil())
|
|
|
|
// clear after test
|
|
objectList = append(objectList, &badRuleConfigMap)
|
|
|
|
notExistParentConfigMap := v1.ConfigMap{TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "ConfigMap"},
|
|
ObjectMeta: metav1.ObjectMeta{Namespace: types3.DefaultKubeVelaNS, Name: "not-exist-parent", Labels: map[string]string{oam.LabelResourceRules: "true"}},
|
|
Data: map[string]string{relationshipKey: notExistParentResourceStr},
|
|
}
|
|
Expect(k8sClient.Create(ctx, ¬ExistParentConfigMap)).Should(BeNil())
|
|
|
|
// clear after test
|
|
objectList = append(objectList, &badRuleConfigMap)
|
|
|
|
res, err := ListAppliedResources(context.Background(), &ListParams{
|
|
Params: ListVars{
|
|
App: Option{
|
|
Name: "app",
|
|
Namespace: "test-namespace",
|
|
WithTree: true,
|
|
},
|
|
},
|
|
RuntimeParams: oamprovidertypes.RuntimeParams{
|
|
KubeClient: k8sClient,
|
|
},
|
|
})
|
|
Expect(err).Should(BeNil())
|
|
Expect(len((*res).Returns.List)).Should(Equal(2))
|
|
})
|
|
})
|
|
|
|
var _ = Describe("test merge globalRules", func() {
|
|
cloneSetStr := `
|
|
- parentResourceType:
|
|
group: apps.kruise.io
|
|
kind: CloneSet
|
|
childrenResourceType:
|
|
- apiVersion: v1
|
|
kind: Pod
|
|
defaultLabelSelector: true
|
|
- apiVersion: apps/v1
|
|
kind: ControllerRevision
|
|
`
|
|
clickhouseJsonStr := `
|
|
[
|
|
{
|
|
"parentResourceType": {
|
|
"group": "clickhouse.altinity.com",
|
|
"kind": "ClickHouseInstallation"
|
|
},
|
|
"childrenResourceType": [
|
|
{
|
|
"apiVersion": "apps/v1",
|
|
"kind": "StatefulSet"
|
|
},
|
|
{
|
|
"apiVersion": "v1",
|
|
"kind": "Service"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
`
|
|
daemonSetStr := `
|
|
- parentResourceType:
|
|
group: apps
|
|
kind: DaemonSet
|
|
childrenResourceType:
|
|
- apiVersion: apps/v1
|
|
kind: ControllerRevision
|
|
`
|
|
stsStr := `
|
|
- parentResourceType:
|
|
group: apps
|
|
kind: StatefulSet
|
|
childrenResourceType:
|
|
- apiVersion: v1
|
|
kind: Pod
|
|
- apiVersion: apps/v1
|
|
kind: ControllerRevision
|
|
`
|
|
missConfigedStr := `
|
|
- parentResourceType:
|
|
group: apps
|
|
kind: StatefulSet
|
|
childrenResourceType:
|
|
- apiVersion: v1
|
|
kind: Pod
|
|
- apiVersion: apps/v1
|
|
kind: ControllerRevision
|
|
`
|
|
|
|
It("test merge rules", func() {
|
|
Expect(k8sClient.Create(ctx, &v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "vela-system"}})).Should(SatisfyAny(BeNil(), util.AlreadyExistMatcher{}))
|
|
cloneSetConfigMap := v1.ConfigMap{TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "ConfigMap"},
|
|
ObjectMeta: metav1.ObjectMeta{Namespace: types3.DefaultKubeVelaNS, Name: "cloneset", Labels: map[string]string{
|
|
oam.LabelResourceRules: "true",
|
|
oam.LabelResourceRuleFormat: oam.ResourceTopologyFormatYAML,
|
|
}},
|
|
Data: map[string]string{relationshipKey: cloneSetStr},
|
|
}
|
|
Expect(k8sClient.Create(ctx, &cloneSetConfigMap)).Should(BeNil())
|
|
|
|
daemonSetConfigMap := v1.ConfigMap{TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "ConfigMap"},
|
|
ObjectMeta: metav1.ObjectMeta{Namespace: types3.DefaultKubeVelaNS, Name: "daemonset", Labels: map[string]string{
|
|
oam.LabelResourceRules: "true",
|
|
oam.LabelResourceRuleFormat: oam.ResourceTopologyFormatYAML,
|
|
}},
|
|
Data: map[string]string{relationshipKey: daemonSetStr},
|
|
}
|
|
Expect(k8sClient.Create(ctx, &daemonSetConfigMap)).Should(BeNil())
|
|
|
|
stsConfigMap := v1.ConfigMap{TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "ConfigMap"},
|
|
ObjectMeta: metav1.ObjectMeta{Namespace: types3.DefaultKubeVelaNS, Name: "sts", Labels: map[string]string{
|
|
oam.LabelResourceRules: "true",
|
|
oam.LabelResourceRuleFormat: oam.ResourceTopologyFormatYAML,
|
|
}},
|
|
Data: map[string]string{relationshipKey: stsStr},
|
|
}
|
|
Expect(k8sClient.Create(ctx, &stsConfigMap)).Should(BeNil())
|
|
|
|
missConfigedCm := v1.ConfigMap{TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "ConfigMap"},
|
|
ObjectMeta: metav1.ObjectMeta{Namespace: types3.DefaultKubeVelaNS, Name: "miss-configed", Labels: map[string]string{oam.LabelResourceRules: "true"}},
|
|
Data: map[string]string{relationshipKey: missConfigedStr},
|
|
}
|
|
Expect(k8sClient.Create(ctx, &missConfigedCm)).Should(BeNil())
|
|
|
|
clickhouseJsonCm := v1.ConfigMap{TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "ConfigMap"},
|
|
ObjectMeta: metav1.ObjectMeta{Namespace: types3.DefaultKubeVelaNS, Name: "clickhouse", Labels: map[string]string{
|
|
oam.LabelResourceRules: "true",
|
|
oam.LabelResourceRuleFormat: oam.ResourceTopologyFormatJSON,
|
|
}},
|
|
Data: map[string]string{relationshipKey: clickhouseJsonStr},
|
|
}
|
|
Expect(k8sClient.Create(ctx, &clickhouseJsonCm)).Should(BeNil())
|
|
|
|
Expect(mergeCustomRules(ctx, k8sClient)).Should(BeNil())
|
|
childrenResources, ok := globalRule.GetRule(GroupResourceType{Group: "apps.kruise.io", Kind: "CloneSet"})
|
|
Expect(ok).Should(BeTrue())
|
|
Expect(childrenResources.DefaultGenListOptionFunc).Should(BeNil())
|
|
Expect(len(*childrenResources.SubResources)).Should(BeEquivalentTo(2))
|
|
|
|
crPod := childrenResources.SubResources.Get(ResourceType{APIVersion: "v1", Kind: "Pod"})
|
|
Expect(crPod).ShouldNot(BeNil())
|
|
Expect(crPod.listOptions).ShouldNot(BeNil())
|
|
|
|
dsChildrenResources, ok := globalRule.GetRule(GroupResourceType{Group: "apps", Kind: "DaemonSet"})
|
|
Expect(ok).Should(BeTrue())
|
|
Expect(dsChildrenResources.DefaultGenListOptionFunc).Should(BeNil())
|
|
Expect(len(*dsChildrenResources.SubResources)).Should(BeEquivalentTo(2))
|
|
|
|
// with the error version
|
|
crPod2 := dsChildrenResources.SubResources.Get(ResourceType{APIVersion: "v1", Kind: "ControllerRevision"})
|
|
Expect(crPod2).Should(BeNil())
|
|
|
|
crPod3 := dsChildrenResources.SubResources.Get(ResourceType{APIVersion: "v1", Kind: "Pod"})
|
|
Expect(crPod3).ShouldNot(BeNil())
|
|
Expect(crPod3.listOptions).ShouldNot(BeNil())
|
|
|
|
cr := dsChildrenResources.SubResources.Get(ResourceType{APIVersion: "apps/v1", Kind: "ControllerRevision"})
|
|
Expect(cr).ShouldNot(BeNil())
|
|
Expect(cr.listOptions).Should(BeNil())
|
|
|
|
stsChildrenResources, ok := globalRule.GetRule(GroupResourceType{Group: "apps", Kind: "StatefulSet"})
|
|
Expect(ok).Should(BeTrue())
|
|
Expect(stsChildrenResources.DefaultGenListOptionFunc).Should(BeNil())
|
|
Expect(len(*stsChildrenResources.SubResources)).Should(BeEquivalentTo(2))
|
|
revisionCR := stsChildrenResources.SubResources.Get(ResourceType{APIVersion: "apps/v1", Kind: "ControllerRevision"})
|
|
Expect(revisionCR).ShouldNot(BeNil())
|
|
Expect(revisionCR.listOptions).Should(BeNil())
|
|
|
|
chChildrenResources, ok := globalRule.GetRule(GroupResourceType{Group: "clickhouse.altinity.com", Kind: "ClickHouseInstallation"})
|
|
Expect(ok).Should(BeTrue())
|
|
Expect(chChildrenResources.DefaultGenListOptionFunc).Should(BeNil())
|
|
Expect(len(*chChildrenResources.SubResources)).Should(BeEquivalentTo(2))
|
|
|
|
chSts := chChildrenResources.SubResources.Get(ResourceType{APIVersion: "apps/v1", Kind: "StatefulSet"})
|
|
Expect(chSts).ShouldNot(BeNil())
|
|
Expect(chSts.listOptions).Should(BeNil())
|
|
|
|
chSvc := chChildrenResources.SubResources.Get(ResourceType{APIVersion: "v1", Kind: "Service"})
|
|
Expect(chSvc).ShouldNot(BeNil())
|
|
Expect(chSvc.listOptions).Should(BeNil())
|
|
|
|
// clear data
|
|
Expect(k8sClient.Delete(context.TODO(), &missConfigedCm)).Should(BeNil())
|
|
Expect(k8sClient.Delete(context.TODO(), &stsConfigMap)).Should(BeNil())
|
|
Expect(k8sClient.Delete(context.TODO(), &daemonSetConfigMap)).Should(BeNil())
|
|
Expect(k8sClient.Delete(context.TODO(), &cloneSetConfigMap)).Should(BeNil())
|
|
})
|
|
})
|