Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor/sdk #31

Merged
merged 13 commits into from
Jul 13, 2024
5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,12 @@ PROJECT_DIR := $(dir $(firstword $(MAKEFILE_LIST)))
.PHONY: generate
generate: pkl-resolve-hack pkl-resolve
go generate ./...
pkl eval --working-dir $(PROJECT_DIR)hack/pklcrd -m ../../pkl/crossplane.contrib crd2module.pkl
pkl eval --working-dir $(PROJECT_DIR)hack/pklcrd -m ../../pkl/crossplane.contrib crd2module.pkl -p source="package/input/pkl.fn.crossplane.io_pkls.yaml"
pkl eval --working-dir $(PROJECT_DIR)hack/pklcrd -m ../../pkl/crossplane.contrib.xrd crd2module.pkl -p source="https://raw.githubusercontent.com/crossplane/crossplane/v1.16.0/cluster/crds/apiextensions.crossplane.io_compositeresourcedefinitions.yaml"
pkl eval --working-dir $(PROJECT_DIR)hack/pklcrd -m ../../pkl/crossplane.contrib crd2module-composition-fix.pkl
pkl eval --working-dir $(PROJECT_DIR)pkl/crossplane.contrib.example -m crds xrds/ExampleXR.pkl
pkl eval --working-dir $(PROJECT_DIR)pkl/crossplane.contrib.example compositions/inline.pkl > $(PROJECT_DIR)example/inline/composition.yaml
pkl eval --working-dir $(PROJECT_DIR)pkl/crossplane.contrib.example compositions/uri.pkl > $(PROJECT_DIR)example/full/composition.yaml
pkl eval --working-dir $(PROJECT_DIR)pkl/crossplane.contrib.example $(EXAMPLE_PARAM) compositions/uri.pkl > $(PROJECT_DIR)example/full/composition.yaml
pkl eval --working-dir $(PROJECT_DIR)pkl/crossplane.contrib.example xrs/inline.pkl > $(PROJECT_DIR)example/inline/xr.yaml
pkl eval --working-dir $(PROJECT_DIR)pkl/crossplane.contrib.example xrs/uri.pkl > $(PROJECT_DIR)example/full/xr.yaml

