Skip to content

Conversation

jannfis
Copy link
Member

@jannfis jannfis commented May 12, 2021

Fixes #6174

This PR introduces a new plugin configuration option, lockRepo: <bool>:

configManagementPlugins: |
  - name: some-plugin
    init: ...
    generate: ...
    lockRepo: <true|false> # defaults to false

Custom plugins may make use of git for certain operations (e.g. git crypt), which requires an exclusive lock on the Git repository.

The current locking mechanism for plugins lock on the application path within the repository, which may not be sufficient if two applications using a plugin that executes git on the same repository, but on different paths.

As a follow-up, we should modify our KeyLock interface at https://github.com/argoproj/pkg/blob/master/sync/key_lock.go to also consider locks on path-based matching, instead of exact matches. E.g. if a lock exist on /tmp/foo/bar, a request on a lock for /tmp/foo/bar/baz should wait until the previous lock is released.

Note on DCO:

If the DCO action in the integration test fails, one or more of your commits are not signed off. Please click on the Details link next to the DCO action for instructions on how to resolve this.

Checklist:

  • Either (a) I've created an enhancement proposal and discussed it with the community, (b) this is a bug fix, or (c) this does not need to be in the release notes.
  • The title of the PR states what changed and the related issues number (used for the release note).
  • I've included "Closes [ISSUE #]" or "Fixes [ISSUE #]" in the description to automatically close the associated issue.
  • I've updated both the CLI and UI to expose my feature, or I plan to submit a second PR with them.
  • Does this PR require documentation updates?
  • I've updated documentation as required by this PR.
  • Optional. My organization is added to USERS.md.
  • I have signed off all my commits as required by DCO
  • I have written unit and/or e2e tests for my change. PRs without these are unlikely to be merged.
  • My build is green (troubleshooting builds).

jannfis added 4 commits May 12, 2021 07:04
Signed-off-by: jannfis <jann@mistrust.net>
Signed-off-by: jannfis <jann@mistrust.net>
Signed-off-by: jannfis <jann@mistrust.net>
Signed-off-by: jannfis <jann@mistrust.net>
@codecov
Copy link

codecov bot commented May 12, 2021

Codecov Report

Merging #6223 (0c95016) into master (374965a) will decrease coverage by 0.00%.
The diff coverage is 55.55%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #6223      +/-   ##
==========================================
- Coverage   41.37%   41.37%   -0.01%     
==========================================
  Files         161      161              
  Lines       21595    21599       +4     
==========================================
  Hits         8936     8936              
- Misses      11397    11399       +2     
- Partials     1262     1264       +2     
Impacted Files Coverage Δ
pkg/apis/application/v1alpha1/types.go 57.51% <ø> (ø)
reposerver/repository/repository.go 60.64% <55.55%> (-0.31%) ⬇️
util/settings/settings.go 46.77% <0.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 374965a...0c95016. Read the comment docs.

@jannfis jannfis requested review from alexmt, jgwest and jessesuen May 12, 2021 11:33
Copy link
Member

@jgwest jgwest left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! Since #4625 merged, reasoning about the concurrency implications of this particular area of the codebase is fairly time consuming 🤔 .

While you're at it, can you add this comment to the var manifestGenerateLock = sync.NewKeyLock() line?

// When multiple threads are accessing a Git repository (checked out in the local container,
// eg under '/tmp/(...)') at the the same time, the existing 'Service.repoLock' lock should
// prevent those threads from clobbering each other's files with different revisions (for non-Helm).
//
// However, some manifest generation utilities (helm, custom config management plugins) might still
// write to this repository path during execution of that utility. Thus we need a way to ALSO
// prevent multiple threads from running manifest generation at the same time against the
// same Git repository path. Note: for non-Helm, this will only happen when the two threads are 
// both using the same Git revision at the same time (differing revisions is covered by repoLock).
//
// That is the purpose of manifestGenerateLock: this lock should be acquired if a manifest
// generation utility might cause files to be written to the checked out Git repository
// path, and thus multiple threads should not run this utility at the same time.
var manifestGenerateLock = sync.NewKeyLock()

This is my understanding of the purpose of this lock, after reading through the code in the context of reviewing the PR.

manifestGenerateLock.Lock(repoRoot)
defer manifestGenerateLock.Unlock(repoRoot)
} else {
concurrencyAllowed := isConcurrencyAllowed(appPath)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The isConcurrencyAllowed method already returns false for plugins. Unless I'm missing something plugins already lock repo. We probably need opposite setting allowConcurrency for plugins

Copy link
Member Author

@jannfis jannfis May 19, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I could tell, it locks on the appPath, but we need to lock at the repository root to prevent concurrent git operations (i.e. two applications using same plugin calling git in the same repo, but on different paths).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That isConcurrencyAllowed method only checks for .argocd-allow-concurrency, which could exist for plugins, unless I am missing something? I had assumed that the general point of the logic here was about forcing this method to lock even if that file was specified (if the plugin is configured with lockrepo).

Copy link
Collaborator

@alexmt alexmt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @jannfis . Forgot to click "Submit review" button.

LGTM

jannfis added 2 commits June 9, 2021 12:12
Signed-off-by: jannfis <jann@mistrust.net>
@PierreR
Copy link

PierreR commented Jul 15, 2021

@jessesuen what is the status ?

@Kronk74
Copy link

Kronk74 commented Oct 1, 2021

Hello,

I've got the same issue. @jessesuen Is is possible to review this PR ? :)

@jessesuen
Copy link
Member

This should be good to go. @jannfis just needs to rebase and merge.

@PierreR
Copy link

PierreR commented Oct 19, 2021

@jannfis @jessesuen we have had a talk about this issue with our RHEL support (OpenShift pipeline). Does it help if I open an issue on that side of the road ?

@jannfis
Copy link
Member Author

jannfis commented Oct 19, 2021

Hey sorry, somehow this slipped under the radar. Going to rebase and merge.

…/plugin-global-lock

Signed-off-by: jannfis <jann@mistrust.net>
Signed-off-by: jannfis <jann@mistrust.net>
@jannfis jannfis merged commit 9a11790 into argoproj:master Oct 19, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Plugin argocd for git-crypt
7 participants