Skip to content

Commit

Permalink
Merge branch 'master' into issue-10724-notification-secrets
Browse files Browse the repository at this point in the history
Signed-off-by: Etien Rožnik <12816736+eroznik@users.noreply.github.com>
  • Loading branch information
eroznik authored Oct 25, 2023
2 parents 5236341 + f37d24f commit 0133a65
Show file tree
Hide file tree
Showing 35 changed files with 292 additions and 41 deletions.
3 changes: 2 additions & 1 deletion USERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Currently, the following organizations are **officially** using Argo CD:
1. [AppDirect](https://www.appdirect.com)
1. [Arctiq Inc.](https://www.arctiq.ca)
1. [ARZ Allgemeines Rechenzentrum GmbH](https://www.arz.at/)
2. [Autodesk](https://www.autodesk.com)
1. [Autodesk](https://www.autodesk.com)
1. [Axual B.V.](https://axual.com)
1. [Back Market](https://www.backmarket.com)
1. [Baloise](https://www.baloise.com)
Expand Down Expand Up @@ -210,6 +210,7 @@ Currently, the following organizations are **officially** using Argo CD:
1. [Patreon](https://www.patreon.com/)
1. [PayPay](https://paypay.ne.jp/)
1. [Peloton Interactive](https://www.onepeloton.com/)
1. [Percona](https://percona.com/)
1. [PGS](https://www.pgs.com)
1. [Pigment](https://www.gopigment.com/)
1. [Pipefy](https://www.pipefy.com/)
Expand Down
7 changes: 7 additions & 0 deletions applicationset/utils/createOrUpdate.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"k8s.io/apimachinery/pkg/conversion"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime/schema"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"

Expand Down Expand Up @@ -78,6 +79,12 @@ func CreateOrUpdate(ctx context.Context, c client.Client, obj client.Object, f c
return a.Namespace == b.Namespace && a.Name == b.Name && a.Server == b.Server
},
)
// make sure updated object has the same apiVersion & kind as original object
if objKind, ok := obj.(schema.ObjectKind); ok {
if existingKind, ok := existing.(schema.ObjectKind); ok {
existingKind.SetGroupVersionKind(objKind.GroupVersionKind())
}
}

if equality.DeepEqual(existing, obj) {
return controllerutil.OperationResultNone, nil
Expand Down
6 changes: 6 additions & 0 deletions cmd/argocd/commands/gpg.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
appsv1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/v2/util/errors"
argoio "github.com/argoproj/argo-cd/v2/util/io"
"github.com/argoproj/argo-cd/v2/util/templates"
)

// NewGPGCommand returns a new instance of an `argocd repo` command
Expand Down Expand Up @@ -109,6 +110,11 @@ func NewGPGAddCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
var command = &cobra.Command{
Use: "add",
Short: "Adds a GPG public key to the server's keyring",
Example: templates.Examples(`
# Add a GPG public key to the server's keyring from a file.
argocd gpg add --from /path/to/keyfile
`),

Run: func(c *cobra.Command, args []string) {
ctx := c.Context()

Expand Down
9 changes: 9 additions & 0 deletions cmd/argocd/commands/project_role.go
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,15 @@ func NewProjectRoleListCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
var command = &cobra.Command{
Use: "list PROJECT",
Short: "List all the roles in a project",
Example: templates.Examples(`
# This command will list all the roles in argocd-project in a default table format.
argocd proj role list PROJECT
# List the roles in the project in formats like json, yaml, wide, or name.
argocd proj role list PROJECT --output json
`),

Run: func(c *cobra.Command, args []string) {
ctx := c.Context()

Expand Down
13 changes: 9 additions & 4 deletions cmpserver/plugin/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,16 @@ func runCommand(ctx context.Context, command Command, path string, env []string)
logCtx.Error(err.Error())
return strings.TrimSuffix(output, "\n"), err
}

logCtx = logCtx.WithFields(log.Fields{
"stderr": stderr.String(),
"command": command,
})
if len(output) == 0 {
log.WithFields(log.Fields{
"stderr": stderr.String(),
"command": command,
}).Warn("Plugin command returned zero output")
logCtx.Warn("Plugin command returned zero output")
} else {
// Log stderr even on successfull commands to help develop plugins
logCtx.Info("Plugin command successfull")
}

return strings.TrimSuffix(output, "\n"), nil
Expand Down
42 changes: 35 additions & 7 deletions controller/appcontroller.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package controller
import (
"context"
"encoding/json"
goerrors "errors"
"fmt"
"math"
"net/http"
Expand Down Expand Up @@ -1330,8 +1331,7 @@ func (ctrl *ApplicationController) setOperationState(app *appv1.Application, sta
}

kube.RetryUntilSucceed(context.Background(), updateOperationStateTimeout, "Update application operation state", logutils.NewLogrusLogger(logutils.NewWithCurrentConfig()), func() error {
appClient := ctrl.applicationClientset.ArgoprojV1alpha1().Applications(app.Namespace)
_, err = appClient.Patch(context.Background(), app.Name, types.MergePatchType, patchJSON, metav1.PatchOptions{})
_, err := ctrl.PatchAppWithWriteBack(context.Background(), app.Name, app.Namespace, types.MergePatchType, patchJSON, metav1.PatchOptions{})
if err != nil {
// Stop retrying updating deleted application
if apierr.IsNotFound(err) {
Expand Down Expand Up @@ -1369,6 +1369,27 @@ func (ctrl *ApplicationController) setOperationState(app *appv1.Application, sta
}
}

// writeBackToInformer writes a just recently updated App back into the informer cache.
// This prevents the situation where the controller operates on a stale app and repeats work
func (ctrl *ApplicationController) writeBackToInformer(app *appv1.Application) {
logCtx := log.WithFields(log.Fields{"application": app.Name, "appNamespace": app.Namespace, "project": app.Spec.Project, "informer-writeBack": true})
err := ctrl.appInformer.GetStore().Update(app)
if err != nil {
logCtx.Errorf("failed to update informer store: %v", err)
return
}
}

// PatchAppWithWriteBack patches an application and writes it back to the informer cache
func (ctrl *ApplicationController) PatchAppWithWriteBack(ctx context.Context, name, ns string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *appv1.Application, err error) {
patchedApp, err := ctrl.applicationClientset.ArgoprojV1alpha1().Applications(ns).Patch(ctx, name, pt, data, opts, subresources...)
if err != nil {
return patchedApp, err
}
ctrl.writeBackToInformer(patchedApp)
return patchedApp, err
}

func (ctrl *ApplicationController) processAppRefreshQueueItem() (processNext bool) {
patchMs := time.Duration(0) // time spent in doing patch/update calls
setOpMs := time.Duration(0) // time spent in doing Operation patch calls in autosync
Expand Down Expand Up @@ -1642,8 +1663,7 @@ func (ctrl *ApplicationController) normalizeApplication(orig, app *appv1.Applica
if err != nil {
logCtx.Errorf("error constructing app spec patch: %v", err)
} else if modified {
appClient := ctrl.applicationClientset.ArgoprojV1alpha1().Applications(app.Namespace)
_, err = appClient.Patch(context.Background(), app.Name, types.MergePatchType, patch, metav1.PatchOptions{})
_, err := ctrl.PatchAppWithWriteBack(context.Background(), app.Name, app.Namespace, types.MergePatchType, patch, metav1.PatchOptions{})
if err != nil {
logCtx.Errorf("Error persisting normalized application spec: %v", err)
} else {
Expand Down Expand Up @@ -1687,8 +1707,7 @@ func (ctrl *ApplicationController) persistAppStatus(orig *appv1.Application, new
defer func() {
patchMs = time.Since(start)
}()
appClient := ctrl.applicationClientset.ArgoprojV1alpha1().Applications(orig.Namespace)
_, err = appClient.Patch(context.Background(), orig.Name, types.MergePatchType, patch, metav1.PatchOptions{})
_, err = ctrl.PatchAppWithWriteBack(context.Background(), orig.Name, orig.Namespace, types.MergePatchType, patch, metav1.PatchOptions{})
if err != nil {
logCtx.Warnf("Error updating application: %v", err)
} else {
Expand Down Expand Up @@ -1798,11 +1817,20 @@ func (ctrl *ApplicationController) autoSync(app *appv1.Application, syncStatus *

appIf := ctrl.applicationClientset.ArgoprojV1alpha1().Applications(app.Namespace)
start := time.Now()
_, err := argo.SetAppOperation(appIf, app.Name, &op)
updatedApp, err := argo.SetAppOperation(appIf, app.Name, &op)
setOpTime := time.Since(start)
if err != nil {
if goerrors.Is(err, argo.ErrAnotherOperationInProgress) {
// skipping auto-sync because another operation is in progress and was not noticed due to stale data in informer
// it is safe to skip auto-sync because it is already running
logCtx.Warnf("Failed to initiate auto-sync to %s: %v", desiredCommitSHA, err)
return nil, 0
}

logCtx.Errorf("Failed to initiate auto-sync to %s: %v", desiredCommitSHA, err)
return &appv1.ApplicationCondition{Type: appv1.ApplicationConditionSyncError, Message: err.Error()}, setOpTime
} else {
ctrl.writeBackToInformer(updatedApp)
}
message := fmt.Sprintf("Initiated automated sync to '%s'", desiredCommitSHA)
ctrl.auditLogger.LogAppEvent(app, argo.EventInfo{Reason: argo.EventReasonOperationStarted, Type: v1.EventTypeNormal}, message, "")
Expand Down
32 changes: 16 additions & 16 deletions controller/appcontroller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,7 @@ func TestFinalizeAppDeletion(t *testing.T) {
})
fakeAppCs.AddReactor("patch", "*", func(action kubetesting.Action) (handled bool, ret runtime.Object, err error) {
patched = true
return true, nil, nil
return true, &v1alpha1.Application{}, nil
})
_, err := ctrl.finalizeApplicationDeletion(app, func(project string) ([]*v1alpha1.Cluster, error) {
return []*v1alpha1.Cluster{}, nil
Expand Down Expand Up @@ -675,7 +675,7 @@ func TestFinalizeAppDeletion(t *testing.T) {
})
fakeAppCs.AddReactor("patch", "*", func(action kubetesting.Action) (handled bool, ret runtime.Object, err error) {
patched = true
return true, nil, nil
return true, &v1alpha1.Application{}, nil
})
objs, err := ctrl.finalizeApplicationDeletion(app, func(project string) ([]*v1alpha1.Cluster, error) {
return []*v1alpha1.Cluster{}, nil
Expand Down Expand Up @@ -709,7 +709,7 @@ func TestFinalizeAppDeletion(t *testing.T) {
})
fakeAppCs.AddReactor("patch", "*", func(action kubetesting.Action) (handled bool, ret runtime.Object, err error) {
patched = true
return true, nil, nil
return true, &v1alpha1.Application{}, nil
})
_, err := ctrl.finalizeApplicationDeletion(app, func(project string) ([]*v1alpha1.Cluster, error) {
return []*v1alpha1.Cluster{}, nil
Expand Down Expand Up @@ -804,7 +804,7 @@ func TestNormalizeApplication(t *testing.T) {
normalized = true
}
}
return true, nil, nil
return true, &v1alpha1.Application{}, nil
})
ctrl.processAppRefreshQueueItem()
assert.True(t, normalized)
Expand All @@ -826,7 +826,7 @@ func TestNormalizeApplication(t *testing.T) {
normalized = true
}
}
return true, nil, nil
return true, &v1alpha1.Application{}, nil
})
ctrl.processAppRefreshQueueItem()
assert.False(t, normalized)
Expand Down Expand Up @@ -923,7 +923,7 @@ func TestSetOperationStateOnDeletedApp(t *testing.T) {
patched := false
fakeAppCs.AddReactor("patch", "*", func(action kubetesting.Action) (handled bool, ret runtime.Object, err error) {
patched = true
return true, nil, apierr.NewNotFound(schema.GroupResource{}, "my-app")
return true, &v1alpha1.Application{}, apierr.NewNotFound(schema.GroupResource{}, "my-app")
})
ctrl.setOperationState(newFakeApp(), &v1alpha1.OperationState{Phase: synccommon.OperationSucceeded})
assert.True(t, patched)
Expand Down Expand Up @@ -955,9 +955,9 @@ func TestSetOperationStateLogRetries(t *testing.T) {
fakeAppCs.AddReactor("patch", "*", func(action kubetesting.Action) (handled bool, ret runtime.Object, err error) {
if !patched {
patched = true
return true, nil, errors.New("fake error")
return true, &v1alpha1.Application{}, errors.New("fake error")
}
return true, nil, nil
return true, &v1alpha1.Application{}, nil
})
ctrl.setOperationState(newFakeApp(), &v1alpha1.OperationState{Phase: synccommon.OperationSucceeded})
assert.True(t, patched)
Expand Down Expand Up @@ -1273,7 +1273,7 @@ func TestUpdateReconciledAt(t *testing.T) {
if patchAction, ok := action.(kubetesting.PatchAction); ok {
assert.NoError(t, json.Unmarshal(patchAction.GetPatch(), &receivedPatch))
}
return true, nil, nil
return true, &v1alpha1.Application{}, nil
})

t.Run("UpdatedOnFullReconciliation", func(t *testing.T) {
Expand Down Expand Up @@ -1347,7 +1347,7 @@ func TestFinalizeProjectDeletion_HasApplications(t *testing.T) {
patched := false
fakeAppCs.PrependReactor("patch", "*", func(action kubetesting.Action) (handled bool, ret runtime.Object, err error) {
patched = true
return true, nil, nil
return true, &v1alpha1.Application{}, nil
})

err := ctrl.finalizeProjectDeletion(proj)
Expand All @@ -1365,7 +1365,7 @@ func TestFinalizeProjectDeletion_DoesNotHaveApplications(t *testing.T) {
if patchAction, ok := action.(kubetesting.PatchAction); ok {
assert.NoError(t, json.Unmarshal(patchAction.GetPatch(), &receivedPatch))
}
return true, nil, nil
return true, &v1alpha1.AppProject{}, nil
})

err := ctrl.finalizeProjectDeletion(proj)
Expand All @@ -1390,7 +1390,7 @@ func TestProcessRequestedAppOperation_FailedNoRetries(t *testing.T) {
if patchAction, ok := action.(kubetesting.PatchAction); ok {
assert.NoError(t, json.Unmarshal(patchAction.GetPatch(), &receivedPatch))
}
return true, nil, nil
return true, &v1alpha1.Application{}, nil
})

ctrl.processRequestedAppOperation(app)
Expand Down Expand Up @@ -1418,7 +1418,7 @@ func TestProcessRequestedAppOperation_InvalidDestination(t *testing.T) {
if patchAction, ok := action.(kubetesting.PatchAction); ok {
assert.NoError(t, json.Unmarshal(patchAction.GetPatch(), &receivedPatch))
}
return true, nil, nil
return true, &v1alpha1.Application{}, nil
})
}()

Expand All @@ -1444,7 +1444,7 @@ func TestProcessRequestedAppOperation_FailedHasRetries(t *testing.T) {
if patchAction, ok := action.(kubetesting.PatchAction); ok {
assert.NoError(t, json.Unmarshal(patchAction.GetPatch(), &receivedPatch))
}
return true, nil, nil
return true, &v1alpha1.Application{}, nil
})

ctrl.processRequestedAppOperation(app)
Expand Down Expand Up @@ -1487,7 +1487,7 @@ func TestProcessRequestedAppOperation_RunningPreviouslyFailed(t *testing.T) {
if patchAction, ok := action.(kubetesting.PatchAction); ok {
assert.NoError(t, json.Unmarshal(patchAction.GetPatch(), &receivedPatch))
}
return true, nil, nil
return true, &v1alpha1.Application{}, nil
})

ctrl.processRequestedAppOperation(app)
Expand Down Expand Up @@ -1520,7 +1520,7 @@ func TestProcessRequestedAppOperation_HasRetriesTerminated(t *testing.T) {
if patchAction, ok := action.(kubetesting.PatchAction); ok {
assert.NoError(t, json.Unmarshal(patchAction.GetPatch(), &receivedPatch))
}
return true, nil, nil
return true, &v1alpha1.Application{}, nil
})

ctrl.processRequestedAppOperation(app)
Expand Down
4 changes: 4 additions & 0 deletions docs/operator-manual/argocd-cmd-params-cm.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,10 @@ data:
reposerver.streamed.manifest.max.extracted.size: "1G"
# Enable git submodule support
reposerver.enable.git.submodule: "true"
# Number of concurrent git ls-remote requests. Any value less than 1 means no limit.
reposerver.git.lsremote.parallelism.limit: "0"
# Git requests timeout.
reposerver.git.request.timeout: "15s"

# Disable TLS on the HTTP endpoint
dexserver.disable.tls: "false"
Expand Down
2 changes: 2 additions & 0 deletions docs/operator-manual/config-management-plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ spec:
args: [-c, 'echo "Initializing..."']
# The generate command runs in the Application source directory each time manifests are generated. Standard output
# must be ONLY valid Kubernetes Objects in either YAML or JSON. A non-zero exit code will fail manifest generation.
# To write log messages from the command, write them to stderr, it will always be displayed.
# Error output will be sent to the UI, so avoid printing sensitive information (such as secrets).
generate:
command: [sh, -c]
Expand Down Expand Up @@ -333,6 +334,7 @@ If you are actively developing a sidecar-installed CMP, keep a few things in min
3. CMP errors are cached by the repo-server in Redis. Restarting the repo-server Pod will not clear the cache. Always
do a "Hard Refresh" when actively developing a CMP so you have the latest output.
4. Verify your sidecar has started properly by viewing the Pod and seeing that two containers are running `kubectl get pod -l app.kubernetes.io/component=repo-server -n argocd`
5. Write log message to stderr and set the `--loglevel=info` flag in the sidecar. This will print everything written to stderr, even on successfull command execution.


### Other Common Errors
Expand Down
23 changes: 23 additions & 0 deletions docs/proposals/feature-bounties/hide-annotations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Proposal: Allow Hiding Certain Annotations in the Argo CD Web UI

Based on this issue: https://github.com/argoproj/argo-cd/issues/15693

Award amount: $100

## Solution

!!! note
This is the proposed solution. The accepted PR may differ from this proposal.

Add a new config item in argocd-cm:

```yaml
hide.secret.annotations: |
- openshift.io/token-secret.value
```
This will hide the `openshift.io/token-secret.value` annotation from the UI. Behind the scenes, it would likely work the
same way as the `last-applied-configuration` annotation hiding works: https://github.com/argoproj/gitops-engine/blob/b0fffe419a0f0a40f9f2c0b6346b752ed6537385/pkg/diff/diff.go#L897

I considered whether we'd want to support hiding things besides annotations and in resources besides secrets, but
having reviewed existing issues, I think this narrow feature is sufficient.
7 changes: 7 additions & 0 deletions docs/user-guide/commands/argocd_gpg_add.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ Adds a GPG public key to the server's keyring
argocd gpg add [flags]
```

### Examples

```
# Add a GPG public key to the server's keyring from a file.
argocd gpg add --from /path/to/keyfile
```

### Options

```
Expand Down
Loading

0 comments on commit 0133a65

Please sign in to comment.