Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Health status customization in Argo for CRD resources #655

Closed
wants to merge 26 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
a3ebe19
add health check for crd
almoelda Dec 28, 2024
b6abb46
Merge pull request #1 from almoelda/feat--Health-status-customization…
almoelda Dec 28, 2024
d3d35d9
deleted handling of deletionTimestamp, added more conditions to handl…
almoelda Dec 28, 2024
040ccba
adding tests
almoelda Dec 28, 2024
394ad04
reverting blank lines
almoelda Dec 28, 2024
fb0f086
add health check for crd
almoelda Dec 28, 2024
fac4caa
deleted handling of deletionTimestamp, added more conditions to handl…
almoelda Dec 28, 2024
b4b762c
adding tests
almoelda Dec 28, 2024
3b97a12
reverting blank lines
almoelda Dec 28, 2024
6e58d04
Merge branch 'master' of github.com:almoelda/gitops-engine
almoelda Dec 28, 2024
a62ee8f
reverting blank lines
almoelda Dec 28, 2024
a4ff366
Merge branch 'master' of github.com:almoelda/gitops-engine
almoelda Dec 29, 2024
5d64820
chore(deps): upgrade go version in dockerfile (#638)
jmeridth Nov 26, 2024
14ea265
fix: Server side diff now works correctly with fields removal (#640)
andrii-korotkov-verkada Dec 11, 2024
2045db1
fix: github actions versions and warnings (#639)
jmeridth Dec 12, 2024
6d883a2
fix: run go mod tidy in ci workflow (#652)
jmeridth Dec 12, 2024
f932f1a
chore: add CODEOWNERS (#641)
jmeridth Dec 12, 2024
6232e52
chore: update README get involved links (#647)
jmeridth Dec 12, 2024
08289bc
fix: avoid resources lock contention utilizing channel (#629)
mpelekh Dec 16, 2024
d833440
add health check for crd
almoelda Dec 28, 2024
6815716
deleted handling of deletionTimestamp, added more conditions to handl…
almoelda Dec 28, 2024
1452251
adding tests
almoelda Dec 28, 2024
7403989
reverting blank lines
almoelda Dec 28, 2024
8aee579
deleted handling of deletionTimestamp, added more conditions to handl…
almoelda Dec 28, 2024
769a2cf
reverting blank lines
almoelda Dec 28, 2024
c881350
Merge branch 'master' of github.com:almoelda/gitops-engine
almoelda Dec 29, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions pkg/health/health.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,11 @@ func GetHealthCheckFunc(gvk schema.GroupVersionKind) func(obj *unstructured.Unst
case kube.IngressKind:
return getIngressHealth
}
case "apiextensions.k8s.io":
switch gvk.Kind {
case kube.CustomResourceDefinitionKind:
return getCustomResourceDefinitionHealth
}
case "argoproj.io":
switch gvk.Kind {
case "Workflow":
Expand Down
99 changes: 99 additions & 0 deletions pkg/health/health_customresourcedefinition.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package health

import (
"fmt"

"github.com/argoproj/gitops-engine/pkg/utils/kube"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
)

func getCustomResourceDefinitionHealth(obj *unstructured.Unstructured) (*HealthStatus, error) {
gvk := obj.GroupVersionKind()
switch gvk {
case apiextensionsv1.SchemeGroupVersion.WithKind(kube.CustomResourceDefinitionKind):
var crd apiextensionsv1.CustomResourceDefinition
err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.Object, &crd)
if err != nil {
return nil, fmt.Errorf("failed to convert unstructured CustomResourceDefinition to typed: %v", err)
}
return getApiExtenstionsV1CustomResourceDefinitionHealth(&crd)
default:
return nil, fmt.Errorf("unsupported CustomResourceDefinition GVK: %s", gvk)
}
}

func getApiExtenstionsV1CustomResourceDefinitionHealth(crd *apiextensionsv1.CustomResourceDefinition) (*HealthStatus, error) {

if crd.Status.Conditions == nil || crd.Status.Conditions != nil && len(crd.Status.Conditions) == 0 {
return &HealthStatus{
Status: HealthStatusProgressing,
Message: "Status conditions not found",
}, nil
}

var (
isEstablished bool
isTerminating bool
namesNotAccepted bool
hasViolations bool
conditionMsg string
)

// Check conditions
for _, condition := range crd.Status.Conditions {
switch condition.Type {
case apiextensionsv1.Terminating:
if condition.Status == apiextensionsv1.ConditionTrue {
isTerminating = true
conditionMsg = condition.Message
}
case apiextensionsv1.NamesAccepted:
if condition.Status == apiextensionsv1.ConditionFalse {
namesNotAccepted = true
conditionMsg = condition.Message
}
case apiextensionsv1.Established:
if condition.Status == apiextensionsv1.ConditionTrue {
isEstablished = true
} else {
conditionMsg = condition.Message
}
case apiextensionsv1.NonStructuralSchema:
if condition.Status == apiextensionsv1.ConditionTrue {
hasViolations = true
conditionMsg = condition.Message
}
}
}

// Return appropriate health status
switch {
case isTerminating:
return &HealthStatus{
Status: HealthStatusProgressing,
Message: fmt.Sprintf("CRD is being terminated: %s", conditionMsg),
}, nil
case namesNotAccepted:
return &HealthStatus{
Status: HealthStatusDegraded,
Message: fmt.Sprintf("CRD names have not been accepted: %s", conditionMsg),
}, nil
case !isEstablished:
return &HealthStatus{
Status: HealthStatusDegraded,
Message: fmt.Sprintf("CRD is not established: %s", conditionMsg),
}, nil
case hasViolations:
return &HealthStatus{
Status: HealthStatusDegraded,
Message: fmt.Sprintf("Schema violations found: %s", conditionMsg),
}, nil
default:
return &HealthStatus{
Status: HealthStatusHealthy,
Message: "CRD is healthy",
}, nil
}
}
8 changes: 8 additions & 0 deletions pkg/health/health_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,14 @@ func TestAPIService(t *testing.T) {
assertAppHealth(t, "./testdata/apiservice-v1beta1-false.yaml", HealthStatusProgressing)
}

func TestCustomResourceDefinitionHealth(t *testing.T) {
assertAppHealth(t, "./testdata/crd-v1-healthy.yaml", HealthStatusHealthy)
assertAppHealth(t, "./testdata/crd-v1-non-structual-degraded.yaml", HealthStatusDegraded)
assertAppHealth(t, "./testdata/crd-v1-not-established-degraded.yaml", HealthStatusDegraded)
assertAppHealth(t, "./testdata/crd-v1-terminating-progressing.yaml", HealthStatusProgressing)
assertAppHealth(t, "./testdata/crd-v1-no-conditions-progressing.yaml", HealthStatusProgressing)
}

func TestGetArgoWorkflowHealth(t *testing.T) {
sampleWorkflow := unstructured.Unstructured{Object: map[string]interface{}{
"spec": map[string]interface{}{
Expand Down
56 changes: 56 additions & 0 deletions pkg/health/testdata/crd-v1-healthy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: examples.example.io
spec:
conversion:
strategy: None
group: example.io
names:
kind: Example
listKind: ExampleList
plural: examples
shortNames:
- ex
singular: example
preserveUnknownFields: true
scope: Namespaced
versions:
- additionalPrinterColumns:
- description: >-
CreationTimestamp is a timestamp representing the server time when
this object was created. It is not guaranteed to be set in
happens-before order across separate operations. Clients may not set
this value. It is represented in RFC3339 form and is in UTC.


Populated by the system. Read-only. Null for lists. More info:
https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata
jsonPath: .metadata.creationTimestamp
name: Age
type: date
name: v1alpha1
served: true
storage: true
subresources: {}
status:
acceptedNames:
kind: Example
listKind: ExampleList
plural: examples
shortNames:
- ex
singular: example
conditions:
- lastTransitionTime: '2024-05-19T23:35:28Z'
message: no conflicts found
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
storedVersions:
- v1alpha1
46 changes: 46 additions & 0 deletions pkg/health/testdata/crd-v1-no-conditions-progressing.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: examples.example.io
spec:
conversion:
strategy: None
group: example.io
names:
kind: Example
listKind: ExampleList
plural: examples
shortNames:
- ex
singular: example
preserveUnknownFields: true
scope: Namespaced
versions:
- additionalPrinterColumns:
- description: >-
CreationTimestamp is a timestamp representing the server time when
this object was created. It is not guaranteed to be set in
happens-before order across separate operations. Clients may not set
this value. It is represented in RFC3339 form and is in UTC.


Populated by the system. Read-only. Null for lists. More info:
https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata
jsonPath: .metadata.creationTimestamp
name: Age
type: date
name: v1alpha1
served: true
storage: true
subresources: {}
status:
acceptedNames:
kind: Example
listKind: ExampleList
plural: examples
shortNames:
- ex
singular: example
conditions: []
storedVersions:
- v1alpha1
61 changes: 61 additions & 0 deletions pkg/health/testdata/crd-v1-non-structual-degraded.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: examples.example.io
spec:
conversion:
strategy: None
group: example.io
names:
kind: Example
listKind: ExampleList
plural: examples
shortNames:
- ex
singular: example
preserveUnknownFields: true
scope: Namespaced
versions:
- additionalPrinterColumns:
- description: >-
CreationTimestamp is a timestamp representing the server time when
this object was created. It is not guaranteed to be set in
happens-before order across separate operations. Clients may not set
this value. It is represented in RFC3339 form and is in UTC.


Populated by the system. Read-only. Null for lists. More info:
https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata
jsonPath: .metadata.creationTimestamp
name: Age
type: date
name: v1alpha1
served: true
storage: true
subresources: {}
status:
acceptedNames:
kind: Example
listKind: ExampleList
plural: examples
shortNames:
- ex
singular: example
conditions:
- lastTransitionTime: '2024-05-19T23:35:28Z'
message: no conflicts found
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
storedVersions:
- v1alpha1
56 changes: 56 additions & 0 deletions pkg/health/testdata/crd-v1-not-established-degraded.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: examples.example.io
spec:
conversion:
strategy: None
group: example.io
names:
kind: Example
listKind: ExampleList
plural: examples
shortNames:
- ex
singular: example
preserveUnknownFields: true
scope: Namespaced
versions:
- additionalPrinterColumns:
- description: >-
CreationTimestamp is a timestamp representing the server time when
this object was created. It is not guaranteed to be set in
happens-before order across separate operations. Clients may not set
this value. It is represented in RFC3339 form and is in UTC.


Populated by the system. Read-only. Null for lists. More info:
https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata
jsonPath: .metadata.creationTimestamp
name: Age
type: date
name: v1alpha1
served: true
storage: true
subresources: {}
status:
acceptedNames:
kind: Example
listKind: ExampleList
plural: examples
shortNames:
- ex
singular: example
conditions:
- lastTransitionTime: '2024-05-19T23:35:28Z'
message: no conflicts found
reason: NoConflicts
status: 'False'
type: NamesAccepted
- lastTransitionTime: '2024-05-19T23:35:28Z'
message: the initial names have been accepted
reason: InitialNamesAccepted
status: 'False'
type: Established
storedVersions:
- v1alpha1
Loading
Loading