Compare commits

...

16 Commits

Author SHA1 Message Date
github-actions[bot]
dc43124058 Bump version to 2.13.2 (#21133)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: ishitasequeira <46771830+ishitasequeira@users.noreply.github.com>
2024-12-11 20:26:41 +05:30
Blake Pettersson
b6af657295 fix: add missing fields in listrepositories (#20991) (#21129)
This fixes a regression in 2.12. Before 2.12 githubAppInstallationID,
`githubAppID` and `gitHubAppEnterpriseBaseURL` were returned, but with
2.12 the repo is retrieved with getRepositories`, which does not
include those fields.

To fix this, add those missing fields to `ListRepositories`.

Signed-off-by: Blake Pettersson <blake.pettersson@gmail.com>
2024-12-11 12:17:21 +01:00
gcp-cherry-pick-bot[bot]
a3624a3f20 fix: Allow to delete repos with invalid urls (#20921) (#20975) (#21116)
* fix: Allow to delete repos with invalid urls (#20921)

Fixes #20921

Normalization of repo url is attempted during repo deletion before comparison with existing repos. Before this change, it'd fail on invalid urls and return "", resulting in permission denied. This ended up in a state where people can add repos with invalid urls but couldn't delete them. Return raw repo url if url parsing failed. Add a test to validate the deletion can be performed and make sure it fails without the main change.

This needs to be cherry-picked to v2.11-2.13



* Don't modify the original NormalizeGitURL



---------

Signed-off-by: Andrii Korotkov <andrii.korotkov@verkada.com>
Co-authored-by: Andrii Korotkov <137232734+andrii-korotkov-verkada@users.noreply.github.com>
2024-12-10 16:28:27 +02:00
gcp-cherry-pick-bot[bot]
01ae20d1b3 fix: 20791 - sync multi-source application out of order source syncs (cherry-pick #21071) (#21077)
Signed-off-by: Ishita Sequeira <ishiseq29@gmail.com>
Co-authored-by: Ishita Sequeira <46771830+ishitasequeira@users.noreply.github.com>
2024-12-05 11:14:25 -07:00
gcp-cherry-pick-bot[bot]
89ef3563db fix: Bitbucket Cloud PR Author is processed correctly (#20769) (#20990) (#21039)
Fixes #20769

Author there is a struct, not a string. Use nickname from that struct as an author name.

Let's cherry pick to 2.11-2.13

Signed-off-by: Andrii Korotkov <andrii.korotkov@verkada.com>
Co-authored-by: Andrii Korotkov <137232734+andrii-korotkov-verkada@users.noreply.github.com>
2024-12-03 17:02:24 +05:30
gcp-cherry-pick-bot[bot]
831e4525c3 fix: API server should not attempt to read secrets in all namespaces (#20950) (#20960)
* fix: api server is trying to list cluster wide secrets while generating apps



* Revert "fix: Fix argocd appset generate failure due to missing clusterrole (#20162)"

This reverts commit fad534bcfe.

---------

Signed-off-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
Co-authored-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
2024-11-26 19:43:12 +05:30
gcp-cherry-pick-bot[bot]
f8d6665c67 fix: Memory leak in repo-server (#20876) (#20894)
Signed-off-by: Adam Chandler <adam_chandler@trimble.com>
Co-authored-by: Adam Chandler <31355738+AJChandler@users.noreply.github.com>
2024-11-21 10:08:04 -05:00
gcp-cherry-pick-bot[bot]
0680ddbdf9 chore(deps): bump http-proxy-middleware from 2.0.4 to 2.0.7 in /ui (#20518) (#20892)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-21 08:44:53 -05:00
gcp-cherry-pick-bot[bot]
ad36916ec4 fix(cli): Fix appset generate in --core mode (#20717) (#20883)
Signed-off-by: OpenGuidou <guillaume.doussin@gmail.com>
Co-authored-by: OpenGuidou <73480729+OpenGuidou@users.noreply.github.com>
2024-11-21 17:36:31 +05:30
github-actions[bot]
af54ef8db5 Bump version to 2.13.1 (#20865)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: pasha-codefresh <39732895+pasha-codefresh@users.noreply.github.com>
2024-11-20 17:45:30 +02:00
gcp-cherry-pick-bot[bot]
68606c6caf fix: Fix repeated 403 due to app namespace being undefined (#20699) (#20819) (#20860)
Fixes #20699

Constructor may not get called every time the application changes, so previous this.appNamespace could be stale. But the update to use `this.props.match.params.appnamespace` could also fail if it's undefined.
As a fix, create and use a helper function `getAppNamespace` which has a special case handling for undefined.

Also, use a namespaced endpoint when namespace is not undefined.

It needs to be cherry-picked to v2.11-2.13.

Signed-off-by: Andrii Korotkov <andrii.korotkov@verkada.com>
Co-authored-by: Andrii Korotkov <137232734+andrii-korotkov-verkada@users.noreply.github.com>
2024-11-20 13:13:11 +02:00
Cayde6
6a8cb6eff0 feat: option to disable writing k8s events(#18205) (#18441) (#20788)
* feat: option to disable writing k8s events

optioned to write logs for k8s events.
Each is passed as an environment variable and defaults to true,
disabling it requires explicitly setting the option to false.

---------

Signed-off-by: Jack-R-lantern <tjdfkr2421@gmail.com>
2024-11-14 13:07:04 +05:30
Pasha Kostohrys
d03ccf305c fix: disable automaxprocs logging (#20069) - cherry-pick 2.13 (#20718)
* fix: disable automaxprocs logging (#20069)

* disable automaxprocs logging

Signed-off-by: nitishfy <justnitish06@gmail.com>

fix lint checks

Signed-off-by: nitishfy <justnitish06@gmail.com>

move maxprocs to main.go

Signed-off-by: nitishfy <justnitish06@gmail.com>

move set auto max procs to a function

Signed-off-by: nitishfy <justnitish06@gmail.com>

add info log

Signed-off-by: nitishfy <justnitish06@gmail.com>

* add info log

Signed-off-by: nitishfy <justnitish06@gmail.com>

* fix lint checks

Signed-off-by: nitishfy <justnitish06@gmail.com>

* fix lint checks

Signed-off-by: nitishfy <justnitish06@gmail.com>

* add unit test

Signed-off-by: nitishfy <justnitish06@gmail.com>

* fix lint issues

Signed-off-by: nitishfy <justnitish06@gmail.com>

---------

Signed-off-by: nitishfy <justnitish06@gmail.com>
(cherry picked from commit cfa1c89c43)

* fix(ci): ignore temporary files when checking for out of bound symlinks (#20527)

Signed-off-by: cef <moncef.abboud95@gmail.com>

---------

Signed-off-by: cef <moncef.abboud95@gmail.com>
Co-authored-by: Nitish Kumar <justnitish06@gmail.com>
Co-authored-by: ABBOUD Moncef <moncef.abboud95@gmail.com>
2024-11-08 19:46:49 +02:00
gcp-cherry-pick-bot[bot]
7f45c9e093 chore: Don't degrade PDB on InsufficientPods (#20171) (#20665) (#20694)
Closes #20171

There are valid use cases for InsufficientPods, e.g. running some jobs or tests that don't want to be terminated. See the discussion on the issue for more details. So don't degrade the PDB on InsufficientPods condition.

This needs to be cherry picked to 2.13, as many people may not upgrade otherwise.

Signed-off-by: Andrii Korotkov <andrii.korotkov@verkada.com>
Co-authored-by: Andrii Korotkov <137232734+andrii-korotkov-verkada@users.noreply.github.com>
2024-11-07 09:11:01 -08:00
austin5219
449e6939b2 fix(pkce): 20202 Backport PKCE auth flow fix for basehref and reauth (#20675)
* fix(pkce): 20111 PKCE auth flow does not return user to previous path like dex auth flow (#20202)

* Adding non-default basehref support for PKCE auth flow

Signed-off-by: austin5219 <3936059+austin5219@users.noreply.github.com>

* Adding ; for linting

Signed-off-by: austin5219 <3936059+austin5219@users.noreply.github.com>

* removing hook function

Signed-off-by: austin5219 <3936059+austin5219@users.noreply.github.com>

* Moving unauthorized error handling to class component to access context for error handling within 401 error

Signed-off-by: austin5219 <3936059+austin5219@users.noreply.github.com>

* Store the subsrition handle to close in unmount

Signed-off-by: austin5219 <3936059+austin5219@users.noreply.github.com>

* reorder imports

Signed-off-by: austin5219 <3936059+austin5219@users.noreply.github.com>

* Actually saving the subscriptions now

Signed-off-by: austin5219 <3936059+austin5219@users.noreply.github.com>

* returning the 401 subscription from helper function

Signed-off-by: austin5219 <3936059+austin5219@users.noreply.github.com>

* Handle the promise of a subscription

Signed-off-by: austin5219 <3936059+austin5219@users.noreply.github.com>

* Removing then from non async subscribe

Signed-off-by: austin5219 <3936059+austin5219@users.noreply.github.com>

* Linter fixes

Signed-off-by: austin5219 <3936059+austin5219@users.noreply.github.com>

* Adding path caching to sessionStorage on pkceLogin and redirect step to cached path if available in pkceCallback to mirror Dex functionality

Signed-off-by: austin5219 <3936059+austin5219@users.noreply.github.com>

---------

Signed-off-by: austin5219 <3936059+austin5219@users.noreply.github.com>

* Merge Conflict fix

Signed-off-by: austin5219 <3936059+austin5219@users.noreply.github.com>

---------

Signed-off-by: austin5219 <3936059+austin5219@users.noreply.github.com>
2024-11-07 15:47:09 +02:00
gcp-cherry-pick-bot[bot]
99aab9a5f3 fix: check for source position when --show-params is set (#20682) (#20689)
Signed-off-by: Soumya Ghosh Dastidar <gdsoumya@gmail.com>
Co-authored-by: Soumya Ghosh Dastidar <44349253+gdsoumya@users.noreply.github.com>
2024-11-07 12:51:49 +05:30
49 changed files with 494 additions and 186 deletions

View File

@@ -1 +1 @@
2.13.0
2.13.2

View File

@@ -19,7 +19,7 @@ type BitbucketCloudPullRequest struct {
ID int `json:"id"`
Title string `json:"title"`
Source BitbucketCloudPullRequestSource `json:"source"`
Author string `json:"author"`
Author BitbucketCloudPullRequestAuthor `json:"author"`
}
type BitbucketCloudPullRequestSource struct {
@@ -35,6 +35,11 @@ type BitbucketCloudPullRequestSourceCommit struct {
Hash string `json:"hash"`
}
// Also have display_name and uuid, but don't plan to use them.
type BitbucketCloudPullRequestAuthor struct {
Nickname string `json:"nickname"`
}
type PullRequestResponse struct {
Page int32 `json:"page"`
Size int32 `json:"size"`
@@ -134,7 +139,7 @@ func (b *BitbucketCloudService) List(_ context.Context) ([]*PullRequest, error)
Title: pull.Title,
Branch: pull.Source.Branch.Name,
HeadSHA: pull.Source.Commit.Hash,
Author: pull.Author,
Author: pull.Author.Nickname,
})
}

View File

@@ -37,7 +37,9 @@ func defaultHandlerCloud(t *testing.T) func(http.ResponseWriter, *http.Request)
"hash": "1a8dd249c04a"
}
},
"author": "testName"
"author": {
"nickname": "testName"
}
}
]
}`)
@@ -154,7 +156,9 @@ func TestListPullRequestPaginationCloud(t *testing.T) {
"hash": "1a8dd249c04a"
}
},
"author": "testName"
"author": {
"nickname": "testName"
}
},
{
"id": 102,
@@ -168,7 +172,9 @@ func TestListPullRequestPaginationCloud(t *testing.T) {
"hash": "4cf807e67a6d"
}
},
"author": "testName"
"author": {
"nickname": "testName"
}
}
]
}`, r.Host))
@@ -191,7 +197,9 @@ func TestListPullRequestPaginationCloud(t *testing.T) {
"hash": "6344d9623e3b"
}
},
"author": "testName"
"author": {
"nickname": "testName"
}
}
]
}`, r.Host))
@@ -339,7 +347,9 @@ func TestListPullRequestBranchMatchCloud(t *testing.T) {
"hash": "1a8dd249c04a"
}
},
"author": "testName"
"author": {
"nickname": "testName"
}
},
{
"id": 200,
@@ -353,7 +363,9 @@ func TestListPullRequestBranchMatchCloud(t *testing.T) {
"hash": "4cf807e67a6d"
}
},
"author": "testName"
"author": {
"nickname": "testName"
}
}
]
}`, r.Host))
@@ -376,7 +388,9 @@ func TestListPullRequestBranchMatchCloud(t *testing.T) {
"hash": "6344d9623e3b"
}
},
"author": "testName"
"author": {
"nickname": "testName"
}
}
]
}`, r.Host))

