flipt-io / cup

Git Contribution Automation
https://cup.flipt.io
Apache License 2.0
76 stars 1 forks source link

feat: Add `Transformer` type #69

Closed yquansah closed 12 months ago

yquansah commented 1 year ago

Transformers

The motivation for adding a Transformer type is to template out a definition of a JSON payload that can be materialized into an actual one based on the ResourceDefintion.

The main use case here that I thought of is abstracting away complex details of a definition. For instance, a Kubernetes Deployment type probably has more details that a developer like myself does not care about, and would rather not have to touch those parts of a definition.

Transformers will allow operators of cup to create standards/conventions of a rather complex type, so consumers of the API can focus on the parts that matter.

Storage

Right now the entire payload that is stored is the transformed payload that is nested under the key "transformed", and the actual Resource definition with the values that is nested under the key "definition".

The ResourceDefinition will also be given the label "transformed", which will have a value of "yes", so consumers of the API can know if this was a transformed Resource from the service perspective.

vercel[bot] commented 1 year ago

The latest updates on your projects. Learn more about Vercel for Git ↗︎

1 Ignored Deployment | Name | Status | Preview | Updated (UTC) | | :--- | :----- | :------ | :------ | | **cup** | ⬜️ Ignored ([Inspect](https://vercel.com/flipt/cup/8r7rNzN1rWC94X4ihLux1DMzxzv5)) | | Oct 2, 2023 4:17pm |
GeorgeMac commented 1 year ago

@yquansah I like the sentiment, however, I am not sure cup needs to support templating the creation of RDs directly as another top-level configuration concept. I think we might be putting the cart before the horse, and maybe further confusing the benefits of writing a custom controller vs automation around resource definition authoring as you have created here.

I think as a configurer of cup itself you can't really escape (all) the details of the resource definition itself. Having a templating engine before the RD just allows you to define the RD in an alternate type to that of the current RD type. Your template definition still needs to template out all the fields of the resulting RD, so you still have to do all that work. This might reduce some boiler plate for producing lots of similar RDs, however, I wonder at this point: what is the cup configurer is trying to achieve? given they're making lots of RDs in this way.

Quick aside: cup was never really intended to just expose, for example, every k8s resource as its own cup resource. Supporting this was just a way to quickly demonstrate cup with something familiar and similar to the cup API resource envelope (e.g. k8s Deployment).

Really, a cup configurer should be able to define their own RD, which encapsulates their higher-level configuration needs. The RD should be the consumer contract, which hides the complexity from the end consumer:

apiVersion: myservice/v1
metadata:
  namespace: ecommerce
  name: shoppingcart
spec:
  replicas: 5
  env:
    SOME_CONFIG: var
  file:
    some_config: file

The cup configurers job is to reduce their complexity to this, for their end users. Sadly this means understanding the complexity at this level (someone has to though). Not to say that we cant help folks going forwards and make this simpler.

Really this is where controllers come into play. This is where you can translate the API contract into the formats stored in Git. I think with cup we really want to push the transformation aspects into the controller layer and keep them there.

WRT to templating RDs, if required, I think this can easily be solved with whatever templating tool a cup configurer desires (Go templates, Jsonnet, CUE and so on) and the resulting RD just passed to cup.

Does this make sense? Am I missing anything?

GeorgeMac commented 1 year ago

One thing I think that would be useful would be to support some level of templating the API resource (like this, without the top-level resource, just as fields in the controller) in the Template type controller.

Right now the template controller maps the API resource 1:1 to a file on disk (and just in JSON). The templates are just used to pick a name for the file / folders.

What would be nice is a way to transform the API payload into something else on disk via (simpler) configuration. This is a little more involved than just a template as it needs to be a two-way transformation (API <-> Disk). Might be possible with a pair of templates + encoding format.

Currently, this is where the WASM controller shines and gives the cup operator the most flexibility. However, there likely exist a few flavours of more constrained, but generally useful configuration driven alternatives.

yquansah commented 1 year ago

@GeorgeMac 100% agreed. Basically for the controller is the piece that sits in the middle doing the heavy lifting of translating/de-translating things from the storage layer which is the ultimate source of truth. I agree with this totally.