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(alertchannels): Add webhook alertchannel type #56

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
28 changes: 26 additions & 2 deletions api/checkly/v1alpha1/alertchannel_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,28 @@ type AlertChannelSpec struct {
// Important: Run "make" to regenerate code after modifying this file

// SendRecovery determines if the Recovery event should be sent to the alert channel
SendRecovery bool `json:"sendrecovery,omitempty"`
SendRecovery bool `json:"sendRecovery,omitempty"`

// SendFailure determines if the Failure event should be sent to the alerting channel
SendFailure bool `json:"sendfailure,omitempty"`
SendFailure bool `json:"sendFailure,omitempty"`

// SendDegraded determines if the Failure event should be sent to the alerting channel
SendDegraded bool `json:"sendDegraded,omitempty"`

// SSLExpiry determine if alerts on SSL Expiry should be sent
SSLExpiry bool `json:"sslExpiry,omitempty"`

// SSLExpiryThreshold At what moment in time to start alerting on SSL certificates.
SSLExpiryThreshold int `json:"sslExpiryThreshold,omitempty"`

// OpsGenie holds information about the Opsgenie alert configuration
OpsGenie AlertChannelOpsGenie `json:"opsgenie,omitempty"`

// Email holds information about the Email alert configuration
Email checkly.AlertChannelEmail `json:"email,omitempty"`

// Webhook holds information about the Webhook alert configuration
Webhook AlertChannelWebhook `json:"webhook,omitempty"`
}