View File

@@ -25,6 +25,7 @@ import (
appclientset "github.com/argoproj/argo-cd/v2/pkg/client/clientset/versioned"
"github.com/argoproj/argo-cd/v2/pkg/ratelimiter"
"github.com/argoproj/argo-cd/v2/reposerver/apiclient"
"github.com/argoproj/argo-cd/v2/util/argo"
"github.com/argoproj/argo-cd/v2/util/argo/normalizers"
cacheutil "github.com/argoproj/argo-cd/v2/util/cache"
appstatecache "github.com/argoproj/argo-cd/v2/util/cache/appstate"
@@ -82,6 +83,9 @@ func NewCommand() *cobra.Command {
enableDynamicClusterDistribution bool
serverSideDiff bool
ignoreNormalizerOpts normalizers.IgnoreNormalizerOpts
// argocd k8s event logging flag
enableK8sEvent []string
)
command := cobra.Command{
Use: cliName,
@@ -190,6 +194,7 @@ func NewCommand() *cobra.Command {
serverSideDiff,
enableDynamicClusterDistribution,
ignoreNormalizerOpts,
enableK8sEvent,
)
errors.CheckError(err)
cacheutil.CollectMetrics(redisClient, appController.GetMetricsServer())
@@ -267,6 +272,9 @@ func NewCommand() *cobra.Command {
command.Flags().BoolVar(&enableDynamicClusterDistribution, "dynamic-cluster-distribution-enabled", env.ParseBoolFromEnv(common.EnvEnableDynamicClusterDistribution, false), "Enables dynamic cluster distribution.")
command.Flags().BoolVar(&serverSideDiff, "server-side-diff-enabled", env.ParseBoolFromEnv(common.EnvServerSideDiff, false), "Feature flag to enable ServerSide diff. Default (\"false\")")
command.Flags().DurationVar(&ignoreNormalizerOpts.JQExecutionTimeout, "ignore-normalizer-jq-execution-timeout-seconds", env.ParseDurationFromEnv("ARGOCD_IGNORE_NORMALIZER_JQ_TIMEOUT", 0*time.Second, 0, math.MaxInt64), "Set ignore normalizer JQ execution timeout")
// argocd k8s event logging flag
command.Flags().StringSliceVar(&enableK8sEvent, "enable-k8s-event", env.StringsFromEnv("ARGOCD_ENABLE_K8S_EVENT", argo.DefaultEnableEventList(), ","), "Enable ArgoCD to use k8s event. For disabling all events, set the value as `none`. (e.g --enable-k8s-event=none), For enabling specific events, set the value as `event reason`. (e.g --enable-k8s-event=StatusRefreshed,ResourceCreated)")
cacheSource = appstatecache.AddCacheFlagsToCmd(&command, cacheutil.Options{
OnClientCreated: func(client *redis.Client) {
redisClient = client

View File

@@ -27,6 +27,7 @@ import (
reposervercache "github.com/argoproj/argo-cd/v2/reposerver/cache"
"github.com/argoproj/argo-cd/v2/server"
servercache "github.com/argoproj/argo-cd/v2/server/cache"
"github.com/argoproj/argo-cd/v2/util/argo"
cacheutil "github.com/argoproj/argo-cd/v2/util/cache"
"github.com/argoproj/argo-cd/v2/util/cli"
"github.com/argoproj/argo-cd/v2/util/dex"
@@ -91,6 +92,9 @@ func NewCommand() *cobra.Command {
scmRootCAPath string
allowedScmProviders []string
enableScmProviders bool
// argocd k8s event logging flag
enableK8sEvent []string
)
command := &cobra.Command{
Use: cliName,
@@ -151,6 +155,7 @@ func NewCommand() *cobra.Command {
controllerClient, err := client.New(config, client.Options{Scheme: scheme})
errors.CheckError(err)
controllerClient = client.NewDryRunClient(controllerClient)
controllerClient = client.NewNamespacedClient(controllerClient, namespace)
// Load CA information to use for validating connections to the
// repository server, if strict TLS validation was requested.
@@ -229,6 +234,7 @@ func NewCommand() *cobra.Command {
ApplicationNamespaces: applicationNamespaces,
EnableProxyExtension: enableProxyExtension,
WebhookParallelism: webhookParallelism,
EnableK8sEvent: enableK8sEvent,
}
appsetOpts := server.ApplicationSetOpts{
@@ -303,6 +309,7 @@ func NewCommand() *cobra.Command {
command.Flags().StringSliceVar(&applicationNamespaces, "application-namespaces", env.StringsFromEnv("ARGOCD_APPLICATION_NAMESPACES", []string{}, ","), "List of additional namespaces where application resources can be managed in")
command.Flags().BoolVar(&enableProxyExtension, "enable-proxy-extension", env.ParseBoolFromEnv("ARGOCD_SERVER_ENABLE_PROXY_EXTENSION", false), "Enable Proxy Extension feature")
command.Flags().IntVar(&webhookParallelism, "webhook-parallelism-limit", env.ParseNumFromEnv("ARGOCD_SERVER_WEBHOOK_PARALLELISM_LIMIT", 50, 1, 1000), "Number of webhook requests processed concurrently")
command.Flags().StringSliceVar(&enableK8sEvent, "enable-k8s-event", env.StringsFromEnv("ARGOCD_ENABLE_K8S_EVENT", argo.DefaultEnableEventList(), ","), "Enable ArgoCD to use k8s event. For disabling all events, set the value as `none`. (e.g --enable-k8s-event=none), For enabling specific events, set the value as `event reason`. (e.g --enable-k8s-event=StatusRefreshed,ResourceCreated)")
// Flags related to the applicationSet component.
command.Flags().StringVar(&scmRootCAPath, "appset-scm-root-ca-path", env.StringFromEnv("ARGOCD_APPLICATIONSET_CONTROLLER_SCM_ROOT_CA_PATH", ""), "Provide Root CA Path for self-signed TLS Certificates")

View File

@@ -379,7 +379,8 @@ func NewApplicationGetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Com
})
errors.CheckError(err)
if app.Spec.HasMultipleSources() {
// check for source position if --show-params is set
if app.Spec.HasMultipleSources() && showParams {
if sourcePosition <= 0 {
errors.CheckError(fmt.Errorf("Source position should be specified and must be greater than 0 for applications with multiple sources"))
}

View File

@@ -15,7 +15,8 @@ import (
"github.com/spf13/cobra"
"github.com/spf13/pflag"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/runtime"
runtimeUtil "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/kubernetes"
cache2 "k8s.io/client-go/tools/cache"
@@ -202,7 +203,7 @@ func MaybeStartLocalServer(ctx context.Context, clientOpts *apiclient.ClientOpti
}
// get rid of logging error handler
runtime.ErrorHandlers = runtime.ErrorHandlers[1:]
runtimeUtil.ErrorHandlers = runtimeUtil.ErrorHandlers[1:]
cli.SetLogLevel(log.ErrorLevel.String())
log.SetLevel(log.ErrorLevel)
os.Setenv(v1alpha1.EnvVarFakeInClusterConfig, "true")
@@ -237,7 +238,14 @@ func MaybeStartLocalServer(ctx context.Context, clientOpts *apiclient.ClientOpti
return fmt.Errorf("error creating kubernetes dynamic clientset: %w", err)
}
controllerClientset, err := client.New(restConfig, client.Options{})
scheme := runtime.NewScheme()
err = v1alpha1.AddToScheme(scheme)
if err != nil {
return fmt.Errorf("error adding argo resources to scheme: %w", err)
}
controllerClientset, err := client.New(restConfig, client.Options{
Scheme: scheme,
})
if err != nil {
return fmt.Errorf("error creating kubernetes controller clientset: %w", err)
}

View File

@@ -4,9 +4,9 @@ import (
"os"
"path/filepath"
"github.com/spf13/cobra"
"github.com/argoproj/argo-cd/v2/cmd/util"
_ "go.uber.org/automaxprocs"
"github.com/spf13/cobra"
appcontroller "github.com/argoproj/argo-cd/v2/cmd/argocd-application-controller/commands"
applicationset "github.com/argoproj/argo-cd/v2/cmd/argocd-applicationset-controller/commands"
@@ -31,9 +31,12 @@ func main() {
if val := os.Getenv(binaryNameEnv); val != "" {
binaryName = val
}
isCLI := false
switch binaryName {
case "argocd", "argocd-linux-amd64", "argocd-darwin-amd64", "argocd-windows-amd64.exe":
command = cli.NewCommand()
isCLI = true
case "argocd-server":
command = apiserver.NewCommand()
case "argocd-application-controller":
@@ -42,19 +45,24 @@ func main() {
command = reposerver.NewCommand()
case "argocd-cmp-server":
command = cmpserver.NewCommand()
isCLI = true
case "argocd-dex":
command = dex.NewCommand()
case "argocd-notifications":
command = notification.NewCommand()
case "argocd-git-ask-pass":
command = gitaskpass.NewCommand()
isCLI = true
case "argocd-applicationset-controller":
command = applicationset.NewCommand()
case "argocd-k8s-auth":
command = k8sauth.NewCommand()
isCLI = true
default:
command = cli.NewCommand()
isCLI = true
}
util.SetAutoMaxProcs(isCLI)
if err := command.Execute(); err != nil {
os.Exit(1)

View File

@@ -9,6 +9,8 @@ import (
"strings"
"time"
"go.uber.org/automaxprocs/maxprocs"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"github.com/argoproj/gitops-engine/pkg/utils/kube"
@@ -88,6 +90,19 @@ type AppOptions struct {
ref string
}
// SetAutoMaxProcs sets the GOMAXPROCS value based on the binary name.
// It suppresses logs for CLI binaries and logs the setting for services.
func SetAutoMaxProcs(isCLI bool) {
if isCLI {
_, _ = maxprocs.Set() // Intentionally ignore errors for CLI binaries
} else {
_, err := maxprocs.Set(maxprocs.Logger(log.Infof))
if err != nil {
log.Errorf("Error setting GOMAXPROCS: %v", err)
}
}
}
func AddAppFlags(command *cobra.Command, opts *AppOptions) {
command.Flags().StringVar(&opts.repoURL, "repo", "", "Repository URL, ignored if a file is set")
command.Flags().StringVar(&opts.appPath, "path", "", "Path in repository to the app directory, ignored if a file is set")

View File

@@ -1,10 +1,11 @@
package util
import (
"bytes"
"log"
"os"
"testing"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -529,3 +530,27 @@ func TestFilterResources(t *testing.T) {
assert.Nil(t, filteredResources)
})
}
func TestSetAutoMaxProcs(t *testing.T) {
t.Run("CLI mode ignores errors", func(t *testing.T) {
logBuffer := &bytes.Buffer{}
oldLogger := log.Default()
log.SetOutput(logBuffer)
defer log.SetOutput(oldLogger.Writer())
SetAutoMaxProcs(true)
assert.Empty(t, logBuffer.String(), "Expected no log output when isCLI is true")
})
t.Run("Non-CLI mode logs error on failure", func(t *testing.T) {
logBuffer := &bytes.Buffer{}
oldLogger := log.Default()
log.SetOutput(logBuffer)
defer log.SetOutput(oldLogger.Writer())
SetAutoMaxProcs(false)
assert.NotContains(t, logBuffer.String(), "Error setting GOMAXPROCS", "Unexpected log output detected")
})
}

View File

@@ -175,6 +175,7 @@ func NewApplicationController(
serverSideDiff bool,
dynamicClusterDistributionEnabled bool,
ignoreNormalizerOpts normalizers.IgnoreNormalizerOpts,
enableK8sEvent []string,
) (*ApplicationController, error) {
log.Infof("appResyncPeriod=%v, appHardResyncPeriod=%v, appResyncJitter=%v", appResyncPeriod, appHardResyncPeriod, appResyncJitter)
db := db.NewDB(namespace, settingsMgr, kubeClientset)
@@ -199,7 +200,7 @@ func NewApplicationController(
statusRefreshJitter: appResyncJitter,
refreshRequestedApps: make(map[string]CompareWith),
refreshRequestedAppsMutex: &sync.Mutex{},
auditLogger: argo.NewAuditLogger(namespace, kubeClientset, common.ApplicationController),
auditLogger: argo.NewAuditLogger(namespace, kubeClientset, common.ApplicationController, enableK8sEvent),
settingsMgr: settingsMgr,
selfHealTimeout: selfHealTimeout,
selfHealBackOff: selfHealBackoff,

View File

@@ -45,12 +45,15 @@ import (
"github.com/argoproj/argo-cd/v2/reposerver/apiclient"
mockrepoclient "github.com/argoproj/argo-cd/v2/reposerver/apiclient/mocks"
"github.com/argoproj/argo-cd/v2/test"
"github.com/argoproj/argo-cd/v2/util/argo"
"github.com/argoproj/argo-cd/v2/util/argo/normalizers"
cacheutil "github.com/argoproj/argo-cd/v2/util/cache"
appstatecache "github.com/argoproj/argo-cd/v2/util/cache/appstate"
"github.com/argoproj/argo-cd/v2/util/settings"
)
var testEnableEventList []string = argo.DefaultEnableEventList()
type namespacedResource struct {
v1alpha1.ResourceNode
AppName string
@@ -170,6 +173,7 @@ func newFakeController(data *fakeData, repoErr error) *ApplicationController {
false,
false,
normalizers.IgnoreNormalizerOpts{},
testEnableEventList,
)
db := &dbmocks.ArgoDB{}
db.On("GetApplicationControllerReplicas").Return(1)

View File

@@ -31,6 +31,7 @@ argocd-application-controller [flags]
--default-cache-expiration duration Cache expiration default (default 24h0m0s)
--disable-compression If true, opt-out of response compression for all requests to the server
--dynamic-cluster-distribution-enabled Enables dynamic cluster distribution.
--enable-k8s-event none Enable ArgoCD to use k8s event. For disabling all events, set the value as none. (e.g --enable-k8s-event=none), For enabling specific events, set the value as `event reason`. (e.g --enable-k8s-event=StatusRefreshed,ResourceCreated) (default [all])
--gloglevel int Set the glog logging level
-h, --help help for argocd-application-controller
--ignore-normalizer-jq-execution-timeout-seconds duration Set ignore normalizer JQ execution timeout

View File

@@ -51,6 +51,7 @@ argocd-server [flags]
--disable-auth Disable client authentication
--disable-compression If true, opt-out of response compression for all requests to the server
--enable-gzip Enable GZIP compression (default true)
--enable-k8s-event none Enable ArgoCD to use k8s event. For disabling all events, set the value as none. (e.g --enable-k8s-event=none), For enabling specific events, set the value as `event reason`. (e.g --enable-k8s-event=StatusRefreshed,ResourceCreated) (default [all])
--enable-proxy-extension Enable Proxy Extension feature
--gloglevel int Set the glog logging level
-h, --help help for argocd-server

View File

@@ -5,7 +5,7 @@ kind: Kustomization
images:
- name: quay.io/argoproj/argocd
newName: quay.io/argoproj/argocd
newTag: v2.13.0
newTag: v2.13.2
resources:
- ./application-controller
- ./dex

View File

@@ -15,7 +15,6 @@ rules:
- delete # supports deletion a live object in UI
- get # supports viewing live object manifest in UI
- patch # supports `argocd app patch`
- list # supports `argocd appset generate` with cluster generator
- apiGroups:
- ""
resources:

View File

@@ -22571,7 +22571,7 @@ spec:
key: applicationsetcontroller.webhook.parallelism.limit
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.13.0
image: quay.io/argoproj/argocd:v2.13.2
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -22689,7 +22689,7 @@ spec:
- argocd
- admin
- redis-initial-password
image: quay.io/argoproj/argocd:v2.13.0
image: quay.io/argoproj/argocd:v2.13.2
imagePullPolicy: IfNotPresent
name: secret-init
securityContext:
@@ -22942,7 +22942,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v2.13.0
image: quay.io/argoproj/argocd:v2.13.2
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -22994,7 +22994,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v2.13.0
image: quay.io/argoproj/argocd:v2.13.2
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -23284,7 +23284,7 @@ spec:
key: controller.ignore.normalizer.jq.timeout
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.13.0
image: quay.io/argoproj/argocd:v2.13.2
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -12,4 +12,4 @@ resources:
images:
- name: quay.io/argoproj/argocd
newName: quay.io/argoproj/argocd
newTag: v2.13.0
newTag: v2.13.2

View File

@@ -12,7 +12,7 @@ patches:
images:
- name: quay.io/argoproj/argocd
newName: quay.io/argoproj/argocd
newTag: v2.13.0
newTag: v2.13.2
resources:
- ../../base/application-controller
- ../../base/applicationset-controller

View File

@@ -22476,7 +22476,6 @@ rules:
- delete
- get
- patch
- list
- apiGroups:
- ""
resources:
@@ -23915,7 +23914,7 @@ spec:
key: applicationsetcontroller.webhook.parallelism.limit
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.13.0
image: quay.io/argoproj/argocd:v2.13.2
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -24050,7 +24049,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:v2.13.0
image: quay.io/argoproj/argocd:v2.13.2
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -24138,7 +24137,7 @@ spec:
key: notificationscontroller.repo.server.plaintext
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.13.0
image: quay.io/argoproj/argocd:v2.13.2
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -24257,7 +24256,7 @@ spec:
- argocd
- admin
- redis-initial-password
image: quay.io/argoproj/argocd:v2.13.0
image: quay.io/argoproj/argocd:v2.13.2
imagePullPolicy: IfNotPresent
name: secret-init
securityContext:
@@ -24538,7 +24537,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v2.13.0
image: quay.io/argoproj/argocd:v2.13.2
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -24590,7 +24589,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v2.13.0
image: quay.io/argoproj/argocd:v2.13.2
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -24944,7 +24943,7 @@ spec:
key: applicationsetcontroller.enable.scm.providers
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.13.0
image: quay.io/argoproj/argocd:v2.13.2
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -25270,7 +25269,7 @@ spec:
key: controller.ignore.normalizer.jq.timeout
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.13.0
image: quay.io/argoproj/argocd:v2.13.2
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -1694,7 +1694,7 @@ spec:
key: applicationsetcontroller.webhook.parallelism.limit
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.13.0
image: quay.io/argoproj/argocd:v2.13.2
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -1829,7 +1829,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:v2.13.0
image: quay.io/argoproj/argocd:v2.13.2
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -1917,7 +1917,7 @@ spec:
key: notificationscontroller.repo.server.plaintext
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.13.0
image: quay.io/argoproj/argocd:v2.13.2
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -2036,7 +2036,7 @@ spec:
- argocd
- admin
- redis-initial-password
image: quay.io/argoproj/argocd:v2.13.0
image: quay.io/argoproj/argocd:v2.13.2
imagePullPolicy: IfNotPresent
name: secret-init
securityContext:
@@ -2317,7 +2317,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v2.13.0
image: quay.io/argoproj/argocd:v2.13.2
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -2369,7 +2369,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v2.13.0
image: quay.io/argoproj/argocd:v2.13.2
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -2723,7 +2723,7 @@ spec:
key: applicationsetcontroller.enable.scm.providers
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.13.0
image: quay.io/argoproj/argocd:v2.13.2
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -3049,7 +3049,7 @@ spec:
key: controller.ignore.normalizer.jq.timeout
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.13.0
image: quay.io/argoproj/argocd:v2.13.2
imagePullPolicy: Always
name: argocd-application-controller
ports:

17
manifests/install.yaml generated
View File

@@ -22443,7 +22443,6 @@ rules:
- delete
- get
- patch
- list
- apiGroups:
- ""
resources:
@@ -23032,7 +23031,7 @@ spec:
key: applicationsetcontroller.webhook.parallelism.limit
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.13.0
image: quay.io/argoproj/argocd:v2.13.2
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -23167,7 +23166,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:v2.13.0
image: quay.io/argoproj/argocd:v2.13.2
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -23255,7 +23254,7 @@ spec:
key: notificationscontroller.repo.server.plaintext
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.13.0
image: quay.io/argoproj/argocd:v2.13.2
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -23355,7 +23354,7 @@ spec:
- argocd
- admin
- redis-initial-password
image: quay.io/argoproj/argocd:v2.13.0
image: quay.io/argoproj/argocd:v2.13.2
imagePullPolicy: IfNotPresent
name: secret-init
securityContext:
@@ -23608,7 +23607,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v2.13.0
image: quay.io/argoproj/argocd:v2.13.2
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -23660,7 +23659,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v2.13.0
image: quay.io/argoproj/argocd:v2.13.2
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -24012,7 +24011,7 @@ spec:
key: applicationsetcontroller.enable.scm.providers
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.13.0
image: quay.io/argoproj/argocd:v2.13.2
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -24338,7 +24337,7 @@ spec:
key: controller.ignore.normalizer.jq.timeout
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.13.0
image: quay.io/argoproj/argocd:v2.13.2
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -811,7 +811,7 @@ spec:
key: applicationsetcontroller.webhook.parallelism.limit
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.13.0
image: quay.io/argoproj/argocd:v2.13.2
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -946,7 +946,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:v2.13.0
image: quay.io/argoproj/argocd:v2.13.2
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -1034,7 +1034,7 @@ spec:
key: notificationscontroller.repo.server.plaintext
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.13.0
image: quay.io/argoproj/argocd:v2.13.2
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -1134,7 +1134,7 @@ spec:
- argocd
- admin
- redis-initial-password
image: quay.io/argoproj/argocd:v2.13.0
image: quay.io/argoproj/argocd:v2.13.2
imagePullPolicy: IfNotPresent
name: secret-init
securityContext:
@@ -1387,7 +1387,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v2.13.0
image: quay.io/argoproj/argocd:v2.13.2
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -1439,7 +1439,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v2.13.0
image: quay.io/argoproj/argocd:v2.13.2
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -1791,7 +1791,7 @@ spec:
key: applicationsetcontroller.enable.scm.providers
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.13.0
image: quay.io/argoproj/argocd:v2.13.2
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -2117,7 +2117,7 @@ spec:
key: controller.ignore.normalizer.jq.timeout
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.13.0
image: quay.io/argoproj/argocd:v2.13.2
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -7,12 +7,13 @@ hs.message = "Waiting for status"
if obj.status ~= nil then
if obj.status.conditions ~= nil then
for i, condition in ipairs(obj.status.conditions) do
if condition.status == "False" then
-- InsufficientPods can have valid use cases
-- See a discussion in https://github.com/argoproj/argo-cd/issues/20171 for more details
if condition.status == "False" and condition.reason ~= "InsufficientPods" then
hs.status = "Degraded"
hs.message = "PodDisruptionBudget has " .. condition.reason
return hs
end
if condition.status == "True" then
else
hs.status = "Healthy"
hs.message = "PodDisruptionBudget has " .. condition.reason
end

View File

@@ -9,5 +9,5 @@ tests:
inputPath: testdata/progressing.yaml
- healthStatus:
status: Degraded
message: 'PodDisruptionBudget has InsufficientPods'
message: 'PodDisruptionBudget has SyncFailed'
inputPath: testdata/degraded.yaml

View File

@@ -16,6 +16,12 @@ status:
reason: InsufficientPods
status: "False"
type: DisruptionAllowed
- lastTransitionTime: "2024-09-06T18:29:06Z"
message: ""
observedGeneration: 2
reason: SyncFailed
status: "False"
type: DisruptionAllowed
currentHealthy: 2
desiredHealthy: 3
disruptionsAllowed: 0

View File

@@ -112,6 +112,7 @@ func NewServer(
settingsMgr *settings.SettingsManager,
projInformer cache.SharedIndexInformer,
enabledNamespaces []string,
enableK8sEvent []string,
) (application.ApplicationServiceServer, AppResourceTreeFn) {
if appBroadcaster == nil {
appBroadcaster = &broadcasterHandler{}
@@ -133,7 +134,7 @@ func NewServer(
kubectl: kubectl,
enf: enf,
projectLock: projectLock,
auditLogger: argo.NewAuditLogger(namespace, kubeclientset, "argocd-server"),
auditLogger: argo.NewAuditLogger(namespace, kubeclientset, "argocd-server", enableK8sEvent),
settingsMgr: settingsMgr,
projInformer: projInformer,
enabledNamespaces: enabledNamespaces,
@@ -2210,7 +2211,7 @@ func getAmbiguousRevision(app *appv1.Application, syncReq *application.Applicati
ambiguousRevision := ""
if app.Spec.HasMultipleSources() {
for i, pos := range syncReq.SourcePositions {
if pos == int64(sourceIndex) {
if pos == int64(sourceIndex+1) {
ambiguousRevision = syncReq.Revisions[i]
}
}

View File

@@ -69,6 +69,8 @@ const (
fakeRepoURL = "https://git.com/repo.git"
)
var testEnableEventList []string = argo.DefaultEnableEventList()
func fakeRepo() *appsv1.Repository {
return &appsv1.Repository{
Repo: fakeRepoURL,
@@ -306,6 +308,7 @@ func newTestAppServerWithEnforcerConfigure(f func(*rbac.Enforcer), t *testing.T,
settingsMgr,
projInformer,
[]string{},
testEnableEventList,
)
return server.(*Server)
}
@@ -486,6 +489,7 @@ func newTestAppServerWithEnforcerConfigureWithBenchmark(f func(*rbac.Enforcer),
settingsMgr,
projInformer,
[]string{},
testEnableEventList,
)
return server.(*Server)
}
@@ -2934,7 +2938,7 @@ func TestGetAmbiguousRevision_MultiSource(t *testing.T) {
},
}
syncReq := &application.ApplicationSyncRequest{
SourcePositions: []int64{0, 1},
SourcePositions: []int64{1, 2},
Revisions: []string{"rev1", "rev2"},
}

View File

@@ -88,6 +88,7 @@ func NewServer(
scmRootCAPath string,
allowedScmProviders []string,
enableScmProviders bool,
enableK8sEvent []string,
) applicationset.ApplicationSetServiceServer {
s := &Server{
ns: namespace,
@@ -103,7 +104,7 @@ func NewServer(
projLister: projLister,
settings: settings,
projectLock: projectLock,
auditLogger: argo.NewAuditLogger(namespace, kubeclientset, "argocd-server"),
auditLogger: argo.NewAuditLogger(namespace, kubeclientset, "argocd-server", enableK8sEvent),
enabledNamespaces: enabledNamespaces,
GitSubmoduleEnabled: gitSubmoduleEnabled,
EnableNewGitFileGlobbing: enableNewGitFileGlobbing,

View File

@@ -22,6 +22,7 @@ import (
apps "github.com/argoproj/argo-cd/v2/pkg/client/clientset/versioned/fake"
appinformer "github.com/argoproj/argo-cd/v2/pkg/client/informers/externalversions"
"github.com/argoproj/argo-cd/v2/server/rbacpolicy"
"github.com/argoproj/argo-cd/v2/util/argo"
"github.com/argoproj/argo-cd/v2/util/assets"
"github.com/argoproj/argo-cd/v2/util/db"
"github.com/argoproj/argo-cd/v2/util/errors"
@@ -34,6 +35,8 @@ const (
fakeRepoURL = "https://git.com/repo.git"
)
var testEnableEventList []string = argo.DefaultEnableEventList()
func fakeRepo() *appsv1.Repository {
return &appsv1.Repository{
Repo: fakeRepoURL,
@@ -162,6 +165,7 @@ func newTestAppSetServerWithEnforcerConfigure(f func(*rbac.Enforcer), namespace
"",
[]string{},
true,
testEnableEventList,
)
return server.(*Server)
}

View File

@@ -58,9 +58,9 @@ type Server struct {
// NewServer returns a new instance of the Project service
func NewServer(ns string, kubeclientset kubernetes.Interface, appclientset appclientset.Interface, enf *rbac.Enforcer, projectLock sync.KeyLock, sessionMgr *session.SessionManager, policyEnf *rbacpolicy.RBACPolicyEnforcer,
projInformer cache.SharedIndexInformer, settingsMgr *settings.SettingsManager, db db.ArgoDB,
projInformer cache.SharedIndexInformer, settingsMgr *settings.SettingsManager, db db.ArgoDB, enableK8sEvent []string,
) *Server {
auditLogger := argo.NewAuditLogger(ns, kubeclientset, "argocd-server")
auditLogger := argo.NewAuditLogger(ns, kubeclientset, "argocd-server", enableK8sEvent)
return &Server{
enf: enf, policyEnf: policyEnf, appclientset: appclientset, kubeclientset: kubeclientset, ns: ns, projectLock: projectLock, auditLogger: auditLogger, sessionMgr: sessionMgr,
projInformer: projInformer, settingsMgr: settingsMgr, db: db,

View File

@@ -6,6 +6,7 @@ import (
"strings"
"testing"
"github.com/argoproj/argo-cd/v2/util/argo"
"github.com/argoproj/argo-cd/v2/util/db"
"github.com/argoproj/pkg/sync"
@@ -37,6 +38,8 @@ import (
const testNamespace = "default"
var testEnableEventList []string = argo.DefaultEnableEventList()
func TestProjectServer(t *testing.T) {
kubeclientset := fake.NewSimpleClientset(&corev1.ConfigMap{
ObjectMeta: v1.ObjectMeta{
@@ -91,7 +94,7 @@ func TestProjectServer(t *testing.T) {
role1 := v1alpha1.ProjectRole{Name: roleName, JWTTokens: []v1alpha1.JWTToken{{IssuedAt: 1}}}
projectWithRole.Spec.Roles = append(projectWithRole.Spec.Roles, role1)
argoDB := db.NewDB("default", settingsMgr, kubeclientset)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projectWithRole), enforcer, sync.NewKeyLock(), sessionMgr, nil, projInformer, settingsMgr, argoDB)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projectWithRole), enforcer, sync.NewKeyLock(), sessionMgr, nil, projInformer, settingsMgr, argoDB, testEnableEventList)
err := projectServer.NormalizeProjs()
require.NoError(t, err)
@@ -105,7 +108,7 @@ func TestProjectServer(t *testing.T) {
enforcer.SetDefaultRole("role:projects")
_ = enforcer.SetBuiltinPolicy("p, role:projects, projects, update, *, allow")
argoDB := db.NewDB("default", settingsMgr, kubeclientset)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(&existingProj, &existingApp), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(&existingProj, &existingApp), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB, testEnableEventList)
updatedProj := existingProj.DeepCopy()
updatedProj.Spec.Destinations = nil
@@ -119,7 +122,7 @@ func TestProjectServer(t *testing.T) {
enforcer.SetDefaultRole("role:projects")
_ = enforcer.SetBuiltinPolicy("p, role:projects, projects, update, *, allow")
argoDB := db.NewDB("default", settingsMgr, kubeclientset)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(&existingProj, &existingApp), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(&existingProj, &existingApp), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB, testEnableEventList)
updatedProj := existingProj.DeepCopy()
updatedProj.Spec.SourceRepos = nil
@@ -133,7 +136,7 @@ func TestProjectServer(t *testing.T) {
enforcer.SetDefaultRole("role:projects")
_ = enforcer.SetBuiltinPolicy("p, role:projects, projects, update, *, allow")
argoDB := db.NewDB("default", settingsMgr, kubeclientset)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(&existingProj, &existingApp), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(&existingProj, &existingApp), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB, testEnableEventList)
updatedProj := existingProj.DeepCopy()
updatedProj.Spec.ClusterResourceWhitelist = []metav1.GroupKind{{}}
@@ -147,7 +150,7 @@ func TestProjectServer(t *testing.T) {
enforcer.SetDefaultRole("role:projects")
_ = enforcer.SetBuiltinPolicy("p, role:projects, projects, update, *, allow")
argoDB := db.NewDB("default", settingsMgr, kubeclientset)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(&existingProj, &existingApp), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(&existingProj, &existingApp), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB, testEnableEventList)
updatedProj := existingProj.DeepCopy()
updatedProj.Spec.NamespaceResourceBlacklist = []metav1.GroupKind{{}}
@@ -166,7 +169,7 @@ func TestProjectServer(t *testing.T) {
}
argoDB := db.NewDB("default", settingsMgr, kubeclientset)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(&existingProj, &existingApp), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(&existingProj, &existingApp), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB, testEnableEventList)
updatedProj := existingProj.DeepCopy()
updatedProj.Spec.Destinations = updatedProj.Spec.Destinations[1:]
@@ -183,7 +186,7 @@ func TestProjectServer(t *testing.T) {
}
argoDB := db.NewDB("default", settingsMgr, kubeclientset)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(&existingProj, &existingApp), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(&existingProj, &existingApp), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB, testEnableEventList)
updatedProj := existingProj.DeepCopy()
updatedProj.Spec.Destinations = updatedProj.Spec.Destinations[1:]
@@ -202,7 +205,7 @@ func TestProjectServer(t *testing.T) {
}
argoDB := db.NewDB("default", settingsMgr, kubeclientset)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(&existingProj, &existingApp), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(&existingProj, &existingApp), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB, testEnableEventList)
updatedProj := existingProj.DeepCopy()
updatedProj.Spec.SourceRepos = []string{}
@@ -219,7 +222,7 @@ func TestProjectServer(t *testing.T) {
}
argoDB := db.NewDB("default", settingsMgr, kubeclientset)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(&existingProj, &existingApp), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(&existingProj, &existingApp), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB, testEnableEventList)
updatedProj := existingProj.DeepCopy()
updatedProj.Spec.SourceRepos = []string{}
@@ -239,7 +242,7 @@ func TestProjectServer(t *testing.T) {
Spec: v1alpha1.ApplicationSpec{Project: "test", Source: &v1alpha1.ApplicationSource{RepoURL: "https://github.com/argoproj/argo-cd.git"}},
}
argoDB := db.NewDB("default", settingsMgr, kubeclientset)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(proj, &existingApp), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(proj, &existingApp), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB, testEnableEventList)
updatedProj := proj.DeepCopy()
updatedProj.Spec.SourceRepos = []string{"https://github.com/argoproj/*"}
@@ -266,7 +269,7 @@ func TestProjectServer(t *testing.T) {
argoDB := db.NewDB("default", settingsMgr, kubeclientset)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(proj, &existingApp), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(proj, &existingApp), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB, testEnableEventList)
updatedProj := proj.DeepCopy()
updatedProj.Spec.Destinations = []v1alpha1.ApplicationDestination{
@@ -281,7 +284,7 @@ func TestProjectServer(t *testing.T) {
t.Run("TestDeleteProjectSuccessful", func(t *testing.T) {
argoDB := db.NewDB("default", settingsMgr, kubeclientset)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(&existingProj), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(&existingProj), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB, testEnableEventList)
_, err := projectServer.Delete(context.Background(), &project.ProjectQuery{Name: "test"})
@@ -294,7 +297,7 @@ func TestProjectServer(t *testing.T) {
Spec: v1alpha1.AppProjectSpec{},
}
argoDB := db.NewDB("default", settingsMgr, kubeclientset)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(&defaultProj), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(&defaultProj), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB, testEnableEventList)
_, err := projectServer.Delete(context.Background(), &project.ProjectQuery{Name: defaultProj.Name})
statusCode, _ := status.FromError(err)
@@ -308,7 +311,7 @@ func TestProjectServer(t *testing.T) {
}
argoDB := db.NewDB("default", settingsMgr, kubeclientset)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(&existingProj, &existingApp), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(&existingProj, &existingApp), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB, testEnableEventList)
_, err := projectServer.Delete(context.Background(), &project.ProjectQuery{Name: "test"})
@@ -335,7 +338,7 @@ func TestProjectServer(t *testing.T) {
projectWithRole.Spec.Roles = []v1alpha1.ProjectRole{{Name: tokenName}}
argoDB := db.NewDB("default", settingsMgr, kubeclientset)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projectWithRole), enforcer, sync.NewKeyLock(), sessionMgr, policyEnf, projInformer, settingsMgr, argoDB)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projectWithRole), enforcer, sync.NewKeyLock(), sessionMgr, policyEnf, projInformer, settingsMgr, argoDB, testEnableEventList)
_, err := projectServer.CreateToken(ctx, &project.ProjectTokenCreateRequest{Project: projectWithRole.Name, Role: tokenName, ExpiresIn: 1})
assert.EqualError(t, err, "rpc error: code = PermissionDenied desc = permission denied: projects, update, test")
})
@@ -345,7 +348,7 @@ func TestProjectServer(t *testing.T) {
projectWithRole := existingProj.DeepCopy()
projectWithRole.Spec.Roles = []v1alpha1.ProjectRole{{Name: tokenName, Groups: []string{"my-group"}}}
argoDB := db.NewDB("default", settingsMgr, kubeclientset)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projectWithRole), enforcer, sync.NewKeyLock(), sessionMgr, policyEnf, projInformer, settingsMgr, argoDB)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projectWithRole), enforcer, sync.NewKeyLock(), sessionMgr, policyEnf, projInformer, settingsMgr, argoDB, testEnableEventList)
_, err := projectServer.CreateToken(ctx, &project.ProjectTokenCreateRequest{Project: projectWithRole.Name, Role: tokenName, ExpiresIn: 1})
require.NoError(t, err)
})
@@ -359,7 +362,7 @@ func TestProjectServer(t *testing.T) {
sessionMgr := session.NewSessionManager(settingsMgr, test.NewFakeProjListerFromInterface(clientset.ArgoprojV1alpha1().AppProjects("default")), "", nil, session.NewUserStateStorage(nil))
argoDB := db.NewDB("default", settingsMgr, kubeclientset)
projectServer := NewServer("default", fake.NewSimpleClientset(), clientset, enforcer, sync.NewKeyLock(), sessionMgr, policyEnf, projInformer, settingsMgr, argoDB)
projectServer := NewServer("default", fake.NewSimpleClientset(), clientset, enforcer, sync.NewKeyLock(), sessionMgr, policyEnf, projInformer, settingsMgr, argoDB, testEnableEventList)
tokenResponse, err := projectServer.CreateToken(context.Background(), &project.ProjectTokenCreateRequest{Project: projectWithRole.Name, Role: tokenName, ExpiresIn: 100})
require.NoError(t, err)
claims, _, err := sessionMgr.Parse(tokenResponse.Token)
@@ -380,7 +383,7 @@ func TestProjectServer(t *testing.T) {
sessionMgr := session.NewSessionManager(settingsMgr, test.NewFakeProjListerFromInterface(clientset.ArgoprojV1alpha1().AppProjects("default")), "", nil, session.NewUserStateStorage(nil))
argoDB := db.NewDB("default", settingsMgr, kubeclientset)
projectServer := NewServer("default", fake.NewSimpleClientset(), clientset, enforcer, sync.NewKeyLock(), sessionMgr, policyEnf, projInformer, settingsMgr, argoDB)
projectServer := NewServer("default", fake.NewSimpleClientset(), clientset, enforcer, sync.NewKeyLock(), sessionMgr, policyEnf, projInformer, settingsMgr, argoDB, testEnableEventList)
tokenResponse, err := projectServer.CreateToken(context.Background(), &project.ProjectTokenCreateRequest{Project: projectWithRole.Name, Role: tokenName, ExpiresIn: 1, Id: id})
require.NoError(t, err)
claims, _, err := sessionMgr.Parse(tokenResponse.Token)
@@ -401,7 +404,7 @@ func TestProjectServer(t *testing.T) {
sessionMgr := session.NewSessionManager(settingsMgr, test.NewFakeProjListerFromInterface(clientset.ArgoprojV1alpha1().AppProjects("default")), "", nil, session.NewUserStateStorage(nil))
argoDB := db.NewDB("default", settingsMgr, kubeclientset)
projectServer := NewServer("default", fake.NewSimpleClientset(), clientset, enforcer, sync.NewKeyLock(), sessionMgr, policyEnf, projInformer, settingsMgr, argoDB)
projectServer := NewServer("default", fake.NewSimpleClientset(), clientset, enforcer, sync.NewKeyLock(), sessionMgr, policyEnf, projInformer, settingsMgr, argoDB, testEnableEventList)
tokenResponse, err := projectServer.CreateToken(context.Background(), &project.ProjectTokenCreateRequest{Project: projectWithRole.Name, Role: tokenName, ExpiresIn: 1, Id: id})
require.NoError(t, err)
@@ -430,7 +433,7 @@ func TestProjectServer(t *testing.T) {
token := v1alpha1.ProjectRole{Name: tokenName, JWTTokens: []v1alpha1.JWTToken{{IssuedAt: issuedAt}, {IssuedAt: secondIssuedAt}}}
projWithToken.Spec.Roles = append(projWithToken.Spec.Roles, token)
argoDB := db.NewDB("default", settingsMgr, kubeclientset)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projWithToken), enforcer, sync.NewKeyLock(), sessionMgr, policyEnf, projInformer, settingsMgr, argoDB)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projWithToken), enforcer, sync.NewKeyLock(), sessionMgr, policyEnf, projInformer, settingsMgr, argoDB, testEnableEventList)
_, err := projectServer.DeleteToken(ctx, &project.ProjectTokenDeleteRequest{Project: projWithToken.Name, Role: tokenName, Iat: issuedAt})
assert.EqualError(t, err, "rpc error: code = PermissionDenied desc = permission denied: projects, update, test")
})
@@ -443,7 +446,7 @@ func TestProjectServer(t *testing.T) {
token := v1alpha1.ProjectRole{Name: tokenName, Groups: []string{"my-group"}, JWTTokens: []v1alpha1.JWTToken{{IssuedAt: issuedAt}, {IssuedAt: secondIssuedAt}}}
projWithToken.Spec.Roles = append(projWithToken.Spec.Roles, token)
argoDB := db.NewDB("default", settingsMgr, kubeclientset)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projWithToken), enforcer, sync.NewKeyLock(), sessionMgr, policyEnf, projInformer, settingsMgr, argoDB)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projWithToken), enforcer, sync.NewKeyLock(), sessionMgr, policyEnf, projInformer, settingsMgr, argoDB, testEnableEventList)
_, err := projectServer.DeleteToken(ctx, &project.ProjectTokenDeleteRequest{Project: projWithToken.Name, Role: tokenName, Iat: issuedAt})
require.NoError(t, err)
})
@@ -459,7 +462,7 @@ p, role:admin, projects, update, *, allow`)
token := v1alpha1.ProjectRole{Name: tokenName, JWTTokens: []v1alpha1.JWTToken{{IssuedAt: issuedAt}, {IssuedAt: secondIssuedAt}}}
projWithToken.Spec.Roles = append(projWithToken.Spec.Roles, token)
argoDB := db.NewDB("default", settingsMgr, kubeclientset)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projWithToken), enforcer, sync.NewKeyLock(), sessionMgr, policyEnf, projInformer, settingsMgr, argoDB)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projWithToken), enforcer, sync.NewKeyLock(), sessionMgr, policyEnf, projInformer, settingsMgr, argoDB, testEnableEventList)
_, err := projectServer.DeleteToken(ctx, &project.ProjectTokenDeleteRequest{Project: projWithToken.Name, Role: tokenName, Iat: issuedAt})
require.NoError(t, err)
projWithoutToken, err := projectServer.Get(context.Background(), &project.ProjectQuery{Name: projWithToken.Name})
@@ -483,7 +486,7 @@ p, role:admin, projects, update, *, allow`)
token := v1alpha1.ProjectRole{Name: tokenName, JWTTokens: []v1alpha1.JWTToken{{IssuedAt: issuedAt, ID: id}, {IssuedAt: secondIssuedAt, ID: secondId}}}
projWithToken.Spec.Roles = append(projWithToken.Spec.Roles, token)
argoDB := db.NewDB("default", settingsMgr, kubeclientset)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projWithToken), enforcer, sync.NewKeyLock(), sessionMgr, policyEnf, projInformer, settingsMgr, argoDB)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projWithToken), enforcer, sync.NewKeyLock(), sessionMgr, policyEnf, projInformer, settingsMgr, argoDB, testEnableEventList)
_, err := projectServer.DeleteToken(ctx, &project.ProjectTokenDeleteRequest{Project: projWithToken.Name, Role: tokenName, Iat: secondIssuedAt, Id: id})
require.NoError(t, err)
projWithoutToken, err := projectServer.Get(context.Background(), &project.ProjectQuery{Name: projWithToken.Name})
@@ -502,7 +505,7 @@ p, role:admin, projects, update, *, allow`)
token := v1alpha1.ProjectRole{Name: tokenName, JWTTokens: []v1alpha1.JWTToken{{IssuedAt: 1}}}
projWithToken.Spec.Roles = append(projWithToken.Spec.Roles, token)
argoDB := db.NewDB("default", settingsMgr, kubeclientset)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projWithToken), enforcer, sync.NewKeyLock(), sessionMgr, policyEnf, projInformer, settingsMgr, argoDB)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projWithToken), enforcer, sync.NewKeyLock(), sessionMgr, policyEnf, projInformer, settingsMgr, argoDB, testEnableEventList)
_, err := projectServer.CreateToken(context.Background(), &project.ProjectTokenCreateRequest{Project: projWithToken.Name, Role: tokenName})
require.NoError(t, err)
projWithTwoTokens, err := projectServer.Get(context.Background(), &project.ProjectQuery{Name: projWithToken.Name})
@@ -516,7 +519,7 @@ p, role:admin, projects, update, *, allow`)
wildSourceRepo := "*"
proj.Spec.SourceRepos = append(proj.Spec.SourceRepos, wildSourceRepo)
argoDB := db.NewDB("default", settingsMgr, kubeclientset)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(proj), enforcer, sync.NewKeyLock(), nil, policyEnf, projInformer, settingsMgr, argoDB)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(proj), enforcer, sync.NewKeyLock(), nil, policyEnf, projInformer, settingsMgr, argoDB, testEnableEventList)
request := &project.ProjectUpdateRequest{Project: proj}
updatedProj, err := projectServer.Update(context.Background(), request)
require.NoError(t, err)
@@ -535,7 +538,7 @@ p, role:admin, projects, update, *, allow`)
role.Policies = append(role.Policies, policy)
projWithRole.Spec.Roles = append(projWithRole.Spec.Roles, role)
argoDB := db.NewDB("default", settingsMgr, kubeclientset)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projWithRole), enforcer, sync.NewKeyLock(), nil, policyEnf, projInformer, settingsMgr, argoDB)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projWithRole), enforcer, sync.NewKeyLock(), nil, policyEnf, projInformer, settingsMgr, argoDB, testEnableEventList)
request := &project.ProjectUpdateRequest{Project: projWithRole}
_, err := projectServer.Update(context.Background(), request)
require.NoError(t, err)
@@ -557,7 +560,7 @@ p, role:admin, projects, update, *, allow`)
role.Policies = append(role.Policies, policy)
projWithRole.Spec.Roles = append(projWithRole.Spec.Roles, role)
argoDB := db.NewDB("default", settingsMgr, kubeclientset)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projWithRole), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projWithRole), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB, testEnableEventList)
request := &project.ProjectUpdateRequest{Project: projWithRole}
_, err := projectServer.Update(context.Background(), request)
expectedErr := fmt.Sprintf("rpc error: code = AlreadyExists desc = policy '%s' already exists for role '%s'", policy, roleName)
@@ -577,7 +580,7 @@ p, role:admin, projects, update, *, allow`)
role.Policies = append(role.Policies, policy)
projWithRole.Spec.Roles = append(projWithRole.Spec.Roles, role)
argoDB := db.NewDB("default", settingsMgr, kubeclientset)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projWithRole), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projWithRole), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB, testEnableEventList)
request := &project.ProjectUpdateRequest{Project: projWithRole}
_, err := projectServer.Update(context.Background(), request)
assert.Contains(t, err.Error(), "object must be of form 'test/*', 'test[/<NAMESPACE>]/<APPNAME>' or 'test/<APPNAME>'")
@@ -596,7 +599,7 @@ p, role:admin, projects, update, *, allow`)
role.Policies = append(role.Policies, invalidPolicy)
projWithRole.Spec.Roles = append(projWithRole.Spec.Roles, role)
argoDB := db.NewDB("default", settingsMgr, kubeclientset)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projWithRole), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projWithRole), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB, testEnableEventList)
request := &project.ProjectUpdateRequest{Project: projWithRole}
_, err := projectServer.Update(context.Background(), request)
assert.Contains(t, err.Error(), "policy subject must be: 'proj:test:testRole'")
@@ -615,7 +618,7 @@ p, role:admin, projects, update, *, allow`)
role.Policies = append(role.Policies, invalidPolicy)
projWithRole.Spec.Roles = append(projWithRole.Spec.Roles, role)
argoDB := db.NewDB("default", settingsMgr, kubeclientset)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projWithRole), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projWithRole), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB, testEnableEventList)
request := &project.ProjectUpdateRequest{Project: projWithRole}
_, err := projectServer.Update(context.Background(), request)
assert.Contains(t, err.Error(), "policy subject must be: 'proj:test:testRole'")
@@ -633,7 +636,7 @@ p, role:admin, projects, update, *, allow`)
role.Policies = append(role.Policies, invalidPolicy)
projWithRole.Spec.Roles = append(projWithRole.Spec.Roles, role)
argoDB := db.NewDB("default", settingsMgr, kubeclientset)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projWithRole), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projWithRole), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB, testEnableEventList)
request := &project.ProjectUpdateRequest{Project: projWithRole}
_, err := projectServer.Update(context.Background(), request)
assert.Contains(t, err.Error(), "effect must be: 'allow' or 'deny'")
@@ -652,7 +655,7 @@ p, role:admin, projects, update, *, allow`)
role.Policies = append(role.Policies, invalidPolicy)
projWithRole.Spec.Roles = append(projWithRole.Spec.Roles, role)
argoDB := db.NewDB("default", settingsMgr, kubeclientset)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projWithRole), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projWithRole), enforcer, sync.NewKeyLock(), nil, nil, projInformer, settingsMgr, argoDB, testEnableEventList)
request := &project.ProjectUpdateRequest{Project: projWithRole}
updateProj, err := projectServer.Update(context.Background(), request)
require.NoError(t, err)
@@ -667,7 +670,7 @@ p, role:admin, projects, update, *, allow`)
win := &v1alpha1.SyncWindow{Kind: "allow", Schedule: "* * * * *", Duration: "1h"}
projectWithSyncWindows.Spec.SyncWindows = append(projectWithSyncWindows.Spec.SyncWindows, win)
argoDB := db.NewDB("default", settingsMgr, kubeclientset)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projectWithSyncWindows), enforcer, sync.NewKeyLock(), sessionMgr, nil, projInformer, settingsMgr, argoDB)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projectWithSyncWindows), enforcer, sync.NewKeyLock(), sessionMgr, nil, projInformer, settingsMgr, argoDB, testEnableEventList)
res, err := projectServer.GetSyncWindowsState(ctx, &project.SyncWindowsQuery{Name: projectWithSyncWindows.Name})
require.NoError(t, err)
assert.Len(t, res.Windows, 1)
@@ -680,7 +683,7 @@ p, role:admin, projects, update, *, allow`)
win := &v1alpha1.SyncWindow{Kind: "allow", Schedule: "* * * * *", Duration: "1h"}
projectWithSyncWindows.Spec.SyncWindows = append(projectWithSyncWindows.Spec.SyncWindows, win)
argoDB := db.NewDB("default", settingsMgr, kubeclientset)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projectWithSyncWindows), enforcer, sync.NewKeyLock(), sessionMgr, nil, projInformer, settingsMgr, argoDB)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projectWithSyncWindows), enforcer, sync.NewKeyLock(), sessionMgr, nil, projInformer, settingsMgr, argoDB, testEnableEventList)
res, err := projectServer.GetSyncWindowsState(ctx, &project.SyncWindowsQuery{Name: "incorrect"})
assert.Contains(t, err.Error(), "not found")
assert.Nil(t, res)
@@ -698,7 +701,7 @@ p, role:admin, projects, update, *, allow`)
win := &v1alpha1.SyncWindow{Kind: "allow", Schedule: "* * * * *", Duration: "1h"}
projectWithSyncWindows.Spec.SyncWindows = append(projectWithSyncWindows.Spec.SyncWindows, win)
argoDB := db.NewDB("default", settingsMgr, kubeclientset)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projectWithSyncWindows), enforcer, sync.NewKeyLock(), sessionMgr, nil, projInformer, settingsMgr, argoDB)
projectServer := NewServer("default", fake.NewSimpleClientset(), apps.NewSimpleClientset(projectWithSyncWindows), enforcer, sync.NewKeyLock(), sessionMgr, nil, projInformer, settingsMgr, argoDB, testEnableEventList)
_, err := projectServer.GetSyncWindowsState(ctx, &project.SyncWindowsQuery{Name: projectWithSyncWindows.Name})
assert.EqualError(t, err, "rpc error: code = PermissionDenied desc = permission denied: projects, get, test")
})

