serving icon indicating copy to clipboard operation
serving copied to clipboard

Add string manipulation functions to domain template

Open braunsonm opened this issue 1 year ago • 16 comments

/area API

Describe the feature

I have an environment where multiple working tenants are deployed in the same cluster and would like to format my domains like so:

myfunc-project.dev.example.com
myfunc-project.prod.example.com

Where myfunc is deployed in the namespace project-dev, project-prod, etc. Right now in order to do this automatically I would need to create a domain template with multiple if/else blocks matching the namespace to a specific domain.

{{if eq .Namespace "project-dev"}}
{{.Name}}-project.dev.example.com
{{else if eq .Namespace "project-prod"}}
{{.Name}}-project.prod.example.com
{{else if eq .Namespace "project2-dev"}}
{{.Name}}-project2.dev.example.com
{{else if eq .Namespace "project2-prod"}}
{{.Name}}-project2.prod.example.com
{{else}}
{{.Name}}.example.com
{{end}}

I know using annotations is possible but unfortunately func deploy does not allow setting labels or annotations, and it would be nice if this was handled for the user automatically by the platform operators.

I would like to be able to simply remove the -<environment> suffix from my namespace and use it in the domain. I'm proposing adding some string manipulation functions to the template. Specifically

funcs := map[string]any{
    "contains":  strings.Contains,
    "hasPrefix": strings.HasPrefix,
    "hasSuffix": strings.HasSuffix,
    "replace": strings.Replace}

Which would allow a template of

{{if hasSuffix .Namespace "-dev"}}
{{.Name}}-{{ replace .Namespace "-dev" "" 1}}.dev.example.com
{{end}}

Which is much more manageable.

I think it would be as simple as adding .Funcs(funcs) to this line: https://github.com/knative/serving/blob/main/pkg/reconciler/route/domains/domains.go#L115

If accepted, I wouldn't mind making a PR for this. Thanks!

braunsonm avatar Feb 15 '24 20:02 braunsonm

It seems like you want a different template per namespace.

Maybe extending the config to support that then trying to do this with templates would the easier approach. This would mirror already what we're doing with domain name selection.

dprotaso avatar Mar 05 '24 21:03 dprotaso

@dprotaso that would work too.

Not sure what you mean about the domain name selection though, as far as I know that only selects on labels not based on the namespace.

braunsonm avatar Mar 05 '24 21:03 braunsonm

This would mirror already what we're doing with domain name selection.

You're right we do domain selection based on labels from the knative service resource. But now with the new config it's easy enough to extend it to have something like a namespaceSelector

dprotaso avatar Mar 07 '24 23:03 dprotaso

Up to you. I think adding namespace selectors to the domain template and domains configuration is a more elegant solution. Even more so if the configurations were consistent formats where you could match labels or namespaces. It would be more user friendly.

But string manipulation would certainly be easier to implement.

braunsonm avatar Mar 08 '24 00:03 braunsonm

This issue is stale because it has been open for 90 days with no activity. It will automatically close after 30 more days of inactivity. Reopen the issue with /reopen. Mark the issue as fresh by adding the comment /remove-lifecycle stale.

github-actions[bot] avatar Jun 06 '24 01:06 github-actions[bot]

/remove-lifecycle stale

braunsonm avatar Jun 06 '24 01:06 braunsonm

I'm going to close this out but feel free to create a new feature request for namespaceSelector in the domain selection

dprotaso avatar Jun 06 '24 13:06 dprotaso

I'm looking more at the label selectors in the domain configmap and I'm not sure it would be a good solution after all for the example I gave. The configuration would still have to be pretty huge and repetitive.

{{.Name}}-project1.dev.example.com: |
  namespaceSelector:
    name: project1-dev
{{.Name}}-project1.test.example.com: |
  namespaceSelector:
    name: project1-test
{{.Name}}-project2.dev.example.com: |
  namespaceSelector:
    name: project2-dev

Whereas some string manipulation functions would reduce this kind of repetitive configuration considerably. Is there a reason you don't think that is a good idea? @dprotaso or do you have a better suggestion on a way forward?

braunsonm avatar Jun 06 '24 16:06 braunsonm

what's {{.Name}} in that example?

The config-domain is just the base domain selection.

project1.dev.example.com: |
  namespaceSelector:
    name: project1-dev
project1.test.example.com: |
  namespaceSelector:
    name: project1-test
project2.dev.example.com: |
  namespaceSelector:
    name: project2-dev

And then pair it with the domain template - https://github.com/knative/networking/blob/41aa2087242da0af0b1fee6721882fc0aed1b87e/config/config-network.yaml#L109

You could then make your domain template the following

"{{.Name}}-{{.Domain}}"

This would give you isolation since you've codified the namespace into the base domain

dprotaso avatar Jun 06 '24 16:06 dprotaso

@dprotaso yea that would work but would be even more verbose than the current solution. So I don't see it as a real improvement.

Edit: It's also more difficult to handle the else case that I listed above unless you built a very long if statement with all the namespaces names in it to decide if the pattern should be {{.Name}}-{{.Domain}} or {{.Name}}.{{.Domain}}

braunsonm avatar Jun 06 '24 17:06 braunsonm

difficult to handle the else case that I listed above

I believe the way it works is we always pick the longest selector - so you could add an empty selector and it would be your fallback which would act like your else

dprotaso avatar Jun 06 '24 19:06 dprotaso

The else would need to be in the domain template not the domain configmap (note that dot instead of a dash). So I'm not sure if that would work.

So where are we at with this issue? Is this not going to be accepted to Knative? If so I don't think I intend on making a new feature request with your suggestion as I mentioned it is actually more verbose than the current workaround.

braunsonm avatar Jun 06 '24 20:06 braunsonm

I'll re-open the issue and see if there's more input from the other maintainers

I'm leaning towards your idea of adding the funcs

cc @ReToCode @skonto

dprotaso avatar Jun 06 '24 21:06 dprotaso

Hm I'm a bit hesitent about adding more dynamics in general. This increases the (already quite high) complexity in various places while the value added is limited (in my personal opinion). For example the domain pattern in https://github.com/knative/serving/issues/14903#issue-2137435784 also ends up adding new challenges to create certificates. There were good reasons for ingress solutions (OpenShift for example) to rely on default domains with just one subdomain (like *.apps.mycluster.com) with the ability to overwrite this for specific services.

ReToCode avatar Jun 07 '24 06:06 ReToCode