carvel-dev / ytt

YAML templating tool that works on YAML structure instead of text
https://carvel.dev/ytt
Apache License 2.0
1.67k stars 136 forks source link

ytt Value different than starlark.Value #622

Closed johnSchnake closed 2 years ago

johnSchnake commented 2 years ago

Hoping for some direction/clarity:

I'm using ytt as a library in a project where I'm trying to add a group of different modules together; some from ytt (e.g. the semver, assert, or ipaddr modules) alongside the modules created via isopod modules (which provide methods like kube.get to get k8s resources).

However, whenever I try to combine these two, I get issues because the ytt library extended/modified the starlark-go types so that now I get:

cmd/root.go:64:17: cannot use assertMod (type "github.com/k14s/starlark-go/starlark".Value) as type "go.starlark.net/starlark".Value in assignment:
    "github.com/k14s/starlark-go/starlark".Value does not implement "go.starlark.net/starlark".Value (wrong type for Truth method)
        have Truth() "github.com/k14s/starlark-go/starlark".Bool
        want Truth() "go.starlark.net/starlark".Bool

The types are just fundamentally different types so is there an approach to using these so that I use both builtins?

I'm trying to effectively just combine the StringDict objects, but they hold different Value types. Once I get all the builtins in the StringDict I'm just calling starlark.ExecFile(..., allBuiltins)

I'm new to starlark so I'd appreciate the help if I'm missing something basic about how to work with it/ytt as libraries.

cari-lynn commented 2 years ago

Hey @johnSchnake, I would love to hear more on this use case. Can you share examples or link to the code on where you are running into this issue? Seeing the code may help us understand how it would be possible to use these differing Starlark values together.

We have some docs that mention and give examples of our current programmatic API. We currently don't commit to a 'formal API' and interfaces may change, providing equivalent behavior.

We are interested in learning more about your use case for this as it can help inform this project in how to mature our programmatic API. Can you share that here?

johnSchnake commented 2 years ago

So I'm trying to just utilize the library functions for starlark from ytt and isopod. Isopod was built using the default starlark-go library but since ytt uses its own modified github.com/k14s/starlark-go/starlark then nothing can work together.

The point is that isopod had built some great functions kube.[get|exists|delete|put] that allow you to easily work with k8s. ytt had some great utility libraries for assertions and other simple data types like ip addresses, regep, etc. I'd love to be able to use both but it doesn't seem like there would be a way.

The code looked like:

pkgs := skycfg.UnstablePredeclaredModules(&protoRegistry{})
k := kube.New(c.Host, dC, dynC, &http.Client{Transport: t}, true, false, false, []string{"metadata.managedFields"})
pkgs["kube"]=k
pkgs["assert"]=yttlibrary.AssertAPI["assert"]

So the left and right sides both refer to starlark.StringDict, and they both look like they have the same methods. But since the underlying types are technically different, Go just sees them as having different signatures and so they can't be mixed.

The execution line: _, err = starlark.ExecFile(starThread, "script.star", nil, pkgs) needs a single object that has all the predeclared functions and such and it would obviously want the types that correspond to the starlark library being used for the ExecFile call.

It seems I just have to choose one and port the functions I want over unless you have another alternative?

Since there was a lot of Isopod that I did not want, I actually spent time this weekend pulling out just the kube methods I want so I have something functional now but I had to just choose one library (yours) to use as the 'true' starlark and ensure only those types were used. It wouldn't be unusual for me to find another cool library that I'd like to integrate though and then I'd have to port that code to also use the same starlark. It would still be ideal to have a way to mix them somehow or if ytt was able to use the vanilla starlark-go library (which I assume isnt possible).

pivotaljohn commented 2 years ago

Thanks for that additional context, @johnSchnake. 👍🏻

The changes we've made in our fork are actually rather isolated: it's mostly about redefining a "block" as being what lies between a starting token and an end (rather than indentation). Here's the delta: https://github.com/vmware-tanzu/starlark-go/compare/master...ytt-1-jul-2020

We have made genuine extensions and most of that code lives here: https://github.com/vmware-tanzu/carvel-ytt/tree/develop/pkg/template/core

It seems I just have to choose one and port the functions I want over unless you have another alternative?

If by "port" you mean copy and adjust the imports in a separate codebase... one thing I can think of is writing adapters between the two modules and maintain wrappers from the source to the target runtime. Naively, I suspect that after the initial investment, wrapping new libraries would be somewhat rote.

🤔