mirror of
https://github.com/argoproj/argo-cd.git
synced 2026-04-06 16:58:48 +02:00
Compare commits
19 Commits
v2.14.16
...
release-2.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
206a6eeca5 | ||
|
|
8b31544069 | ||
|
|
9b7bf3e16d | ||
|
|
879895af78 | ||
|
|
1f98e3f989 | ||
|
|
741f00e2e3 | ||
|
|
e889f0a7ff | ||
|
|
7b219ee97f | ||
|
|
4ab9cd45bf | ||
|
|
ba5b938858 | ||
|
|
4a133ce41b | ||
|
|
376525eea2 | ||
|
|
9fa9bb8c89 | ||
|
|
4359b3c774 | ||
|
|
4f6686fc3f | ||
|
|
caa4dc1bd2 | ||
|
|
981e7f762a | ||
|
|
3d76aa5daa | ||
|
|
fca3a7ed2a |
2
.github/workflows/ci-build.yaml
vendored
2
.github/workflows/ci-build.yaml
vendored
@@ -486,7 +486,7 @@ jobs:
|
||||
run: |
|
||||
docker pull ghcr.io/dexidp/dex:v2.41.1
|
||||
docker pull argoproj/argo-cd-ci-builder:v1.0.0
|
||||
docker pull redis:7.0.15-alpine
|
||||
docker pull redis:7.2.11-alpine
|
||||
- name: Create target directory for binaries in the build-process
|
||||
run: |
|
||||
mkdir -p dist
|
||||
|
||||
66
.github/workflows/release.yaml
vendored
66
.github/workflows/release.yaml
vendored
@@ -32,6 +32,42 @@ jobs:
|
||||
quay_username: ${{ secrets.RELEASE_QUAY_USERNAME }}
|
||||
quay_password: ${{ secrets.RELEASE_QUAY_TOKEN }}
|
||||
|
||||
setup-variables:
|
||||
name: Setup Release Variables
|
||||
if: github.repository == 'argoproj/argo-cd'
|
||||
runs-on: ubuntu-22.04
|
||||
outputs:
|
||||
is_pre_release: ${{ steps.var.outputs.is_pre_release }}
|
||||
is_latest_release: ${{ steps.var.outputs.is_latest_release }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@8410ad0602e1e429cee44a835ae9f77f654a6694 # v4.0.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Setup variables
|
||||
id: var
|
||||
run: |
|
||||
set -xue
|
||||
# Fetch all tag information
|
||||
git fetch --prune --tags --force
|
||||
|
||||
LATEST_RELEASE_TAG=$(git -c 'versionsort.suffix=-rc' tag --list --sort=version:refname | grep -v '-' | tail -n1)
|
||||
|
||||
PRE_RELEASE=false
|
||||
# Check if latest tag is a pre-release
|
||||
if echo ${{ github.ref_name }} | grep -E -- '-rc[0-9]+$';then
|
||||
PRE_RELEASE=true
|
||||
fi
|
||||
|
||||
IS_LATEST=false
|
||||
# Ensure latest release tag matches github.ref_name
|
||||
if [[ $LATEST_RELEASE_TAG == ${{ github.ref_name }} ]];then
|
||||
IS_LATEST=true
|
||||
fi
|
||||
echo "is_pre_release=$PRE_RELEASE" >> $GITHUB_OUTPUT
|
||||
echo "is_latest_release=$IS_LATEST" >> $GITHUB_OUTPUT
|
||||
|
||||
argocd-image-provenance:
|
||||
needs: [argocd-image]
|
||||
permissions:
|
||||
@@ -50,15 +86,17 @@ jobs:
|
||||
|
||||
goreleaser:
|
||||
needs:
|
||||
- setup-variables
|
||||
- argocd-image
|
||||
- argocd-image-provenance
|
||||
permissions:
|
||||
contents: write # used for uploading assets
|
||||
if: github.repository == 'argoproj/argo-cd'
|
||||
runs-on: ubuntu-22.04
|
||||
env:
|
||||
GORELEASER_MAKE_LATEST: ${{ needs.setup-variables.outputs.is_latest_release }}
|
||||
outputs:
|
||||
hashes: ${{ steps.hash.outputs.hashes }}
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@8410ad0602e1e429cee44a835ae9f77f654a6694 # v4.0.0
|
||||
@@ -140,7 +178,7 @@ jobs:
|
||||
permissions:
|
||||
contents: write # Needed for release uploads
|
||||
outputs:
|
||||
hashes: ${{ steps.sbom-hash.outputs.hashes}}
|
||||
hashes: ${{ steps.sbom-hash.outputs.hashes }}
|
||||
if: github.repository == 'argoproj/argo-cd'
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
@@ -218,6 +256,7 @@ jobs:
|
||||
|
||||
post-release:
|
||||
needs:
|
||||
- setup-variables
|
||||
- argocd-image
|
||||
- goreleaser
|
||||
- generate-sbom
|
||||
@@ -226,6 +265,8 @@ jobs:
|
||||
pull-requests: write # Needed to create PR for VERSION update.
|
||||
if: github.repository == 'argoproj/argo-cd'
|
||||
runs-on: ubuntu-22.04
|
||||
env:
|
||||
TAG_STABLE: ${{ needs.setup-variables.outputs.is_latest_release }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@8410ad0602e1e429cee44a835ae9f77f654a6694 # v4.0.0
|
||||
@@ -239,27 +280,6 @@ jobs:
|
||||
git config --global user.email 'ci@argoproj.com'
|
||||
git config --global user.name 'CI'
|
||||
|
||||
- name: Check if tag is the latest version and not a pre-release
|
||||
run: |
|
||||
set -xue
|
||||
# Fetch all tag information
|
||||
git fetch --prune --tags --force
|
||||
|
||||
LATEST_TAG=$(git -c 'versionsort.suffix=-rc' tag --list --sort=version:refname | tail -n1)
|
||||
|
||||
PRE_RELEASE=false
|
||||
# Check if latest tag is a pre-release
|
||||
if echo $LATEST_TAG | grep -E -- '-rc[0-9]+$';then
|
||||
PRE_RELEASE=true
|
||||
fi
|
||||
|
||||
# Ensure latest tag matches github.ref_name & not a pre-release
|
||||
if [[ $LATEST_TAG == ${{ github.ref_name }} ]] && [[ $PRE_RELEASE != 'true' ]];then
|
||||
echo "TAG_STABLE=true" >> $GITHUB_ENV
|
||||
else
|
||||
echo "TAG_STABLE=false" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Update stable tag to latest version
|
||||
run: |
|
||||
git tag -f stable ${{ github.ref_name }}
|
||||
|
||||
@@ -46,16 +46,17 @@ builds:
|
||||
archives:
|
||||
- id: argocd-archive
|
||||
builds:
|
||||
- argocd-cli
|
||||
- argocd-cli
|
||||
name_template: |-
|
||||
{{ .ProjectName }}-{{ .Os }}-{{ .Arch }}
|
||||
format: binary
|
||||
formats: [binary]
|
||||
|
||||
checksum:
|
||||
name_template: 'cli_checksums.txt'
|
||||
algorithm: sha256
|
||||
|
||||
release:
|
||||
make_latest: '{{ .Env.GORELEASER_MAKE_LATEST }}'
|
||||
prerelease: auto
|
||||
draft: false
|
||||
header: |
|
||||
@@ -85,16 +86,14 @@ release:
|
||||
If upgrading from a different minor version, be sure to read the [upgrading](https://argo-cd.readthedocs.io/en/stable/operator-manual/upgrading/overview/) documentation.
|
||||
footer: |
|
||||
**Full Changelog**: https://github.com/argoproj/argo-cd/compare/{{ .PreviousTag }}...{{ .Tag }}
|
||||
|
||||
|
||||
<a href="https://argoproj.github.io/cd/"><img src="https://raw.githubusercontent.com/argoproj/argo-site/master/content/pages/cd/gitops-cd.png" width="25%" ></a>
|
||||
|
||||
|
||||
snapshot: #### To be removed for PR
|
||||
name_template: "2.6.0"
|
||||
name_template: '2.6.0'
|
||||
|
||||
changelog:
|
||||
use:
|
||||
github
|
||||
use: github
|
||||
sort: asc
|
||||
abbrev: 0
|
||||
groups: # Regex use RE2 syntax as defined here: https://github.com/google/re2/wiki/Syntax.
|
||||
@@ -117,7 +116,4 @@ changelog:
|
||||
- '^test:'
|
||||
- '^.*?Bump(\([[:word:]]+\))?.+$'
|
||||
- '^.*?\[Bot\](\([[:word:]]+\))?.+$'
|
||||
|
||||
|
||||
# yaml-language-server: $schema=https://goreleaser.com/static/schema.json
|
||||
|
||||
|
||||
@@ -91,6 +91,7 @@ type ApplicationSetReconciler struct {
|
||||
GlobalPreservedAnnotations []string
|
||||
GlobalPreservedLabels []string
|
||||
Metrics *metrics.ApplicationsetMetrics
|
||||
MaxResourcesStatusCount int
|
||||
}
|
||||
|
||||
// +kubebuilder:rbac:groups=argoproj.io,resources=applicationsets,verbs=get;list;watch;create;update;patch;delete
|
||||
@@ -1314,6 +1315,11 @@ func (r *ApplicationSetReconciler) updateResourcesStatus(ctx context.Context, lo
|
||||
sort.Slice(statuses, func(i, j int) bool {
|
||||
return statuses[i].Name < statuses[j].Name
|
||||
})
|
||||
|
||||
if r.MaxResourcesStatusCount > 0 && len(statuses) > r.MaxResourcesStatusCount {
|
||||
logCtx.Warnf("Truncating ApplicationSet %s resource status from %d to max allowed %d entries", appset.Name, len(statuses), r.MaxResourcesStatusCount)
|
||||
statuses = statuses[:r.MaxResourcesStatusCount]
|
||||
}
|
||||
appset.Status.Resources = statuses
|
||||
// DefaultRetry will retry 5 times with a backoff factor of 1, jitter of 0.1 and a duration of 10ms
|
||||
err := retry.RetryOnConflict(retry.DefaultRetry, func() error {
|
||||
|
||||
@@ -6097,10 +6097,11 @@ func TestUpdateResourceStatus(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, cc := range []struct {
|
||||
name string
|
||||
appSet v1alpha1.ApplicationSet
|
||||
apps []v1alpha1.Application
|
||||
expectedResources []v1alpha1.ResourceStatus
|
||||
name string
|
||||
appSet v1alpha1.ApplicationSet
|
||||
apps []v1alpha1.Application
|
||||
expectedResources []v1alpha1.ResourceStatus
|
||||
maxResourcesStatusCount int
|
||||
}{
|
||||
{
|
||||
name: "handles an empty application list",
|
||||
@@ -6271,6 +6272,73 @@ func TestUpdateResourceStatus(t *testing.T) {
|
||||
apps: []v1alpha1.Application{},
|
||||
expectedResources: nil,
|
||||
},
|
||||
{
|
||||
name: "truncates resources status list to",
|
||||
appSet: v1alpha1.ApplicationSet{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "name",
|
||||
Namespace: "argocd",
|
||||
},
|
||||
Status: v1alpha1.ApplicationSetStatus{
|
||||
Resources: []v1alpha1.ResourceStatus{
|
||||
{
|
||||
Name: "app1",
|
||||
Status: v1alpha1.SyncStatusCodeOutOfSync,
|
||||
Health: &v1alpha1.HealthStatus{
|
||||
Status: health.HealthStatusProgressing,
|
||||
Message: "this is progressing",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "app2",
|
||||
Status: v1alpha1.SyncStatusCodeOutOfSync,
|
||||
Health: &v1alpha1.HealthStatus{
|
||||
Status: health.HealthStatusProgressing,
|
||||
Message: "this is progressing",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
apps: []v1alpha1.Application{
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "app1",
|
||||
},
|
||||
Status: v1alpha1.ApplicationStatus{
|
||||
Sync: v1alpha1.SyncStatus{
|
||||
Status: v1alpha1.SyncStatusCodeSynced,
|
||||
},
|
||||
Health: v1alpha1.HealthStatus{
|
||||
Status: health.HealthStatusHealthy,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "app2",
|
||||
},
|
||||
Status: v1alpha1.ApplicationStatus{
|
||||
Sync: v1alpha1.SyncStatus{
|
||||
Status: v1alpha1.SyncStatusCodeSynced,
|
||||
},
|
||||
Health: v1alpha1.HealthStatus{
|
||||
Status: health.HealthStatusHealthy,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedResources: []v1alpha1.ResourceStatus{
|
||||
{
|
||||
Name: "app1",
|
||||
Status: v1alpha1.SyncStatusCodeSynced,
|
||||
Health: &v1alpha1.HealthStatus{
|
||||
Status: health.HealthStatusHealthy,
|
||||
},
|
||||
},
|
||||
},
|
||||
maxResourcesStatusCount: 1,
|
||||
},
|
||||
} {
|
||||
t.Run(cc.name, func(t *testing.T) {
|
||||
kubeclientset := kubefake.NewSimpleClientset([]runtime.Object{}...)
|
||||
@@ -6279,13 +6347,14 @@ func TestUpdateResourceStatus(t *testing.T) {
|
||||
metrics := appsetmetrics.NewFakeAppsetMetrics(client)
|
||||
|
||||
r := ApplicationSetReconciler{
|
||||
Client: client,
|
||||
Scheme: scheme,
|
||||
Recorder: record.NewFakeRecorder(1),
|
||||
Generators: map[string]generators.Generator{},
|
||||
ArgoDB: &dbmocks.ArgoDB{},
|
||||
KubeClientset: kubeclientset,
|
||||
Metrics: metrics,
|
||||
Client: client,
|
||||
Scheme: scheme,
|
||||
Recorder: record.NewFakeRecorder(1),
|
||||
Generators: map[string]generators.Generator{},
|
||||
ArgoDB: &dbmocks.ArgoDB{},
|
||||
KubeClientset: kubeclientset,
|
||||
Metrics: metrics,
|
||||
MaxResourcesStatusCount: cc.maxResourcesStatusCount,
|
||||
}
|
||||
|
||||
err := r.updateResourcesStatus(context.TODO(), log.NewEntry(log.StandardLogger()), &cc.appSet, cc.apps)
|
||||
|
||||
@@ -28,10 +28,11 @@ type GitGenerator struct {
|
||||
namespace string
|
||||
}
|
||||
|
||||
func NewGitGenerator(repos services.Repos, namespace string) Generator {
|
||||
// NewGitGenerator creates a new instance of Git Generator
|
||||
func NewGitGenerator(repos services.Repos, controllerNamespace string) Generator {
|
||||
g := &GitGenerator{
|
||||
repos: repos,
|
||||
namespace: namespace,
|
||||
namespace: controllerNamespace,
|
||||
}
|
||||
|
||||
return g
|
||||
@@ -70,11 +71,11 @@ func (g *GitGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.Applic
|
||||
if !strings.Contains(appSet.Spec.Template.Spec.Project, "{{") {
|
||||
project := appSet.Spec.Template.Spec.Project
|
||||
appProject := &argoprojiov1alpha1.AppProject{}
|
||||
namespace := g.namespace
|
||||
if namespace == "" {
|
||||
namespace = appSet.Namespace
|
||||
controllerNamespace := g.namespace
|
||||
if controllerNamespace == "" {
|
||||
controllerNamespace = appSet.Namespace
|
||||
}
|
||||
if err := client.Get(context.TODO(), types.NamespacedName{Name: project, Namespace: namespace}, appProject); err != nil {
|
||||
if err := client.Get(context.TODO(), types.NamespacedName{Name: project, Namespace: controllerNamespace}, appProject); err != nil {
|
||||
return nil, fmt.Errorf("error getting project %s: %w", project, err)
|
||||
}
|
||||
// we need to verify the signature on the Git revision if GPG is enabled
|
||||
|
||||
@@ -10,15 +10,15 @@ import (
|
||||
"github.com/argoproj/argo-cd/v2/applicationset/services"
|
||||
)
|
||||
|
||||
func GetGenerators(ctx context.Context, c client.Client, k8sClient kubernetes.Interface, namespace string, argoCDService services.Repos, dynamicClient dynamic.Interface, scmConfig SCMConfig) map[string]Generator {
|
||||
func GetGenerators(ctx context.Context, c client.Client, k8sClient kubernetes.Interface, controllerNamespace string, argoCDService services.Repos, dynamicClient dynamic.Interface, scmConfig SCMConfig) map[string]Generator {
|
||||
terminalGenerators := map[string]Generator{
|
||||
"List": NewListGenerator(),
|
||||
"Clusters": NewClusterGenerator(c, ctx, k8sClient, namespace),
|
||||
"Git": NewGitGenerator(argoCDService, namespace),
|
||||
"Clusters": NewClusterGenerator(c, ctx, k8sClient, controllerNamespace),
|
||||
"Git": NewGitGenerator(argoCDService, controllerNamespace),
|
||||
"SCMProvider": NewSCMProviderGenerator(c, scmConfig),
|
||||
"ClusterDecisionResource": NewDuckTypeGenerator(ctx, dynamicClient, k8sClient, namespace),
|
||||
"ClusterDecisionResource": NewDuckTypeGenerator(ctx, dynamicClient, k8sClient, controllerNamespace),
|
||||
"PullRequest": NewPullRequestGenerator(c, scmConfig),
|
||||
"Plugin": NewPluginGenerator(c, ctx, k8sClient, namespace),
|
||||
"Plugin": NewPluginGenerator(c, ctx, k8sClient, controllerNamespace),
|
||||
}
|
||||
|
||||
nestedGenerators := map[string]Generator{
|
||||
|
||||
@@ -25,10 +25,14 @@ import (
|
||||
"github.com/go-playground/webhooks/v6/github"
|
||||
"github.com/go-playground/webhooks/v6/gitlab"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/argoproj/argo-cd/v2/util/guard"
|
||||
)
|
||||
|
||||
const payloadQueueSize = 50000
|
||||
|
||||
const panicMsgAppSet = "panic while processing applicationset-controller webhook event"
|
||||
|
||||
type WebhookHandler struct {
|
||||
sync.WaitGroup // for testing
|
||||
namespace string
|
||||
@@ -103,6 +107,7 @@ func NewWebhookHandler(namespace string, webhookParallelism int, argocdSettingsM
|
||||
}
|
||||
|
||||
func (h *WebhookHandler) startWorkerPool(webhookParallelism int) {
|
||||
compLog := log.WithField("component", "applicationset-webhook")
|
||||
for i := 0; i < webhookParallelism; i++ {
|
||||
h.Add(1)
|
||||
go func() {
|
||||
@@ -112,7 +117,7 @@ func (h *WebhookHandler) startWorkerPool(webhookParallelism int) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
h.HandleEvent(payload)
|
||||
guard.RecoverAndLog(func() { h.HandleEvent(payload) }, compLog, panicMsgAppSet)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
@@ -74,6 +74,7 @@ func NewCommand() *cobra.Command {
|
||||
enableScmProviders bool
|
||||
webhookParallelism int
|
||||
tokenRefStrictMode bool
|
||||
maxResourcesStatusCount int
|
||||
)
|
||||
scheme := runtime.NewScheme()
|
||||
_ = clientgoscheme.AddToScheme(scheme)
|
||||
@@ -227,6 +228,7 @@ func NewCommand() *cobra.Command {
|
||||
GlobalPreservedAnnotations: globalPreservedAnnotations,
|
||||
GlobalPreservedLabels: globalPreservedLabels,
|
||||
Metrics: &metrics,
|
||||
MaxResourcesStatusCount: maxResourcesStatusCount,
|
||||
}).SetupWithManager(mgr, enableProgressiveSyncs, maxConcurrentReconciliations); err != nil {
|
||||
log.Error(err, "unable to create controller", "controller", "ApplicationSet")
|
||||
os.Exit(1)
|
||||
@@ -270,6 +272,7 @@ func NewCommand() *cobra.Command {
|
||||
command.Flags().StringSliceVar(&globalPreservedLabels, "preserved-labels", env.StringsFromEnv("ARGOCD_APPLICATIONSET_CONTROLLER_GLOBAL_PRESERVED_LABELS", []string{}, ","), "Sets global preserved field values for labels")
|
||||
command.Flags().IntVar(&webhookParallelism, "webhook-parallelism-limit", env.ParseNumFromEnv("ARGOCD_APPLICATIONSET_CONTROLLER_WEBHOOK_PARALLELISM_LIMIT", 50, 1, 1000), "Number of webhook requests processed concurrently")
|
||||
command.Flags().StringSliceVar(&metricsAplicationsetLabels, "metrics-applicationset-labels", []string{}, "List of Application labels that will be added to the argocd_applicationset_labels metric")
|
||||
command.Flags().IntVar(&maxResourcesStatusCount, "max-resources-status-count", env.ParseNumFromEnv("ARGOCD_APPLICATIONSET_CONTROLLER_MAX_RESOURCES_STATUS_COUNT", 0, 0, math.MaxInt), "Max number of resources stored in appset status.")
|
||||
return &command
|
||||
}
|
||||
|
||||
|
||||
@@ -1197,7 +1197,7 @@ func (ctrl *ApplicationController) finalizeApplicationDeletion(app *appv1.Applic
|
||||
isValid, cluster := ctrl.isValidDestination(app)
|
||||
if !isValid {
|
||||
app.UnSetCascadedDeletion()
|
||||
app.UnSetPostDeleteFinalizer()
|
||||
app.UnSetPostDeleteFinalizerAll()
|
||||
if err := ctrl.updateFinalizers(app); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -272,6 +272,8 @@ data:
|
||||
applicationsetcontroller.requeue.after: "3m"
|
||||
# Enable strict mode for tokenRef in ApplicationSet resources. When enabled, the referenced secret must have a label `argocd.argoproj.io/secret-type` with value `scm-creds`.
|
||||
applicationsetcontroller.enable.tokenref.strict.mode: "false"
|
||||
# The maximum number of resources stored in the status of an ApplicationSet. This is a safeguard to prevent the status from growing too large.
|
||||
applicationsetcontroller.status.max.resources.count: "5000"
|
||||
|
||||
## Argo CD Notifications Controller Properties
|
||||
# Set the logging level. One of: debug|info|warn|error (default "info")
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Argo CD is largely stateless. All data is persisted as Kubernetes objects, which in turn is stored in Kubernetes' etcd. Redis is only used as a throw-away cache and can be lost. When lost, it will be rebuilt without loss of service.
|
||||
|
||||
A set of [HA manifests](https://github.com/argoproj/argo-cd/tree/master/manifests/ha) are provided for users who wish to run Argo CD in a highly available manner. This runs more containers, and runs Redis in HA mode.
|
||||
A set of [HA manifests](https://github.com/argoproj/argo-cd/tree/stable/manifests/ha) are provided for users who wish to run Argo CD in a highly available manner. This runs more containers, and runs Redis in HA mode.
|
||||
|
||||
> **NOTE:** The HA installation will require at least three different nodes due to pod anti-affinity roles in the
|
||||
> specs. Additionally, IPv6 only clusters are not supported.
|
||||
|
||||
@@ -175,6 +175,12 @@ spec:
|
||||
name: argocd-cmd-params-cm
|
||||
key: applicationsetcontroller.requeue.after
|
||||
optional: true
|
||||
- name: ARGOCD_APPLICATIONSET_CONTROLLER_MAX_RESOURCES_STATUS_COUNT
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: argocd-cmd-params-cm
|
||||
key: applicationsetcontroller.status.max.resources.count
|
||||
optional: true
|
||||
volumeMounts:
|
||||
- mountPath: /app/config/ssh
|
||||
name: ssh-known-hosts
|
||||
|
||||
@@ -12,4 +12,4 @@ resources:
|
||||
images:
|
||||
- name: quay.io/argoproj/argocd
|
||||
newName: quay.io/argoproj/argocd
|
||||
newTag: v2.14.16
|
||||
newTag: v2.14.21
|
||||
|
||||
@@ -5,7 +5,7 @@ kind: Kustomization
|
||||
images:
|
||||
- name: quay.io/argoproj/argocd
|
||||
newName: quay.io/argoproj/argocd
|
||||
newTag: v2.14.16
|
||||
newTag: v2.14.21
|
||||
resources:
|
||||
- ./application-controller
|
||||
- ./dex
|
||||
|
||||
@@ -40,7 +40,7 @@ spec:
|
||||
serviceAccountName: argocd-redis
|
||||
containers:
|
||||
- name: redis
|
||||
image: redis:7.0.15-alpine
|
||||
image: redis:7.2.11-alpine
|
||||
imagePullPolicy: Always
|
||||
args:
|
||||
- "--save"
|
||||
|
||||
@@ -24165,7 +24165,13 @@ spec:
|
||||
key: applicationsetcontroller.requeue.after
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
- name: ARGOCD_APPLICATIONSET_CONTROLLER_MAX_RESOURCES_STATUS_COUNT
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: applicationsetcontroller.status.max.resources.count
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
name: argocd-applicationset-controller
|
||||
ports:
|
||||
@@ -24285,7 +24291,7 @@ spec:
|
||||
key: commitserver.log.level
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -24331,7 +24337,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /var/run/argocd/argocd-cmp-server
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
name: copyutil
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
@@ -24419,7 +24425,7 @@ spec:
|
||||
secretKeyRef:
|
||||
key: auth
|
||||
name: argocd-redis
|
||||
image: redis:7.0.15-alpine
|
||||
image: redis:7.2.11-alpine
|
||||
imagePullPolicy: Always
|
||||
name: redis
|
||||
ports:
|
||||
@@ -24435,7 +24441,7 @@ spec:
|
||||
- argocd
|
||||
- admin
|
||||
- redis-initial-password
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: secret-init
|
||||
securityContext:
|
||||
@@ -24696,7 +24702,7 @@ spec:
|
||||
value: /helm-working-dir
|
||||
- name: HELM_DATA_HOME
|
||||
value: /helm-working-dir
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -24748,7 +24754,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /var/run/argocd/argocd-cmp-server
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
name: copyutil
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
@@ -25078,7 +25084,7 @@ spec:
|
||||
optional: true
|
||||
- name: KUBECACHEDIR
|
||||
value: /tmp/kubecache
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
name: argocd-application-controller
|
||||
ports:
|
||||
|
||||
18
manifests/core-install.yaml
generated
18
manifests/core-install.yaml
generated
@@ -24133,7 +24133,13 @@ spec:
|
||||
key: applicationsetcontroller.requeue.after
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
- name: ARGOCD_APPLICATIONSET_CONTROLLER_MAX_RESOURCES_STATUS_COUNT
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: applicationsetcontroller.status.max.resources.count
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
name: argocd-applicationset-controller
|
||||
ports:
|
||||
@@ -24237,7 +24243,7 @@ spec:
|
||||
secretKeyRef:
|
||||
key: auth
|
||||
name: argocd-redis
|
||||
image: redis:7.0.15-alpine
|
||||
image: redis:7.2.11-alpine
|
||||
imagePullPolicy: Always
|
||||
name: redis
|
||||
ports:
|
||||
@@ -24253,7 +24259,7 @@ spec:
|
||||
- argocd
|
||||
- admin
|
||||
- redis-initial-password
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: secret-init
|
||||
securityContext:
|
||||
@@ -24514,7 +24520,7 @@ spec:
|
||||
value: /helm-working-dir
|
||||
- name: HELM_DATA_HOME
|
||||
value: /helm-working-dir
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -24566,7 +24572,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /var/run/argocd/argocd-cmp-server
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
name: copyutil
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
@@ -24896,7 +24902,7 @@ spec:
|
||||
optional: true
|
||||
- name: KUBECACHEDIR
|
||||
value: /tmp/kubecache
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
name: argocd-application-controller
|
||||
ports:
|
||||
|
||||
@@ -12,4 +12,4 @@ resources:
|
||||
images:
|
||||
- name: quay.io/argoproj/argocd
|
||||
newName: quay.io/argoproj/argocd
|
||||
newTag: v2.14.16
|
||||
newTag: v2.14.21
|
||||
|
||||
@@ -12,7 +12,7 @@ patches:
|
||||
images:
|
||||
- name: quay.io/argoproj/argocd
|
||||
newName: quay.io/argoproj/argocd
|
||||
newTag: v2.14.16
|
||||
newTag: v2.14.21
|
||||
resources:
|
||||
- ../../base/application-controller
|
||||
- ../../base/applicationset-controller
|
||||
|
||||
@@ -1219,7 +1219,7 @@ spec:
|
||||
automountServiceAccountToken: false
|
||||
initContainers:
|
||||
- name: config-init
|
||||
image: public.ecr.aws/docker/library/redis:7.0.15-alpine
|
||||
image: public.ecr.aws/docker/library/redis:7.2.11-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
resources:
|
||||
{}
|
||||
@@ -1258,7 +1258,7 @@ spec:
|
||||
|
||||
containers:
|
||||
- name: redis
|
||||
image: public.ecr.aws/docker/library/redis:7.0.15-alpine
|
||||
image: public.ecr.aws/docker/library/redis:7.2.11-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
command:
|
||||
- redis-server
|
||||
@@ -1321,7 +1321,7 @@ spec:
|
||||
- /bin/sh
|
||||
- /readonly-config/trigger-failover-if-master.sh
|
||||
- name: sentinel
|
||||
image: public.ecr.aws/docker/library/redis:7.0.15-alpine
|
||||
image: public.ecr.aws/docker/library/redis:7.2.11-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
command:
|
||||
- redis-sentinel
|
||||
@@ -1383,7 +1383,7 @@ spec:
|
||||
- sleep 30; redis-cli -p 26379 sentinel reset argocd
|
||||
|
||||
- name: split-brain-fix
|
||||
image: public.ecr.aws/docker/library/redis:7.0.15-alpine
|
||||
image: public.ecr.aws/docker/library/redis:7.2.11-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
command:
|
||||
- sh
|
||||
|
||||
@@ -23,7 +23,7 @@ redis-ha:
|
||||
metrics:
|
||||
enabled: true
|
||||
image:
|
||||
tag: 7.0.15-alpine
|
||||
tag: 7.2.11-alpine
|
||||
containerSecurityContext: null
|
||||
sentinel:
|
||||
bind: '0.0.0.0'
|
||||
|
||||
@@ -25506,7 +25506,13 @@ spec:
|
||||
key: applicationsetcontroller.requeue.after
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
- name: ARGOCD_APPLICATIONSET_CONTROLLER_MAX_RESOURCES_STATUS_COUNT
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: applicationsetcontroller.status.max.resources.count
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
name: argocd-applicationset-controller
|
||||
ports:
|
||||
@@ -25626,7 +25632,7 @@ spec:
|
||||
key: commitserver.log.level
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -25672,7 +25678,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /var/run/argocd/argocd-cmp-server
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
name: copyutil
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
@@ -25793,7 +25799,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /shared/argocd-dex
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
name: copyutil
|
||||
securityContext:
|
||||
@@ -25883,7 +25889,7 @@ spec:
|
||||
key: notificationscontroller.repo.server.plaintext
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
@@ -26004,7 +26010,7 @@ spec:
|
||||
- argocd
|
||||
- admin
|
||||
- redis-initial-password
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: secret-init
|
||||
securityContext:
|
||||
@@ -26291,7 +26297,7 @@ spec:
|
||||
value: /helm-working-dir
|
||||
- name: HELM_DATA_HOME
|
||||
value: /helm-working-dir
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -26343,7 +26349,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /var/run/argocd/argocd-cmp-server
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
name: copyutil
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
@@ -26705,7 +26711,7 @@ spec:
|
||||
key: hydrator.enabled
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
@@ -27071,7 +27077,7 @@ spec:
|
||||
optional: true
|
||||
- name: KUBECACHEDIR
|
||||
value: /tmp/kubecache
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
name: argocd-application-controller
|
||||
ports:
|
||||
@@ -27169,7 +27175,7 @@ spec:
|
||||
secretKeyRef:
|
||||
key: auth
|
||||
name: argocd-redis
|
||||
image: public.ecr.aws/docker/library/redis:7.0.15-alpine
|
||||
image: public.ecr.aws/docker/library/redis:7.2.11-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
lifecycle:
|
||||
preStop:
|
||||
@@ -27229,7 +27235,7 @@ spec:
|
||||
secretKeyRef:
|
||||
key: auth
|
||||
name: argocd-redis
|
||||
image: public.ecr.aws/docker/library/redis:7.0.15-alpine
|
||||
image: public.ecr.aws/docker/library/redis:7.2.11-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
lifecycle:
|
||||
postStart:
|
||||
@@ -27293,7 +27299,7 @@ spec:
|
||||
secretKeyRef:
|
||||
key: auth
|
||||
name: argocd-redis
|
||||
image: public.ecr.aws/docker/library/redis:7.0.15-alpine
|
||||
image: public.ecr.aws/docker/library/redis:7.2.11-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: split-brain-fix
|
||||
resources: {}
|
||||
@@ -27328,7 +27334,7 @@ spec:
|
||||
secretKeyRef:
|
||||
key: auth
|
||||
name: argocd-redis
|
||||
image: public.ecr.aws/docker/library/redis:7.0.15-alpine
|
||||
image: public.ecr.aws/docker/library/redis:7.2.11-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: config-init
|
||||
securityContext:
|
||||
|
||||
30
manifests/ha/install.yaml
generated
30
manifests/ha/install.yaml
generated
@@ -25476,7 +25476,13 @@ spec:
|
||||
key: applicationsetcontroller.requeue.after
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
- name: ARGOCD_APPLICATIONSET_CONTROLLER_MAX_RESOURCES_STATUS_COUNT
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: applicationsetcontroller.status.max.resources.count
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
name: argocd-applicationset-controller
|
||||
ports:
|
||||
@@ -25613,7 +25619,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /shared/argocd-dex
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
name: copyutil
|
||||
securityContext:
|
||||
@@ -25703,7 +25709,7 @@ spec:
|
||||
key: notificationscontroller.repo.server.plaintext
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
@@ -25824,7 +25830,7 @@ spec:
|
||||
- argocd
|
||||
- admin
|
||||
- redis-initial-password
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: secret-init
|
||||
securityContext:
|
||||
@@ -26111,7 +26117,7 @@ spec:
|
||||
value: /helm-working-dir
|
||||
- name: HELM_DATA_HOME
|
||||
value: /helm-working-dir
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -26163,7 +26169,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /var/run/argocd/argocd-cmp-server
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
name: copyutil
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
@@ -26525,7 +26531,7 @@ spec:
|
||||
key: hydrator.enabled
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
@@ -26891,7 +26897,7 @@ spec:
|
||||
optional: true
|
||||
- name: KUBECACHEDIR
|
||||
value: /tmp/kubecache
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
name: argocd-application-controller
|
||||
ports:
|
||||
@@ -26989,7 +26995,7 @@ spec:
|
||||
secretKeyRef:
|
||||
key: auth
|
||||
name: argocd-redis
|
||||
image: public.ecr.aws/docker/library/redis:7.0.15-alpine
|
||||
image: public.ecr.aws/docker/library/redis:7.2.11-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
lifecycle:
|
||||
preStop:
|
||||
@@ -27049,7 +27055,7 @@ spec:
|
||||
secretKeyRef:
|
||||
key: auth
|
||||
name: argocd-redis
|
||||
image: public.ecr.aws/docker/library/redis:7.0.15-alpine
|
||||
image: public.ecr.aws/docker/library/redis:7.2.11-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
lifecycle:
|
||||
postStart:
|
||||
@@ -27113,7 +27119,7 @@ spec:
|
||||
secretKeyRef:
|
||||
key: auth
|
||||
name: argocd-redis
|
||||
image: public.ecr.aws/docker/library/redis:7.0.15-alpine
|
||||
image: public.ecr.aws/docker/library/redis:7.2.11-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: split-brain-fix
|
||||
resources: {}
|
||||
@@ -27148,7 +27154,7 @@ spec:
|
||||
secretKeyRef:
|
||||
key: auth
|
||||
name: argocd-redis
|
||||
image: public.ecr.aws/docker/library/redis:7.0.15-alpine
|
||||
image: public.ecr.aws/docker/library/redis:7.2.11-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: config-init
|
||||
securityContext:
|
||||
|
||||
@@ -1736,7 +1736,13 @@ spec:
|
||||
key: applicationsetcontroller.requeue.after
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
- name: ARGOCD_APPLICATIONSET_CONTROLLER_MAX_RESOURCES_STATUS_COUNT
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: applicationsetcontroller.status.max.resources.count
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
name: argocd-applicationset-controller
|
||||
ports:
|
||||
@@ -1856,7 +1862,7 @@ spec:
|
||||
key: commitserver.log.level
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -1902,7 +1908,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /var/run/argocd/argocd-cmp-server
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
name: copyutil
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
@@ -2023,7 +2029,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /shared/argocd-dex
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
name: copyutil
|
||||
securityContext:
|
||||
@@ -2113,7 +2119,7 @@ spec:
|
||||
key: notificationscontroller.repo.server.plaintext
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
@@ -2234,7 +2240,7 @@ spec:
|
||||
- argocd
|
||||
- admin
|
||||
- redis-initial-password
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: secret-init
|
||||
securityContext:
|
||||
@@ -2521,7 +2527,7 @@ spec:
|
||||
value: /helm-working-dir
|
||||
- name: HELM_DATA_HOME
|
||||
value: /helm-working-dir
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -2573,7 +2579,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /var/run/argocd/argocd-cmp-server
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
name: copyutil
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
@@ -2935,7 +2941,7 @@ spec:
|
||||
key: hydrator.enabled
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
@@ -3301,7 +3307,7 @@ spec:
|
||||
optional: true
|
||||
- name: KUBECACHEDIR
|
||||
value: /tmp/kubecache
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
name: argocd-application-controller
|
||||
ports:
|
||||
@@ -3399,7 +3405,7 @@ spec:
|
||||
secretKeyRef:
|
||||
key: auth
|
||||
name: argocd-redis
|
||||
image: public.ecr.aws/docker/library/redis:7.0.15-alpine
|
||||
image: public.ecr.aws/docker/library/redis:7.2.11-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
lifecycle:
|
||||
preStop:
|
||||
@@ -3459,7 +3465,7 @@ spec:
|
||||
secretKeyRef:
|
||||
key: auth
|
||||
name: argocd-redis
|
||||
image: public.ecr.aws/docker/library/redis:7.0.15-alpine
|
||||
image: public.ecr.aws/docker/library/redis:7.2.11-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
lifecycle:
|
||||
postStart:
|
||||
@@ -3523,7 +3529,7 @@ spec:
|
||||
secretKeyRef:
|
||||
key: auth
|
||||
name: argocd-redis
|
||||
image: public.ecr.aws/docker/library/redis:7.0.15-alpine
|
||||
image: public.ecr.aws/docker/library/redis:7.2.11-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: split-brain-fix
|
||||
resources: {}
|
||||
@@ -3558,7 +3564,7 @@ spec:
|
||||
secretKeyRef:
|
||||
key: auth
|
||||
name: argocd-redis
|
||||
image: public.ecr.aws/docker/library/redis:7.0.15-alpine
|
||||
image: public.ecr.aws/docker/library/redis:7.2.11-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: config-init
|
||||
securityContext:
|
||||
|
||||
30
manifests/ha/namespace-install.yaml
generated
30
manifests/ha/namespace-install.yaml
generated
@@ -1706,7 +1706,13 @@ spec:
|
||||
key: applicationsetcontroller.requeue.after
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
- name: ARGOCD_APPLICATIONSET_CONTROLLER_MAX_RESOURCES_STATUS_COUNT
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: applicationsetcontroller.status.max.resources.count
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
name: argocd-applicationset-controller
|
||||
ports:
|
||||
@@ -1843,7 +1849,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /shared/argocd-dex
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
name: copyutil
|
||||
securityContext:
|
||||
@@ -1933,7 +1939,7 @@ spec:
|
||||
key: notificationscontroller.repo.server.plaintext
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
@@ -2054,7 +2060,7 @@ spec:
|
||||
- argocd
|
||||
- admin
|
||||
- redis-initial-password
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: secret-init
|
||||
securityContext:
|
||||
@@ -2341,7 +2347,7 @@ spec:
|
||||
value: /helm-working-dir
|
||||
- name: HELM_DATA_HOME
|
||||
value: /helm-working-dir
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -2393,7 +2399,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /var/run/argocd/argocd-cmp-server
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
name: copyutil
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
@@ -2755,7 +2761,7 @@ spec:
|
||||
key: hydrator.enabled
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
@@ -3121,7 +3127,7 @@ spec:
|
||||
optional: true
|
||||
- name: KUBECACHEDIR
|
||||
value: /tmp/kubecache
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
name: argocd-application-controller
|
||||
ports:
|
||||
@@ -3219,7 +3225,7 @@ spec:
|
||||
secretKeyRef:
|
||||
key: auth
|
||||
name: argocd-redis
|
||||
image: public.ecr.aws/docker/library/redis:7.0.15-alpine
|
||||
image: public.ecr.aws/docker/library/redis:7.2.11-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
lifecycle:
|
||||
preStop:
|
||||
@@ -3279,7 +3285,7 @@ spec:
|
||||
secretKeyRef:
|
||||
key: auth
|
||||
name: argocd-redis
|
||||
image: public.ecr.aws/docker/library/redis:7.0.15-alpine
|
||||
image: public.ecr.aws/docker/library/redis:7.2.11-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
lifecycle:
|
||||
postStart:
|
||||
@@ -3343,7 +3349,7 @@ spec:
|
||||
secretKeyRef:
|
||||
key: auth
|
||||
name: argocd-redis
|
||||
image: public.ecr.aws/docker/library/redis:7.0.15-alpine
|
||||
image: public.ecr.aws/docker/library/redis:7.2.11-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: split-brain-fix
|
||||
resources: {}
|
||||
@@ -3378,7 +3384,7 @@ spec:
|
||||
secretKeyRef:
|
||||
key: auth
|
||||
name: argocd-redis
|
||||
image: public.ecr.aws/docker/library/redis:7.0.15-alpine
|
||||
image: public.ecr.aws/docker/library/redis:7.2.11-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: config-init
|
||||
securityContext:
|
||||
|
||||
@@ -24625,7 +24625,13 @@ spec:
|
||||
key: applicationsetcontroller.requeue.after
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
- name: ARGOCD_APPLICATIONSET_CONTROLLER_MAX_RESOURCES_STATUS_COUNT
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: applicationsetcontroller.status.max.resources.count
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
name: argocd-applicationset-controller
|
||||
ports:
|
||||
@@ -24745,7 +24751,7 @@ spec:
|
||||
key: commitserver.log.level
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -24791,7 +24797,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /var/run/argocd/argocd-cmp-server
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
name: copyutil
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
@@ -24912,7 +24918,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /shared/argocd-dex
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
name: copyutil
|
||||
securityContext:
|
||||
@@ -25002,7 +25008,7 @@ spec:
|
||||
key: notificationscontroller.repo.server.plaintext
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
@@ -25088,7 +25094,7 @@ spec:
|
||||
secretKeyRef:
|
||||
key: auth
|
||||
name: argocd-redis
|
||||
image: redis:7.0.15-alpine
|
||||
image: redis:7.2.11-alpine
|
||||
imagePullPolicy: Always
|
||||
name: redis
|
||||
ports:
|
||||
@@ -25104,7 +25110,7 @@ spec:
|
||||
- argocd
|
||||
- admin
|
||||
- redis-initial-password
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: secret-init
|
||||
securityContext:
|
||||
@@ -25365,7 +25371,7 @@ spec:
|
||||
value: /helm-working-dir
|
||||
- name: HELM_DATA_HOME
|
||||
value: /helm-working-dir
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -25417,7 +25423,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /var/run/argocd/argocd-cmp-server
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
name: copyutil
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
@@ -25777,7 +25783,7 @@ spec:
|
||||
key: hydrator.enabled
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
@@ -26143,7 +26149,7 @@ spec:
|
||||
optional: true
|
||||
- name: KUBECACHEDIR
|
||||
value: /tmp/kubecache
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
name: argocd-application-controller
|
||||
ports:
|
||||
|
||||
24
manifests/install.yaml
generated
24
manifests/install.yaml
generated
@@ -24593,7 +24593,13 @@ spec:
|
||||
key: applicationsetcontroller.requeue.after
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
- name: ARGOCD_APPLICATIONSET_CONTROLLER_MAX_RESOURCES_STATUS_COUNT
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: applicationsetcontroller.status.max.resources.count
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
name: argocd-applicationset-controller
|
||||
ports:
|
||||
@@ -24730,7 +24736,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /shared/argocd-dex
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
name: copyutil
|
||||
securityContext:
|
||||
@@ -24820,7 +24826,7 @@ spec:
|
||||
key: notificationscontroller.repo.server.plaintext
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
@@ -24906,7 +24912,7 @@ spec:
|
||||
secretKeyRef:
|
||||
key: auth
|
||||
name: argocd-redis
|
||||
image: redis:7.0.15-alpine
|
||||
image: redis:7.2.11-alpine
|
||||
imagePullPolicy: Always
|
||||
name: redis
|
||||
ports:
|
||||
@@ -24922,7 +24928,7 @@ spec:
|
||||
- argocd
|
||||
- admin
|
||||
- redis-initial-password
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: secret-init
|
||||
securityContext:
|
||||
@@ -25183,7 +25189,7 @@ spec:
|
||||
value: /helm-working-dir
|
||||
- name: HELM_DATA_HOME
|
||||
value: /helm-working-dir
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -25235,7 +25241,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /var/run/argocd/argocd-cmp-server
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
name: copyutil
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
@@ -25595,7 +25601,7 @@ spec:
|
||||
key: hydrator.enabled
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
@@ -25961,7 +25967,7 @@ spec:
|
||||
optional: true
|
||||
- name: KUBECACHEDIR
|
||||
value: /tmp/kubecache
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
name: argocd-application-controller
|
||||
ports:
|
||||
|
||||
@@ -855,7 +855,13 @@ spec:
|
||||
key: applicationsetcontroller.requeue.after
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
- name: ARGOCD_APPLICATIONSET_CONTROLLER_MAX_RESOURCES_STATUS_COUNT
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: applicationsetcontroller.status.max.resources.count
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
name: argocd-applicationset-controller
|
||||
ports:
|
||||
@@ -975,7 +981,7 @@ spec:
|
||||
key: commitserver.log.level
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -1021,7 +1027,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /var/run/argocd/argocd-cmp-server
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
name: copyutil
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
@@ -1142,7 +1148,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /shared/argocd-dex
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
name: copyutil
|
||||
securityContext:
|
||||
@@ -1232,7 +1238,7 @@ spec:
|
||||
key: notificationscontroller.repo.server.plaintext
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
@@ -1318,7 +1324,7 @@ spec:
|
||||
secretKeyRef:
|
||||
key: auth
|
||||
name: argocd-redis
|
||||
image: redis:7.0.15-alpine
|
||||
image: redis:7.2.11-alpine
|
||||
imagePullPolicy: Always
|
||||
name: redis
|
||||
ports:
|
||||
@@ -1334,7 +1340,7 @@ spec:
|
||||
- argocd
|
||||
- admin
|
||||
- redis-initial-password
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: secret-init
|
||||
securityContext:
|
||||
@@ -1595,7 +1601,7 @@ spec:
|
||||
value: /helm-working-dir
|
||||
- name: HELM_DATA_HOME
|
||||
value: /helm-working-dir
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -1647,7 +1653,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /var/run/argocd/argocd-cmp-server
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
name: copyutil
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
@@ -2007,7 +2013,7 @@ spec:
|
||||
key: hydrator.enabled
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
@@ -2373,7 +2379,7 @@ spec:
|
||||
optional: true
|
||||
- name: KUBECACHEDIR
|
||||
value: /tmp/kubecache
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
name: argocd-application-controller
|
||||
ports:
|
||||
|
||||
24
manifests/namespace-install.yaml
generated
24
manifests/namespace-install.yaml
generated
@@ -823,7 +823,13 @@ spec:
|
||||
key: applicationsetcontroller.requeue.after
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
- name: ARGOCD_APPLICATIONSET_CONTROLLER_MAX_RESOURCES_STATUS_COUNT
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: applicationsetcontroller.status.max.resources.count
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
name: argocd-applicationset-controller
|
||||
ports:
|
||||
@@ -960,7 +966,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /shared/argocd-dex
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
name: copyutil
|
||||
securityContext:
|
||||
@@ -1050,7 +1056,7 @@ spec:
|
||||
key: notificationscontroller.repo.server.plaintext
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
@@ -1136,7 +1142,7 @@ spec:
|
||||
secretKeyRef:
|
||||
key: auth
|
||||
name: argocd-redis
|
||||
image: redis:7.0.15-alpine
|
||||
image: redis:7.2.11-alpine
|
||||
imagePullPolicy: Always
|
||||
name: redis
|
||||
ports:
|
||||
@@ -1152,7 +1158,7 @@ spec:
|
||||
- argocd
|
||||
- admin
|
||||
- redis-initial-password
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: secret-init
|
||||
securityContext:
|
||||
@@ -1413,7 +1419,7 @@ spec:
|
||||
value: /helm-working-dir
|
||||
- name: HELM_DATA_HOME
|
||||
value: /helm-working-dir
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -1465,7 +1471,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /var/run/argocd/argocd-cmp-server
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
name: copyutil
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
@@ -1825,7 +1831,7 @@ spec:
|
||||
key: hydrator.enabled
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
@@ -2191,7 +2197,7 @@ spec:
|
||||
optional: true
|
||||
- name: KUBECACHEDIR
|
||||
value: /tmp/kubecache
|
||||
image: quay.io/argoproj/argocd:v2.14.16
|
||||
image: quay.io/argoproj/argocd:v2.14.21
|
||||
imagePullPolicy: Always
|
||||
name: argocd-application-controller
|
||||
ports:
|
||||
|
||||
@@ -3060,6 +3060,14 @@ func (app *Application) SetPostDeleteFinalizer(stage ...string) {
|
||||
setFinalizer(&app.ObjectMeta, strings.Join(append([]string{PostDeleteFinalizerName}, stage...), "/"), true)
|
||||
}
|
||||
|
||||
func (app *Application) UnSetPostDeleteFinalizerAll() {
|
||||
for _, finalizer := range app.Finalizers {
|
||||
if strings.HasPrefix(finalizer, PostDeleteFinalizerName) {
|
||||
setFinalizer(&app.ObjectMeta, finalizer, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (app *Application) UnSetPostDeleteFinalizer(stage ...string) {
|
||||
setFinalizer(&app.ObjectMeta, strings.Join(append([]string{PostDeleteFinalizerName}, stage...), "/"), false)
|
||||
}
|
||||
|
||||
@@ -203,7 +203,7 @@ func (s *Server) Create(ctx context.Context, q *applicationset.ApplicationSetCre
|
||||
}
|
||||
|
||||
if q.GetDryRun() {
|
||||
apps, err := s.generateApplicationSetApps(ctx, log.WithField("applicationset", appset.Name), *appset, namespace)
|
||||
apps, err := s.generateApplicationSetApps(ctx, log.WithField("applicationset", appset.Name), *appset)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to generate Applications of ApplicationSet: %w", err)
|
||||
}
|
||||
@@ -262,7 +262,7 @@ func (s *Server) Create(ctx context.Context, q *applicationset.ApplicationSetCre
|
||||
return updated, nil
|
||||
}
|
||||
|
||||
func (s *Server) generateApplicationSetApps(ctx context.Context, logEntry *log.Entry, appset v1alpha1.ApplicationSet, namespace string) ([]v1alpha1.Application, error) {
|
||||
func (s *Server) generateApplicationSetApps(ctx context.Context, logEntry *log.Entry, appset v1alpha1.ApplicationSet) ([]v1alpha1.Application, error) {
|
||||
argoCDDB := s.db
|
||||
|
||||
scmConfig := generators.NewSCMConfig(s.ScmRootCAPath, s.AllowedScmProviders, s.EnableScmProviders, github_app.NewAuthCredentials(argoCDDB.(db.RepoCredsDB)), true)
|
||||
@@ -275,7 +275,7 @@ func (s *Server) generateApplicationSetApps(ctx context.Context, logEntry *log.E
|
||||
return nil, fmt.Errorf("error creating ArgoCDService: %w", err)
|
||||
}
|
||||
|
||||
appSetGenerators := generators.GetGenerators(ctx, s.client, s.k8sClient, namespace, argoCDService, s.dynamicClient, scmConfig)
|
||||
appSetGenerators := generators.GetGenerators(ctx, s.client, s.k8sClient, s.ns, argoCDService, s.dynamicClient, scmConfig)
|
||||
|
||||
apps, _, err := appsettemplate.GenerateApplications(logEntry, appset, appSetGenerators, &appsetutils.Render{}, s.client)
|
||||
if err != nil {
|
||||
@@ -372,11 +372,15 @@ func (s *Server) Generate(ctx context.Context, q *applicationset.ApplicationSetG
|
||||
if appset == nil {
|
||||
return nil, errors.New("error creating ApplicationSets: ApplicationSets is nil in request")
|
||||
}
|
||||
namespace := s.appsetNamespaceOrDefault(appset.Namespace)
|
||||
|
||||
// The RBAC check needs to be performed against the appset namespace
|
||||
// However, when trying to generate params, the server namespace needs
|
||||
// to be passed.
|
||||
namespace := s.appsetNamespaceOrDefault(appset.Namespace)
|
||||
if !s.isNamespaceEnabled(namespace) {
|
||||
return nil, security.NamespaceNotPermittedError(namespace)
|
||||
}
|
||||
|
||||
projectName, err := s.validateAppSet(appset)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error validating ApplicationSets: %w", err)
|
||||
@@ -389,7 +393,16 @@ func (s *Server) Generate(ctx context.Context, q *applicationset.ApplicationSetG
|
||||
logger := log.New()
|
||||
logger.SetOutput(logs)
|
||||
|
||||
apps, err := s.generateApplicationSetApps(ctx, logger.WithField("applicationset", appset.Name), *appset, namespace)
|
||||
// The server namespace will be used in the function
|
||||
// since this is the exact namespace that is being used
|
||||
// to generate parameters (especially for git generator).
|
||||
//
|
||||
// In case of Git generator, if the namespace is set to
|
||||
// appset namespace, we'll look for a project in the appset
|
||||
// namespace that would lead to error when generating params
|
||||
// for an appset in any namespace feature.
|
||||
// See https://github.com/argoproj/argo-cd/issues/22942
|
||||
apps, err := s.generateApplicationSetApps(ctx, logger.WithField("applicationset", appset.Name), *appset)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to generate Applications of ApplicationSet: %w\n%s", err, logs.String())
|
||||
}
|
||||
|
||||
@@ -5,6 +5,9 @@ import (
|
||||
"sort"
|
||||
"testing"
|
||||
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
cr_fake "sigs.k8s.io/controller-runtime/pkg/client/fake"
|
||||
|
||||
"github.com/argoproj/gitops-engine/pkg/health"
|
||||
"github.com/argoproj/pkg/sync"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -52,26 +55,29 @@ func fakeCluster() *appsv1.Cluster {
|
||||
}
|
||||
|
||||
// return an ApplicationServiceServer which returns fake data
|
||||
func newTestAppSetServer(objects ...runtime.Object) *Server {
|
||||
func newTestAppSetServer(t *testing.T, objects ...client.Object) *Server {
|
||||
t.Helper()
|
||||
f := func(enf *rbac.Enforcer) {
|
||||
_ = enf.SetBuiltinPolicy(assets.BuiltinPolicyCSV)
|
||||
enf.SetDefaultRole("role:admin")
|
||||
}
|
||||
scopedNamespaces := ""
|
||||
return newTestAppSetServerWithEnforcerConfigure(f, scopedNamespaces, objects...)
|
||||
return newTestAppSetServerWithEnforcerConfigure(t, f, scopedNamespaces, objects...)
|
||||
}
|
||||
|
||||
// return an ApplicationServiceServer which returns fake data
|
||||
func newTestNamespacedAppSetServer(objects ...runtime.Object) *Server {
|
||||
func newTestNamespacedAppSetServer(t *testing.T, objects ...client.Object) *Server {
|
||||
t.Helper()
|
||||
f := func(enf *rbac.Enforcer) {
|
||||
_ = enf.SetBuiltinPolicy(assets.BuiltinPolicyCSV)
|
||||
enf.SetDefaultRole("role:admin")
|
||||
}
|
||||
scopedNamespaces := "argocd"
|
||||
return newTestAppSetServerWithEnforcerConfigure(f, scopedNamespaces, objects...)
|
||||
return newTestAppSetServerWithEnforcerConfigure(t, f, scopedNamespaces, objects...)
|
||||
}
|
||||
|
||||
func newTestAppSetServerWithEnforcerConfigure(f func(*rbac.Enforcer), namespace string, objects ...runtime.Object) *Server {
|
||||
func newTestAppSetServerWithEnforcerConfigure(t *testing.T, f func(*rbac.Enforcer), namespace string, objects ...client.Object) *Server {
|
||||
t.Helper()
|
||||
kubeclientset := fake.NewClientset(&v1.ConfigMap{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: testNamespace,
|
||||
@@ -114,8 +120,12 @@ func newTestAppSetServerWithEnforcerConfigure(f func(*rbac.Enforcer), namespace
|
||||
|
||||
objects = append(objects, defaultProj, myProj)
|
||||
|
||||
fakeAppsClientset := apps.NewSimpleClientset(objects...)
|
||||
factory := appinformer.NewSharedInformerFactoryWithOptions(fakeAppsClientset, 0, appinformer.WithNamespace(namespace), appinformer.WithTweakListOptions(func(options *metav1.ListOptions) {}))
|
||||
runtimeObjects := make([]runtime.Object, len(objects))
|
||||
for i := range objects {
|
||||
runtimeObjects[i] = objects[i]
|
||||
}
|
||||
fakeAppsClientset := apps.NewSimpleClientset(runtimeObjects...)
|
||||
factory := appinformer.NewSharedInformerFactoryWithOptions(fakeAppsClientset, 0, appinformer.WithNamespace(namespace), appinformer.WithTweakListOptions(func(_ *metav1.ListOptions) {}))
|
||||
fakeProjLister := factory.Argoproj().V1alpha1().AppProjects().Lister().AppProjects(testNamespace)
|
||||
|
||||
enforcer := rbac.NewEnforcer(kubeclientset, testNamespace, common.ArgoCDRBACConfigMapName, nil)
|
||||
@@ -139,6 +149,13 @@ func newTestAppSetServerWithEnforcerConfigure(f func(*rbac.Enforcer), namespace
|
||||
panic("Timed out waiting for caches to sync")
|
||||
}
|
||||
|
||||
scheme := runtime.NewScheme()
|
||||
err = appsv1.AddToScheme(scheme)
|
||||
require.NoError(t, err)
|
||||
err = v1.AddToScheme(scheme)
|
||||
require.NoError(t, err)
|
||||
crClient := cr_fake.NewClientBuilder().WithScheme(scheme).WithObjects(objects...).Build()
|
||||
|
||||
projInformer := factory.Argoproj().V1alpha1().AppProjects().Informer()
|
||||
go projInformer.Run(ctx.Done())
|
||||
if !k8scache.WaitForCacheSync(ctx.Done(), projInformer.HasSynced) {
|
||||
@@ -149,7 +166,7 @@ func newTestAppSetServerWithEnforcerConfigure(f func(*rbac.Enforcer), namespace
|
||||
db,
|
||||
kubeclientset,
|
||||
nil,
|
||||
nil,
|
||||
crClient,
|
||||
enforcer,
|
||||
nil,
|
||||
fakeAppsClientset,
|
||||
@@ -274,17 +291,17 @@ func testListAppsetsWithLabels(t *testing.T, appsetQuery applicationset.Applicat
|
||||
|
||||
func TestListAppSetsInNamespaceWithLabels(t *testing.T) {
|
||||
testNamespace := "test-namespace"
|
||||
appSetServer := newTestAppSetServer(newTestAppSet(func(appset *appsv1.ApplicationSet) {
|
||||
appSetServer := newTestAppSetServer(t, newTestAppSet(func(appset *appsv1.ApplicationSet) {
|
||||
appset.Name = "AppSet1"
|
||||
appset.ObjectMeta.Namespace = testNamespace
|
||||
appset.Namespace = testNamespace
|
||||
appset.SetLabels(map[string]string{"key1": "value1", "key2": "value1"})
|
||||
}), newTestAppSet(func(appset *appsv1.ApplicationSet) {
|
||||
appset.Name = "AppSet2"
|
||||
appset.ObjectMeta.Namespace = testNamespace
|
||||
appset.Namespace = testNamespace
|
||||
appset.SetLabels(map[string]string{"key1": "value2"})
|
||||
}), newTestAppSet(func(appset *appsv1.ApplicationSet) {
|
||||
appset.Name = "AppSet3"
|
||||
appset.ObjectMeta.Namespace = testNamespace
|
||||
appset.Namespace = testNamespace
|
||||
appset.SetLabels(map[string]string{"key1": "value3"})
|
||||
}))
|
||||
appSetServer.enabledNamespaces = []string{testNamespace}
|
||||
@@ -294,7 +311,7 @@ func TestListAppSetsInNamespaceWithLabels(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestListAppSetsInDefaultNSWithLabels(t *testing.T) {
|
||||
appSetServer := newTestAppSetServer(newTestAppSet(func(appset *appsv1.ApplicationSet) {
|
||||
appSetServer := newTestAppSetServer(t, newTestAppSet(func(appset *appsv1.ApplicationSet) {
|
||||
appset.Name = "AppSet1"
|
||||
appset.SetLabels(map[string]string{"key1": "value1", "key2": "value1"})
|
||||
}), newTestAppSet(func(appset *appsv1.ApplicationSet) {
|
||||
@@ -314,30 +331,30 @@ func TestListAppSetsInDefaultNSWithLabels(t *testing.T) {
|
||||
// default namespace must be used and not all the namespaces
|
||||
func TestListAppSetsWithoutNamespace(t *testing.T) {
|
||||
testNamespace := "test-namespace"
|
||||
appSetServer := newTestNamespacedAppSetServer(newTestAppSet(func(appset *appsv1.ApplicationSet) {
|
||||
appSetServer := newTestNamespacedAppSetServer(t, newTestAppSet(func(appset *appsv1.ApplicationSet) {
|
||||
appset.Name = "AppSet1"
|
||||
appset.ObjectMeta.Namespace = testNamespace
|
||||
appset.Namespace = testNamespace
|
||||
appset.SetLabels(map[string]string{"key1": "value1", "key2": "value1"})
|
||||
}), newTestAppSet(func(appset *appsv1.ApplicationSet) {
|
||||
appset.Name = "AppSet2"
|
||||
appset.ObjectMeta.Namespace = testNamespace
|
||||
appset.Namespace = testNamespace
|
||||
appset.SetLabels(map[string]string{"key1": "value2"})
|
||||
}), newTestAppSet(func(appset *appsv1.ApplicationSet) {
|
||||
appset.Name = "AppSet3"
|
||||
appset.ObjectMeta.Namespace = testNamespace
|
||||
appset.Namespace = testNamespace
|
||||
appset.SetLabels(map[string]string{"key1": "value3"})
|
||||
}))
|
||||
appSetServer.enabledNamespaces = []string{testNamespace}
|
||||
appsetQuery := applicationset.ApplicationSetListQuery{}
|
||||
|
||||
res, err := appSetServer.List(context.Background(), &appsetQuery)
|
||||
res, err := appSetServer.List(t.Context(), &appsetQuery)
|
||||
require.NoError(t, err)
|
||||
assert.Empty(t, res.Items)
|
||||
}
|
||||
|
||||
func TestCreateAppSet(t *testing.T) {
|
||||
testAppSet := newTestAppSet()
|
||||
appServer := newTestAppSetServer()
|
||||
appServer := newTestAppSetServer(t)
|
||||
testAppSet.Spec.Generators = []appsv1.ApplicationSetGenerator{
|
||||
{
|
||||
List: &appsv1.ListGenerator{},
|
||||
@@ -346,36 +363,36 @@ func TestCreateAppSet(t *testing.T) {
|
||||
createReq := applicationset.ApplicationSetCreateRequest{
|
||||
Applicationset: testAppSet,
|
||||
}
|
||||
_, err := appServer.Create(context.Background(), &createReq)
|
||||
_, err := appServer.Create(t.Context(), &createReq)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestCreateAppSetTemplatedProject(t *testing.T) {
|
||||
testAppSet := newTestAppSet()
|
||||
appServer := newTestAppSetServer()
|
||||
appServer := newTestAppSetServer(t)
|
||||
testAppSet.Spec.Template.Spec.Project = "{{ .project }}"
|
||||
createReq := applicationset.ApplicationSetCreateRequest{
|
||||
Applicationset: testAppSet,
|
||||
}
|
||||
_, err := appServer.Create(context.Background(), &createReq)
|
||||
_, err := appServer.Create(t.Context(), &createReq)
|
||||
assert.EqualError(t, err, "error validating ApplicationSets: the Argo CD API does not currently support creating ApplicationSets with templated `project` fields")
|
||||
}
|
||||
|
||||
func TestCreateAppSetWrongNamespace(t *testing.T) {
|
||||
testAppSet := newTestAppSet()
|
||||
appServer := newTestAppSetServer()
|
||||
testAppSet.ObjectMeta.Namespace = "NOT-ALLOWED"
|
||||
appServer := newTestAppSetServer(t)
|
||||
testAppSet.Namespace = "NOT-ALLOWED"
|
||||
createReq := applicationset.ApplicationSetCreateRequest{
|
||||
Applicationset: testAppSet,
|
||||
}
|
||||
_, err := appServer.Create(context.Background(), &createReq)
|
||||
_, err := appServer.Create(t.Context(), &createReq)
|
||||
|
||||
assert.EqualError(t, err, "namespace 'NOT-ALLOWED' is not permitted")
|
||||
}
|
||||
|
||||
func TestCreateAppSetDryRun(t *testing.T) {
|
||||
testAppSet := newTestAppSet()
|
||||
appServer := newTestAppSetServer()
|
||||
appServer := newTestAppSetServer(t)
|
||||
testAppSet.Spec.Template.Name = "{{name}}"
|
||||
testAppSet.Spec.Generators = []appsv1.ApplicationSetGenerator{
|
||||
{
|
||||
@@ -388,7 +405,7 @@ func TestCreateAppSetDryRun(t *testing.T) {
|
||||
Applicationset: testAppSet,
|
||||
DryRun: true,
|
||||
}
|
||||
result, err := appServer.Create(context.Background(), &createReq)
|
||||
result, err := appServer.Create(t.Context(), &createReq)
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, result.Status.Resources, 2)
|
||||
@@ -406,7 +423,7 @@ func TestCreateAppSetDryRun(t *testing.T) {
|
||||
|
||||
func TestCreateAppSetDryRunWithDuplicate(t *testing.T) {
|
||||
testAppSet := newTestAppSet()
|
||||
appServer := newTestAppSetServer()
|
||||
appServer := newTestAppSetServer(t)
|
||||
testAppSet.Spec.Template.Name = "{{name}}"
|
||||
testAppSet.Spec.Generators = []appsv1.ApplicationSetGenerator{
|
||||
{
|
||||
@@ -419,7 +436,7 @@ func TestCreateAppSetDryRunWithDuplicate(t *testing.T) {
|
||||
Applicationset: testAppSet,
|
||||
DryRun: true,
|
||||
}
|
||||
result, err := appServer.Create(context.Background(), &createReq)
|
||||
result, err := appServer.Create(t.Context(), &createReq)
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, result.Status.Resources, 1)
|
||||
@@ -441,7 +458,7 @@ func TestGetAppSet(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("Get in default namespace", func(t *testing.T) {
|
||||
appSetServer := newTestAppSetServer(appSet1, appSet2, appSet3)
|
||||
appSetServer := newTestAppSetServer(t, appSet1, appSet2, appSet3)
|
||||
|
||||
appsetQuery := applicationset.ApplicationSetGetQuery{Name: "AppSet1"}
|
||||
|
||||
@@ -451,7 +468,7 @@ func TestGetAppSet(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("Get in named namespace", func(t *testing.T) {
|
||||
appSetServer := newTestAppSetServer(appSet1, appSet2, appSet3)
|
||||
appSetServer := newTestAppSetServer(t, appSet1, appSet2, appSet3)
|
||||
|
||||
appsetQuery := applicationset.ApplicationSetGetQuery{Name: "AppSet1", AppsetNamespace: testNamespace}
|
||||
|
||||
@@ -461,7 +478,7 @@ func TestGetAppSet(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("Get in not allowed namespace", func(t *testing.T) {
|
||||
appSetServer := newTestAppSetServer(appSet1, appSet2, appSet3)
|
||||
appSetServer := newTestAppSetServer(t, appSet1, appSet2, appSet3)
|
||||
|
||||
appsetQuery := applicationset.ApplicationSetGetQuery{Name: "AppSet1", AppsetNamespace: "NOT-ALLOWED"}
|
||||
|
||||
@@ -484,7 +501,7 @@ func TestDeleteAppSet(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("Delete in default namespace", func(t *testing.T) {
|
||||
appSetServer := newTestAppSetServer(appSet1, appSet2, appSet3)
|
||||
appSetServer := newTestAppSetServer(t, appSet1, appSet2, appSet3)
|
||||
|
||||
appsetQuery := applicationset.ApplicationSetDeleteRequest{Name: "AppSet1"}
|
||||
|
||||
@@ -494,7 +511,7 @@ func TestDeleteAppSet(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("Delete in named namespace", func(t *testing.T) {
|
||||
appSetServer := newTestAppSetServer(appSet1, appSet2, appSet3)
|
||||
appSetServer := newTestAppSetServer(t, appSet1, appSet2, appSet3)
|
||||
|
||||
appsetQuery := applicationset.ApplicationSetDeleteRequest{Name: "AppSet1", AppsetNamespace: testNamespace}
|
||||
|
||||
@@ -526,7 +543,7 @@ func TestUpdateAppSet(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("Update merge", func(t *testing.T) {
|
||||
appServer := newTestAppSetServer(appSet)
|
||||
appServer := newTestAppSetServer(t, appSet)
|
||||
|
||||
updated, err := appServer.updateAppSet(appSet, newAppSet, context.Background(), true)
|
||||
|
||||
@@ -542,7 +559,7 @@ func TestUpdateAppSet(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("Update no merge", func(t *testing.T) {
|
||||
appServer := newTestAppSetServer(appSet)
|
||||
appServer := newTestAppSetServer(t, appSet)
|
||||
|
||||
updated, err := appServer.updateAppSet(appSet, newAppSet, context.Background(), false)
|
||||
|
||||
@@ -611,7 +628,7 @@ func TestResourceTree(t *testing.T) {
|
||||
}
|
||||
|
||||
t.Run("ResourceTree in default namespace", func(t *testing.T) {
|
||||
appSetServer := newTestAppSetServer(appSet1, appSet2, appSet3)
|
||||
appSetServer := newTestAppSetServer(t, appSet1, appSet2, appSet3)
|
||||
|
||||
appsetQuery := applicationset.ApplicationSetTreeQuery{Name: "AppSet1"}
|
||||
|
||||
@@ -621,7 +638,7 @@ func TestResourceTree(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("ResourceTree in named namespace", func(t *testing.T) {
|
||||
appSetServer := newTestAppSetServer(appSet1, appSet2, appSet3)
|
||||
appSetServer := newTestAppSetServer(t, appSet1, appSet2, appSet3)
|
||||
|
||||
appsetQuery := applicationset.ApplicationSetTreeQuery{Name: "AppSet1", AppsetNamespace: testNamespace}
|
||||
|
||||
@@ -631,7 +648,7 @@ func TestResourceTree(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("ResourceTree in not allowed namespace", func(t *testing.T) {
|
||||
appSetServer := newTestAppSetServer(appSet1, appSet2, appSet3)
|
||||
appSetServer := newTestAppSetServer(t, appSet1, appSet2, appSet3)
|
||||
|
||||
appsetQuery := applicationset.ApplicationSetTreeQuery{Name: "AppSet1", AppsetNamespace: "NOT-ALLOWED"}
|
||||
|
||||
@@ -639,3 +656,54 @@ func TestResourceTree(t *testing.T) {
|
||||
assert.EqualError(t, err, "namespace 'NOT-ALLOWED' is not permitted")
|
||||
})
|
||||
}
|
||||
|
||||
func TestAppSet_Generate_Cluster(t *testing.T) {
|
||||
appSet1 := newTestAppSet(func(appset *appsv1.ApplicationSet) {
|
||||
appset.Name = "AppSet1"
|
||||
appset.Spec.Template.Name = "{{name}}"
|
||||
appset.Spec.Generators = []appsv1.ApplicationSetGenerator{
|
||||
{
|
||||
Clusters: &appsv1.ClusterGenerator{},
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Generate in default namespace", func(t *testing.T) {
|
||||
appSetServer := newTestAppSetServer(t, appSet1)
|
||||
appsetQuery := applicationset.ApplicationSetGenerateRequest{
|
||||
ApplicationSet: appSet1,
|
||||
}
|
||||
|
||||
res, err := appSetServer.Generate(t.Context(), &appsetQuery)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, res.Applications, 2)
|
||||
assert.Equal(t, "fake-cluster", res.Applications[0].Name)
|
||||
assert.Equal(t, "in-cluster", res.Applications[1].Name)
|
||||
})
|
||||
|
||||
t.Run("Generate in different namespace", func(t *testing.T) {
|
||||
appSetServer := newTestAppSetServer(t, appSet1)
|
||||
|
||||
appSet1Ns := appSet1.DeepCopy()
|
||||
appSet1Ns.Namespace = "external-namespace"
|
||||
appsetQuery := applicationset.ApplicationSetGenerateRequest{ApplicationSet: appSet1Ns}
|
||||
|
||||
res, err := appSetServer.Generate(t.Context(), &appsetQuery)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, res.Applications, 2)
|
||||
assert.Equal(t, "fake-cluster", res.Applications[0].Name)
|
||||
assert.Equal(t, "in-cluster", res.Applications[1].Name)
|
||||
})
|
||||
|
||||
t.Run("Generate in not allowed namespace", func(t *testing.T) {
|
||||
appSetServer := newTestAppSetServer(t, appSet1)
|
||||
|
||||
appSet1Ns := appSet1.DeepCopy()
|
||||
appSet1Ns.Namespace = "NOT-ALLOWED"
|
||||
|
||||
appsetQuery := applicationset.ApplicationSetGenerateRequest{ApplicationSet: appSet1Ns}
|
||||
|
||||
_, err := appSetServer.Generate(t.Context(), &appsetQuery)
|
||||
assert.EqualError(t, err, "namespace 'NOT-ALLOWED' is not permitted")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1219,7 +1219,7 @@ func (a *ArgoCDServer) newHTTPServer(ctx context.Context, port int, grpcWebHandl
|
||||
|
||||
// Webhook handler for git events (Note: cache timeouts are hardcoded because API server does not write to cache and not really using them)
|
||||
argoDB := db.NewDB(a.Namespace, a.settingsMgr, a.KubeClientset)
|
||||
acdWebhookHandler := webhook.NewHandler(a.Namespace, a.ArgoCDServerOpts.ApplicationNamespaces, a.ArgoCDServerOpts.WebhookParallelism, a.AppClientset, a.settings, a.settingsMgr, a.RepoServerCache, a.Cache, argoDB, a.settingsMgr.GetMaxWebhookPayloadSize())
|
||||
acdWebhookHandler := webhook.NewHandler(a.Namespace, a.ArgoCDServerOpts.ApplicationNamespaces, a.ArgoCDServerOpts.WebhookParallelism, a.AppClientset, a.appLister, a.settings, a.settingsMgr, a.RepoServerCache, a.Cache, argoDB, a.settingsMgr.GetMaxWebhookPayloadSize())
|
||||
|
||||
mux.HandleFunc("/api/webhook", acdWebhookHandler.Handler)
|
||||
|
||||
|
||||
@@ -34,9 +34,9 @@ func (s *secretsRepositoryBackend) CreateRepository(ctx context.Context, reposit
|
||||
},
|
||||
}
|
||||
|
||||
s.repositoryToSecret(repository, repositorySecret)
|
||||
updatedSecret := s.repositoryToSecret(repository, repositorySecret)
|
||||
|
||||
_, err := s.db.createSecret(ctx, repositorySecret)
|
||||
_, err := s.db.createSecret(ctx, updatedSecret)
|
||||
if err != nil {
|
||||
if apierr.IsAlreadyExists(err) {
|
||||
hasLabel, err := s.hasRepoTypeLabel(secName)
|
||||
@@ -143,9 +143,9 @@ func (s *secretsRepositoryBackend) UpdateRepository(ctx context.Context, reposit
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.repositoryToSecret(repository, repositorySecret)
|
||||
updatedSecret := s.repositoryToSecret(repository, repositorySecret)
|
||||
|
||||
_, err = s.db.kubeclientset.CoreV1().Secrets(s.db.ns).Update(ctx, repositorySecret, metav1.UpdateOptions{})
|
||||
_, err = s.db.kubeclientset.CoreV1().Secrets(s.db.ns).Update(ctx, updatedSecret, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -188,9 +188,9 @@ func (s *secretsRepositoryBackend) CreateRepoCreds(ctx context.Context, repoCred
|
||||
},
|
||||
}
|
||||
|
||||
repoCredsToSecret(repoCreds, repoCredsSecret)
|
||||
updatedSecret := repoCredsToSecret(repoCreds, repoCredsSecret)
|
||||
|
||||
_, err := s.db.createSecret(ctx, repoCredsSecret)
|
||||
_, err := s.db.createSecret(ctx, updatedSecret)
|
||||
if err != nil {
|
||||
if apierr.IsAlreadyExists(err) {
|
||||
return nil, status.Errorf(codes.AlreadyExists, "repository credentials %q already exists", repoCreds.URL)
|
||||
@@ -238,9 +238,9 @@ func (s *secretsRepositoryBackend) UpdateRepoCreds(ctx context.Context, repoCred
|
||||
return nil, err
|
||||
}
|
||||
|
||||
repoCredsToSecret(repoCreds, repoCredsSecret)
|
||||
updatedSecret := repoCredsToSecret(repoCreds, repoCredsSecret)
|
||||
|
||||
repoCredsSecret, err = s.db.kubeclientset.CoreV1().Secrets(s.db.ns).Update(ctx, repoCredsSecret, metav1.UpdateOptions{})
|
||||
repoCredsSecret, err = s.db.kubeclientset.CoreV1().Secrets(s.db.ns).Update(ctx, updatedSecret, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -302,60 +302,62 @@ func (s *secretsRepositoryBackend) GetAllHelmRepoCreds(ctx context.Context) ([]*
|
||||
}
|
||||
|
||||
func secretToRepository(secret *corev1.Secret) (*appsv1.Repository, error) {
|
||||
secretCopy := secret.DeepCopy()
|
||||
|
||||
repository := &appsv1.Repository{
|
||||
Name: string(secret.Data["name"]),
|
||||
Repo: string(secret.Data["url"]),
|
||||
Username: string(secret.Data["username"]),
|
||||
Password: string(secret.Data["password"]),
|
||||
SSHPrivateKey: string(secret.Data["sshPrivateKey"]),
|
||||
TLSClientCertData: string(secret.Data["tlsClientCertData"]),
|
||||
TLSClientCertKey: string(secret.Data["tlsClientCertKey"]),
|
||||
Type: string(secret.Data["type"]),
|
||||
GithubAppPrivateKey: string(secret.Data["githubAppPrivateKey"]),
|
||||
GitHubAppEnterpriseBaseURL: string(secret.Data["githubAppEnterpriseBaseUrl"]),
|
||||
Proxy: string(secret.Data["proxy"]),
|
||||
NoProxy: string(secret.Data["noProxy"]),
|
||||
Project: string(secret.Data["project"]),
|
||||
GCPServiceAccountKey: string(secret.Data["gcpServiceAccountKey"]),
|
||||
Name: string(secretCopy.Data["name"]),
|
||||
Repo: string(secretCopy.Data["url"]),
|
||||
Username: string(secretCopy.Data["username"]),
|
||||
Password: string(secretCopy.Data["password"]),
|
||||
SSHPrivateKey: string(secretCopy.Data["sshPrivateKey"]),
|
||||
TLSClientCertData: string(secretCopy.Data["tlsClientCertData"]),
|
||||
TLSClientCertKey: string(secretCopy.Data["tlsClientCertKey"]),
|
||||
Type: string(secretCopy.Data["type"]),
|
||||
GithubAppPrivateKey: string(secretCopy.Data["githubAppPrivateKey"]),
|
||||
GitHubAppEnterpriseBaseURL: string(secretCopy.Data["githubAppEnterpriseBaseUrl"]),
|
||||
Proxy: string(secretCopy.Data["proxy"]),
|
||||
NoProxy: string(secretCopy.Data["noProxy"]),
|
||||
Project: string(secretCopy.Data["project"]),
|
||||
GCPServiceAccountKey: string(secretCopy.Data["gcpServiceAccountKey"]),
|
||||
}
|
||||
|
||||
insecureIgnoreHostKey, err := boolOrFalse(secret, "insecureIgnoreHostKey")
|
||||
insecureIgnoreHostKey, err := boolOrFalse(secretCopy, "insecureIgnoreHostKey")
|
||||
if err != nil {
|
||||
return repository, err
|
||||
}
|
||||
repository.InsecureIgnoreHostKey = insecureIgnoreHostKey
|
||||
|
||||
insecure, err := boolOrFalse(secret, "insecure")
|
||||
insecure, err := boolOrFalse(secretCopy, "insecure")
|
||||
if err != nil {
|
||||
return repository, err
|
||||
}
|
||||
repository.Insecure = insecure
|
||||
|
||||
enableLfs, err := boolOrFalse(secret, "enableLfs")
|
||||
enableLfs, err := boolOrFalse(secretCopy, "enableLfs")
|
||||
if err != nil {
|
||||
return repository, err
|
||||
}
|
||||
repository.EnableLFS = enableLfs
|
||||
|
||||
enableOCI, err := boolOrFalse(secret, "enableOCI")
|
||||
enableOCI, err := boolOrFalse(secretCopy, "enableOCI")
|
||||
if err != nil {
|
||||
return repository, err
|
||||
}
|
||||
repository.EnableOCI = enableOCI
|
||||
|
||||
githubAppID, err := intOrZero(secret, "githubAppID")
|
||||
githubAppID, err := intOrZero(secretCopy, "githubAppID")
|
||||
if err != nil {
|
||||
return repository, err
|
||||
}
|
||||
repository.GithubAppId = githubAppID
|
||||
|
||||
githubAppInstallationID, err := intOrZero(secret, "githubAppInstallationID")
|
||||
githubAppInstallationID, err := intOrZero(secretCopy, "githubAppInstallationID")
|
||||
if err != nil {
|
||||
return repository, err
|
||||
}
|
||||
repository.GithubAppInstallationId = githubAppInstallationID
|
||||
|
||||
forceBasicAuth, err := boolOrFalse(secret, "forceHttpBasicAuth")
|
||||
forceBasicAuth, err := boolOrFalse(secretCopy, "forceHttpBasicAuth")
|
||||
if err != nil {
|
||||
return repository, err
|
||||
}
|
||||
@@ -364,70 +366,76 @@ func secretToRepository(secret *corev1.Secret) (*appsv1.Repository, error) {
|
||||
return repository, nil
|
||||
}
|
||||
|
||||
func (s *secretsRepositoryBackend) repositoryToSecret(repository *appsv1.Repository, secret *corev1.Secret) {
|
||||
if secret.Data == nil {
|
||||
secret.Data = make(map[string][]byte)
|
||||
func (s *secretsRepositoryBackend) repositoryToSecret(repository *appsv1.Repository, secret *corev1.Secret) *corev1.Secret {
|
||||
secretCopy := secret.DeepCopy()
|
||||
|
||||
if secretCopy.Data == nil {
|
||||
secretCopy.Data = make(map[string][]byte)
|
||||
}
|
||||
|
||||
updateSecretString(secret, "name", repository.Name)
|
||||
updateSecretString(secret, "project", repository.Project)
|
||||
updateSecretString(secret, "url", repository.Repo)
|
||||
updateSecretString(secret, "username", repository.Username)
|
||||
updateSecretString(secret, "password", repository.Password)
|
||||
updateSecretString(secret, "sshPrivateKey", repository.SSHPrivateKey)
|
||||
updateSecretBool(secret, "enableOCI", repository.EnableOCI)
|
||||
updateSecretString(secret, "tlsClientCertData", repository.TLSClientCertData)
|
||||
updateSecretString(secret, "tlsClientCertKey", repository.TLSClientCertKey)
|
||||
updateSecretString(secret, "type", repository.Type)
|
||||
updateSecretString(secret, "githubAppPrivateKey", repository.GithubAppPrivateKey)
|
||||
updateSecretInt(secret, "githubAppID", repository.GithubAppId)
|
||||
updateSecretInt(secret, "githubAppInstallationID", repository.GithubAppInstallationId)
|
||||
updateSecretString(secret, "githubAppEnterpriseBaseUrl", repository.GitHubAppEnterpriseBaseURL)
|
||||
updateSecretBool(secret, "insecureIgnoreHostKey", repository.InsecureIgnoreHostKey)
|
||||
updateSecretBool(secret, "insecure", repository.Insecure)
|
||||
updateSecretBool(secret, "enableLfs", repository.EnableLFS)
|
||||
updateSecretString(secret, "proxy", repository.Proxy)
|
||||
updateSecretString(secret, "noProxy", repository.NoProxy)
|
||||
updateSecretString(secret, "gcpServiceAccountKey", repository.GCPServiceAccountKey)
|
||||
updateSecretBool(secret, "forceHttpBasicAuth", repository.ForceHttpBasicAuth)
|
||||
addSecretMetadata(secret, s.getSecretType())
|
||||
updateSecretString(secretCopy, "name", repository.Name)
|
||||
updateSecretString(secretCopy, "project", repository.Project)
|
||||
updateSecretString(secretCopy, "url", repository.Repo)
|
||||
updateSecretString(secretCopy, "username", repository.Username)
|
||||
updateSecretString(secretCopy, "password", repository.Password)
|
||||
updateSecretString(secretCopy, "sshPrivateKey", repository.SSHPrivateKey)
|
||||
updateSecretBool(secretCopy, "enableOCI", repository.EnableOCI)
|
||||
updateSecretString(secretCopy, "tlsClientCertData", repository.TLSClientCertData)
|
||||
updateSecretString(secretCopy, "tlsClientCertKey", repository.TLSClientCertKey)
|
||||
updateSecretString(secretCopy, "type", repository.Type)
|
||||
updateSecretString(secretCopy, "githubAppPrivateKey", repository.GithubAppPrivateKey)
|
||||
updateSecretInt(secretCopy, "githubAppID", repository.GithubAppId)
|
||||
updateSecretInt(secretCopy, "githubAppInstallationID", repository.GithubAppInstallationId)
|
||||
updateSecretString(secretCopy, "githubAppEnterpriseBaseUrl", repository.GitHubAppEnterpriseBaseURL)
|
||||
updateSecretBool(secretCopy, "insecureIgnoreHostKey", repository.InsecureIgnoreHostKey)
|
||||
updateSecretBool(secretCopy, "insecure", repository.Insecure)
|
||||
updateSecretBool(secretCopy, "enableLfs", repository.EnableLFS)
|
||||
updateSecretString(secretCopy, "proxy", repository.Proxy)
|
||||
updateSecretString(secretCopy, "noProxy", repository.NoProxy)
|
||||
updateSecretString(secretCopy, "gcpServiceAccountKey", repository.GCPServiceAccountKey)
|
||||
updateSecretBool(secretCopy, "forceHttpBasicAuth", repository.ForceHttpBasicAuth)
|
||||
addSecretMetadata(secretCopy, s.getSecretType())
|
||||
|
||||
return secretCopy
|
||||
}
|
||||
|
||||
func (s *secretsRepositoryBackend) secretToRepoCred(secret *corev1.Secret) (*appsv1.RepoCreds, error) {
|
||||
secretCopy := secret.DeepCopy()
|
||||
|
||||
repository := &appsv1.RepoCreds{
|
||||
URL: string(secret.Data["url"]),
|
||||
Username: string(secret.Data["username"]),
|
||||
Password: string(secret.Data["password"]),
|
||||
SSHPrivateKey: string(secret.Data["sshPrivateKey"]),
|
||||
TLSClientCertData: string(secret.Data["tlsClientCertData"]),
|
||||
TLSClientCertKey: string(secret.Data["tlsClientCertKey"]),
|
||||
Type: string(secret.Data["type"]),
|
||||
GithubAppPrivateKey: string(secret.Data["githubAppPrivateKey"]),
|
||||
GitHubAppEnterpriseBaseURL: string(secret.Data["githubAppEnterpriseBaseUrl"]),
|
||||
GCPServiceAccountKey: string(secret.Data["gcpServiceAccountKey"]),
|
||||
Proxy: string(secret.Data["proxy"]),
|
||||
NoProxy: string(secret.Data["noProxy"]),
|
||||
URL: string(secretCopy.Data["url"]),
|
||||
Username: string(secretCopy.Data["username"]),
|
||||
Password: string(secretCopy.Data["password"]),
|
||||
SSHPrivateKey: string(secretCopy.Data["sshPrivateKey"]),
|
||||
TLSClientCertData: string(secretCopy.Data["tlsClientCertData"]),
|
||||
TLSClientCertKey: string(secretCopy.Data["tlsClientCertKey"]),
|
||||
Type: string(secretCopy.Data["type"]),
|
||||
GithubAppPrivateKey: string(secretCopy.Data["githubAppPrivateKey"]),
|
||||
GitHubAppEnterpriseBaseURL: string(secretCopy.Data["githubAppEnterpriseBaseUrl"]),
|
||||
GCPServiceAccountKey: string(secretCopy.Data["gcpServiceAccountKey"]),
|
||||
Proxy: string(secretCopy.Data["proxy"]),
|
||||
NoProxy: string(secretCopy.Data["noProxy"]),
|
||||
}
|
||||
|
||||
enableOCI, err := boolOrFalse(secret, "enableOCI")
|
||||
enableOCI, err := boolOrFalse(secretCopy, "enableOCI")
|
||||
if err != nil {
|
||||
return repository, err
|
||||
}
|
||||
repository.EnableOCI = enableOCI
|
||||
|
||||
githubAppID, err := intOrZero(secret, "githubAppID")
|
||||
githubAppID, err := intOrZero(secretCopy, "githubAppID")
|
||||
if err != nil {
|
||||
return repository, err
|
||||
}
|
||||
repository.GithubAppId = githubAppID
|
||||
|
||||
githubAppInstallationID, err := intOrZero(secret, "githubAppInstallationID")
|
||||
githubAppInstallationID, err := intOrZero(secretCopy, "githubAppInstallationID")
|
||||
if err != nil {
|
||||
return repository, err
|
||||
}
|
||||
repository.GithubAppInstallationId = githubAppInstallationID
|
||||
|
||||
forceBasicAuth, err := boolOrFalse(secret, "forceHttpBasicAuth")
|
||||
forceBasicAuth, err := boolOrFalse(secretCopy, "forceHttpBasicAuth")
|
||||
if err != nil {
|
||||
return repository, err
|
||||
}
|
||||
@@ -436,28 +444,32 @@ func (s *secretsRepositoryBackend) secretToRepoCred(secret *corev1.Secret) (*app
|
||||
return repository, nil
|
||||
}
|
||||
|
||||
func repoCredsToSecret(repoCreds *appsv1.RepoCreds, secret *corev1.Secret) {
|
||||
if secret.Data == nil {
|
||||
secret.Data = make(map[string][]byte)
|
||||
func repoCredsToSecret(repoCreds *appsv1.RepoCreds, secret *corev1.Secret) *corev1.Secret {
|
||||
secretCopy := secret.DeepCopy()
|
||||
|
||||
if secretCopy.Data == nil {
|
||||
secretCopy.Data = make(map[string][]byte)
|
||||
}
|
||||
|
||||
updateSecretString(secret, "url", repoCreds.URL)
|
||||
updateSecretString(secret, "username", repoCreds.Username)
|
||||
updateSecretString(secret, "password", repoCreds.Password)
|
||||
updateSecretString(secret, "sshPrivateKey", repoCreds.SSHPrivateKey)
|
||||
updateSecretBool(secret, "enableOCI", repoCreds.EnableOCI)
|
||||
updateSecretString(secret, "tlsClientCertData", repoCreds.TLSClientCertData)
|
||||
updateSecretString(secret, "tlsClientCertKey", repoCreds.TLSClientCertKey)
|
||||
updateSecretString(secret, "type", repoCreds.Type)
|
||||
updateSecretString(secret, "githubAppPrivateKey", repoCreds.GithubAppPrivateKey)
|
||||
updateSecretInt(secret, "githubAppID", repoCreds.GithubAppId)
|
||||
updateSecretInt(secret, "githubAppInstallationID", repoCreds.GithubAppInstallationId)
|
||||
updateSecretString(secret, "githubAppEnterpriseBaseUrl", repoCreds.GitHubAppEnterpriseBaseURL)
|
||||
updateSecretString(secret, "gcpServiceAccountKey", repoCreds.GCPServiceAccountKey)
|
||||
updateSecretString(secret, "proxy", repoCreds.Proxy)
|
||||
updateSecretString(secret, "noProxy", repoCreds.NoProxy)
|
||||
updateSecretBool(secret, "forceHttpBasicAuth", repoCreds.ForceHttpBasicAuth)
|
||||
addSecretMetadata(secret, common.LabelValueSecretTypeRepoCreds)
|
||||
updateSecretString(secretCopy, "url", repoCreds.URL)
|
||||
updateSecretString(secretCopy, "username", repoCreds.Username)
|
||||
updateSecretString(secretCopy, "password", repoCreds.Password)
|
||||
updateSecretString(secretCopy, "sshPrivateKey", repoCreds.SSHPrivateKey)
|
||||
updateSecretBool(secretCopy, "enableOCI", repoCreds.EnableOCI)
|
||||
updateSecretString(secretCopy, "tlsClientCertData", repoCreds.TLSClientCertData)
|
||||
updateSecretString(secretCopy, "tlsClientCertKey", repoCreds.TLSClientCertKey)
|
||||
updateSecretString(secretCopy, "type", repoCreds.Type)
|
||||
updateSecretString(secretCopy, "githubAppPrivateKey", repoCreds.GithubAppPrivateKey)
|
||||
updateSecretInt(secretCopy, "githubAppID", repoCreds.GithubAppId)
|
||||
updateSecretInt(secretCopy, "githubAppInstallationID", repoCreds.GithubAppInstallationId)
|
||||
updateSecretString(secretCopy, "githubAppEnterpriseBaseUrl", repoCreds.GitHubAppEnterpriseBaseURL)
|
||||
updateSecretString(secretCopy, "gcpServiceAccountKey", repoCreds.GCPServiceAccountKey)
|
||||
updateSecretString(secretCopy, "proxy", repoCreds.Proxy)
|
||||
updateSecretString(secretCopy, "noProxy", repoCreds.NoProxy)
|
||||
updateSecretBool(secretCopy, "forceHttpBasicAuth", repoCreds.ForceHttpBasicAuth)
|
||||
addSecretMetadata(secretCopy, common.LabelValueSecretTypeRepoCreds)
|
||||
|
||||
return secretCopy
|
||||
}
|
||||
|
||||
func (s *secretsRepositoryBackend) getRepositorySecret(repoURL, project string, allowFallback bool) (*corev1.Secret, error) {
|
||||
|
||||
@@ -2,7 +2,9 @@ package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -84,9 +86,9 @@ func TestSecretsRepositoryBackend_CreateRepository(t *testing.T) {
|
||||
t.Parallel()
|
||||
secret := &corev1.Secret{}
|
||||
s := secretsRepositoryBackend{}
|
||||
s.repositoryToSecret(repo, secret)
|
||||
delete(secret.Labels, common.LabelKeySecretType)
|
||||
f := setupWithK8sObjects(secret)
|
||||
updatedSecret := s.repositoryToSecret(repo, secret)
|
||||
delete(updatedSecret.Labels, common.LabelKeySecretType)
|
||||
f := setupWithK8sObjects(updatedSecret)
|
||||
f.clientSet.ReactionChain = nil
|
||||
f.clientSet.AddReactor("create", "secrets", func(action k8stesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||
gr := schema.GroupResource{
|
||||
@@ -121,8 +123,8 @@ func TestSecretsRepositoryBackend_CreateRepository(t *testing.T) {
|
||||
},
|
||||
}
|
||||
s := secretsRepositoryBackend{}
|
||||
s.repositoryToSecret(repo, secret)
|
||||
f := setupWithK8sObjects(secret)
|
||||
updatedSecret := s.repositoryToSecret(repo, secret)
|
||||
f := setupWithK8sObjects(updatedSecret)
|
||||
f.clientSet.ReactionChain = nil
|
||||
f.clientSet.WatchReactionChain = nil
|
||||
f.clientSet.AddReactor("create", "secrets", func(action k8stesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||
@@ -133,7 +135,7 @@ func TestSecretsRepositoryBackend_CreateRepository(t *testing.T) {
|
||||
return true, nil, k8serrors.NewAlreadyExists(gr, "already exists")
|
||||
})
|
||||
watcher := watch.NewFakeWithChanSize(1, true)
|
||||
watcher.Add(secret)
|
||||
watcher.Add(updatedSecret)
|
||||
f.clientSet.AddWatchReactor("secrets", func(action k8stesting.Action) (handled bool, ret watch.Interface, err error) {
|
||||
return true, watcher, nil
|
||||
})
|
||||
@@ -944,7 +946,7 @@ func TestRepoCredsToSecret(t *testing.T) {
|
||||
GithubAppInstallationId: 456,
|
||||
GitHubAppEnterpriseBaseURL: "GitHubAppEnterpriseBaseURL",
|
||||
}
|
||||
repoCredsToSecret(creds, s)
|
||||
s = repoCredsToSecret(creds, s)
|
||||
assert.Equal(t, []byte(creds.URL), s.Data["url"])
|
||||
assert.Equal(t, []byte(creds.Username), s.Data["username"])
|
||||
assert.Equal(t, []byte(creds.Password), s.Data["password"])
|
||||
@@ -960,3 +962,169 @@ func TestRepoCredsToSecret(t *testing.T) {
|
||||
assert.Equal(t, map[string]string{common.AnnotationKeyManagedBy: common.AnnotationValueManagedByArgoCD}, s.Annotations)
|
||||
assert.Equal(t, map[string]string{common.LabelKeySecretType: common.LabelValueSecretTypeRepoCreds}, s.Labels)
|
||||
}
|
||||
|
||||
func TestRaceConditionInRepoCredsOperations(t *testing.T) {
|
||||
// Create a single shared secret that will be accessed concurrently
|
||||
sharedSecret := &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: RepoURLToSecretName(repoSecretPrefix, "git@github.com:argoproj/argo-cd.git", ""),
|
||||
Namespace: testNamespace,
|
||||
Labels: map[string]string{
|
||||
common.LabelKeySecretType: common.LabelValueSecretTypeRepoCreds,
|
||||
},
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"url": []byte("git@github.com:argoproj/argo-cd.git"),
|
||||
"username": []byte("test-user"),
|
||||
"password": []byte("test-pass"),
|
||||
},
|
||||
}
|
||||
|
||||
// Create test credentials that we'll use for conversion
|
||||
repoCreds := &appsv1.RepoCreds{
|
||||
URL: "git@github.com:argoproj/argo-cd.git",
|
||||
Username: "test-user",
|
||||
Password: "test-pass",
|
||||
}
|
||||
|
||||
backend := &secretsRepositoryBackend{}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
concurrentOps := 50
|
||||
errChan := make(chan error, concurrentOps*2) // Channel to collect errors
|
||||
|
||||
// Launch goroutines that perform concurrent operations
|
||||
for i := 0; i < concurrentOps; i++ {
|
||||
wg.Add(2)
|
||||
|
||||
// One goroutine converts from RepoCreds to Secret
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
errChan <- fmt.Errorf("panic in repoCredsToSecret: %v", r)
|
||||
}
|
||||
}()
|
||||
_ = repoCredsToSecret(repoCreds, sharedSecret)
|
||||
}()
|
||||
|
||||
// Another goroutine converts from Secret to RepoCreds
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
errChan <- fmt.Errorf("panic in secretToRepoCred: %v", r)
|
||||
}
|
||||
}()
|
||||
creds, err := backend.secretToRepoCred(sharedSecret)
|
||||
if err != nil {
|
||||
errChan <- fmt.Errorf("error in secretToRepoCred: %w", err)
|
||||
return
|
||||
}
|
||||
// Verify data integrity
|
||||
if creds.URL != repoCreds.URL || creds.Username != repoCreds.Username || creds.Password != repoCreds.Password {
|
||||
errChan <- fmt.Errorf("data mismatch in conversion: expected %v, got %v", repoCreds, creds)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
close(errChan)
|
||||
|
||||
// Check for any errors that occurred during concurrent operations
|
||||
for err := range errChan {
|
||||
t.Errorf("concurrent operation error: %v", err)
|
||||
}
|
||||
|
||||
// Verify final state
|
||||
finalCreds, err := backend.secretToRepoCred(sharedSecret)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, repoCreds.URL, finalCreds.URL)
|
||||
assert.Equal(t, repoCreds.Username, finalCreds.Username)
|
||||
assert.Equal(t, repoCreds.Password, finalCreds.Password)
|
||||
}
|
||||
|
||||
func TestRaceConditionInRepositoryOperations(t *testing.T) {
|
||||
// Create a single shared secret that will be accessed concurrently
|
||||
sharedSecret := &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: RepoURLToSecretName(repoSecretPrefix, "git@github.com:argoproj/argo-cd.git", ""),
|
||||
Namespace: testNamespace,
|
||||
Labels: map[string]string{
|
||||
common.LabelKeySecretType: common.LabelValueSecretTypeRepository,
|
||||
},
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"url": []byte("git@github.com:argoproj/argo-cd.git"),
|
||||
"name": []byte("test-repo"),
|
||||
"username": []byte("test-user"),
|
||||
"password": []byte("test-pass"),
|
||||
},
|
||||
}
|
||||
|
||||
// Create test repository that we'll use for conversion
|
||||
repo := &appsv1.Repository{
|
||||
Name: "test-repo",
|
||||
Repo: "git@github.com:argoproj/argo-cd.git",
|
||||
Username: "test-user",
|
||||
Password: "test-pass",
|
||||
}
|
||||
|
||||
backend := &secretsRepositoryBackend{}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
concurrentOps := 50
|
||||
errChan := make(chan error, concurrentOps*2) // Channel to collect errors
|
||||
|
||||
// Launch goroutines that perform concurrent operations
|
||||
for i := 0; i < concurrentOps; i++ {
|
||||
wg.Add(2)
|
||||
|
||||
// One goroutine converts from Repository to Secret
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
errChan <- fmt.Errorf("panic in repositoryToSecret: %v", r)
|
||||
}
|
||||
}()
|
||||
_ = backend.repositoryToSecret(repo, sharedSecret)
|
||||
}()
|
||||
|
||||
// Another goroutine converts from Secret to Repository
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
errChan <- fmt.Errorf("panic in secretToRepository: %v", r)
|
||||
}
|
||||
}()
|
||||
repository, err := secretToRepository(sharedSecret)
|
||||
if err != nil {
|
||||
errChan <- fmt.Errorf("error in secretToRepository: %w", err)
|
||||
return
|
||||
}
|
||||
// Verify data integrity
|
||||
if repository.Name != repo.Name || repository.Repo != repo.Repo ||
|
||||
repository.Username != repo.Username || repository.Password != repo.Password {
|
||||
errChan <- fmt.Errorf("data mismatch in conversion: expected %v, got %v", repo, repository)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
close(errChan)
|
||||
|
||||
// Check for any errors that occurred during concurrent operations
|
||||
for err := range errChan {
|
||||
t.Errorf("concurrent operation error: %v", err)
|
||||
}
|
||||
|
||||
// Verify final state
|
||||
finalRepo, err := secretToRepository(sharedSecret)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, repo.Name, finalRepo.Name)
|
||||
assert.Equal(t, repo.Repo, finalRepo.Repo)
|
||||
assert.Equal(t, repo.Username, finalRepo.Username)
|
||||
assert.Equal(t, repo.Password, finalRepo.Password)
|
||||
}
|
||||
|
||||
11
util/env/env.go
vendored
11
util/env/env.go
vendored
@@ -7,6 +7,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
timeutil "github.com/argoproj/pkg/time"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
@@ -133,8 +135,13 @@ func ParseDurationFromEnv(env string, defaultValue, min, max time.Duration) time
|
||||
}
|
||||
dur, err := time.ParseDuration(str)
|
||||
if err != nil {
|
||||
log.Warnf("Could not parse '%s' as a duration string from environment %s", str, env)
|
||||
return defaultValue
|
||||
// provides backwards compatibility for durations defined in days, see: https://github.com/argoproj/argo-cd/issues/24740
|
||||
durPtr, err2 := timeutil.ParseDuration(str)
|
||||
if err2 != nil {
|
||||
log.Warnf("Could not parse '%s' as a duration from environment %s", str, env)
|
||||
return defaultValue
|
||||
}
|
||||
dur = *durPtr
|
||||
}
|
||||
|
||||
if dur < min {
|
||||
|
||||
84
util/env/env_test.go
vendored
84
util/env/env_test.go
vendored
@@ -142,6 +142,90 @@ func TestParseDurationFromEnv(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseDurationFromEnvEdgeCases(t *testing.T) {
|
||||
envKey := "SOME_ENV_KEY"
|
||||
def := 3 * time.Minute
|
||||
minimum := 1 * time.Second
|
||||
maximum := 2160 * time.Hour // 3 months
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
env string
|
||||
expected time.Duration
|
||||
}{{
|
||||
name: "EnvNotSet",
|
||||
expected: def,
|
||||
}, {
|
||||
name: "Durations defined as days are valid",
|
||||
env: "12d",
|
||||
expected: time.Hour * 24 * 12,
|
||||
}, {
|
||||
name: "Negative durations should fail parsing and use the default value",
|
||||
env: "-1h",
|
||||
expected: def,
|
||||
}, {
|
||||
name: "Negative day durations should fail parsing and use the default value",
|
||||
env: "-12d",
|
||||
expected: def,
|
||||
}, {
|
||||
name: "Scientific notation should fail parsing and use the default value",
|
||||
env: "1e3s",
|
||||
expected: def,
|
||||
}, {
|
||||
name: "Durations with a leading zero are considered valid and parsed as decimal notation",
|
||||
env: "0755s",
|
||||
expected: time.Second * 755,
|
||||
}, {
|
||||
name: "Durations with many leading zeroes are considered valid and parsed as decimal notation",
|
||||
env: "000083m",
|
||||
expected: time.Minute * 83,
|
||||
}, {
|
||||
name: "Decimal Durations should not fail parsing",
|
||||
env: "30.5m",
|
||||
expected: time.Minute*30 + time.Second*30,
|
||||
}, {
|
||||
name: "Decimal Day Durations should fail parsing and use the default value",
|
||||
env: "30.5d",
|
||||
expected: def,
|
||||
}, {
|
||||
name: "Fraction Durations should fail parsing and use the default value",
|
||||
env: "1/2h",
|
||||
expected: def,
|
||||
}, {
|
||||
name: "Durations without a time unit should fail parsing and use the default value",
|
||||
env: "15",
|
||||
expected: def,
|
||||
}, {
|
||||
name: "Durations with a trailing symbol should fail parsing and use the default value",
|
||||
env: "+12d",
|
||||
expected: def,
|
||||
}, {
|
||||
name: "Leading space Duration should fail parsing use the default value",
|
||||
env: " 2h",
|
||||
expected: def,
|
||||
}, {
|
||||
name: "Trailing space Duration should fail parsing use the default value",
|
||||
env: "6m ",
|
||||
expected: def,
|
||||
}, {
|
||||
name: "Empty Duration should fail parsing use the default value",
|
||||
env: "",
|
||||
expected: def,
|
||||
}, {
|
||||
name: "Whitespace Duration should fail parsing and use the default value",
|
||||
env: " ",
|
||||
expected: def,
|
||||
}}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Setenv(envKey, tc.env)
|
||||
val := ParseDurationFromEnv(envKey, def, minimum, maximum)
|
||||
assert.Equal(t, tc.expected, val)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_ParseBoolFromEnv(t *testing.T) {
|
||||
envKey := "SOMEKEY"
|
||||
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
package git
|
||||
|
||||
import (
|
||||
"crypto/fips140"
|
||||
"fmt"
|
||||
|
||||
gitssh "github.com/go-git/go-git/v5/plumbing/transport/ssh"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
// List of all currently supported algorithms for SSH key exchange
|
||||
// SupportedSSHKeyExchangeAlgorithms is a list of all currently supported algorithms for SSH key exchange
|
||||
// Unfortunately, crypto/ssh does not offer public constants or list for
|
||||
// this.
|
||||
var SupportedSSHKeyExchangeAlgorithms = []string{
|
||||
@@ -21,10 +22,15 @@ var SupportedSSHKeyExchangeAlgorithms = []string{
|
||||
"diffie-hellman-group14-sha1",
|
||||
}
|
||||
|
||||
// List of default key exchange algorithms to use. We use those that are
|
||||
// available by default, we can become more opinionated later on (when
|
||||
// we support configuration of algorithms to use).
|
||||
var DefaultSSHKeyExchangeAlgorithms = SupportedSSHKeyExchangeAlgorithms
|
||||
// SupportedFIPSCompliantSSHKeyExchangeAlgorithms is a list of all currently supported algorithms for SSH key exchange
|
||||
// that are FIPS compliant
|
||||
var SupportedFIPSCompliantSSHKeyExchangeAlgorithms = []string{
|
||||
"ecdh-sha2-nistp256",
|
||||
"ecdh-sha2-nistp384",
|
||||
"ecdh-sha2-nistp521",
|
||||
"diffie-hellman-group-exchange-sha256",
|
||||
"diffie-hellman-group14-sha256",
|
||||
}
|
||||
|
||||
// PublicKeysWithOptions is an auth method for go-git's SSH client that
|
||||
// inherits from PublicKeys, but provides the possibility to override
|
||||
@@ -51,9 +57,17 @@ func (a *PublicKeysWithOptions) ClientConfig() (*ssh.ClientConfig, error) {
|
||||
if len(a.KexAlgorithms) > 0 {
|
||||
kexAlgos = a.KexAlgorithms
|
||||
} else {
|
||||
kexAlgos = DefaultSSHKeyExchangeAlgorithms
|
||||
kexAlgos = getDefaultSSHKeyExchangeAlgorithms()
|
||||
}
|
||||
config := ssh.Config{KeyExchanges: kexAlgos}
|
||||
opts := &ssh.ClientConfig{Config: config, User: a.User, Auth: []ssh.AuthMethod{ssh.PublicKeys(a.Signer)}}
|
||||
return a.SetHostKeyCallback(opts)
|
||||
}
|
||||
|
||||
// getDefaultSSHKeyExchangeAlgorithms returns the default key exchange algorithms to be used
|
||||
func getDefaultSSHKeyExchangeAlgorithms() []string {
|
||||
if fips140.Enabled() {
|
||||
return SupportedFIPSCompliantSSHKeyExchangeAlgorithms
|
||||
}
|
||||
return SupportedSSHKeyExchangeAlgorithms
|
||||
}
|
||||
|
||||
20
util/guard/guard.go
Normal file
20
util/guard/guard.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package guard
|
||||
|
||||
import (
|
||||
"runtime/debug"
|
||||
)
|
||||
|
||||
// Minimal logger contract; avoids depending on any specific logging package.
|
||||
type Logger interface{ Errorf(string, ...any) }
|
||||
|
||||
// Run executes fn and recovers a panic, logging a component-specific message.
|
||||
func RecoverAndLog(fn func(), log Logger, msg string) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
if log != nil {
|
||||
log.Errorf("%s: %v %s", msg, r, debug.Stack())
|
||||
}
|
||||
}
|
||||
}()
|
||||
fn()
|
||||
}
|
||||
92
util/guard/guard_test.go
Normal file
92
util/guard/guard_test.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package guard
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type nop struct{}
|
||||
|
||||
func (nop) Errorf(string, ...any) {}
|
||||
|
||||
// recorder is a thread-safe logger that captures formatted messages.
|
||||
type recorder struct {
|
||||
mu sync.Mutex
|
||||
calls int
|
||||
msgs []string
|
||||
}
|
||||
|
||||
func (r *recorder) Errorf(format string, args ...any) {
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
r.calls++
|
||||
r.msgs = append(r.msgs, fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
func TestRun_Recovers(_ *testing.T) {
|
||||
RecoverAndLog(func() { panic("boom") }, nop{}, "msg") // fails if panic escapes
|
||||
}
|
||||
|
||||
func TestRun_AllowsNextCall(t *testing.T) {
|
||||
ran := false
|
||||
RecoverAndLog(func() { panic("boom") }, nop{}, "msg")
|
||||
RecoverAndLog(func() { ran = true }, nop{}, "msg")
|
||||
if !ran {
|
||||
t.Fatal("expected second callback to run")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRun_LogsMessageAndStack(t *testing.T) {
|
||||
r := &recorder{}
|
||||
RecoverAndLog(func() { panic("boom") }, r, "msg")
|
||||
if r.calls != 1 {
|
||||
t.Fatalf("expected 1 log call, got %d", r.calls)
|
||||
}
|
||||
got := strings.Join(r.msgs, "\n")
|
||||
if !strings.Contains(got, "msg") {
|
||||
t.Errorf("expected log to contain message %q; got %q", "msg", got)
|
||||
}
|
||||
if !strings.Contains(got, "boom") {
|
||||
t.Errorf("expected log to contain panic value %q; got %q", "boom", got)
|
||||
}
|
||||
// Heuristic check that a stack trace was included.
|
||||
if !strings.Contains(got, "guard.go") && !strings.Contains(got, "runtime/panic.go") && !strings.Contains(got, "goroutine") {
|
||||
t.Errorf("expected log to contain a stack trace; got %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRun_NilLoggerDoesNotPanic(_ *testing.T) {
|
||||
var l Logger // nil
|
||||
RecoverAndLog(func() { panic("boom") }, l, "ignored")
|
||||
}
|
||||
|
||||
func TestRun_NoPanicDoesNotLog(t *testing.T) {
|
||||
r := &recorder{}
|
||||
ran := false
|
||||
RecoverAndLog(func() { ran = true }, r, "msg")
|
||||
if !ran {
|
||||
t.Fatal("expected fn to run")
|
||||
}
|
||||
if r.calls != 0 {
|
||||
t.Fatalf("expected 0 log calls, got %d", r.calls)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRun_ConcurrentPanicsLogged(t *testing.T) {
|
||||
r := &recorder{}
|
||||
const n = 10
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(n)
|
||||
for i := 0; i < n; i++ {
|
||||
go func(i int) {
|
||||
defer wg.Done()
|
||||
RecoverAndLog(func() { panic(fmt.Sprintf("boom-%d", i)) }, r, "msg")
|
||||
}(i)
|
||||
}
|
||||
wg.Wait()
|
||||
if r.calls != n {
|
||||
t.Fatalf("expected %d log calls, got %d", n, r.calls)
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,8 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
alpha1 "github.com/argoproj/argo-cd/v2/pkg/client/listers/application/v1alpha1"
|
||||
|
||||
"github.com/Masterminds/semver/v3"
|
||||
"github.com/go-playground/webhooks/v6/azuredevops"
|
||||
"github.com/go-playground/webhooks/v6/bitbucket"
|
||||
@@ -20,7 +22,7 @@ import (
|
||||
"github.com/go-playground/webhooks/v6/gogs"
|
||||
gogsclient "github.com/gogits/go-gogs-client"
|
||||
log "github.com/sirupsen/logrus"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
|
||||
"github.com/argoproj/argo-cd/v2/common"
|
||||
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
|
||||
@@ -31,6 +33,7 @@ import (
|
||||
"github.com/argoproj/argo-cd/v2/util/argo"
|
||||
"github.com/argoproj/argo-cd/v2/util/db"
|
||||
"github.com/argoproj/argo-cd/v2/util/glob"
|
||||
"github.com/argoproj/argo-cd/v2/util/guard"
|
||||
"github.com/argoproj/argo-cd/v2/util/settings"
|
||||
)
|
||||
|
||||
@@ -46,6 +49,8 @@ const usernameRegex = `[a-zA-Z0-9_\.][a-zA-Z0-9_\.-]{0,30}[a-zA-Z0-9_\.\$-]?`
|
||||
|
||||
const payloadQueueSize = 50000
|
||||
|
||||
const panicMsgServer = "panic while processing api-server webhook event"
|
||||
|
||||
var _ settingsSource = &settings.SettingsManager{}
|
||||
|
||||
type ArgoCDWebhookHandler struct {
|
||||
@@ -56,6 +61,7 @@ type ArgoCDWebhookHandler struct {
|
||||
ns string
|
||||
appNs []string
|
||||
appClientset appclientset.Interface
|
||||
appsLister alpha1.ApplicationLister
|
||||
github *github.Webhook
|
||||
gitlab *gitlab.Webhook
|
||||
bitbucket *bitbucket.Webhook
|
||||
@@ -67,7 +73,7 @@ type ArgoCDWebhookHandler struct {
|
||||
maxWebhookPayloadSizeB int64
|
||||
}
|
||||
|
||||
func NewHandler(namespace string, applicationNamespaces []string, webhookParallelism int, appClientset appclientset.Interface, set *settings.ArgoCDSettings, settingsSrc settingsSource, repoCache *cache.Cache, serverCache *servercache.Cache, argoDB db.ArgoDB, maxWebhookPayloadSizeB int64) *ArgoCDWebhookHandler {
|
||||
func NewHandler(namespace string, applicationNamespaces []string, webhookParallelism int, appClientset appclientset.Interface, appsLister alpha1.ApplicationLister, set *settings.ArgoCDSettings, settingsSrc settingsSource, repoCache *cache.Cache, serverCache *servercache.Cache, argoDB db.ArgoDB, maxWebhookPayloadSizeB int64) *ArgoCDWebhookHandler {
|
||||
githubWebhook, err := github.New(github.Options.Secret(set.WebhookGitHubSecret))
|
||||
if err != nil {
|
||||
log.Warnf("Unable to init the GitHub webhook")
|
||||
@@ -109,6 +115,7 @@ func NewHandler(namespace string, applicationNamespaces []string, webhookParalle
|
||||
db: argoDB,
|
||||
queue: make(chan interface{}, payloadQueueSize),
|
||||
maxWebhookPayloadSizeB: maxWebhookPayloadSizeB,
|
||||
appsLister: appsLister,
|
||||
}
|
||||
|
||||
acdWebhook.startWorkerPool(webhookParallelism)
|
||||
@@ -117,6 +124,7 @@ func NewHandler(namespace string, applicationNamespaces []string, webhookParalle
|
||||
}
|
||||
|
||||
func (a *ArgoCDWebhookHandler) startWorkerPool(webhookParallelism int) {
|
||||
compLog := log.WithField("component", "api-server-webhook")
|
||||
for i := 0; i < webhookParallelism; i++ {
|
||||
a.Add(1)
|
||||
go func() {
|
||||
@@ -126,7 +134,7 @@ func (a *ArgoCDWebhookHandler) startWorkerPool(webhookParallelism int) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
a.HandleEvent(payload)
|
||||
guard.RecoverAndLog(func() { a.HandleEvent(payload) }, compLog, panicMsgServer)
|
||||
}
|
||||
}()
|
||||
}
|
||||
@@ -144,10 +152,12 @@ func affectedRevisionInfo(payloadIf interface{}) (webURLs []string, revision str
|
||||
case azuredevops.GitPushEvent:
|
||||
// See: https://learn.microsoft.com/en-us/azure/devops/service-hooks/events?view=azure-devops#git.push
|
||||
webURLs = append(webURLs, payload.Resource.Repository.RemoteURL)
|
||||
revision = ParseRevision(payload.Resource.RefUpdates[0].Name)
|
||||
change.shaAfter = ParseRevision(payload.Resource.RefUpdates[0].NewObjectID)
|
||||
change.shaBefore = ParseRevision(payload.Resource.RefUpdates[0].OldObjectID)
|
||||
touchedHead = payload.Resource.RefUpdates[0].Name == payload.Resource.Repository.DefaultBranch
|
||||
if len(payload.Resource.RefUpdates) > 0 {
|
||||
revision = ParseRevision(payload.Resource.RefUpdates[0].Name)
|
||||
change.shaAfter = ParseRevision(payload.Resource.RefUpdates[0].NewObjectID)
|
||||
change.shaBefore = ParseRevision(payload.Resource.RefUpdates[0].OldObjectID)
|
||||
touchedHead = payload.Resource.RefUpdates[0].Name == payload.Resource.Repository.DefaultBranch
|
||||
}
|
||||
// unfortunately, Azure DevOps doesn't provide a list of changed files
|
||||
case github.PushPayload:
|
||||
// See: https://developer.github.com/v3/activity/events/types/#pushevent
|
||||
@@ -206,13 +216,15 @@ func affectedRevisionInfo(payloadIf interface{}) (webURLs []string, revision str
|
||||
|
||||
// Webhook module does not parse the inner links
|
||||
if payload.Repository.Links != nil {
|
||||
for _, l := range payload.Repository.Links["clone"].([]interface{}) {
|
||||
link := l.(map[string]interface{})
|
||||
if link["name"] == "http" {
|
||||
webURLs = append(webURLs, link["href"].(string))
|
||||
}
|
||||
if link["name"] == "ssh" {
|
||||
webURLs = append(webURLs, link["href"].(string))
|
||||
clone, ok := payload.Repository.Links["clone"].([]any)
|
||||
if ok {
|
||||
for _, l := range clone {
|
||||
link := l.(map[string]any)
|
||||
if link["name"] == "http" || link["name"] == "ssh" {
|
||||
if href, ok := link["href"].(string); ok {
|
||||
webURLs = append(webURLs, href)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -231,11 +243,13 @@ func affectedRevisionInfo(payloadIf interface{}) (webURLs []string, revision str
|
||||
// so we cannot update changedFiles for this type of payload
|
||||
|
||||
case gogsclient.PushPayload:
|
||||
webURLs = append(webURLs, payload.Repo.HTMLURL)
|
||||
revision = ParseRevision(payload.Ref)
|
||||
change.shaAfter = ParseRevision(payload.After)
|
||||
change.shaBefore = ParseRevision(payload.Before)
|
||||
touchedHead = bool(payload.Repo.DefaultBranch == revision)
|
||||
if payload.Repo != nil {
|
||||
webURLs = append(webURLs, payload.Repo.HTMLURL)
|
||||
touchedHead = payload.Repo.DefaultBranch == revision
|
||||
}
|
||||
for _, commit := range payload.Commits {
|
||||
changedFiles = append(changedFiles, commit.Added...)
|
||||
changedFiles = append(changedFiles, commit.Modified...)
|
||||
@@ -268,8 +282,8 @@ func (a *ArgoCDWebhookHandler) HandleEvent(payload interface{}) {
|
||||
nsFilter = ""
|
||||
}
|
||||
|
||||
appIf := a.appClientset.ArgoprojV1alpha1().Applications(nsFilter)
|
||||
apps, err := appIf.List(context.Background(), metav1.ListOptions{})
|
||||
appIf := a.appsLister.Applications(nsFilter)
|
||||
apps, err := appIf.List(labels.Everything())
|
||||
if err != nil {
|
||||
log.Warnf("Failed to list applications: %v", err)
|
||||
return
|
||||
@@ -294,9 +308,9 @@ func (a *ArgoCDWebhookHandler) HandleEvent(payload interface{}) {
|
||||
// Skip any application that is neither in the control plane's namespace
|
||||
// nor in the list of enabled namespaces.
|
||||
var filteredApps []v1alpha1.Application
|
||||
for _, app := range apps.Items {
|
||||
for _, app := range apps {
|
||||
if app.Namespace == a.ns || glob.MatchStringInList(a.appNs, app.Namespace, glob.REGEXP) {
|
||||
filteredApps = append(filteredApps, app)
|
||||
filteredApps = append(filteredApps, *app)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package webhook
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -11,6 +12,9 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-playground/webhooks/v6/azuredevops"
|
||||
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
|
||||
"github.com/go-playground/webhooks/v6/bitbucket"
|
||||
@@ -21,6 +25,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
kubetesting "k8s.io/client-go/testing"
|
||||
|
||||
argov1 "github.com/argoproj/argo-cd/v2/pkg/client/listers/application/v1alpha1"
|
||||
"github.com/argoproj/argo-cd/v2/util/cache/appstate"
|
||||
|
||||
"github.com/argoproj/argo-cd/v2/util/db/mocks"
|
||||
@@ -64,6 +69,31 @@ func NewMockHandler(reactor *reactorDef, applicationNamespaces []string, objects
|
||||
return NewMockHandlerWithPayloadLimit(reactor, applicationNamespaces, defaultMaxPayloadSize, objects...)
|
||||
}
|
||||
|
||||
type fakeAppsLister struct {
|
||||
argov1.ApplicationLister
|
||||
argov1.ApplicationNamespaceLister
|
||||
namespace string
|
||||
clientset *appclientset.Clientset
|
||||
}
|
||||
|
||||
func (f *fakeAppsLister) Applications(namespace string) argov1.ApplicationNamespaceLister {
|
||||
return &fakeAppsLister{namespace: namespace, clientset: f.clientset}
|
||||
}
|
||||
|
||||
func (f *fakeAppsLister) List(selector labels.Selector) ([]*v1alpha1.Application, error) {
|
||||
res, err := f.clientset.ArgoprojV1alpha1().Applications(f.namespace).List(context.Background(), metav1.ListOptions{
|
||||
LabelSelector: selector.String(),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var apps []*v1alpha1.Application
|
||||
for i := range res.Items {
|
||||
apps = append(apps, &res.Items[i])
|
||||
}
|
||||
return apps, nil
|
||||
}
|
||||
|
||||
func NewMockHandlerWithPayloadLimit(reactor *reactorDef, applicationNamespaces []string, maxPayloadSize int64, objects ...runtime.Object) *ArgoCDWebhookHandler {
|
||||
appClientset := appclientset.NewSimpleClientset(objects...)
|
||||
if reactor != nil {
|
||||
@@ -76,7 +106,7 @@ func NewMockHandlerWithPayloadLimit(reactor *reactorDef, applicationNamespaces [
|
||||
}
|
||||
cacheClient := cacheutil.NewCache(cacheutil.NewInMemoryCache(1 * time.Hour))
|
||||
|
||||
return NewHandler("argocd", applicationNamespaces, 10, appClientset, &settings.ArgoCDSettings{}, &fakeSettingsSrc{}, cache.NewCache(
|
||||
return NewHandler("argocd", applicationNamespaces, 10, appClientset, &fakeAppsLister{clientset: appClientset}, &settings.ArgoCDSettings{}, &fakeSettingsSrc{}, cache.NewCache(
|
||||
cacheClient,
|
||||
1*time.Minute,
|
||||
1*time.Minute,
|
||||
@@ -664,6 +694,26 @@ func Test_affectedRevisionInfo_appRevisionHasChanged(t *testing.T) {
|
||||
{true, "refs/tags/no-slashes", bitbucketPushPayload("no-slashes"), "bitbucket push branch or tag name without slashes, targetRevision tag prefixed"},
|
||||
{true, "refs/tags/no-slashes", bitbucketRefChangedPayload("no-slashes"), "bitbucket ref changed branch or tag name without slashes, targetRevision tag prefixed"},
|
||||
{true, "refs/tags/no-slashes", gogsPushPayload("no-slashes"), "gogs push branch or tag name without slashes, targetRevision tag prefixed"},
|
||||
|
||||
// Tests fix for https://github.com/argoproj/argo-cd/security/advisories/GHSA-wp4p-9pxh-cgx2
|
||||
{true, "test", gogsclient.PushPayload{Ref: "test", Repo: nil}, "gogs push branch with nil repo in payload"},
|
||||
|
||||
// Testing fix for https://github.com/argoproj/argo-cd/security/advisories/GHSA-gpx4-37g2-c8pv
|
||||
{false, "test", azuredevops.GitPushEvent{Resource: azuredevops.Resource{RefUpdates: []azuredevops.RefUpdate{}}}, "Azure DevOps malformed push event with no ref updates"},
|
||||
|
||||
{true, "some-ref", bitbucketserver.RepositoryReferenceChangedPayload{
|
||||
Changes: []bitbucketserver.RepositoryChange{
|
||||
{Reference: bitbucketserver.RepositoryReference{ID: "refs/heads/some-ref"}},
|
||||
},
|
||||
Repository: bitbucketserver.Repository{Links: map[string]any{"clone": "boom"}}, // The string "boom" here is what previously caused a panic.
|
||||
}, "bitbucket push branch or tag name, malformed link"}, // https://github.com/argoproj/argo-cd/security/advisories/GHSA-f9gq-prrc-hrhc
|
||||
|
||||
{true, "some-ref", bitbucketserver.RepositoryReferenceChangedPayload{
|
||||
Changes: []bitbucketserver.RepositoryChange{
|
||||
{Reference: bitbucketserver.RepositoryReference{ID: "refs/heads/some-ref"}},
|
||||
},
|
||||
Repository: bitbucketserver.Repository{Links: map[string]any{"clone": []any{map[string]any{"name": "http", "href": []string{}}}}}, // The href as an empty array is what previously caused a panic.
|
||||
}, "bitbucket push branch or tag name, malformed href"},
|
||||
}
|
||||
for _, testCase := range tests {
|
||||
testCopy := testCase
|
||||
|
||||
Reference in New Issue
Block a user