View File

@@ -188,18 +188,21 @@ func (s *Server) ListRepositories(ctx context.Context, q *repositorypkg.RepoQuer
}
// remove secrets
items = append(items, &appsv1.Repository{
Repo: repo.Repo,
Type: rType,
Name: repo.Name,
Username: repo.Username,
Insecure: repo.IsInsecure(),
EnableLFS: repo.EnableLFS,
EnableOCI: repo.EnableOCI,
Proxy: repo.Proxy,
NoProxy: repo.NoProxy,
Project: repo.Project,
ForceHttpBasicAuth: repo.ForceHttpBasicAuth,
InheritedCreds: repo.InheritedCreds,
Repo: repo.Repo,
Type: rType,
Name: repo.Name,
Username: repo.Username,
Insecure: repo.IsInsecure(),
EnableLFS: repo.EnableLFS,
EnableOCI: repo.EnableOCI,
Proxy: repo.Proxy,
NoProxy: repo.NoProxy,
Project: repo.Project,
ForceHttpBasicAuth: repo.ForceHttpBasicAuth,
InheritedCreds: repo.InheritedCreds,
GithubAppId: repo.GithubAppId,
GithubAppInstallationId: repo.GithubAppInstallationId,
GitHubAppEnterpriseBaseURL: repo.GitHubAppEnterpriseBaseURL,
})
}
}

