Skip to content

Commit

Permalink
Merge branch 'argoproj:master' into feature/scm_manager_support
Browse files Browse the repository at this point in the history
  • Loading branch information
TiDgCloudogu authored Nov 21, 2024
2 parents 30977b0 + 4a14051 commit 486a82c
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 8 deletions.
4 changes: 4 additions & 0 deletions common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,10 @@ const (
// AnnotationCompareOptions is a comma-separated list of options for comparison
AnnotationCompareOptions = "argocd.argoproj.io/compare-options"

// AnnotationIgnoreHealthCheck when set on an Application's immediate child indicates that its health check
// can be disregarded.
AnnotationIgnoreHealthCheck = "argocd.argoproj.io/ignore-healthcheck"

// AnnotationKeyManagedBy is annotation name which indicates that k8s resource is managed by an application.
AnnotationKeyManagedBy = "managed-by"
// AnnotationValueManagedByArgoCD is a 'managed-by' annotation value for resources managed by Argo CD
Expand Down
4 changes: 4 additions & 0 deletions controller/health.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
log "github.com/sirupsen/logrus"
"k8s.io/apimachinery/pkg/runtime/schema"

"github.com/argoproj/argo-cd/v2/common"
"github.com/argoproj/argo-cd/v2/pkg/apis/application"
appv1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/v2/util/lua"
Expand All @@ -24,6 +25,9 @@ func setApplicationHealth(resources []managedResource, statuses []appv1.Resource
if res.Target != nil && hookutil.Skip(res.Target) {
continue
}
if res.Target != nil && res.Target.GetAnnotations() != nil && res.Target.GetAnnotations()[common.AnnotationIgnoreHealthCheck] == "true" {
continue
}

if res.Live != nil && (hookutil.IsHook(res.Live) || ignore.Ignore(res.Live)) {
continue
Expand Down
9 changes: 9 additions & 0 deletions controller/health_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,15 @@ func TestSetApplicationHealth(t *testing.T) {
healthStatus, err = setApplicationHealth(resources, resourceStatuses, nil, app, true)
require.NoError(t, err)
assert.Equal(t, health.HealthStatusHealthy, healthStatus.Status)

// now we set the `argocd.argoproj.io/ignore-healthcheck: "true"` annotation on the job's target.
// The app is considered healthy
failedJob.SetAnnotations(nil)
failedJobIgnoreHealthcheck := resourceFromFile("./testdata/job-failed-ignore-healthcheck.yaml")
resources[1].Target = &failedJobIgnoreHealthcheck
healthStatus, err = setApplicationHealth(resources, resourceStatuses, nil, app, true)
require.NoError(t, err)
assert.Equal(t, health.HealthStatusHealthy, healthStatus.Status)
}

func TestSetApplicationHealth_ResourceHealthNotPersisted(t *testing.T) {
Expand Down
36 changes: 36 additions & 0 deletions controller/testdata/job-failed-ignore-healthcheck.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
apiVersion: batch/v1
kind: Job
metadata:
annotations:
argocd.argoproj.io/ignore-healthcheck: "true"
labels:
job-name: fail
name: fail
namespace: argoci-workflows
selfLink: /apis/batch/v1/namespaces/argoci-workflows/jobs/fail
spec:
backoffLimit: 0
completions: 1
parallelism: 1
template:
metadata:
creationTimestamp: null
labels:
job-name: fail
spec:
containers:
- command:
- sh
- -c
- exit 1
image: alpine:latest
imagePullPolicy: Always
name: fail
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Never
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
13 changes: 13 additions & 0 deletions docs/operator-manual/health.md
Original file line number Diff line number Diff line change
Expand Up @@ -229,3 +229,16 @@ App (healthy)
└── CustomResource (healthy) <- This resource's health check needs to be fixed to mark the App as unhealthy
└── CustomChildResource (unhealthy)
```
## Ignoring Child Resource Health Check in Applications
To ignore the health check of an immediate child resource within an Application, set the annotation `argocd.argoproj.io/ignore-healthcheck` to `true`. For example:
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
argocd.argoproj.io/ignore-healthcheck: "true"
```

By doing this, the health status of the Deployment will not affect the health of its parent Application.
1 change: 1 addition & 0 deletions docs/operator-manual/metrics.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Metrics about applications. Scraped at the `argocd-metrics:8082/metrics` endpoin
| `argocd_app_condition` | gauge | Report Applications conditions. It contains the conditions currently present in the application status. |
| `argocd_app_k8s_request_total` | counter | Number of Kubernetes requests executed during application reconciliation |
| `argocd_app_labels` | gauge | Argo Application labels converted to Prometheus labels. Disabled by default. See section below about how to enable it. |
| `argocd_app_orphaned_resources_count` | gauge | Number of orphaned resources per application. |
| `argocd_app_reconcile` | histogram | Application reconciliation performance in seconds. |
| `argocd_app_sync_total` | counter | Counter for application sync history |
| `argocd_cluster_api_resource_objects` | gauge | Number of k8s resource objects in the cache. |
Expand Down
56 changes: 48 additions & 8 deletions pkg/apis/application/v1alpha1/types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,100 +107,140 @@ func TestAppProject_IsNegatedSourcePermitted(t *testing.T) {
}

func TestAppProject_IsDestinationPermitted(t *testing.T) {
t.Parallel()

testData := []struct {
name string
projDest []ApplicationDestination
appDest ApplicationDestination
isPermitted bool
}{
{
name: "server an namespace match",
projDest: []ApplicationDestination{{
Server: "https://kubernetes.default.svc", Namespace: "default",
}},
appDest: ApplicationDestination{Server: "https://kubernetes.default.svc", Namespace: "default"},
isPermitted: true,
},
{
name: "namespace does not match",
projDest: []ApplicationDestination{{
Server: "https://kubernetes.default.svc", Namespace: "default",
}},
appDest: ApplicationDestination{Server: "https://kubernetes.default.svc", Namespace: "kube-system"},
isPermitted: false,
},
{
name: "server does not match",
projDest: []ApplicationDestination{{
Server: "https://my-cluster", Namespace: "default",
}},
appDest: ApplicationDestination{Server: "https://kubernetes.default.svc", Namespace: "default"},
isPermitted: false,
},
{
name: "wildcard namespace",
projDest: []ApplicationDestination{{
Server: "https://kubernetes.default.svc", Namespace: "*",
}},
appDest: ApplicationDestination{Server: "https://kubernetes.default.svc", Namespace: "kube-system"},
isPermitted: true,
},
{
name: "wildcard server",
projDest: []ApplicationDestination{{
Server: "https://*.default.svc", Namespace: "default",
}},
appDest: ApplicationDestination{Server: "https://kubernetes.default.svc", Namespace: "default"},
isPermitted: true,
},
{
name: "wildcard server and namespace",
projDest: []ApplicationDestination{{
Server: "https://team1-*", Namespace: "default",
}},
appDest: ApplicationDestination{Server: "https://test2-dev-cluster", Namespace: "default"},
isPermitted: false,
},
{
name: "wildcard namespace with prefix",
projDest: []ApplicationDestination{{
Server: "https://kubernetes.default.svc", Namespace: "test-*",
}},
appDest: ApplicationDestination{Server: "https://kubernetes.default.svc", Namespace: "test-foo"},
isPermitted: true,
},
{
name: "wildcard namespace without prefix",
projDest: []ApplicationDestination{{
Server: "https://kubernetes.default.svc", Namespace: "test-*",
}},
appDest: ApplicationDestination{Server: "https://kubernetes.default.svc", Namespace: "test"},
isPermitted: false,
},
{
name: "wildcard server and namespace",
projDest: []ApplicationDestination{{
Server: "*", Namespace: "*",
}},
appDest: ApplicationDestination{Server: "https://kubernetes.default.svc", Namespace: "test"},
isPermitted: true,
},
{
name: "wildcard server and namespace with name",
projDest: []ApplicationDestination{{
Server: "", Namespace: "*", Name: "test",
}},
appDest: ApplicationDestination{Name: "test", Namespace: "test"},
isPermitted: true,
},
{
name: "wildcard server and namespace with different name",
projDest: []ApplicationDestination{{
Server: "", Namespace: "*", Name: "test2",
}},
appDest: ApplicationDestination{Name: "test", Namespace: "test"},
isPermitted: false,
},
/**
- name: host-cluster
namespace: '!{kube-system,argocd}'
server: 'https://kubernetes.default.svc'
- name: destination-cluster-01
namespace: '*'
server: 'https://eks-cluster-endpoint.ap-southeast-1.eks.amazonaws.com'
destination:
server: https://eks-cluster-endpoint.ap-southeast-1.eks.amazonaws.com
namespace: karpenter
*/
{
name: "negated namespace with multiple values",
projDest: []ApplicationDestination{
{Name: "host-cluster", Server: "https://kubernetes.default.svc", Namespace: "!{kube-system,argocd}"},
{Name: "destination-cluster-01", Server: "https://eks-cluster-endpoint.ap-southeast-1.eks.amazonaws.com", Namespace: "*"},
},
appDest: ApplicationDestination{Server: "https://eks-cluster-endpoint.ap-southeast-1.eks.amazonaws.com", Namespace: "kube-system"},
isPermitted: true,
},
}

for _, data := range testData {
proj := AppProject{
Spec: AppProjectSpec{
Destinations: data.projDest,
},
}
permitted, _ := proj.IsDestinationPermitted(data.appDest, func(project string) ([]*Cluster, error) {
return []*Cluster{}, nil
data := data
t.Run(data.name, func(t *testing.T) {
t.Parallel()

proj := AppProject{
Spec: AppProjectSpec{
Destinations: data.projDest,
},
}
permitted, _ := proj.IsDestinationPermitted(data.appDest, func(project string) ([]*Cluster, error) {
return []*Cluster{}, nil
})
assert.Equal(t, data.isPermitted, permitted)
})
assert.Equal(t, data.isPermitted, permitted)
}
}

Expand Down

0 comments on commit 486a82c

Please sign in to comment.