type AlertChannelOpsGenie struct {
Expand All @@ -51,6 +63,18 @@ type AlertChannelOpsGenie struct {
Priority string `json:"priority,omitempty"`
}

// AlertChannelWebhook is a custom struct to hold information about Webhook configuration, source https://github.com/checkly/checkly-go-sdk/blame/main/types.go#L799-L808
type AlertChannelWebhook struct {
Name string `json:"name"`
URL string `json:"url"`
WebhookType string `json:"webhookType,omitempty"`
Method string `json:"method"`
Template string `json:"template,omitempty"`
WebhookSecret corev1.ObjectReference `json:"webhookSecret,omitempty"`
Headers []checkly.KeyValue `json:"headers,omitempty"`
QueryParameters []checkly.KeyValue `json:"queryParameters,omitempty"`
}

// AlertChannelStatus defines the observed state of AlertChannel
type AlertChannelStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
Expand Down
30 changes: 29 additions & 1 deletion api/checkly/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

131 changes: 129 additions & 2 deletions config/crd/bases/k8s.checklyhq.com_alertchannels.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -105,14 +105,141 @@ spec:
required:
- apisecret
type: object
sendfailure:
sendDegraded:
description: SendDegraded determines if the Failure event should be
sent to the alerting channel
type: boolean
sendFailure:
description: SendFailure determines if the Failure event should be
sent to the alerting channel
type: boolean
sendrecovery:
sendRecovery:
description: SendRecovery determines if the Recovery event should
be sent to the alert channel
type: boolean
sslExpiry:
description: SSLExpiry determine if alerts on SSL Expiry should be
sent
type: boolean
sslExpiryThreshold:
description: SSLExpiryThreshold At what moment in time to start alerting
on SSL certificates.
type: integer
webhook:
description: Webhook holds information about the Webhook alert configuration
properties:
headers:
items:
description: |-
KeyValue represents a key-value pair, for example a request header setting,
or a query parameter.
properties:
key:
type: string
locked:
type: boolean
value:
type: string
required:
- key
- locked
- value
type: object
type: array
method:
type: string
name:
type: string
queryParameters:
items:
description: |-
KeyValue represents a key-value pair, for example a request header setting,
or a query parameter.
properties:
key:
type: string
locked:
type: boolean
value:
type: string
required:
- key
- locked
- value
type: object
type: array
template:
type: string
url:
type: string
webhookSecret:
description: |-
ObjectReference contains enough information to let you inspect or modify the referred object.
---
New uses of this type are discouraged because of difficulty describing its usage when embedded in APIs.
1. Ignored fields. It includes many fields which are not generally honored. For instance, ResourceVersion and FieldPath are both very rarely valid in actual usage.
2. Invalid usage help. It is impossible to add specific help for individual usage. In most embedded usages, there are particular
restrictions like, "must refer only to types A and B" or "UID not honored" or "name must be restricted".
Those cannot be well described when embedded.
3. Inconsistent validation. Because the usages are different, the validation rules are different by usage, which makes it hard for users to predict what will happen.
4. The fields are both imprecise and overly precise. Kind is not a precise mapping to a URL. This can produce ambiguity
during interpretation and require a REST mapping. In most cases, the dependency is on the group,resource tuple
and the version of the actual struct is irrelevant.
5. We cannot easily change it. Because this type is embedded in many locations, updates to this type
will affect numerous schemas. Don't make new APIs embed an underspecified API type they do not control.


Instead of using this type, create a locally provided and used type that is well-focused on your reference.
For example, ServiceReferences for admission registration: https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533 .
properties:
apiVersion:
description: API version of the referent.
type: string
fieldPath:
description: |-
If referring to a piece of an object instead of an entire object, this string
should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2].
For example, if the object reference is to a container within a pod, this would take on a value like:
"spec.containers{name}" (where "name" refers to the name of the container that triggered
the event) or if no container name is specified "spec.containers[2]" (container with
index 2 in this pod). This syntax is chosen only to have some well-defined way of
referencing a part of an object.
TODO: this design is not final and this field is subject to change in the future.
type: string
kind:
description: |-
Kind of the referent.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
name:
description: |-
Name of the referent.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
namespace:
description: |-
Namespace of the referent.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/
type: string
resourceVersion:
description: |-
Specific resourceVersion to which this reference is made, if any.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency
type: string
uid:
description: |-
UID of the referent.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids
type: string
type: object
x-kubernetes-map-type: atomic
webhookType:
type: string
required:
- method
- name
- url
type: object
type: object
status:
description: AlertChannelStatus defines the observed state of AlertChannel
Expand Down
26 changes: 26 additions & 0 deletions config/samples/checkly_v1alpha1_alertchannel.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ kind: AlertChannel
metadata:
name: alertchannel-sample
spec:
sendRecovery: false
sendFailure: true
sendDegraded: true
sslExpiry: true
sslExpiryThreshold: 30
# only one of the below can be specified at once, either email or opsgenie
email:
address: "[email protected]"
Expand All @@ -13,3 +18,24 @@ spec:
# fieldPath: "TEST" # Key inside the secret
# priority: "P3"
# region: "US"
# sslExpiry: true
# sendDegraded: true
# sslExpiryThreshold: 15
# webhook:
# name: foo # Name of the webhook
# url: https://foo.bar # URL of the webhook
# webhookType : baz # Type of webhook
# method: POST # Method of webhook
# template: testing # Checkly webhook template
# webhookSecret:
# name: test-secret # Name of the secret or configmap which holds the webhook secret
# namespace: default # Namespace of the secret or configmap
# fieldPath: "SECRET_KEY" # Key inside the secret or configmap
# headers:
# - key: "foo"
# value: "bar"
# locked: true
# queryParameters:
# - key: "bar"
# value: "baz"
# locked: false
79 changes: 78 additions & 1 deletion docs/alert-channels.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,36 @@ See the [official checkly docs](https://www.checklyhq.com/docs/alerting/) on wha

The name of the Alert channel derives from the `metadata.name` of the created kubernetes resource.

We're supporting the email and OpsGenie configurations. You can not specify both in a config as each alert channel can only have one channel, if you want to alert to multiple channels, create a resource for each and later reference them in the check group configuration.
We're supporting the email, OpsGenie and webhook configurations. You can not specify all in a config as each alert channel can only have one channel, if you want to alert to multiple channels, create a resource for each and later reference them in the check group configuration.

### Spec

| Option | Details | Default |
|--------------|-----------|------------|
| `sendRecovery` | Bool; Should recovery alerts be sent | none |
| `sendFailure` | Bool; Should failure alerts be sent | none |
| `sslExpiry` | Bool; Should ssl expiry check alerts be sent | none |
| `sendDegraded` | Bool; Should degraded alerts be sent | none |
| `sslExpiryThreshold` | int; At what moment in time to start alerting on SSL certificates. | none |
| `email.address` | string; Which email address should the alert be sent to | none |
| `opsgenie.apikey.name` | string; Name of the secret or configmap which holds the Opsgenie API key | none |
| `opsgenie.apikey.namespace` | string; Namespace of the secret or configmap | none |
| `opsgenie.apikey.fieldPath` | string; Key inside the secret or configmap | none |
| `webhook.name` | string; Name for the webhook | none |
| `webhook.url` | string; URL for the webhook | none |
| `webhook.webhookType` | string; TODO: can't determine what this is | none |
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could someone please tell me what this is used for? Couldn't determine based on the docs or the console UI.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked into this and it seems like the value is not critical at all. It is mostly used as a bucket for monitoring and metrics purposes, and it may also be used in the frontend for display purposes. If the value is not set, or is set to an unsupported value, then it's effectively just the generic "WEBHOOK".

This is the list of valid values:

WEBHOOK_DISCORD
WEBHOOK_FIREHYDRANT
WEBHOOK_GITLAB_ALERT
WEBHOOK_SPIKESH
WEBHOOK_SPLUNK
WEBHOOK_MSTEAMS
WEBHOOK_TELEGRAM
WEBHOOK_CORALOGIX
WEBHOOK_ILERT

Note: It looks like you can provide an unsupported value as well, as I mentioned above. You will not get a validation error but it will behave the same as if no value was provided in the first place.

| `webhook.method` | string; HTTP type for the webhook (POST/GET/PUT/HEAD/DELETE/PATCH) | none |
| `webhook.template` | string; Template for webhook message | none |
| `webhook.name` | string; Name for the webhook | none |
| `webhook.webhookSecret.name` | string; Name of the secret or configmap which holds the Opsgenie API key | none |
| `webhook.webhookSecret.namespace` | string; Namespace of the secret or configmap | none |
| `webhook.webhookSecret.fieldPath` | string; Key inside the secret or configmap | none |
| `webhook.(*).headers.key` | string; Name for the header key | none |
| `webhook.(*).headers.value` | string; Value of the header | none |
| `webhook.(*).headers.locked` | bool; Is the header value visible in the checklyhq console | none |
| `webhook.(*).queryParameters.key` | string; Name for the query parameter key | none |
| `webhook.(*).queryParameters.value` | string; Value of the query parameter | none |
| `webhook.(*).queryParameters.locked` | bool; Is the query parameter value visible in the checklyhq console | none |

### Email

Expand All @@ -18,6 +47,10 @@ kind: AlertChannel
metadata:
name: checkly-operator-test-email
spec:
sendRecovery: false
sendFailure: true
sslExpiry: true
sslExpiryThreshold: 30
email:
address: "[email protected]"
```
Expand All @@ -35,6 +68,10 @@ kind: AlertChannel
metadata:
name: checkly-operator-test-opsgenie
spec:
sendRecovery: false
sendFailure: true
sslExpiry: true
sslExpiryThreshold: 30
opsgenie:
apikey:
name: test-secret # Name of the secret or configmap which holds the API key
Expand All @@ -44,6 +81,46 @@ spec:
region: "EU" # Your OpsGenie region
```

### Webhook
The webhook integration supports all the fields which are supported by the checkly-go-sdk, see [details](https://pkg.go.dev/github.com/checkly/checkly-go-sdk#AlertChannelWebhook). For other fields and their options, please see [the official docs](https://www.checklyhq.com/docs/alerting-and-retries/webhooks/).

The `WebhookSecret` is an optional field and it requires a kubernetes secret (just like the OpsGenie integration).

Minimum required fields:
* `name` - string
* `url` - string
* `method` - string

```yaml
apiVersion: k8s.checklyhq.com/v1alpha1
kind: AlertChannel
metadata:
name: checkly-operator-test-webhook
spec:
sendRecovery: false
sendFailure: true
sslExpiry: true
sslExpiryThreshold: 30
webhook:
name: foo # Name of the webhook
url: https://foo.bar # URL of the webhook
webhookType : baz # Type of webhook
method: POST # Method of webhook
template: testing # Checkly webhook template
webhookSecret:
name: test-secret # Name of the secret or configmap which holds the webhook secret
namespace: default # Namespace of the secret or configmap
fieldPath: "SECRET_KEY" # Key inside the secret or configmap
headers:
- key: "foo"
value: "bar"
locked: true # Not visible in the UI
queryParameters:
- key: "bar"
value: "baz"
locked: false # Visible in the UI
```

## Referencing

You'll need to reference the name of the alert channel in the group check configuration. See [check-group](check-group.md) for more details.
Loading
Loading