View File

@@ -21,6 +21,7 @@ import (
"github.com/argoproj/argo-cd/v2/common"
"github.com/argoproj/argo-cd/v2/pkg/apiclient/repository"
repositorypkg "github.com/argoproj/argo-cd/v2/pkg/apiclient/repository"
appsv1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
fakeapps "github.com/argoproj/argo-cd/v2/pkg/client/clientset/versioned/fake"
appinformer "github.com/argoproj/argo-cd/v2/pkg/client/informers/externalversions"
@@ -1057,3 +1058,35 @@ func TestGetRepository(t *testing.T) {
})
}
}
func TestDeleteRepository(t *testing.T) {
repositories := map[string]string{
"valid": "https://bitbucket.org/workspace/repo.git",
// Check a wrongly formatter repo as well, see https://github.com/argoproj/argo-cd/issues/20921
"invalid": "git clone https://bitbucket.org/workspace/repo.git",
}
kubeclientset := fake.NewSimpleClientset(&argocdCM, &argocdSecret)
settingsMgr := settings.NewSettingsManager(context.Background(), kubeclientset, testNamespace)
for name, repo := range repositories {
t.Run(name, func(t *testing.T) {
repoServerClient := mocks.RepoServerServiceClient{}
repoServerClient.On("TestRepository", mock.Anything, mock.Anything).Return(&apiclient.TestRepositoryResponse{}, nil)
repoServerClientset := mocks.Clientset{RepoServerServiceClient: &repoServerClient}
enforcer := newEnforcer(kubeclientset)
db := &dbmocks.ArgoDB{}
db.On("DeleteRepository", context.TODO(), repo, "default").Return(nil)
db.On("ListRepositories", context.TODO()).Return([]*appsv1.Repository{{Repo: repo, Project: "default"}}, nil)
db.On("GetRepository", context.TODO(), repo, "default").Return(&appsv1.Repository{Repo: repo, Project: "default"}, nil)
appLister, projLister := newAppAndProjLister(defaultProj)
s := NewServer(&repoServerClientset, db, enforcer, newFixtures().Cache, appLister, projLister, testNamespace, settingsMgr)
resp, err := s.DeleteRepository(context.TODO(), &repository.RepoQuery{Repo: repo, AppProject: "default"})
require.NoError(t, err)
assert.Equal(t, repositorypkg.RepoResponse{}, *resp)
})
}
}

