mirror of
https://github.com/argoproj/argo-cd.git
synced 2026-04-08 17:58:47 +02:00
Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
083ef929a5 | ||
|
|
d6e0e5c852 | ||
|
|
46e7c008ce | ||
|
|
274ab28f8f | ||
|
|
b1df89bfce | ||
|
|
d76cedea57 | ||
|
|
3fb825c36c | ||
|
|
7822fbd43a | ||
|
|
d11bf1ac88 | ||
|
|
ed1e2397ef | ||
|
|
5e769f900f | ||
|
|
fc27c4d099 | ||
|
|
240a1833c0 | ||
|
|
b19defcd40 | ||
|
|
bbf0582eb0 | ||
|
|
ba3d90972c | ||
|
|
0fe62852c7 | ||
|
|
108dab6e16 | ||
|
|
873289c409 | ||
|
|
3ab0e9c1f5 | ||
|
|
f7d0ebda31 | ||
|
|
ea7e2b7905 | ||
|
|
06fd5060a0 | ||
|
|
f264eaa40f | ||
|
|
be3e9403e9 | ||
|
|
a1faf0265f | ||
|
|
8868f91bbd | ||
|
|
902826f8c7 | ||
|
|
95d8b48624 |
2
.github/workflows/ci-build.yaml
vendored
2
.github/workflows/ci-build.yaml
vendored
@@ -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 }}
|
||||
|
||||
4
.github/workflows/image.yaml
vendored
4
.github/workflows/image.yaml
vendored
@@ -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:
|
||||
|
||||
4
.github/workflows/release.yaml
vendored
4
.github/workflows/release.yaml
vendored
@@ -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:
|
||||
|
||||
@@ -24,8 +24,8 @@ builds:
|
||||
- -extldflags="-static"
|
||||
goos:
|
||||
- linux
|
||||
- darwin
|
||||
- windows
|
||||
- darwin
|
||||
goarch:
|
||||
- amd64
|
||||
- arm64
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
//go:build !darwin || (cgo && darwin)
|
||||
|
||||
package commands
|
||||
|
||||
import (
|
||||
25
cmd/argocd-k8s-auth/commands/azure_no_cgo.go
Normal file
25
cmd/argocd-k8s-auth/commands/azure_no_cgo.go
Normal 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
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
2
go.mod
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -12,4 +12,4 @@ resources:
|
||||
images:
|
||||
- name: quay.io/argoproj/argocd
|
||||
newName: quay.io/argoproj/argocd
|
||||
newTag: v3.0.7
|
||||
newTag: v3.0.13
|
||||
|
||||
@@ -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
|
||||
|
||||
20
manifests/core-install-with-hydrator.yaml
generated
20
manifests/core-install-with-hydrator.yaml
generated
@@ -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:
|
||||
|
||||
16
manifests/core-install.yaml
generated
16
manifests/core-install.yaml
generated
@@ -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:
|
||||
|
||||
@@ -12,4 +12,4 @@ resources:
|
||||
images:
|
||||
- name: quay.io/argoproj/argocd
|
||||
newName: quay.io/argoproj/argocd
|
||||
newTag: v3.0.7
|
||||
newTag: v3.0.13
|
||||
|
||||
@@ -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
|
||||
|
||||
26
manifests/ha/install-with-hydrator.yaml
generated
26
manifests/ha/install-with-hydrator.yaml
generated
@@ -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:
|
||||
|
||||
22
manifests/ha/install.yaml
generated
22
manifests/ha/install.yaml
generated
@@ -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:
|
||||
|
||||
26
manifests/ha/namespace-install-with-hydrator.yaml
generated
26
manifests/ha/namespace-install-with-hydrator.yaml
generated
@@ -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:
|
||||
|
||||
22
manifests/ha/namespace-install.yaml
generated
22
manifests/ha/namespace-install.yaml
generated
@@ -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:
|
||||
|
||||
26
manifests/install-with-hydrator.yaml
generated
26
manifests/install-with-hydrator.yaml
generated
@@ -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
22
manifests/install.yaml
generated
@@ -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:
|
||||
|
||||
26
manifests/namespace-install-with-hydrator.yaml
generated
26
manifests/namespace-install-with-hydrator.yaml
generated
@@ -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:
|
||||
|
||||
22
manifests/namespace-install.yaml
generated
22
manifests/namespace-install.yaml
generated
@@ -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:
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
---
|
||||
kustomize:
|
||||
componentsPath: ../../../../../../kustomize/components
|
||||
@@ -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
|
||||
@@ -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: []
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- deployment.yaml
|
||||
- service.yaml
|
||||
- serviceaccount.yaml
|
||||
@@ -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
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: hello-world
|
||||
labels:
|
||||
app.kubernetes.io/name: hello-world
|
||||
@@ -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
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
36
util/workloadidentity/workloadidentity_cgo.go
Normal file
36
util/workloadidentity/workloadidentity_cgo.go
Normal 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
|
||||
}
|
||||
25
util/workloadidentity/workloadidentity_no_cgo.go
Normal file
25
util/workloadidentity/workloadidentity_no_cgo.go
Normal 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)
|
||||
}
|
||||
Reference in New Issue
Block a user