argo-cd: sync is not working with ignoreDifferences and RespectIgnoreDifferences=true
Checklist:
- I’ve searched in the docs and FAQ for my answer: https://bit.ly/argocd-faq.
- I’ve included steps to reproduce the bug.
- I’ve pasted the output of
argocd version
.
Describe the bug
I have an application where I want to ignore the image of the deployment and ignore it from being synced, I can see that the image is ignored and there is new env variables to be added in app diff but once I sync it it succeeds without applying the env variables like it’s ignored with the image itself and I still see them in app diff!. This is the application:
project: default
source:
repoURL: 'git@bitbucket.org:x/x.git'
path: kubernetes/production
targetRevision: master
plugin:
name: argocd-vault-plugin
destination:
server: 'https://x.x.x.x'
syncPolicy:
syncOptions:
- RespectIgnoreDifferences=true
ignoreDifferences:
- group: apps
kind: Deployment
name: service
jqPathExpressions:
- >-
.spec.template.spec.containers[] | select(.name == "service").image
To Reproduce
Apply an application with ignoreDifferences like the application above and add new changes inside the same container specs The new specs will not be applied after sync.
Expected behavior
I expect the image to be ignored and the new env variables to be applied/synced
Version
❯ argocd version --grpc-web
argocd: v2.2.7+b8e154f
BuildDate: 2022-03-09T01:07:22Z
GitCommit: b8e154f767412172bb0c2b41131460c34d2a0c73
GitTreeState: clean
GoVersion: go1.16.11
Compiler: gc
Platform: linux/amd64
argocd-server: v2.3.4+ac8b7df
BuildDate: 2022-05-18T11:41:37Z
GitCommit: ac8b7df9467ffcc0920b826c62c4b603a7bfed24
GitTreeState: clean
GoVersion: go1.17.10
Compiler: gc
Platform: linux/amd64
Ksonnet Version: v0.13.1
Kustomize Version: v4.4.1 2021-11-11T23:36:27Z
Helm Version: v3.8.0+gd141386
Kubectl Version: v0.23.1
Jsonnet Version: v0.18.0
About this issue
- Original URL
- State: open
- Created 2 years ago
- Reactions: 43
- Comments: 56 (26 by maintainers)
Commits related to this issue
- fix: keep array entries not found in live state There's an issue with `intersectMap` not appending items for array properties where the live array is smaller than the desired array. Hopefully fixes ... — committed to blakepettersson/argo-cd by blakepettersson a year ago
- fix: keep array entries not found in live state There's an issue with `intersectMap` not appending items for array properties where the live array is smaller than the desired array. Hopefully fixes ... — committed to blakepettersson/argo-cd by blakepettersson a year ago
There may be more than one problem, but I think most of them can be traced back to this function: https://github.com/argoproj/argo-cd/blob/ef8dae885d988bad9033276cd27ccc28945f3433/controller/sync.go#L446
Imagine I want to modify a CronJob to add a new container.
To construct the patch, Argo CD takes the git state (
templateMap
) and the live state (valueMap
) and merges them, using thisintersectMap
function.When
intersectMap
encounters an array, it loops over the array from git (say, an array with two containers) and for each item merges the same array from the live object (say, an array with only one container). If the array in the live object is shorter than the array in the git object,intersectMap
just drops any remaining items from the git state. So the patch contains only the first container.That’s the answer for the specific case of “adding a new container.” The general answer is: this patch function is custom and is not Kubernetes-aware. A Kubernetes-aware patch function would have merged the array on a merge key (like container name) if present.
I just pushed a change to #14602 where array entries are merged by a merge key (currently hardcoded to
name
). There are likely many dragons here, both in terms of edge cases and performance. Due to a new child, my ability to carry on the work will be quite limited these next couple of weeks. Hopefully someone can move this PR forward by either bringing on some more test cases, reviewing the PR itself or by fixing it where necessary. If someone wants to move this forward, I’ll try to help when I can.I added a draft PR (see #14602), there are likely hidden dragons (I can’t believe that the fix is that simple 😛). Feel free to add test cases which I can add to the unit tests.
I think I’ve hit the same bug. Is there any progress or estimation on this?
@si-c613 I’m super excited about the PR. My two hesitations are:
But overall, this is really cool. Even if the PR has limitations, we can document them, and still be in a much better place than we are today.
what are the chances that this issue is related? i just saw that argo using
gojq
and there was bug in compiler related to arrays that was fixed in 0.12.11 and argo 2.5 uses 0.12.9 at the latestI like how I’m following this issue, and every week or so I basically get an email notification with a *joke XD
Thanks for making me laugh once again @cirano-eusebi
** I’ll be ruthlessly truthful, The joke is this ‘tool’ and that more and more people are being affected by this issue… (I’m on your team) I tend to try and not to spam a meaningful conversations, but 4 months have past since my last outburst, and also, my Argo instance malfunctioned today [got stuck refreshing], as expected at this point…
https://github.com/argoproj/argo-cd/issues/9678#issuecomment-1669716126 Sorry 🙏
same issue on latest version
@QuingKhaos, I’ll elaborate We have deployment applied with argo, on the app configured
ignoreDifferences
at this stage behavior is following:
on every change in the app, argocd does “full” sync, overriding env var to what it see in the git, as it happens, the operator sees changes and applies its patch to env var. Argocd according to
ignoreDifferences
not doing anything with this change. Until a change in any other place of the app.After adding
RespectIgnoreDifferences=true
behaviors is the following:argocd not triggering sync at all when change is related to anything inside
'.spec.template.spec.containers[]
. the workaround of syncing from UI with removingV
fromRespectIgnoreDifferences
is working, but it is “not the GitOps that we want” 😃Confirmed this is also not working with 2.5.2. We are have an ignore like this
We see the ignore works correctly, but the 3rd dns name is removed when syncing with
RespectIgnoreDifferences
. We also tried/spec/dnsNames
in case there is an oddity with arrays and had the same behavior. Our source file has this for the item being removed for live state:And desired state
Sounds like a good case to unit test and add to #14602 😃
hi folks, update on my comment above: https://github.com/argoproj/argo-cd/issues/9678#issuecomment-1631504590
for those seeing this issue with
Secrets
, in our case this was caused by the targetSecret
resource not having attributedata
set. we set the data field to a foo value (foo: 'bar'
) and it began respecting theignoreDifferences
. so it’s unable to match on the fields when anull
value is coming from the source manifest AND there are out-of-band modifications to the live object. this hack only works for key-value fields likedata
though.@FredrikAugust indeed it was easy to reproduce, and it also seems like it’s currently failing locally. I’ll look into that and fix it, and push the update to #14602.
@blakepettersson Sure!
I’ve posted the live state to a gist here: https://gist.github.com/FredrikAugust/8ba73d9665b60b168ab96d3f5ec69949
The desired state, if I understand the UI correctly should be that, but with the
initialDelaySeconds: 15
instead of: 20
. I don’t have the desired state at ready right now as I’ve manually applied the changes, but it should be easy to reproduce.Added a test case in #14602; for this to pass we’ll likely need to merge the target object(s) with a merge key. At the moment I’m working on doing this by having
name
as a hard-coded merge key, but could likely use some refinement. Once I get this working we can see if we can/should have some way of specifying merge keys.I managed to get that test to pass anyways 😄 The gist of it is that at times we also need to compare with values from the full live object.
Brilliant! I’m sure you’re already deep into this now but I’ve had a look at the test case and your PR updates. I wonder if the bug that has now been uncovered is in the
diff.Normalize
function called here.I wonder if the return values for live and target shouldn’t include the ignored fields, this is true for live but not true for target? The test that’s failing shows a value changing outside the cluster and not being present in the cluster.
Hope this makes some sort of sense. Apologies that I’m keeping a little distance from this, if it’s more of a hinderance than a help feel free to say 😃
@si-c613 from your test cases I managed to get them to pass, but that caused another test (which I need a bit more info on the reasoning behind why it is the way it is) to fail; the
will remove fields from target if not present in live
test case.Beyond that, we’ll need to consider how entries should be merged by key. Keep bringing on the test cases 😄
Had a brief after thought about the previous test being focused on adding values, slightly refactored the naming and added a test for the reverse as well in this commit. Currently this test is passing, but given it’s looking for the lack of something may need a bit more scrutiny.
@si-c613 this is great, thank you!
Same here with 2.7.6:
Upon changing container command arguments, ArgoCD sync succeeds with
unchanged
resource, we are using argoproj-labs/argocd-image-updater, that particular jq is about ignoring our double tagged images in our registry ( we do both minor ‘latest’ and patch update upon deployment, similar to how you would havepython:3.11
equivalent topython:3.11.4
as of writing this )indeed works, and the resource is
updated
… this is not GitOps… 🫤I had a similar issue where I couldn’t sync because of a difference in an immutable field which I wanted to ignore. However, setting
ServerSideApply=true
fixed the issue for me:same issue on latest version
We are using some operator that is changing the env vars of the pod in the deployment. So now, because of this issue, argo rolling back operator changes to its defaults on every sync (and then operator changes it again). So we have a restart of the deployment on every change of the application, even when it is not related to mentioned deployments at all.