View File

@@ -229,6 +229,7 @@ type ArgoCDServerOpts struct {
ApplicationNamespaces []string
EnableProxyExtension bool
WebhookParallelism int
EnableK8sEvent []string
}
type ApplicationSetOpts struct {
@@ -885,7 +886,9 @@ func newArgoCDServiceSet(a *ArgoCDServer) *ArgoCDServiceSet {
projectLock,
a.settingsMgr,
a.projInformer,
a.ApplicationNamespaces)
a.ApplicationNamespaces,
a.EnableK8sEvent,
)
applicationSetService := applicationset.NewServer(
a.db,
@@ -907,9 +910,10 @@ func newArgoCDServiceSet(a *ArgoCDServer) *ArgoCDServiceSet {
a.ScmRootCAPath,
a.AllowedScmProviders,
a.EnableScmProviders,
a.EnableK8sEvent,
)
projectService := project.NewServer(a.Namespace, a.KubeClientset, a.AppClientset, a.enf, projectLock, a.sessionMgr, a.policyEnforcer, a.projInformer, a.settingsMgr, a.db)
projectService := project.NewServer(a.Namespace, a.KubeClientset, a.AppClientset, a.enf, projectLock, a.sessionMgr, a.policyEnforcer, a.projInformer, a.settingsMgr, a.db, a.EnableK8sEvent)
appsInAnyNamespaceEnabled := len(a.ArgoCDServerOpts.ApplicationNamespaces) > 0
settingsService := settings.NewServer(a.settingsMgr, a.RepoClientset, a, a.DisableAuth, appsInAnyNamespaceEnabled)
accountService := account.NewServer(a.sessionMgr, a.settingsMgr, a.enf)

View File

@@ -1,9 +1,10 @@
import {DataLoader, NavigationManager, Notifications, NotificationsManager, PageContext, Popup, PopupManager, PopupProps} from 'argo-ui';
import {DataLoader, NavigationManager, NotificationType, Notifications, NotificationsManager, PageContext, Popup, PopupManager, PopupProps} from 'argo-ui';
import {createBrowserHistory} from 'history';
import * as PropTypes from 'prop-types';
import * as React from 'react';
import {Helmet} from 'react-helmet';
import {Redirect, Route, RouteComponentProps, Router, Switch} from 'react-router';
import {Subscription} from 'rxjs';
import applications from './applications';
import help from './help';
import login from './login';
@@ -19,6 +20,7 @@ import {Banner} from './ui-banner/ui-banner';
import userInfo from './user-info';
import {AuthSettings} from './shared/models';
import {PKCEVerification} from './login/components/pkce-verify';
import {getPKCERedirectURI, pkceLogin} from './login/components/utils';
import {SystemLevelExtension} from './shared/services/extensions-service';
services.viewPreferences.init();
@@ -86,28 +88,6 @@ async function isExpiredSSO() {
return false;
}
requests.onError.subscribe(async err => {
if (err.status === 401) {
if (history.location.pathname.startsWith('/login')) {
return;
}
const isSSO = await isExpiredSSO();
// location might change after async method call, so we need to check again.
if (history.location.pathname.startsWith('/login')) {
return;
}
// Query for basehref and remove trailing /.
// If basehref is the default `/` it will become an empty string.
const basehref = document.querySelector('head > base').getAttribute('href').replace(/\/$/, '');
if (isSSO) {
window.location.href = `${basehref}/auth/login?return_url=${encodeURIComponent(location.href)}`;
} else {
history.push(`/login?return_url=${encodeURIComponent(location.href)}`);
}
}
});
export class App extends React.Component<
{},
{popupProps: PopupProps; showVersionPanel: boolean; error: Error; navItems: NavItem[]; routes: Routes; extensionsLoaded: boolean; authSettings: AuthSettings}
@@ -126,6 +106,8 @@ export class App extends React.Component<
private navigationManager: NavigationManager;
private navItems: NavItem[];
private routes: Routes;
private popupPropsSubscription: Subscription;
private unauthorizedSubscription: Subscription;
constructor(props: {}) {
super(props);
@@ -135,11 +117,16 @@ export class App extends React.Component<
this.navigationManager = new NavigationManager(history);
this.navItems = navItems;
this.routes = routes;
this.popupPropsSubscription = null;
this.unauthorizedSubscription = null;
services.extensions.addEventListener('systemLevel', this.onAddSystemLevelExtension.bind(this));
}
public async componentDidMount() {
this.popupManager.popupProps.subscribe(popupProps => this.setState({popupProps}));
this.popupPropsSubscription = this.popupManager.popupProps.subscribe(popupProps => this.setState({popupProps}));
this.subscribeUnauthorized().then(subscription => {
this.unauthorizedSubscription = subscription;
});
const authSettings = await services.authService.settings();
const {trackingID, anonymizeUsers} = authSettings.googleAnalytics || {trackingID: '', anonymizeUsers: true};
const {loggedIn, username} = await services.users.get();
@@ -167,6 +154,15 @@ export class App extends React.Component<
this.setState({...this.state, navItems: this.navItems, routes: this.routes, extensionsLoaded: false, authSettings});
}
public componentWillUnmount() {
if (this.popupPropsSubscription) {
this.popupPropsSubscription.unsubscribe();
}
if (this.unauthorizedSubscription) {
this.unauthorizedSubscription.unsubscribe();
}
}
public render() {
if (this.state.error != null) {
const stack = this.state.error.stack;
@@ -242,6 +238,41 @@ export class App extends React.Component<
return {history, apis: {popup: this.popupManager, notifications: this.notificationsManager, navigation: this.navigationManager}};
}
private async subscribeUnauthorized() {
return requests.onError.subscribe(async err => {
if (err.status === 401) {
if (history.location.pathname.startsWith('/login')) {
return;
}
const isSSO = await isExpiredSSO();
// location might change after async method call, so we need to check again.
if (history.location.pathname.startsWith('/login')) {
return;
}
// Query for basehref and remove trailing /.
// If basehref is the default `/` it will become an empty string.
const basehref = document.querySelector('head > base').getAttribute('href').replace(/\/$/, '');
if (isSSO) {
const authSettings = await services.authService.settings();
if (authSettings?.oidcConfig?.enablePKCEAuthentication) {
pkceLogin(authSettings.oidcConfig, getPKCERedirectURI().toString()).catch(err => {
this.getChildContext().apis.notifications.show({
type: NotificationType.Error,
content: err?.message || JSON.stringify(err)
});
});
} else {
window.location.href = `${basehref}/auth/login?return_url=${encodeURIComponent(location.href)}`;
}
} else {
history.push(`/login?return_url=${encodeURIComponent(location.href)}`);
}
}
});
}
private onAddSystemLevelExtension(extension: SystemLevelExtension) {
const extendedNavItems = this.navItems;
const extendedRoutes = this.routes;

View File

@@ -3,6 +3,7 @@ import * as React from 'react';
import {Context} from '../../../shared/context';
import {services} from '../../../shared/services';
import {getAppUrl} from '../utils';
export const ApplicationsDetailsAppDropdown = (props: {appName: string}) => {
const [opened, setOpened] = React.useState(false);
@@ -42,7 +43,7 @@ export const ApplicationsDetailsAppDropdown = (props: {appName: string}) => {
})
.slice(0, 100) // take top 100 results after filtering to avoid performance issues
.map(app => (
<li key={app.metadata.name} onClick={() => ctx.navigation.goto(`/applications/${app.metadata.namespace}/${app.metadata.name}`)}>
<li key={app.metadata.name} onClick={() => ctx.navigation.goto(getAppUrl(app))}>
{app.metadata.name} {app.metadata.name === props.appName && ' (current)'}
</li>
))

View File

@@ -82,7 +82,6 @@ export class ApplicationDetails extends React.Component<RouteComponentProps<{app
};
private appChanged = new BehaviorSubject<appModels.Application>(null);
private appNamespace: string;
constructor(props: RouteComponentProps<{appnamespace: string; name: string}>) {
super(props);
@@ -95,11 +94,6 @@ export class ApplicationDetails extends React.Component<RouteComponentProps<{app
collapsedNodes: [],
...this.getExtensionsState()
};
if (typeof this.props.match.params.appnamespace === 'undefined') {
this.appNamespace = '';
} else {
this.appNamespace = this.props.match.params.appnamespace;
}
}
public componentDidMount() {
@@ -116,6 +110,13 @@ export class ApplicationDetails extends React.Component<RouteComponentProps<{app
services.extensions.removeEventListener('topBar', this.onExtensionsUpdate);
}
private getAppNamespace() {
if (typeof this.props.match.params.appnamespace === 'undefined') {
return '';
}
return this.props.match.params.appnamespace;
}
private onExtensionsUpdate = () => {
this.setState({...this.state, ...this.getExtensionsState()});
};
@@ -426,7 +427,7 @@ export class ApplicationDetails extends React.Component<RouteComponentProps<{app
loadingRenderer={() => <Page title='Application Details'>Loading...</Page>}
input={this.props.match.params.name}
load={name =>
combineLatest([this.loadAppInfo(name, this.props.match.params.appnamespace), services.viewPreferences.getPreferences(), q]).pipe(
combineLatest([this.loadAppInfo(name, this.getAppNamespace()), services.viewPreferences.getPreferences(), q]).pipe(
map(items => {
const application = items[0].application;
const pref = items[1].appDetails;
@@ -1170,8 +1171,8 @@ Are you sure you want to disable auto-sync and rollback application '${this.prop
update.spec.syncPolicy = {automated: null};
await services.applications.update(update);
}
await services.applications.rollback(this.props.match.params.name, this.appNamespace, revisionHistory.id);
this.appChanged.next(await services.applications.get(this.props.match.params.name, this.appNamespace));
await services.applications.rollback(this.props.match.params.name, this.getAppNamespace(), revisionHistory.id);
this.appChanged.next(await services.applications.get(this.props.match.params.name, this.getAppNamespace()));
this.setRollbackPanelVisible(-1);
}
} catch (e) {
@@ -1187,7 +1188,7 @@ Are you sure you want to disable auto-sync and rollback application '${this.prop
}
private async deleteApplication() {
await AppUtils.deleteApplication(this.props.match.params.name, this.appNamespace, this.appContext.apis);
await AppUtils.deleteApplication(this.props.match.params.name, this.getAppNamespace(), this.appContext.apis);
}
}

View File

@@ -37,7 +37,7 @@ export const ApplicationsTable = (props: {
keys: Key.ENTER,
action: () => {
if (selectedApp > -1) {
ctxh.navigation.goto(`/applications/${props.applications[selectedApp].metadata.name}`);
ctxh.navigation.goto(AppUtils.getAppUrl(props.applications[selectedApp]));
return true;
}
return false;
@@ -57,9 +57,7 @@ export const ApplicationsTable = (props: {
key={AppUtils.appInstanceName(app)}
className={`argo-table-list__row
applications-list__entry applications-list__entry--health-${app.status.health.status} ${selectedApp === i ? 'applications-tiles__selected' : ''}`}>
<div
className={`row applications-list__table-row`}
onClick={e => ctx.navigation.goto(`applications/${app.metadata.namespace}/${app.metadata.name}`, {}, {event: e})}>
<div className={`row applications-list__table-row`} onClick={e => ctx.navigation.goto(AppUtils.getAppUrl(app), {}, {event: e})}>
<div className='columns small-4'>
<div className='row'>
<div className=' columns small-2'>

View File

@@ -66,7 +66,7 @@ export const ApplicationTiles = ({applications, syncApplication, refreshApplicat
keys: Key.ENTER,
action: () => {
if (selectedApp > -1) {
ctxh.navigation.goto(`/applications/${applications[selectedApp].metadata.name}`);
ctxh.navigation.goto(AppUtils.getAppUrl(applications[selectedApp]));
return true;
}
return false;
@@ -118,9 +118,7 @@ export const ApplicationTiles = ({applications, syncApplication, refreshApplicat
}`}>
<div
className='row applications-tiles__wrapper'
onClick={e =>
ctx.navigation.goto(`applications/${app.metadata.namespace}/${app.metadata.name}`, {view: pref.appDetails.view}, {event: e})
}>
onClick={e => ctx.navigation.goto(AppUtils.getAppUrl(app), {view: pref.appDetails.view}, {event: e})}>
<div
className={`columns small-12 applications-list__info qe-applications-list-${AppUtils.appInstanceName(
app

View File

@@ -1471,3 +1471,10 @@ export const userMsgsList: {[key: string]: string} = {
groupNodes: `Since the number of pods has surpassed the threshold pod count of 15, you will now be switched to the group node view.
If you prefer the tree view, you can simply click on the Group Nodes toolbar button to deselect the current view.`
};
export function getAppUrl(app: appModels.Application): string {
if (typeof app.metadata.namespace === 'undefined') {
return `/applications/${app.metadata.name}`;
}
return `/applications/${app.metadata.namespace}/${app.metadata.name}`;
}

View File

@@ -2,6 +2,7 @@ import React, {useEffect, useState} from 'react';
import {RouteComponentProps} from 'react-router';
import {services} from '../../shared/services';
import {PKCECodeVerifier, PKCELoginError, getPKCERedirectURI, pkceCallback} from './utils';
import requests from '../../shared/services/requests';
import './pkce-verify.scss';
@@ -31,7 +32,7 @@ export const PKCEVerification = (props: RouteComponentProps<any>) => {
<div>
<h3>Error occurred: </h3>
<p>{error?.message || JSON.stringify(error)}</p>
<a href='/login'>Try to Login again</a>
<a href={requests.toAbsURL('/login')}>Try to Login again</a>
</div>
</div>
);

View File

@@ -13,6 +13,7 @@ import {
validateAuthResponse
} from 'oauth4webapi';
import {AuthSettings} from '../../shared/models';
import requests from '../../shared/services/requests';
export const discoverAuthServer = (issuerURL: URL): Promise<AuthorizationServer> => discoveryRequest(issuerURL).then(res => processDiscoveryResponse(issuerURL, res));
@@ -25,7 +26,7 @@ export const PKCECodeVerifier = {
export const getPKCERedirectURI = () => {
const currentOrigin = new URL(window.location.origin);
currentOrigin.pathname = '/pkce/verify';
currentOrigin.pathname = requests.toAbsURL('/pkce/verify');
return currentOrigin;
};
@@ -70,6 +71,12 @@ const validateAndGetOIDCForPKCE = async (oidcConfig: AuthSettings['oidcConfig'])
export const pkceLogin = async (oidcConfig: AuthSettings['oidcConfig'], redirectURI: string) => {
const {authorizationServer} = await validateAndGetOIDCForPKCE(oidcConfig);
// This sets the return path for the user after the pkce auth flow.
// This is ignored if the return path would be the login page as it would just loop.
if (!location.pathname.startsWith(requests.toAbsURL('/login'))) {
sessionStorage.setItem('return_url', location.pathname + location.search);
}
if (!authorizationServer.authorization_endpoint) {
throw new PKCELoginError('No Authorization Server endpoint found');
}
@@ -145,7 +152,18 @@ export const pkceCallback = async (queryParams: string, oidcConfig: AuthSettings
throw new PKCELoginError('No token in response');
}
document.cookie = `argocd.token=${result.id_token}; path=/`;
// This regex removes any leading or trailing '/' characters and the result is appended to a '/'.
// This is because when base href if not just '/' toAbsURL() will append a trailing '/'.
// Just removing a trailing '/' from the string would break when base href is not specified, defaulted to '/'.
// This pattern is used to handle both cases.
document.cookie = `argocd.token=${result.id_token}; path=/${requests.toAbsURL('').replace(/^\/|\/$/g, '')}`;
window.location.replace('/applications');
const returnURL = sessionStorage.getItem('return_url');
if (returnURL) {
sessionStorage.removeItem('return_url');
window.location.replace(returnURL);
} else {
window.location.replace(requests.toAbsURL('/applications'));
}
};

View File

@@ -5639,9 +5639,9 @@ http-proxy-agent@^5.0.0:
debug "4"
http-proxy-middleware@^2.0.0:
version "2.0.4"
resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.4.tgz#03af0f4676d172ae775cb5c33f592f40e1a4e07a"
integrity sha512-m/4FxX17SUvz4lJ5WPXOHDUuCwIqXLfLHs1s0uZ3oYjhoXlx9csYxaOa0ElDEJ+h8Q4iJ1s+lTMbiCa4EXIJqg==
version "2.0.7"
resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.7.tgz#915f236d92ae98ef48278a95dedf17e991936ec6"
integrity sha512-fgVY8AV7qU7z/MmXJ/rxwbrtQH4jBQ9m7kp3llF0liB7glmFeVZFBepQb32T3y8n8k2+AEYuMPCpinYW+/CuRA==
dependencies:
"@types/http-proxy" "^1.17.8"
http-proxy "^1.18.1"

View File

@@ -170,6 +170,7 @@ func cmpSupports(ctx context.Context, pluginSockFilePath, appPath, repoPath, fil
cfg, err := cmpClient.CheckPluginConfiguration(ctx, &empty.Empty{})
if err != nil {
log.Errorf("error checking plugin configuration %s, %v", fileName, err)
io.Close(conn)
return nil, nil, false
}
@@ -178,6 +179,7 @@ func cmpSupports(ctx context.Context, pluginSockFilePath, appPath, repoPath, fil
if namedPlugin {
return conn, cmpClient, true
}
io.Close(conn)
return nil, nil, false
}

View File

@@ -1,6 +1,7 @@
package path
import (
"errors"
"fmt"
"os"
"path/filepath"
@@ -51,6 +52,11 @@ func CheckOutOfBoundsSymlinks(basePath string) error {
}
return filepath.Walk(absBasePath, func(path string, info os.FileInfo, err error) error {
if err != nil {
// Ignore "no such file or directory" errors than can happen with
// temporary files such as .git/*.lock
if errors.Is(err, os.ErrNotExist) {
return nil
}
return fmt.Errorf("failed to walk for symlinks in %s: %w", absBasePath, err)
}
if files.IsSymlink(info) {

View File

@@ -18,9 +18,10 @@ import (
)
type AuditLogger struct {
kIf kubernetes.Interface
component string
ns string
kIf kubernetes.Interface
component string
ns string
enableEventLog map[string]bool
}
type EventInfo struct {
@@ -95,7 +96,15 @@ func (l *AuditLogger) logEvent(objMeta ObjectRef, gvk schema.GroupVersionKind, i
}
}
func (l *AuditLogger) enableK8SEventLog(info EventInfo) bool {
return l.enableEventLog["all"] || l.enableEventLog[info.Reason]
}
func (l *AuditLogger) LogAppEvent(app *v1alpha1.Application, info EventInfo, message, user string, eventLabels map[string]string) {
if !l.enableK8SEventLog(info) {
return
}
objectMeta := ObjectRef{
Name: app.ObjectMeta.Name,
Namespace: app.ObjectMeta.Namespace,
@@ -113,6 +122,10 @@ func (l *AuditLogger) LogAppEvent(app *v1alpha1.Application, info EventInfo, mes
}
func (l *AuditLogger) LogAppSetEvent(app *v1alpha1.ApplicationSet, info EventInfo, message, user string) {
if !l.enableK8SEventLog(info) {
return
}
objectMeta := ObjectRef{
Name: app.ObjectMeta.Name,
Namespace: app.ObjectMeta.Namespace,
@@ -127,6 +140,10 @@ func (l *AuditLogger) LogAppSetEvent(app *v1alpha1.ApplicationSet, info EventInf
}
func (l *AuditLogger) LogResourceEvent(res *v1alpha1.ResourceNode, info EventInfo, message, user string) {
if !l.enableK8SEventLog(info) {
return
}
objectMeta := ObjectRef{
Name: res.ResourceRef.Name,
Namespace: res.ResourceRef.Namespace,
@@ -145,6 +162,10 @@ func (l *AuditLogger) LogResourceEvent(res *v1alpha1.ResourceNode, info EventInf
}
func (l *AuditLogger) LogAppProjEvent(proj *v1alpha1.AppProject, info EventInfo, message, user string) {
if !l.enableK8SEventLog(info) {
return
}
objectMeta := ObjectRef{
Name: proj.ObjectMeta.Name,
Namespace: proj.ObjectMeta.Namespace,
@@ -158,10 +179,35 @@ func (l *AuditLogger) LogAppProjEvent(proj *v1alpha1.AppProject, info EventInfo,
l.logEvent(objectMeta, v1alpha1.AppProjectSchemaGroupVersionKind, info, message, nil, nil)
}
func NewAuditLogger(ns string, kIf kubernetes.Interface, component string) *AuditLogger {
func NewAuditLogger(ns string, kIf kubernetes.Interface, component string, enableK8sEvent []string) *AuditLogger {
return &AuditLogger{
ns: ns,
kIf: kIf,
component: component,
ns: ns,
kIf: kIf,
component: component,
enableEventLog: setK8sEventList(enableK8sEvent),
}
}
func setK8sEventList(enableK8sEvent []string) map[string]bool {
enableK8sEventList := make(map[string]bool)
for _, event := range enableK8sEvent {
if event == "all" {
enableK8sEventList = map[string]bool{
"all": true,
}
return enableK8sEventList
} else if event == "none" {
enableK8sEventList = map[string]bool{}
return enableK8sEventList
}
enableK8sEventList[event] = true
}
return enableK8sEventList
}
func DefaultEnableEventList() []string {
return []string{"all"}
}

View File

@@ -14,6 +14,13 @@ import (
argoappv1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
)
const (
_somecomponent = "somecomponent"
_test = "test"
)
var testEnableEventLog []string = []string{_somecomponent, _test}
// Helper to capture log entries generated by the logger and return it as string
func captureLogEntries(run func()) string {
f := log.StandardLogger().Formatter
@@ -29,12 +36,12 @@ func captureLogEntries(run func()) string {
}
func TestNewAuditLogger(t *testing.T) {
logger := NewAuditLogger("default", fake.NewSimpleClientset(), "somecomponent")
logger := NewAuditLogger("default", fake.NewSimpleClientset(), _somecomponent, testEnableEventLog)
assert.NotNil(t, logger)
}
func TestLogAppProjEvent(t *testing.T) {
logger := NewAuditLogger("default", fake.NewSimpleClientset(), "somecomponent")
logger := NewAuditLogger("default", fake.NewSimpleClientset(), _somecomponent, testEnableEventLog)
assert.NotNil(t, logger)
proj := argoappv1.AppProject{
@@ -50,7 +57,7 @@ func TestLogAppProjEvent(t *testing.T) {
}
ei := EventInfo{
Reason: "test",
Reason: _test,
Type: "info",
}
@@ -63,10 +70,19 @@ func TestLogAppProjEvent(t *testing.T) {
assert.Contains(t, output, "reason=test")
assert.Contains(t, output, "type=info")
assert.Contains(t, output, "msg=\"This is a test message\"")
ei.Reason = "Unknown"
// If K8s Event Disable Log
output = captureLogEntries(func() {
logger.LogAppProjEvent(&proj, ei, "This is a test message", "")
})
assert.Empty(t, output)
}
func TestLogAppEvent(t *testing.T) {
logger := NewAuditLogger("default", fake.NewSimpleClientset(), "somecomponent")
logger := NewAuditLogger("default", fake.NewSimpleClientset(), _somecomponent, testEnableEventLog)
assert.NotNil(t, logger)
app := argoappv1.Application{
@@ -85,7 +101,7 @@ func TestLogAppEvent(t *testing.T) {
}
ei := EventInfo{
Reason: "test",
Reason: _test,
Type: "info",
}
@@ -100,10 +116,19 @@ func TestLogAppEvent(t *testing.T) {
assert.Contains(t, output, "reason=test")
assert.Contains(t, output, "type=info")
assert.Contains(t, output, "msg=\"This is a test message\"")
ei.Reason = "Unknown"
// If K8s Event Disable Log
output = captureLogEntries(func() {
logger.LogAppEvent(&app, ei, "This is a test message", "", nil)
})
assert.Empty(t, output)
}
func TestLogResourceEvent(t *testing.T) {
logger := NewAuditLogger("default", fake.NewSimpleClientset(), "somecomponent")
logger := NewAuditLogger("default", fake.NewSimpleClientset(), _somecomponent, testEnableEventLog)
assert.NotNil(t, logger)
res := argoappv1.ResourceNode{
@@ -118,7 +143,7 @@ func TestLogResourceEvent(t *testing.T) {
}
ei := EventInfo{
Reason: "test",
Reason: _test,
Type: "info",
}
@@ -131,4 +156,13 @@ func TestLogResourceEvent(t *testing.T) {
assert.Contains(t, output, "reason=test")
assert.Contains(t, output, "type=info")
assert.Contains(t, output, "msg=\"This is a test message\"")
ei.Reason = "Unknown"
// If K8s Event Disable Log
output = captureLogEntries(func() {
logger.LogResourceEvent(&res, ei, "This is a test message", "")
})
assert.Empty(t, output)
}

View File

@@ -35,11 +35,21 @@ func IsTruncatedCommitSHA(sha string) bool {
// SameURL returns whether or not the two repository URLs are equivalent in location
func SameURL(leftRepo, rightRepo string) bool {
normalLeft := NormalizeGitURL(leftRepo)
normalRight := NormalizeGitURL(rightRepo)
normalLeft := NormalizeGitURLAllowInvalid(leftRepo)
normalRight := NormalizeGitURLAllowInvalid(rightRepo)
return normalLeft != "" && normalRight != "" && normalLeft == normalRight
}
// Similar to NormalizeGitURL, except returning an original url if the url is invalid.
// Needed to allow a deletion of repos with invalid urls. See https://github.com/argoproj/argo-cd/issues/20921.
func NormalizeGitURLAllowInvalid(repo string) string {
normalized := NormalizeGitURL(repo)
if normalized == "" {
return repo
}
return normalized
}
// NormalizeGitURL normalizes a git URL for purposes of comparison, as well as preventing redundant
// local clones (by normalizing various forms of a URL to a consistent location).
// Prefer using SameURL() over this function when possible. This algorithm may change over time