From 36d15d62468b941699747007bd0fbcc2a5fd4ee7 Mon Sep 17 00:00:00 2001 From: peefy Date: Sat, 11 May 2024 18:05:31 +0800 Subject: [PATCH] refactor: function kcl input to krm kcl spec and add more tests Signed-off-by: peefy --- .github/workflows/ci.yaml | 2 +- fn.go | 8 +++- fn_test.go | 99 ++++++++++++++++++++++++++++++++++++--- go.mod | 10 ++-- go.sum | 24 ++++------ 5 files changed, 115 insertions(+), 28 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 74a4acf..1b36986 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -33,7 +33,7 @@ env: XPKG: xpkg.upbound.io/${{ github.repository}} # The package version to push. The default is 0.0.0-gitsha. - XPKG_VERSION: v0.7.3 + XPKG_VERSION: v0.8.0 jobs: unit-test: diff --git a/fn.go b/fn.go index f8b1c59..399b6af 100644 --- a/fn.go +++ b/fn.go @@ -8,6 +8,8 @@ import ( "github.com/crossplane/crossplane-runtime/pkg/errors" "github.com/crossplane/crossplane-runtime/pkg/logging" "k8s.io/apimachinery/pkg/runtime" + "kcl-lang.io/krm-kcl/pkg/api" + "kcl-lang.io/krm-kcl/pkg/api/v1alpha1" "kcl-lang.io/krm-kcl/pkg/kio" fnv1beta1 "github.com/crossplane/function-sdk-go/proto/v1beta1" @@ -119,8 +121,12 @@ func (f *Function) RunFunction(_ context.Context, req *fnv1beta1.RunFunctionRequ return rsp, nil } in.Spec.Params["ctx"] = ctxObj - // Input Example: https://github.com/kcl-lang/krm-kcl/blob/main/examples/mutation/set-annotations/suite/good.yaml inputBytes, outputBytes := bytes.NewBuffer([]byte{}), bytes.NewBuffer([]byte{}) + // Convert the function-kcl KCLInput to the KRM-KCL spec and run function pipelines. + // Input Example: https://github.com/kcl-lang/krm-kcl/blob/main/examples/mutation/set-annotations/suite/good.yaml + in.APIVersion = v1alpha1.KCLRunAPIVersion + in.Kind = api.KCLRunKind + // Note use "sigs.k8s.io/yaml" here. kclRunBytes, err := yaml.Marshal(in) if err != nil { response.Fatal(rsp, errors.Wrap(err, "cannot marshal input to yaml")) diff --git a/fn_test.go b/fn_test.go index 2184d49..6d46d01 100644 --- a/fn_test.go +++ b/fn_test.go @@ -2,22 +2,26 @@ package main import ( "context" + "os" + "path/filepath" "testing" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "google.golang.org/protobuf/testing/protocmp" "google.golang.org/protobuf/types/known/durationpb" + "google.golang.org/protobuf/types/known/structpb" "github.com/crossplane/crossplane-runtime/pkg/logging" fnv1beta1 "github.com/crossplane/function-sdk-go/proto/v1beta1" "github.com/crossplane/function-sdk-go/resource" "github.com/crossplane/function-sdk-go/response" -) -func TestRunFunction(t *testing.T) { + "kcl-lang.io/krm-kcl/pkg/kube" +) +func TestRunFunctionSimple(t *testing.T) { type args struct { ctx context.Context req *fnv1beta1.RunFunctionRequest @@ -26,7 +30,6 @@ func TestRunFunction(t *testing.T) { rsp *fnv1beta1.RunFunctionResponse err error } - cases := map[string]struct { reason string args args @@ -39,7 +42,7 @@ func TestRunFunction(t *testing.T) { Meta: &fnv1beta1.RequestMeta{Tag: "hello"}, Input: resource.MustStructJSON(`{ "apiVersion": "krm.kcl.dev/v1alpha1", - "kind": "KCLRun", + "kind": "KCLInput", "metadata": { "name": "basic" }, @@ -78,7 +81,7 @@ func TestRunFunction(t *testing.T) { Meta: &fnv1beta1.RequestMeta{Tag: "database-instance"}, Input: resource.MustStructJSON(`{ "apiVersion": "krm.kcl.dev/v1alpha1", - "kind": "KCLRun", + "kind": "KCLInput", "metadata": { "name": "basic" }, @@ -116,7 +119,7 @@ func TestRunFunction(t *testing.T) { Meta: &fnv1beta1.RequestMeta{Tag: "hello"}, Input: resource.MustStructJSON(`{ "apiVersion": "krm.kcl.dev/v1alpha1", - "kind": "KCLRun", + "kind": "KCLInput", "metadata": { "name": "basic" }, @@ -165,3 +168,87 @@ func TestRunFunction(t *testing.T) { }) } } + +const ( + xrFile = "xr.yaml" + compositionFile = "composition.yaml" +) + +func findXRandCompositionYAMLFiles(rootPath string) ([]string, error) { + var dirs []string + + // Walk receives the root directory and a function to process each path + err := filepath.Walk(rootPath, func(path string, info os.FileInfo, err error) error { + if err != nil { // Handle potential errors + return err + } + + // Check if the current path is a directory and it contains xr.yaml file + if info.IsDir() { + xrPath := filepath.Join(path, xrFile) + compositionPath := filepath.Join(path, compositionFile) + if _, err := os.Stat(xrPath); err == nil { + if _, err := os.Stat(compositionPath); err == nil { + dirs = append(dirs, path) // File exists, add directory to list + } + } + } + + return nil + }) + + return dirs, err +} + +func readResourceFromFile(p string) (*structpb.Struct, error) { + c, err := os.ReadFile(p) + if err != nil { + return nil, err + } + o, err := kube.ParseKubeObject(c) + if err != nil { + return nil, err + } + j, err := o.Node().MarshalJSON() + if err != nil { + return nil, err + } + return resource.MustStructJSON(string(j)), nil +} + +func TestFunctionExamples(t *testing.T) { + rootPath := "examples" // Change to your examples folder path + dirs, err := findXRandCompositionYAMLFiles(rootPath) + if err != nil { + t.Fatal(err) + } + // Print all directories containing xr.yaml file + for _, dir := range dirs { + xrPath := filepath.Join(dir, xrFile) + compositionPath := filepath.Join(dir, compositionFile) + t.Run(compositionPath, func(t *testing.T) { + f := &Function{log: logging.NewNopLogger()} + input, err := readResourceFromFile(xrPath) + if err != nil { + t.Fatal(err) + } + oxr, err := readResourceFromFile(compositionPath) + if err != nil { + t.Fatal(err) + } + req := &fnv1beta1.RunFunctionRequest{ + Input: input, + // option("params").oxr + Observed: &fnv1beta1.State{ + Composite: &fnv1beta1.Resource{ + Resource: oxr, + }, + }, + } + _, err = f.RunFunction(context.TODO(), req) + if err != nil { + t.Fatal(err) + } + }) + } +} diff --git a/go.mod b/go.mod index 37e0697..830c773 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( google.golang.org/protobuf v1.34.1 gopkg.in/yaml.v2 v2.4.0 k8s.io/apimachinery v0.30.0 - kcl-lang.io/krm-kcl v0.8.6 + kcl-lang.io/krm-kcl v0.8.7-0.20240511092915-909e5fb3485f sigs.k8s.io/controller-tools v0.15.0 sigs.k8s.io/yaml v1.4.0 ) @@ -26,8 +26,6 @@ require ( github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/BurntSushi/toml v1.3.2 // indirect - github.com/GoogleContainerTools/kpt-functions-sdk/go/api v0.0.0-20220720212527-133180134b93 // indirect - github.com/GoogleContainerTools/kpt-functions-sdk/go/fn v0.0.0-20230427202446-3255accc518d // indirect github.com/Microsoft/go-winio v0.6.1 // indirect github.com/Microsoft/hcsshim v0.11.4 // indirect github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect @@ -191,11 +189,11 @@ require ( k8s.io/klog/v2 v2.120.1 // indirect k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect k8s.io/utils v0.0.0-20240102154912-e7106e64919e // indirect - kcl-lang.io/cli v0.8.7 // indirect - kcl-lang.io/kcl-go v0.8.6 // indirect + kcl-lang.io/cli v0.8.8 // indirect + kcl-lang.io/kcl-go v0.8.7 // indirect kcl-lang.io/kcl-openapi v0.6.1 // indirect kcl-lang.io/kpm v0.8.6 // indirect - kcl-lang.io/lib v0.8.6 // indirect + kcl-lang.io/lib v0.8.7 // indirect oras.land/oras-go v1.2.3 // indirect oras.land/oras-go/v2 v2.3.0 // indirect sigs.k8s.io/controller-runtime v0.17.0 // indirect diff --git a/go.sum b/go.sum index 6afc2e2..6b5a1a5 100644 --- a/go.sum +++ b/go.sum @@ -195,10 +195,6 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/GoogleContainerTools/kpt-functions-sdk/go/api v0.0.0-20220720212527-133180134b93 h1:c1GhPzYzU2a3E+/2WB9OxoljK2pNYfsBF5Fz9GkdYXs= -github.com/GoogleContainerTools/kpt-functions-sdk/go/api v0.0.0-20220720212527-133180134b93/go.mod h1:gkK43tTaPXFNASpbIbQImzhmt1hdcdin++kvzTblykc= -github.com/GoogleContainerTools/kpt-functions-sdk/go/fn v0.0.0-20230427202446-3255accc518d h1:kgC/R6Kl+tBjsRvcPr4Beae1MiHumNMtbmUTy7qlPZI= -github.com/GoogleContainerTools/kpt-functions-sdk/go/fn v0.0.0-20230427202446-3255accc518d/go.mod h1:Pnd3ImgaWS3OBVjztSiGMACMf+CDs20l5nT5Oljy/tA= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= @@ -762,8 +758,8 @@ github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.17.2 h1:7eMhcy3GimbsA3hEnVKdw/PQM9XN9krpKVXsZdph0/g= github.com/onsi/ginkgo/v2 v2.17.2/go.mod h1:nP2DPOQoNsQmsVyv5rDA8JkXQoCs6goXIvr/PRJ1eCc= -github.com/onsi/gomega v1.33.0 h1:snPCflnZrpMsy94p4lXVEkHo12lmPnc3vY5XBbreexE= -github.com/onsi/gomega v1.33.0/go.mod h1:+925n5YtiFsLzzafLUHzVMBpvvRAzrydIBiSIxjX3wY= +github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= +github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= @@ -1559,18 +1555,18 @@ k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7F k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= k8s.io/utils v0.0.0-20240102154912-e7106e64919e h1:eQ/4ljkx21sObifjzXwlPKpdGLrCfRziVtos3ofG/sQ= k8s.io/utils v0.0.0-20240102154912-e7106e64919e/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -kcl-lang.io/cli v0.8.7 h1:sqwb0GUCJAsp5GOKXMQxLDt6Axy5mDkZdMa0l36XgP0= -kcl-lang.io/cli v0.8.7/go.mod h1:F93PpwwT0ZvZK62burKlRdz0aZnPn2O/5G1F9u9KlHo= -kcl-lang.io/kcl-go v0.8.6 h1:mcQUX9edtKHGFl6m/QRYIDpRNKAcpFHJsZzoHQbAVV4= -kcl-lang.io/kcl-go v0.8.6/go.mod h1:m6vy5z9hCXlKEgKrL10uZGbwoCKPokpuFKtZC2488d8= +kcl-lang.io/cli v0.8.8 h1:wsf8FB8CEGPJeMdQZXVV4CF939AU060tnlrxfz8sqac= +kcl-lang.io/cli v0.8.8/go.mod h1:UM4AIt/uX8s2ad93lHkLLV3HfIJ0nkcUOhBaNhJ+DMs= +kcl-lang.io/kcl-go v0.8.7 h1:KekBSkoZYWupMjsC0yX3bCQzEvFTI9HTpKREvWrvu/8= +kcl-lang.io/kcl-go v0.8.7/go.mod h1:PjOAZXoCdmx+rz/zybRNLQWvybnU4z4gbKDW7IwUDH4= kcl-lang.io/kcl-openapi v0.6.1 h1:iPH0EvPgDGZS5Lk00/Su5Av6AQP5IBG8f7gAUyevkHE= kcl-lang.io/kcl-openapi v0.6.1/go.mod h1:Ai9mFztCVKkRSFabczO/r5hCNdqaNtAc2ZIRxTeV0Mk= kcl-lang.io/kpm v0.8.6 h1:uGaZjfkyG2ot9xVqdbE7ZsHcUfi6qYDa3UZUM77hhR8= kcl-lang.io/kpm v0.8.6/go.mod h1:buvccvOf1JdN9WiPG1bOYHUnzapWNBLfURJf8W/VswU= -kcl-lang.io/krm-kcl v0.8.6 h1:XDthlR22e21ttFFxG8YhPh5ymB+aCOdledEpz7wgvoU= -kcl-lang.io/krm-kcl v0.8.6/go.mod h1:CAb+LBz4Zn670W+tKurWDpfErBWxPHCNSCeI2L9b++4= -kcl-lang.io/lib v0.8.6 h1:y7+t19DZX/hJzgEsfAAN22gUHXVVJ1VOGJoWx8LGORo= -kcl-lang.io/lib v0.8.6/go.mod h1:ubsalGXxJaa5II/EsHmsI/tL2EluYHIcW+BwzQPt+uY= +kcl-lang.io/krm-kcl v0.8.7-0.20240511092915-909e5fb3485f h1:iRxTZwNo00ufyxP0ljCJzFo4dtkPg7qSQZc+BNh8+QI= +kcl-lang.io/krm-kcl v0.8.7-0.20240511092915-909e5fb3485f/go.mod h1:TQGqN8/frOFUbPqkxi1cJXwYeD5KHIVkomtg6788GyM= +kcl-lang.io/lib v0.8.7 h1:qN7FOrwd8l4IiuPUDEEIKJqavGAq+rTMR1GCn0OrydE= +kcl-lang.io/lib v0.8.7/go.mod h1:ubsalGXxJaa5II/EsHmsI/tL2EluYHIcW+BwzQPt+uY= oras.land/oras-go v1.2.5 h1:XpYuAwAb0DfQsunIyMfeET92emK8km3W4yEzZvUbsTo= oras.land/oras-go v1.2.5/go.mod h1:PuAwRShRZCsZb7g8Ar3jKKQR/2A/qN+pkYxIOd/FAoo= oras.land/oras-go/v2 v2.5.0 h1:o8Me9kLY74Vp5uw07QXPiitjsw7qNXi8Twd+19Zf02c=