Skip to content

Commit

Permalink
add normalizeService in k8s runtime
Browse files Browse the repository at this point in the history
  • Loading branch information
SparkYuan committed Feb 13, 2023
1 parent 7a6e482 commit b689f6f
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 4 deletions.
35 changes: 34 additions & 1 deletion pkg/engine/runtime/kubernetes/kubernetes_runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
k8sruntime "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
k8syaml "k8s.io/apimachinery/pkg/runtime/serializer/yaml"
"k8s.io/apimachinery/pkg/types"
Expand Down Expand Up @@ -223,12 +224,25 @@ func (k *KubernetesRuntime) Import(ctx context.Context, request *runtime.ImportR
return &runtime.ImportResponse{Status: status.NewErrorStatusWithCode(status.IllegalManifest, err)}
}
} else {
unstructured.RemoveNestedField(ur.Object, "status")

// normalize
switch ur.GetKind() {
case k8s.Service:
if err := normalizeService(ur); err != nil {
return &runtime.ImportResponse{
Resource: nil,
Status: status.NewErrorStatusWithCode(status.IllegalManifest, err),
}
}
}

const metadata = "metadata"
unstructured.RemoveNestedField(ur.Object, "status")
unstructured.RemoveNestedField(ur.Object, metadata, "resourceVersion")
unstructured.RemoveNestedField(ur.Object, metadata, "creationTimestamp")
unstructured.RemoveNestedField(ur.Object, metadata, "selfLink")
unstructured.RemoveNestedField(ur.Object, metadata, "uid")

}
response.Resource.Attributes = ur.Object
return &runtime.ImportResponse{
Expand All @@ -237,6 +251,25 @@ func (k *KubernetesRuntime) Import(ctx context.Context, request *runtime.ImportR
}
}

func normalizeService(ur *unstructured.Unstructured) error {
target := &corev1.Service{}
if err := k8sruntime.DefaultUnstructuredConverter.FromUnstructured(ur.Object, target); err != nil {
return err
}
if len(target.Spec.ClusterIPs) > 0 {
target.Spec.ClusterIPs = nil
}
if len(target.Spec.ClusterIP) > 0 {
target.Spec.ClusterIP = ""
}
toUnstructured, err := k8sruntime.DefaultUnstructuredConverter.ToUnstructured(target)
if err != nil {
return err
}
ur.Object = toUnstructured
return nil
}

// Delete kubernetes Resource by client-go
func (k *KubernetesRuntime) Delete(ctx context.Context, request *runtime.DeleteRequest) *runtime.DeleteResponse {
requestResource := request.Resource
Expand Down
120 changes: 120 additions & 0 deletions pkg/engine/runtime/kubernetes/kubernetes_runtime_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
//go:build ignore
// +build ignore

// ignore for test coverage
package kubernetes

import (
"context"
"os"
"reflect"
"testing"

"bou.ke/monkey"
yamlv3 "gopkg.in/yaml.v3"

"kusionstack.io/kusion/pkg/engine/models"
"kusionstack.io/kusion/pkg/engine/runtime"
jsonutil "kusionstack.io/kusion/pkg/util/json"
)

func TestKubernetesRuntime_Import(t *testing.T) {
planServiceYaml, _ := os.ReadFile("testdata/plan_service.yaml")
planSvc := &models.Resource{}
yamlv3.Unmarshal(planServiceYaml, planSvc)

lastAppliedYaml, _ := os.ReadFile("testdata/live_service_with_last_applied_annotation.yaml")
lastAppliedObj := make(map[string]interface{})
yamlv3.Unmarshal(lastAppliedYaml, lastAppliedObj)

liveSvcYaml, _ := os.ReadFile("testdata/live_service.yaml")
liveSvcObj := make(map[string]interface{})
yamlv3.Unmarshal(liveSvcYaml, liveSvcObj)

liveSvcImpYaml, _ := os.ReadFile("testdata/live_service_import_result.yaml")
liveSvcImpObj := make(map[string]interface{})
yamlv3.Unmarshal(liveSvcImpYaml, liveSvcImpObj)

svcYaml, _ := os.ReadFile("testdata/service.yaml")
svcObj := make(map[string]interface{})
yamlv3.Unmarshal(svcYaml, svcObj)

type args struct {
ctx context.Context
request *runtime.ImportRequest
}
tests := []struct {
name string
args args
want *runtime.ImportResponse
}{
{name: "import-svc-with-last-applied", args: struct {
ctx context.Context
request *runtime.ImportRequest
}{ctx: context.Background(), request: &runtime.ImportRequest{
PlanResource: planSvc,
}}, want: &runtime.ImportResponse{
Resource: &models.Resource{
ID: planSvc.ResourceKey(),
Type: planSvc.Type,
Attributes: svcObj,
DependsOn: planSvc.DependsOn,
Extensions: planSvc.Extensions,
},
Status: nil,
}},
{name: "import-svc", args: args{
ctx: context.Background(),
request: &runtime.ImportRequest{
PlanResource: planSvc,
},
}, want: &runtime.ImportResponse{
Resource: &models.Resource{
ID: planSvc.ResourceKey(),
Type: planSvc.Type,
Attributes: liveSvcImpObj,
DependsOn: planSvc.DependsOn,
Extensions: planSvc.Extensions,
},
Status: nil,
}},
}

t.Run(tests[0].name, func(t *testing.T) {
k := &KubernetesRuntime{}
defer monkey.UnpatchAll()

monkey.PatchInstanceMethod(reflect.TypeOf(k), "Read", func(k *KubernetesRuntime, ctx context.Context, request *runtime.ReadRequest) *runtime.ReadResponse {
return &runtime.ReadResponse{Resource: &models.Resource{
ID: planSvc.ResourceKey(),
Type: planSvc.Type,
Attributes: lastAppliedObj,
DependsOn: planSvc.DependsOn,
Extensions: planSvc.Extensions,
}}
})

got := k.Import(tests[0].args.ctx, tests[0].args.request)
if !reflect.DeepEqual(jsonutil.Marshal2PrettyString(got.Resource), jsonutil.Marshal2PrettyString(tests[0].want.Resource)) {
t.Errorf("Import() = %v, want %v", jsonutil.Marshal2PrettyString(got.Resource), jsonutil.Marshal2PrettyString(tests[0].want.Resource))
}
})

t.Run(tests[1].name, func(t *testing.T) {
k := &KubernetesRuntime{}
monkey.PatchInstanceMethod(reflect.TypeOf(k), "Read", func(k *KubernetesRuntime, ctx context.Context, request *runtime.ReadRequest) *runtime.ReadResponse {
return &runtime.ReadResponse{Resource: &models.Resource{
ID: planSvc.ResourceKey(),
Type: planSvc.Type,
Attributes: liveSvcObj,
DependsOn: planSvc.DependsOn,
Extensions: planSvc.Extensions,
}}
})
defer monkey.UnpatchAll()

if got := k.Import(tests[1].args.ctx, tests[1].args.request); !reflect.DeepEqual(jsonutil.Marshal2PrettyString(got), jsonutil.Marshal2PrettyString(tests[1].want)) {
t.Errorf("Import() = %v, want %v", jsonutil.Marshal2PrettyString(got), jsonutil.Marshal2PrettyString(tests[1].want))
}
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@ metadata:
name: gocity
namespace: code-city
spec:
clusterIP: 10.101.160.144
clusterIPs:
- 10.101.160.144
internalTrafficPolicy: Cluster
ipFamilies:
- IPv4
Expand Down

0 comments on commit b689f6f

Please sign in to comment.