Expand Down
2 changes: 1 addition & 1 deletion example/full/composition.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ spec:
kind: Pkl
spec:
type: uri
uri: package://pkg.pkl-lang.org/github.com/crossplane-contrib/function-pkl/[email protected].0#/compositions/steps/full.pkl
uri: package://pkg.pkl-lang.org/github.com/crossplane-contrib/function-pkl/[email protected].1#/compositions/steps/full.pkl
step: pkl-template
5 changes: 5 additions & 0 deletions example/full/extraresources.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
apiVersion: kubernetes.crossplane.io/v1alpha2
kind: Object
metadata:
name: required
4 changes: 0 additions & 4 deletions example/inline/composition.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,10 @@ spec:
resources {
["cm-minimal"] = new {
resource = new Object {
metadata {
name = "cm-one"
}
spec {
forProvider {
manifest = new ConfigMap {
metadata {
name = "cm-minimal"
namespace = "crossplane-system"
}
data {
Expand Down
12 changes: 11 additions & 1 deletion hack/pklcrd/crd2module.pkl
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
amends "@k8s.contrib.crd/generate.pkl"

source = "package/input/pkl.fn.crossplane.io_pkls.yaml"
import "@k8s/apiextensions-apiserver/pkg/apis/apiextensions/v1/CustomResourceDefinition.pkl"

// source = "package/input/pkl.fn.crossplane.io_pkls.yaml"

// These Converters Provide Type Safety on the Object resource. Without them manifest would be of type "Dynamic"
converters {
["compositeresourcedefinitions.apiextensions.crossplane.io"] {
[List("spec", "versions", "version", "schema", "openAPIV3Schema")] = CustomResourceDefinition.JSONSchemaProps
}
}

// The Package references to be used within the new Module
k8sImportPath = "@k8s" // package://pkg.pkl-lang.org/pkl-k8s/k8s@<version>#

3 changes: 2 additions & 1 deletion internal/function/fn.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ type Function struct {

// RunFunction runs the Function.
func (f *Function) RunFunction(ctx context.Context, req *fnv1beta1.RunFunctionRequest) (*fnv1beta1.RunFunctionResponse, error) {
f.Log.Info("Running function", "tag", req.GetMeta().GetTag())
f.Log.Debug("Running function", "tag", req.GetMeta().GetTag())

rsp := response.To(req, response.DefaultTTL)

Expand Down Expand Up @@ -101,6 +101,7 @@ func (f *Function) RunFunction(ctx context.Context, req *fnv1beta1.RunFunctionRe

renderedManifest, err := evaluator.EvaluateOutputText(ctx, moduleSource)
if err != nil {
f.Log.Debug("Error parsing Pkl file", "error", err)
response.Fatal(rsp, errors.Wrap(err, "error while parsing the Pkl file"))
return rsp, nil
}
Expand Down
219 changes: 145 additions & 74 deletions internal/function/fn_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ import (
var (
workdir, _ = os.Getwd()
pklPackage = fmt.Sprintf("%s/../../pkl/crossplane.contrib.example", workdir)

xr = `{"apiVersion": "example.crossplane.io/v1","kind": "XR","metadata": {"name": "example-xr"},"spec": {}}`
xrStatus = `{"apiVersion": "example.crossplane.io/v1","kind": "XR","status": {"someStatus": "pretty status"}}`
environmentConfig = `{"apiextensions.crossplane.io/environment": {"foo": "bar"}, "greetings": "with <3 from function-pkl"}`

objectWithRequired = `{"apiVersion": "kubernetes.crossplane.io/v1alpha2","kind": "Object","spec": {"forProvider": {"manifest": {"apiVersion": "v1","kind": "ConfigMap","metadata": {"namespace": "crossplane-system"},"data": {"foo": "example-xr","required": "required"}}}}}`
objectWithoutRequired = `{"apiVersion": "kubernetes.crossplane.io/v1alpha2","kind": "Object","spec": {"forProvider": {"manifest": {"apiVersion": "v1","kind": "ConfigMap","metadata": {"namespace": "crossplane-system"},"data": {"foo": "example-xr","required": "i could not find what I needed..."}}}}}`
objectMinimal = `{"apiVersion": "kubernetes.crossplane.io/v1alpha2","kind": "Object","spec": {"forProvider": {"manifest": {"apiVersion": "v1","kind": "ConfigMap","metadata": {"namespace": "crossplane-system"},"data": {"foo": "bar"}}}}}`
)

func TestRunFunction(t *testing.T) {
Expand Down Expand Up @@ -71,14 +79,7 @@ func TestRunFunction(t *testing.T) {
}),
Observed: &fnv1beta1.State{
Composite: &fnv1beta1.Resource{
Resource: resource.MustStructJSON(`{
"apiVersion": "example.crossplane.io/v1",
"kind": "XR",
"metadata": {
"name": "example-xr"
},
"spec": {}
}`),
Resource: resource.MustStructJSON(xr),
},
},
},
Expand All @@ -89,30 +90,141 @@ func TestRunFunction(t *testing.T) {
Ttl: durationpb.New(response.DefaultTTL),
},
Desired: &fnv1beta1.State{
Composite: &fnv1beta1.Resource{},
Resources: map[string]*fnv1beta1.Resource{
"cm-minimal": {
Resource: resource.MustStructJSON(`{
"apiVersion": "kubernetes.crossplane.io/v1alpha2",
"kind": "Object",
"spec": {
"forProvider": {
"manifest": {
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": {
"namespace": "crossplane-system"
},
"data": {
"foo": "bar"
}
}
}
}
}`),
Resource: resource.MustStructJSON(objectMinimal),
},
},
},
},
},
},
"FullFirstRun": {
reason: "The Function should create a full functionResult",
args: args{
ctx: context.TODO(),
req: &fnv1beta1.RunFunctionRequest{
Meta: &fnv1beta1.RequestMeta{Tag: "extra"},
Input: resource.MustStructObject(&v1beta1.Pkl{
Spec: v1beta1.PklSpec{
Type: "local",
Local: &v1beta1.Local{
ProjectDir: pklPackage,
File: pklPackage + "/compositions/steps/full.pkl",
},
},
}),
Context: resource.MustStructJSON(environmentConfig),
Observed: &fnv1beta1.State{
Composite: &fnv1beta1.Resource{
Resource: resource.MustStructJSON(xr),
},
},
},
},
want: want{
rsp: &fnv1beta1.RunFunctionResponse{
Desired: &fnv1beta1.State{
Composite: &fnv1beta1.Resource{
Resource: resource.MustStructJSON(xrStatus),
},
Resources: map[string]*fnv1beta1.Resource{
"cm-one": {
Resource: resource.MustStructJSON(objectWithoutRequired),
Ready: fnv1beta1.Ready_READY_TRUE,
},
},
},
Requirements: &fnv1beta1.Requirements{
ExtraResources: map[string]*fnv1beta1.ResourceSelector{
"ineed": {
ApiVersion: "kubernetes.crossplane.io/v1alpha2",
Kind: "Object",
Match: &fnv1beta1.ResourceSelector_MatchName{
MatchName: "required",
},
},
},
},
Meta: &fnv1beta1.ResponseMeta{
Tag: "extra",
Ttl: &durationpb.Duration{
Seconds: 60,
},
},
Context: resource.MustStructJSON(environmentConfig),
Results: []*fnv1beta1.Result{
{
Severity: fnv1beta1.Severity_SEVERITY_NORMAL,
Message: "welcome",
},
},
},
},
},
"FullCantFindRequirement": {
reason: "The Function should create a full functionResult",
args: args{
ctx: context.TODO(),
req: &fnv1beta1.RunFunctionRequest{
Meta: &fnv1beta1.RequestMeta{Tag: "extra"},
Input: resource.MustStructObject(&v1beta1.Pkl{
Spec: v1beta1.PklSpec{
Type: "local",
Local: &v1beta1.Local{
ProjectDir: pklPackage,
File: pklPackage + "/compositions/steps/full.pkl",
},
},
}),
Context: resource.MustStructJSON(environmentConfig),
Observed: &fnv1beta1.State{
Composite: &fnv1beta1.Resource{
Resource: resource.MustStructJSON(xr),
},
},
ExtraResources: map[string]*fnv1beta1.Resources{
"ineed": {},
},
},
},
want: want{
rsp: &fnv1beta1.RunFunctionResponse{
Desired: &fnv1beta1.State{
Composite: &fnv1beta1.Resource{
Resource: resource.MustStructJSON(xrStatus),
},
Resources: map[string]*fnv1beta1.Resource{
"cm-one": {
Resource: resource.MustStructJSON(objectWithoutRequired),
Ready: fnv1beta1.Ready_READY_TRUE,
},
},
},
Requirements: &fnv1beta1.Requirements{
ExtraResources: map[string]*fnv1beta1.ResourceSelector{
"ineed": {
ApiVersion: "kubernetes.crossplane.io/v1alpha2",
Kind: "Object",
Match: &fnv1beta1.ResourceSelector_MatchName{
MatchName: "required",
},
},
},
},
Meta: &fnv1beta1.ResponseMeta{
Tag: "extra",
Ttl: &durationpb.Duration{
Seconds: 60,
},
},
Context: resource.MustStructJSON(environmentConfig),
Results: []*fnv1beta1.Result{
{
Severity: fnv1beta1.Severity_SEVERITY_NORMAL,
Message: "welcome",
},
},
},
},
},
Expand Down Expand Up @@ -169,36 +281,12 @@ func TestRunFunction(t *testing.T) {
rsp: &fnv1beta1.RunFunctionResponse{
Desired: &fnv1beta1.State{
Composite: &fnv1beta1.Resource{
Resource: resource.MustStructJSON(`{
"apiVersion": "example.crossplane.io/v1",
"kind": "XR",
"status": {
"someStatus": "pretty status"
}
}`),
Resource: resource.MustStructJSON(xrStatus),
},
Resources: map[string]*fnv1beta1.Resource{
"cm-one": {
Resource: resource.MustStructJSON(`{
"apiVersion": "kubernetes.crossplane.io/v1alpha2",
"kind": "Object",
"spec": {
"forProvider": {
"manifest": {
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": {
"namespace": "crossplane-system"
},
"data": {
"foo": "example-xr",
"required": "required"
}
}
}
}
}`),
Ready: fnv1beta1.Ready_READY_TRUE,
Resource: resource.MustStructJSON(objectWithRequired),
Ready: fnv1beta1.Ready_READY_TRUE,
},
},
},
Expand All @@ -219,12 +307,7 @@ func TestRunFunction(t *testing.T) {
Seconds: 60,
},
},
Context: resource.MustStructJSON(`{
"apiextensions.crossplane.io/environment": {
"foo": "bar"
},
"greetings": "with <3 from function-pkl"
}`),
Context: resource.MustStructJSON(environmentConfig),
Results: []*fnv1beta1.Result{
{
Severity: fnv1beta1.Severity_SEVERITY_NORMAL,
Expand All @@ -250,13 +333,7 @@ func TestRunFunction(t *testing.T) {
}),
Desired: &fnv1beta1.State{
Composite: &fnv1beta1.Resource{
Resource: resource.MustStructJSON(`{
"apiVersion": "example.crossplane.io/v1",
"kind": "XR",
"status": {
"someStatus": "pretty status"
}
}`),
Resource: resource.MustStructJSON(xrStatus),
},
},
},
Expand All @@ -265,13 +342,7 @@ func TestRunFunction(t *testing.T) {
rsp: &fnv1beta1.RunFunctionResponse{
Desired: &fnv1beta1.State{
Composite: &fnv1beta1.Resource{
Resource: resource.MustStructJSON(`{
"apiVersion": "example.crossplane.io/v1",
"kind": "XR",
"status": {
"someStatus": "pretty status"
}
}`),
Resource: resource.MustStructJSON(xrStatus),
},
},
Results: []*fnv1beta1.Result{
Expand Down
1 change: 1 addition & 0 deletions internal/pkl/reader/crossplane_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ func (f *CrossplaneReader) BaseRead(url url.URL) ([]byte, error) {
return nil, err
}

f.Log.Debug("compositionRequest", "request", requestYaml)
return requestYaml, nil
default:
return nil, fmt.Errorf("unsupported path")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ desired = request.desired

results {
new {
severity = SEVERITY_WARNING
severity = "Warning"
message = "I am an Event from Pkl!"
}
}
4 changes: 2 additions & 2 deletions pkl/crossplane.contrib.example/compositions/steps/full.pkl
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,13 @@ desired {
}
}
}
ready = READY_TRUE
ready = true
}
}
}
results {
new {
severity = SEVERITY_NORMAL
severity = "Normal"
message = "welcome"
}
}
Expand Down
Loading