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

Discussion: Add a way to check if an external variable is defined #1252

Open
sabeechen opened this issue Nov 30, 2024 · 3 comments
Open

Discussion: Add a way to check if an external variable is defined #1252

sabeechen opened this issue Nov 30, 2024 · 3 comments

Comments

@sabeechen
Copy link
Contributor

I'm making an issue to discuss this because I'm not entirely sure if the idea I'm proposing is aligned with Tanka's goals. What I'd like to add is a native method that checks if an external variable was passed in, the intention being to allow external variables to assume a default value if not otherwise specified.

Example Use Case - default value for image tags

main.jsonnet

{
 imageTag:: if std.native('hasExtVar')('imageTag') then std.extVar('imageTag') else 'latest',
 apiVersion: 'tanka.dev/v1alpha1',
 kind: 'Environment',
 metadata: {
   name: "testing",
 },
 spec: {
   apiServer: 'https://localhost',
   namespace: 'default',
 },
 data: {
   apiVersion: 'v1',
   kind: 'Deployment',
   metadata: {
     name: 'MyDeployment',
   },
   spec: {
     replicas: 3,
     template: {
       spec: {
         containers: [
           {
             name: 'MyContainer',
             image: 'myImage:' + $.imageTag,
           },
         ],
       },
     },
   }
 },
}

My organization is in the midst of migrating a very large number of manifests from kustomize to tanka, and while we have really appreciated its breadth of features, there are times having this would make the flexibility we're trying to achieve a lot cleaner. So much so that we're considering maintaining a fork of tanka for use internally that has this added.

From reading the Jsonnet Language Specification's section on external variables and some discussion in issues it seems to me that this is a feature intentionally missing from jsonnet, is that also the case for Tanka?

I've created an example PR against a fork implementing the changes necessary, but I didn't want to be "that guy" and just create a PR upstream advocating for something the project is philosophically opposed to without checking in with the maintainers.

@Duologic
Copy link
Member

Top-Level Arguments (TLAs) are much better suited for this, they take the form of function arguments which can also have a default value.

@sabeechen
Copy link
Contributor Author

When all your files are in a single/simple tanka project, I'd 100% agree. I've actually got a PR open right now against tanka that facilitates that use case (its currently broken in some subtle ways when using defaults) because thats how we're doing it right now.

The problem we run into is that I'm seeing this become unmaintainable in two related ways:

  • Our project has ~50 possible inputs, and that number is growing as we port more over from kustomize. For any given tk export we only want to override a handful of defaults (often 0). Maintaining this as a flat list of arguments in main.jsonnet and plumbing it through everywhere we want it to go is tedious and error prone.
  • We maintain a jsonnet library in a private repo for things like a base Deployment, Ingress, etc which need to make use of the TLA's values. This means each of our projects that imports the TLA's needs to have it plumbed through to the base library. So when we add a new variable in the base library, we also have to plumb it through from the main.jsonnet in each of the N entrypoints form each tanka project that uses it. Its tedious and error prone to reproduce this logic all over the place, a loose coupling with hasExtVarwould let us inherit new functionality from the base library without having to plumb it through.

So in my contrived example above, 100% agree a TLA is the way to go. In my org's real use-case where the manifests are spread across many different repos/projects and a lot of flex is needed to handle all the different use cases (eg different monitoring annotations, various states of migration from one backend to another, discrepancies between different cluster versions, etc) I think the native method would be a lot easier to maintain.

@Duologic
Copy link
Member

Duologic commented Dec 1, 2024

If there are that many inputs, then I think extVars are not your best solution here, how are you ever going to reproduce something in a reasonable way?

We also have many environments, the way we handle differences is by storing them as values in a file (JSON or jsonnet), that way we can track what has changed.

Can you expand further on what the source is for these extVar values? The data must be stored somewhere that could be imported in a more conventional way into jsonnet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Triage
Development

No branches or pull requests

2 participants