Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 25 additions & 42 deletions pkg/kclshim/kcl.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,57 +4,33 @@
//
// 1. Create a folder and write your KCLs. Take "./fixtures/example_synthesizer/main.k" as an example.
//
// 2. Write a main.go and call "Synthesize()", defined below.
// 2. Write a main.go and call "Synthesize(workingDir, input)", defined below.
package kclshim

import (
"encoding/json"
"fmt"
"io"
"os"

krmv1 "github.com/Azure/eno/pkg/krm/functions/api/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
kcl "kcl-lang.io/kcl-go"
"kcl-lang.io/kcl-go/pkg/spec/gpyrpc"
"sigs.k8s.io/controller-runtime/pkg/client"
)

func printErr(err error) {
rl := krmv1.ResourceList{
APIVersion: krmv1.SchemeGroupVersion.String(),
Kind: krmv1.ResourceListKind,
Items: []*unstructured.Unstructured{},
Results: []*krmv1.Result{
{
Message: err.Error(),
Severity: krmv1.ResultSeverityError,
},
},
}
bytes, err := json.Marshal(rl)
if err != nil {
rl.Results = append(rl.Results, &krmv1.Result{
Message: fmt.Sprintf("error marshaling error response: %v", err),
Severity: krmv1.ResultSeverityError,
})
}
fmt.Print(string(bytes))
}

func Synthesize(workingDir string) {
buffer, err := io.ReadAll(os.Stdin)
// Synthesize runs a KCL program in the given directory with JSON-serializable structured input.
// It returns the synthesized Kubernetes objects or an error.
func Synthesize(workingDir string, input any) ([]client.Object, error) {
inputJSON, err := json.Marshal(input)
if err != nil {
printErr(fmt.Errorf("error reading from stdin: %w", err))
return
return nil, fmt.Errorf("error marshaling input to JSON: %w", err)
}
input := string(buffer)
inputStr := string(inputJSON)

depResult, err := kcl.UpdateDependencies(&gpyrpc.UpdateDependencies_Args{
ManifestPath: workingDir,
})
if err != nil {
printErr(fmt.Errorf("error updating dependencies: %w", err))
return
return nil, fmt.Errorf("error updating dependencies: %w", err)
}

depOpt := kcl.NewOption()
Expand All @@ -64,24 +40,31 @@ func Synthesize(workingDir string) {
"main.k",
kcl.WithWorkDir(workingDir),
*depOpt,
kcl.WithOptions(fmt.Sprintf("input=%s", input)),
kcl.WithOptions(fmt.Sprintf("input=%s", inputStr)),
)
if err != nil {
printErr(fmt.Errorf("error running KCL: %w", err))
return
return nil, fmt.Errorf("error running KCL: %w", err)
}

result, err := results.First().ToMap()
if err != nil {
return nil, fmt.Errorf("error converting KCL result to map: %w", err)
}

output := result["output"]
outputJSON, err := json.Marshal(output)
if err != nil {
printErr(fmt.Errorf("error marshaling output to JSON: %w", err))
return
return nil, fmt.Errorf("error marshaling output to JSON: %w", err)
}

_, err = fmt.Println(string(outputJSON))
if err != nil {
printErr(fmt.Errorf("error printing output: %w", err))
return
var rl krmv1.ResourceList
if err := json.Unmarshal(outputJSON, &rl); err != nil {
return nil, fmt.Errorf("error unmarshaling output to ResourceList: %w", err)
}

var objects []client.Object
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder why you don't return krmv1.ResourceList directly?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was doing that previously, but then I found function.Main expects SynthFunc to return ([]client.Object, error), so I added this one more step to convert krmv1.ResourceList to []client.Object

for _, item := range rl.Items {
objects = append(objects, item)
}
return objects, nil
}
Loading
Loading