Compare commits

...

11 Commits

Author SHA1 Message Date
github-actions[bot]
8c4ab63a9c Bump version to 3.2.1 on release-3.2 branch (#25449)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: reggie-k <19544836+reggie-k@users.noreply.github.com>
2025-11-30 13:37:38 +02:00
dudinea
29f869c82f fix: the concurrency issue with git detached processing in Repo Server (#25101) (cherry-pick #25127 for 3.2) (#25448)
Signed-off-by: Eugene Doudine <eugene.doudine@octopus.com>
2025-11-30 13:24:37 +02:00
argo-cd-cherry-pick-bot[bot]
c11e67d4bf docs: Document usage of ?. in notifications triggers and fix examples (#25352) (cherry-pick #25418 for 3.2) (#25421)
Signed-off-by: Eugene Doudine <eugene.doudine@octopus.com>
Co-authored-by: dudinea <eugene.doudine@octopus.com>
2025-11-26 09:41:59 +02:00
Regina Voloshin
a0a18438ab docs: Improve switch to annotation tracking docs, clarifying that a new Git commit may be needed to avoid orphan resources - (cherry-pick #25309 for 3.2) (#25338)
Signed-off-by: Regina Voloshin <regina.voloshin@codefresh.io>
2025-11-19 11:46:19 +01:00
Jaewoo Choi
dabdf39772 fix(ui): overlapping UI elements and add resource units to tooltips (cherry-pick #24717 for 3.2) (#25225)
Signed-off-by: choejwoo <jaewoo45@gmail.com>
2025-11-18 14:17:12 -08:00
argo-cd-cherry-pick-bot[bot]
cd8df1721c fix: Allow the ISVC to be healthy when the Stopped Condition is False (cherry-pick #25312 for 3.2) (#25318)
Signed-off-by: Hannah DeFazio <h2defazio@gmail.com>
Co-authored-by: Hannah DeFazio <h2defazio@gmail.com>
2025-11-17 23:20:41 -10:00
argo-cd-cherry-pick-bot[bot]
27c5065308 fix: revert #24197 (cherry-pick #25294 for 3.2) (#25314)
Signed-off-by: Blake Pettersson <blake.pettersson@gmail.com>
Co-authored-by: Blake Pettersson <blake.pettersson@gmail.com>
2025-11-17 23:19:48 -10:00
Peter Jiang
1545390cd8 fix(cherry-pick): bump gitops-engine ssd regression (#25226)
Signed-off-by: Peter Jiang <peterjiang823@gmail.com>
2025-11-08 19:13:02 -05:00
argo-cd-cherry-pick-bot[bot]
7bd02d7f02 fix:(ui) don't render ApplicationSelector unless the panel is showing (cherry-pick #25201 for 3.2) (#25208)
Signed-off-by: Jonathan Winters <wintersjonathan0@gmail.com>
Co-authored-by: jwinters01 <34199886+jwinters01@users.noreply.github.com>
2025-11-06 17:55:27 -05:00
argo-cd-cherry-pick-bot[bot]
86c9994394 docs: update user content for deleting applications (cherry-pick #25124 for 3.2) (#25174)
Signed-off-by: Atif Ali <atali@redhat.com>
Co-authored-by: Atif Ali <atali@redhat.com>
Co-authored-by: Dan Garfield <dan@codefresh.io>
2025-11-05 01:15:04 -10:00
argo-cd-cherry-pick-bot[bot]
6dd5e7a6d2 fix(ui): add null-safe handling for assignedWindows in status panel (cherry-pick #25128 for 3.2) (#25180)
Signed-off-by: choejwoo <jaewoo45@gmail.com>
Co-authored-by: Jaewoo Choi <jaewoo45@gmail.com>
2025-11-05 01:12:47 -10:00
53 changed files with 631 additions and 641 deletions

View File

@@ -1 +1 @@
3.2.0
3.2.1

View File

@@ -80,6 +80,7 @@ func NewCommand() *cobra.Command {
includeHiddenDirectories bool
cmpUseManifestGeneratePaths bool
ociMediaTypes []string
enableBuiltinGitConfig bool
)
command := cobra.Command{
Use: cliName,
@@ -155,6 +156,7 @@ func NewCommand() *cobra.Command {
IncludeHiddenDirectories: includeHiddenDirectories,
CMPUseManifestGeneratePaths: cmpUseManifestGeneratePaths,
OCIMediaTypes: ociMediaTypes,
EnableBuiltinGitConfig: enableBuiltinGitConfig,
}, askPassServer)
errors.CheckError(err)
@@ -264,6 +266,7 @@ func NewCommand() *cobra.Command {
command.Flags().BoolVar(&includeHiddenDirectories, "include-hidden-directories", env.ParseBoolFromEnv("ARGOCD_REPO_SERVER_INCLUDE_HIDDEN_DIRECTORIES", false), "Include hidden directories from Git")
command.Flags().BoolVar(&cmpUseManifestGeneratePaths, "plugin-use-manifest-generate-paths", env.ParseBoolFromEnv("ARGOCD_REPO_SERVER_PLUGIN_USE_MANIFEST_GENERATE_PATHS", false), "Pass the resources described in argocd.argoproj.io/manifest-generate-paths value to the cmpserver to generate the application manifests.")
command.Flags().StringSliceVar(&ociMediaTypes, "oci-layer-media-types", env.StringsFromEnv("ARGOCD_REPO_SERVER_OCI_LAYER_MEDIA_TYPES", []string{"application/vnd.oci.image.layer.v1.tar", "application/vnd.oci.image.layer.v1.tar+gzip", "application/vnd.cncf.helm.chart.content.v1.tar+gzip"}, ","), "Comma separated list of allowed media types for OCI media types. This only accounts for media types within layers.")
command.Flags().BoolVar(&enableBuiltinGitConfig, "enable-builtin-git-config", env.ParseBoolFromEnv("ARGOCD_REPO_SERVER_ENABLE_BUILTIN_GIT_CONFIG", true), "Enable builtin git configuration options that are required for correct argocd-repo-server operation.")
tlsConfigCustomizerSrc = tls.AddTLSFlagsToCmd(&command)
cacheSrc = reposervercache.AddCacheFlagsToCmd(&command, cacheutil.Options{
OnClientCreated: func(client *redis.Client) {

View File

@@ -2,7 +2,6 @@ package controller
import (
"context"
"encoding/json"
stderrors "errors"
"fmt"
"os"
@@ -263,7 +262,7 @@ func (m *appStateManager) SyncAppState(app *v1alpha1.Application, project *v1alp
// resources which in this case applies the live values in the configured
// ignore differences fields.
if syncOp.SyncOptions.HasOption("RespectIgnoreDifferences=true") {
patchedTargets, err := normalizeTargetResources(openAPISchema, compareResult)
patchedTargets, err := normalizeTargetResources(compareResult)
if err != nil {
state.Phase = common.OperationError
state.Message = fmt.Sprintf("Failed to normalize target resources: %s", err)
@@ -435,65 +434,53 @@ func (m *appStateManager) SyncAppState(app *v1alpha1.Application, project *v1alp
// - applies normalization to the target resources based on the live resources
// - copies ignored fields from the matching live resources: apply normalizer to the live resource,
// calculates the patch performed by normalizer and applies the patch to the target resource
func normalizeTargetResources(openAPISchema openapi.Resources, cr *comparisonResult) ([]*unstructured.Unstructured, error) {
// Normalize live and target resources (cleaning or aligning them)
func normalizeTargetResources(cr *comparisonResult) ([]*unstructured.Unstructured, error) {
// normalize live and target resources
normalized, err := diff.Normalize(cr.reconciliationResult.Live, cr.reconciliationResult.Target, cr.diffConfig)
if err != nil {
return nil, err
}
patchedTargets := []*unstructured.Unstructured{}
for idx, live := range cr.reconciliationResult.Live {
normalizedTarget := normalized.Targets[idx]
if normalizedTarget == nil {
patchedTargets = append(patchedTargets, nil)
continue
}
gvk := normalizedTarget.GroupVersionKind()
originalTarget := cr.reconciliationResult.Target[idx]
if live == nil {
// No live resource, just use target
patchedTargets = append(patchedTargets, originalTarget)
continue
}
var (
lookupPatchMeta strategicpatch.LookupPatchMeta
versionedObject any
)
// Load patch meta struct or OpenAPI schema for CRDs
if versionedObject, err = scheme.Scheme.New(gvk); err == nil {
if lookupPatchMeta, err = strategicpatch.NewPatchMetaFromStruct(versionedObject); err != nil {
var lookupPatchMeta *strategicpatch.PatchMetaFromStruct
versionedObject, err := scheme.Scheme.New(normalizedTarget.GroupVersionKind())
if err == nil {
meta, err := strategicpatch.NewPatchMetaFromStruct(versionedObject)
if err != nil {
return nil, err
}
} else if crdSchema := openAPISchema.LookupResource(gvk); crdSchema != nil {
lookupPatchMeta = strategicpatch.NewPatchMetaFromOpenAPI(crdSchema)
lookupPatchMeta = &meta
}
// Calculate live patch
livePatch, err := getMergePatch(normalized.Lives[idx], live, lookupPatchMeta)
if err != nil {
return nil, err
}
// Apply the patch to the normalized target
// This ensures ignored fields in live are restored into the target before syncing
normalizedTarget, err = applyMergePatch(normalizedTarget, livePatch, versionedObject, lookupPatchMeta)
normalizedTarget, err = applyMergePatch(normalizedTarget, livePatch, versionedObject)
if err != nil {
return nil, err
}
patchedTargets = append(patchedTargets, normalizedTarget)
}
return patchedTargets, nil
}
// getMergePatch calculates and returns the patch between the original and the
// modified unstructures.
func getMergePatch(original, modified *unstructured.Unstructured, lookupPatchMeta strategicpatch.LookupPatchMeta) ([]byte, error) {
func getMergePatch(original, modified *unstructured.Unstructured, lookupPatchMeta *strategicpatch.PatchMetaFromStruct) ([]byte, error) {
originalJSON, err := original.MarshalJSON()
if err != nil {
return nil, err
@@ -509,35 +496,18 @@ func getMergePatch(original, modified *unstructured.Unstructured, lookupPatchMet
return jsonpatch.CreateMergePatch(originalJSON, modifiedJSON)
}
// applyMergePatch will apply the given patch in the obj and return the patched unstructure.
func applyMergePatch(obj *unstructured.Unstructured, patch []byte, versionedObject any, meta strategicpatch.LookupPatchMeta) (*unstructured.Unstructured, error) {
// applyMergePatch will apply the given patch in the obj and return the patched
// unstructure.
func applyMergePatch(obj *unstructured.Unstructured, patch []byte, versionedObject any) (*unstructured.Unstructured, error) {
originalJSON, err := obj.MarshalJSON()
if err != nil {
return nil, err
}
var patchedJSON []byte
switch {
case versionedObject != nil:
patchedJSON, err = strategicpatch.StrategicMergePatch(originalJSON, patch, versionedObject)
case meta != nil:
var originalMap, patchMap map[string]any
if err := json.Unmarshal(originalJSON, &originalMap); err != nil {
return nil, err
}
if err := json.Unmarshal(patch, &patchMap); err != nil {
return nil, err
}
patchedMap, err := strategicpatch.StrategicMergeMapPatchUsingLookupPatchMeta(originalMap, patchMap, meta)
if err != nil {
return nil, err
}
patchedJSON, err = json.Marshal(patchedMap)
if err != nil {
return nil, err
}
default:
if versionedObject == nil {
patchedJSON, err = jsonpatch.MergePatch(originalJSON, patch)
} else {
patchedJSON, err = strategicpatch.StrategicMergePatch(originalJSON, patch, versionedObject)
}
if err != nil {
return nil, err

View File

@@ -1,17 +1,9 @@
package controller
import (
"fmt"
"os"
"strconv"
"testing"
openapi_v2 "github.com/google/gnostic-models/openapiv2"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/kubectl/pkg/util/openapi"
"sigs.k8s.io/yaml"
"github.com/argoproj/gitops-engine/pkg/sync"
synccommon "github.com/argoproj/gitops-engine/pkg/sync/common"
"github.com/argoproj/gitops-engine/pkg/utils/kube"
@@ -31,29 +23,6 @@ import (
"github.com/argoproj/argo-cd/v3/util/argo/normalizers"
)
type fakeDiscovery struct {
schema *openapi_v2.Document
}
func (f *fakeDiscovery) OpenAPISchema() (*openapi_v2.Document, error) {
return f.schema, nil
}
func loadCRDSchema(t *testing.T, path string) *openapi_v2.Document {
t.Helper()
data, err := os.ReadFile(path)
require.NoError(t, err)
jsonData, err := yaml.YAMLToJSON(data)
require.NoError(t, err)
doc, err := openapi_v2.ParseDocument(jsonData)
require.NoError(t, err)
return doc
}
func TestPersistRevisionHistory(t *testing.T) {
app := newFakeApp()
app.Status.OperationState = nil
@@ -416,7 +385,7 @@ func TestNormalizeTargetResources(t *testing.T) {
f := setup(t, ignores)
// when
targets, err := normalizeTargetResources(nil, f.comparisonResult)
targets, err := normalizeTargetResources(f.comparisonResult)
// then
require.NoError(t, err)
@@ -429,7 +398,7 @@ func TestNormalizeTargetResources(t *testing.T) {
f := setup(t, []v1alpha1.ResourceIgnoreDifferences{})
// when
targets, err := normalizeTargetResources(nil, f.comparisonResult)
targets, err := normalizeTargetResources(f.comparisonResult)
// then
require.NoError(t, err)
@@ -449,7 +418,7 @@ func TestNormalizeTargetResources(t *testing.T) {
unstructured.RemoveNestedField(live.Object, "metadata", "annotations", "iksm-version")
// when
targets, err := normalizeTargetResources(nil, f.comparisonResult)
targets, err := normalizeTargetResources(f.comparisonResult)
// then
require.NoError(t, err)
@@ -474,7 +443,7 @@ func TestNormalizeTargetResources(t *testing.T) {
f := setup(t, ignores)
// when
targets, err := normalizeTargetResources(nil, f.comparisonResult)
targets, err := normalizeTargetResources(f.comparisonResult)
// then
require.NoError(t, err)
@@ -489,6 +458,7 @@ func TestNormalizeTargetResources(t *testing.T) {
assert.Equal(t, int64(4), replicas)
})
t.Run("will keep new array entries not found in live state if not ignored", func(t *testing.T) {
t.Skip("limitation in the current implementation")
// given
ignores := []v1alpha1.ResourceIgnoreDifferences{
{
@@ -502,7 +472,7 @@ func TestNormalizeTargetResources(t *testing.T) {
f.comparisonResult.reconciliationResult.Target = []*unstructured.Unstructured{target}
// when
targets, err := normalizeTargetResources(nil, f.comparisonResult)
targets, err := normalizeTargetResources(f.comparisonResult)
// then
require.NoError(t, err)
@@ -539,11 +509,6 @@ func TestNormalizeTargetResourcesWithList(t *testing.T) {
}
t.Run("will properly ignore nested fields within arrays", func(t *testing.T) {
doc := loadCRDSchema(t, "testdata/schemas/httpproxy_openapi_v2.yaml")
disco := &fakeDiscovery{schema: doc}
oapiGetter := openapi.NewOpenAPIGetter(disco)
oapiResources, err := openapi.NewOpenAPIParser(oapiGetter).Parse()
require.NoError(t, err)
// given
ignores := []v1alpha1.ResourceIgnoreDifferences{
{
@@ -557,11 +522,8 @@ func TestNormalizeTargetResourcesWithList(t *testing.T) {
target := test.YamlToUnstructured(testdata.TargetHTTPProxy)
f.comparisonResult.reconciliationResult.Target = []*unstructured.Unstructured{target}
gvk := schema.GroupVersionKind{Group: "projectcontour.io", Version: "v1", Kind: "HTTPProxy"}
fmt.Printf("LookupResource result: %+v\n", oapiResources.LookupResource(gvk))
// when
patchedTargets, err := normalizeTargetResources(oapiResources, f.comparisonResult)
patchedTargets, err := normalizeTargetResources(f.comparisonResult)
// then
require.NoError(t, err)
@@ -600,7 +562,7 @@ func TestNormalizeTargetResourcesWithList(t *testing.T) {
f.comparisonResult.reconciliationResult.Target = []*unstructured.Unstructured{target}
// when
targets, err := normalizeTargetResources(nil, f.comparisonResult)
targets, err := normalizeTargetResources(f.comparisonResult)
// then
require.NoError(t, err)
@@ -652,7 +614,7 @@ func TestNormalizeTargetResourcesWithList(t *testing.T) {
f.comparisonResult.reconciliationResult.Target = []*unstructured.Unstructured{target}
// when
targets, err := normalizeTargetResources(nil, f.comparisonResult)
targets, err := normalizeTargetResources(f.comparisonResult)
// then
require.NoError(t, err)
@@ -706,175 +668,6 @@ func TestNormalizeTargetResourcesWithList(t *testing.T) {
assert.Equal(t, "EV", env0["name"])
assert.Equal(t, "here", env0["value"])
})
t.Run("patches ignored differences in individual array elements of HTTPProxy CRD", func(t *testing.T) {
doc := loadCRDSchema(t, "testdata/schemas/httpproxy_openapi_v2.yaml")
disco := &fakeDiscovery{schema: doc}
oapiGetter := openapi.NewOpenAPIGetter(disco)
oapiResources, err := openapi.NewOpenAPIParser(oapiGetter).Parse()
require.NoError(t, err)
ignores := []v1alpha1.ResourceIgnoreDifferences{
{
Group: "projectcontour.io",
Kind: "HTTPProxy",
JQPathExpressions: []string{".spec.routes[].rateLimitPolicy.global.descriptors[].entries[]"},
},
}
f := setupHTTPProxy(t, ignores)
target := test.YamlToUnstructured(testdata.TargetHTTPProxy)
f.comparisonResult.reconciliationResult.Target = []*unstructured.Unstructured{target}
live := test.YamlToUnstructured(testdata.LiveHTTPProxy)
f.comparisonResult.reconciliationResult.Live = []*unstructured.Unstructured{live}
patchedTargets, err := normalizeTargetResources(oapiResources, f.comparisonResult)
require.NoError(t, err)
require.Len(t, patchedTargets, 1)
patched := patchedTargets[0]
// verify descriptors array in patched target
descriptors := dig(patched.Object, "spec", "routes", 0, "rateLimitPolicy", "global", "descriptors").([]any)
require.Len(t, descriptors, 1) // Only the descriptors with ignored entries should remain
// verify individual entries array inside the descriptor
entriesArr := dig(patched.Object, "spec", "routes", 0, "rateLimitPolicy", "global", "descriptors", 0, "entries").([]any)
require.Len(t, entriesArr, 1) // Only the ignored entry should be patched
// verify the content of the entry is preserved correctly
entry := entriesArr[0].(map[string]any)
requestHeader := entry["requestHeader"].(map[string]any)
assert.Equal(t, "sample-header", requestHeader["headerName"])
assert.Equal(t, "sample-key", requestHeader["descriptorKey"])
})
}
func TestNormalizeTargetResourcesCRDs(t *testing.T) {
type fixture struct {
comparisonResult *comparisonResult
}
setupHTTPProxy := func(t *testing.T, ignores []v1alpha1.ResourceIgnoreDifferences) *fixture {
t.Helper()
dc, err := diff.NewDiffConfigBuilder().
WithDiffSettings(ignores, nil, true, normalizers.IgnoreNormalizerOpts{}).
WithNoCache().
Build()
require.NoError(t, err)
live := test.YamlToUnstructured(testdata.SimpleAppLiveYaml)
target := test.YamlToUnstructured(testdata.SimpleAppTargetYaml)
return &fixture{
&comparisonResult{
reconciliationResult: sync.ReconciliationResult{
Live: []*unstructured.Unstructured{live},
Target: []*unstructured.Unstructured{target},
},
diffConfig: dc,
},
}
}
t.Run("sample-app", func(t *testing.T) {
doc := loadCRDSchema(t, "testdata/schemas/simple-app.yaml")
disco := &fakeDiscovery{schema: doc}
oapiGetter := openapi.NewOpenAPIGetter(disco)
oapiResources, err := openapi.NewOpenAPIParser(oapiGetter).Parse()
require.NoError(t, err)
ignores := []v1alpha1.ResourceIgnoreDifferences{
{
Group: "example.com",
Kind: "SimpleApp",
JQPathExpressions: []string{".spec.servers[1].enabled", ".spec.servers[0].port"},
},
}
f := setupHTTPProxy(t, ignores)
target := test.YamlToUnstructured(testdata.SimpleAppTargetYaml)
f.comparisonResult.reconciliationResult.Target = []*unstructured.Unstructured{target}
live := test.YamlToUnstructured(testdata.SimpleAppLiveYaml)
f.comparisonResult.reconciliationResult.Live = []*unstructured.Unstructured{live}
patchedTargets, err := normalizeTargetResources(oapiResources, f.comparisonResult)
require.NoError(t, err)
require.Len(t, patchedTargets, 1)
patched := patchedTargets[0]
require.NotNil(t, patched)
// 'spec.servers' array has length 2
servers := dig(patched.Object, "spec", "servers").([]any)
require.Len(t, servers, 2)
// first server's 'name' is 'server1'
name1 := dig(patched.Object, "spec", "servers", 0, "name").(string)
assert.Equal(t, "server1", name1)
assert.Equal(t, int64(8081), dig(patched.Object, "spec", "servers", 0, "port").(int64))
assert.Equal(t, int64(9090), dig(patched.Object, "spec", "servers", 1, "port").(int64))
// first server's 'enabled' should be true
enabled1 := dig(patched.Object, "spec", "servers", 0, "enabled").(bool)
assert.True(t, enabled1)
// second server's 'name' should be 'server2'
name2 := dig(patched.Object, "spec", "servers", 1, "name").(string)
assert.Equal(t, "server2", name2)
// second server's 'enabled' should be true (respected from live due to ignoreDifferences)
enabled2 := dig(patched.Object, "spec", "servers", 1, "enabled").(bool)
assert.True(t, enabled2)
})
t.Run("rollout-obj", func(t *testing.T) {
// Load Rollout CRD schema like SimpleApp
doc := loadCRDSchema(t, "testdata/schemas/rollout-schema.yaml")
disco := &fakeDiscovery{schema: doc}
oapiGetter := openapi.NewOpenAPIGetter(disco)
oapiResources, err := openapi.NewOpenAPIParser(oapiGetter).Parse()
require.NoError(t, err)
ignores := []v1alpha1.ResourceIgnoreDifferences{
{
Group: "argoproj.io",
Kind: "Rollout",
JQPathExpressions: []string{`.spec.template.spec.containers[] | select(.name == "init") | .image`},
},
}
f := setupHTTPProxy(t, ignores)
live := test.YamlToUnstructured(testdata.LiveRolloutYaml)
target := test.YamlToUnstructured(testdata.TargetRolloutYaml)
f.comparisonResult.reconciliationResult.Live = []*unstructured.Unstructured{live}
f.comparisonResult.reconciliationResult.Target = []*unstructured.Unstructured{target}
targets, err := normalizeTargetResources(oapiResources, f.comparisonResult)
require.NoError(t, err)
require.Len(t, targets, 1)
patched := targets[0]
require.NotNil(t, patched)
containers := dig(patched.Object, "spec", "template", "spec", "containers").([]any)
require.Len(t, containers, 2)
initContainer := containers[0].(map[string]any)
mainContainer := containers[1].(map[string]any)
// Assert init container image is preserved (ignoreDifferences works)
initImage := dig(initContainer, "image").(string)
assert.Equal(t, "init-container:v1", initImage)
// Assert main container fields as expected
mainName := dig(mainContainer, "name").(string)
assert.Equal(t, "main", mainName)
mainImage := dig(mainContainer, "image").(string)
assert.Equal(t, "main-container:v1", mainImage)
})
}
func TestDeriveServiceAccountMatchingNamespaces(t *testing.T) {

View File

@@ -32,16 +32,4 @@ var (
//go:embed additional-image-replicas-deployment.yaml
AdditionalImageReplicaDeploymentYaml string
//go:embed simple-app-live.yaml
SimpleAppLiveYaml string
//go:embed simple-app-target.yaml
SimpleAppTargetYaml string
//go:embed target-rollout.yaml
TargetRolloutYaml string
//go:embed live-rollout.yaml
LiveRolloutYaml string
)

View File

@@ -1,25 +0,0 @@
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: rollout-sample
spec:
replicas: 2
strategy:
canary:
steps:
- setWeight: 20
selector:
matchLabels:
app: rollout-sample
template:
metadata:
labels:
app: rollout-sample
spec:
containers:
- name: init
image: init-container:v1
livenessProbe:
initialDelaySeconds: 10
- name: main
image: main-container:v1

View File

@@ -1,62 +0,0 @@
swagger: "2.0"
info:
title: HTTPProxy
version: "v1"
paths: {}
definitions:
io.projectcontour.v1.HTTPProxy:
type: object
x-kubernetes-group-version-kind:
- group: projectcontour.io
version: v1
kind: HTTPProxy
properties:
spec:
type: object
properties:
routes:
type: array
items:
type: object
properties:
rateLimitPolicy:
type: object
properties:
global:
type: object
properties:
descriptors:
type: array
x-kubernetes-list-map-keys:
- entries
items:
type: object
properties:
entries:
type: array
x-kubernetes-list-map-keys:
- headerName
items:
type: object
properties:
requestHeader:
type: object
properties:
descriptorKey:
type: string
headerName:
type: string
requestHeaderValueMatch:
type: object
properties:
headers:
type: array
items:
type: object
properties:
name:
type: string
contains:
type: string
value:
type: string

View File

@@ -1,67 +0,0 @@
swagger: "2.0"
info:
title: Rollout
version: "v1alpha1"
paths: {}
definitions:
argoproj.io.v1alpha1.Rollout:
type: object
x-kubernetes-group-version-kind:
- group: argoproj.io
version: v1alpha1
kind: Rollout
properties:
spec:
type: object
properties:
replicas:
type: integer
strategy:
type: object
properties:
canary:
type: object
properties:
steps:
type: array
items:
type: object
properties:
setWeight:
type: integer
selector:
type: object
properties:
matchLabels:
type: object
additionalProperties:
type: string
template:
type: object
properties:
metadata:
type: object
properties:
labels:
type: object
additionalProperties:
type: string
spec:
type: object
properties:
containers:
type: array
x-kubernetes-list-map-keys:
- name
items:
type: object
properties:
name:
type: string
image:
type: string
livenessProbe:
type: object
properties:
initialDelaySeconds:
type: integer

View File

@@ -1,29 +0,0 @@
swagger: "2.0"
info:
title: SimpleApp
version: "v1"
paths: {}
definitions:
example.com.v1.SimpleApp:
type: object
x-kubernetes-group-version-kind:
- group: example.com
version: v1
kind: SimpleApp
properties:
spec:
type: object
properties:
servers:
type: array
x-kubernetes-list-map-keys:
- name
items:
type: object
properties:
name:
type: string
port:
type: integer
enabled:
type: boolean

View File

@@ -1,12 +0,0 @@
apiVersion: example.com/v1
kind: SimpleApp
metadata:
name: simpleapp-sample
spec:
servers:
- name: server1
port: 8081 # port changed in live from 8080
enabled: true
- name: server2
port: 9090
enabled: true # enabled changed in live from false

View File

@@ -1,12 +0,0 @@
apiVersion: example.com/v1
kind: SimpleApp
metadata:
name: simpleapp-sample
spec:
servers:
- name: server1
port: 8080
enabled: true
- name: server2
port: 9090
enabled: false

View File

@@ -1,25 +0,0 @@
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: rollout-sample
spec:
replicas: 2
strategy:
canary:
steps:
- setWeight: 20
selector:
matchLabels:
app: rollout-sample
template:
metadata:
labels:
app: rollout-sample
spec:
containers:
- name: init
image: init-container:v1
livenessProbe:
initialDelaySeconds: 15
- name: main
image: main-container:v1

View File

@@ -219,6 +219,8 @@ data:
reposerver.git.lsremote.parallelism.limit: "0"
# Git requests timeout.
reposerver.git.request.timeout: "15s"
# Enable builtin git configuration options that are required for correct argocd-repo-server operation (default "true")
reposerver.enable.builtin.git.config: "true"
# Include hidden directories from Git
reposerver.include.hidden.directories: "false"

View File

@@ -121,6 +121,18 @@ spec:
...
```
### Deleting child applications
When working with the App of Apps pattern, you may need to delete individual child applications. Starting in 3.2, Argo CD provides consistent deletion behaviour whether you delete from the Applications List or from the parent application's Resource Tree.
For detailed information about deletion options and behaviour, including:
- Consistent deletion across UI views
- Non-cascading (orphan) deletion to preserve managed resources
- Child application detection and improved dialog messages
- Best practices and example scenarios
See [Deleting Applications in the UI](../user-guide/app_deletion.md#deleting-applications-in-the-ui).
### Ignoring differences in child applications
To allow changes in child apps without triggering an out-of-sync status, or modification for debugging etc, the app of apps pattern works with [diff customization](../user-guide/diffing/). The example below shows how to ignore changes to syncPolicy and other common values.

View File

@@ -0,0 +1,43 @@
# Git Configuration
## System Configuration
Argo CD uses the Git installation from its base image (Ubuntu), which
includes a standard system configuration file located at
`/etc/gitconfig`. This file is minimal, just defining filters
necessary for Git LFS functionality.
You can customize Git's system configuration by mounting a file from a
ConfigMap or by creating a custom Argo CD image.
## Global Configuration
Argo CD runs Git with the `HOME` environment variable set to
`/dev/null`. As a result, global Git configuration is not supported.
## Built-in Configuration
The `argocd-repo-server` adds specific configuration parameters to the
Git environment to ensure proper Argo CD operation. These built-in
settings override any conflicting values from the system Git
configuration.
Currently, the following built-in configuration options are set:
- `maintenance.autoDetach=false`
- `gc.autoDetach=false`
These settings force Git's repository maintenance tasks to run in the
foreground. This prevents Git from running detached background
processes that could modify the repository and interfere with
subsequent Git invocations from `argocd-repo-server`.
You can disable these built-in settings by setting the
`argocd-cmd-params-cm` value `reposerver.enable.builtin.git.config` to
`"false"`. This allows you to experiment with background processing or
if you are certain that concurrency issues will not occur in your
environment.
> [!NOTE]
> Disabling this is not recommended and is not supported!

View File

@@ -35,14 +35,26 @@ metadata:
name: argocd-notifications-cm
data:
trigger.sync-operation-change: |
- when: app.status.operationState.phase in ['Succeeded']
- when: app.status?.operationState.phase in ['Succeeded']
send: [github-commit-status]
- when: app.status.operationState.phase in ['Running']
- when: app.status?.operationState.phase in ['Running']
send: [github-commit-status]
- when: app.status.operationState.phase in ['Error', 'Failed']
- when: app.status?.operationState.phase in ['Error', 'Failed']
send: [app-sync-failed, github-commit-status]
```
## Accessing Optional Manifest Sections and Fields
Note that in the trigger example above, the `?.` (optional chaining) operator is used to access the Application's
`status.operationState` section. This section is optional; it is not present when an operation has been initiated but has not yet
started by the Application Controller.
If the `?.` operator were not used, `status.operationState` would resolve to `nil` and the evaluation of the
`app.status.operationState.phase` expression would fail. The `app.status?.operationState.phase` expression is equivalent to
`app.status.operationState != nil ? app.status.operationState.phase : nil`.
## Avoid Sending Same Notification Too Often
In some cases, the trigger condition might be "flapping". The example below illustrates the problem.
@@ -60,14 +72,14 @@ data:
# Optional 'oncePer' property ensure that notification is sent only once per specified field value
# E.g. following is triggered once per sync revision
trigger.on-deployed: |
when: app.status.operationState.phase in ['Succeeded'] and app.status.health.status == 'Healthy'
when: app.status?.operationState.phase in ['Succeeded'] and app.status.health.status == 'Healthy'
oncePer: app.status.sync.revision
send: [app-sync-succeeded]
```
**Mono Repo Usage**
When one repo is used to sync multiple applications, the `oncePer: app.status.sync.revision` field will trigger a notification for each commit. For mono repos, the better approach will be using `oncePer: app.status.operationState.syncResult.revision` statement. This way a notification will be sent only for a particular Application's revision.
When one repo is used to sync multiple applications, the `oncePer: app.status.sync.revision` field will trigger a notification for each commit. For mono repos, the better approach will be using `oncePer: app.status?.operationState.syncResult.revision` statement. This way a notification will be sent only for a particular Application's revision.
### oncePer
@@ -122,7 +134,7 @@ Triggers have access to the set of built-in functions.
Example:
```yaml
when: time.Now().Sub(time.Parse(app.status.operationState.startedAt)).Minutes() >= 5
when: time.Now().Sub(time.Parse(app.status?.operationState.startedAt)).Minutes() >= 5
```
{!docs/operator-manual/notifications/functions.md!}

View File

@@ -21,6 +21,7 @@ argocd-repo-server [flags]
--disable-helm-manifest-max-extracted-size Disable maximum size of helm manifest archives when extracted
--disable-oci-manifest-max-extracted-size Disable maximum size of oci manifest archives when extracted
--disable-tls Disable TLS on the gRPC endpoint
--enable-builtin-git-config Enable builtin git configuration options that are required for correct argocd-repo-server operation. (default true)
--helm-manifest-max-extracted-size string Maximum size of helm manifest archives when extracted (default "1G")
--helm-registry-max-index-size string Maximum size of registry index file (default "1G")
-h, --help help for argocd-repo-server

View File

@@ -288,6 +288,9 @@ 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.
After upgrading to version 3.0, the Argo CD tracking annotation will only appear on an Applications resources when
either a new Git commit is made or the Application is explicitly synced.
##### 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
@@ -497,4 +500,4 @@ More details for ignored resource updates in the [Diffing customization](../../u
Due to security reasons ([GHSA-786q-9hcg-v9ff](https://github.com/argoproj/argo-cd/security/advisories/GHSA-786q-9hcg-v9ff)),
the project API response was sanitized to remove sensitive information. This includes
credentials of project-scoped repositories and clusters.
credentials of project-scoped repositories and clusters.

View File

@@ -58,3 +58,120 @@ Argo CD performs [background cascading deletion](https://kubernetes.io/docs/conc
When you invoke `argocd app delete` with `--cascade`, the finalizer is added automatically.
You can set the propagation policy with `--propagation-policy <foreground|background>`.
## Deleting Applications in the UI
Argo CD provides a consistent deletion experience across different views in the UI. When deleting applications, you can access the delete functionality from:
- **Applications List View**: The main applications page showing all applications
- **Application Details View - Resource Tree**: When viewing an application's resource tree that contains child applications
### Consistent Deletion Behaviour
Starting in Argo CD 3.2, deletion behavior is now **consistent** across all UI views. Whether you delete an application from the Applications List or from the Resource Tree view, the same deletion mechanism and options are used.
Previously, deleting an application from the Resource Tree treated it as a generic Kubernetes resource, which could lead to unexpected behaviour with non-cascading deletes. Now, Argo CD properly detects Application resources and uses the standard Application deletion API in all contexts.
### Deleting Child Applications in App of Apps Pattern
When using the [App of Apps pattern](../operator-manual/cluster-bootstrapping.md), parent applications can contain child applications as resources. Argo CD automatically detects child applications and provides improved dialog messages to help you understand what you're deleting.
#### Child Application Detection
Argo CD identifies a child application by checking for the `app.kubernetes.io/part-of` label. If this label is present and has a non-empty value, the application is considered a child application.
#### Delete Dialog Differences
**When deleting a child application:**
- Dialog title: "Delete child application"
- Confirmation prompt references "child application" to make it clear you're deleting a managed application
- Additional warning note appears when deleting from the Resource Tree
**When deleting a regular application:**
- Dialog title: "Delete application"
- Standard confirmation prompt
**When deleting from the Resource Tree:**
An additional informational note appears:
> ⚠️ **Note:** You are about to delete an Application from the resource tree. This uses the same deletion behaviour as the Applications list page.
This note clarifies that the deletion will use the proper Application deletion API, not generic Kubernetes resource deletion.
### Deletion Options (Propagation Policies)
When deleting an application through the UI, you can choose from three propagation policies:
#### 1. Foreground (Default)
- Deletes the application and all its managed resources
- Waits for all managed resources to be deleted before the Application is removed
- **Use case**: When you want to ensure all resources are cleaned up before the Application disappears
#### 2. Background
- Deletes the application and all its managed resources
- The Application is removed immediately, and resources are deleted in the background
- **Use case**: When you want faster Application deletion and don't need to wait for resource cleanup
#### 3. Non-Cascading (Orphan)
- Deletes **only** the Application resource
- All managed resources (Deployments, Services, ConfigMaps, etc.) are **preserved** in the cluster
- The finalizer is removed automatically before deletion
- **Use case**: When you want to stop managing resources through Argo CD but keep them running
> [!WARNING]
> **Important for Non-Cascading Deletes**
>
> When you select **Non-Cascading**, Argo CD will:
> - Remove the `resources-finalizer.argocd.argoproj.io` finalizer from the Application
> - Delete only the Application resource
> - Leave all managed resources (Pods, Services, Deployments, etc.) running in the cluster
>
> This behaviour is now **consistent** whether you delete from the Applications List or from the Resource Tree view.
### Best Practices for App of Apps Pattern
When working with the App of Apps pattern:
1. **Understand the impact**: Deleting a child application with Foreground or Background propagation will delete all of its managed resources
2. **Review before deleting**: Always verify what resources are managed by the application before performing a cascading delete
3. **Use Non-Cascading cautiously**: If you only want to remove the Application resource but keep the deployed workloads, use Non-Cascading delete
4. **Consider finalizers**: Ensure child applications have appropriate finalizers set based on your deletion strategy (see [Cascading Deletion](../operator-manual/cluster-bootstrapping.md#cascading-deletion))
### Example Scenarios
#### Scenario 1: Deleting a child application and all its resources
1. Navigate to the parent application's Resource Tree
2. Click the kebab menu (button with the three vertical dots) on a child Application resource
3. Select "Delete"
4. Choose **Foreground** or **Background** propagation policy
5. Confirm the deletion
**Result**: The child Application and all its managed resources (Deployments, Services, etc.) are deleted.
#### Scenario 2: Removing Argo CD management but keeping resources
1. Navigate to the Applications List or the parent application's Resource Tree
2. Click the kebab menu (button with the three vertical dots) on a child Application resource
3. Select "Delete"
4. Choose **Non-Cascading** propagation policy
5. Confirm the deletion
**Result**: Only the Application resource is deleted. All managed resources continue running in the cluster.
#### Scenario 3: Deleting from Resource Tree with context awareness
When you delete a child application from the Resource Tree view:
- Argo CD recognizes it as an Application resource (not just a generic Kubernetes resource)
- Shows "Delete child application" dialog if it detects the `app.kubernetes.io/part-of` label
- Displays an informational note explaining you're using the same behaviour as the Applications List
- Provides the same three propagation policy options
This ensures predictable and consistent deletion behaviour regardless of where you initiate the deletion.

4
go.mod
View File

@@ -12,7 +12,7 @@ require (
github.com/Masterminds/sprig/v3 v3.3.0
github.com/TomOnTime/utfutil v1.0.0
github.com/alicebob/miniredis/v2 v2.35.0
github.com/argoproj/gitops-engine v0.7.1-0.20251006172252-b89b0871b414
github.com/argoproj/gitops-engine v0.7.1-0.20251108235403-13d5172d3ee2
github.com/argoproj/notifications-engine v0.4.1-0.20250908182349-da04400446ff
github.com/argoproj/pkg v0.13.6
github.com/argoproj/pkg/v2 v2.0.1
@@ -47,7 +47,7 @@ require (
github.com/golang-jwt/jwt/v5 v5.3.0
github.com/golang/protobuf v1.5.4
github.com/google/btree v1.1.3
github.com/google/gnostic-models v0.7.0
github.com/google/gnostic-models v0.7.0 // indirect
github.com/google/go-cmp v0.7.0
github.com/google/go-github/v69 v69.2.0
github.com/google/go-jsonnet v0.21.0

4
go.sum
View File

@@ -113,8 +113,8 @@ github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFI
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/appscode/go v0.0.0-20191119085241-0887d8ec2ecc/go.mod h1:OawnOmAL4ZX3YaPdN+8HTNwBveT1jMsqP74moa9XUbE=
github.com/argoproj/gitops-engine v0.7.1-0.20251006172252-b89b0871b414 h1:2w1vd2VZja7Mlf/rblJkp6/Eq8fNDuM7p6pI4PTAJhg=
github.com/argoproj/gitops-engine v0.7.1-0.20251006172252-b89b0871b414/go.mod h1:2nqYZBhj8CfVZb3ATakZpi1KNb/yc7mpadIHslicTFI=
github.com/argoproj/gitops-engine v0.7.1-0.20251108235403-13d5172d3ee2 h1:g9XclEd+1mYQtpLL3rMgYbMUdB3kEppw3+Jd1/H54VM=
github.com/argoproj/gitops-engine v0.7.1-0.20251108235403-13d5172d3ee2/go.mod h1:2nqYZBhj8CfVZb3ATakZpi1KNb/yc7mpadIHslicTFI=
github.com/argoproj/notifications-engine v0.4.1-0.20250908182349-da04400446ff h1:pGGAeHIktPuYCRl1Z540XdxPFnedqyUhJK4VgpyJZfY=
github.com/argoproj/notifications-engine v0.4.1-0.20250908182349-da04400446ff/go.mod h1:d1RazGXWvKRFv9//rg4MRRR7rbvbE7XLgTSMT5fITTE=
github.com/argoproj/pkg v0.13.6 h1:36WPD9MNYECHcO1/R1pj6teYspiK7uMQLCgLGft2abM=

View File

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

View File

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

View File

@@ -239,6 +239,12 @@ spec:
key: reposerver.git.request.timeout
name: argocd-cmd-params-cm
optional: true
- name: ARGOCD_REPO_SERVER_ENABLE_BUILTIN_GIT_CONFIG
valueFrom:
configMapKeyRef:
name: argocd-cmd-params-cm
key: reposerver.enable.builtin.git.config
optional: true
- name: ARGOCD_GRPC_MAX_SIZE_MB
valueFrom:
configMapKeyRef:

View File

@@ -24850,7 +24850,7 @@ spec:
key: applicationsetcontroller.status.max.resources.count
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -24985,7 +24985,7 @@ spec:
key: log.format.timestamp
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -25113,7 +25113,7 @@ spec:
- argocd
- admin
- redis-initial-password
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: IfNotPresent
name: secret-init
securityContext:
@@ -25386,6 +25386,12 @@ spec:
key: reposerver.git.request.timeout
name: argocd-cmd-params-cm
optional: true
- name: ARGOCD_REPO_SERVER_ENABLE_BUILTIN_GIT_CONFIG
valueFrom:
configMapKeyRef:
key: reposerver.enable.builtin.git.config
name: argocd-cmd-params-cm
optional: true
- name: ARGOCD_GRPC_MAX_SIZE_MB
valueFrom:
configMapKeyRef:
@@ -25404,7 +25410,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -25456,7 +25462,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -25804,7 +25810,7 @@ spec:
optional: true
- name: KUBECACHEDIR
value: /tmp/kubecache
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -24818,7 +24818,7 @@ spec:
key: applicationsetcontroller.status.max.resources.count
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -24947,7 +24947,7 @@ spec:
- argocd
- admin
- redis-initial-password
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: IfNotPresent
name: secret-init
securityContext:
@@ -25220,6 +25220,12 @@ spec:
key: reposerver.git.request.timeout
name: argocd-cmd-params-cm
optional: true
- name: ARGOCD_REPO_SERVER_ENABLE_BUILTIN_GIT_CONFIG
valueFrom:
configMapKeyRef:
key: reposerver.enable.builtin.git.config
name: argocd-cmd-params-cm
optional: true
- name: ARGOCD_GRPC_MAX_SIZE_MB
valueFrom:
configMapKeyRef:
@@ -25238,7 +25244,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -25290,7 +25296,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -25638,7 +25644,7 @@ spec:
optional: true
- name: KUBECACHEDIR
value: /tmp/kubecache
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

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

View File

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

View File

@@ -26216,7 +26216,7 @@ spec:
key: applicationsetcontroller.status.max.resources.count
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -26351,7 +26351,7 @@ spec:
key: log.format.timestamp
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -26502,7 +26502,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -26598,7 +26598,7 @@ spec:
key: notificationscontroller.repo.server.plaintext
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -26722,7 +26722,7 @@ spec:
- argocd
- admin
- redis-initial-password
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: IfNotPresent
name: secret-init
securityContext:
@@ -27021,6 +27021,12 @@ spec:
key: reposerver.git.request.timeout
name: argocd-cmd-params-cm
optional: true
- name: ARGOCD_REPO_SERVER_ENABLE_BUILTIN_GIT_CONFIG
valueFrom:
configMapKeyRef:
key: reposerver.enable.builtin.git.config
name: argocd-cmd-params-cm
optional: true
- name: ARGOCD_GRPC_MAX_SIZE_MB
valueFrom:
configMapKeyRef:
@@ -27039,7 +27045,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -27091,7 +27097,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -27465,7 +27471,7 @@ spec:
key: server.sync.replace.allowed
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -27849,7 +27855,7 @@ spec:
optional: true
- name: KUBECACHEDIR
value: /tmp/kubecache
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -26186,7 +26186,7 @@ spec:
key: applicationsetcontroller.status.max.resources.count
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -26338,7 +26338,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -26434,7 +26434,7 @@ spec:
key: notificationscontroller.repo.server.plaintext
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -26558,7 +26558,7 @@ spec:
- argocd
- admin
- redis-initial-password
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: IfNotPresent
name: secret-init
securityContext:
@@ -26857,6 +26857,12 @@ spec:
key: reposerver.git.request.timeout
name: argocd-cmd-params-cm
optional: true
- name: ARGOCD_REPO_SERVER_ENABLE_BUILTIN_GIT_CONFIG
valueFrom:
configMapKeyRef:
key: reposerver.enable.builtin.git.config
name: argocd-cmd-params-cm
optional: true
- name: ARGOCD_GRPC_MAX_SIZE_MB
valueFrom:
configMapKeyRef:
@@ -26875,7 +26881,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -26927,7 +26933,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -27301,7 +27307,7 @@ spec:
key: server.sync.replace.allowed
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -27685,7 +27691,7 @@ spec:
optional: true
- name: KUBECACHEDIR
value: /tmp/kubecache
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -1897,7 +1897,7 @@ spec:
key: applicationsetcontroller.status.max.resources.count
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -2032,7 +2032,7 @@ spec:
key: log.format.timestamp
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -2183,7 +2183,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -2279,7 +2279,7 @@ spec:
key: notificationscontroller.repo.server.plaintext
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -2403,7 +2403,7 @@ spec:
- argocd
- admin
- redis-initial-password
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: IfNotPresent
name: secret-init
securityContext:
@@ -2702,6 +2702,12 @@ spec:
key: reposerver.git.request.timeout
name: argocd-cmd-params-cm
optional: true
- name: ARGOCD_REPO_SERVER_ENABLE_BUILTIN_GIT_CONFIG
valueFrom:
configMapKeyRef:
key: reposerver.enable.builtin.git.config
name: argocd-cmd-params-cm
optional: true
- name: ARGOCD_GRPC_MAX_SIZE_MB
valueFrom:
configMapKeyRef:
@@ -2720,7 +2726,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -2772,7 +2778,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -3146,7 +3152,7 @@ spec:
key: server.sync.replace.allowed
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -3530,7 +3536,7 @@ spec:
optional: true
- name: KUBECACHEDIR
value: /tmp/kubecache
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -1867,7 +1867,7 @@ spec:
key: applicationsetcontroller.status.max.resources.count
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -2019,7 +2019,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -2115,7 +2115,7 @@ spec:
key: notificationscontroller.repo.server.plaintext
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -2239,7 +2239,7 @@ spec:
- argocd
- admin
- redis-initial-password
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: IfNotPresent
name: secret-init
securityContext:
@@ -2538,6 +2538,12 @@ spec:
key: reposerver.git.request.timeout
name: argocd-cmd-params-cm
optional: true
- name: ARGOCD_REPO_SERVER_ENABLE_BUILTIN_GIT_CONFIG
valueFrom:
configMapKeyRef:
key: reposerver.enable.builtin.git.config
name: argocd-cmd-params-cm
optional: true
- name: ARGOCD_GRPC_MAX_SIZE_MB
valueFrom:
configMapKeyRef:
@@ -2556,7 +2562,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -2608,7 +2614,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -2982,7 +2988,7 @@ spec:
key: server.sync.replace.allowed
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -3366,7 +3372,7 @@ spec:
optional: true
- name: KUBECACHEDIR
value: /tmp/kubecache
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -25294,7 +25294,7 @@ spec:
key: applicationsetcontroller.status.max.resources.count
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -25429,7 +25429,7 @@ spec:
key: log.format.timestamp
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -25580,7 +25580,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -25676,7 +25676,7 @@ spec:
key: notificationscontroller.repo.server.plaintext
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -25778,7 +25778,7 @@ spec:
- argocd
- admin
- redis-initial-password
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: IfNotPresent
name: secret-init
securityContext:
@@ -26051,6 +26051,12 @@ spec:
key: reposerver.git.request.timeout
name: argocd-cmd-params-cm
optional: true
- name: ARGOCD_REPO_SERVER_ENABLE_BUILTIN_GIT_CONFIG
valueFrom:
configMapKeyRef:
key: reposerver.enable.builtin.git.config
name: argocd-cmd-params-cm
optional: true
- name: ARGOCD_GRPC_MAX_SIZE_MB
valueFrom:
configMapKeyRef:
@@ -26069,7 +26075,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -26121,7 +26127,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -26493,7 +26499,7 @@ spec:
key: server.sync.replace.allowed
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -26877,7 +26883,7 @@ spec:
optional: true
- name: KUBECACHEDIR
value: /tmp/kubecache
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
name: argocd-application-controller
ports:

22
manifests/install.yaml generated
View File

@@ -25262,7 +25262,7 @@ spec:
key: applicationsetcontroller.status.max.resources.count
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -25414,7 +25414,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -25510,7 +25510,7 @@ spec:
key: notificationscontroller.repo.server.plaintext
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -25612,7 +25612,7 @@ spec:
- argocd
- admin
- redis-initial-password
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: IfNotPresent
name: secret-init
securityContext:
@@ -25885,6 +25885,12 @@ spec:
key: reposerver.git.request.timeout
name: argocd-cmd-params-cm
optional: true
- name: ARGOCD_REPO_SERVER_ENABLE_BUILTIN_GIT_CONFIG
valueFrom:
configMapKeyRef:
key: reposerver.enable.builtin.git.config
name: argocd-cmd-params-cm
optional: true
- name: ARGOCD_GRPC_MAX_SIZE_MB
valueFrom:
configMapKeyRef:
@@ -25903,7 +25909,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -25955,7 +25961,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -26327,7 +26333,7 @@ spec:
key: server.sync.replace.allowed
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -26711,7 +26717,7 @@ spec:
optional: true
- name: KUBECACHEDIR
value: /tmp/kubecache
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -975,7 +975,7 @@ spec:
key: applicationsetcontroller.status.max.resources.count
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -1110,7 +1110,7 @@ spec:
key: log.format.timestamp
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -1261,7 +1261,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -1357,7 +1357,7 @@ spec:
key: notificationscontroller.repo.server.plaintext
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -1459,7 +1459,7 @@ spec:
- argocd
- admin
- redis-initial-password
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: IfNotPresent
name: secret-init
securityContext:
@@ -1732,6 +1732,12 @@ spec:
key: reposerver.git.request.timeout
name: argocd-cmd-params-cm
optional: true
- name: ARGOCD_REPO_SERVER_ENABLE_BUILTIN_GIT_CONFIG
valueFrom:
configMapKeyRef:
key: reposerver.enable.builtin.git.config
name: argocd-cmd-params-cm
optional: true
- name: ARGOCD_GRPC_MAX_SIZE_MB
valueFrom:
configMapKeyRef:
@@ -1750,7 +1756,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -1802,7 +1808,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -2174,7 +2180,7 @@ spec:
key: server.sync.replace.allowed
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -2558,7 +2564,7 @@ spec:
optional: true
- name: KUBECACHEDIR
value: /tmp/kubecache
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -943,7 +943,7 @@ spec:
key: applicationsetcontroller.status.max.resources.count
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -1095,7 +1095,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -1191,7 +1191,7 @@ spec:
key: notificationscontroller.repo.server.plaintext
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -1293,7 +1293,7 @@ spec:
- argocd
- admin
- redis-initial-password
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: IfNotPresent
name: secret-init
securityContext:
@@ -1566,6 +1566,12 @@ spec:
key: reposerver.git.request.timeout
name: argocd-cmd-params-cm
optional: true
- name: ARGOCD_REPO_SERVER_ENABLE_BUILTIN_GIT_CONFIG
valueFrom:
configMapKeyRef:
key: reposerver.enable.builtin.git.config
name: argocd-cmd-params-cm
optional: true
- name: ARGOCD_GRPC_MAX_SIZE_MB
valueFrom:
configMapKeyRef:
@@ -1584,7 +1590,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -1636,7 +1642,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -2008,7 +2014,7 @@ spec:
key: server.sync.replace.allowed
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -2392,7 +2398,7 @@ spec:
optional: true
- name: KUBECACHEDIR
value: /tmp/kubecache
image: quay.io/argoproj/argocd:v3.2.0
image: quay.io/argoproj/argocd:v3.2.1
imagePullPolicy: Always
name: argocd-application-controller
ports:

View File

@@ -63,6 +63,7 @@ nav:
- operator-manual/web_based_terminal.md
- operator-manual/config-management-plugins.md
- operator-manual/deep_links.md
- operator-manual/git_configuration.md
- Notifications:
- Overview: operator-manual/notifications/index.md
- operator-manual/notifications/triggers.md

View File

@@ -117,6 +117,7 @@ type RepoServerInitConstants struct {
DisableHelmManifestMaxExtractedSize bool
IncludeHiddenDirectories bool
CMPUseManifestGeneratePaths bool
EnableBuiltinGitConfig bool
}
var manifestGenerateLock = sync.NewKeyLock()
@@ -2566,7 +2567,9 @@ func (s *Service) newClient(repo *v1alpha1.Repository, opts ...git.ClientOpts) (
if err != nil {
return nil, err
}
opts = append(opts, git.WithEventHandlers(metrics.NewGitClientEventHandlers(s.metricsServer)))
opts = append(opts,
git.WithEventHandlers(metrics.NewGitClientEventHandlers(s.metricsServer)),
git.WithBuiltinGitConfig(s.initConstants.EnableBuiltinGitConfig))
return s.newGitClient(repo.Repo, repoPath, repo.GetGitCreds(s.gitCredsStore), repo.IsInsecure(), repo.EnableLFS, repo.Proxy, repo.NoProxy, opts...)
}

View File

@@ -24,14 +24,23 @@ if obj.status ~= nil then
if obj.status.conditions ~= nil then
for i, condition in pairs(obj.status.conditions) do
-- Check if the InferenceService is Stopped
if condition.type == "Stopped" and condition.status == "True" then
health_status.status = "Suspended"
health_status.message = "InferenceService is Stopped"
return health_status
end
-- Check for unhealthy statuses
-- Note: The Stopped condition's healthy status is False
if condition.status == "Unknown" then
status_unknown = status_unknown + 1
elseif condition.status == "False" then
elseif condition.status == "False" and condition.type ~= "Stopped" then
status_false = status_false + 1
end
if condition.status ~= "True" then
-- Add the error messages if the status is unhealthy
if condition.status ~= "True" and condition.type ~= "Stopped" then
msg = msg .. " | " .. i .. ": " .. condition.type .. " | " .. condition.status
if condition.reason ~= nil and condition.reason ~= "" then
msg = msg .. " | " .. condition.reason

View File

@@ -23,6 +23,10 @@ tests:
status: Degraded
message: "0: transitionStatus | BlockedByFailedLoad"
inputPath: testdata/degraded_modelmesh.yaml
- healthStatus:
status: Suspended
message: InferenceService is Stopped
inputPath: testdata/stopped.yaml
- healthStatus:
status: Healthy
message: InferenceService is healthy.

View File

@@ -23,3 +23,7 @@ status:
- lastTransitionTime: "2023-06-20T22:44:51Z"
status: "True"
type: Ready
- lastTransitionTime: "2023-06-20T22:44:51Z"
severity: Info
status: 'False'
type: Stopped

View File

@@ -31,5 +31,9 @@ status:
severity: Info
status: 'True'
type: RoutesReady
- lastTransitionTime: '2024-05-30T22:14:31Z'
severity: Info
status: 'False'
type: Stopped
modelStatus:
transitionStatus: UpToDate

View File

@@ -17,3 +17,7 @@ status:
- lastTransitionTime: '2024-05-16T18:48:56Z'
status: 'True'
type: Ready
- lastTransitionTime: '2024-05-16T18:48:56Z'
severity: Info
status: 'False'
type: Stopped

View File

@@ -0,0 +1,23 @@
apiVersion: serving.kserve.io/v1beta1
kind: InferenceService
metadata:
name: helloworld
namespace: default
annotations:
serving.kserve.io/deploymentMode: RawDeployment
serving.kserve.io/stop: 'true'
spec: {}
status:
conditions:
- lastTransitionTime: '2024-05-16T18:48:56Z'
reason: Stopped
status: 'False'
type: PredictorReady
- lastTransitionTime: '2024-05-16T18:48:56Z'
reason: Stopped
status: 'False'
type: Ready
- lastTransitionTime: '2024-05-16T18:48:56Z'
severity: Info
status: 'True'
type: Stopped

View File

@@ -1,8 +1,7 @@
import * as React from 'react';
import Moment from 'react-moment';
import {Pod, ResourceName} from '../../../shared/models';
import {isYoungerThanXMinutes} from '../utils';
import {formatMetric} from './pod-view';
import {isYoungerThanXMinutes, formatResourceInfo} from '../utils';
export const PodTooltip = (props: {pod: Pod}) => {
const pod = props.pod;
@@ -23,10 +22,20 @@ export const PodTooltip = (props: {pod: Pod}) => {
})
.map(i => {
const isPodRequests = i.name === ResourceName.ResourceCPU || i.name === ResourceName.ResourceMemory;
const formattedValue = isPodRequests ? formatMetric(i.name as ResourceName, parseInt(i.value, 10)) : i.value;
let formattedValue = i.value;
let label = `${i.name}:`;
//this is just to show cpu and mem info with "Requests" as prefix
const label = i.name === ResourceName.ResourceCPU ? 'Requests CPU:' : i.name === ResourceName.ResourceMemory ? 'Requests MEM:' : `${i.name}:`;
if (isPodRequests) {
if (i.name === ResourceName.ResourceCPU) {
const {displayValue} = formatResourceInfo('cpu', i.value);
formattedValue = displayValue;
label = 'Requests CPU:';
} else if (i.name === ResourceName.ResourceMemory) {
const {displayValue} = formatResourceInfo('memory', i.value);
formattedValue = displayValue;
label = 'Requests MEM:';
}
}
return (
<div className='row' key={i.name}>

View File

@@ -20,7 +20,7 @@
position: absolute;
color: #A3A3A3;
font-size: 10px;
top: -10px;
top: -9px;
transform: rotate(180deg);
}
}

View File

@@ -22,7 +22,8 @@ import {
NodeId,
nodeKey,
PodHealthIcon,
getUsrMsgKeyToDisplay
getUsrMsgKeyToDisplay,
formatResourceInfo
} from '../utils';
import {NodeUpdateAnimation} from './node-update-animation';
import {PodGroup} from '../application-pod-view/pod-view';
@@ -530,11 +531,19 @@ function renderPodGroup(props: ApplicationResourceTreeProps, id: string, node: R
<Tooltip
content={
<>
{(node.info || []).map(i => (
<div key={i.name}>
{i.name}: {i.value}
</div>
))}
{(node.info || []).map(i => {
// Use common formatting function for CPU and Memory
if (i.name === 'cpu' || i.name === 'memory') {
const {tooltipValue} = formatResourceInfo(i.name, `${i.value}`);
return <div key={i.name}>{tooltipValue}</div>;
} else {
return (
<div key={i.name}>
{i.name}: {i.value}
</div>
);
}
})}
</>
}
key={node.uid}>
@@ -662,9 +671,9 @@ function expandCollapse(node: ResourceTreeNode, props: ApplicationResourceTreePr
function NodeInfoDetails({tag: tag, kind: kind}: {tag: models.InfoItem; kind: string}) {
if (kind === 'Pod') {
const val = `${tag.name}`;
const val = tag.name;
if (val === 'Status Reason') {
if (`${tag.value}` !== 'ImagePullBackOff')
if (String(tag.value) !== 'ImagePullBackOff')
return (
<span className='application-resource-tree__node-label' title={`Status: ${tag.value}`}>
{tag.value}
@@ -680,10 +689,10 @@ function NodeInfoDetails({tag: tag, kind: kind}: {tag: models.InfoItem; kind: st
);
}
} else if (val === 'Containers') {
const arr = `${tag.value}`.split('/');
const arr = String(tag.value).split('/');
const title = `Number of containers in total: ${arr[1]} \nNumber of ready containers: ${arr[0]}`;
return (
<span className='application-resource-tree__node-label' title={`${title}`}>
<span className='application-resource-tree__node-label' title={title}>
{tag.value}
</span>
);
@@ -699,6 +708,14 @@ function NodeInfoDetails({tag: tag, kind: kind}: {tag: models.InfoItem; kind: st
{tag.value}
</span>
);
} else if (val === 'cpu' || val === 'memory') {
// Use common formatting function for CPU and Memory
const {displayValue, tooltipValue} = formatResourceInfo(val, String(tag.value));
return (
<span className='application-resource-tree__node-label' title={tooltipValue}>
{displayValue}
</span>
);
} else {
return (
<span className='application-resource-tree__node-label' title={`${tag.name}: ${tag.value}`}>
@@ -801,19 +818,27 @@ function renderResourceNode(props: ApplicationResourceTreeProps, id: string, nod
) : null}
{(node.info || [])
.filter(tag => !tag.name.includes('Node'))
.slice(0, 4)
.slice(0, 2)
.map((tag, i) => {
return <NodeInfoDetails tag={tag} kind={node.kind} key={i} />;
})}
{(node.info || []).length > 4 && (
{(node.info || []).length > 3 && (
<Tooltip
content={
<>
{(node.info || []).map(i => (
<div key={i.name}>
{i.name}: {i.value}
</div>
))}
{(node.info || []).map(i => {
// Use common formatting function for CPU and Memory
if (i.name === 'cpu' || i.name === 'memory') {
const {tooltipValue} = formatResourceInfo(i.name, `${i.value}`);
return <div key={i.name}>{tooltipValue}</div>;
} else {
return (
<div key={i.name}>
{i.name}: {i.value}
</div>
);
}
})}
</>
}
key={node.uid}>

View File

@@ -338,7 +338,7 @@ export const ApplicationStatusPanel = ({application, showDiff, showOperation, sh
}}>
{(data: models.ApplicationSyncWindowState) => (
<React.Fragment>
{data.assignedWindows && (
{data?.assignedWindows && (
<div className='application-status-panel__item' style={{position: 'relative'}}>
{sectionLabel({
title: 'SYNC WINDOWS',

View File

@@ -94,7 +94,7 @@ export const ApplicationsRefreshPanel = ({show, apps, hide}: {show: boolean; app
))}
</div>
</div>
<ApplicationSelector apps={apps} formApi={formApi} />
{show && <ApplicationSelector apps={apps} formApi={formApi} />}
</div>
)}
</Form>

View File

@@ -146,7 +146,7 @@ export const ApplicationsSyncPanel = ({show, apps, hide}: {show: boolean; apps:
<ApplicationRetryOptions id='applications-sync-panel' formApi={formApi} />
<ApplicationSelector apps={apps} formApi={formApi} />
{show && <ApplicationSelector apps={apps} formApi={formApi} />}
</div>
)}
</Form>

View File

@@ -1553,13 +1553,13 @@ export const SyncWindowStatusIcon = ({state, window}: {state: appModels.SyncWind
);
};
export const ApplicationSyncWindowStatusIcon = ({project, state}: {project: string; state: appModels.ApplicationSyncWindowState}) => {
export const ApplicationSyncWindowStatusIcon = ({project, state}: {project: string; state?: appModels.ApplicationSyncWindowState}) => {
let className = '';
let color = '';
let deny = false;
let allow = false;
let inactiveAllow = false;
if (state.assignedWindows !== undefined && state.assignedWindows.length > 0) {
if (state?.assignedWindows !== undefined && state?.assignedWindows.length > 0) {
if (state.activeWindows !== undefined && state.activeWindows.length > 0) {
for (const w of state.activeWindows) {
if (w.kind === 'deny') {
@@ -1815,3 +1815,43 @@ export const podRequests = {
CPU: 'Requests (CPU)',
MEMORY: 'Requests (MEM)'
} as const;
export function formatResourceInfo(name: string, value: string): {displayValue: string; tooltipValue: string} {
const numValue = parseInt(value, 10);
const formatCPUValue = (milliCpu: number): string => {
return milliCpu >= 1000 ? `${(milliCpu / 1000).toFixed(1)}` : `${milliCpu}m`;
};
const formatMemoryValue = (milliBytes: number): string => {
const mib = Math.round(milliBytes / (1024 * 1024 * 1000));
return `${mib}Mi`;
};
const formatCPUTooltip = (milliCpu: number): string => {
const displayValue = milliCpu >= 1000 ? `${(milliCpu / 1000).toFixed(1)} cores` : `${milliCpu}m`;
return `CPU Request: ${displayValue}`;
};
const formatMemoryTooltip = (milliBytes: number): string => {
const mib = Math.round(milliBytes / (1024 * 1024 * 1000));
return `Memory Request: ${mib}Mi`;
};
if (name === 'cpu') {
return {
displayValue: formatCPUValue(numValue),
tooltipValue: formatCPUTooltip(numValue)
};
} else if (name === 'memory') {
return {
displayValue: formatMemoryValue(numValue),
tooltipValue: formatMemoryTooltip(numValue)
};
}
return {
displayValue: value,
tooltipValue: `${name}: ${value}`
};
}

View File

@@ -45,6 +45,18 @@ import (
var ErrInvalidRepoURL = errors.New("repo URL is invalid")
// builtinGitConfig configuration contains statements that are needed
// for correct ArgoCD operation. These settings will override any
// user-provided configuration of same options.
var builtinGitConfig = map[string]string{
"maintenance.autoDetach": "false",
"gc.autoDetach": "false",
}
// BuiltinGitConfigEnv contains builtin git configuration in the
// format acceptable by Git.
var BuiltinGitConfigEnv []string
// CommitMetadata contains metadata about a commit that is related in some way to another commit.
type CommitMetadata struct {
// Author is the author of the commit.
@@ -162,6 +174,8 @@ type nativeGitClient struct {
proxy string
// list of targets that shouldn't use the proxy, applies only if the proxy is set
noProxy string
// git configuration environment variables
gitConfigEnv []string
}
type runOpts struct {
@@ -188,6 +202,14 @@ func init() {
maxRetryDuration = env.ParseDurationFromEnv(common.EnvGitRetryMaxDuration, common.DefaultGitRetryMaxDuration, 0, math.MaxInt64)
retryDuration = env.ParseDurationFromEnv(common.EnvGitRetryDuration, common.DefaultGitRetryDuration, 0, math.MaxInt64)
factor = env.ParseInt64FromEnv(common.EnvGitRetryFactor, common.DefaultGitRetryFactor, 0, math.MaxInt64)
BuiltinGitConfigEnv = append(BuiltinGitConfigEnv, fmt.Sprintf("GIT_CONFIG_COUNT=%d", len(builtinGitConfig)))
idx := 0
for k, v := range builtinGitConfig {
BuiltinGitConfigEnv = append(BuiltinGitConfigEnv, fmt.Sprintf("GIT_CONFIG_KEY_%d=%s", idx, k))
BuiltinGitConfigEnv = append(BuiltinGitConfigEnv, fmt.Sprintf("GIT_CONFIG_VALUE_%d=%s", idx, v))
idx++
}
}
type ClientOpts func(c *nativeGitClient)
@@ -200,6 +222,16 @@ func WithCache(cache gitRefCache, loadRefFromCache bool) ClientOpts {
}
}
func WithBuiltinGitConfig(enable bool) ClientOpts {
return func(c *nativeGitClient) {
if enable {
c.gitConfigEnv = BuiltinGitConfigEnv
} else {
c.gitConfigEnv = nil
}
}
}
// WithEventHandlers sets the git client event handlers
func WithEventHandlers(handlers EventHandlers) ClientOpts {
return func(c *nativeGitClient) {
@@ -222,13 +254,14 @@ func NewClient(rawRepoURL string, creds Creds, insecure bool, enableLfs bool, pr
func NewClientExt(rawRepoURL string, root string, creds Creds, insecure bool, enableLfs bool, proxy string, noProxy string, opts ...ClientOpts) (Client, error) {
client := &nativeGitClient{
repoURL: rawRepoURL,
root: root,
creds: creds,
insecure: insecure,
enableLfs: enableLfs,
proxy: proxy,
noProxy: noProxy,
repoURL: rawRepoURL,
root: root,
creds: creds,
insecure: insecure,
enableLfs: enableLfs,
proxy: proxy,
noProxy: noProxy,
gitConfigEnv: BuiltinGitConfigEnv,
}
for i := range opts {
opts[i](client)
@@ -1111,6 +1144,8 @@ func (m *nativeGitClient) runCmdOutput(cmd *exec.Cmd, ropts runOpts) (string, er
cmd.Env = append(cmd.Env, "GIT_LFS_SKIP_SMUDGE=1")
// Disable Git terminal prompts in case we're running with a tty
cmd.Env = append(cmd.Env, "GIT_TERMINAL_PROMPT=false")
// Add Git configuration options that are essential for ArgoCD operation
cmd.Env = append(cmd.Env, m.gitConfigEnv...)
// For HTTPS repositories, we need to consider insecure repositories as well
// as custom CA bundles from the cert database.

View File

@@ -10,6 +10,7 @@ import (
"os/exec"
"path"
"path/filepath"
"regexp"
"strings"
"sync"
"testing"
@@ -1210,3 +1211,53 @@ Argocd-reference-commit-repourl: https://github.com/another/repo.git`,
})
}
}
func Test_BuiltinConfig(t *testing.T) {
tempDir := t.TempDir()
for _, enabled := range []bool{false, true} {
client, err := NewClientExt("file://"+tempDir, tempDir, NopCreds{}, true, false, "", "", WithBuiltinGitConfig(enabled))
require.NoError(t, err)
native := client.(*nativeGitClient)
configOut, err := native.config("--list", "--show-origin")
require.NoError(t, err)
for k, v := range builtinGitConfig {
r := regexp.MustCompile(fmt.Sprintf("(?m)^command line:\\s+%s=%s$", strings.ToLower(k), regexp.QuoteMeta(v)))
matches := r.FindString(configOut)
if enabled {
assert.NotEmpty(t, matches, "missing builtin configuration option: %s=%s", k, v)
} else {
assert.Empty(t, matches, "unexpected builtin configuration when builtin config is disabled: %s=%s", k, v)
}
}
}
}
func Test_GitNoDetachedMaintenance(t *testing.T) {
tempDir := t.TempDir()
ctx := t.Context()
client, err := NewClientExt("file://"+tempDir, tempDir, NopCreds{}, true, false, "", "")
require.NoError(t, err)
native := client.(*nativeGitClient)
err = client.Init()
require.NoError(t, err)
cmd := exec.CommandContext(ctx, "git", "fetch")
// trace execution of Git subcommands and their arguments to stderr
cmd.Env = append(cmd.Env, "GIT_TRACE=true")
// Ignore system config in case it disables auto maintenance
cmd.Env = append(cmd.Env, "GIT_CONFIG_NOSYSTEM=true")
output, err := native.runCmdOutput(cmd, runOpts{CaptureStderr: true})
require.NoError(t, err)
lines := strings.Split(output, "\n")
for _, line := range lines {
if strings.Contains(line, "git maintenance run") {
assert.NotContains(t, output, "--detach", "Unexpected --detach when running git maintenance")
return
}
}
assert.Fail(t, "Expected to see `git maintenance` run after `git fetch`")
}