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: Shared custom health check for multiple resources (#4212) #10885

Merged
merged 19 commits into from
Nov 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
f9d79b0
Kind wildcard support in health customizations
reggie-k Oct 10, 2022
aff1d44
Updated health customizations docs to using the correct field with a /
reggie-k Oct 10, 2022
0654777
Updated health customizations docs to using the correct field with a /
reggie-k Oct 10, 2022
eedcd09
Document resource kind wildcard for custom health check
reggie-k Oct 10, 2022
a01a85e
Merge branch 'master' into master
reggie-k Oct 10, 2022
df70776
Merge branch 'master' into master
reggie-k Oct 11, 2022
e98d753
Implemented wildcard * support in API Group and Resource Kind and upd…
reggie-k Oct 12, 2022
90004c8
Merge branch 'master' of https://github.com/reggie-k/argo-cd
reggie-k Oct 12, 2022
a51f39a
Merge branch 'argoproj:master' into master
reggie-k Oct 12, 2022
55e2a0a
Merge branch 'master' of https://github.com/reggie-k/argo-cd
reggie-k Oct 12, 2022
1117332
Implemented wildcard * support in API Group and Resource Kind and upd…
reggie-k Oct 12, 2022
28d7d31
Implemented wildcard * support in API Group and Resource Kind and upd…
reggie-k Oct 12, 2022
1b603e4
Merge branch 'argoproj:master' into master
reggie-k Oct 13, 2022
1300ce9
Merge branch 'argoproj:master' into master
reggie-k Oct 14, 2022
d1d988c
Merge branch 'master' into master
reggie-k Oct 15, 2022
caff8f4
Merge branch 'master' into master
reggie-k Oct 21, 2022
d5f6366
Merge branch 'master' into master
crenshaw-dev Oct 21, 2022
5ec8879
Merge branch 'argoproj:master' into master
reggie-k Oct 21, 2022
7cc4c2e
Removed code duplication and returned an empty string instead of an e…
reggie-k Oct 21, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
84 changes: 52 additions & 32 deletions docs/operator-manual/health.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,21 @@ metadata:
app.kubernetes.io/name: argocd-cm
app.kubernetes.io/part-of: argocd
data:
resource.customizations.health.argoproj.io_Application: |
hs = {}
hs.status = "Progressing"
hs.message = ""
if obj.status ~= nil then
if obj.status.health ~= nil then
hs.status = obj.status.health.status
if obj.status.health.message ~= nil then
hs.message = obj.status.health.message
resource.customizations: |
argoproj.io/Application:
health.lua: |
hs = {}
hs.status = "Progressing"
hs.message = ""
if obj.status ~= nil then
if obj.status.health ~= nil then
hs.status = obj.status.health.status
if obj.status.health.message ~= nil then
hs.message = obj.status.health.message
end
end
end
end
end
return hs
return hs
```

## Custom Health Checks
Expand All @@ -62,34 +64,50 @@ There are two ways to configure a custom health check. The next two sections des

### Way 1. Define a Custom Health Check in `argocd-cm` ConfigMap

Custom health checks can be defined in `resource.customizations.health.<group_kind>` field of `argocd-cm`. If you are using argocd-operator, this is overridden by [the argocd-operator resourceCustomizations](https://argocd-operator.readthedocs.io/en/latest/reference/argocd/#resource-customizations).
Custom health checks can be defined in
crenshaw-dev marked this conversation as resolved.
Show resolved Hide resolved
```yaml
resource.customizations: |
<group/kind>:
health.lua: |
```
field of `argocd-cm`. If you are using argocd-operator, this is overridden by [the argocd-operator resourceCustomizations](https://argocd-operator.readthedocs.io/en/latest/reference/argocd/#resource-customizations).

The following example demonstrates a health check for `cert-manager.io/Certificate`.

```yaml
data:
resource.customizations.health.cert-manager.io_Certificate: |
hs = {}
if obj.status ~= nil then
if obj.status.conditions ~= nil then
for i, condition in ipairs(obj.status.conditions) do
if condition.type == "Ready" and condition.status == "False" then
hs.status = "Degraded"
hs.message = condition.message
return hs
end
if condition.type == "Ready" and condition.status == "True" then
hs.status = "Healthy"
hs.message = condition.message
return hs
resource.customizations: |
cert-manager.io/Certificate:
health.lua: |
hs = {}
if obj.status ~= nil then
if obj.status.conditions ~= nil then
for i, condition in ipairs(obj.status.conditions) do
if condition.type == "Ready" and condition.status == "False" then
hs.status = "Degraded"
hs.message = condition.message
return hs
end
if condition.type == "Ready" and condition.status == "True" then
hs.status = "Healthy"
hs.message = condition.message
return hs
end
end
end
end
end
end

hs.status = "Progressing"
hs.message = "Waiting for certificate"
return hs
hs.status = "Progressing"
hs.message = "Waiting for certificate"
return hs
```
In order to prevent duplication of the same custom health check for potentially multiple resources, it is also possible to specify a wildcard in the resource kind, like this:

```yaml
resource.customizations: |
ec2.aws.crossplane.io/*:
health.lua: |
...
```

The `obj` is a global variable which contains the resource. The script must return an object with status and optional message field.
Expand Down Expand Up @@ -139,3 +157,5 @@ tests:
To test the implemented custom health checks, run `go test -v ./util/lua/`.

The [PR#1139](https://github.com/argoproj/argo-cd/pull/1139) is an example of Cert Manager CRDs custom health check.

Please note that bundled health checks with wildcards are not supported.
26 changes: 26 additions & 0 deletions util/lua/lua.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (

appv1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/v2/resource_customizations"
"github.com/argoproj/argo-cd/v2/util/glob"
)

const (
Expand Down Expand Up @@ -122,10 +123,24 @@ func (vm VM) ExecuteHealthLua(obj *unstructured.Unstructured, script string) (*h

// GetHealthScript attempts to read lua script from config and then filesystem for that resource
func (vm VM) GetHealthScript(obj *unstructured.Unstructured) (string, bool, error) {
// first, search the gvk as is in the ResourceOverrides
key := GetConfigMapKey(obj.GroupVersionKind())

if script, ok := vm.ResourceOverrides[key]; ok && script.HealthLua != "" {
return script.HealthLua, script.UseOpenLibs, nil
}

// if not found as is, perhaps it matches wildcard entries in the configmap
wildcardKey := GetWildcardConfigMapKey(vm, obj.GroupVersionKind())

if wildcardKey != "" {
if wildcardScript, ok := vm.ResourceOverrides[wildcardKey]; ok && wildcardScript.HealthLua != "" {
return wildcardScript.HealthLua, wildcardScript.UseOpenLibs, nil
}
}

// if not found in the ResourceOverrides at all, search it as is in the built-in scripts
// (as built-in scripts are files in folders, named after the GVK, currently there is no wildcard support for them)
builtInScript, err := vm.getPredefinedLuaScripts(key, healthScriptFile)
// standard libraries will be enabled for all built-in scripts
return builtInScript, true, err
Expand Down Expand Up @@ -333,6 +348,17 @@ func GetConfigMapKey(gvk schema.GroupVersionKind) string {
return fmt.Sprintf("%s/%s", gvk.Group, gvk.Kind)
}

func GetWildcardConfigMapKey(vm VM, gvk schema.GroupVersionKind) string {
gvkKeyToMatch := GetConfigMapKey(gvk)

for key := range vm.ResourceOverrides {
if glob.Match(key, gvkKeyToMatch) {
return key
}
}
return ""
}

func (vm VM) getPredefinedLuaScripts(objKey string, scriptFile string) (string, error) {
data, err := resource_customizations.Embedded.ReadFile(filepath.Join(objKey, scriptFile))
if err != nil {
Expand Down
34 changes: 34 additions & 0 deletions util/lua/lua_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,40 @@ func TestGetHealthScriptWithOverride(t *testing.T) {
assert.Equal(t, newHealthStatusFunction, script)
}

func TestGetHealthScriptWithKindWildcardOverride(t *testing.T) {
testObj := StrToUnstructured(objJSON)
vm := VM{
ResourceOverrides: map[string]appv1.ResourceOverride{
"argoproj.io/*": {
HealthLua: newHealthStatusFunction,
UseOpenLibs: false,
},
},
}

script, useOpenLibs, err := vm.GetHealthScript(testObj)
assert.Nil(t, err)
assert.Equal(t, false, useOpenLibs)
assert.Equal(t, newHealthStatusFunction, script)
}

func TestGetHealthScriptWithGroupWildcardOverride(t *testing.T) {
testObj := StrToUnstructured(objJSON)
vm := VM{
ResourceOverrides: map[string]appv1.ResourceOverride{
"*.io/Rollout": {
HealthLua: newHealthStatusFunction,
UseOpenLibs: false,
},
},
}

script, useOpenLibs, err := vm.GetHealthScript(testObj)
assert.Nil(t, err)
assert.Equal(t, false, useOpenLibs)
assert.Equal(t, newHealthStatusFunction, script)
}

func TestGetHealthScriptPredefined(t *testing.T) {
testObj := StrToUnstructured(objJSON)
vm := VM{}
Expand Down