Compare commits

...

29 Commits

Author SHA1 Message Date
github-actions[bot]
083ef929a5 Bump version to 3.0.13 on release-3.0 branch (#24261)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: crenshaw-dev <350466+crenshaw-dev@users.noreply.github.com>
2025-08-25 11:30:39 -04:00
Codey Jenkins
d6e0e5c852 chore: cherry pick #24235 to release-3.0 (#24237)
Signed-off-by: Codey Jenkins <FourFifthsCode@users.noreply.github.com>
Co-authored-by: Matthew Bennett <mtbennett@godaddy.com>
Co-authored-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2025-08-22 16:55:13 -04:00
rumstead
46e7c008ce fix(server): Send Azure DevOps token via git extra headers (#23478) (#23631) (#24222)
Signed-off-by: Mike Bordon <mikebordon@gmail.com>
Signed-off-by: rumstead <37445536+rumstead@users.noreply.github.com>
Co-authored-by: mikebordon <31316193+mikebordon@users.noreply.github.com>
2025-08-22 09:42:21 -04:00
Anand Francis Joseph
274ab28f8f fix(util): Fix default key exchange algorthims used for SSH connection to be FIPS compliant (#24086) (cherry-pick 3.0) (#24165)
Signed-off-by: anandf <anjoseph@redhat.com>
2025-08-15 11:30:55 +02:00
Alexandre Gaudreault
b1df89bfce fix(lua): allow actions to add items to array (#24136)
Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2025-08-13 17:20:55 -04:00
Blake Pettersson
d76cedea57 fix: kustomize edit add component check (#24100) (cherry-pick 3.0) (#24103)
Signed-off-by: Blake Pettersson <blake.pettersson@gmail.com>
2025-08-11 12:02:56 +02:00
Ville Vesilehto
3fb825c36c chore: update Go to 1.24.6 (release-3.0) (#24092)
Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>
2025-08-11 10:38:43 +02:00
gcp-cherry-pick-bot[bot]
7822fbd43a docs: 3.0 migration - added remediation for explicitly syncing apps that use ApplyOutOfSyncOnly=true (cherry-pick #23918) (#23957)
Signed-off-by: reggie-k <regina.voloshin@codefresh.io>
Co-authored-by: Regina Voloshin <regina.voloshin@codefresh.io>
2025-08-03 23:22:23 -04:00
gcp-cherry-pick-bot[bot]
d11bf1ac88 fix: helm GetTags cache writing (cherry-pick #23865) (#23953)
Signed-off-by: Matthew Clarke <mclarke@spotify.com>
Co-authored-by: Matthew Clarke <matthewclarke47@gmail.com>
Co-authored-by: Linghao Su <linghao.su@daocloud.io>
2025-07-28 23:42:32 +02:00
github-actions[bot]
ed1e2397ef Bump version to 3.0.12 on release-3.0 branch (#23936)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: crenshaw-dev <350466+crenshaw-dev@users.noreply.github.com>
2025-07-25 10:35:18 -07:00
pbhatnagar-oss
5e769f900f fix(metrics): Cherrypick grpc stats fix release 3.0 (#23889)
Signed-off-by: pbhatnagar-oss <pbhatifiwork@gmail.com>
2025-07-23 07:51:52 -07:00
rumstead
fc27c4d099 fix(appset): When Appset is deleted, the controller should reconcile applicationset #23723 (cherry-pick ##23823) (#23834)
Signed-off-by: rumstead <37445536+rumstead@users.noreply.github.com>
Co-authored-by: sangeer <86688098+sangdammad@users.noreply.github.com>
2025-07-17 12:18:29 -04:00
github-actions[bot]
240a1833c0 Bump version to 3.0.11 on release-3.0 branch (#23745)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: crenshaw-dev <350466+crenshaw-dev@users.noreply.github.com>
2025-07-10 10:26:31 -04:00
github-actions[bot]
b19defcd40 Bump version to 3.0.10 on release-3.0 branch (#23744)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: crenshaw-dev <350466+crenshaw-dev@users.noreply.github.com>
2025-07-10 10:18:47 -04:00
gcp-cherry-pick-bot[bot]
bbf0582eb0 fix(health): CRD health check message (#23690) (cherry-pick #23691) (#23739)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-07-10 10:18:28 -04:00
gcp-cherry-pick-bot[bot]
ba3d90972c docs(images): add a note about missing images for 3.0 releases (cherry-pick #23741) (#23742)
Signed-off-by: rumstead <37445536+rumstead@users.noreply.github.com>
Co-authored-by: rumstead <37445536+rumstead@users.noreply.github.com>
2025-07-10 10:17:27 -04:00
gcp-cherry-pick-bot[bot]
0fe62852c7 fix(darwin): remove the need for cgo when building a darwin binary on linux (cherry-pick #23507) (#23735)
Signed-off-by: rumstead <37445536+rumstead@users.noreply.github.com>
Co-authored-by: rumstead <37445536+rumstead@users.noreply.github.com>
2025-07-10 09:58:01 -04:00
gcp-cherry-pick-bot[bot]
108dab6e16 docs(images): add a note about missing images for 3.0 releases (#23612) (cherry-pick #23712) (#23714)
Signed-off-by: rumstead <37445536+rumstead@users.noreply.github.com>
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: rumstead <37445536+rumstead@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-07-09 13:56:56 -04:00
Michael Crenshaw
873289c409 fix(server): infer resource status health for apps-in-any-ns (#22944) (#23706)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-07-09 11:20:22 -04:00
gcp-cherry-pick-bot[bot]
3ab0e9c1f5 fix: improves the ui message when an operation is terminated due to controller sync timeout (cherry-pick #23657) (#23671)
Signed-off-by: Patroklos Papapetrou <ppapapetrou76@gmail.com>
Co-authored-by: Papapetrou Patroklos <1743100+ppapapetrou76@users.noreply.github.com>
2025-07-07 10:49:04 +03:00
Alexandre Gaudreault
f7d0ebda31 fix(sync): auto-sync loop when FailOnSharedResource (#23357) (#23639)
Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
2025-07-02 15:00:22 -04:00
gcp-cherry-pick-bot[bot]
ea7e2b7905 fix(controller): get commit server url from env (cherry-pick #23536) (#23542)
Signed-off-by: Alexej Disterhoft <alexej.disterhoft@redcare-pharmacy.com>
Co-authored-by: Alexej Disterhoft <alexej@disterhoft.de>
2025-06-24 14:40:49 -04:00
gcp-cherry-pick-bot[bot]
06fd5060a0 fix: kustomize components + monorepos (cherry-pick #23486) (#23539)
Signed-off-by: Blake Pettersson <blake.pettersson@gmail.com>
Co-authored-by: Blake Pettersson <blake.pettersson@gmail.com>
2025-06-24 18:07:24 +02:00
gcp-cherry-pick-bot[bot]
f264eaa40f fix(controller): impersonation with destination name (#23309) (cherry-pick #23504) (#23517)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
Co-authored-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
2025-06-23 09:52:45 -04:00
gcp-cherry-pick-bot[bot]
be3e9403e9 fix(appset): Add token to enterprise client (#23240) (cherry-pick #23455) (#23476)
Signed-off-by: Collin Walker <cwalker@ancestry.com>
Co-authored-by: Collin Walker <10523817+lets-call-n-walk@users.noreply.github.com>
Co-authored-by: Collin Walker <cwalker@ancestry.com>
2025-06-18 19:50:46 +05:30
github-actions[bot]
a1faf0265f Bump version to 3.0.9 on release-3.0 branch (#23462)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: rumstead <37445536+rumstead@users.noreply.github.com>
2025-06-17 16:45:12 -04:00
gcp-cherry-pick-bot[bot]
8868f91bbd fix(goreleaser): add darwin with CGO enabled and remove static to gorelease (cherry-pick #23457) (#23459)
Signed-off-by: rumstead <37445536+rumstead@users.noreply.github.com>
Co-authored-by: rumstead <37445536+rumstead@users.noreply.github.com>
2025-06-17 16:41:31 -04:00
github-actions[bot]
902826f8c7 Bump version to 3.0.8 on release-3.0 branch (#23451)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: rumstead <37445536+rumstead@users.noreply.github.com>
2025-06-17 11:53:16 -04:00
rumstead
95d8b48624 fix(goreleaser): add darwin with CGO enabled to gorelease (#23438)
Signed-off-by: rumstead <37445536+rumstead@users.noreply.github.com>
2025-06-16 23:01:14 -04:00
66 changed files with 1060 additions and 308 deletions

View File

@@ -14,7 +14,7 @@ on:
env:
# Golang version to use across CI steps
# renovate: datasource=golang-version packageName=golang
GOLANG_VERSION: '1.24.4'
GOLANG_VERSION: '1.24.6'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}

View File

@@ -53,7 +53,7 @@ jobs:
with:
# Note: cannot use env variables to set go-version (https://docs.github.com/en/actions/using-workflows/reusing-workflows#limitations)
# renovate: datasource=golang-version packageName=golang
go-version: 1.24.4
go-version: 1.24.6
platforms: ${{ needs.set-vars.outputs.platforms }}
push: false
@@ -70,7 +70,7 @@ jobs:
ghcr_image_name: ghcr.io/argoproj/argo-cd/argocd:${{ needs.set-vars.outputs.image-tag }}
# Note: cannot use env variables to set go-version (https://docs.github.com/en/actions/using-workflows/reusing-workflows#limitations)
# renovate: datasource=golang-version packageName=golang
go-version: 1.24.4
go-version: 1.24.6
platforms: ${{ needs.set-vars.outputs.platforms }}
push: true
secrets:

View File

@@ -11,7 +11,7 @@ permissions: {}
env:
# renovate: datasource=golang-version packageName=golang
GOLANG_VERSION: '1.24.4' # Note: go-version must also be set in job argocd-image.with.go-version
GOLANG_VERSION: '1.24.6' # Note: go-version must also be set in job argocd-image.with.go-version
jobs:
argocd-image:
@@ -25,7 +25,7 @@ jobs:
quay_image_name: quay.io/argoproj/argocd:${{ github.ref_name }}
# Note: cannot use env variables to set go-version (https://docs.github.com/en/actions/using-workflows/reusing-workflows#limitations)
# renovate: datasource=golang-version packageName=golang
go-version: 1.24.4
go-version: 1.24.6
platforms: linux/amd64,linux/arm64,linux/s390x,linux/ppc64le
push: true
secrets:

View File

@@ -24,8 +24,8 @@ builds:
- -extldflags="-static"
goos:
- linux
- darwin
- windows
- darwin
goarch:
- amd64
- arm64

View File

@@ -4,7 +4,7 @@ ARG BASE_IMAGE=docker.io/library/ubuntu:24.04@sha256:80dd3c3b9c6cecb9f1667e9290b
# Initial stage which pulls prepares build dependencies and CLI tooling we need for our final image
# Also used as the image in CI jobs so needs all dependencies
####################################################################################################
FROM docker.io/library/golang:1.24.4@sha256:db5d0afbfb4ab648af2393b92e87eaae9ad5e01132803d80caef91b5752d289c AS builder
FROM docker.io/library/golang:1.24.6@sha256:2c89c41fb9efc3807029b59af69645867cfe978d2b877d475be0d72f6c6ce6f6 AS builder
WORKDIR /tmp
@@ -103,7 +103,7 @@ RUN HOST_ARCH=$TARGETARCH NODE_ENV='production' NODE_ONLINE_ENV='online' NODE_OP
####################################################################################################
# Argo CD Build stage which performs the actual build of Argo CD binaries
####################################################################################################
FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.24.4@sha256:db5d0afbfb4ab648af2393b92e87eaae9ad5e01132803d80caef91b5752d289c AS argocd-build
FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.24.6@sha256:2c89c41fb9efc3807029b59af69645867cfe978d2b877d475be0d72f6c6ce6f6 AS argocd-build
WORKDIR /go/src/github.com/argoproj/argo-cd

View File

@@ -1 +1 @@
3.0.7
3.0.13

View File

@@ -1603,14 +1603,15 @@ func shouldRequeueForApplicationSet(appSetOld, appSetNew *argov1alpha1.Applicati
}
}
// only compare the applicationset spec, annotations, labels and finalizers, specifically avoiding
// only compare the applicationset spec, annotations, labels and finalizers, deletionTimestamp, specifically avoiding
// the status field. status is owned by the applicationset controller,
// and we do not need to requeue when it does bookkeeping
// NB: the ApplicationDestination comes from the ApplicationSpec being embedded
// in the ApplicationSetTemplate from the generators
if !cmp.Equal(appSetOld.Spec, appSetNew.Spec, cmpopts.EquateEmpty(), cmpopts.EquateComparable(argov1alpha1.ApplicationDestination{})) ||
!cmp.Equal(appSetOld.ObjectMeta.GetLabels(), appSetNew.ObjectMeta.GetLabels(), cmpopts.EquateEmpty()) ||
!cmp.Equal(appSetOld.ObjectMeta.GetFinalizers(), appSetNew.ObjectMeta.GetFinalizers(), cmpopts.EquateEmpty()) {
!cmp.Equal(appSetOld.GetLabels(), appSetNew.GetLabels(), cmpopts.EquateEmpty()) ||
!cmp.Equal(appSetOld.GetFinalizers(), appSetNew.GetFinalizers(), cmpopts.EquateEmpty()) ||
!cmp.Equal(appSetOld.DeletionTimestamp, appSetNew.DeletionTimestamp, cmpopts.EquateEmpty()) {
return true
}

View File

@@ -6821,6 +6821,28 @@ func TestApplicationSetOwnsHandlerUpdate(t *testing.T) {
enableProgressiveSyncs: false,
want: false,
},
{
name: "deletionTimestamp present when progressive sync enabled",
appSetOld: buildAppSet(map[string]string{}),
appSetNew: &v1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
DeletionTimestamp: &metav1.Time{Time: time.Now()},
},
},
enableProgressiveSyncs: true,
want: true,
},
{
name: "deletionTimestamp present when progressive sync disabled",
appSetOld: buildAppSet(map[string]string{}),
appSetNew: &v1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
DeletionTimestamp: &metav1.Time{Time: time.Now()},
},
},
enableProgressiveSyncs: false,
want: true,
},
}
for _, tt := range tests {
@@ -6969,6 +6991,36 @@ func TestShouldRequeueForApplicationSet(t *testing.T) {
},
want: true,
},
{
name: "ApplicationSetWithDeletionTimestamp",
args: args{
appSetOld: &v1alpha1.ApplicationSet{
Status: v1alpha1.ApplicationSetStatus{
ApplicationStatus: []v1alpha1.ApplicationSetApplicationStatus{
{
Application: "app1",
Status: "Healthy",
},
},
},
},
appSetNew: &v1alpha1.ApplicationSet{
ObjectMeta: metav1.ObjectMeta{
DeletionTimestamp: &metav1.Time{Time: time.Now()},
},
Status: v1alpha1.ApplicationSetStatus{
ApplicationStatus: []v1alpha1.ApplicationSetApplicationStatus{
{
Application: "app1",
Status: "Waiting",
},
},
},
},
enableProgressiveSyncs: false,
},
want: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {

View File

@@ -33,7 +33,11 @@ func NewGithubService(token, url, owner, repo string, labels []string) (PullRequ
}
} else {
var err error
client, err = github.NewClient(httpClient).WithEnterpriseURLs(url, url)
if token == "" {
client, err = github.NewClient(httpClient).WithEnterpriseURLs(url, url)
} else {
client, err = github.NewClient(httpClient).WithAuthToken(token).WithEnterpriseURLs(url, url)
}
if err != nil {
return nil, err
}

View File

@@ -32,7 +32,11 @@ func NewGithubProvider(organization string, token string, url string, allBranche
}
} else {
var err error
client, err = github.NewClient(httpClient).WithEnterpriseURLs(url, url)
if token == "" {
client, err = github.NewClient(httpClient).WithEnterpriseURLs(url, url)
} else {
client, err = github.NewClient(httpClient).WithAuthToken(token).WithEnterpriseURLs(url, url)
}
if err != nil {
return nil, err
}

View File

@@ -1,3 +1,5 @@
//go:build !darwin || (cgo && darwin)
package commands
import (

View File

@@ -0,0 +1,25 @@
//go:build darwin && !cgo
// Package commands
// This file is used when the GOOS is darwin and CGO is not enabled.
// It provides a no-op implementation of newAzureCommand to allow goreleaser to build
// a darwin binary on a linux machine.
package commands
import (
"log"
"github.com/spf13/cobra"
"github.com/argoproj/argo-cd/v3/util/workloadidentity"
)
func newAzureCommand() *cobra.Command {
command := &cobra.Command{
Use: "azure",
Run: func(c *cobra.Command, _ []string) {
log.Fatalf(workloadidentity.CGOError)
},
}
return command
}

View File

@@ -1481,7 +1481,7 @@ func (ctrl *ApplicationController) processRequestedAppOperation(app *appv1.Appli
} else {
state.Phase = synccommon.OperationRunning
state.RetryCount++
state.Message = fmt.Sprintf("%s. Retrying attempt #%d at %s.", state.Message, state.RetryCount, retryAt.Format(time.Kitchen))
state.Message = fmt.Sprintf("%s due to application controller sync timeout. Retrying attempt #%d at %s.", state.Message, state.RetryCount, retryAt.Format(time.Kitchen))
}
} else if state.RetryCount > 0 {
state.Message = fmt.Sprintf("%s (retried %d times).", state.Message, state.RetryCount)

View File

@@ -2051,7 +2051,7 @@ func TestProcessRequestedAppOperation_FailedHasRetries(t *testing.T) {
phase, _, _ := unstructured.NestedString(receivedPatch, "status", "operationState", "phase")
assert.Equal(t, string(synccommon.OperationRunning), phase)
message, _, _ := unstructured.NestedString(receivedPatch, "status", "operationState", "message")
assert.Contains(t, message, "Retrying attempt #1")
assert.Contains(t, message, "due to application controller sync timeout. Retrying attempt #1")
retryCount, _, _ := unstructured.NestedFloat64(receivedPatch, "status", "operationState", "retryCount")
assert.InEpsilon(t, float64(1), retryCount, 0.0001)
}

View File

@@ -109,15 +109,6 @@ func (m *appStateManager) SyncAppState(app *v1alpha1.Application, state *v1alpha
}
syncOp = *state.Operation.Sync
// validates if it should fail the sync if it finds shared resources
hasSharedResource, sharedResourceMessage := hasSharedResourceCondition(app)
if syncOp.SyncOptions.HasOption("FailOnSharedResource=true") &&
hasSharedResource {
state.Phase = common.OperationFailed
state.Message = "Shared resource found: " + sharedResourceMessage
return
}
isMultiSourceRevision := app.Spec.HasMultipleSources()
rollback := len(syncOp.Sources) > 0 || syncOp.Source != nil
if rollback {
@@ -208,6 +199,15 @@ func (m *appStateManager) SyncAppState(app *v1alpha1.Application, state *v1alpha
syncRes.Revision = compareResult.syncStatus.Revision
syncRes.Revisions = compareResult.syncStatus.Revisions
// validates if it should fail the sync if it finds shared resources
hasSharedResource, sharedResourceMessage := hasSharedResourceCondition(app)
if syncOp.SyncOptions.HasOption("FailOnSharedResource=true") &&
hasSharedResource {
state.Phase = common.OperationFailed
state.Message = "Shared resource found: %s" + sharedResourceMessage
return
}
// If there are any comparison or spec errors error conditions do not perform the operation
if errConditions := app.Status.GetConditions(map[v1alpha1.ApplicationConditionType]bool{
v1alpha1.ApplicationConditionComparisonError: true,
@@ -321,7 +321,7 @@ func (m *appStateManager) SyncAppState(app *v1alpha1.Application, state *v1alpha
return
}
if impersonationEnabled {
serviceAccountToImpersonate, err := deriveServiceAccountToImpersonate(proj, app)
serviceAccountToImpersonate, err := deriveServiceAccountToImpersonate(proj, app, destCluster)
if err != nil {
state.Phase = common.OperationError
state.Message = fmt.Sprintf("failed to find a matching service account to impersonate: %v", err)
@@ -598,7 +598,7 @@ func syncWindowPreventsSync(app *v1alpha1.Application, proj *v1alpha1.AppProject
// deriveServiceAccountToImpersonate determines the service account to be used for impersonation for the sync operation.
// The returned service account will be fully qualified including namespace and the service account name in the format system:serviceaccount:<namespace>:<service_account>
func deriveServiceAccountToImpersonate(project *v1alpha1.AppProject, application *v1alpha1.Application) (string, error) {
func deriveServiceAccountToImpersonate(project *v1alpha1.AppProject, application *v1alpha1.Application, destCluster *v1alpha1.Cluster) (string, error) {
// spec.Destination.Namespace is optional. If not specified, use the Application's
// namespace
serviceAccountNamespace := application.Spec.Destination.Namespace
@@ -608,7 +608,7 @@ func deriveServiceAccountToImpersonate(project *v1alpha1.AppProject, application
// Loop through the destinationServiceAccounts and see if there is any destination that is a candidate.
// if so, return the service account specified for that destination.
for _, item := range project.Spec.DestinationServiceAccounts {
dstServerMatched, err := glob.MatchWithError(item.Server, application.Spec.Destination.Server)
dstServerMatched, err := glob.MatchWithError(item.Server, destCluster.Server)
if err != nil {
return "", fmt.Errorf("invalid glob pattern for destination server: %w", err)
}

View File

@@ -5,7 +5,7 @@ import (
"testing"
"github.com/argoproj/gitops-engine/pkg/sync"
"github.com/argoproj/gitops-engine/pkg/sync/common"
synccommon "github.com/argoproj/gitops-engine/pkg/sync/common"
"github.com/argoproj/gitops-engine/pkg/utils/kube"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -14,6 +14,7 @@ import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"github.com/argoproj/argo-cd/v3/common"
"github.com/argoproj/argo-cd/v3/controller/testdata"
"github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/v3/reposerver/apiclient"
@@ -189,17 +190,23 @@ func TestSyncComparisonError(t *testing.T) {
}
func TestAppStateManager_SyncAppState(t *testing.T) {
t.Parallel()
type fixture struct {
project *v1alpha1.AppProject
application *v1alpha1.Application
project *v1alpha1.AppProject
controller *ApplicationController
}
setup := func() *fixture {
setup := func(liveObjects map[kube.ResourceKey]*unstructured.Unstructured) *fixture {
app := newFakeApp()
app.Status.OperationState = nil
app.Status.History = nil
if liveObjects == nil {
liveObjects = make(map[kube.ResourceKey]*unstructured.Unstructured)
}
project := &v1alpha1.AppProject{
ObjectMeta: metav1.ObjectMeta{
Namespace: test.FakeArgoCDNamespace,
@@ -207,6 +214,12 @@ func TestAppStateManager_SyncAppState(t *testing.T) {
},
Spec: v1alpha1.AppProjectSpec{
SignatureKeys: []v1alpha1.SignatureKey{{KeyID: "test"}},
Destinations: []v1alpha1.ApplicationDestination{
{
Namespace: "*",
Server: "*",
},
},
},
}
data := fakeData{
@@ -217,13 +230,13 @@ func TestAppStateManager_SyncAppState(t *testing.T) {
Server: test.FakeClusterURL,
Revision: "abc123",
},
managedLiveObjs: make(map[kube.ResourceKey]*unstructured.Unstructured),
managedLiveObjs: liveObjects,
}
ctrl := newFakeController(&data, nil)
return &fixture{
project: project,
application: app,
project: project,
controller: ctrl,
}
}
@@ -231,13 +244,23 @@ func TestAppStateManager_SyncAppState(t *testing.T) {
t.Run("will fail the sync if finds shared resources", func(t *testing.T) {
// given
t.Parallel()
f := setup()
syncErrorMsg := "deployment already applied by another application"
condition := v1alpha1.ApplicationCondition{
Type: v1alpha1.ApplicationConditionSharedResourceWarning,
Message: syncErrorMsg,
}
f.application.Status.Conditions = append(f.application.Status.Conditions, condition)
sharedObject := kube.MustToUnstructured(&corev1.ConfigMap{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "ConfigMap",
},
ObjectMeta: metav1.ObjectMeta{
Name: "configmap1",
Namespace: "default",
Annotations: map[string]string{
common.AnnotationKeyAppInstance: "guestbook:/ConfigMap:default/configmap1",
},
},
})
liveObjects := make(map[kube.ResourceKey]*unstructured.Unstructured)
liveObjects[kube.GetResourceKey(sharedObject)] = sharedObject
f := setup(liveObjects)
// Sync with source unspecified
opState := &v1alpha1.OperationState{Operation: v1alpha1.Operation{
@@ -251,8 +274,8 @@ func TestAppStateManager_SyncAppState(t *testing.T) {
f.controller.appStateManager.SyncAppState(f.application, opState)
// then
assert.Equal(t, common.OperationFailed, opState.Phase)
assert.Contains(t, opState.Message, syncErrorMsg)
assert.Equal(t, synccommon.OperationFailed, opState.Phase)
assert.Contains(t, opState.Message, "ConfigMap/configmap1 is part of applications fake-argocd-ns/my-app and guestbook")
})
}
@@ -315,13 +338,13 @@ func TestSyncWindowDeniesSync(t *testing.T) {
Source: &v1alpha1.ApplicationSource{},
},
},
Phase: common.OperationRunning,
Phase: synccommon.OperationRunning,
}
// when
f.controller.appStateManager.SyncAppState(f.application, opState)
// then
assert.Equal(t, common.OperationRunning, opState.Phase)
assert.Equal(t, synccommon.OperationRunning, opState.Phase)
assert.Contains(t, opState.Message, opMessage)
})
}
@@ -649,6 +672,7 @@ func TestDeriveServiceAccountMatchingNamespaces(t *testing.T) {
type fixture struct {
project *v1alpha1.AppProject
application *v1alpha1.Application
cluster *v1alpha1.Cluster
}
setup := func(destinationServiceAccounts []v1alpha1.ApplicationDestinationServiceAccount, destinationNamespace, destinationServerURL, applicationNamespace string) *fixture {
@@ -674,9 +698,14 @@ func TestDeriveServiceAccountMatchingNamespaces(t *testing.T) {
},
},
}
cluster := &v1alpha1.Cluster{
Server: "https://kubernetes.svc.local",
Name: "test-cluster",
}
return &fixture{
project: project,
application: app,
cluster: cluster,
}
}
@@ -692,7 +721,7 @@ func TestDeriveServiceAccountMatchingNamespaces(t *testing.T) {
f := setup(destinationServiceAccounts, destinationNamespace, destinationServerURL, applicationNamespace)
// when
sa, err := deriveServiceAccountToImpersonate(f.project, f.application)
sa, err := deriveServiceAccountToImpersonate(f.project, f.application, f.cluster)
assert.Equal(t, expectedSA, sa)
// then, there should be an error saying no valid match was found
@@ -716,7 +745,7 @@ func TestDeriveServiceAccountMatchingNamespaces(t *testing.T) {
f := setup(destinationServiceAccounts, destinationNamespace, destinationServerURL, applicationNamespace)
// when
sa, err := deriveServiceAccountToImpersonate(f.project, f.application)
sa, err := deriveServiceAccountToImpersonate(f.project, f.application, f.cluster)
// then, there should be no error and should use the right service account for impersonation
require.NoError(t, err)
@@ -755,7 +784,7 @@ func TestDeriveServiceAccountMatchingNamespaces(t *testing.T) {
f := setup(destinationServiceAccounts, destinationNamespace, destinationServerURL, applicationNamespace)
// when
sa, err := deriveServiceAccountToImpersonate(f.project, f.application)
sa, err := deriveServiceAccountToImpersonate(f.project, f.application, f.cluster)
// then, there should be no error and should use the right service account for impersonation
require.NoError(t, err)
@@ -794,7 +823,7 @@ func TestDeriveServiceAccountMatchingNamespaces(t *testing.T) {
f := setup(destinationServiceAccounts, destinationNamespace, destinationServerURL, applicationNamespace)
// when
sa, err := deriveServiceAccountToImpersonate(f.project, f.application)
sa, err := deriveServiceAccountToImpersonate(f.project, f.application, f.cluster)
// then, there should be no error and it should use the first matching service account for impersonation
require.NoError(t, err)
@@ -828,7 +857,7 @@ func TestDeriveServiceAccountMatchingNamespaces(t *testing.T) {
f := setup(destinationServiceAccounts, destinationNamespace, destinationServerURL, applicationNamespace)
// when
sa, err := deriveServiceAccountToImpersonate(f.project, f.application)
sa, err := deriveServiceAccountToImpersonate(f.project, f.application, f.cluster)
// then, there should not be any error and should use the first matching glob pattern service account for impersonation
require.NoError(t, err)
@@ -863,7 +892,7 @@ func TestDeriveServiceAccountMatchingNamespaces(t *testing.T) {
f := setup(destinationServiceAccounts, destinationNamespace, destinationServerURL, applicationNamespace)
// when
sa, err := deriveServiceAccountToImpersonate(f.project, f.application)
sa, err := deriveServiceAccountToImpersonate(f.project, f.application, f.cluster)
// then, there should be an error saying no match was found
require.EqualError(t, err, expectedErrMsg)
@@ -891,7 +920,7 @@ func TestDeriveServiceAccountMatchingNamespaces(t *testing.T) {
f := setup(destinationServiceAccounts, destinationNamespace, destinationServerURL, applicationNamespace)
// when
sa, err := deriveServiceAccountToImpersonate(f.project, f.application)
sa, err := deriveServiceAccountToImpersonate(f.project, f.application, f.cluster)
// then, there should not be any error and the service account configured for with empty namespace should be used.
require.NoError(t, err)
@@ -925,7 +954,7 @@ func TestDeriveServiceAccountMatchingNamespaces(t *testing.T) {
f := setup(destinationServiceAccounts, destinationNamespace, destinationServerURL, applicationNamespace)
// when
sa, err := deriveServiceAccountToImpersonate(f.project, f.application)
sa, err := deriveServiceAccountToImpersonate(f.project, f.application, f.cluster)
// then, there should not be any error and the catch all service account should be returned
require.NoError(t, err)
@@ -949,7 +978,7 @@ func TestDeriveServiceAccountMatchingNamespaces(t *testing.T) {
f := setup(destinationServiceAccounts, destinationNamespace, destinationServerURL, applicationNamespace)
// when
sa, err := deriveServiceAccountToImpersonate(f.project, f.application)
sa, err := deriveServiceAccountToImpersonate(f.project, f.application, f.cluster)
// then, there must be an error as the glob pattern is invalid.
require.ErrorContains(t, err, "invalid glob pattern for destination namespace")
@@ -983,7 +1012,35 @@ func TestDeriveServiceAccountMatchingNamespaces(t *testing.T) {
f := setup(destinationServiceAccounts, destinationNamespace, destinationServerURL, applicationNamespace)
// when
sa, err := deriveServiceAccountToImpersonate(f.project, f.application)
sa, err := deriveServiceAccountToImpersonate(f.project, f.application, f.cluster)
assert.Equal(t, expectedSA, sa)
// then, there should not be any error and the service account with its namespace should be returned.
require.NoError(t, err)
})
t.Run("app destination name instead of server URL", func(t *testing.T) {
t.Parallel()
destinationServiceAccounts := []v1alpha1.ApplicationDestinationServiceAccount{
{
Server: "https://kubernetes.svc.local",
Namespace: "*",
DefaultServiceAccount: "test-sa",
},
}
destinationNamespace := "testns"
destinationServerURL := "https://kubernetes.svc.local"
applicationNamespace := "argocd-ns"
expectedSA := "system:serviceaccount:testns:test-sa"
f := setup(destinationServiceAccounts, destinationNamespace, destinationServerURL, applicationNamespace)
// Use destination name instead of server URL
f.application.Spec.Destination.Server = ""
f.application.Spec.Destination.Name = f.cluster.Name
// when
sa, err := deriveServiceAccountToImpersonate(f.project, f.application, f.cluster)
assert.Equal(t, expectedSA, sa)
// then, there should not be any error and the service account with its namespace should be returned.
@@ -995,6 +1052,7 @@ func TestDeriveServiceAccountMatchingServers(t *testing.T) {
type fixture struct {
project *v1alpha1.AppProject
application *v1alpha1.Application
cluster *v1alpha1.Cluster
}
setup := func(destinationServiceAccounts []v1alpha1.ApplicationDestinationServiceAccount, destinationNamespace, destinationServerURL, applicationNamespace string) *fixture {
@@ -1020,9 +1078,14 @@ func TestDeriveServiceAccountMatchingServers(t *testing.T) {
},
},
}
cluster := &v1alpha1.Cluster{
Server: "https://kubernetes.svc.local",
Name: "test-cluster",
}
return &fixture{
project: project,
application: app,
cluster: cluster,
}
}
@@ -1058,7 +1121,7 @@ func TestDeriveServiceAccountMatchingServers(t *testing.T) {
f := setup(destinationServiceAccounts, destinationNamespace, destinationServerURL, applicationNamespace)
// when
sa, err := deriveServiceAccountToImpersonate(f.project, f.application)
sa, err := deriveServiceAccountToImpersonate(f.project, f.application, f.cluster)
// then, there should not be any error and the right service account must be returned.
require.NoError(t, err)
@@ -1097,7 +1160,7 @@ func TestDeriveServiceAccountMatchingServers(t *testing.T) {
f := setup(destinationServiceAccounts, destinationNamespace, destinationServerURL, applicationNamespace)
// when
sa, err := deriveServiceAccountToImpersonate(f.project, f.application)
sa, err := deriveServiceAccountToImpersonate(f.project, f.application, f.cluster)
// then, there should not be any error and first matching service account should be used
require.NoError(t, err)
@@ -1131,7 +1194,7 @@ func TestDeriveServiceAccountMatchingServers(t *testing.T) {
f := setup(destinationServiceAccounts, destinationNamespace, destinationServerURL, applicationNamespace)
// when
sa, err := deriveServiceAccountToImpersonate(f.project, f.application)
sa, err := deriveServiceAccountToImpersonate(f.project, f.application, f.cluster)
assert.Equal(t, expectedSA, sa)
// then, there should not be any error and the service account of the glob pattern, being the first match should be returned.
@@ -1166,7 +1229,7 @@ func TestDeriveServiceAccountMatchingServers(t *testing.T) {
f := setup(destinationServiceAccounts, destinationNamespace, destinationServerURL, applicationNamespace)
// when
sa, err := deriveServiceAccountToImpersonate(f.project, f.application)
sa, err := deriveServiceAccountToImpersonate(f.project, f.application, &v1alpha1.Cluster{Server: destinationServerURL})
// then, there an error with appropriate message must be returned
require.EqualError(t, err, expectedErr)
@@ -1200,7 +1263,7 @@ func TestDeriveServiceAccountMatchingServers(t *testing.T) {
f := setup(destinationServiceAccounts, destinationNamespace, destinationServerURL, applicationNamespace)
// when
sa, err := deriveServiceAccountToImpersonate(f.project, f.application)
sa, err := deriveServiceAccountToImpersonate(f.project, f.application, f.cluster)
// then, there should not be any error and the service account of the glob pattern match must be returned.
require.NoError(t, err)
@@ -1224,7 +1287,7 @@ func TestDeriveServiceAccountMatchingServers(t *testing.T) {
f := setup(destinationServiceAccounts, destinationNamespace, destinationServerURL, applicationNamespace)
// when
sa, err := deriveServiceAccountToImpersonate(f.project, f.application)
sa, err := deriveServiceAccountToImpersonate(f.project, f.application, f.cluster)
// then, there must be an error as the glob pattern is invalid.
require.ErrorContains(t, err, "invalid glob pattern for destination server")
@@ -1258,12 +1321,40 @@ func TestDeriveServiceAccountMatchingServers(t *testing.T) {
f := setup(destinationServiceAccounts, destinationNamespace, destinationServerURL, applicationNamespace)
// when
sa, err := deriveServiceAccountToImpersonate(f.project, f.application)
sa, err := deriveServiceAccountToImpersonate(f.project, f.application, &v1alpha1.Cluster{Server: destinationServerURL})
// then, there should not be any error and the service account with the given namespace prefix must be returned.
require.NoError(t, err)
assert.Equal(t, expectedSA, sa)
})
t.Run("app destination name instead of server URL", func(t *testing.T) {
t.Parallel()
destinationServiceAccounts := []v1alpha1.ApplicationDestinationServiceAccount{
{
Server: "https://kubernetes.svc.local",
Namespace: "*",
DefaultServiceAccount: "test-sa",
},
}
destinationNamespace := "testns"
destinationServerURL := "https://kubernetes.svc.local"
applicationNamespace := "argocd-ns"
expectedSA := "system:serviceaccount:testns:test-sa"
f := setup(destinationServiceAccounts, destinationNamespace, destinationServerURL, applicationNamespace)
// Use destination name instead of server URL
f.application.Spec.Destination.Server = ""
f.application.Spec.Destination.Name = f.cluster.Name
// when
sa, err := deriveServiceAccountToImpersonate(f.project, f.application, f.cluster)
assert.Equal(t, expectedSA, sa)
// then, there should not be any error and the service account with its namespace should be returned.
require.NoError(t, err)
})
}
func TestSyncWithImpersonate(t *testing.T) {
@@ -1336,13 +1427,13 @@ func TestSyncWithImpersonate(t *testing.T) {
Source: &v1alpha1.ApplicationSource{},
},
},
Phase: common.OperationRunning,
Phase: synccommon.OperationRunning,
}
// when
f.controller.appStateManager.SyncAppState(f.application, opState)
// then, app sync should fail with expected error message in operation state
assert.Equal(t, common.OperationError, opState.Phase)
assert.Equal(t, synccommon.OperationError, opState.Phase)
assert.Contains(t, opState.Message, opMessage)
})
@@ -1357,13 +1448,13 @@ func TestSyncWithImpersonate(t *testing.T) {
Source: &v1alpha1.ApplicationSource{},
},
},
Phase: common.OperationRunning,
Phase: synccommon.OperationRunning,
}
// when
f.controller.appStateManager.SyncAppState(f.application, opState)
// then app sync should fail with expected error message in operation state
assert.Equal(t, common.OperationError, opState.Phase)
assert.Equal(t, synccommon.OperationError, opState.Phase)
assert.Contains(t, opState.Message, opMessage)
})
@@ -1378,13 +1469,13 @@ func TestSyncWithImpersonate(t *testing.T) {
Source: &v1alpha1.ApplicationSource{},
},
},
Phase: common.OperationRunning,
Phase: synccommon.OperationRunning,
}
// when
f.controller.appStateManager.SyncAppState(f.application, opState)
// then app sync should not fail
assert.Equal(t, common.OperationSucceeded, opState.Phase)
assert.Equal(t, synccommon.OperationSucceeded, opState.Phase)
assert.Contains(t, opState.Message, opMessage)
})
@@ -1399,13 +1490,38 @@ func TestSyncWithImpersonate(t *testing.T) {
Source: &v1alpha1.ApplicationSource{},
},
},
Phase: common.OperationRunning,
Phase: synccommon.OperationRunning,
}
// when
f.controller.appStateManager.SyncAppState(f.application, opState)
// then application sync should pass using the control plane service account
assert.Equal(t, common.OperationSucceeded, opState.Phase)
assert.Equal(t, synccommon.OperationSucceeded, opState.Phase)
assert.Contains(t, opState.Message, opMessage)
})
t.Run("app destination name instead of server URL", func(t *testing.T) {
// given app sync impersonation feature is enabled with an application referring a project matching service account
f := setup(true, test.FakeDestNamespace, "test-sa")
opMessage := "successfully synced (no more tasks)"
opState := &v1alpha1.OperationState{
Operation: v1alpha1.Operation{
Sync: &v1alpha1.SyncOperation{
Source: &v1alpha1.ApplicationSource{},
},
},
Phase: synccommon.OperationRunning,
}
f.application.Spec.Destination.Server = ""
f.application.Spec.Destination.Name = "minikube"
// when
f.controller.appStateManager.SyncAppState(f.application, opState)
// then app sync should not fail
assert.Equal(t, synccommon.OperationSucceeded, opState.Phase)
assert.Contains(t, opState.Message, opMessage)
})
}

View File

@@ -193,6 +193,7 @@ argocd_cluster_labels{label_environment="production",label_team_name="team3",nam
## API Server Metrics
Metrics about API Server API request and response activity (request totals, response codes, etc...).
Scraped at the `argocd-server-metrics:8083/metrics` endpoint.
For GRPC metrics to show up environment variable ARGOCD_ENABLE_GRPC_TIME_HISTOGRAM must be set to true.
| Metric | Type | Description |
|---------------------------------------------------|:---------:|---------------------------------------------------------------------------------------------|
@@ -231,17 +232,20 @@ Scraped at the `argocd-server-metrics:8083/metrics` endpoint.
| version | v2.13.3 | Argo CD version. |
## Repo Server Metrics
Metrics about the Repo Server.
Metrics about the Repo Server. The gRPC metrics are not exposed by default. Metrics can be enabled using
`ARGOCD_ENABLE_GRPC_TIME_HISTOGRAM=true` environment variable.
Scraped at the `argocd-repo-server:8084/metrics` endpoint.
| Metric | Type | Description |
|--------|:----:|-------------|
| `argocd_git_request_duration_seconds` | histogram | Git requests duration seconds. |
| `argocd_git_request_total` | counter | Number of git requests performed by repo server |
| `argocd_git_fetch_fail_total` | counter | Number of git fetch requests failures by repo server |
| `argocd_redis_request_duration_seconds` | histogram | Redis requests duration seconds. |
| `argocd_redis_request_total` | counter | Number of Kubernetes requests executed during application reconciliation. |
| `argocd_repo_pending_request_total` | gauge | Number of pending requests requiring repository lock |
| Metric | Type | Description |
| --------------------------------------- | :-------: | ------------------------------------------------------------------------- |
| `argocd_git_request_duration_seconds` | histogram | Git requests duration seconds. |
| `argocd_git_request_total` | counter | Number of git requests performed by repo server |
| `argocd_git_fetch_fail_total` | counter | Number of git fetch requests failures by repo server |
| `argocd_redis_request_duration_seconds` | histogram | Redis requests duration seconds. |
| `argocd_redis_request_total` | counter | Number of Kubernetes requests executed during application reconciliation. |
| `argocd_repo_pending_request_total` | gauge | Number of pending requests requiring repository lock |
## Commit Server Metrics

View File

@@ -7,6 +7,13 @@ applicable) restore Argo CD 2.x default behavior.
Once 3.0 is released, no more 2.x minor versions will be released. We will continue to cut patch releases for the two
most recent minor versions (so 2.14 until 3.2 is released and 2.13 until 3.1 is released).
## Images missing release notes on GitHub
!!! important
Images 3.0.7 - 3.0.10 are missing release notes on GitHub. There was an issue with GoReleaser and building the darwin
CLI that prevented the release notes from being published. More information can be found
on [PR #23507](https://github.com/argoproj/argo-cd/pull/23507)
## Breaking Changes
### Fine-Grained RBAC for application `update` and `delete` sub-resources
@@ -239,16 +246,36 @@ external code copying tracking labels from one resource to another.
#### Detection
To detect if you are impacted, check the `argocd-cm` ConfigMap for the `application.resourceTrackingMethod` field. If it
To detect if you are impacted, check the `argocd-cm` ConfigMap for the `application.resourceTrackingMethod` field. If it is
unset or is set to `label`, you are using label-based tracking. If it is set to `annotation`, you are already using
annotation-based tracking and are not impacted by this change.
```sh
kubectl get cm argocd-cm -n argocd -o jsonpath='{.data.application\.resourceTrackingMethod}'
```
If you are using label-based tracking, it is also important to detect whether you have Applications that use `ApplyOutOfSyncOnly=true` syncOptions, as such Applications are likely to have orphan resources after switching to `annotation` tracking method and need to be synced explicitly right after the upgrade.
To detect whether you have such Applications, run:
```sh
kubectl get applications.argoproj.io -A -o json | jq -r '.items[] | select(.spec.syncPolicy.syncOptions[]? == "ApplyOutOfSyncOnly=true") | .metadata.name'
```
#### Remediation
##### Users with ApplyOutOfSyncOnly=true syncOptions and label-based tracking
For users with label-based tracking and Applications that have `ApplyOutOfSyncOnly=true` syncOptions, an explicit sync has to be run for those Applications after you upgrade.
Here is an example command, that syncs such an Application, it can be run after you [obtain a token](../../developer-guide/api-docs.md#authorization) to Argo CD API:
```sh
curl -X POST -H "Authorization: Bearer $ARGOCD_TOKEN" -H "Content-Type: application/json" -d '{
"name": "$YOUR_APP_NAME"
}' "http://$YOUR_ARGOCD_URL/api/v1/applications/$YOUR_APP_NAME/sync"
```
It is also possible to sync such an Applicaton using the UI, with `ApplyOutOfSyncOnly` option unchecked. However, currently, performing a sync without `ApplyOutOfSyncOnly` option is not possible using the CLI.
##### Other users
For most users, it is safe to upgrade to Argo CD 3.0 and use annotation-based tracking. Labels will be replaced with
annotations on the next sync. Applications will not be marked as out-of-sync if labels are not present on the
resources.
@@ -261,6 +288,7 @@ resources.
delete it. To avoid this edge case, it is recommended to perform a sync operation on your Applications, even if
they are not out of sync, so that orphan resource detection will work as expected on the next sync.
##### Users who rely on label-based for resources that are not managed by Argo CD
Some users rely on label-based tracking to track resources that are not managed by Argo CD. They may set annotations
to have Argo CD ignore the resource as extraneous or to disable pruning. If you are using label-based tracking to track
resources that are not managed by Argo CD, you will need to construct tracking annotations instead of tracking labels

2
go.mod
View File

@@ -1,6 +1,6 @@
module github.com/argoproj/argo-cd/v3
go 1.24.4
go 1.24.6
require (
code.gitea.io/sdk/gitea v0.20.0

View File

@@ -253,6 +253,12 @@ spec:
name: argocd-cmd-params-cm
key: controller.cluster.cache.events.processing.interval
optional: true
- name: ARGOCD_APPLICATION_CONTROLLER_COMMIT_SERVER
valueFrom:
configMapKeyRef:
name: argocd-cmd-params-cm
key: commit.server
optional: true
image: quay.io/argoproj/argocd:latest
imagePullPolicy: Always
name: argocd-application-controller

View File

@@ -268,6 +268,12 @@ spec:
name: argocd-cmd-params-cm
key: controller.cluster.cache.events.processing.interval
optional: true
- name: ARGOCD_APPLICATION_CONTROLLER_COMMIT_SERVER
valueFrom:
configMapKeyRef:
name: argocd-cmd-params-cm
key: commit.server
optional: true
- name: KUBECACHEDIR
value: /tmp/kubecache
image: quay.io/argoproj/argocd:latest

View File

@@ -12,4 +12,4 @@ resources:
images:
- name: quay.io/argoproj/argocd
newName: quay.io/argoproj/argocd
newTag: v3.0.7
newTag: v3.0.13

View File

@@ -5,7 +5,7 @@ kind: Kustomization
images:
- name: quay.io/argoproj/argocd
newName: quay.io/argoproj/argocd
newTag: v3.0.7
newTag: v3.0.13
resources:
- ./application-controller
- ./dex

View File

@@ -24609,7 +24609,7 @@ spec:
key: applicationsetcontroller.requeue.after
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -24735,7 +24735,7 @@ spec:
key: log.format.timestamp
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -24781,7 +24781,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -24885,7 +24885,7 @@ spec:
- argocd
- admin
- redis-initial-password
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: IfNotPresent
name: secret-init
securityContext:
@@ -25158,7 +25158,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -25210,7 +25210,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -25544,9 +25544,15 @@ spec:
key: controller.cluster.cache.events.processing.interval
name: argocd-cmd-params-cm
optional: true
- name: ARGOCD_APPLICATION_CONTROLLER_COMMIT_SERVER
valueFrom:
configMapKeyRef:
key: commit.server
name: argocd-cmd-params-cm
optional: true
- name: KUBECACHEDIR
value: /tmp/kubecache
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -24577,7 +24577,7 @@ spec:
key: applicationsetcontroller.requeue.after
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -24697,7 +24697,7 @@ spec:
- argocd
- admin
- redis-initial-password
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: IfNotPresent
name: secret-init
securityContext:
@@ -24970,7 +24970,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -25022,7 +25022,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -25356,9 +25356,15 @@ spec:
key: controller.cluster.cache.events.processing.interval
name: argocd-cmd-params-cm
optional: true
- name: ARGOCD_APPLICATION_CONTROLLER_COMMIT_SERVER
valueFrom:
configMapKeyRef:
key: commit.server
name: argocd-cmd-params-cm
optional: true
- name: KUBECACHEDIR
value: /tmp/kubecache
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -12,4 +12,4 @@ resources:
images:
- name: quay.io/argoproj/argocd
newName: quay.io/argoproj/argocd
newTag: v3.0.7
newTag: v3.0.13

View File

@@ -12,7 +12,7 @@ patches:
images:
- name: quay.io/argoproj/argocd
newName: quay.io/argoproj/argocd
newTag: v3.0.7
newTag: v3.0.13
resources:
- ../../base/application-controller
- ../../base/applicationset-controller

View File

@@ -25975,7 +25975,7 @@ spec:
key: applicationsetcontroller.requeue.after
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -26101,7 +26101,7 @@ spec:
key: log.format.timestamp
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -26147,7 +26147,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -26274,7 +26274,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -26370,7 +26370,7 @@ spec:
key: notificationscontroller.repo.server.plaintext
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -26494,7 +26494,7 @@ spec:
- argocd
- admin
- redis-initial-password
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: IfNotPresent
name: secret-init
securityContext:
@@ -26793,7 +26793,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -26845,7 +26845,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -27219,7 +27219,7 @@ spec:
key: server.sync.replace.allowed
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -27589,9 +27589,15 @@ spec:
key: controller.cluster.cache.events.processing.interval
name: argocd-cmd-params-cm
optional: true
- name: ARGOCD_APPLICATION_CONTROLLER_COMMIT_SERVER
valueFrom:
configMapKeyRef:
key: commit.server
name: argocd-cmd-params-cm
optional: true
- name: KUBECACHEDIR
value: /tmp/kubecache
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -25945,7 +25945,7 @@ spec:
key: applicationsetcontroller.requeue.after
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -26088,7 +26088,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -26184,7 +26184,7 @@ spec:
key: notificationscontroller.repo.server.plaintext
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -26308,7 +26308,7 @@ spec:
- argocd
- admin
- redis-initial-password
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: IfNotPresent
name: secret-init
securityContext:
@@ -26607,7 +26607,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -26659,7 +26659,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -27033,7 +27033,7 @@ spec:
key: server.sync.replace.allowed
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -27403,9 +27403,15 @@ spec:
key: controller.cluster.cache.events.processing.interval
name: argocd-cmd-params-cm
optional: true
- name: ARGOCD_APPLICATION_CONTROLLER_COMMIT_SERVER
valueFrom:
configMapKeyRef:
key: commit.server
name: argocd-cmd-params-cm
optional: true
- name: KUBECACHEDIR
value: /tmp/kubecache
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -1862,7 +1862,7 @@ spec:
key: applicationsetcontroller.requeue.after
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -1988,7 +1988,7 @@ spec:
key: log.format.timestamp
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -2034,7 +2034,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -2161,7 +2161,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -2257,7 +2257,7 @@ spec:
key: notificationscontroller.repo.server.plaintext
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -2381,7 +2381,7 @@ spec:
- argocd
- admin
- redis-initial-password
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: IfNotPresent
name: secret-init
securityContext:
@@ -2680,7 +2680,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -2732,7 +2732,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -3106,7 +3106,7 @@ spec:
key: server.sync.replace.allowed
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -3476,9 +3476,15 @@ spec:
key: controller.cluster.cache.events.processing.interval
name: argocd-cmd-params-cm
optional: true
- name: ARGOCD_APPLICATION_CONTROLLER_COMMIT_SERVER
valueFrom:
configMapKeyRef:
key: commit.server
name: argocd-cmd-params-cm
optional: true
- name: KUBECACHEDIR
value: /tmp/kubecache
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -1832,7 +1832,7 @@ spec:
key: applicationsetcontroller.requeue.after
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -1975,7 +1975,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -2071,7 +2071,7 @@ spec:
key: notificationscontroller.repo.server.plaintext
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -2195,7 +2195,7 @@ spec:
- argocd
- admin
- redis-initial-password
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: IfNotPresent
name: secret-init
securityContext:
@@ -2494,7 +2494,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -2546,7 +2546,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -2920,7 +2920,7 @@ spec:
key: server.sync.replace.allowed
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -3290,9 +3290,15 @@ spec:
key: controller.cluster.cache.events.processing.interval
name: argocd-cmd-params-cm
optional: true
- name: ARGOCD_APPLICATION_CONTROLLER_COMMIT_SERVER
valueFrom:
configMapKeyRef:
key: commit.server
name: argocd-cmd-params-cm
optional: true
- name: KUBECACHEDIR
value: /tmp/kubecache
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -25069,7 +25069,7 @@ spec:
key: applicationsetcontroller.requeue.after
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -25195,7 +25195,7 @@ spec:
key: log.format.timestamp
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -25241,7 +25241,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -25368,7 +25368,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -25464,7 +25464,7 @@ spec:
key: notificationscontroller.repo.server.plaintext
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -25566,7 +25566,7 @@ spec:
- argocd
- admin
- redis-initial-password
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: IfNotPresent
name: secret-init
securityContext:
@@ -25839,7 +25839,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -25891,7 +25891,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -26263,7 +26263,7 @@ spec:
key: server.sync.replace.allowed
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -26633,9 +26633,15 @@ spec:
key: controller.cluster.cache.events.processing.interval
name: argocd-cmd-params-cm
optional: true
- name: ARGOCD_APPLICATION_CONTROLLER_COMMIT_SERVER
valueFrom:
configMapKeyRef:
key: commit.server
name: argocd-cmd-params-cm
optional: true
- name: KUBECACHEDIR
value: /tmp/kubecache
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
name: argocd-application-controller
ports:

22
manifests/install.yaml generated
View File

@@ -25037,7 +25037,7 @@ spec:
key: applicationsetcontroller.requeue.after
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -25180,7 +25180,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -25276,7 +25276,7 @@ spec:
key: notificationscontroller.repo.server.plaintext
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -25378,7 +25378,7 @@ spec:
- argocd
- admin
- redis-initial-password
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: IfNotPresent
name: secret-init
securityContext:
@@ -25651,7 +25651,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -25703,7 +25703,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -26075,7 +26075,7 @@ spec:
key: server.sync.replace.allowed
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -26445,9 +26445,15 @@ spec:
key: controller.cluster.cache.events.processing.interval
name: argocd-cmd-params-cm
optional: true
- name: ARGOCD_APPLICATION_CONTROLLER_COMMIT_SERVER
valueFrom:
configMapKeyRef:
key: commit.server
name: argocd-cmd-params-cm
optional: true
- name: KUBECACHEDIR
value: /tmp/kubecache
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -956,7 +956,7 @@ spec:
key: applicationsetcontroller.requeue.after
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -1082,7 +1082,7 @@ spec:
key: log.format.timestamp
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -1128,7 +1128,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -1255,7 +1255,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -1351,7 +1351,7 @@ spec:
key: notificationscontroller.repo.server.plaintext
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -1453,7 +1453,7 @@ spec:
- argocd
- admin
- redis-initial-password
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: IfNotPresent
name: secret-init
securityContext:
@@ -1726,7 +1726,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -1778,7 +1778,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -2150,7 +2150,7 @@ spec:
key: server.sync.replace.allowed
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -2520,9 +2520,15 @@ spec:
key: controller.cluster.cache.events.processing.interval
name: argocd-cmd-params-cm
optional: true
- name: ARGOCD_APPLICATION_CONTROLLER_COMMIT_SERVER
valueFrom:
configMapKeyRef:
key: commit.server
name: argocd-cmd-params-cm
optional: true
- name: KUBECACHEDIR
value: /tmp/kubecache
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -924,7 +924,7 @@ spec:
key: applicationsetcontroller.requeue.after
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -1067,7 +1067,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -1163,7 +1163,7 @@ spec:
key: notificationscontroller.repo.server.plaintext
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -1265,7 +1265,7 @@ spec:
- argocd
- admin
- redis-initial-password
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: IfNotPresent
name: secret-init
securityContext:
@@ -1538,7 +1538,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -1590,7 +1590,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -1962,7 +1962,7 @@ spec:
key: server.sync.replace.allowed
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -2332,9 +2332,15 @@ spec:
key: controller.cluster.cache.events.processing.interval
name: argocd-cmd-params-cm
optional: true
- name: ARGOCD_APPLICATION_CONTROLLER_COMMIT_SERVER
valueFrom:
configMapKeyRef:
key: commit.server
name: argocd-cmd-params-cm
optional: true
- name: KUBECACHEDIR
value: /tmp/kubecache
image: quay.io/argoproj/argocd:v3.0.7
image: quay.io/argoproj/argocd:v3.0.13
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -19,6 +19,7 @@ type MetricsServer struct {
repoPendingRequestsGauge *prometheus.GaugeVec
redisRequestCounter *prometheus.CounterVec
redisRequestHistogram *prometheus.HistogramVec
PrometheusRegistry *prometheus.Registry
}
type GitRequestType string
@@ -108,6 +109,7 @@ func NewMetricsServer() *MetricsServer {
repoPendingRequestsGauge: repoPendingRequestsGauge,
redisRequestCounter: redisRequestCounter,
redisRequestHistogram: redisRequestHistogram,
PrometheusRegistry: registry,
}
}

View File

@@ -9,7 +9,6 @@ import (
grpc_prometheus "github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus"
"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/logging"
"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/recovery"
"github.com/prometheus/client_golang/prometheus"
log "github.com/sirupsen/logrus"
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
"google.golang.org/grpc"
@@ -69,8 +68,7 @@ func NewServer(metricsServer *metrics.MetricsServer, cache *reposervercache.Cach
serverMetricsOptions = append(serverMetricsOptions, grpc_prometheus.WithServerHandlingTimeHistogram())
}
serverMetrics := grpc_prometheus.NewServerMetrics(serverMetricsOptions...)
reg := prometheus.NewRegistry()
reg.MustRegister(serverMetrics)
metricsServer.PrometheusRegistry.MustRegister(serverMetrics)
serverLog := log.NewEntry(log.StandardLogger())
streamInterceptors := []grpc.StreamServerInterceptor{

View File

@@ -20,23 +20,29 @@ if #obj.status.conditions == 0 then
end
local isEstablished
local isTerminating
local namesNotAccepted
local hasViolations
local conditionMsg = ""
for _, condition in pairs(obj.status.conditions) do
-- Check if CRD is terminating
if condition.type == "Terminating" and condition.status == "True" then
isTerminating = true
conditionMsg = condition.message
hs.status = "Progressing"
hs.message = "CRD is terminating: " .. condition.message
return hs
end
-- Check if K8s has accepted names for this CRD
if condition.type == "NamesAccepted" and condition.status == "False" then
namesNotAccepted = true
conditionMsg = condition.message
hs.status = "Degraded"
hs.message = "CRD names have not been accepted: " .. condition.message
return hs
end
-- Checking if CRD has violations
if condition.type == "NonStructuralSchema" and condition.status == "True" then
hs.status = "Degraded"
hs.message = "Schema violations found: " .. condition.message
return hs
end
-- Checking if CRD is established
@@ -44,25 +50,6 @@ for _, condition in pairs(obj.status.conditions) do
isEstablished = true
conditionMsg = condition.message
end
-- Checking if CRD has violations
if condition.type == "NonStructuralSchema" and condition.status == "True" then
hasViolations = true
conditionMsg = condition.message
end
end
if isTerminating then
hs.status = "Progressing"
hs.message = "CRD is terminating: " .. conditionMsg
return hs
end
if namesNotAccepted then
hs.status = "Degraded"
hs.message = "CRD names have not been accepted: " .. conditionMsg
return hs
end
if not isEstablished then
@@ -71,12 +58,6 @@ if not isEstablished then
return hs
end
if hasViolations then
hs.status = "Degraded"
hs.message = "Schema violations found: " .. conditionMsg
return hs
end
hs.status = "Healthy"
hs.message = "CRD is healthy"
return hs

View File

@@ -47,15 +47,15 @@ status:
reason: NoConflicts
status: 'True'
type: NamesAccepted
- lastTransitionTime: '2024-05-19T23:35:28Z'
message: the initial names have been accepted
reason: InitialNamesAccepted
status: 'True'
type: Established
- lastTransitionTime: '2024-10-26T19:44:57Z'
message: 'spec.preserveUnknownFields: Invalid value: true: must be false'
reason: Violations
status: 'True'
type: NonStructuralSchema
- lastTransitionTime: '2024-05-19T23:35:28Z'
message: the initial names have been accepted
reason: InitialNamesAccepted
status: 'True'
type: Established
storedVersions:
- v1alpha1

View File

@@ -2679,7 +2679,7 @@ func (s *Server) GetApplicationSyncWindows(ctx context.Context, q *application.A
func (s *Server) inferResourcesStatusHealth(app *v1alpha1.Application) {
if app.Status.ResourceHealthSource == v1alpha1.ResourceHealthLocationAppTree {
tree := &v1alpha1.ApplicationTree{}
if err := s.cache.GetAppResourcesTree(app.Name, tree); err == nil {
if err := s.cache.GetAppResourcesTree(app.InstanceName(s.ns), tree); err == nil {
healthByKey := map[kube.ResourceKey]*v1alpha1.HealthStatus{}
for _, node := range tree.Nodes {
if node.Health != nil {

View File

@@ -21,6 +21,7 @@ type MetricsServer struct {
extensionRequestCounter *prometheus.CounterVec
extensionRequestDuration *prometheus.HistogramVec
argoVersion *prometheus.GaugeVec
PrometheusRegistry *prometheus.Registry
}
var (
@@ -95,6 +96,7 @@ func NewMetricsServer(host string, port int) *MetricsServer {
extensionRequestCounter: extensionRequestCounter,
extensionRequestDuration: extensionRequestDuration,
argoVersion: argoVersion,
PrometheusRegistry: registry,
}
}

View File

@@ -564,7 +564,7 @@ func (server *ArgoCDServer) Run(ctx context.Context, listeners *Listeners) {
svcSet := newArgoCDServiceSet(server)
server.serviceSet = svcSet
grpcS, appResourceTreeFn := server.newGRPCServer()
grpcS, appResourceTreeFn := server.newGRPCServer(metricsServ.PrometheusRegistry)
grpcWebS := grpcweb.WrapServer(grpcS)
var httpS *http.Server
var httpsS *http.Server
@@ -887,14 +887,13 @@ func (server *ArgoCDServer) useTLS() bool {
return true
}
func (server *ArgoCDServer) newGRPCServer() (*grpc.Server, application.AppResourceTreeFn) {
func (server *ArgoCDServer) newGRPCServer(prometheusRegistry *prometheus.Registry) (*grpc.Server, application.AppResourceTreeFn) {
var serverMetricsOptions []grpc_prometheus.ServerMetricsOption
if enableGRPCTimeHistogram {
serverMetricsOptions = append(serverMetricsOptions, grpc_prometheus.WithServerHandlingTimeHistogram())
}
serverMetrics := grpc_prometheus.NewServerMetrics(serverMetricsOptions...)
reg := prometheus.NewRegistry()
reg.MustRegister(serverMetrics)
prometheusRegistry.MustRegister(serverMetrics)
sOpts := []grpc.ServerOption{
// Set the both send and receive the bytes limit to be 100MB

View File

@@ -8,7 +8,7 @@ RUN ln -s /usr/lib/$(uname -m)-linux-gnu /usr/lib/linux-gnu
# Please make sure to also check the contained yarn version and update the references below when upgrading this image's version
FROM docker.io/library/node:22.9.0@sha256:69e667a79aa41ec0db50bc452a60e705ca16f35285eaf037ebe627a65a5cdf52 AS node
FROM docker.io/library/golang:1.24.4@sha256:db5d0afbfb4ab648af2393b92e87eaae9ad5e01132803d80caef91b5752d289c AS golang
FROM docker.io/library/golang:1.24.6@sha256:2c89c41fb9efc3807029b59af69645867cfe978d2b877d475be0d72f6c6ce6f6 AS golang
FROM docker.io/library/registry:2.8@sha256:543dade69668e02e5768d7ea2b0aa4fae6aa7384c9a5a8dbecc2be5136079ddb AS registry

View File

@@ -103,4 +103,6 @@ func TestKubectlMetrics(t *testing.T) {
assert.Contains(t, string(body), "argocd_kubectl_response_size_bytes", "metrics should have contained argocd_kubectl_response_size_bytes")
assert.Contains(t, string(body), "argocd_kubectl_rate_limiter_duration_seconds", "metrics should have contained argocd_kubectl_rate_limiter_duration_seconds")
assert.Contains(t, string(body), "argocd_kubectl_requests_total", "metrics should have contained argocd_kubectl_requests_total")
assert.Contains(t, string(body), "grpc_server_handled_total", "metrics should have contained grpc_server_handled_total for all the reflected methods")
assert.Contains(t, string(body), "grpc_server_msg_received_total", "metrics should have contained grpc_server_msg_received_total for all the reflected methods")
}

View File

@@ -1,6 +1,6 @@
ARG BASE_IMAGE=docker.io/library/ubuntu:24.04@sha256:80dd3c3b9c6cecb9f1667e9290b3bc61b78c2678c02cbdae5f0fea92cc6734ab
FROM docker.io/library/golang:1.24.4@sha256:db5d0afbfb4ab648af2393b92e87eaae9ad5e01132803d80caef91b5752d289c AS go
FROM docker.io/library/golang:1.24.6@sha256:2c89c41fb9efc3807029b59af69645867cfe978d2b877d475be0d72f6c6ce6f6 AS go
RUN go install github.com/mattn/goreman@latest && \
go install github.com/kisielk/godepgraph@latest

View File

@@ -94,12 +94,14 @@ func (db *db) ListClusters(_ context.Context) (*appv1.ClusterList, error) {
// CreateCluster creates a cluster
func (db *db) CreateCluster(ctx context.Context, c *appv1.Cluster) (*appv1.Cluster, error) {
settings, err := db.settingsMgr.GetSettings()
if err != nil {
return nil, err
}
if c.Server == appv1.KubernetesInternalAPIServerAddr && !settings.InClusterEnabled {
return nil, status.Errorf(codes.InvalidArgument, "cannot register cluster: in-cluster has been disabled")
if c.Server == appv1.KubernetesInternalAPIServerAddr {
settings, err := db.settingsMgr.GetSettings()
if err != nil {
return nil, err
}
if !settings.InClusterEnabled {
return nil, status.Errorf(codes.InvalidArgument, "cannot register cluster: in-cluster has been disabled")
}
}
secName, err := URIToSecretName("cluster", c.Server)
if err != nil {
@@ -225,12 +227,14 @@ func (db *db) getClusterSecret(server string) (*corev1.Secret, error) {
// GetCluster returns a cluster from a query
func (db *db) GetCluster(_ context.Context, server string) (*appv1.Cluster, error) {
argoSettings, err := db.settingsMgr.GetSettings()
if err != nil {
return nil, err
}
if server == appv1.KubernetesInternalAPIServerAddr && !argoSettings.InClusterEnabled {
return nil, status.Errorf(codes.NotFound, "cluster %q is disabled", server)
if server == appv1.KubernetesInternalAPIServerAddr {
argoSettings, err := db.settingsMgr.GetSettings()
if err != nil {
return nil, err
}
if !argoSettings.InClusterEnabled {
return nil, status.Errorf(codes.NotFound, "cluster %q is disabled", server)
}
}
informer, err := db.settingsMgr.GetSecretsInformer()

View File

@@ -719,6 +719,7 @@ func (creds AzureWorkloadIdentityCreds) Environ() (io.Closer, []string, error) {
}
nonce := creds.store.Add("", token)
env := creds.store.Environ(nonce)
env = append(env, fmt.Sprintf("%s=Authorization: Bearer %s", bearerAuthHeaderEnv, token))
return argoioutils.NewCloser(func() error {
creds.store.Remove(nonce)

View File

@@ -419,7 +419,7 @@ func TestAzureWorkloadIdentityCreds_Environ(t *testing.T) {
workloadIdentityMock := new(mocks.TokenProvider)
workloadIdentityMock.On("GetToken", azureDevopsEntraResourceId).Return(&workloadidentity.Token{AccessToken: "accessToken", ExpiresOn: time.Now().Add(time.Minute)}, nil)
creds := AzureWorkloadIdentityCreds{store, workloadIdentityMock}
_, _, err := creds.Environ()
_, env, err := creds.Environ()
require.NoError(t, err)
assert.Len(t, store.creds, 1)
@@ -427,6 +427,9 @@ func TestAzureWorkloadIdentityCreds_Environ(t *testing.T) {
assert.Equal(t, "", value.username)
assert.Equal(t, "accessToken", value.password)
}
require.Len(t, env, 1)
assert.Equal(t, "ARGOCD_GIT_BEARER_AUTH_HEADER=Authorization: Bearer accessToken", env[0], "ARGOCD_GIT_BEARER_AUTH_HEADER env var must be set")
}
func TestAzureWorkloadIdentityCreds_Environ_cleanup(t *testing.T) {

View File

@@ -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
}

View File

@@ -496,7 +496,11 @@ func (c *nativeHelmChart) GetTags(chart string, noCache bool) ([]string, error)
).Info("took to get tags")
if c.indexCache != nil {
if err := c.indexCache.SetHelmIndex(tagsURL, data); err != nil {
cacheData, err := json.Marshal(entries)
if err != nil {
return nil, fmt.Errorf("failed to encode tags: %w", err)
}
if err := c.indexCache.SetHelmIndex(tagsURL, cacheData); err != nil {
log.Warnf("Failed to store tags list cache for repo: %s: %v", tagsURL, err)
}
}

View File

@@ -481,3 +481,95 @@ func TestGetTagsFromURLEnvironmentAuthentication(t *testing.T) {
})
}
}
func TestGetTagsCaching(t *testing.T) {
requestCount := 0
server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
requestCount++
t.Logf("request %d called %s", requestCount, r.URL.Path)
responseTags := fakeTagsList{
Tags: []string{
"1.0.0",
"1.1.0",
"2.0.0_beta",
},
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
require.NoError(t, json.NewEncoder(w).Encode(responseTags))
}))
t.Cleanup(server.Close)
serverURL, err := url.Parse(server.URL)
require.NoError(t, err)
t.Run("should cache tags correctly", func(t *testing.T) {
cache := &fakeIndexCache{}
client := NewClient(serverURL.Host, HelmCreds{
InsecureSkipVerify: true,
}, true, "", "", WithIndexCache(cache))
tags1, err := client.GetTags("mychart", false)
require.NoError(t, err)
assert.ElementsMatch(t, tags1, []string{
"1.0.0",
"1.1.0",
"2.0.0+beta",
})
assert.Equal(t, 1, requestCount)
requestCount = 0
tags2, err := client.GetTags("mychart", false)
require.NoError(t, err)
assert.ElementsMatch(t, tags2, []string{
"1.0.0",
"1.1.0",
"2.0.0+beta",
})
assert.Equal(t, 0, requestCount)
assert.NotEmpty(t, cache.data)
type entriesStruct struct {
Tags []string
}
var entries entriesStruct
err = json.Unmarshal(cache.data, &entries)
require.NoError(t, err)
assert.ElementsMatch(t, entries.Tags, []string{
"1.0.0",
"1.1.0",
"2.0.0+beta",
})
})
t.Run("should bypass cache when noCache is true", func(t *testing.T) {
cache := &fakeIndexCache{}
client := NewClient(serverURL.Host, HelmCreds{
InsecureSkipVerify: true,
}, true, "", "", WithIndexCache(cache))
requestCount = 0
tags1, err := client.GetTags("mychart", true)
require.NoError(t, err)
assert.ElementsMatch(t, tags1, []string{
"1.0.0",
"1.1.0",
"2.0.0+beta",
})
assert.Equal(t, 1, requestCount)
tags2, err := client.GetTags("mychart", true)
require.NoError(t, err)
assert.ElementsMatch(t, tags2, []string{
"1.0.0",
"1.1.0",
"2.0.0+beta",
})
assert.Equal(t, 2, requestCount)
})
}

View File

@@ -15,6 +15,8 @@ import (
"github.com/Masterminds/semver/v3"
"sigs.k8s.io/yaml"
"github.com/argoproj/argo-cd/v3/util/io"
"github.com/argoproj/gitops-engine/pkg/utils/kube"
log "github.com/sirupsen/logrus"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
@@ -24,8 +26,6 @@ import (
executil "github.com/argoproj/argo-cd/v3/util/exec"
"github.com/argoproj/argo-cd/v3/util/git"
"github.com/argoproj/argo-cd/v3/util/proxy"
securejoin "github.com/cyphar/filepath-securejoin"
)
// Image represents a Docker image in the format NAME[:TAG].
@@ -346,12 +346,18 @@ func (k *kustomize) Build(opts *v1alpha1.ApplicationSourceKustomize, kustomizeOp
foundComponents := opts.Components
if opts.IgnoreMissingComponents {
foundComponents = make([]string, 0)
root, err := os.OpenRoot(k.repoRoot)
defer io.Close(root)
if err != nil {
return nil, nil, nil, fmt.Errorf("failed to open the repo folder: %w", err)
}
for _, c := range opts.Components {
resolvedPath, err := securejoin.SecureJoin(k.path, c)
resolvedPath, err := filepath.Rel(k.repoRoot, filepath.Join(k.path, c))
if err != nil {
return nil, nil, nil, fmt.Errorf("Kustomize components path failed: %w", err)
return nil, nil, nil, fmt.Errorf("kustomize components path failed: %w", err)
}
_, err = os.Stat(resolvedPath)
_, err = root.Stat(resolvedPath)
if err != nil {
log.Debugf("%s component directory does not exist", resolvedPath)
continue
@@ -359,15 +365,18 @@ func (k *kustomize) Build(opts *v1alpha1.ApplicationSourceKustomize, kustomizeOp
foundComponents = append(foundComponents, c)
}
}
args := []string{"edit", "add", "component"}
args = append(args, foundComponents...)
cmd := exec.Command(k.getBinaryPath(), args...)
cmd.Dir = k.path
cmd.Env = env
commands = append(commands, executil.GetCommandArgsToLog(cmd))
_, err := executil.Run(cmd)
if err != nil {
return nil, nil, nil, err
if len(foundComponents) > 0 {
args := []string{"edit", "add", "component"}
args = append(args, foundComponents...)
cmd := exec.Command(k.getBinaryPath(), args...)
cmd.Dir = k.path
cmd.Env = env
commands = append(commands, executil.GetCommandArgsToLog(cmd))
_, err := executil.Run(cmd)
if err != nil {
return nil, nil, nil, err
}
}
}
}

View File

@@ -25,6 +25,7 @@ const (
kustomization6 = "kustomization_yaml_components"
kustomization7 = "label_without_selector"
kustomization8 = "kustomization_yaml_patches_empty"
kustomization9 = "kustomization_yaml_components_monorepo"
)
func testDataDir(tb testing.TB, testData string) (string, error) {
@@ -506,6 +507,31 @@ func TestKustomizeBuildComponents(t *testing.T) {
assert.Equal(t, int64(3), replicas)
}
func TestKustomizeBuildComponentsMonoRepo(t *testing.T) {
rootPath, err := testDataDir(t, kustomization9)
require.NoError(t, err)
appPath := path.Join(rootPath, "envs/inseng-pdx-egert-sandbox/namespaces/inst-system/apps/hello-world")
kustomize := NewKustomizeApp(rootPath, appPath, git.NopCreds{}, "", "", "", "")
kustomizeSource := v1alpha1.ApplicationSourceKustomize{
Components: []string{"../../../../../../kustomize/components/all"},
IgnoreMissingComponents: true,
}
objs, _, _, err := kustomize.Build(&kustomizeSource, nil, nil, nil)
require.NoError(t, err)
obj := objs[2]
require.Equal(t, "hello-world-kustomize", obj.GetName())
require.Equal(t, map[string]string{
"app.kubernetes.io/name": "hello-world-kustomize",
"app.kubernetes.io/owner": "fire-team",
}, obj.GetLabels())
replicas, ok, err := unstructured.NestedSlice(obj.Object, "spec", "template", "spec", "tolerations")
require.NoError(t, err)
require.True(t, ok)
require.Len(t, replicas, 1)
require.Equal(t, "my-special-toleration", replicas[0].(map[string]any)["key"])
require.Equal(t, "Exists", replicas[0].(map[string]any)["operator"])
}
func TestKustomizeBuildPatches(t *testing.T) {
appPath, err := testDataDir(t, kustomization5)
require.NoError(t, err)
@@ -582,3 +608,23 @@ func TestFailKustomizeBuildPatches(t *testing.T) {
_, _, _, err = kustomize.Build(&kustomizeSource, nil, nil, nil)
require.EqualError(t, err, "kustomization file not found in the path")
}
func TestKustomizeBuildComponentsNoFoundComponents(t *testing.T) {
appPath, err := testDataDir(t, kustomization6)
require.NoError(t, err)
kustomize := NewKustomizeApp(appPath, appPath, git.NopCreds{}, "", "", "", "")
// Test with non-existent components and IgnoreMissingComponents = true
// This should result in foundComponents being empty, so no "edit add component" command should be executed
kustomizeSource := v1alpha1.ApplicationSourceKustomize{
Components: []string{"./non-existent-component1", "./non-existent-component2"},
IgnoreMissingComponents: true,
}
_, _, commands, err := kustomize.Build(&kustomizeSource, nil, nil, nil)
require.NoError(t, err)
// Verify that no "edit add component" command was executed
for _, cmd := range commands {
assert.NotContains(t, cmd, "edit add component", "kustomize edit add component should not be invoked when foundComponents is empty")
}
}

View File

@@ -0,0 +1,3 @@
---
kustomize:
componentsPath: ../../../../../../kustomize/components

View File

@@ -0,0 +1,33 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
# All the members of this group are meant be populated from the
# same nonproduction overlay of the matching app
resources:
- ../../../../../../kustomize/apps/hello-world/base
nameSuffix: -kustomize
labels:
- pairs:
app.kubernetes.io/name: hello-world-kustomize
includeSelectors: true
includeTemplates: true
patches:
# Adjusting the serviceAccount ref
- patch: |-
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-world
spec:
template:
spec:
serviceAccountName: hello-world-kustomize
# Container image versions across the members
images:
- name: hello-world
newTag: 1.17.0

View File

@@ -0,0 +1,34 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-world
labels:
app.kubernetes.io/name: hello-world
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: hello-world
template:
metadata:
labels:
app.kubernetes.io/name: hello-world
spec:
serviceAccountName: hello-world
containers:
- name: hello-world
image: "nginx:1.16.0"
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
protocol: TCP
livenessProbe:
httpGet:
path: /
port: http
readinessProbe:
httpGet:
path: /
port: http
tolerations: []

View File

@@ -0,0 +1,8 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
- serviceaccount.yaml

View File

@@ -0,0 +1,16 @@
---
apiVersion: v1
kind: Service
metadata:
name: hello-world
labels:
app.kubernetes.io/name: hello-world
spec:
type: ClusterIP
ports:
- port: 80
targetPort: http
protocol: TCP
name: http
selector:
app.kubernetes.io/name: hello-world

View File

@@ -0,0 +1,7 @@
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: hello-world
labels:
app.kubernetes.io/name: hello-world

View File

@@ -0,0 +1,19 @@
---
apiVersion: kustomize.config.k8s.io/v1alpha1
kind: Component
labels:
- pairs:
app.kubernetes.io/owner: fire-team
includeSelectors: false
includeTemplates: false
patches:
- target:
kind: Deployment
patch: |-
- op: add
path: /spec/template/spec/tolerations/-
value:
key: my-special-toleration
operator: Exists

View File

@@ -25,13 +25,9 @@ func (t testNormalizer) Normalize(un *unstructured.Unstructured) error {
if un == nil {
return nil
}
if un.GetKind() == "Job" {
err := unstructured.SetNestedField(un.Object, map[string]any{"name": "not sure why this works"}, "metadata")
if err != nil {
return fmt.Errorf("failed to normalize Job: %w", err)
}
}
switch un.GetKind() {
case "Job":
return t.normalizeJob(un)
case "DaemonSet", "Deployment", "StatefulSet":
err := unstructured.SetNestedStringMap(un.Object, map[string]string{"kubectl.kubernetes.io/restartedAt": "0001-01-01T00:00:00Z"}, "spec", "template", "metadata", "annotations")
if err != nil {
@@ -84,6 +80,28 @@ func (t testNormalizer) Normalize(un *unstructured.Unstructured) error {
return nil
}
func (t testNormalizer) normalizeJob(un *unstructured.Unstructured) error {
if conditions, exist, err := unstructured.NestedSlice(un.Object, "status", "conditions"); err != nil {
return fmt.Errorf("failed to normalize %s: %w", un.GetKind(), err)
} else if exist {
changed := false
for i := range conditions {
condition := conditions[i].(map[string]any)
cType := condition["type"].(string)
if cType == "FailureTarget" {
condition["lastTransitionTime"] = "0001-01-01T00:00:00Z"
changed = true
}
}
if changed {
if err := unstructured.SetNestedSlice(un.Object, conditions, "status", "conditions"); err != nil {
return fmt.Errorf("failed to normalize %s: %w", un.GetKind(), err)
}
}
}
return nil
}
type ActionTestStructure struct {
DiscoveryTests []IndividualDiscoveryTest `yaml:"discoveryTests"`
ActionTests []IndividualActionTest `yaml:"actionTests"`
@@ -179,8 +197,7 @@ func TestLuaResourceActionsScript(t *testing.T) {
assert.EqualValues(t, sourceObj.GetNamespace(), result.GetNamespace())
case CreateOperation:
switch result.GetKind() {
case "Job":
case "Workflow":
case "Job", "Workflow":
// The name of the created resource is derived from the source object name, so the returned name is not actually equal to the testdata output name
result.SetName(expectedObj.GetName())
}

View File

@@ -258,7 +258,8 @@ func cleanReturnedObj(newObj, obj map[string]any) map[string]any {
switch oldValue := oldValueInterface.(type) {
case map[string]any:
if len(newValue) == 0 {
mapToReturn[key] = oldValue
// Lua incorrectly decoded the empty object as an empty array, so set it to an empty object
mapToReturn[key] = map[string]any{}
}
case []any:
newArray := cleanReturnedArray(newValue, oldValue)
@@ -275,6 +276,10 @@ func cleanReturnedObj(newObj, obj map[string]any) map[string]any {
func cleanReturnedArray(newObj, obj []any) []any {
arrayToReturn := newObj
for i := range newObj {
if i >= len(obj) {
// If the new object is longer than the old one, we added an item to the array
break
}
switch newValue := newObj[i].(type) {
case map[string]any:
if oldValue, ok := obj[i].(map[string]any); ok {

View File

@@ -516,7 +516,7 @@ const expectedCreatedMultipleJobsObjList = `
kind: Job
metadata:
name: hello-2
namespace: test-ns
namespace: test-ns
`
const expectedActionMixedOperationObjList = `
@@ -533,9 +533,9 @@ const expectedActionMixedOperationObjList = `
kind: CronJob
metadata:
name: hello
namespace: test-ns
namespace: test-ns
labels:
test: test
test: test
`
const createJobActionLua = `
@@ -707,7 +707,9 @@ func TestExecuteResourceActionInvalidUnstructured(t *testing.T) {
require.Error(t, err)
}
const objWithEmptyStruct = `
func TestCleanPatch(t *testing.T) {
t.Run("Empty Struct preserved", func(t *testing.T) {
const obj = `
apiVersion: argoproj.io/v1alpha1
kind: Test
metadata:
@@ -719,7 +721,8 @@ metadata:
resourceVersion: "123"
spec:
resources: {}
paused: true
updated:
something: true
containers:
- name: name1
test: {}
@@ -727,8 +730,7 @@ spec:
- name: name2
test2: {}
`
const expectedUpdatedObjWithEmptyStruct = `
const expected = `
apiVersion: argoproj.io/v1alpha1
kind: Test
metadata:
@@ -740,7 +742,7 @@ metadata:
resourceVersion: "123"
spec:
resources: {}
paused: false
updated: {}
containers:
- name: name1
test: {}
@@ -748,21 +750,133 @@ spec:
- name: name2
test2: {}
`
const pausedToFalseLua = `
obj.spec.paused = false
const luaAction = `
obj.spec.updated = {}
return obj
`
testObj := StrToUnstructured(obj)
expectedObj := StrToUnstructured(expected)
vm := VM{}
newObjects, err := vm.ExecuteResourceAction(testObj, luaAction)
require.NoError(t, err)
assert.Len(t, newObjects, 1)
assert.Equal(t, newObjects[0].K8SOperation, K8SOperation("patch"))
assert.Equal(t, expectedObj, newObjects[0].UnstructuredObj)
})
func TestCleanPatch(t *testing.T) {
testObj := StrToUnstructured(objWithEmptyStruct)
expectedObj := StrToUnstructured(expectedUpdatedObjWithEmptyStruct)
vm := VM{}
newObjects, err := vm.ExecuteResourceAction(testObj, pausedToFalseLua)
require.NoError(t, err)
assert.Len(t, newObjects, 1)
assert.Equal(t, newObjects[0].K8SOperation, K8SOperation("patch"))
assert.Equal(t, expectedObj, newObjects[0].UnstructuredObj)
t.Run("New item added to array", func(t *testing.T) {
const obj = `
apiVersion: argoproj.io/v1alpha1
kind: Test
metadata:
labels:
app.kubernetes.io/instance: helm-guestbook
test: test
name: helm-guestbook
namespace: default
resourceVersion: "123"
spec:
containers:
- name: name1
test: {}
anotherList:
- name: name2
test2: {}
`
const expected = `
apiVersion: argoproj.io/v1alpha1
kind: Test
metadata:
labels:
app.kubernetes.io/instance: helm-guestbook
test: test
name: helm-guestbook
namespace: default
resourceVersion: "123"
spec:
containers:
- name: name1
test: {}
anotherList:
- name: name2
test2: {}
- name: added
#test: {} ### would be decoded as an empty array and is not supported. The type is unknown
testArray: [] ### works since it is decoded in the correct type
another:
supported: true
`
// `test: {}` in new container would be decoded as an empty array and is not supported. The type is unknown
// `testArray: []` works since it is decoded in the correct type
const luaAction = `
table.insert(obj.spec.containers, {name = "added", testArray = {}, another = {supported = true}})
return obj
`
testObj := StrToUnstructured(obj)
expectedObj := StrToUnstructured(expected)
vm := VM{}
newObjects, err := vm.ExecuteResourceAction(testObj, luaAction)
require.NoError(t, err)
assert.Len(t, newObjects, 1)
assert.Equal(t, newObjects[0].K8SOperation, K8SOperation("patch"))
assert.Equal(t, expectedObj, newObjects[0].UnstructuredObj)
})
t.Run("Last item removed from array", func(t *testing.T) {
const obj = `
apiVersion: argoproj.io/v1alpha1
kind: Test
metadata:
labels:
app.kubernetes.io/instance: helm-guestbook
test: test
name: helm-guestbook
namespace: default
resourceVersion: "123"
spec:
containers:
- name: name1
test: {}
anotherList:
- name: name2
test2: {}
- name: name3
test: {}
anotherList:
- name: name4
test2: {}
`
const expected = `
apiVersion: argoproj.io/v1alpha1
kind: Test
metadata:
labels:
app.kubernetes.io/instance: helm-guestbook
test: test
name: helm-guestbook
namespace: default
resourceVersion: "123"
spec:
containers:
- name: name1
test: {}
anotherList:
- name: name2
test2: {}
`
const luaAction = `
table.remove(obj.spec.containers)
return obj
`
testObj := StrToUnstructured(obj)
expectedObj := StrToUnstructured(expected)
vm := VM{}
newObjects, err := vm.ExecuteResourceAction(testObj, luaAction)
require.NoError(t, err)
assert.Len(t, newObjects, 1)
assert.Equal(t, newObjects[0].K8SOperation, K8SOperation("patch"))
assert.Equal(t, expectedObj, newObjects[0].UnstructuredObj)
})
}
func TestGetResourceHealth(t *testing.T) {

View File

@@ -1,12 +1,7 @@
package workloadidentity
import (
"context"
"time"
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
)
const (
@@ -22,34 +17,9 @@ type TokenProvider interface {
GetToken(scope string) (*Token, error)
}
type WorkloadIdentityTokenProvider struct {
tokenCredential azcore.TokenCredential
}
// Used to propagate initialization error if any
var initError error
func NewWorkloadIdentityTokenProvider() TokenProvider {
cred, err := azidentity.NewDefaultAzureCredential(&azidentity.DefaultAzureCredentialOptions{})
initError = err
return WorkloadIdentityTokenProvider{tokenCredential: cred}
}
func (c WorkloadIdentityTokenProvider) GetToken(scope string) (*Token, error) {
if initError != nil {
return nil, initError
}
token, err := c.tokenCredential.GetToken(context.Background(), policy.TokenRequestOptions{
Scopes: []string{scope},
})
if err != nil {
return nil, err
}
return &Token{AccessToken: token.Token, ExpiresOn: token.ExpiresOn}, nil
}
func CalculateCacheExpiryBasedOnTokenExpiry(tokenExpiry time.Time) time.Duration {
// Calculate the cache expiry as 5 minutes before the token expires
cacheExpiry := time.Until(tokenExpiry) - time.Minute*5

View File

@@ -0,0 +1,36 @@
//go:build !darwin || (cgo && darwin)
package workloadidentity
import (
"context"
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
)
type WorkloadIdentityTokenProvider struct {
tokenCredential azcore.TokenCredential
}
func NewWorkloadIdentityTokenProvider() TokenProvider {
cred, err := azidentity.NewDefaultAzureCredential(&azidentity.DefaultAzureCredentialOptions{})
initError = err
return WorkloadIdentityTokenProvider{tokenCredential: cred}
}
func (c WorkloadIdentityTokenProvider) GetToken(scope string) (*Token, error) {
if initError != nil {
return nil, initError
}
token, err := c.tokenCredential.GetToken(context.Background(), policy.TokenRequestOptions{
Scopes: []string{scope},
})
if err != nil {
return nil, err
}
return &Token{AccessToken: token.Token, ExpiresOn: token.ExpiresOn}, nil
}

View File

@@ -0,0 +1,25 @@
//go:build darwin && !cgo
// Package workloadidentity
// This file is used when the GOOS is darwin and CGO is not enabled.
// It provides a no-op implementation of the WorkloadIdentityTokenProvider to allow goreleaser to build
// a darwin binary on a linux machine.
package workloadidentity
import (
"errors"
)
type WorkloadIdentityTokenProvider struct {
}
const CGOError = "CGO is not enabled, cannot use workload identity token provider"
// Code that does not require CGO
func NewWorkloadIdentityTokenProvider() TokenProvider {
panic(CGOError)
}
func (c WorkloadIdentityTokenProvider) GetToken(scope string) (*Token, error) {
return nil, errors.New(CGOError)
}