Closed FernandoMiguel closed 1 year ago
What Argo CD version are you running?
And when do you get the error? On refresh, sync, etc.?
Straight way on refresh. On sync there's a similar but slightly different error.
A version detail can be found on another ticket I opened this week https://github.com/argoproj/argo-cd/issues/14718
I'm surprised by the error message, because (based on a quick search of source) it doesn't seem to be coming from Argo CD. I wonder if it could be coming from Helm.
Is that the full text of the error message? Maybe there's corresponding logging in the repo-server or application-controller which may be helpful.
Thanks for looking into this I'll repro this again tomorrow and try to gather full logs and error messages. Anything in particular that I should be looking for?
FYI although I did not deploy our test chart from helm cli, I did not a dry run before investing time into coding this, and at least there, the output was what I expected.
Having anchors in a single file does work very well on Argo too. Just seems that if you do merge one file with the pointers and another with the destination anchor, something in Argo rendering fails to see it as a single merged file. I did try in both orders of precedence just to be sure, and made no difference, and I think showed similar error messages
Yeah, at the end of the day Argo CD just sends the valueFiles
strings as args to helm template
. afaik Argo CD doesn't make any attempt itself to parse the value files. But I could be missing something.
Hmm. I actually do see where we unmarshal the individual values files when loading the App Details page. That would be an issue. But shouldn't be an issue on refresh.
{
"Version": "v2.7.6+00c914a.dirty",
"BuildDate": "2023-06-20T20:51:13Z",
"GitCommit": "00c914a948d9e8ad99be8bd82a368fbdeba12f88",
"GitTreeState": "dirty",
"GoVersion": "go1.19.10",
"Compiler": "gc",
"Platform": "linux/amd64",
"KustomizeVersion": "v5.0.1 2023-03-14T01:32:48Z",
"HelmVersion": "v3.11.2+g912ebc1",
"KubectlVersion": "v0.24.2",
"JsonnetVersion": "v0.19.1"
}
once i removed the anchors from the values.yaml i got this from the applicationset
HEALTH DETAILS
child generator returned an error on parameter generation: failed to get params for second generator in the matrix generator: child generator returned an error on parameter generation: unable to process file 'base/kubecost/values.yaml': unable to parse file: error converting YAML to JSON: yaml: unknown anchor 'roleArn' referenced
values.yaml
x-anchors:
clustername: &clustername alpha-mt
argo:
clustername:
- *clustername
cost-analyzer:
serviceAccount:
annotations:
eks.amazonaws.com/role-arn: *roleArn
anchors-values.yaml
x-anchors:
roleArn: &roleArn arn:aws:iam::XXX:role/XXX
projectID: &projectID 1234
these two lines were below x-anchors:
in the values.yaml, and once i removed, argo complained it couldnt find roleArn
Can you post your generator config?
kubecost is showing the following
rpc error: code = Unknown desc = `helm template . \
--name-template alpha-mt-kubecost \
--namespace kubecost \
--kube-version 1.27 \
--values .common/values.kubecost.yaml \
--values .base/kubecost/anchors-values.yaml \
--values .base/kubecost/values.yaml \
--api-versions admissionregistration.k8s.io/v1 \
--api-versions admissionregistration.k8s.io/v1/MutatingWebhookConfiguration \
--api-versions admissionregistration.k8s.io/v1/ValidatingWebhookConfiguration \
--api-versions apiextensions.k8s.io/v1 \
--api-versions apiextensions.k8s.io/v1/CustomResourceDefinition \
--api-versions apiregistration.k8s.io/v1 \
--api-versions apiregistration.k8s.io/v1/APIService \
--api-versions apps/v1 \
--api-versions apps/v1/ControllerRevision \
--api-versions apps/v1/DaemonSet \
--api-versions apps/v1/Deployment \
--api-versions apps/v1/ReplicaSet \
--api-versions apps/v1/StatefulSet \
--api-versions autoscaling/v1 \
--api-versions autoscaling/v1/HorizontalPodAutoscaler \
--api-versions autoscaling/v2 \
--api-versions autoscaling/v2/HorizontalPodAutoscaler \
--api-versions batch/v1 \
--api-versions batch/v1/CronJob \
--api-versions batch/v1/Job \
--api-versions certificates.k8s.io/v1 \
--api-versions certificates.k8s.io/v1/CertificateSigningRequest \
--api-versions coordination.k8s.io/v1 \
--api-versions coordination.k8s.io/v1/Lease \
--api-versions crd.k8s.amazonaws.com/v1alpha1 \
--api-versions crd.k8s.amazonaws.com/v1alpha1/ENIConfig \
--api-versions discovery.k8s.io/v1 \
--api-versions discovery.k8s.io/v1/EndpointSlice \
--api-versions elbv2.k8s.aws/v1alpha1 \
--api-versions elbv2.k8s.aws/v1alpha1/TargetGroupBinding \
--api-versions elbv2.k8s.aws/v1beta1 \
--api-versions elbv2.k8s.aws/v1beta1/IngressClassParams \
--api-versions elbv2.k8s.aws/v1beta1/TargetGroupBinding \
--api-versions events.k8s.io/v1 \
--api-versions events.k8s.io/v1/Event \
--api-versions external-secrets.io/v1alpha1 \
--api-versions external-secrets.io/v1alpha1/ClusterSecretStore \
--api-versions external-secrets.io/v1alpha1/ExternalSecret \
--api-versions external-secrets.io/v1alpha1/PushSecret \
--api-versions external-secrets.io/v1alpha1/SecretStore \
--api-versions external-secrets.io/v1beta1 \
--api-versions external-secrets.io/v1beta1/ClusterExternalSecret \
--api-versions external-secrets.io/v1beta1/ClusterSecretStore \
--api-versions external-secrets.io/v1beta1/ExternalSecret \
--api-versions external-secrets.io/v1beta1/SecretStore \
--api-versions flowcontrol.apiserver.k8s.io/v1beta2 \
--api-versions flowcontrol.apiserver.k8s.io/v1beta2/FlowSchema \
--api-versions flowcontrol.apiserver.k8s.io/v1beta2/PriorityLevelConfiguration \
--api-versions flowcontrol.apiserver.k8s.io/v1beta3 \
--api-versions flowcontrol.apiserver.k8s.io/v1beta3/FlowSchema \
--api-versions flowcontrol.apiserver.k8s.io/v1beta3/PriorityLevelConfiguration \
--api-versions generators.external-secrets.io/v1alpha1 \
--api-versions generators.external-secrets.io/v1alpha1/ACRAccessToken \
--api-versions generators.external-secrets.io/v1alpha1/ECRAuthorizationToken \
--api-versions generators.external-secrets.io/v1alpha1/Fake \
--api-versions generators.external-secrets.io/v1alpha1/GCRAccessToken \
--api-versions generators.external-secrets.io/v1alpha1/Password \
--api-versions generators.external-secrets.io/v1alpha1/VaultDynamicSecret \
--api-versions karpenter.k8s.aws/v1alpha1 \
--api-versions karpenter.k8s.aws/v1alpha1/AWSNodeTemplate \
--api-versions karpenter.sh/v1alpha5 \
--api-versions karpenter.sh/v1alpha5/Machine \
--api-versions karpenter.sh/v1alpha5/Provisioner \
--api-versions kyverno.io/v1 \
--api-versions kyverno.io/v1/ClusterPolicy \
--api-versions kyverno.io/v1/Policy \
--api-versions kyverno.io/v1alpha2 \
--api-versions kyverno.io/v1alpha2/AdmissionReport \
--api-versions kyverno.io/v1alpha2/BackgroundScanReport \
--api-versions kyverno.io/v1alpha2/ClusterAdmissionReport \
--api-versions kyverno.io/v1alpha2/ClusterBackgroundScanReport \
--api-versions kyverno.io/v1beta1 \
--api-versions kyverno.io/v1beta1/UpdateRequest \
--api-versions kyverno.io/v2alpha1 \
--api-versions kyverno.io/v2alpha1/CleanupPolicy \
--api-versions kyverno.io/v2alpha1/ClusterCleanupPolicy \
--api-versions kyverno.io/v2alpha1/PolicyException \
--api-versions kyverno.io/v2beta1 \
--api-versions kyverno.io/v2beta1/ClusterPolicy \
--api-versions kyverno.io/v2beta1/Policy \
--api-versions networking.k8s.io/v1 \
--api-versions networking.k8s.io/v1/Ingress \
--api-versions networking.k8s.io/v1/IngressClass \
--api-versions networking.k8s.io/v1/NetworkPolicy \
--api-versions node.k8s.io/v1 \
--api-versions node.k8s.io/v1/RuntimeClass \
--api-versions policy/v1 \
--api-versions policy/v1/PodDisruptionBudget \
--api-versions rbac.authorization.k8s.io/v1 \
--api-versions rbac.authorization.k8s.io/v1/ClusterRole \
--api-versions rbac.authorization.k8s.io/v1/ClusterRoleBinding \
--api-versions rbac.authorization.k8s.io/v1/Role \
--api-versions rbac.authorization.k8s.io/v1/RoleBinding \
--api-versions scheduling.k8s.io/v1 \
--api-versions scheduling.k8s.io/v1/PriorityClass \
--api-versions storage.k8s.io/v1 \
--api-versions storage.k8s.io/v1/CSIDriver \
--api-versions storage.k8s.io/v1/CSINode \
--api-versions storage.k8s.io/v1/CSIStorageCapacity \
--api-versions storage.k8s.io/v1/StorageClass \
--api-versions storage.k8s.io/v1/VolumeAttachment \
--api-versions v1 \
--api-versions v1/ConfigMap \
--api-versions v1/Endpoints \
--api-versions v1/Event \
--api-versions v1/LimitRange \
--api-versions v1/Namespace \
--api-versions v1/Node \
--api-versions v1/PersistentVolume \
--api-versions v1/PersistentVolumeClaim \
--api-versions v1/Pod \
--api-versions v1/PodTemplate \
--api-versions v1/ReplicationController \
--api-versions v1/ResourceQuota \
--api-versions v1/Secret \
--api-versions v1/Service \
--api-versions v1/ServiceAccount \
--api-versions vpcresources.k8s.aws/v1beta1 \
--api-versions vpcresources.k8s.aws/v1beta1/SecurityGroupPolicy \
--api-versions wgpolicyk8s.io/v1alpha2 \
--api-versions wgpolicyk8s.io/v1alpha2/ClusterPolicyReport \
--api-versions wgpolicyk8s.io/v1alpha2/PolicyReport \
--include-crds` failed exit status 1: Error: failed to parse .base/kubecost/values.yaml: error converting YAML to JSON: yaml: unknown anchor 'roleArn' referenced
here's the generator
spec:
goTemplate: true
generators:
- matrix:
generators:
- matrix:
generators:
- git:
repoURL: "https://github.com/XXX/deployments.git"
revision: HEAD
directories:
- path: "base/*/*/*"
- git:
repoURL: "https://github.com/XXX/deployments.git"
revision: HEAD
files:
- path: "{{ .path.path }}/values.yaml"
- clusters:
selector:
matchLabels:
argocd.argoproj.io/secret-type: cluster
matchExpressions:
- key: cluster-name
operator: In
values:
- "{{if lt 0 (len .argo.clustername)}}{{index .argo.clustername 0}}{{else}}na{{end}}"
- "{{if lt 1 (len .argo.clustername)}}{{index .argo.clustername 1}}{{else}}na{{end}}"
(paths wont match, since i redacted them in the pasted logs)
I think the git files generator is throwing the initial error. It's parsing values.yaml to turn its contents into parameters. I think the only fix for that would to be introduce a mode where we don't parse the file.
shouldnt it merge it first, and only then generate the parameters?
You're only referencing one file (values.yaml) in the git files generator, so there's nothing to merge.
AHHHH so i should add both ?
or even the 3 files, really
I think that still won't work. We currently parse those files individually. We'd need a new feature to concatenate them before merging.
i just tried a really bad workaround i added empty anchors to the values.yaml and place the anchors in a later precedence. it works... but means we cant override from the values.yaml like before... not the end of the world, but not our ideal scenario either
Ah yikes, yeah that wouldn't be my favorite either.
Maybe something like this would work:
git:
files:
pathsCombined:
- a.yaml
- b.yaml
Do you even need the contents of those files for appset templating? Maybe we could just disable parsing altogether.
we need .argo.clustername
which is present on the values.yaml (it's an anchor in the file itself, but not used on other files)
actually, my hack seems to be failing on karpenter (and only karpenter weirdly enough)
Ah yikes, yeah that wouldn't be my favorite either.
Maybe something like this would work:
git: files: pathsCombined: - a.yaml - b.yaml
how exactly can i implement this ?
That'll require digging into some go. Are you up for that?
Actually, what might be easier: can you split the cluster name into its own file with no anchors and then duplicate that one field in the other files?
Maybe... I'll have to see how much we use that var. I'll check after lunch. I'll see if I can join slack and ping you there.
moved the argo values to a new file, so now the generator looks like
spec:
goTemplate: true
generators:
- matrix:
generators:
- matrix:
generators:
- git:
repoURL: "https://github.com/XXX/deployments.git"
revision: HEAD
directories:
- path: "base/*/*/*"
- git:
repoURL: "https://github.com/XXX/deployments.git"
revision: HEAD
files:
- path: "{{ .path.path }}/argo-values.yaml"
- clusters:
selector:
matchLabels:
argocd.argoproj.io/secret-type: cluster
matchExpressions:
- key: cluster-name
operator: In
values:
- "{{if lt 0 (len .argo.clustername)}}{{index .argo.clustername 0}}{{else}}na{{end}}"
- "{{if lt 1 (len .argo.clustername)}}{{index .argo.clustername 1}}{{else}}na{{end}}"
the spec is like
spec:
project: default
source:
repoURL: "https://github.com/XXXX/deployments.git"
path: "{{ .path.path }}"
targetRevision: HEAD
helm:
passCredentials: true
valueFiles:
- "/common/values.{{ .path.basename }}.yaml"
- "./anchors-values.yaml"
- "./values.yaml"
argo-values.yaml
argo:
clustername:
- alpha-mt
values.yaml
x-anchors:
clustername: &clustername alpha-mt
# ingress-nginx-internal
internal:
ingress:
enable: *internalIngressEnable
clustername: *clustername
certificateArn: *certificateArnInternal
subnets: *subnetsInternal
businessUnit: *businessUnit
environment: *environment
sourceCode: *sourceCode
controller:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app.kubernetes.io/name: internal
app.kubernetes.io/component: controller
app.kubernetes.io/instance: *instanceLabel
topologyKey: "kubernetes.io/hostname"
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app.kubernetes.io/instance: *instanceLabel
defaultBackend:
enabled: *internalIngressEnable
...
anchors-values.yaml
x-anchors:
environment: &environment XXX
instanceLabel: &instanceLabel alpha-mt-ingress-nginx
certificateArnInternal: &certificateArnInternal arn:aws:acm:XXX
subnetsInternal: &subnetsInternal subnet-XXXX
internalIngressEnable: &internalIngressEnable true
and got a new issue.
rpc error: code = Unknown desc = Manifest generation error (cached): `helm template .
--name-template alpha-mt-ingress-nginx
--namespace ingress-nginx
--kube-version 1.27
--values .common/values.ingress-nginx.yaml
--values .base/alpha-mt/phase-3/ingress-nginx/anchors-values.yaml
--values .base/alpha-mt/phase-3/ingress-nginx/values.yaml
--api-versions admissionregistration.k8s.io/v1
--api-versions admissionregistration.k8s.io/v1/MutatingWebhookConfiguration
--api-versions admissionregistration.k8s.io/v1/ValidatingWebhookConfiguration
--api-versions apiextensions.k8s.io/v1
--api-versions apiextensions.k8s.io/v1/CustomResourceDefinition
--api-versions apiregistration.k8s.io/v1
--api-versions apiregistration.k8s.io/v1/APIService
--api-versions apps/v1
--api-versions apps/v1/ControllerRevision
--api-versions apps/v1/DaemonSet
--api-versions apps/v1/Deployment
--api-versions apps/v1/ReplicaSet
--api-versions apps/v1/StatefulSet
--api-versions autoscaling/v1
--api-versions autoscaling/v1/HorizontalPodAutoscaler
--api-versions autoscaling/v2
--api-versions autoscaling/v2/HorizontalPodAutoscaler
--api-versions batch/v1
--api-versions batch/v1/CronJob
--api-versions batch/v1/Job
--api-versions certificates.k8s.io/v1
--api-versions certificates.k8s.io/v1/CertificateSigningRequest
--api-versions coordination.k8s.io/v1
--api-versions coordination.k8s.io/v1/Lease
--api-versions crd.k8s.amazonaws.com/v1alpha1
--api-versions crd.k8s.amazonaws.com/v1alpha1/ENIConfig
--api-versions discovery.k8s.io/v1
--api-versions discovery.k8s.io/v1/EndpointSlice
--api-versions elbv2.k8s.aws/v1alpha1
--api-versions elbv2.k8s.aws/v1alpha1/TargetGroupBinding
--api-versions elbv2.k8s.aws/v1beta1
--api-versions elbv2.k8s.aws/v1beta1/IngressClassParams
--api-versions elbv2.k8s.aws/v1beta1/TargetGroupBinding
--api-versions events.k8s.io/v1
--api-versions events.k8s.io/v1/Event
--api-versions external-secrets.io/v1alpha1
--api-versions external-secrets.io/v1alpha1/ClusterSecretStore
--api-versions external-secrets.io/v1alpha1/ExternalSecret
--api-versions external-secrets.io/v1alpha1/PushSecret
--api-versions external-secrets.io/v1alpha1/SecretStore
--api-versions external-secrets.io/v1beta1
--api-versions external-secrets.io/v1beta1/ClusterExternalSecret
--api-versions external-secrets.io/v1beta1/ClusterSecretStore
--api-versions external-secrets.io/v1beta1/ExternalSecret
--api-versions external-secrets.io/v1beta1/SecretStore
--api-versions flowcontrol.apiserver.k8s.io/v1beta2
--api-versions flowcontrol.apiserver.k8s.io/v1beta2/FlowSchema
--api-versions flowcontrol.apiserver.k8s.io/v1beta2/PriorityLevelConfiguration
--api-versions flowcontrol.apiserver.k8s.io/v1beta3
--api-versions flowcontrol.apiserver.k8s.io/v1beta3/FlowSchema
--api-versions flowcontrol.apiserver.k8s.io/v1beta3/PriorityLevelConfiguration
--api-versions generators.external-secrets.io/v1alpha1
--api-versions generators.external-secrets.io/v1alpha1/ACRAccessToken
--api-versions generators.external-secrets.io/v1alpha1/ECRAuthorizationToken
--api-versions generators.external-secrets.io/v1alpha1/Fake
--api-versions generators.external-secrets.io/v1alpha1/GCRAccessToken
--api-versions generators.external-secrets.io/v1alpha1/Password
--api-versions generators.external-secrets.io/v1alpha1/VaultDynamicSecret
--api-versions karpenter.k8s.aws/v1alpha1
--api-versions karpenter.k8s.aws/v1alpha1/AWSNodeTemplate
--api-versions karpenter.sh/v1alpha5
--api-versions karpenter.sh/v1alpha5/Machine
--api-versions karpenter.sh/v1alpha5/Provisioner
--api-versions kyverno.io/v1
--api-versions kyverno.io/v1/ClusterPolicy
--api-versions kyverno.io/v1/Policy
--api-versions kyverno.io/v1alpha2
--api-versions kyverno.io/v1alpha2/AdmissionReport
--api-versions kyverno.io/v1alpha2/BackgroundScanReport
--api-versions kyverno.io/v1alpha2/ClusterAdmissionReport
--api-versions kyverno.io/v1alpha2/ClusterBackgroundScanReport
--api-versions kyverno.io/v1beta1
--api-versions kyverno.io/v1beta1/UpdateRequest
--api-versions kyverno.io/v2alpha1
--api-versions kyverno.io/v2alpha1/CleanupPolicy
--api-versions kyverno.io/v2alpha1/ClusterCleanupPolicy
--api-versions kyverno.io/v2alpha1/PolicyException
--api-versions kyverno.io/v2beta1
--api-versions kyverno.io/v2beta1/ClusterPolicy
--api-versions kyverno.io/v2beta1/Policy
--api-versions networking.k8s.io/v1
--api-versions networking.k8s.io/v1/Ingress
--api-versions networking.k8s.io/v1/IngressClass
--api-versions networking.k8s.io/v1/NetworkPolicy
--api-versions node.k8s.io/v1
--api-versions node.k8s.io/v1/RuntimeClass
--api-versions policy/v1
--api-versions policy/v1/PodDisruptionBudget
--api-versions rbac.authorization.k8s.io/v1
--api-versions rbac.authorization.k8s.io/v1/ClusterRole
--api-versions rbac.authorization.k8s.io/v1/ClusterRoleBinding
--api-versions rbac.authorization.k8s.io/v1/Role
--api-versions rbac.authorization.k8s.io/v1/RoleBinding
--api-versions scheduling.k8s.io/v1
--api-versions scheduling.k8s.io/v1/PriorityClass
--api-versions storage.k8s.io/v1
--api-versions storage.k8s.io/v1/CSIDriver
--api-versions storage.k8s.io/v1/CSINode
--api-versions storage.k8s.io/v1/CSIStorageCapacity
--api-versions storage.k8s.io/v1/StorageClass
--api-versions storage.k8s.io/v1/VolumeAttachment
--api-versions v1
--api-versions v1/ConfigMap
--api-versions v1/Endpoints
--api-versions v1/Event
--api-versions v1/LimitRange
--api-versions v1/Namespace
--api-versions v1/Node
--api-versions v1/PersistentVolume
--api-versions v1/PersistentVolumeClaim
--api-versions v1/Pod
--api-versions v1/PodTemplate
--api-versions v1/ReplicationController
--api-versions v1/ResourceQuota
--api-versions v1/Secret
--api-versions v1/Service
--api-versions v1/ServiceAccount
--api-versions vpcresources.k8s.aws/v1beta1
--api-versions vpcresources.k8s.aws/v1beta1/SecurityGroupPolicy
--api-versions wgpolicyk8s.io/v1alpha2
--api-versions wgpolicyk8s.io/v1alpha2/ClusterPolicyReport
--api-versions wgpolicyk8s.io/v1alpha2/PolicyReport
--include-crds` failed exit status 1: Error: failed to parse .base/XXX/ingress-nginx/values.yaml: error converting YAML to JSON: yaml: unknown anchor 'internalIngressEnable' referenced
Yep, that error is directly from Helm. Can you reproduce the helm error locally?
i'll have to check next week.
thanks for all the help today
@FernandoMiguel what you are trying to achieve will not work unfortunately, because once the anchor-values.yaml
gets parsed, all your anchors gets expanded and dropped, rendering your aliases void.
Means, anchoring only works implicitly in the same file.
From https://helm.sh/docs/chart_template_guide/yaml_techniques/ "While there are a few cases where anchors are useful, there is one aspect of them that can cause subtle bugs: The first time the YAML is consumed, the reference is expanded and then discarded."
Yep, discovered that this morning while testing. I've opted to go another way to get this sorted. Thanks for the validation and link. We can close this card now!
Summary
Support merge of values.yaml files containing yaml anchors
Motivation
We currently generate a decent amount of configuration via terraform, and save that into values.yaml files we also have other files that are maintained by the plataform team. In order to avoid repeating code, we make use of yaml anchors. Some of that information comes from the files generated by terraform.
Our idea is to merge all those files, and have the anchors fill in the gaps. This does work with helm --dry-run, but seems to fail on argo deployments
the
anchors-values.yaml
is terraform generated.A sample of the merge of
anchors-values.yaml
and/values.yaml
looks like:here's the error from argo
Proposal
support same feature set of helm cli