Open nbjohnson opened 1 year ago
@nbjohnson: This issue is currently awaiting triage.
SIG CLI takes a lead on issue triage for this repo, but any Kubernetes member can accept issues by applying the triage/accepted
label.
The triage/accepted
label can be added by org members by writing /triage accepted
in a comment.
I believe you are correct that it isn't possible to target that field with the prefix or suffix transformers. Those transformers can traverse through lists, but they require the terminal node to be a scalar. The code for the traversal is here, and the code that expects the field we land on to be a scalar is here.
/retitle Prefix/Suffix transformers cannot target list elements /triage under-consideration /kind feature
As an admittedly verbose workaround, the replacements transformer is capable of targeting that field. You'll just need to make sure the prefix transformer runs first, which you can do either but using both through the transformers
field, or by putting your custom fieldSpecs into `configurations. For example:
# kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- resources.yaml
namePrefix: prefix-
configurations:
- my-config.yaml
replacements:
- path: replacement.yaml
# my-config.yaml
namePrefix:
- path: spec/rules/host
kind: Ingress
- path: spec/tls/secretName
kind: Ingress
nameSuffix:
- path: spec/rules/host
kind: Ingress
- path: spec/tls/secretName
kind: Ingress
# replacement.yaml
source:
kind: Ingress
name: test-ingress
fieldPath: .spec.rules.0.host
targets:
- select:
name: test-ingress
kind: Ingress
fieldPaths:
- spec.tls.0.hosts.0
Result:
kind: Ingress
metadata:
foo: bar
name: prefix-test-ingress
namespace: test
spec:
rules:
- host: prefix-test.fakedomain.com
tls:
- hosts:
- prefix-test.fakedomain.com
secretName: prefix-test-secret
@KnVerey I have a similar problem, but a bit more complex. I need a dynamic prefix for my istio VirtualService in order to use it for PR environments. foo- prefix wasn't substituted. Also I see that argocd-vault-plugin wasn't able to substitute value, but it is not important at the moment.
kustomization.yaml:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
configurations:
- namereference.yaml
transformers:
- replacement1.yaml
- prefixsuffix.yaml
- replacement2.yaml
namereference.yaml:
nameReference:
- kind: Service
fieldSpecs:
- kind: Namespace
path: metadata/name
replacement1.yaml:
apiVersion: builtin
kind: ReplacementTransformer
metadata:
name: prefix
replacements:
- source:
kind: VirtualService
fieldPath: metadata.name
targets:
- select:
kind: PrefixSuffixTransformer
fieldPaths:
- prefix
prefixsuffix.yaml
apiVersion: builtin
kind: PrefixSuffixTransformer
metadata:
name: host
prefix: "foo-"
fieldSpecs:
- kind: VirtualService
path: metadata/annotations/host
replacement2.yaml:
apiVersion: builtin
kind: ReplacementTransformer
metadata:
name: host
replacements:
- source:
kind: VirtualService
fieldPath: metadata.annotations.host
targets:
- select:
kind: VirtualService
fieldPaths:
- spec.hosts.0
virtualservice.yaml (in base):
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: example
annotations:
host: <path:secret#domain>
spec:
hosts:
- "<path:secret#domain>"
gateways:
- istio-gateway/istio-gateway
http:
- route:
- destination:
host: example
port:
number: 8000
Actual result:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
annotations:
host: 'foo-<path:secret#domain>'
labels:
app.kubernetes.io/instance: example-pr-10
name: example-pr-10
namespace: example-pr-10
spec:
gateways:
- istio-gateway/istio-gateway
hosts:
- 'foo-<path:secret#domain>'
http:
- route:
- destination:
host: example
port:
number: 8000
Expected result:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
annotations:
host: 'example-pr-10.example.com'
labels:
app.kubernetes.io/instance: example-pr-10
name: example-pr-10
namespace: example-pr-10
spec:
gateways:
- istio-gateway/istio-gateway
hosts:
- 'example-pr-10.example.com'
http:
- route:
- destination:
host: example
port:
number: 8000
@KnVerey Thanks for the suggestion, I was actually trying to use the replacement transformer similar to your suggestion as a workaround, but I can't quite get it to work with my situation. I want it to be able to be general so in this case if there are multiple ingresses it will update all of them. However, I keep getting the error Error: multiple matches for selector Ingress.[noVer].[noGrp]/[noName].[noNs]:.spec.rules.0.host
as I leave out the name compared to your example. I assume this is just a limitation of the replacement transformer, but is it possible to make the replacement transformer relative so it can work generally across multiple ingresses?
apiVersion: builtin
kind: ReplacementTransformer
metadata:
name: configReplacement
replacements:
- source:
kind: Ingress
fieldPath: .spec.rules.0.host
targets:
- select:
kind: Ingress
fieldPaths:
- spec.tls.0.hosts.0
@IvanovOleg at a glance I see two possible issues with the provided configuration. One is that transformers in the transformers
field require fieldspecs to be provided as part of the transformer yaml; anything provided through configurations
is overridden when using that method. Second, you seem to be attempting to modify the transformer config using replacements. That is possible, but it's an advanced pattern called "transformed tranformers" that requires a bit of a different setup, which you can read about here: https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/#transformed-transformers.
@nbjohnson that error is coming from having multiple ingresses targeted by the source
field, and that is indeed a limitation of how the transformer works. It starts by finding the one specific value to use as the replacement, then identifies all the target spots in one or more target objects and inserts that value. There's no connection between the source and the target. It sounds like what you want is a self-reference feature, which is not currently available but does sound useful. I think there's enough to think about that it should be proposed in a mini enhancement proposal if you're interested.
@KnVerey Are you suggesting opening an enhancement proposal for a change to prefix/suffix transformer in order to be able to target a terminal node that in non-scalar? Or for a proposal on adding a self-reference feature for the replacements transformer? Or for a discussion on what might be overall the most useful between the two, while also solving my issue? Sorry just want to clarify what proposal you are suggesting I open
Are you suggesting opening an enhancement proposal for a change to prefix/suffix transformer in order to be able to target a terminal node that in non-scalar? Or for a proposal on adding a self-reference feature for the replacements transformer?
I meant for the self-reference feature for the replacements transformer. The ability to target non-scalar terminal nodes has precedent in other transformers in terms of what the fieldspecs would look like, so there's not much to design there--this issue itself is sufficient for tracking the feature request.
Or for a discussion on what might be overall the most useful between the two, while also solving my issue?
Thinking more about your goal, what bothers me about both solutions is that they both update the target fields pretty blindly. Say your hosts
list contained some entries that shouldn't be prefixed. Even if we implemented both options discussed so far, they would only be capable of updating all the entries, or at best specific entries by individually specified indexes (not ideal, since order != identity). The self-reference approach points out something important: we are dealing with several fields that all actually refer to the same name and therefore need to be updated together. Kustomize is able to do that for object names referenced in arbitrary places, including scalar lists. So, another approach would be to use a fake, local-only Kind to tie all these name references together, including any you may have in objects other than Ingress. This almost works, but only if the fake objects are not stripped--I think this is a bug, and one that is trivial (unlike the other changes we've been talking about so far) to fix. I threw up a quick PR with the fix, and it includes a test demonstrating this technique. PTAL--I'm curious to hear what you think of this approach, and whether it would work for you in practice: https://github.com/kubernetes-sigs/kustomize/pull/4895
@KnVerey That local reference method is interesting, I don't know too much about it and can't seem to find docs on it. Seems quite useful being able to directly reference a pairing like that and have it be able to differentiate between different hosts. However, at least for my need I am not sure that will work as that requires knowledge of the hostnames. In my situation I do not have advance knowledge of the hostnames, I just need to prefix all that I receive, so unless there is a way for me to extract all of the hostnames and generate those fake objects on the fly not sure it helps my situation but might be useful for someone else's scenario. I understand the hesitation with only being able to update all the entries, but at least for my need right now that is exactly what I need to do. I just want to be able to target all Ingresses and update all of their name references, so metadata name, tls secret name, and the hostnames. I understand that is probably undesirable in most scenarios for people, but the prefix/suffix transformer is able to target names indiscriminately, but just not the tls hostname in Ingress.
@KnVerey Just want to follow-up, any additional thoughts on this? I do need to be able to mass prefix all parts of my ingress hostnames
@KnVerey Wanted to follow-up as I am still in need of being able to target Ingress spec.tls.*.hosts.*
to be able to prefix. Your above name reference example does look interesting, but I don't think it would work in my case, that looks like I need to define IngressHost ahead of time, but in my situation I am generating these on the fly, so I do not know the hostname ahead of time to define that, unless there is a way to fetch all of the Ingress hostnames and generate those on the fly.
I have a situation where I want to add a suffix to containers/0/env/0/secretKeyRef/name
It works for metadata/name
but not for the env.
---
apiVersion: builtin
kind: PrefixSuffixTransformer
metadata:
name: networkSuffix
suffix: "-goerli"
fieldSpecs:
- kind: Deployment
path: metadata/name
- kind: Deployment
path: spec/template/spec/containers/0/env/0/valueFrom/secretKeyRef/name
I get:
Error: accumulating components: accumulateDirectory: "recursed accumulation of path 'postgraphile/components/goerli': considering field 'spec/template/spec/containers/0/env/0/valueFrom/secretKeyRef/name' of object Deployment.v1.apps/postgraphile-goerli.namespace: visit traversal on path: [0 env 0 valueFrom secretKeyRef name]: fieldName: 0: wrong node kind: expected SequenceNode but got MappingNode
...
The Kubernetes project currently lacks enough contributors to adequately respond to all issues.
This bot triages un-triaged issues according to the following rules:
lifecycle/stale
is appliedlifecycle/stale
was applied, lifecycle/rotten
is appliedlifecycle/rotten
was applied, the issue is closedYou can:
/remove-lifecycle stale
/close
Please send feedback to sig-contributor-experience at kubernetes/community.
/lifecycle stale
The Kubernetes project currently lacks enough active contributors to adequately respond to all issues.
This bot triages un-triaged issues according to the following rules:
lifecycle/stale
is appliedlifecycle/stale
was applied, lifecycle/rotten
is appliedlifecycle/rotten
was applied, the issue is closedYou can:
/remove-lifecycle rotten
/close
Please send feedback to sig-contributor-experience at kubernetes/community.
/lifecycle rotten
~I'm having the same problem with spec.tls.hosts.*
with replacements, while spec.rules.*.host
compiles as expected.~
My bad – messed up pathspec for replacement. It works 😅
/remove-lifecycle rotten
Have you found a workaround for this feature ? I'm trying to achieve the same operation as you. (Adding a suffix to the TLS host of an Ingress dynamically, as it may contain multiple ones)
@Zegorax hey! I personally ended up switching to grafana tanka/jsonnet entirely, with no issues so far. Requires some brain reconfiguration, yes, but totally worth it.
@endersonmaia You should use , see #4392 [0]
instead of /0
Edit: It doesn't work
Kustimize is a serious tool, but the simplest task - how to add a suffix to a dynamically generated service name and add this value to the first element of the array in the hosts field in another kind - seems impossible.
This ticket is the latest point in my journey of trying to resolve this issue. I’ll subscribe, what if someday this will become possible?
The Kubernetes project currently lacks enough contributors to adequately respond to all issues.
This bot triages un-triaged issues according to the following rules:
lifecycle/stale
is appliedlifecycle/stale
was applied, lifecycle/rotten
is appliedlifecycle/rotten
was applied, the issue is closedYou can:
/remove-lifecycle stale
/close
Please send feedback to sig-contributor-experience at kubernetes/community.
/lifecycle stale
The Kubernetes project currently lacks enough active contributors to adequately respond to all issues.
This bot triages un-triaged issues according to the following rules:
lifecycle/stale
is appliedlifecycle/stale
was applied, lifecycle/rotten
is appliedlifecycle/rotten
was applied, the issue is closedYou can:
/remove-lifecycle rotten
/close
Please send feedback to sig-contributor-experience at kubernetes/community.
/lifecycle rotten
/remove-lifecycle rotten
@endersonmaia This is probably way too late. However, it may help some others who read your post and are possibly experiencing the same issue as you did.
The following should work:
---
apiVersion: builtin
kind: PrefixSuffixTransformer
metadata:
name: networkSuffix
suffix: "-goerli"
fieldSpecs:
- kind: Deployment
path: metadata/name
- kind: Deployment
path: spec/template/spec/containers[]/env[]/valueFrom/secretKeyRef/name
Note that there is no path separator /
between e.g. containers and the pair of square braces.
You cannot use an index inside the braces to target a specific element of the array / list e.g. [0]
. Nor can you target an element of an array / list by using some match criteria inside the braces e.g. [name=foo].
Strange that this doesn't work quite the same way as other transformers....
Any workarounds for this? I'm struggling with the same problem with no apparent solution.
Ciao everyone,
@KnVerey is there any update about this one ? I'm still stuck with some automated ArgoCD workloads due to this. Thanks a lot in advance!
I am trying to use a Prefix/Suffix transformer on my Ingress TLS hosts hostname, but it cannot seem to target that field. Below is my sample transformer and ingress configs. I have tried many variations on
spec/tls/hosts
but I cannot seem to target that list hostname object. The key here is I want to be able to prefix any name, hostname, or secretNames that are listed and I can get the others just not this last one. Any help would be appreciated as I know other people have had issues with list objects previously, not sure if I am missing something or if this is not currently possible.