diff --git a/.releaserc b/.releaserc index 207ec09bb..9953dc382 100644 --- a/.releaserc +++ b/.releaserc @@ -8,6 +8,7 @@ plugins: - { type: feat, release: patch } - { type: ci, release: false } - { type: style, release: false } + - { type: major, release: major } parserOpts: noteKeywords: - MAJOR RELEASE diff --git a/README.md b/README.md index e476f4a00..629b50c2c 100644 --- a/README.md +++ b/README.md @@ -1,141 +1,139 @@ -
+

Kubernetes operator for executing synthetic tests

- +

--- +Canary checker is a kubernetes-native platform for monitoring health across application and infrastructure using both passive and active (synthetic) mechanisms. -# Introduction +## Features -Canary Checker is a Kubernetes native multi-tenant synthetic monitoring system. To learn more, see the [docs](https://docs.flanksource.com/canary-checker/overview/). +* **Batteries Included** - 35+ built-in check types +* **Kubernetes Native** - Health checks (or canaries) are CRD's that reflect health via the `status` field, making them compatible with GitOps, [Flux Health Checks](https://fluxcd.io/flux/components/kustomize/kustomization/#health-checks), Argo, Helm, etc.. +* **Secret Management** - Leverage K8S secrets and configmaps for authentication and connection details +* **Prometheus** - Prometheus compatible metrics are exposed at `/metrics`. A Grafana Dashboard is also available. +* **Dependency Free** - Runs an embedded postgres instance by default, can also be configured to use an external database. +* **JUnit Export (CI/CD)** - Export health check results to JUnit format for integration into CI/CD pipelines +* **JUnit Import (k6/newman/puppeter/etc)** - Use any container that creates JUnit test results +* **Scriptable** - Go templates, Javascript and [Expr](https://github.com/antonmedv/expr) can be used to: + * Evaluate whether a check is passing and severity to use when failing + * Extract a user friendly error message + * Transform and filter check responses into individual check results +* **Multi-Modal** - While designed as a Kubernetes Operator, canary checker can also run as a CLI and a server without K8s -# Features +## Getting Started -* Built-in UI/Dashboard -* CRD based configuration and status reporting -* Prometheus Integration -* Runnable as a CLI for once-off checks or as a standalone server outside kubernetes -* Junit formatting for CI/CD integration -* Many built-in check types +1. Install canary checker: -## Getting started - -The easiest way to get started with canary-checker is to run it as CLI, it will take specifications in a YAML / CRD format and execute them before returning. The CLI can be used within CI/CD platforms and also exports to JUnit XML reports. - -1. Install the CLI - -```bash -wget https://github.com/flanksource/canary-checker/releases/latest/download/canary-checker_linux_amd64 \ - -O /usr/bin/canary-checker && \ - chmod +x /usr/bin/canary-checker -``` + ```shell +helm repo add flanksource https://flanksource.github.io/charts +helm repo update +helm install canary-checker + ``` -2. Create a new spec called `http.yaml` +2. Create a new check: -```yaml + ```yaml title="canary.yaml" apiVersion: canaries.flanksource.com/v1 kind: Canary metadata: - name: http-pass + name: http-check spec: interval: 30 http: - - endpoint: https://httpstat.us/200 - thresholdMillis: 3000 - responseCodes: [201, 200, 301] - responseContent: "" - maxSSLExpiry: 7 -``` - -3. Run the canary using: - -```bash -canary-checker run http.yaml -``` - -[![asciicast](https://asciinema.org/a/N3jELGSn8HoRQHPpCdeK7MDBV.svg)](https://asciinema.org/a/N3jELGSn8HoRQHPpCdeK7MDBV) - -### Junit Formating - -Canary checker can export JUnit formatted results for use in CI/CD pipelines - -```bash -canary-checker run http.yaml -j -o results.xml -``` - -## Deploying as Kubernetes Operator + - name: basic-check + url: https://httpbin.demo.aws.flanksource.com/status/200 + - name: failing-check + url: https://httpbin.demo.aws.flanksource.com/status/500 + ``` -1. Deploy the operator +2a. Run the check locally (Optional) -```bash -helm repo add flanksource https://flanksource.github.io/charts -helm repo update -helm install canary-checker-demo \ - --wait \ - -n canary-checker \ - --create-namespace flanksource/canary-checker \ - -f values.yaml +```shell +canary-checker run canary.yaml ``` -```yaml title="values.yaml" -flanksource-ui: - ingress: - host: canary-checker.127.0.0.1.nip.io - annotations: - kubernetes.io/ingress.class: nginx - kubernetes.io/tls-acme: "true" - tls: - - secretName: canary-checker-tls - hosts: - - canary-checker.127.0.0.1.nip.io -``` - -2. Install a canary +[![asciicast](https://asciinema.org/a/cYS6hlmX516JQeECHH7za3IDG.svg)](https://asciinema.org/a/cYS6hlmX516JQeECHH7za3IDG) -```bash -kubectl apply -f https://raw.githubusercontent.com/flanksource/canary-checker/master/fixtures/minimal/http_pass_single.yaml -``` + ```shell + kubectl apply -f canary.yaml + ``` -3. Check the results via the CLI +3. Check the status of the health check: -```bash + ```shell kubectl get canary -``` + ``` ``` title="sample output" NAME INTERVAL STATUS LAST CHECK UPTIME 1H LATENCY 1H LAST TRANSITIONED -http-pass-single 30 Passed 13s 18/18 (100.0%) 480ms 13s +http-check. 30 Passed 13s 18/18 (100.0%) 480ms 13s ``` -### Dashboard - -Canary checker comes with a built-in dashboard for displaying canary results, it can be turned off using `--set flanksource-ui.enabled=false` - -![](https://github.com/flanksource/docs/blob/85bdd4875d0d3ded16b7aa6c132d423852fcad90/docs/images/dashboard-http-pass-canary.png?raw=true) - -### Prometheus - -The helm chart can install a `ServiceMonitor` for the prometheus operator, by enabling the serviceMonitor flag `--set serviceMonitor=true` - -Metrics exposed by canary-checker: - -| Metric | Type | Description | -| ---------------------------------------------- | --------- | ------------------------------------------- | -| canary_check | Guage | Set to 0 when passing and 1 when failing | -| canary_check_success_count | Counter | | -| canary_check_failed_count | Counter | | -| canary_check_info | Info | | -| canary_check_duration | Histogram | Histogram of canary durations | -| **Pod Check Metrics** | | | -| canary_check_histogram{metric="creation_time"} | Histogram | Time for pod to be `Pending` | -| canary_check_histogram{metric="delete_time"} | Histogram | Time to delete pod | -| canary_check_histogram{metric="ingress_time"} | Histogram | Time until ingress is returning requests | -| canary_check_histogram{metric="request_time"} | Histogram | Duration of http request once ingress is up | -| canary_check_histogram{metric="schedule_time"} | Histogram | Time for pod to be `Running` | -| **HTTP Check Metrics** | | | -| canary_check_http_response_status | Counter | Response code counter for each endpoint | +## Getting Help + +If you have any questions about canary checker: + +* Read the [docs](https://canarychecker.io) +* Invite yourself to the [CNCF community slack](https://slack.cncf.io/)and join the [#canary-checker](https://cloud-native.slack.com/messages/canary-checker/) channel. +* Check out the [Youtube Playlist](https://www.youtube.com/playlist?list=PLz4F_KggvA58D6krlw433TNr8qMbu1aIU). +* File an [issue](https://github.com/flanksource/canary-checker/issues/new) - (We do provide user support via Github Issues, so don't worry if your issue a real bug or not) + +Your feedback is always welcome! + +## Check Types + +| Protocol | Status | Checks | +| ------------------------------------------------------------ | ---------- | ------------------------------------------------------------ | +| [HTTP(s)](https://canarychecker.io/reference/http) | GA | Response body, headers and duration | +| [DNS](https://canarychecker.io/reference/dns) | GA | Response and duration | +| [Ping/ICMP](https://canarychecker.io/reference/icmp) | GA | Duration and packet loss | +| [TCP](https://canarychecker.io/reference/tcp) | GA | Port is open and connectable | +| **Data Sources** | | | +| SQL ([MySQL](https://canarychecker.io/reference/mysql), [Postgres](https://canarychecker.io/reference/postgres), [SQL Server](https://canarychecker.io/reference/mssql)) | GA | Ability to login, results, duration, health exposed via stored procedures | +| [LDAP](https://canarychecker.io/reference/ldap) | GA | Ability to login, response time | +| [ElasticSearch / Opensearch](https://canarychecker.io/reference/elasticsearch) | GA | Ability to login, response time, size of search results | +| [Mongo](https://canarychecker.io/reference/mongo) | Beta | Ability to login, results, duration, | +| [Redis](https://canarychecker.io/reference/redis) | GA | Ability to login, results, duration, | +| [Prometheus](https://canarychecker.io/reference/prometheus) | GA | Ability to login, results, duration, | +| **Alerts** | | Prometheus | +| [Prometheus Alert Manager](https://canarychecker.io/reference/alert-manager) | GA | Pending and firing alerts | +| [AWS Cloudwatch Alarms](https://canarychecker.io/reference/cloudwatch) | GA | Pending and firing alarms | +| [Dynatrace Problems](./reference/dynatrace.md) | Beta | Problems deteced | +| **DevOps** | | | +| [Git](https://canarychecker.io/reference/git) | GA | Query Git and Github repositories via SQL | +| [Azure Devops](https://canarychecker.io/reference) | | | +| **Integration Testing** | | | +| [JMeter](https://canarychecker.io/reference/jmeter) | Beta | Runs and checks the result of a JMeter test | +| [JUnit / BYO](https://canarychecker.io/reference/junit) | Beta | Run a pod that saves Junit test results | +| **File Systems / Batch** | | | +| [Local Disk / NFS](https://canarychecker.io/reference/folder) | GA | Check folders for files that are: too few/many, too old/new, too small/large | +| [S3](https://canarychecker.io/reference/s3-bucket) | GA | Check contents of AWS S3 Buckets | +| [GCS](https://canarychecker.io/reference/gcs-bucket) | GA | Check contents of Google Cloud Storage Buckets | +| [SFTP](https://canarychecker.io/reference/sftp) | GA | Check contents of folders over SFTP | +| [SMB / CIFS](../smb) | GA | Check contents of folders over SMB/CIFS | +| **Config** | | | +| [AWS Config](https://canarychecker.io/reference/aws-config) | GA | Query AWS config using SQL | +| [AWS Config Rule](https://canarychecker.io/reference/aws-config-rule) | GA | AWS Config Rules that are firing, Custom AWS Config queries | +| [Config DB](https://canarychecker.io/reference/configdb) | GA | Custom config queries for Mission Control Config D | +| [Kubernetes Resources](https://canarychecker.io/reference/kubernetes) | GA | Kubernetes resources that are missing or are in a non-ready state | +| **Backups** | | | +| [GCP Databases](..refere) | GA | Backup freshness | +| [Restic](https://canarychecker.io/reference/restic) | Beta | Backup freshness and integrity | +| **Infrastructure** | | | +| [EC2](https://canarychecker.io/reference/ec2) | GA | Ability to launch new EC2 instances | +| [Kubernetes Ingress](https://canarychecker.io/reference/pod) | GA | Ability to schedule and then route traffic via an ingress to a pod | +| [Docker/Containerd](https://canarychecker.io/reference/containerd) | Deprecated | Ability to push and pull containers via docker/containerd | +| [Helm](https://canarychecker.io/reference/helm) | Deprecated | Ability to push and pull helm charts | +| [S3 Protocol](https://canarychecker.io/reference/s3-protocol) | GA | Ability to read/write/list objects on an S3 compatible object store | + +## License + +Canary Checker core (the code in this repository) is licensed under [Apache 2.0](https://raw.githubusercontent.com/flanksource/canary-checker/main/LICENSE) and accepts contributions via GitHub pull requests after signing a CLA. + +The UI (Dashboard) is free to use with canary checker under a license exception of [Flanksource UI](https://github.com/flanksource/flanksource-ui/blob/main/LICENSE#L7) diff --git a/api/context/context.go b/api/context/context.go index 088bbb592..33b02b749 100644 --- a/api/context/context.go +++ b/api/context/context.go @@ -9,6 +9,7 @@ import ( v1 "github.com/flanksource/canary-checker/api/v1" "github.com/flanksource/commons/logger" + ctemplate "github.com/flanksource/commons/template" "github.com/flanksource/duty" "github.com/flanksource/duty/models" "github.com/flanksource/duty/types" @@ -55,12 +56,90 @@ func (ctx *Context) GetEnvValueFromCache(env types.EnvVar) (string, error) { return duty.GetEnvValueFromCache(ctx.Kubernetes, env, ctx.Namespace) } +func getDomain(username string) string { + parts := strings.Split(username, "@") + if len(parts) == 2 { + return parts[1] + } + return "" +} + +func (ctx *Context) GetConnection(conn v1.Connection) (*models.Connection, error) { + var _conn *models.Connection + var err error + + if _conn, err = ctx.HydrateConnectionByURL(conn.Connection); err != nil { + return nil, err + } + + if _conn == nil { + _conn = &models.Connection{ + URL: conn.URL, + } + } + + if conn.URL != "" { + // override the url specified at the connection level + _conn.URL = conn.URL + } + + if _conn.Username == "" || _conn.Password == "" { + // no username specified at connection level, use the one from inline connection + auth, err := ctx.GetAuthValues(conn.Authentication) + if err != nil { + return nil, err + } + _conn.Username = auth.Username.ValueStatic + _conn.Password = auth.Password.ValueStatic + } + + data := map[string]interface{}{ + "name": ctx.Canary.Name, + "namespace": ctx.Namespace, + "username": _conn.Username, + "password": _conn.Password, + "domain": getDomain(_conn.Username), + } + templater := ctemplate.StructTemplater{ + Values: data, + // access go values in template requires prefix everything with . + // to support $(username) instead of $(.username) we add a function for each var + ValueFunctions: true, + DelimSets: []ctemplate.Delims{ + {Left: "{{", Right: "}}"}, + {Left: "$(", Right: ")"}, + }, + RequiredTag: "template", + } + if err := templater.Walk(_conn); err != nil { + return nil, err + } + + return _conn, nil +} + +func (ctx Context) GetAuthValues(auth v1.Authentication) (v1.Authentication, error) { + // in case nil we are sending empty string values for username and password + if auth.IsEmpty() { + return auth, nil + } + var err error + + if auth.Username.ValueStatic, err = ctx.GetEnvValueFromCache(auth.Username); err != nil { + return auth, err + } + if auth.Password.ValueStatic, err = ctx.GetEnvValueFromCache(auth.Password); err != nil { + return auth, err + } + return auth, nil +} + func (ctx *Context) HydrateConnectionByURL(connectionName string) (*models.Connection, error) { - if !strings.HasPrefix(connectionName, "connection://") { + if connectionName == "" { return nil, nil } - if connectionName == "" { + if !strings.HasPrefix(connectionName, "connection://") { return nil, nil } diff --git a/api/v1/checks.go b/api/v1/checks.go index d73c7adf1..5df6ce171 100644 --- a/api/v1/checks.go +++ b/api/v1/checks.go @@ -53,9 +53,8 @@ func (c Check) GetLabels() map[string]string { type HTTPCheck struct { Description `yaml:",inline" json:",inline"` Templatable `yaml:",inline" json:",inline"` - // Name of the connection that'll be used to derive the endpoint. - ConnectionName string `yaml:"connection,omitempty" json:"connection,omitempty"` - // HTTP endpoint to check. Mutually exclusive with Namespace + Connection `yaml:",inline" json:",inline"` + // Deprecated: Use url instead Endpoint string `yaml:"endpoint" json:"endpoint,omitempty" template:"true"` // Namespace to crawl for TLS endpoints. Mutually exclusive with Endpoint Namespace string `yaml:"namespace,omitempty" json:"namespace,omitempty" template:"true"` @@ -79,16 +78,10 @@ type HTTPCheck struct { Body string `yaml:"body,omitempty" json:"body,omitempty" template:"true"` // Header fields to be used in the query Headers []types.EnvVar `yaml:"headers,omitempty" json:"headers,omitempty"` - // Credentials for authentication headers - Authentication *Authentication `yaml:"authentication,omitempty" json:"authentication,omitempty"` //Template the request body TemplateBody bool `yaml:"templateBody,omitempty" json:"templateBody,omitempty"` } -func (c HTTPCheck) GetEndpoint() string { - return c.Endpoint -} - func (c HTTPCheck) GetType() string { return "http" } @@ -151,10 +144,10 @@ func (c S3Check) GetType() string { } type CloudWatchCheck struct { - Description `yaml:",inline" json:",inline"` - AWSConnection `yaml:",inline" json:",inline"` - Templatable `yaml:",inline" json:",inline"` - Filter CloudWatchFilter `yaml:"filter,omitempty" json:"filter,omitempty"` + Description `yaml:",inline" json:",inline"` + AWSConnection `yaml:",inline" json:",inline"` + Templatable `yaml:",inline" json:",inline"` + CloudWatchFilter `yaml:",inline" json:",inline"` } type CloudWatchFilter struct { @@ -166,11 +159,11 @@ type CloudWatchFilter struct { func (c CloudWatchCheck) GetEndpoint() string { endpoint := c.Region - if c.Filter.ActionPrefix != nil { - endpoint += "-" + *c.Filter.ActionPrefix + if c.CloudWatchFilter.ActionPrefix != nil { + endpoint += "-" + *c.CloudWatchFilter.ActionPrefix } - if c.Filter.AlarmPrefix != nil { - endpoint += "-" + *c.Filter.AlarmPrefix + if c.CloudWatchFilter.AlarmPrefix != nil { + endpoint += "-" + *c.CloudWatchFilter.AlarmPrefix } return endpoint } @@ -211,8 +204,6 @@ func (c ResticCheck) GetType() string { type JmeterCheck struct { Description `yaml:",inline" json:",inline"` - // Name of the connection that'll be used to derive host and other connection details. - ConnectionName string `yaml:"connection,omitempty" json:"connection,omitempty"` // Jmx defines the ConfigMap or Secret reference to get the JMX test plan Jmx types.EnvVar `yaml:"jmx" json:"jmx"` // Host is the server against which test plan needs to be executed @@ -235,28 +226,6 @@ func (c JmeterCheck) GetType() string { return "jmeter" } -// HydrateConnection will attempt to populate the host and port from the connection name. -func (c *JmeterCheck) HydrateConnection(ctx checkContext) (bool, error) { - connection, err := ctx.HydrateConnectionByURL(c.ConnectionName) - if err != nil { - return false, err - } - - if connection == nil { - return false, nil - } - - c.Host = connection.URL - - if portRaw, ok := connection.Properties["port"]; ok { - if port, err := strconv.Atoi(portRaw); nil == err { - c.Port = int32(port) - } - } - - return true, nil -} - type DockerPullCheck struct { Description `yaml:",inline" json:",inline"` Image string `yaml:"image" json:"image"` @@ -320,12 +289,10 @@ func (c ContainerdPushCheck) GetType() string { type RedisCheck struct { Description `yaml:",inline" json:",inline"` - // ConnectionName is the name of the connection. - // It is used to populate addr, db and auth. - ConnectionName string `yaml:"connection,omitempty" json:"connection,omitempty"` - Addr string `yaml:"addr" json:"addr" template:"true"` - Auth *Authentication `yaml:"auth,omitempty" json:"auth,omitempty"` - DB int `yaml:"db" json:"db"` + Connection `yaml:",inline" json:",inline"` + // Deprecated: Use url instead + Addr string `yaml:"addr,omitempty" json:"addr,omitempty" template:"true"` + DB *int `yaml:"db,omitempty" json:"db,omitempty"` } func (c RedisCheck) GetType() string { @@ -430,14 +397,12 @@ type Mongo struct { } type OpenSearchCheck struct { - Description `yaml:",inline" json:",inline"` - Templatable `yaml:",inline" json:",inline"` - ConnectionName string `yaml:"connection,omitempty" json:"connection,omitempty"` - URL string `yaml:"url,omitempty" json:"url,omitempty"` - Auth Authentication `yaml:"auth" json:"auth"` - Query string `yaml:"query" json:"query"` - Index string `yaml:"index" json:"index"` - Results int64 `yaml:"results,omitempty" json:"results,omitempty"` + Description `yaml:",inline" json:",inline"` + Templatable `yaml:",inline" json:",inline"` + Connection `yaml:",inline" json:",inline"` + Query string `yaml:"query" json:"query"` + Index string `yaml:"index" json:"index"` + Results int64 `yaml:"results,omitempty" json:"results,omitempty"` } func (c OpenSearchCheck) GetType() string { @@ -448,34 +413,6 @@ func (c OpenSearchCheck) GetEndpoint() string { return c.URL } -func (c *OpenSearchCheck) HydrateConnection(ctx checkContext) error { - connection, err := ctx.HydrateConnectionByURL(c.ConnectionName) - if err != nil { - return err - } - - if connection != nil { - c.URL = connection.URL - c.Auth.Username.ValueStatic = connection.Username - c.Auth.Password.ValueStatic = connection.Password - return nil - } - - if val, err := ctx.GetEnvValueFromCache(c.Auth.Username); err != nil { - return fmt.Errorf("failed to get username from cache: %w", err) - } else { - c.Auth.Username.ValueStatic = val - } - - if val, err := ctx.GetEnvValueFromCache(c.Auth.Password); err != nil { - return fmt.Errorf("failed to get username from cache: %w", err) - } else { - c.Auth.Password.ValueStatic = val - } - - return nil -} - /* [include:datasources/elasticsearch_pass.yaml] */ @@ -485,59 +422,26 @@ type Elasticsearch struct { } type ElasticsearchCheck struct { - Description `yaml:",inline" json:",inline"` - Templatable `yaml:",inline" json:",inline"` - ConnectionName string `yaml:"connection,omitempty" json:"connection,omitempty"` - URL string `yaml:"url" json:"url,omitempty" template:"true"` - Auth *Authentication `yaml:"auth,omitempty" json:"auth,omitempty"` - Query string `yaml:"query" json:"query,omitempty" template:"true"` - Index string `yaml:"index" json:"index,omitempty" template:"true"` - Results int `yaml:"results" json:"results,omitempty" template:"true"` + Description `yaml:",inline" json:",inline"` + Templatable `yaml:",inline" json:",inline"` + Connection `yaml:",inline" json:",inline"` + Query string `yaml:"query" json:"query,omitempty" template:"true"` + Index string `yaml:"index" json:"index,omitempty" template:"true"` + Results int `yaml:"results" json:"results,omitempty" template:"true"` } func (c ElasticsearchCheck) GetType() string { return "elasticsearch" } -func (c ElasticsearchCheck) GetEndpoint() string { - return c.URL -} - -func (c *ElasticsearchCheck) HydrateConnection(ctx checkContext) error { - connection, err := ctx.HydrateConnectionByURL(c.ConnectionName) - if err != nil { - return err - } - - if connection != nil { - c.URL = connection.URL - c.Auth.Username.ValueStatic = connection.Username - c.Auth.Password.ValueStatic = connection.Password - return nil - } - - if val, err := ctx.GetEnvValueFromCache(c.Auth.Username); err != nil { - return fmt.Errorf("failed to get username from cache: %w", err) - } else { - c.Auth.Username.ValueStatic = val - } - - if val, err := ctx.GetEnvValueFromCache(c.Auth.Password); err != nil { - return fmt.Errorf("failed to get password from cache: %w", err) - } else { - c.Auth.Password.ValueStatic = val - } - - return nil -} - type DynatraceCheck struct { - Description `yaml:",inline" json:",inline"` - Templatable `yaml:",inline" json:",inline"` - Host string `yaml:"host" json:"host,omitempty" template:"true"` - Scheme string `yaml:"scheme" json:"scheme,omitempty"` - APIKey types.EnvVar `yaml:"apiKey" json:"apiKey,omitempty"` - Namespace string `yaml:"namespace" json:"namespace,omitempty" template:"true"` + Description `yaml:",inline" json:",inline"` + Templatable `yaml:",inline" json:",inline"` + ConnectionName string `yaml:"connection,omitempty" json:"connection,omitempty"` + Host string `yaml:"host" json:"host,omitempty" template:"true"` + Scheme string `yaml:"scheme" json:"scheme,omitempty"` + APIKey types.EnvVar `yaml:"apiKey" json:"apiKey,omitempty"` + Namespace string `yaml:"namespace" json:"namespace,omitempty" template:"true"` } func (t DynatraceCheck) GetType() string { @@ -557,24 +461,18 @@ type AlertManager struct { } type AlertManagerCheck struct { - Description `yaml:",inline" json:",inline"` - Templatable `yaml:",inline" json:",inline"` - ConnectionName string `yaml:"connection,omitempty" json:"connection,omitempty"` - Host string `yaml:"host" json:"host,omitempty" template:"true"` - Auth *Authentication `yaml:"auth,omitempty" json:"auth,omitempty"` - Alerts []string `yaml:"alerts" json:"alerts,omitempty" template:"true"` - Filters map[string]string `yaml:"filters" json:"filters,omitempty" template:"true"` - Ignore []string `yaml:"ignore" json:"ignore,omitempty" template:"true"` + Description `yaml:",inline" json:",inline"` + Templatable `yaml:",inline" json:",inline"` + Connection `yaml:",inline" json:",inline"` + Alerts []string `yaml:"alerts" json:"alerts,omitempty" template:"true"` + Filters map[string]string `yaml:"filters" json:"filters,omitempty" template:"true"` + Ignore []string `yaml:"ignore" json:"ignore,omitempty" template:"true"` } func (c AlertManagerCheck) GetType() string { return "alertmanager" } -func (c AlertManagerCheck) GetEndpoint() string { - return c.Host -} - type PodCheck struct { Description `yaml:",inline" json:",inline"` Namespace string `yaml:"namespace" json:"namespace,omitempty" template:"true"` @@ -609,45 +507,17 @@ func (c PodCheck) GetType() string { } type LDAPCheck struct { - Description `yaml:",inline" json:",inline"` - ConnectionName string `yaml:"connection,omitempty" json:"connection,omitempty"` - Host string `yaml:"host" json:"host" template:"true"` - Auth *Authentication `yaml:"auth" json:"auth"` - BindDN string `yaml:"bindDN" json:"bindDN"` - UserSearch string `yaml:"userSearch,omitempty" json:"userSearch,omitempty"` - SkipTLSVerify bool `yaml:"skipTLSVerify,omitempty" json:"skipTLSVerify,omitempty"` -} - -func (c LDAPCheck) GetEndpoint() string { - return c.Host + Description `yaml:",inline" json:",inline"` + Connection `yaml:",inline" json:",inline"` + BindDN string `yaml:"bindDN" json:"bindDN"` + UserSearch string `yaml:"userSearch,omitempty" json:"userSearch,omitempty"` + SkipTLSVerify bool `yaml:"skipTLSVerify,omitempty" json:"skipTLSVerify,omitempty"` } func (c LDAPCheck) GetType() string { return "ldap" } -func (c *LDAPCheck) HydrateConnection(ctx checkContext) (bool, error) { - connection, err := ctx.HydrateConnectionByURL(c.ConnectionName) - if err != nil { - return false, err - } - - if connection == nil { - return false, nil - } - - c.Host = connection.URL - c.Auth.Username.ValueStatic = connection.Username - c.Auth.Password.ValueStatic = connection.Password - - c.Auth = &Authentication{ - Username: types.EnvVar{ValueStatic: c.Auth.Username.ValueStatic}, - Password: types.EnvVar{ValueStatic: c.Auth.Password.ValueStatic}, - } - - return true, nil -} - type NamespaceCheck struct { Description `yaml:",inline" json:",inline"` NamespaceNamePrefix string `yaml:"namespaceNamePrefix,omitempty" json:"namespaceNamePrefix,omitempty"` @@ -768,16 +638,10 @@ type SMBConnection struct { // ConnectionName of the connection. It'll be used to populate the connection fields. ConnectionName string `yaml:"connection,omitempty" json:"connection,omitempty"` //Port on which smb server is running. Defaults to 445 - Port int `yaml:"port,omitempty" json:"port,omitempty"` - Auth *Authentication `yaml:"auth" json:"auth"` + Port int `yaml:"port,omitempty" json:"port,omitempty"` + Authentication `yaml:",inline" json:",inline"` //Domain... Domain string `yaml:"domain,omitempty" json:"domain,omitempty"` - // Workstation... - Workstation string `yaml:"workstation,omitempty" json:"workstation,omitempty"` - //Sharename to mount from the samba server - Sharename string `yaml:"sharename,omitempty" json:"sharename,omitempty"` - //SearchPath sub-path inside the mount location - SearchPath string `yaml:"searchPath,omitempty" json:"searchPath,omitempty" ` } func (c SMBConnection) GetPort() int { @@ -797,27 +661,15 @@ func (c *SMBConnection) HydrateConnection(ctx checkContext) (found bool, err err return false, nil } - c.Auth = &Authentication{ + c.Authentication = Authentication{ Username: types.EnvVar{ValueStatic: connection.Username}, Password: types.EnvVar{ValueStatic: connection.Password}, } - if workstation, ok := connection.Properties["workstation"]; ok { - c.Workstation = workstation - } - if domain, ok := connection.Properties["domain"]; ok { c.Domain = domain } - if sharename, ok := connection.Properties["sharename"]; ok { - c.Sharename = sharename - } - - if searchPath, ok := connection.Properties["searchPath"]; ok { - c.SearchPath = searchPath - } - if portRaw, ok := connection.Properties["port"]; ok { if port, err := strconv.Atoi(portRaw); nil == err { c.Port = port @@ -831,9 +683,9 @@ type SFTPConnection struct { // ConnectionName of the connection. It'll be used to populate the connection fields. ConnectionName string `yaml:"connection,omitempty" json:"connection,omitempty"` // Port for the SSH server. Defaults to 22 - Port int `yaml:"port,omitempty" json:"port,omitempty"` - Host string `yaml:"host" json:"host"` - Auth *Authentication `yaml:"auth" json:"auth"` + Port int `yaml:"port,omitempty" json:"port,omitempty"` + Host string `yaml:"host" json:"host"` + Authentication `yaml:",inline" json:",inline"` } func (c *SFTPConnection) HydrateConnection(ctx checkContext) (found bool, err error) { @@ -847,7 +699,7 @@ func (c *SFTPConnection) HydrateConnection(ctx checkContext) (found bool, err er } c.Host = connection.URL - c.Auth = &Authentication{ + c.Authentication = Authentication{ Username: types.EnvVar{ValueStatic: connection.Username}, Password: types.EnvVar{ValueStatic: connection.Password}, } @@ -876,11 +728,11 @@ type Prometheus struct { } type PrometheusCheck struct { - Description `yaml:",inline" json:",inline"` - Templatable `yaml:",inline" json:",inline"` - ConnectionName string `yaml:"connection,omitempty" json:"connection,omitempty"` - // Address of the prometheus server - Host string `yaml:"host" json:"host" template:"true" ` + Description `yaml:",inline" json:",inline"` + Templatable `yaml:",inline" json:",inline"` + // Deprecated: use `url` instead + Host string `yaml:"host,omitempty" json:"host,omitempty"` + Connection `yaml:",inline" json:",inline"` // PromQL query Query string `yaml:"query" json:"query" template:"true"` } @@ -889,28 +741,9 @@ func (c PrometheusCheck) GetType() string { return "prometheus" } -func (c PrometheusCheck) GetEndpoint() string { - return fmt.Sprintf("%v/%v", c.Host, c.Description) -} - -func (c *PrometheusCheck) HydrateConnection(ctx checkContext) (bool, error) { - connection, err := ctx.HydrateConnectionByURL(c.ConnectionName) - if err != nil { - return false, err - } - - if connection == nil { - return false, nil - } - - c.Host = connection.URL - return true, nil -} - type MongoDBCheck struct { Description `yaml:",inline" json:",inline"` - // Monogodb connection string, e.g. mongodb://:27017/?authSource=admin, See https://docs.mongodb.com/manual/reference/connection-string/ - Connection `yaml:",inline" json:",inline"` + Connection `yaml:",inline" json:",inline"` } func (c MongoDBCheck) GetType() string { @@ -978,13 +811,6 @@ func (c KubernetesCheck) GetEndpoint() string { return fmt.Sprintf("%v/%v/%v", c.Kind, c.Description.Description, c.Namespace.Name) } -func (c KubernetesCheck) CheckReady() bool { - if c.Ready == nil { - return true - } - return *c.Ready -} - type AWSConnection struct { // ConnectionName of the connection. It'll be used to populate the endpoint, accessKey and secretKey. ConnectionName string `yaml:"connection,omitempty" json:"connection,omitempty"` @@ -1011,7 +837,16 @@ func (t *AWSConnection) Populate(ctx checkContext, k8s kubernetes.Interface, nam t.AccessKey.ValueStatic = connection.Username t.SecretKey.ValueStatic = connection.Password - t.Endpoint = connection.URL + if t.Endpoint == "" { + t.Endpoint = connection.URL + } + + t.SkipTLSVerify = connection.InsecureTLS + if t.Region == "" { + if region, ok := connection.Properties["region"]; ok { + t.Region = region + } + } } if accessKey, err := duty.GetEnvValueFromCache(k8s, t.AccessKey, namespace); err != nil { @@ -1107,7 +942,7 @@ type AwsConfigCheck struct { Description `yaml:",inline" json:",inline"` Templatable `yaml:",inline" json:",inline"` Query string `yaml:"query" json:"query"` - *AWSConnection `yaml:"awsConnection,omitempty" json:"awsConnection,omitempty"` + *AWSConnection `yaml:",inline" json:",inline"` AggregatorName *string `yaml:"aggregatorName,omitempty" json:"aggregatorName,omitempty"` } @@ -1128,7 +963,7 @@ type AwsConfigRuleCheck struct { Rules []string `yaml:"rules,omitempty" json:"rules,omitempty"` // Filters the results by compliance. The allowed values are INSUFFICIENT_DATA, NON_COMPLIANT, NOT_APPLICABLE, COMPLIANT ComplianceTypes []string `yaml:"complianceTypes,omitempty" json:"complianceTypes,omitempty"` - *AWSConnection `yaml:"awsConnection,omitempty" json:"awsConnection,omitempty"` + *AWSConnection `yaml:",inline" json:",inline"` } func (c AwsConfigRuleCheck) GetType() string { diff --git a/api/v1/common.go b/api/v1/common.go index 82e303b36..f37f15876 100644 --- a/api/v1/common.go +++ b/api/v1/common.go @@ -169,8 +169,8 @@ type JSONCheck struct { } type Authentication struct { - Username types.EnvVar `yaml:"username" json:"username"` - Password types.EnvVar `yaml:"password" json:"password"` + Username types.EnvVar `yaml:"username,omitempty" json:"username,omitempty"` + Password types.EnvVar `yaml:"password,omitempty" json:"password,omitempty"` } func (auth Authentication) IsEmpty() bool { @@ -306,21 +306,15 @@ func (d Description) GetLabels() map[string]string { } type Connection struct { - Connection string `yaml:"connection" json:"connection" template:"true"` - Authentication Authentication `yaml:"auth,omitempty" json:"auth,omitempty"` -} - -// +k8s:deepcopy-gen=false -type Connectable interface { - GetConnection() string -} - -func (c Connection) GetConnection() string { - return c.Connection + // Connection name e.g. connection://http/google + Connection string `yaml:"connection,omitempty" json:"connection,omitempty"` + // Connection url, interpolated with username,password + URL string `yaml:"url,omitempty" json:"url,omitempty" template:"true"` + Authentication `yaml:",inline" json:",inline"` } func (c Connection) GetEndpoint() string { - return sanitizeEndpoints(c.Connection) + return sanitizeEndpoints(c.URL) } // Obfuscate passwords of the form ' password=xxxxx ' from connectionString since diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go index 92c41197d..ced6151af 100644 --- a/api/v1/zz_generated.deepcopy.go +++ b/api/v1/zz_generated.deepcopy.go @@ -66,11 +66,7 @@ func (in *AlertManagerCheck) DeepCopyInto(out *AlertManagerCheck) { *out = *in in.Description.DeepCopyInto(&out.Description) out.Templatable = in.Templatable - if in.Auth != nil { - in, out := &in.Auth, &out.Auth - *out = new(Authentication) - (*in).DeepCopyInto(*out) - } + in.Connection.DeepCopyInto(&out.Connection) if in.Alerts != nil { in, out := &in.Alerts, &out.Alerts *out = make([]string, len(*in)) @@ -745,7 +741,7 @@ func (in *CloudWatchCheck) DeepCopyInto(out *CloudWatchCheck) { in.Description.DeepCopyInto(&out.Description) in.AWSConnection.DeepCopyInto(&out.AWSConnection) out.Templatable = in.Templatable - in.Filter.DeepCopyInto(&out.Filter) + in.CloudWatchFilter.DeepCopyInto(&out.CloudWatchFilter) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CloudWatchCheck. @@ -1528,11 +1524,7 @@ func (in *ElasticsearchCheck) DeepCopyInto(out *ElasticsearchCheck) { *out = *in in.Description.DeepCopyInto(&out.Description) out.Templatable = in.Templatable - if in.Auth != nil { - in, out := &in.Auth, &out.Auth - *out = new(Authentication) - (*in).DeepCopyInto(*out) - } + in.Connection.DeepCopyInto(&out.Connection) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ElasticsearchCheck. @@ -1826,6 +1818,7 @@ func (in *HTTPCheck) DeepCopyInto(out *HTTPCheck) { *out = *in in.Description.DeepCopyInto(&out.Description) out.Templatable = in.Templatable + in.Connection.DeepCopyInto(&out.Connection) if in.ResponseCodes != nil { in, out := &in.ResponseCodes, &out.ResponseCodes *out = make([]int, len(*in)) @@ -1843,11 +1836,6 @@ func (in *HTTPCheck) DeepCopyInto(out *HTTPCheck) { (*in)[i].DeepCopyInto(&(*out)[i]) } } - if in.Authentication != nil { - in, out := &in.Authentication, &out.Authentication - *out = new(Authentication) - (*in).DeepCopyInto(*out) - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPCheck. @@ -2090,11 +2078,7 @@ func (in *LDAP) DeepCopy() *LDAP { func (in *LDAPCheck) DeepCopyInto(out *LDAPCheck) { *out = *in in.Description.DeepCopyInto(&out.Description) - if in.Auth != nil { - in, out := &in.Auth, &out.Auth - *out = new(Authentication) - (*in).DeepCopyInto(*out) - } + in.Connection.DeepCopyInto(&out.Connection) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LDAPCheck. @@ -2297,7 +2281,7 @@ func (in *OpenSearchCheck) DeepCopyInto(out *OpenSearchCheck) { *out = *in in.Description.DeepCopyInto(&out.Description) out.Templatable = in.Templatable - in.Auth.DeepCopyInto(&out.Auth) + in.Connection.DeepCopyInto(&out.Connection) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenSearchCheck. @@ -2400,6 +2384,7 @@ func (in *PrometheusCheck) DeepCopyInto(out *PrometheusCheck) { *out = *in in.Description.DeepCopyInto(&out.Description) out.Templatable = in.Templatable + in.Connection.DeepCopyInto(&out.Connection) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrometheusCheck. @@ -2493,10 +2478,11 @@ func (in *Redis) DeepCopy() *Redis { func (in *RedisCheck) DeepCopyInto(out *RedisCheck) { *out = *in in.Description.DeepCopyInto(&out.Description) - if in.Auth != nil { - in, out := &in.Auth, &out.Auth - *out = new(Authentication) - (*in).DeepCopyInto(*out) + in.Connection.DeepCopyInto(&out.Connection) + if in.DB != nil { + in, out := &in.DB, &out.DB + *out = new(int) + **out = **in } } @@ -2642,11 +2628,7 @@ func (in *S3Check) DeepCopy() *S3Check { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SFTPConnection) DeepCopyInto(out *SFTPConnection) { *out = *in - if in.Auth != nil { - in, out := &in.Auth, &out.Auth - *out = new(Authentication) - (*in).DeepCopyInto(*out) - } + in.Authentication.DeepCopyInto(&out.Authentication) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SFTPConnection. @@ -2662,11 +2644,7 @@ func (in *SFTPConnection) DeepCopy() *SFTPConnection { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SMBConnection) DeepCopyInto(out *SMBConnection) { *out = *in - if in.Auth != nil { - in, out := &in.Auth, &out.Auth - *out = new(Authentication) - (*in).DeepCopyInto(*out) - } + in.Authentication.DeepCopyInto(&out.Authentication) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SMBConnection. diff --git a/chart/Chart.yaml b/chart/Chart.yaml index e0a6d188b..e97ac6069 100644 --- a/chart/Chart.yaml +++ b/chart/Chart.yaml @@ -1,15 +1,15 @@ apiVersion: v2 name: canary-checker -description: a Kubernetes native, multi-tenant synthetic monitoring system +description: Kubernetes native, multi-tenant synthetic monitoring system type: application version: 0.0.0 appVersion: "master" maintainers: - name: Flanksource url: https://www.flanksource.com -icon: https://avatars.githubusercontent.com/u/58787470 +icon: https://github.com/flanksource/docs/blob/main/docs/canary-checker/images/canary-checker-icon.svg dependencies: - name: flanksource-ui - version: "1.0.143" + version: "1.0.395" repository: https://flanksource.github.io/charts condition: flanksource-ui.enabled diff --git a/checks/alertmanager.go b/checks/alertmanager.go index 6ea68c9a3..3cdb1f447 100644 --- a/checks/alertmanager.go +++ b/checks/alertmanager.go @@ -33,14 +33,13 @@ func (c *AlertManagerChecker) Check(ctx *context.Context, extConfig external.Che result := pkg.Success(check, ctx.Canary) results = append(results, result) - if connection, err := ctx.HydrateConnectionByURL(check.ConnectionName); err != nil { - return results.Failf("failed to find connection from %q: %v", check.ConnectionName, err) - } else if connection != nil { - check.Host = connection.URL + connection, err := ctx.GetConnection(check.Connection) + if err != nil { + return results.Failf("error getting connection: %v", err) } client := alertmanagerClient.NewHTTPClientWithConfig(nil, &alertmanagerClient.TransportConfig{ - Host: check.GetEndpoint(), + Host: connection.URL, Schemes: []string{"http", "https"}, BasePath: alertmanagerClient.DefaultBasePath, }) @@ -91,15 +90,29 @@ func extractMessage(annotations map[string]string) string { } func generateFullName(name string, labels map[string]string) string { - // We add alert metadata to the check name based on priority order - priorityOrder := []string{"namespace", "node", "deployment", "daemonset", "job_name", "pod", "container"} - fullName := []string{name} - for _, key := range priorityOrder { + + // We add alert metadata to the check name + level1 := []string{"namespace", "node"} + for _, key := range level1 { + if labels[key] != "" { + fullName = append(fullName, labels[key]) + } + } + + // Only one of these labels must be used + level2 := []string{"deployment", "daemonset", "cronjob_name", "job_name", "pod"} + for _, key := range level2 { if labels[key] != "" { fullName = append(fullName, labels[key]) + break } } + // Add container name if it exists + if labels["container"] != "" { + fullName = append(fullName, labels["container"]) + } + return strings.Join(fullName, "/") } diff --git a/checks/cloudwatch.go b/checks/cloudwatch.go index 2b4a85d45..aeb745aae 100644 --- a/checks/cloudwatch.go +++ b/checks/cloudwatch.go @@ -49,10 +49,10 @@ func (c *CloudWatchChecker) Check(ctx *context.Context, extConfig external.Check client := cloudwatch.NewFromConfig(*cfg) maxRecords := int32(100) alarms, err := client.DescribeAlarms(ctx, &cloudwatch.DescribeAlarmsInput{ - AlarmNames: check.Filter.Alarms, - AlarmNamePrefix: check.Filter.AlarmPrefix, - ActionPrefix: check.Filter.ActionPrefix, - StateValue: types.StateValue(check.Filter.State), + AlarmNames: check.CloudWatchFilter.Alarms, + AlarmNamePrefix: check.CloudWatchFilter.AlarmPrefix, + ActionPrefix: check.CloudWatchFilter.ActionPrefix, + StateValue: types.StateValue(check.CloudWatchFilter.State), MaxRecords: &maxRecords, }) if err != nil { diff --git a/checks/common.go b/checks/common.go index c45e3df8e..4d4708bcf 100644 --- a/checks/common.go +++ b/checks/common.go @@ -12,66 +12,9 @@ import ( "github.com/flanksource/canary-checker/pkg" "github.com/flanksource/canary-checker/pkg/utils" "github.com/flanksource/canary-checker/templating" - ctemplate "github.com/flanksource/commons/template" "github.com/robfig/cron/v3" ) -func GetConnection(ctx *context.Context, conn *v1.Connection, namespace string) (string, error) { - // TODO: this function should not be necessary, each check should be templated out individual - // however, the walk method only support high level values, not values from siblings. - - if conn.Authentication.IsEmpty() { - return conn.Connection, nil - } - - auth, err := GetAuthValues(ctx, &conn.Authentication) - if err != nil { - return "", err - } - - clone := conn.DeepCopy() - - data := map[string]interface{}{ - "name": ctx.Canary.Name, - "namespace": namespace, - "username": auth.GetUsername(), - "password": auth.GetPassword(), - "domain": auth.GetDomain(), - } - templater := ctemplate.StructTemplater{ - Values: data, - // access go values in template requires prefix everything with . - // to support $(username) instead of $(.username) we add a function for each var - ValueFunctions: true, - DelimSets: []ctemplate.Delims{ - {Left: "{{", Right: "}}"}, - {Left: "$(", Right: ")"}, - }, - RequiredTag: "template", - } - if err := templater.Walk(clone); err != nil { - return "", err - } - - return clone.Connection, nil -} - -func GetAuthValues(ctx *context.Context, auth *v1.Authentication) (*v1.Authentication, error) { - // in case nil we are sending empty string values for username and password - if auth == nil { - return auth, nil - } - var err error - - if auth.Username.ValueStatic, err = ctx.GetEnvValueFromCache(auth.Username); err != nil { - return nil, err - } - if auth.Password.ValueStatic, err = ctx.GetEnvValueFromCache(auth.Password); err != nil { - return nil, err - } - return auth, nil -} - func age(t time.Time) string { return utils.Age(time.Since(t)) } diff --git a/checks/elasticsearch.go b/checks/elasticsearch.go index 688ebe411..c51840952 100644 --- a/checks/elasticsearch.go +++ b/checks/elasticsearch.go @@ -34,14 +34,15 @@ func (c *ElasticsearchChecker) Check(ctx *context.Context, extConfig external.Ch var results pkg.Results results = append(results, result) - if err := check.HydrateConnection(ctx); err != nil { - return results.Failf("Failed to find connection for elastic search: %v", err) + connection, err := ctx.GetConnection(check.Connection) + if err != nil { + return results.Failf("error getting connection: %v", err) } cfg := elasticsearch.Config{ - Addresses: []string{check.GetEndpoint()}, - Username: check.Auth.GetUsername(), - Password: check.Auth.GetPassword(), + Addresses: []string{connection.URL}, + Username: connection.Username, + Password: connection.Password, } es, err := elasticsearch.NewClient(cfg) @@ -67,7 +68,7 @@ func (c *ElasticsearchChecker) Check(ctx *context.Context, extConfig external.Ch fmt.Errorf("Error parsing the response body: %s", err), ) } else { - return results.ErrorMessage(fmt.Errorf("Error from elasticsearch.[%s]: %v, %v", + return results.ErrorMessage(fmt.Errorf("Error from elasticsearch [%s]: %v, %v", res.Status(), e["error"].(map[string]interface{})["type"], e["error"].(map[string]interface{})["reason"], diff --git a/checks/folder_sftp.go b/checks/folder_sftp.go index 77bdaf8fa..22df10b29 100644 --- a/checks/folder_sftp.go +++ b/checks/folder_sftp.go @@ -20,9 +20,9 @@ func CheckSFTP(ctx *context.Context, check v1.FolderCheck) pkg.Results { return results.Failf("failed to populate SFTP connection: %v", err) } - auth := check.SFTPConnection.Auth + auth := check.SFTPConnection.Authentication if !foundConn { - auth, err = GetAuthValues(ctx, check.SFTPConnection.Auth) + auth, err = ctx.GetAuthValues(check.SFTPConnection.Authentication) if err != nil { return results.ErrorMessage(err) } diff --git a/checks/folder_smb.go b/checks/folder_smb.go index c7d873698..92c23ebca 100644 --- a/checks/folder_smb.go +++ b/checks/folder_smb.go @@ -30,7 +30,7 @@ func (s *SMBSession) Close() error { return nil } -func smbConnect(server string, port int, share string, auth *v1.Authentication) (Filesystem, uint64, uint64, uint64, error) { +func smbConnect(server string, port int, share string, auth v1.Authentication) (Filesystem, uint64, uint64, uint64, error) { var err error var smb *SMBSession server = server + ":" + fmt.Sprintf("%d", port) @@ -83,9 +83,9 @@ func CheckSmb(ctx *context.Context, check v1.FolderCheck) pkg.Results { return results.Failf("failed to populate SMB connection: %v", err) } - auth := check.SMBConnection.Auth + auth := check.SMBConnection.Authentication if !foundConn { - auth, err = GetAuthValues(ctx, check.SMBConnection.Auth) + auth, err = ctx.GetAuthValues(check.SMBConnection.Authentication) if err != nil { return results.ErrorMessage(err) } diff --git a/checks/http.go b/checks/http.go index 23590f5b6..15a5251b6 100644 --- a/checks/http.go +++ b/checks/http.go @@ -8,6 +8,7 @@ import ( "github.com/flanksource/canary-checker/api/context" "github.com/flanksource/commons/text" + "github.com/flanksource/duty/models" "github.com/pkg/errors" "github.com/flanksource/canary-checker/api/external" @@ -60,7 +61,7 @@ func (c *HTTPChecker) Run(ctx *context.Context) pkg.Results { return results } -func (c *HTTPChecker) configure(req *http.HTTPRequest, ctx *context.Context, check v1.HTTPCheck) error { +func (c *HTTPChecker) configure(req *http.HTTPRequest, ctx *context.Context, check v1.HTTPCheck, connection *models.Connection) error { for _, header := range check.Headers { value, err := ctx.GetEnvValueFromCache(header) if err != nil { @@ -69,12 +70,8 @@ func (c *HTTPChecker) configure(req *http.HTTPRequest, ctx *context.Context, che req.Header(header.Name, value) } - auth, err := GetAuthValues(ctx, check.Authentication) - if err != nil { - return err - } - if auth != nil { - req.Auth(auth.Username.ValueStatic, auth.Password.ValueStatic) + if connection.Username != "" || connection.Password != "" { + req.Auth(connection.Username, connection.Password) } req.NTLM(check.NTLM) @@ -103,17 +100,35 @@ func (c *HTTPChecker) Check(ctx *context.Context, extConfig external.Check) pkg. result := pkg.Success(check, ctx.Canary) results = append(results, result) - if connection, err := ctx.HydrateConnectionByURL(check.ConnectionName); err != nil { - return results.Failf("failed to find HTTP connection %q: %v", check.ConnectionName, err) - } else if connection != nil { - check.Endpoint = connection.URL + //nolint:staticcheck + if check.Endpoint != "" && check.URL != "" { + return results.Failf("cannot specify both endpoint and url") } - if _, err := url.Parse(check.Endpoint); err != nil { - return results.ErrorMessage(err) + //nolint:staticcheck + if check.Endpoint != "" && check.URL == "" { + check.URL = check.Endpoint + } + + connection, err := ctx.GetConnection(check.Connection) + if err != nil { + return results.Failf("error getting connection %v", err) + } + + if connection.URL == "" { + return results.Failf("no url or connection specified") + } + + if ntlm, ok := connection.Properties["ntlm"]; ok { + check.NTLM = ntlm == "true" + } else if ntlm, ok := connection.Properties["ntlmv2"]; ok { + check.NTLMv2 = ntlm == "true" + } + + if _, err := url.Parse(connection.URL); err != nil { + return results.Failf("failed to parse url: %v", err) } - endpoint := check.Endpoint body := check.Body if check.TemplateBody { body, err = text.Template(body, ctx.Canary) @@ -122,9 +137,9 @@ func (c *HTTPChecker) Check(ctx *context.Context, extConfig external.Check) pkg. } } - req := http.NewRequest(check.Endpoint).Method(check.GetMethod()) + req := http.NewRequest(connection.URL).Method(check.GetMethod()) - if err := c.configure(req, ctx, check); err != nil { + if err := c.configure(req, ctx, check, connection); err != nil { return results.ErrorMessage(err) } @@ -137,15 +152,15 @@ func (c *HTTPChecker) Check(ctx *context.Context, extConfig external.Check) pkg. Name: "response_code", Type: metrics.CounterType, Labels: map[string]string{ - "code": strconv.Itoa(status), - "endpoint": endpoint, + "code": strconv.Itoa(status), + "url": check.URL, }, }) result.Duration = elapsed.Milliseconds() - responseStatus.WithLabelValues(strconv.Itoa(status), statusCodeToClass(status), endpoint).Inc() + responseStatus.WithLabelValues(strconv.Itoa(status), statusCodeToClass(status), check.URL).Inc() age := resp.GetSSLAge() if age != nil { - sslExpiration.WithLabelValues(endpoint).Set(age.Hours() * 24) + sslExpiration.WithLabelValues(check.URL).Set(age.Hours() * 24) } body, _ = resp.AsString() diff --git a/checks/jmeter.go b/checks/jmeter.go index fdd87bb57..44b4c8531 100644 --- a/checks/jmeter.go +++ b/checks/jmeter.go @@ -55,10 +55,6 @@ func (c *JmeterChecker) Check(ctx *context.Context, extConfig external.Check) pk return results.Failf("unable to write test plan file") } - if _, err := check.HydrateConnection(ctx); err != nil { - return results.Failf("unable to populate JMeter connection: %v", err) - } - var host string var port string if check.Host != "" { diff --git a/checks/kubernetes.go b/checks/kubernetes.go index 4d1272472..7367aef78 100644 --- a/checks/kubernetes.go +++ b/checks/kubernetes.go @@ -7,7 +7,7 @@ import ( "github.com/flanksource/canary-checker/api/external" v1 "github.com/flanksource/canary-checker/api/v1" "github.com/flanksource/canary-checker/pkg" - "github.com/flanksource/kommons" + "github.com/flanksource/is-healthy/pkg/health" "github.com/gobwas/glob" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" @@ -50,8 +50,6 @@ func (c *KubernetesChecker) Check(ctx *context.Context, extConfig external.Check } var allResources []unstructured.Unstructured - message := "" - for _, namespace := range namespaces { resources, err := getResourcesFromNamespace(ctx, client, check, namespace) if err != nil { @@ -65,15 +63,10 @@ func (c *KubernetesChecker) Check(ctx *context.Context, extConfig external.Check } } ctx.Tracef("Found %d resources in namespace %s with label=%s field=%s", len(resources), namespace, check.Resource.LabelSelector, check.Resource.FieldSelector) - if check.CheckReady() { - for _, resource := range resources { - ready, msg := ctx.Kommons.IsReady(&resource) - if !ready { - if message != "" { - message += ", " - } - message += fmt.Sprintf("%s is not ready: %v", kommons.GetName(resource), msg) - } + for _, resource := range resources { + resourceHealth, err := health.GetResourceHealth(&resource, nil) + if err == nil { + resource.Object["healthStatus"] = resourceHealth } } allResources = append(allResources, resources...) @@ -82,9 +75,6 @@ func (c *KubernetesChecker) Check(ctx *context.Context, extConfig external.Check return results.Failf("no resources found") } result.AddDetails(allResources) - if message != "" { - return results.Failf(message) - } return results } diff --git a/checks/ldap.go b/checks/ldap.go index 125e89399..50cdae424 100644 --- a/checks/ldap.go +++ b/checks/ldap.go @@ -38,22 +38,22 @@ func (c *LdapChecker) Check(ctx *context.Context, extConfig external.Check) pkg. var err error results = append(results, result) - if ok, err := check.HydrateConnection(ctx); err != nil { - return results.Failf("failed to hydrate connection: %v", err) - } else if !ok { - check.Auth, err = GetAuthValues(ctx, check.Auth) - if err != nil { - return results.Failf("failed to fetch auth details: %v", err) - } + connection, err := ctx.GetConnection(check.Connection) + if err != nil { + return results.Failf("failed to get connection: %v", err) + } + + if connection.URL == "" { + return results.Failf("Must specify a connection or URL") } - ld, err := ldap.DialURL(check.Host, ldap.DialWithTLSConfig(&tls.Config{InsecureSkipVerify: check.SkipTLSVerify})) + ld, err := ldap.DialURL(connection.URL, ldap.DialWithTLSConfig(&tls.Config{InsecureSkipVerify: check.SkipTLSVerify})) if err != nil { return results.Failf("Failed to connect %v", err) } - if err := ld.Bind(check.Auth.Username.ValueStatic, check.Auth.Password.ValueStatic); err != nil { - return results.Failf("Failed to bind using %s %v", check.Auth.Username.ValueStatic, err) + if err := ld.Bind(connection.Username, connection.Password); err != nil { + return results.Failf("Failed to bind using %s %v", connection.Username, err) } req := &ldap.SearchRequest{ @@ -63,7 +63,7 @@ func (c *LdapChecker) Check(ctx *context.Context, extConfig external.Check) pkg. } res, err := ld.Search(req) if err != nil { - return results.Failf("Failed to search host %v error: %v", check.Host, err) + return results.Failf("Failed to search host %v error: %v", connection.URL, err) } if len(res.Entries) == 0 { diff --git a/checks/mongodb.go b/checks/mongodb.go index 8c20ad68c..9ef51e17c 100644 --- a/checks/mongodb.go +++ b/checks/mongodb.go @@ -36,20 +36,13 @@ func (c *MongoDBChecker) Check(ctx *context.Context, extConfig external.Check) p results = append(results, result) var err error - var dbConnectionString string - if connection, err := ctx.HydrateConnectionByURL(check.Connection.Connection); err != nil { + connection, err := ctx.GetConnection(check.Connection) + if err != nil { return results.Failf("error getting connection: %v", err) - } else if connection != nil { - dbConnectionString = connection.URL - } else { - dbConnectionString, err = GetConnection(ctx, &check.Connection, ctx.Namespace) - if err != nil { - return results.ErrorMessage(err) - } } opts := options.Client(). - ApplyURI(dbConnectionString). + ApplyURI(connection.URL). SetConnectTimeout(3 * time.Second). SetSocketTimeout(3 * time.Second) diff --git a/checks/opensearch.go b/checks/opensearch.go index 0d4b56cdf..b3994c119 100644 --- a/checks/opensearch.go +++ b/checks/opensearch.go @@ -31,14 +31,19 @@ func (t *OpenSearchChecker) check(ctx *context.Context, check v1.OpenSearchCheck var results pkg.Results results = append(results, result) - if err := check.HydrateConnection(ctx); err != nil { - return results.Failf("error hydrating connection: %v", err) + connection, err := ctx.GetConnection(check.Connection) + if err != nil { + return results.Failf("error getting connection: %v", err) + } + + if connection.URL == "" { + return results.Failf("Must specify a URL") } cfg := opensearch.Config{ - Username: check.Auth.Username.ValueStatic, - Password: check.Auth.Password.ValueStatic, - Addresses: []string{check.GetEndpoint()}, + Username: connection.Username, + Password: connection.Password, + Addresses: []string{connection.URL}, } osClient, err := opensearch.NewClient(cfg) diff --git a/checks/prometheus.go b/checks/prometheus.go index b96930014..b14dde923 100644 --- a/checks/prometheus.go +++ b/checks/prometheus.go @@ -33,15 +33,21 @@ func (c *PrometheusChecker) Check(ctx *context.Context, extConfig external.Check var results pkg.Results results = append(results, result) - if _, err := check.HydrateConnection(ctx); err != nil { - return results.Failf("error hydrating connection: %v", err) + //nolint:staticcheck + if check.Host != "" && check.URL == "" { + check.URL = check.Host } - if check.Host == "" { - return results.Failf("Must specify a prometheus host") + connection, err := ctx.GetConnection(check.Connection) + if err != nil { + return results.Failf("error getting connection: %v", err) + } + + if connection.URL == "" { + return results.Failf("Must specify a URL") } - promClient, err := prometheus.NewPrometheusAPI(check.Host) + promClient, err := prometheus.NewPrometheusAPI(connection.URL) if err != nil { return results.ErrorMessage(err) } diff --git a/checks/redis.go b/checks/redis.go index b1b16d369..95f2fba3d 100644 --- a/checks/redis.go +++ b/checks/redis.go @@ -40,36 +40,28 @@ func (c *RedisChecker) Check(ctx *context.Context, extConfig external.Check) pkg results = append(results, result) var redisOpts *redis.Options - if check.ConnectionName != "" { - connection, err := ctx.HydrateConnectionByURL(check.ConnectionName) - if err != nil { - return results.Failf("failed to fetch connection %q: %v", check.ConnectionName, err) - } - redisOpts = &redis.Options{ - Addr: connection.URL, - Username: connection.Username, - Password: connection.Password, - } + //nolint:staticcheck + if check.Addr != "" && check.URL == "" { + check.URL = check.Addr + } - if db, ok := connection.Properties["db"]; ok { - if dbInt, err := strconv.Atoi(db); nil == err { - redisOpts.DB = dbInt - } - } - } else { - auth, err := GetAuthValues(ctx, check.Auth) - if err != nil { - return results.Failf("failed to fetch auth details: %v", err) - } + connection, err := ctx.GetConnection(check.Connection) + if err != nil { + return results.Failf("error getting connection: %v", err) + } - redisOpts = &redis.Options{ - Addr: check.Addr, - DB: check.DB, - } - if auth != nil { - redisOpts.Username = auth.GetUsername() - redisOpts.Password = auth.GetPassword() + redisOpts = &redis.Options{ + Addr: connection.URL, + Username: connection.Username, + Password: connection.Password, + } + + if check.DB != nil { + redisOpts.DB = *check.DB + } else if db, ok := connection.Properties["db"]; ok { + if dbInt, err := strconv.Atoi(db); nil == err { + redisOpts.DB = dbInt } } diff --git a/checks/restic.go b/checks/restic.go index fe4d77984..d7fd2883a 100644 --- a/checks/restic.go +++ b/checks/restic.go @@ -75,7 +75,7 @@ func (c *ResticChecker) Check(ctx *context.Context, extConfig external.Check) pk } if check.AWSConnectionName != "" { - connection, err := ctx.HydrateConnectionByURL(check.ConnectionName) + connection, err := ctx.HydrateConnectionByURL(check.AWSConnectionName) if err != nil { return results.Failf("error getting aws connection: %v", err) } diff --git a/checks/runchecks.go b/checks/runchecks.go index d5146979c..1e2280c3b 100644 --- a/checks/runchecks.go +++ b/checks/runchecks.go @@ -115,7 +115,7 @@ func processTemplates(ctx *context.Context, r *pkg.CheckResult) *pkg.CheckResult if message != "false" { r.Failf("expecting either 'true' or 'false' but got '%v'", message) } else { - r.Failf("Test expression failed. Expecting true from: %v", tpl.Expression) + r.Failf("") } } } diff --git a/checks/sql.go b/checks/sql.go index 3dc0a3412..9ae59b73f 100644 --- a/checks/sql.go +++ b/checks/sql.go @@ -3,6 +3,7 @@ package checks import ( "database/sql" "fmt" + "strings" "github.com/flanksource/canary-checker/api/context" "github.com/flanksource/canary-checker/api/external" @@ -84,23 +85,17 @@ func CheckSQL(ctx *context.Context, checker SQLChecker) pkg.Results { // nolint: var results pkg.Results results = append(results, result) - var dbConnectionString string - if connection, err := ctx.HydrateConnectionByURL(check.Connection.Connection); err != nil { - return results.Failf("error getting connection: %v", err) - } else if connection != nil { - dbConnectionString = connection.URL - } else { - dbConnectionString, err = GetConnection(ctx, &check.Connection, ctx.Namespace) - if err != nil { - return results.ErrorMessage(err) - } + if check.Connection.Connection != "" && !strings.HasPrefix(check.Connection.Connection, "connection://") { + check.URL = check.Connection.Connection + check.Connection.Connection = "" } - if ctx.IsTrace() { - ctx.Tracef("connecting to %s", dbConnectionString) + connection, err := ctx.GetConnection(check.Connection) + if err != nil { + return results.Failf("error getting connection: %v", err) } - details, err := querySQL(checker.GetDriver(), dbConnectionString, check.GetQuery()) + details, err := querySQL(checker.GetDriver(), connection.URL, check.GetQuery()) if err != nil { return results.ErrorMessage(err) } diff --git a/config/deploy/crd.yaml b/config/deploy/crd.yaml index 3c97dc1ba..d1298ca64 100644 --- a/config/deploy/crd.yaml +++ b/config/deploy/crd.yaml @@ -64,69 +64,8 @@ spec: items: type: string type: array - auth: - properties: - password: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - type: object - type: object - username: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - type: object - type: object - required: - - password - - username - type: object connection: + description: Connection name e.g. connection://http/google type: string description: description: Description for the check @@ -146,8 +85,6 @@ spec: additionalProperties: type: string type: object - host: - type: string icon: description: Icon for overwriting default icon on the dashboard type: string @@ -163,6 +100,34 @@ spec: name: description: Name of the check type: string + password: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object test: properties: expr: @@ -185,6 +150,37 @@ spec: template: type: string type: object + url: + description: Connection url, interpolated with username,password + type: string + username: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object required: - name type: object @@ -192,83 +188,39 @@ spec: awsConfig: items: properties: - aggregatorName: - type: string - awsConnection: + accessKey: properties: - accessKey: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - type: object - type: object - connection: - description: ConnectionName of the connection. It'll be used to populate the endpoint, accessKey and secretKey. - type: string - endpoint: - type: string - objectPath: - description: glob path to restrict matches to a subset + name: type: string - region: + value: type: string - secretKey: + valueFrom: properties: - name: - type: string - value: - type: string - valueFrom: + configMapKeyRef: properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key type: object type: object - skipTLSVerify: - description: Skip TLS verify when connecting to aws - type: boolean - usePathStyle: - description: 'Use path style path: http://s3.amazonaws.com/BUCKET/KEY instead of http://BUCKET.s3.amazonaws.com/KEY' - type: boolean type: object + aggregatorName: + type: string + connection: + description: ConnectionName of the connection. It'll be used to populate the endpoint, accessKey and secretKey. + type: string description: description: Description for the check type: string @@ -283,6 +235,8 @@ spec: template: type: string type: object + endpoint: + type: string icon: description: Icon for overwriting default icon on the dashboard type: string @@ -294,8 +248,44 @@ spec: name: description: Name of the check type: string + objectPath: + description: glob path to restrict matches to a subset + type: string query: type: string + region: + type: string + secretKey: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object + skipTLSVerify: + description: Skip TLS verify when connecting to aws + type: boolean test: properties: expr: @@ -318,6 +308,9 @@ spec: template: type: string type: object + usePathStyle: + description: 'Use path style path: http://s3.amazonaws.com/BUCKET/KEY instead of http://BUCKET.s3.amazonaws.com/KEY' + type: boolean required: - name - query @@ -326,86 +319,42 @@ spec: awsConfigRule: items: properties: - awsConnection: + accessKey: properties: - accessKey: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - type: object - type: object - connection: - description: ConnectionName of the connection. It'll be used to populate the endpoint, accessKey and secretKey. - type: string - endpoint: - type: string - objectPath: - description: glob path to restrict matches to a subset + name: type: string - region: + value: type: string - secretKey: + valueFrom: properties: - name: - type: string - value: - type: string - valueFrom: + configMapKeyRef: properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key type: object type: object - skipTLSVerify: - description: Skip TLS verify when connecting to aws - type: boolean - usePathStyle: - description: 'Use path style path: http://s3.amazonaws.com/BUCKET/KEY instead of http://BUCKET.s3.amazonaws.com/KEY' - type: boolean type: object complianceTypes: description: Filters the results by compliance. The allowed values are INSUFFICIENT_DATA, NON_COMPLIANT, NOT_APPLICABLE, COMPLIANT items: type: string type: array + connection: + description: ConnectionName of the connection. It'll be used to populate the endpoint, accessKey and secretKey. + type: string description: description: Description for the check type: string @@ -420,6 +369,8 @@ spec: template: type: string type: object + endpoint: + type: string icon: description: Icon for overwriting default icon on the dashboard type: string @@ -436,11 +387,47 @@ spec: name: description: Name of the check type: string + objectPath: + description: glob path to restrict matches to a subset + type: string + region: + type: string rules: description: Specify one or more Config rule names to filter the results by rule. items: type: string type: array + secretKey: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object + skipTLSVerify: + description: Skip TLS verify when connecting to aws + type: boolean test: properties: expr: @@ -463,6 +450,9 @@ spec: template: type: string type: object + usePathStyle: + description: 'Use path style path: http://s3.amazonaws.com/BUCKET/KEY instead of http://BUCKET.s3.amazonaws.com/KEY' + type: boolean required: - name type: object @@ -606,6 +596,14 @@ spec: type: object type: object type: object + actionPrefix: + type: string + alarmPrefix: + type: string + alarms: + items: + type: string + type: array connection: description: ConnectionName of the connection. It'll be used to populate the endpoint, accessKey and secretKey. type: string @@ -625,19 +623,6 @@ spec: type: object endpoint: type: string - filter: - properties: - actionPrefix: - type: string - alarmPrefix: - type: string - alarms: - items: - type: string - type: array - state: - type: string - type: object icon: description: Icon for overwriting default icon on the dashboard type: string @@ -685,6 +670,8 @@ spec: skipTLSVerify: description: Skip TLS verify when connecting to aws type: boolean + state: + type: string test: properties: expr: @@ -832,9 +819,6 @@ spec: type: object type: object type: object - required: - - password - - username type: object description: description: Description for the check @@ -1092,9 +1076,6 @@ spec: type: object type: object type: object - required: - - password - - username type: object description: description: Description for the check @@ -1183,9 +1164,6 @@ spec: type: object type: object type: object - required: - - password - - username type: object description: description: Description for the check @@ -1239,6 +1217,8 @@ spec: type: object type: object type: object + connection: + type: string description: description: Description for the check type: string @@ -1414,69 +1394,8 @@ spec: elasticsearch: items: properties: - auth: - properties: - password: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - type: object - type: object - username: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - type: object - type: object - required: - - password - - username - type: object connection: + description: Connection name e.g. connection://http/google type: string description: description: Description for the check @@ -1505,6 +1424,34 @@ spec: name: description: Name of the check type: string + password: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object query: type: string results: @@ -1532,29 +1479,58 @@ spec: type: string type: object url: + description: Connection url, interpolated with username,password type: string - required: - - name - type: object - type: array - env: - additionalProperties: - description: VarSource represents a source for a value - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. + username: properties: - key: - description: The key to select. - type: string name: - description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' type: string - optional: - description: Specify whether the ConfigMap or its key must be defined - type: boolean - required: - - key + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object + required: + - name + type: object + type: array + env: + additionalProperties: + description: VarSource represents a source for a value + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap or its key must be defined + type: boolean + required: + - key type: object x-kubernetes-map-type: atomic fieldRef: @@ -1826,186 +1802,162 @@ spec: type: string sftpConnection: properties: - auth: + connection: + description: ConnectionName of the connection. It'll be used to populate the connection fields. + type: string + host: + type: string + password: properties: - password: + name: + type: string + value: + type: string + valueFrom: properties: - name: - type: string - value: - type: string - valueFrom: + configMapKeyRef: properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object + key: + type: string + name: + type: string + required: + - key type: object - type: object - username: - properties: - name: - type: string - value: - type: string - valueFrom: + secretKeyRef: properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object + key: + type: string + name: + type: string + required: + - key type: object type: object - required: - - password - - username type: object - connection: - description: ConnectionName of the connection. It'll be used to populate the connection fields. - type: string - host: - type: string port: description: Port for the SSH server. Defaults to 22 type: integer - required: - - auth - - host - type: object - smbConnection: - properties: - auth: + username: properties: - password: + name: + type: string + value: + type: string + valueFrom: properties: - name: - type: string - value: - type: string - valueFrom: + configMapKeyRef: properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object + key: + type: string + name: + type: string + required: + - key type: object - type: object - username: - properties: - name: - type: string - value: - type: string - valueFrom: + secretKeyRef: properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object + key: + type: string + name: + type: string + required: + - key type: object type: object - required: - - password - - username type: object + required: + - host + type: object + smbConnection: + properties: connection: description: ConnectionName of the connection. It'll be used to populate the connection fields. type: string domain: description: Domain... type: string + password: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object port: description: Port on which smb server is running. Defaults to 445 type: integer - searchPath: - description: SearchPath sub-path inside the mount location - type: string - sharename: - description: Sharename to mount from the samba server - type: string - workstation: - description: Workstation... - type: string - required: - - auth - type: object - test: - properties: - expr: - type: string - javascript: - type: string - jsonPath: - type: string - template: - type: string - type: object - totalSize: - description: TotalSize present on the filesystem - type: string - transform: - properties: - expr: - type: string - javascript: - type: string - jsonPath: + username: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object + type: object + test: + properties: + expr: + type: string + javascript: + type: string + jsonPath: + type: string + template: + type: string + type: object + totalSize: + description: TotalSize present on the filesystem + type: string + transform: + properties: + expr: + type: string + javascript: + type: string + jsonPath: type: string template: type: string @@ -2164,9 +2116,6 @@ spec: type: object type: object type: object - required: - - password - - username type: object cafile: type: string @@ -2195,74 +2144,11 @@ spec: http: items: properties: - authentication: - description: Credentials for authentication headers - properties: - password: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - type: object - type: object - username: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - type: object - type: object - required: - - password - - username - type: object body: description: Request Body Contents type: string connection: - description: Name of the connection that'll be used to derive the endpoint. + description: Connection name e.g. connection://http/google type: string description: description: Description for the check @@ -2279,7 +2165,7 @@ spec: type: string type: object endpoint: - description: HTTP endpoint to check. Mutually exclusive with Namespace + description: 'Deprecated: Use url instead' type: string headers: description: Header fields to be used in the query @@ -2338,6 +2224,34 @@ spec: ntlmv2: description: NTLM when set to true will do authentication using NTLM v2 protocol type: boolean + password: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object responseCodes: description: Expected response codes for the HTTP Request. items: @@ -2385,6 +2299,37 @@ spec: template: type: string type: object + url: + description: Connection url, interpolated with username,password + type: string + username: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object required: - name type: object @@ -2429,9 +2374,6 @@ spec: jmeter: items: properties: - connection: - description: Name of the connection that'll be used to derive host and other connection details. - type: string description: description: Description for the check type: string @@ -2649,77 +2591,14 @@ spec: ldap: items: properties: - auth: - properties: - password: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - type: object - type: object - username: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - type: object - type: object - required: - - password - - username - type: object bindDN: type: string connection: + description: Connection name e.g. connection://http/google type: string description: description: Description for the check type: string - host: - type: string icon: description: Icon for overwriting default icon on the dashboard type: string @@ -2731,83 +2610,79 @@ spec: name: description: Name of the check type: string - skipTLSVerify: - type: boolean - userSearch: - type: string - required: - - auth - - bindDN - - host - - name - type: object - type: array - mongodb: - items: - properties: - auth: + password: properties: - password: + name: + type: string + value: + type: string + valueFrom: properties: - name: - type: string - value: - type: string - valueFrom: + configMapKeyRef: properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key type: object type: object - username: + type: object + skipTLSVerify: + type: boolean + url: + description: Connection url, interpolated with username,password + type: string + userSearch: + type: string + username: + properties: + name: + type: string + value: + type: string + valueFrom: properties: - name: - type: string - value: - type: string - valueFrom: + configMapKeyRef: properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key type: object type: object - required: - - password - - username type: object + required: + - bindDN + - name + type: object + type: array + mongodb: + items: + properties: connection: + description: Connection name e.g. connection://http/google type: string description: description: Description for the check @@ -2823,77 +2698,74 @@ spec: name: description: Name of the check type: string - required: - - connection - - name - type: object - type: array - mssql: - items: - properties: - auth: + password: properties: - password: + name: + type: string + value: + type: string + valueFrom: properties: - name: - type: string - value: - type: string - valueFrom: + configMapKeyRef: properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key type: object type: object - username: + type: object + url: + description: Connection url, interpolated with username,password + type: string + username: + properties: + name: + type: string + value: + type: string + valueFrom: properties: - name: - type: string - value: - type: string - valueFrom: + configMapKeyRef: properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key type: object type: object - required: - - password - - username type: object + required: + - name + type: object + type: array + mssql: + items: + properties: connection: + description: Connection name e.g. connection://http/google type: string description: description: Description for the check @@ -2920,6 +2792,34 @@ spec: name: description: Name of the check type: string + password: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object query: type: string results: @@ -2947,77 +2847,46 @@ spec: template: type: string type: object - required: - - connection - - name - type: object - type: array - mysql: - items: - properties: - auth: + url: + description: Connection url, interpolated with username,password + type: string + username: properties: - password: + name: + type: string + value: + type: string + valueFrom: properties: - name: - type: string - value: - type: string - valueFrom: + configMapKeyRef: properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object + key: + type: string + name: + type: string + required: + - key type: object - type: object - username: - properties: - name: - type: string - value: - type: string - valueFrom: + secretKeyRef: properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object + key: + type: string + name: + type: string + required: + - key type: object type: object - required: - - password - - username type: object + required: + - name + type: object + type: array + mysql: + items: + properties: connection: + description: Connection name e.g. connection://http/google type: string description: description: Description for the check @@ -3044,6 +2913,34 @@ spec: name: description: Name of the check type: string + password: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object query: type: string results: @@ -3071,8 +2968,38 @@ spec: template: type: string type: object + url: + description: Connection url, interpolated with username,password + type: string + username: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object required: - - connection - name type: object type: array @@ -3152,69 +3079,8 @@ spec: opensearch: items: properties: - auth: - properties: - password: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - type: object - type: object - username: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - type: object - type: object - required: - - password - - username - type: object connection: + description: Connection name e.g. connection://http/google type: string description: description: Description for the check @@ -3243,6 +3109,34 @@ spec: name: description: Name of the check type: string + password: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object query: type: string results: @@ -3271,9 +3165,37 @@ spec: type: string type: object url: + description: Connection url, interpolated with username,password type: string + username: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object required: - - auth - index - name - query @@ -3327,91 +3249,30 @@ spec: type: string namespace: type: string - path: - type: string - port: - format: int64 - type: integer - priorityClass: - type: string - readyTimeout: - format: int64 - type: integer - scheduleTimeout: - format: int64 - type: integer - spec: - type: string - required: - - name - type: object - type: array - postgres: - items: - properties: - auth: - properties: - password: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - type: object - type: object - username: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - type: object - type: object - required: - - password - - username - type: object + path: + type: string + port: + format: int64 + type: integer + priorityClass: + type: string + readyTimeout: + format: int64 + type: integer + scheduleTimeout: + format: int64 + type: integer + spec: + type: string + required: + - name + type: object + type: array + postgres: + items: + properties: connection: + description: Connection name e.g. connection://http/google type: string description: description: Description for the check @@ -3438,6 +3299,34 @@ spec: name: description: Name of the check type: string + password: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object query: type: string results: @@ -3465,8 +3354,38 @@ spec: template: type: string type: object + url: + description: Connection url, interpolated with username,password + type: string + username: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object required: - - connection - name type: object type: array @@ -3474,6 +3393,7 @@ spec: items: properties: connection: + description: Connection name e.g. connection://http/google type: string description: description: Description for the check @@ -3490,7 +3410,7 @@ spec: type: string type: object host: - description: Address of the prometheus server + description: 'Deprecated: use `url` instead' type: string icon: description: Icon for overwriting default icon on the dashboard @@ -3503,6 +3423,34 @@ spec: name: description: Name of the check type: string + password: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object query: description: PromQL query type: string @@ -3528,8 +3476,38 @@ spec: template: type: string type: object + url: + description: Connection url, interpolated with username,password + type: string + username: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object required: - - host - name - query type: object @@ -3538,71 +3516,10 @@ spec: items: properties: addr: + description: 'Deprecated: Use url instead' type: string - auth: - properties: - password: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - type: object - type: object - username: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - type: object - type: object - required: - - password - - username - type: object connection: - description: ConnectionName is the name of the connection. It is used to populate addr, db and auth. + description: Connection name e.g. connection://http/google type: string db: type: integer @@ -3620,9 +3537,66 @@ spec: name: description: Name of the check type: string + password: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object + url: + description: Connection url, interpolated with username,password + type: string + username: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object required: - - addr - - db - name type: object type: array diff --git a/config/deploy/manifests.yaml b/config/deploy/manifests.yaml index cbb6b5316..67ee9e654 100644 --- a/config/deploy/manifests.yaml +++ b/config/deploy/manifests.yaml @@ -64,69 +64,8 @@ spec: items: type: string type: array - auth: - properties: - password: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - type: object - type: object - username: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - type: object - type: object - required: - - password - - username - type: object connection: + description: Connection name e.g. connection://http/google type: string description: description: Description for the check @@ -146,8 +85,6 @@ spec: additionalProperties: type: string type: object - host: - type: string icon: description: Icon for overwriting default icon on the dashboard type: string @@ -163,6 +100,34 @@ spec: name: description: Name of the check type: string + password: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object test: properties: expr: @@ -185,6 +150,37 @@ spec: template: type: string type: object + url: + description: Connection url, interpolated with username,password + type: string + username: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object required: - name type: object @@ -192,83 +188,39 @@ spec: awsConfig: items: properties: - aggregatorName: - type: string - awsConnection: + accessKey: properties: - accessKey: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - type: object - type: object - connection: - description: ConnectionName of the connection. It'll be used to populate the endpoint, accessKey and secretKey. - type: string - endpoint: - type: string - objectPath: - description: glob path to restrict matches to a subset + name: type: string - region: + value: type: string - secretKey: + valueFrom: properties: - name: - type: string - value: - type: string - valueFrom: + configMapKeyRef: properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key type: object type: object - skipTLSVerify: - description: Skip TLS verify when connecting to aws - type: boolean - usePathStyle: - description: 'Use path style path: http://s3.amazonaws.com/BUCKET/KEY instead of http://BUCKET.s3.amazonaws.com/KEY' - type: boolean type: object + aggregatorName: + type: string + connection: + description: ConnectionName of the connection. It'll be used to populate the endpoint, accessKey and secretKey. + type: string description: description: Description for the check type: string @@ -283,6 +235,8 @@ spec: template: type: string type: object + endpoint: + type: string icon: description: Icon for overwriting default icon on the dashboard type: string @@ -294,8 +248,44 @@ spec: name: description: Name of the check type: string + objectPath: + description: glob path to restrict matches to a subset + type: string query: type: string + region: + type: string + secretKey: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object + skipTLSVerify: + description: Skip TLS verify when connecting to aws + type: boolean test: properties: expr: @@ -318,6 +308,9 @@ spec: template: type: string type: object + usePathStyle: + description: 'Use path style path: http://s3.amazonaws.com/BUCKET/KEY instead of http://BUCKET.s3.amazonaws.com/KEY' + type: boolean required: - name - query @@ -326,86 +319,42 @@ spec: awsConfigRule: items: properties: - awsConnection: + accessKey: properties: - accessKey: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - type: object - type: object - connection: - description: ConnectionName of the connection. It'll be used to populate the endpoint, accessKey and secretKey. - type: string - endpoint: - type: string - objectPath: - description: glob path to restrict matches to a subset + name: type: string - region: + value: type: string - secretKey: + valueFrom: properties: - name: - type: string - value: - type: string - valueFrom: + configMapKeyRef: properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key type: object type: object - skipTLSVerify: - description: Skip TLS verify when connecting to aws - type: boolean - usePathStyle: - description: 'Use path style path: http://s3.amazonaws.com/BUCKET/KEY instead of http://BUCKET.s3.amazonaws.com/KEY' - type: boolean type: object complianceTypes: description: Filters the results by compliance. The allowed values are INSUFFICIENT_DATA, NON_COMPLIANT, NOT_APPLICABLE, COMPLIANT items: type: string type: array + connection: + description: ConnectionName of the connection. It'll be used to populate the endpoint, accessKey and secretKey. + type: string description: description: Description for the check type: string @@ -420,6 +369,8 @@ spec: template: type: string type: object + endpoint: + type: string icon: description: Icon for overwriting default icon on the dashboard type: string @@ -436,11 +387,47 @@ spec: name: description: Name of the check type: string + objectPath: + description: glob path to restrict matches to a subset + type: string + region: + type: string rules: description: Specify one or more Config rule names to filter the results by rule. items: type: string type: array + secretKey: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object + skipTLSVerify: + description: Skip TLS verify when connecting to aws + type: boolean test: properties: expr: @@ -463,6 +450,9 @@ spec: template: type: string type: object + usePathStyle: + description: 'Use path style path: http://s3.amazonaws.com/BUCKET/KEY instead of http://BUCKET.s3.amazonaws.com/KEY' + type: boolean required: - name type: object @@ -606,6 +596,14 @@ spec: type: object type: object type: object + actionPrefix: + type: string + alarmPrefix: + type: string + alarms: + items: + type: string + type: array connection: description: ConnectionName of the connection. It'll be used to populate the endpoint, accessKey and secretKey. type: string @@ -625,19 +623,6 @@ spec: type: object endpoint: type: string - filter: - properties: - actionPrefix: - type: string - alarmPrefix: - type: string - alarms: - items: - type: string - type: array - state: - type: string - type: object icon: description: Icon for overwriting default icon on the dashboard type: string @@ -685,6 +670,8 @@ spec: skipTLSVerify: description: Skip TLS verify when connecting to aws type: boolean + state: + type: string test: properties: expr: @@ -832,9 +819,6 @@ spec: type: object type: object type: object - required: - - password - - username type: object description: description: Description for the check @@ -1092,9 +1076,6 @@ spec: type: object type: object type: object - required: - - password - - username type: object description: description: Description for the check @@ -1183,9 +1164,6 @@ spec: type: object type: object type: object - required: - - password - - username type: object description: description: Description for the check @@ -1239,6 +1217,8 @@ spec: type: object type: object type: object + connection: + type: string description: description: Description for the check type: string @@ -1414,69 +1394,8 @@ spec: elasticsearch: items: properties: - auth: - properties: - password: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - type: object - type: object - username: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - type: object - type: object - required: - - password - - username - type: object connection: + description: Connection name e.g. connection://http/google type: string description: description: Description for the check @@ -1505,6 +1424,34 @@ spec: name: description: Name of the check type: string + password: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object query: type: string results: @@ -1532,29 +1479,58 @@ spec: type: string type: object url: + description: Connection url, interpolated with username,password type: string - required: - - name - type: object - type: array - env: - additionalProperties: - description: VarSource represents a source for a value - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. + username: properties: - key: - description: The key to select. - type: string name: - description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' type: string - optional: - description: Specify whether the ConfigMap or its key must be defined - type: boolean - required: - - key + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object + required: + - name + type: object + type: array + env: + additionalProperties: + description: VarSource represents a source for a value + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap or its key must be defined + type: boolean + required: + - key type: object x-kubernetes-map-type: atomic fieldRef: @@ -1826,186 +1802,162 @@ spec: type: string sftpConnection: properties: - auth: + connection: + description: ConnectionName of the connection. It'll be used to populate the connection fields. + type: string + host: + type: string + password: properties: - password: + name: + type: string + value: + type: string + valueFrom: properties: - name: - type: string - value: - type: string - valueFrom: + configMapKeyRef: properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object + key: + type: string + name: + type: string + required: + - key type: object - type: object - username: - properties: - name: - type: string - value: - type: string - valueFrom: + secretKeyRef: properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object + key: + type: string + name: + type: string + required: + - key type: object type: object - required: - - password - - username type: object - connection: - description: ConnectionName of the connection. It'll be used to populate the connection fields. - type: string - host: - type: string port: description: Port for the SSH server. Defaults to 22 type: integer - required: - - auth - - host - type: object - smbConnection: - properties: - auth: + username: properties: - password: + name: + type: string + value: + type: string + valueFrom: properties: - name: - type: string - value: - type: string - valueFrom: + configMapKeyRef: properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object + key: + type: string + name: + type: string + required: + - key type: object - type: object - username: - properties: - name: - type: string - value: - type: string - valueFrom: + secretKeyRef: properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object + key: + type: string + name: + type: string + required: + - key type: object type: object - required: - - password - - username type: object + required: + - host + type: object + smbConnection: + properties: connection: description: ConnectionName of the connection. It'll be used to populate the connection fields. type: string domain: description: Domain... type: string + password: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object port: description: Port on which smb server is running. Defaults to 445 type: integer - searchPath: - description: SearchPath sub-path inside the mount location - type: string - sharename: - description: Sharename to mount from the samba server - type: string - workstation: - description: Workstation... - type: string - required: - - auth - type: object - test: - properties: - expr: - type: string - javascript: - type: string - jsonPath: - type: string - template: - type: string - type: object - totalSize: - description: TotalSize present on the filesystem - type: string - transform: - properties: - expr: - type: string - javascript: - type: string - jsonPath: + username: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object + type: object + test: + properties: + expr: + type: string + javascript: + type: string + jsonPath: + type: string + template: + type: string + type: object + totalSize: + description: TotalSize present on the filesystem + type: string + transform: + properties: + expr: + type: string + javascript: + type: string + jsonPath: type: string template: type: string @@ -2164,9 +2116,6 @@ spec: type: object type: object type: object - required: - - password - - username type: object cafile: type: string @@ -2195,74 +2144,11 @@ spec: http: items: properties: - authentication: - description: Credentials for authentication headers - properties: - password: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - type: object - type: object - username: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - type: object - type: object - required: - - password - - username - type: object body: description: Request Body Contents type: string connection: - description: Name of the connection that'll be used to derive the endpoint. + description: Connection name e.g. connection://http/google type: string description: description: Description for the check @@ -2279,7 +2165,7 @@ spec: type: string type: object endpoint: - description: HTTP endpoint to check. Mutually exclusive with Namespace + description: 'Deprecated: Use url instead' type: string headers: description: Header fields to be used in the query @@ -2338,6 +2224,34 @@ spec: ntlmv2: description: NTLM when set to true will do authentication using NTLM v2 protocol type: boolean + password: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object responseCodes: description: Expected response codes for the HTTP Request. items: @@ -2385,6 +2299,37 @@ spec: template: type: string type: object + url: + description: Connection url, interpolated with username,password + type: string + username: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object required: - name type: object @@ -2429,9 +2374,6 @@ spec: jmeter: items: properties: - connection: - description: Name of the connection that'll be used to derive host and other connection details. - type: string description: description: Description for the check type: string @@ -2649,77 +2591,14 @@ spec: ldap: items: properties: - auth: - properties: - password: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - type: object - type: object - username: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - type: object - type: object - required: - - password - - username - type: object bindDN: type: string connection: + description: Connection name e.g. connection://http/google type: string description: description: Description for the check type: string - host: - type: string icon: description: Icon for overwriting default icon on the dashboard type: string @@ -2731,83 +2610,79 @@ spec: name: description: Name of the check type: string - skipTLSVerify: - type: boolean - userSearch: - type: string - required: - - auth - - bindDN - - host - - name - type: object - type: array - mongodb: - items: - properties: - auth: + password: properties: - password: + name: + type: string + value: + type: string + valueFrom: properties: - name: - type: string - value: - type: string - valueFrom: + configMapKeyRef: properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key type: object type: object - username: + type: object + skipTLSVerify: + type: boolean + url: + description: Connection url, interpolated with username,password + type: string + userSearch: + type: string + username: + properties: + name: + type: string + value: + type: string + valueFrom: properties: - name: - type: string - value: - type: string - valueFrom: + configMapKeyRef: properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key type: object type: object - required: - - password - - username type: object + required: + - bindDN + - name + type: object + type: array + mongodb: + items: + properties: connection: + description: Connection name e.g. connection://http/google type: string description: description: Description for the check @@ -2823,77 +2698,74 @@ spec: name: description: Name of the check type: string - required: - - connection - - name - type: object - type: array - mssql: - items: - properties: - auth: + password: properties: - password: + name: + type: string + value: + type: string + valueFrom: properties: - name: - type: string - value: - type: string - valueFrom: + configMapKeyRef: properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key type: object type: object - username: + type: object + url: + description: Connection url, interpolated with username,password + type: string + username: + properties: + name: + type: string + value: + type: string + valueFrom: properties: - name: - type: string - value: - type: string - valueFrom: + configMapKeyRef: properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key type: object type: object - required: - - password - - username type: object + required: + - name + type: object + type: array + mssql: + items: + properties: connection: + description: Connection name e.g. connection://http/google type: string description: description: Description for the check @@ -2920,6 +2792,34 @@ spec: name: description: Name of the check type: string + password: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object query: type: string results: @@ -2947,77 +2847,46 @@ spec: template: type: string type: object - required: - - connection - - name - type: object - type: array - mysql: - items: - properties: - auth: + url: + description: Connection url, interpolated with username,password + type: string + username: properties: - password: + name: + type: string + value: + type: string + valueFrom: properties: - name: - type: string - value: - type: string - valueFrom: + configMapKeyRef: properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object + key: + type: string + name: + type: string + required: + - key type: object - type: object - username: - properties: - name: - type: string - value: - type: string - valueFrom: + secretKeyRef: properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object + key: + type: string + name: + type: string + required: + - key type: object type: object - required: - - password - - username type: object + required: + - name + type: object + type: array + mysql: + items: + properties: connection: + description: Connection name e.g. connection://http/google type: string description: description: Description for the check @@ -3044,6 +2913,34 @@ spec: name: description: Name of the check type: string + password: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object query: type: string results: @@ -3071,8 +2968,38 @@ spec: template: type: string type: object + url: + description: Connection url, interpolated with username,password + type: string + username: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object required: - - connection - name type: object type: array @@ -3152,69 +3079,8 @@ spec: opensearch: items: properties: - auth: - properties: - password: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - type: object - type: object - username: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - type: object - type: object - required: - - password - - username - type: object connection: + description: Connection name e.g. connection://http/google type: string description: description: Description for the check @@ -3243,6 +3109,34 @@ spec: name: description: Name of the check type: string + password: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object query: type: string results: @@ -3271,9 +3165,37 @@ spec: type: string type: object url: + description: Connection url, interpolated with username,password type: string + username: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object required: - - auth - index - name - query @@ -3327,91 +3249,30 @@ spec: type: string namespace: type: string - path: - type: string - port: - format: int64 - type: integer - priorityClass: - type: string - readyTimeout: - format: int64 - type: integer - scheduleTimeout: - format: int64 - type: integer - spec: - type: string - required: - - name - type: object - type: array - postgres: - items: - properties: - auth: - properties: - password: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - type: object - type: object - username: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - type: object - type: object - required: - - password - - username - type: object + path: + type: string + port: + format: int64 + type: integer + priorityClass: + type: string + readyTimeout: + format: int64 + type: integer + scheduleTimeout: + format: int64 + type: integer + spec: + type: string + required: + - name + type: object + type: array + postgres: + items: + properties: connection: + description: Connection name e.g. connection://http/google type: string description: description: Description for the check @@ -3438,6 +3299,34 @@ spec: name: description: Name of the check type: string + password: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object query: type: string results: @@ -3465,8 +3354,38 @@ spec: template: type: string type: object + url: + description: Connection url, interpolated with username,password + type: string + username: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object required: - - connection - name type: object type: array @@ -3474,6 +3393,7 @@ spec: items: properties: connection: + description: Connection name e.g. connection://http/google type: string description: description: Description for the check @@ -3490,7 +3410,7 @@ spec: type: string type: object host: - description: Address of the prometheus server + description: 'Deprecated: use `url` instead' type: string icon: description: Icon for overwriting default icon on the dashboard @@ -3503,6 +3423,34 @@ spec: name: description: Name of the check type: string + password: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object query: description: PromQL query type: string @@ -3528,8 +3476,38 @@ spec: template: type: string type: object + url: + description: Connection url, interpolated with username,password + type: string + username: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object required: - - host - name - query type: object @@ -3538,71 +3516,10 @@ spec: items: properties: addr: + description: 'Deprecated: Use url instead' type: string - auth: - properties: - password: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - type: object - type: object - username: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - required: - - key - type: object - type: object - type: object - required: - - password - - username - type: object connection: - description: ConnectionName is the name of the connection. It is used to populate addr, db and auth. + description: Connection name e.g. connection://http/google type: string db: type: integer @@ -3620,9 +3537,66 @@ spec: name: description: Name of the check type: string + password: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object + url: + description: Connection url, interpolated with username,password + type: string + username: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + secretKeyRef: + properties: + key: + type: string + name: + type: string + required: + - key + type: object + type: object + type: object required: - - addr - - db - name type: object type: array diff --git a/config/schemas/canary.schema.json b/config/schemas/canary.schema.json index 2bdf053df..225d7af56 100644 --- a/config/schemas/canary.schema.json +++ b/config/schemas/canary.schema.json @@ -59,11 +59,14 @@ "connection": { "type": "string" }, - "host": { + "url": { "type": "string" }, - "auth": { - "$ref": "#/$defs/Authentication" + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" }, "alerts": { "items": { @@ -102,11 +105,7 @@ } }, "additionalProperties": false, - "type": "object", - "required": [ - "username", - "password" - ] + "type": "object" }, "AwsConfigCheck": { "properties": { @@ -134,8 +133,29 @@ "query": { "type": "string" }, - "awsConnection": { - "$ref": "#/$defs/AWSConnection" + "connection": { + "type": "string" + }, + "accessKey": { + "$ref": "#/$defs/EnvVar" + }, + "secretKey": { + "$ref": "#/$defs/EnvVar" + }, + "region": { + "type": "string" + }, + "endpoint": { + "type": "string" + }, + "skipTLSVerify": { + "type": "boolean" + }, + "objectPath": { + "type": "string" + }, + "usePathStyle": { + "type": "boolean" }, "aggregatorName": { "type": "string" @@ -189,8 +209,29 @@ }, "type": "array" }, - "awsConnection": { - "$ref": "#/$defs/AWSConnection" + "connection": { + "type": "string" + }, + "accessKey": { + "$ref": "#/$defs/EnvVar" + }, + "secretKey": { + "$ref": "#/$defs/EnvVar" + }, + "region": { + "type": "string" + }, + "endpoint": { + "type": "string" + }, + "skipTLSVerify": { + "type": "boolean" + }, + "objectPath": { + "type": "string" + }, + "usePathStyle": { + "type": "boolean" } }, "additionalProperties": false, @@ -663,18 +704,6 @@ "transform": { "$ref": "#/$defs/Template" }, - "filter": { - "$ref": "#/$defs/CloudWatchFilter" - } - }, - "additionalProperties": false, - "type": "object", - "required": [ - "name" - ] - }, - "CloudWatchFilter": { - "properties": { "actionPrefix": { "type": "string" }, @@ -692,7 +721,10 @@ } }, "additionalProperties": false, - "type": "object" + "type": "object", + "required": [ + "name" + ] }, "ConfigDBCheck": { "properties": { @@ -980,6 +1012,9 @@ "transform": { "$ref": "#/$defs/Template" }, + "connection": { + "type": "string" + }, "host": { "type": "string" }, @@ -1097,8 +1132,11 @@ "url": { "type": "string" }, - "auth": { - "$ref": "#/$defs/Authentication" + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" }, "query": { "type": "string" @@ -1376,6 +1414,15 @@ "connection": { "type": "string" }, + "url": { + "type": "string" + }, + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" + }, "endpoint": { "type": "string" }, @@ -1418,9 +1465,6 @@ }, "type": "array" }, - "authentication": { - "$ref": "#/$defs/Authentication" - }, "templateBody": { "type": "boolean" } @@ -1527,9 +1571,6 @@ "labels": { "$ref": "#/$defs/Labels" }, - "connection": { - "type": "string" - }, "jmx": { "$ref": "#/$defs/EnvVar" }, @@ -1667,11 +1708,14 @@ "connection": { "type": "string" }, - "host": { + "url": { "type": "string" }, - "auth": { - "$ref": "#/$defs/Authentication" + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" }, "bindDN": { "type": "string" @@ -1687,8 +1731,6 @@ "type": "object", "required": [ "name", - "host", - "auth", "bindDN" ] }, @@ -1753,15 +1795,20 @@ "connection": { "type": "string" }, - "auth": { - "$ref": "#/$defs/Authentication" + "url": { + "type": "string" + }, + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" } }, "additionalProperties": false, "type": "object", "required": [ - "name", - "connection" + "name" ] }, "MssqlCheck": { @@ -1790,8 +1837,14 @@ "connection": { "type": "string" }, - "auth": { - "$ref": "#/$defs/Authentication" + "url": { + "type": "string" + }, + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" }, "query": { "type": "string" @@ -1803,8 +1856,7 @@ "additionalProperties": false, "type": "object", "required": [ - "name", - "connection" + "name" ] }, "MysqlCheck": { @@ -1833,8 +1885,14 @@ "connection": { "type": "string" }, - "auth": { - "$ref": "#/$defs/Authentication" + "url": { + "type": "string" + }, + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" }, "query": { "type": "string" @@ -1846,8 +1904,7 @@ "additionalProperties": false, "type": "object", "required": [ - "name", - "connection" + "name" ] }, "NamespaceCheck": { @@ -2053,8 +2110,11 @@ "url": { "type": "string" }, - "auth": { - "$ref": "#/$defs/Authentication" + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" }, "query": { "type": "string" @@ -2070,7 +2130,6 @@ "type": "object", "required": [ "name", - "auth", "query", "index" ] @@ -2206,8 +2265,14 @@ "connection": { "type": "string" }, - "auth": { - "$ref": "#/$defs/Authentication" + "url": { + "type": "string" + }, + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" }, "query": { "type": "string" @@ -2219,8 +2284,7 @@ "additionalProperties": false, "type": "object", "required": [ - "name", - "connection" + "name" ] }, "PrometheusCheck": { @@ -2246,12 +2310,21 @@ "transform": { "$ref": "#/$defs/Template" }, + "host": { + "type": "string" + }, "connection": { "type": "string" }, - "host": { + "url": { "type": "string" }, + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" + }, "query": { "type": "string" } @@ -2260,7 +2333,6 @@ "type": "object", "required": [ "name", - "host", "query" ] }, @@ -2281,11 +2353,17 @@ "connection": { "type": "string" }, - "addr": { + "url": { "type": "string" }, - "auth": { - "$ref": "#/$defs/Authentication" + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" + }, + "addr": { + "type": "string" }, "db": { "type": "integer" @@ -2294,9 +2372,7 @@ "additionalProperties": false, "type": "object", "required": [ - "name", - "addr", - "db" + "name" ] }, "ResourceSelector": { @@ -2424,15 +2500,17 @@ "host": { "type": "string" }, - "auth": { - "$ref": "#/$defs/Authentication" + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" } }, "additionalProperties": false, "type": "object", "required": [ - "host", - "auth" + "host" ] }, "SMBConnection": { @@ -2443,27 +2521,18 @@ "port": { "type": "integer" }, - "auth": { - "$ref": "#/$defs/Authentication" - }, - "domain": { - "type": "string" - }, - "workstation": { - "type": "string" + "username": { + "$ref": "#/$defs/EnvVar" }, - "sharename": { - "type": "string" + "password": { + "$ref": "#/$defs/EnvVar" }, - "searchPath": { + "domain": { "type": "string" } }, "additionalProperties": false, - "type": "object", - "required": [ - "auth" - ] + "type": "object" }, "SecretKeySelector": { "properties": { diff --git a/config/schemas/component.schema.json b/config/schemas/component.schema.json index 7bc0361e9..ae87b1661 100644 --- a/config/schemas/component.schema.json +++ b/config/schemas/component.schema.json @@ -59,11 +59,14 @@ "connection": { "type": "string" }, - "host": { + "url": { "type": "string" }, - "auth": { - "$ref": "#/$defs/Authentication" + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" }, "alerts": { "items": { @@ -102,11 +105,7 @@ } }, "additionalProperties": false, - "type": "object", - "required": [ - "username", - "password" - ] + "type": "object" }, "AwsConfigCheck": { "properties": { @@ -134,8 +133,29 @@ "query": { "type": "string" }, - "awsConnection": { - "$ref": "#/$defs/AWSConnection" + "connection": { + "type": "string" + }, + "accessKey": { + "$ref": "#/$defs/EnvVar" + }, + "secretKey": { + "$ref": "#/$defs/EnvVar" + }, + "region": { + "type": "string" + }, + "endpoint": { + "type": "string" + }, + "skipTLSVerify": { + "type": "boolean" + }, + "objectPath": { + "type": "string" + }, + "usePathStyle": { + "type": "boolean" }, "aggregatorName": { "type": "string" @@ -189,8 +209,29 @@ }, "type": "array" }, - "awsConnection": { - "$ref": "#/$defs/AWSConnection" + "connection": { + "type": "string" + }, + "accessKey": { + "$ref": "#/$defs/EnvVar" + }, + "secretKey": { + "$ref": "#/$defs/EnvVar" + }, + "region": { + "type": "string" + }, + "endpoint": { + "type": "string" + }, + "skipTLSVerify": { + "type": "boolean" + }, + "objectPath": { + "type": "string" + }, + "usePathStyle": { + "type": "boolean" } }, "additionalProperties": false, @@ -569,18 +610,6 @@ "transform": { "$ref": "#/$defs/Template" }, - "filter": { - "$ref": "#/$defs/CloudWatchFilter" - } - }, - "additionalProperties": false, - "type": "object", - "required": [ - "name" - ] - }, - "CloudWatchFilter": { - "properties": { "actionPrefix": { "type": "string" }, @@ -598,7 +627,10 @@ } }, "additionalProperties": false, - "type": "object" + "type": "object", + "required": [ + "name" + ] }, "Component": { "properties": { @@ -1159,6 +1191,9 @@ "transform": { "$ref": "#/$defs/Template" }, + "connection": { + "type": "string" + }, "host": { "type": "string" }, @@ -1276,8 +1311,11 @@ "url": { "type": "string" }, - "auth": { - "$ref": "#/$defs/Authentication" + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" }, "query": { "type": "string" @@ -1588,6 +1626,15 @@ "connection": { "type": "string" }, + "url": { + "type": "string" + }, + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" + }, "endpoint": { "type": "string" }, @@ -1630,9 +1677,6 @@ }, "type": "array" }, - "authentication": { - "$ref": "#/$defs/Authentication" - }, "templateBody": { "type": "boolean" } @@ -1739,9 +1783,6 @@ "labels": { "$ref": "#/$defs/Labels" }, - "connection": { - "type": "string" - }, "jmx": { "$ref": "#/$defs/EnvVar" }, @@ -1879,11 +1920,14 @@ "connection": { "type": "string" }, - "host": { + "url": { "type": "string" }, - "auth": { - "$ref": "#/$defs/Authentication" + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" }, "bindDN": { "type": "string" @@ -1899,8 +1943,6 @@ "type": "object", "required": [ "name", - "host", - "auth", "bindDN" ] }, @@ -2015,15 +2057,20 @@ "connection": { "type": "string" }, - "auth": { - "$ref": "#/$defs/Authentication" + "url": { + "type": "string" + }, + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" } }, "additionalProperties": false, "type": "object", "required": [ - "name", - "connection" + "name" ] }, "MssqlCheck": { @@ -2052,8 +2099,14 @@ "connection": { "type": "string" }, - "auth": { - "$ref": "#/$defs/Authentication" + "url": { + "type": "string" + }, + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" }, "query": { "type": "string" @@ -2065,8 +2118,7 @@ "additionalProperties": false, "type": "object", "required": [ - "name", - "connection" + "name" ] }, "MysqlCheck": { @@ -2095,8 +2147,14 @@ "connection": { "type": "string" }, - "auth": { - "$ref": "#/$defs/Authentication" + "url": { + "type": "string" + }, + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" }, "query": { "type": "string" @@ -2108,8 +2166,7 @@ "additionalProperties": false, "type": "object", "required": [ - "name", - "connection" + "name" ] }, "NamespaceCheck": { @@ -2315,8 +2372,11 @@ "url": { "type": "string" }, - "auth": { - "$ref": "#/$defs/Authentication" + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" }, "query": { "type": "string" @@ -2332,7 +2392,6 @@ "type": "object", "required": [ "name", - "auth", "query", "index" ] @@ -2468,8 +2527,14 @@ "connection": { "type": "string" }, - "auth": { - "$ref": "#/$defs/Authentication" + "url": { + "type": "string" + }, + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" }, "query": { "type": "string" @@ -2481,8 +2546,7 @@ "additionalProperties": false, "type": "object", "required": [ - "name", - "connection" + "name" ] }, "PrometheusCheck": { @@ -2508,12 +2572,21 @@ "transform": { "$ref": "#/$defs/Template" }, + "host": { + "type": "string" + }, "connection": { "type": "string" }, - "host": { + "url": { "type": "string" }, + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" + }, "query": { "type": "string" } @@ -2522,7 +2595,6 @@ "type": "object", "required": [ "name", - "host", "query" ] }, @@ -2615,11 +2687,17 @@ "connection": { "type": "string" }, - "addr": { + "url": { "type": "string" }, - "auth": { - "$ref": "#/$defs/Authentication" + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" + }, + "addr": { + "type": "string" }, "db": { "type": "integer" @@ -2628,9 +2706,7 @@ "additionalProperties": false, "type": "object", "required": [ - "name", - "addr", - "db" + "name" ] }, "RelationshipSpec": { @@ -2776,15 +2852,17 @@ "host": { "type": "string" }, - "auth": { - "$ref": "#/$defs/Authentication" + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" } }, "additionalProperties": false, "type": "object", "required": [ - "host", - "auth" + "host" ] }, "SMBConnection": { @@ -2795,27 +2873,18 @@ "port": { "type": "integer" }, - "auth": { - "$ref": "#/$defs/Authentication" - }, - "domain": { - "type": "string" - }, - "workstation": { - "type": "string" + "username": { + "$ref": "#/$defs/EnvVar" }, - "sharename": { - "type": "string" + "password": { + "$ref": "#/$defs/EnvVar" }, - "searchPath": { + "domain": { "type": "string" } }, "additionalProperties": false, - "type": "object", - "required": [ - "auth" - ] + "type": "object" }, "SecretKeySelector": { "properties": { diff --git a/config/schemas/health_alertmanager.schema.json b/config/schemas/health_alertmanager.schema.json index e8b21a521..93a6c0009 100644 --- a/config/schemas/health_alertmanager.schema.json +++ b/config/schemas/health_alertmanager.schema.json @@ -29,11 +29,14 @@ "connection": { "type": "string" }, - "host": { + "url": { "type": "string" }, - "auth": { - "$ref": "#/$defs/Authentication" + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" }, "alerts": { "items": { @@ -62,22 +65,6 @@ "name" ] }, - "Authentication": { - "properties": { - "username": { - "$ref": "#/$defs/EnvVar" - }, - "password": { - "$ref": "#/$defs/EnvVar" - } - }, - "additionalProperties": false, - "type": "object", - "required": [ - "username", - "password" - ] - }, "ConfigMapKeySelector": { "properties": { "name": { diff --git a/config/schemas/health_awsconfig.schema.json b/config/schemas/health_awsconfig.schema.json index 3fc17bcba..b14fd834c 100644 --- a/config/schemas/health_awsconfig.schema.json +++ b/config/schemas/health_awsconfig.schema.json @@ -3,36 +3,6 @@ "$id": "https://github.com/flanksource/canary-checker/api/v1/aws-config-check", "$ref": "#/$defs/AwsConfigCheck", "$defs": { - "AWSConnection": { - "properties": { - "connection": { - "type": "string" - }, - "accessKey": { - "$ref": "#/$defs/EnvVar" - }, - "secretKey": { - "$ref": "#/$defs/EnvVar" - }, - "region": { - "type": "string" - }, - "endpoint": { - "type": "string" - }, - "skipTLSVerify": { - "type": "boolean" - }, - "objectPath": { - "type": "string" - }, - "usePathStyle": { - "type": "boolean" - } - }, - "additionalProperties": false, - "type": "object" - }, "AwsConfigCheck": { "properties": { "description": { @@ -59,8 +29,29 @@ "query": { "type": "string" }, - "awsConnection": { - "$ref": "#/$defs/AWSConnection" + "connection": { + "type": "string" + }, + "accessKey": { + "$ref": "#/$defs/EnvVar" + }, + "secretKey": { + "$ref": "#/$defs/EnvVar" + }, + "region": { + "type": "string" + }, + "endpoint": { + "type": "string" + }, + "skipTLSVerify": { + "type": "boolean" + }, + "objectPath": { + "type": "string" + }, + "usePathStyle": { + "type": "boolean" }, "aggregatorName": { "type": "string" diff --git a/config/schemas/health_awsconfigrule.schema.json b/config/schemas/health_awsconfigrule.schema.json index e3c0ba95e..245ec69bc 100644 --- a/config/schemas/health_awsconfigrule.schema.json +++ b/config/schemas/health_awsconfigrule.schema.json @@ -3,36 +3,6 @@ "$id": "https://github.com/flanksource/canary-checker/api/v1/aws-config-rule-check", "$ref": "#/$defs/AwsConfigRuleCheck", "$defs": { - "AWSConnection": { - "properties": { - "connection": { - "type": "string" - }, - "accessKey": { - "$ref": "#/$defs/EnvVar" - }, - "secretKey": { - "$ref": "#/$defs/EnvVar" - }, - "region": { - "type": "string" - }, - "endpoint": { - "type": "string" - }, - "skipTLSVerify": { - "type": "boolean" - }, - "objectPath": { - "type": "string" - }, - "usePathStyle": { - "type": "boolean" - } - }, - "additionalProperties": false, - "type": "object" - }, "AwsConfigRuleCheck": { "properties": { "description": { @@ -74,8 +44,29 @@ }, "type": "array" }, - "awsConnection": { - "$ref": "#/$defs/AWSConnection" + "connection": { + "type": "string" + }, + "accessKey": { + "$ref": "#/$defs/EnvVar" + }, + "secretKey": { + "$ref": "#/$defs/EnvVar" + }, + "region": { + "type": "string" + }, + "endpoint": { + "type": "string" + }, + "skipTLSVerify": { + "type": "boolean" + }, + "objectPath": { + "type": "string" + }, + "usePathStyle": { + "type": "boolean" } }, "additionalProperties": false, diff --git a/config/schemas/health_cloudwatch.schema.json b/config/schemas/health_cloudwatch.schema.json index e93212c60..dac455c88 100644 --- a/config/schemas/health_cloudwatch.schema.json +++ b/config/schemas/health_cloudwatch.schema.json @@ -50,18 +50,6 @@ "transform": { "$ref": "#/$defs/Template" }, - "filter": { - "$ref": "#/$defs/CloudWatchFilter" - } - }, - "additionalProperties": false, - "type": "object", - "required": [ - "name" - ] - }, - "CloudWatchFilter": { - "properties": { "actionPrefix": { "type": "string" }, @@ -79,7 +67,10 @@ } }, "additionalProperties": false, - "type": "object" + "type": "object", + "required": [ + "name" + ] }, "ConfigMapKeySelector": { "properties": { diff --git a/config/schemas/health_containerdPull.schema.json b/config/schemas/health_containerdPull.schema.json index d770e9562..073ebc88e 100644 --- a/config/schemas/health_containerdPull.schema.json +++ b/config/schemas/health_containerdPull.schema.json @@ -13,11 +13,7 @@ } }, "additionalProperties": false, - "type": "object", - "required": [ - "username", - "password" - ] + "type": "object" }, "ConfigMapKeySelector": { "properties": { diff --git a/config/schemas/health_dockerPull.schema.json b/config/schemas/health_dockerPull.schema.json index 2991e10a1..5bf82ae0f 100644 --- a/config/schemas/health_dockerPull.schema.json +++ b/config/schemas/health_dockerPull.schema.json @@ -13,11 +13,7 @@ } }, "additionalProperties": false, - "type": "object", - "required": [ - "username", - "password" - ] + "type": "object" }, "ConfigMapKeySelector": { "properties": { diff --git a/config/schemas/health_dockerPush.schema.json b/config/schemas/health_dockerPush.schema.json index 37eee6a5c..598c86e57 100644 --- a/config/schemas/health_dockerPush.schema.json +++ b/config/schemas/health_dockerPush.schema.json @@ -13,11 +13,7 @@ } }, "additionalProperties": false, - "type": "object", - "required": [ - "username", - "password" - ] + "type": "object" }, "ConfigMapKeySelector": { "properties": { diff --git a/config/schemas/health_dynatrace.schema.json b/config/schemas/health_dynatrace.schema.json index 07c64266b..8ca1b569f 100644 --- a/config/schemas/health_dynatrace.schema.json +++ b/config/schemas/health_dynatrace.schema.json @@ -41,6 +41,9 @@ "transform": { "$ref": "#/$defs/Template" }, + "connection": { + "type": "string" + }, "host": { "type": "string" }, diff --git a/config/schemas/health_elasticsearch.schema.json b/config/schemas/health_elasticsearch.schema.json index 7fbf163a7..16a9311df 100644 --- a/config/schemas/health_elasticsearch.schema.json +++ b/config/schemas/health_elasticsearch.schema.json @@ -3,22 +3,6 @@ "$id": "https://github.com/flanksource/canary-checker/api/v1/elasticsearch-check", "$ref": "#/$defs/ElasticsearchCheck", "$defs": { - "Authentication": { - "properties": { - "username": { - "$ref": "#/$defs/EnvVar" - }, - "password": { - "$ref": "#/$defs/EnvVar" - } - }, - "additionalProperties": false, - "type": "object", - "required": [ - "username", - "password" - ] - }, "ConfigMapKeySelector": { "properties": { "name": { @@ -63,8 +47,11 @@ "url": { "type": "string" }, - "auth": { - "$ref": "#/$defs/Authentication" + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" }, "query": { "type": "string" diff --git a/config/schemas/health_folder.schema.json b/config/schemas/health_folder.schema.json index 080b7efe7..6f6ec1b01 100644 --- a/config/schemas/health_folder.schema.json +++ b/config/schemas/health_folder.schema.json @@ -33,22 +33,6 @@ "additionalProperties": false, "type": "object" }, - "Authentication": { - "properties": { - "username": { - "$ref": "#/$defs/EnvVar" - }, - "password": { - "$ref": "#/$defs/EnvVar" - } - }, - "additionalProperties": false, - "type": "object", - "required": [ - "username", - "password" - ] - }, "ConfigMapKeySelector": { "properties": { "name": { @@ -219,15 +203,17 @@ "host": { "type": "string" }, - "auth": { - "$ref": "#/$defs/Authentication" + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" } }, "additionalProperties": false, "type": "object", "required": [ - "host", - "auth" + "host" ] }, "SMBConnection": { @@ -238,27 +224,18 @@ "port": { "type": "integer" }, - "auth": { - "$ref": "#/$defs/Authentication" - }, - "domain": { - "type": "string" - }, - "workstation": { - "type": "string" + "username": { + "$ref": "#/$defs/EnvVar" }, - "sharename": { - "type": "string" + "password": { + "$ref": "#/$defs/EnvVar" }, - "searchPath": { + "domain": { "type": "string" } }, "additionalProperties": false, - "type": "object", - "required": [ - "auth" - ] + "type": "object" }, "SecretKeySelector": { "properties": { diff --git a/config/schemas/health_helm.schema.json b/config/schemas/health_helm.schema.json index 38c27395b..e7bb864df 100644 --- a/config/schemas/health_helm.schema.json +++ b/config/schemas/health_helm.schema.json @@ -13,11 +13,7 @@ } }, "additionalProperties": false, - "type": "object", - "required": [ - "username", - "password" - ] + "type": "object" }, "ConfigMapKeySelector": { "properties": { diff --git a/config/schemas/health_http.schema.json b/config/schemas/health_http.schema.json index 86f00743b..2a703be73 100644 --- a/config/schemas/health_http.schema.json +++ b/config/schemas/health_http.schema.json @@ -3,22 +3,6 @@ "$id": "https://github.com/flanksource/canary-checker/api/v1/http-check", "$ref": "#/$defs/HTTPCheck", "$defs": { - "Authentication": { - "properties": { - "username": { - "$ref": "#/$defs/EnvVar" - }, - "password": { - "$ref": "#/$defs/EnvVar" - } - }, - "additionalProperties": false, - "type": "object", - "required": [ - "username", - "password" - ] - }, "ConfigMapKeySelector": { "properties": { "name": { @@ -87,6 +71,15 @@ "connection": { "type": "string" }, + "url": { + "type": "string" + }, + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" + }, "endpoint": { "type": "string" }, @@ -129,9 +122,6 @@ }, "type": "array" }, - "authentication": { - "$ref": "#/$defs/Authentication" - }, "templateBody": { "type": "boolean" } diff --git a/config/schemas/health_jmeter.schema.json b/config/schemas/health_jmeter.schema.json index a05060192..dfbcb3c42 100644 --- a/config/schemas/health_jmeter.schema.json +++ b/config/schemas/health_jmeter.schema.json @@ -59,9 +59,6 @@ "labels": { "$ref": "#/$defs/Labels" }, - "connection": { - "type": "string" - }, "jmx": { "$ref": "#/$defs/EnvVar" }, diff --git a/config/schemas/health_ldap.schema.json b/config/schemas/health_ldap.schema.json index ecd98cdb4..715f818d1 100644 --- a/config/schemas/health_ldap.schema.json +++ b/config/schemas/health_ldap.schema.json @@ -3,22 +3,6 @@ "$id": "https://github.com/flanksource/canary-checker/api/v1/ldap-check", "$ref": "#/$defs/LDAPCheck", "$defs": { - "Authentication": { - "properties": { - "username": { - "$ref": "#/$defs/EnvVar" - }, - "password": { - "$ref": "#/$defs/EnvVar" - } - }, - "additionalProperties": false, - "type": "object", - "required": [ - "username", - "password" - ] - }, "ConfigMapKeySelector": { "properties": { "name": { @@ -78,11 +62,14 @@ "connection": { "type": "string" }, - "host": { + "url": { "type": "string" }, - "auth": { - "$ref": "#/$defs/Authentication" + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" }, "bindDN": { "type": "string" @@ -98,8 +85,6 @@ "type": "object", "required": [ "name", - "host", - "auth", "bindDN" ] }, diff --git a/config/schemas/health_mongodb.schema.json b/config/schemas/health_mongodb.schema.json index edc955f9d..965c98918 100644 --- a/config/schemas/health_mongodb.schema.json +++ b/config/schemas/health_mongodb.schema.json @@ -3,22 +3,6 @@ "$id": "https://github.com/flanksource/canary-checker/api/v1/mongo-db-check", "$ref": "#/$defs/MongoDBCheck", "$defs": { - "Authentication": { - "properties": { - "username": { - "$ref": "#/$defs/EnvVar" - }, - "password": { - "$ref": "#/$defs/EnvVar" - } - }, - "additionalProperties": false, - "type": "object", - "required": [ - "username", - "password" - ] - }, "ConfigMapKeySelector": { "properties": { "name": { @@ -86,15 +70,20 @@ "connection": { "type": "string" }, - "auth": { - "$ref": "#/$defs/Authentication" + "url": { + "type": "string" + }, + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" } }, "additionalProperties": false, "type": "object", "required": [ - "name", - "connection" + "name" ] }, "SecretKeySelector": { diff --git a/config/schemas/health_mssql.schema.json b/config/schemas/health_mssql.schema.json index 6bbe145e9..6c8d42c87 100644 --- a/config/schemas/health_mssql.schema.json +++ b/config/schemas/health_mssql.schema.json @@ -3,22 +3,6 @@ "$id": "https://github.com/flanksource/canary-checker/api/v1/mssql-check", "$ref": "#/$defs/MssqlCheck", "$defs": { - "Authentication": { - "properties": { - "username": { - "$ref": "#/$defs/EnvVar" - }, - "password": { - "$ref": "#/$defs/EnvVar" - } - }, - "additionalProperties": false, - "type": "object", - "required": [ - "username", - "password" - ] - }, "ConfigMapKeySelector": { "properties": { "name": { @@ -95,8 +79,14 @@ "connection": { "type": "string" }, - "auth": { - "$ref": "#/$defs/Authentication" + "url": { + "type": "string" + }, + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" }, "query": { "type": "string" @@ -108,8 +98,7 @@ "additionalProperties": false, "type": "object", "required": [ - "name", - "connection" + "name" ] }, "SecretKeySelector": { diff --git a/config/schemas/health_mysql.schema.json b/config/schemas/health_mysql.schema.json index 412c22a59..987204f58 100644 --- a/config/schemas/health_mysql.schema.json +++ b/config/schemas/health_mysql.schema.json @@ -3,22 +3,6 @@ "$id": "https://github.com/flanksource/canary-checker/api/v1/mysql-check", "$ref": "#/$defs/MysqlCheck", "$defs": { - "Authentication": { - "properties": { - "username": { - "$ref": "#/$defs/EnvVar" - }, - "password": { - "$ref": "#/$defs/EnvVar" - } - }, - "additionalProperties": false, - "type": "object", - "required": [ - "username", - "password" - ] - }, "ConfigMapKeySelector": { "properties": { "name": { @@ -95,8 +79,14 @@ "connection": { "type": "string" }, - "auth": { - "$ref": "#/$defs/Authentication" + "url": { + "type": "string" + }, + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" }, "query": { "type": "string" @@ -108,8 +98,7 @@ "additionalProperties": false, "type": "object", "required": [ - "name", - "connection" + "name" ] }, "SecretKeySelector": { diff --git a/config/schemas/health_opensearch.schema.json b/config/schemas/health_opensearch.schema.json index 62cf19442..b7aa49707 100644 --- a/config/schemas/health_opensearch.schema.json +++ b/config/schemas/health_opensearch.schema.json @@ -3,22 +3,6 @@ "$id": "https://github.com/flanksource/canary-checker/api/v1/open-search-check", "$ref": "#/$defs/OpenSearchCheck", "$defs": { - "Authentication": { - "properties": { - "username": { - "$ref": "#/$defs/EnvVar" - }, - "password": { - "$ref": "#/$defs/EnvVar" - } - }, - "additionalProperties": false, - "type": "object", - "required": [ - "username", - "password" - ] - }, "ConfigMapKeySelector": { "properties": { "name": { @@ -98,8 +82,11 @@ "url": { "type": "string" }, - "auth": { - "$ref": "#/$defs/Authentication" + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" }, "query": { "type": "string" @@ -115,7 +102,6 @@ "type": "object", "required": [ "name", - "auth", "query", "index" ] diff --git a/config/schemas/health_postgres.schema.json b/config/schemas/health_postgres.schema.json index 196dce3b5..82bf8296a 100644 --- a/config/schemas/health_postgres.schema.json +++ b/config/schemas/health_postgres.schema.json @@ -3,22 +3,6 @@ "$id": "https://github.com/flanksource/canary-checker/api/v1/postgres-check", "$ref": "#/$defs/PostgresCheck", "$defs": { - "Authentication": { - "properties": { - "username": { - "$ref": "#/$defs/EnvVar" - }, - "password": { - "$ref": "#/$defs/EnvVar" - } - }, - "additionalProperties": false, - "type": "object", - "required": [ - "username", - "password" - ] - }, "ConfigMapKeySelector": { "properties": { "name": { @@ -95,8 +79,14 @@ "connection": { "type": "string" }, - "auth": { - "$ref": "#/$defs/Authentication" + "url": { + "type": "string" + }, + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" }, "query": { "type": "string" @@ -108,8 +98,7 @@ "additionalProperties": false, "type": "object", "required": [ - "name", - "connection" + "name" ] }, "SecretKeySelector": { diff --git a/config/schemas/health_prometheus.schema.json b/config/schemas/health_prometheus.schema.json index 9e7a1de14..b4dcab392 100644 --- a/config/schemas/health_prometheus.schema.json +++ b/config/schemas/health_prometheus.schema.json @@ -3,6 +3,48 @@ "$id": "https://github.com/flanksource/canary-checker/api/v1/prometheus-check", "$ref": "#/$defs/PrometheusCheck", "$defs": { + "ConfigMapKeySelector": { + "properties": { + "name": { + "type": "string" + }, + "key": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "key" + ] + }, + "EnvVar": { + "properties": { + "name": { + "type": "string" + }, + "value": { + "type": "string" + }, + "valueFrom": { + "$ref": "#/$defs/EnvVarSource" + } + }, + "additionalProperties": false, + "type": "object" + }, + "EnvVarSource": { + "properties": { + "configMapKeyRef": { + "$ref": "#/$defs/ConfigMapKeySelector" + }, + "secretKeyRef": { + "$ref": "#/$defs/SecretKeySelector" + } + }, + "additionalProperties": false, + "type": "object" + }, "Labels": { "patternProperties": { ".*": { @@ -34,12 +76,21 @@ "transform": { "$ref": "#/$defs/Template" }, + "host": { + "type": "string" + }, "connection": { "type": "string" }, - "host": { + "url": { "type": "string" }, + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" + }, "query": { "type": "string" } @@ -48,10 +99,24 @@ "type": "object", "required": [ "name", - "host", "query" ] }, + "SecretKeySelector": { + "properties": { + "name": { + "type": "string" + }, + "key": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "key" + ] + }, "Template": { "properties": { "template": { diff --git a/config/schemas/health_redis.schema.json b/config/schemas/health_redis.schema.json index adc3a6bd6..153d4cc4b 100644 --- a/config/schemas/health_redis.schema.json +++ b/config/schemas/health_redis.schema.json @@ -3,22 +3,6 @@ "$id": "https://github.com/flanksource/canary-checker/api/v1/redis-check", "$ref": "#/$defs/RedisCheck", "$defs": { - "Authentication": { - "properties": { - "username": { - "$ref": "#/$defs/EnvVar" - }, - "password": { - "$ref": "#/$defs/EnvVar" - } - }, - "additionalProperties": false, - "type": "object", - "required": [ - "username", - "password" - ] - }, "ConfigMapKeySelector": { "properties": { "name": { @@ -86,11 +70,17 @@ "connection": { "type": "string" }, - "addr": { + "url": { "type": "string" }, - "auth": { - "$ref": "#/$defs/Authentication" + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" + }, + "addr": { + "type": "string" }, "db": { "type": "integer" @@ -99,9 +89,7 @@ "additionalProperties": false, "type": "object", "required": [ - "name", - "addr", - "db" + "name" ] }, "SecretKeySelector": { diff --git a/config/schemas/topology.schema.json b/config/schemas/topology.schema.json index 628b6f8c5..c33ab0b94 100644 --- a/config/schemas/topology.schema.json +++ b/config/schemas/topology.schema.json @@ -59,11 +59,14 @@ "connection": { "type": "string" }, - "host": { + "url": { "type": "string" }, - "auth": { - "$ref": "#/$defs/Authentication" + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" }, "alerts": { "items": { @@ -102,11 +105,7 @@ } }, "additionalProperties": false, - "type": "object", - "required": [ - "username", - "password" - ] + "type": "object" }, "AwsConfigCheck": { "properties": { @@ -134,8 +133,29 @@ "query": { "type": "string" }, - "awsConnection": { - "$ref": "#/$defs/AWSConnection" + "connection": { + "type": "string" + }, + "accessKey": { + "$ref": "#/$defs/EnvVar" + }, + "secretKey": { + "$ref": "#/$defs/EnvVar" + }, + "region": { + "type": "string" + }, + "endpoint": { + "type": "string" + }, + "skipTLSVerify": { + "type": "boolean" + }, + "objectPath": { + "type": "string" + }, + "usePathStyle": { + "type": "boolean" }, "aggregatorName": { "type": "string" @@ -189,8 +209,29 @@ }, "type": "array" }, - "awsConnection": { - "$ref": "#/$defs/AWSConnection" + "connection": { + "type": "string" + }, + "accessKey": { + "$ref": "#/$defs/EnvVar" + }, + "secretKey": { + "$ref": "#/$defs/EnvVar" + }, + "region": { + "type": "string" + }, + "endpoint": { + "type": "string" + }, + "skipTLSVerify": { + "type": "boolean" + }, + "objectPath": { + "type": "string" + }, + "usePathStyle": { + "type": "boolean" } }, "additionalProperties": false, @@ -569,18 +610,6 @@ "transform": { "$ref": "#/$defs/Template" }, - "filter": { - "$ref": "#/$defs/CloudWatchFilter" - } - }, - "additionalProperties": false, - "type": "object", - "required": [ - "name" - ] - }, - "CloudWatchFilter": { - "properties": { "actionPrefix": { "type": "string" }, @@ -598,7 +627,10 @@ } }, "additionalProperties": false, - "type": "object" + "type": "object", + "required": [ + "name" + ] }, "ComponentCheck": { "properties": { @@ -1129,6 +1161,9 @@ "transform": { "$ref": "#/$defs/Template" }, + "connection": { + "type": "string" + }, "host": { "type": "string" }, @@ -1246,8 +1281,11 @@ "url": { "type": "string" }, - "auth": { - "$ref": "#/$defs/Authentication" + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" }, "query": { "type": "string" @@ -1558,6 +1596,15 @@ "connection": { "type": "string" }, + "url": { + "type": "string" + }, + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" + }, "endpoint": { "type": "string" }, @@ -1600,9 +1647,6 @@ }, "type": "array" }, - "authentication": { - "$ref": "#/$defs/Authentication" - }, "templateBody": { "type": "boolean" } @@ -1709,9 +1753,6 @@ "labels": { "$ref": "#/$defs/Labels" }, - "connection": { - "type": "string" - }, "jmx": { "$ref": "#/$defs/EnvVar" }, @@ -1849,11 +1890,14 @@ "connection": { "type": "string" }, - "host": { + "url": { "type": "string" }, - "auth": { - "$ref": "#/$defs/Authentication" + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" }, "bindDN": { "type": "string" @@ -1869,8 +1913,6 @@ "type": "object", "required": [ "name", - "host", - "auth", "bindDN" ] }, @@ -1985,15 +2027,20 @@ "connection": { "type": "string" }, - "auth": { - "$ref": "#/$defs/Authentication" + "url": { + "type": "string" + }, + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" } }, "additionalProperties": false, "type": "object", "required": [ - "name", - "connection" + "name" ] }, "MssqlCheck": { @@ -2022,8 +2069,14 @@ "connection": { "type": "string" }, - "auth": { - "$ref": "#/$defs/Authentication" + "url": { + "type": "string" + }, + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" }, "query": { "type": "string" @@ -2035,8 +2088,7 @@ "additionalProperties": false, "type": "object", "required": [ - "name", - "connection" + "name" ] }, "MysqlCheck": { @@ -2065,8 +2117,14 @@ "connection": { "type": "string" }, - "auth": { - "$ref": "#/$defs/Authentication" + "url": { + "type": "string" + }, + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" }, "query": { "type": "string" @@ -2078,8 +2136,7 @@ "additionalProperties": false, "type": "object", "required": [ - "name", - "connection" + "name" ] }, "NamespaceCheck": { @@ -2285,8 +2342,11 @@ "url": { "type": "string" }, - "auth": { - "$ref": "#/$defs/Authentication" + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" }, "query": { "type": "string" @@ -2302,7 +2362,6 @@ "type": "object", "required": [ "name", - "auth", "query", "index" ] @@ -2438,8 +2497,14 @@ "connection": { "type": "string" }, - "auth": { - "$ref": "#/$defs/Authentication" + "url": { + "type": "string" + }, + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" }, "query": { "type": "string" @@ -2451,8 +2516,7 @@ "additionalProperties": false, "type": "object", "required": [ - "name", - "connection" + "name" ] }, "PrometheusCheck": { @@ -2478,12 +2542,21 @@ "transform": { "$ref": "#/$defs/Template" }, + "host": { + "type": "string" + }, "connection": { "type": "string" }, - "host": { + "url": { "type": "string" }, + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" + }, "query": { "type": "string" } @@ -2492,7 +2565,6 @@ "type": "object", "required": [ "name", - "host", "query" ] }, @@ -2585,11 +2657,17 @@ "connection": { "type": "string" }, - "addr": { + "url": { "type": "string" }, - "auth": { - "$ref": "#/$defs/Authentication" + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" + }, + "addr": { + "type": "string" }, "db": { "type": "integer" @@ -2598,9 +2676,7 @@ "additionalProperties": false, "type": "object", "required": [ - "name", - "addr", - "db" + "name" ] }, "RelationshipSpec": { @@ -2746,15 +2822,17 @@ "host": { "type": "string" }, - "auth": { - "$ref": "#/$defs/Authentication" + "username": { + "$ref": "#/$defs/EnvVar" + }, + "password": { + "$ref": "#/$defs/EnvVar" } }, "additionalProperties": false, "type": "object", "required": [ - "host", - "auth" + "host" ] }, "SMBConnection": { @@ -2765,27 +2843,18 @@ "port": { "type": "integer" }, - "auth": { - "$ref": "#/$defs/Authentication" - }, - "domain": { - "type": "string" - }, - "workstation": { - "type": "string" + "username": { + "$ref": "#/$defs/EnvVar" }, - "sharename": { - "type": "string" + "password": { + "$ref": "#/$defs/EnvVar" }, - "searchPath": { + "domain": { "type": "string" } }, "additionalProperties": false, - "type": "object", - "required": [ - "auth" - ] + "type": "object" }, "SecretKeySelector": { "properties": { diff --git a/docs/API.md b/docs/API.md deleted file mode 100644 index d38d55646..000000000 --- a/docs/API.md +++ /dev/null @@ -1,1268 +0,0 @@ ---- -title: Canary Types -hide: - - toc ---- - -## Canary - -Canary is the Schema for the canaries API - -| Field | Description | Scheme | Required | -| ----- | ----------- | ------ | -------- | -| **ObjectMeta** | | [metav1.ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.20/#objectmeta-v1-meta) | Yes | -| **Spec** | | [CanarySpec](#canaryspec) | Yes | -| **Status** | | [CanaryStatus](#canarystatus) | Yes | -| **TypeMeta** | | metav1.TypeMeta | Yes | - - -## CanarySpec - -CanarySpec defines the desired state of Canary - -| Field | Description | Scheme | Required | -| ----- | ----------- | ------ | -------- | -| cloudwatch | | \[\][CloudWatchCheck](#cloudwatchcheck) | | -| containerd | | \[\][ContainerdPullCheck](#containerdpullcheck) | | -| containerdPush | | \[\][ContainerdPushCheck](#containerdpushcheck) | | -| dns | | \[\][DNSCheck](#dnscheck) | | -| docker | | \[\][DockerPullCheck](#dockerpullcheck) | | -| dockerPush | | \[\][DockerPushCheck](#dockerpushcheck) | | -| ec2 | | \[\][EC2Check](#ec2check) | | -| env | | map[string][VarSource](#varsource) | | -| gcsBucket | | \[\][GCSBucketCheck](#gcsbucketcheck) | | -| helm | | \[\][HelmCheck](#helmcheck) | | -| http | | \[\][HTTPCheck](#httpcheck) | | -| icmp | | \[\][ICMPCheck](#icmpcheck) | | -| icon | | string | | -| interval | interval (in seconds) to run checks on Deprecated in favor of Schedule | uint64 | | -| jmeter | | \[\][JmeterCheck](#jmetercheck) | | -| junit | | \[\][JunitCheck](#junitcheck) | | -| ldap | | \[\][LDAPCheck](#ldapcheck) | | -| mongodb | | \[\][MongoDBCheck](#mongodbcheck) | | -| mssql | | \[\][MssqlCheck](#mssqlcheck) | | -| namespace | | \[\][NamespaceCheck](#namespacecheck) | | -| owner | | string | | -| pod | | \[\][PodCheck](#podcheck) | | -| postgres | | \[\][PostgresCheck](#postgrescheck) | | -| prometheus | | \[\][PrometheusCheck](#prometheuscheck) | | -| redis | | \[\][RedisCheck](#redischeck) | | -| restic | | \[\][ResticCheck](#resticcheck) | | -| s3 | | \[\][S3Check](#s3check) | | -| s3Bucket | | \[\][S3BucketCheck](#s3bucketcheck) | | -| schedule | Schedule to run checks on. Supports all cron expression, example: '30 3-6,20-23 * * *'. For more info about cron expression syntax see https://en.wikipedia.org/wiki/Cron - Also supports golang duration, can be set as '@every 1m30s' which runs the check every 1 minute and 30 seconds. | string | | -| severity | | string | | -| smb | | \[\][SmbCheck](#smbcheck) | | -| tcp | | \[\][TCPCheck](#tcpcheck) | | - - -## CanaryStatus - -CanaryStatus defines the observed state of Canary - -| Field | Description | Scheme | Required | -| ----- | ----------- | ------ | -------- | -| **ChecksStatus** | | map[string]*[CheckStatus](#checkstatus) | Yes | -| **ErrorMessage** | | *string | Yes | -| **LastCheck** | | *metav1.Time | Yes | -| **LastTransitionedTime** | | *metav1.Time | Yes | -| **Latency1H** | Average latency to complete all checks | string | Yes | -| **Message** | | *string | Yes | -| **ObservedGeneration** | | int64 | Yes | -| **Status** | | *CanaryStatusCondition | Yes | -| **Uptime1H** | Availibility over a rolling 1h period | string | Yes | - - -## CanaryList - -CanaryList contains a list of Canary - -| Field | Description | Scheme | Required | -| ----- | ----------- | ------ | -------- | -| **Items** | | \[\][Canary](#canary) | Yes | -| **ListMeta** | | [metav1.ListMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.20/#listmeta-v1-meta) | Yes | -| **TypeMeta** | | metav1.TypeMeta | Yes | - - -## CloudWatch - -This checks the cloudwatch for all the Active alarm and response with the reason -??? example - ```yaml - cloudwatch: - - accessKey: - valueFrom: - secretKeyRef: - key: aws - name: access-key - secretKey: - valueFrom: - secretKeyRef: - key: aws - name: secrey-key - region: "us-east-1" - #skipTLSVerify: true - - ``` - -| Field | Description | Scheme | Required | -| ----- | ----------- | ------ | -------- | -| **accessKey** | | [kommons.EnvVar](https://pkg.go.dev/github.com/flanksource/kommons#EnvVar) | Yes | -| description | Description for the check | string | | -| display | | [Template](#template) | | -| endpoint | | string | | -| filter | | [CloudWatchFilter](#cloudwatchfilter) | | -| icon | Icon for overwriting default icon on the dashboard | string | | -| name | Name of the check | string | | -| region | | string | | -| **secretKey** | | [kommons.EnvVar](https://pkg.go.dev/github.com/flanksource/kommons#EnvVar) | Yes | -| skipTLSVerify | Skip TLS verify when connecting to aws | bool | | -| test | | [Template](#template) | | - - -## ContainerdPull - -??? example - ```yaml - apiVersion: canaries.flanksource.com/v1 - kind: Canary - metadata: - name: containerd-pull-pass - spec: - interval: 30 - containerd: - - image: docker.io/library/busybox:1.31.1 - expectedDigest: sha256:95cf004f559831017cdf4628aaf1bb30133677be8702a8c5f2994629f637a209 - expectedSize: 764556 - - ``` - -| Field | Description | Scheme | Required | -| ----- | ----------- | ------ | -------- | -| auth | | [Authentication](#authentication) | | -| description | Description for the check | string | | -| expectedDigest | | string | | -| expectedSize | | int64 | | -| icon | Icon for overwriting default icon on the dashboard | string | | -| **image** | | string | Yes | -| name | Name of the check | string | | - - -## ContainerdPush - -??? example - ```yaml - - ``` - -| Field | Description | Scheme | Required | -| ----- | ----------- | ------ | -------- | -| description | Description for the check | string | | -| icon | Icon for overwriting default icon on the dashboard | string | | -| **image** | | string | Yes | -| name | Name of the check | string | | -| **password** | | string | Yes | -| **username** | | string | Yes | - - -## DNS - -??? example - ```yaml - apiVersion: canaries.flanksource.com/v1 - kind: Canary - metadata: - name: dns-pass - spec: - interval: 30 - dns: - - server: 8.8.8.8 - port: 53 - query: "1.2.3.4.nip.io" - querytype: "A" - minrecords: 1 - exactreply: ["1.2.3.4"] - timeout: 10 - thresholdMillis: 1000 - - server: 8.8.8.8 - port: 53 - query: "8.8.8.8" - querytype: "PTR" - minrecords: 1 - exactreply: ["dns.google."] - timeout: 10 - thresholdMillis: 100 - - server: 8.8.8.8 - port: 53 - query: "dns.google" - querytype: "CNAME" - minrecords: 1 - exactreply: ["dns.google."] - timeout: 10 - thresholdMillis: 1000 - - server: 8.8.8.8 - port: 53 - query: "flanksource.com" - querytype: "MX" - minrecords: 1 - exactreply: - - "aspmx.l.google.com. 1" - - "alt1.aspmx.l.google.com. 5" - - "alt2.aspmx.l.google.com. 5" - - "aspmx3.googlemail.com. 10" - - "aspmx2.googlemail.com. 10" - timeout: 10 - thresholdMillis: 1000 - - server: 8.8.8.8 - port: 53 - query: "flanksource.com" - querytype: "TXT" - minrecords: 1 - exactreply: ["google-site-verification=IIE1aJuvqseLUKSXSIhu2O2lgdU_d8csfJjjIQVc-q0"] - timeout: 10 - thresholdMillis: 1000 - - server: 8.8.8.8 - port: 53 - query: "flanksource.com" - querytype: "NS" - minrecords: 1 - exactreply: - - "ns-91.awsdns-11.com." - - "ns-908.awsdns-49.net." - - "ns-1450.awsdns-53.org." - - "ns-1896.awsdns-45.co.uk." - timeout: 10 - thresholdMillis: 1000 - # - server: 8.8.8.8 - # port: 53 - # querytype: "SRV" - # query: "_test._tcp.test" - # timeout: 10 - # srvReply: - # target: "" - # port: 0 - # priority: 0 - # weight: 0* - - ``` - -| Field | Description | Scheme | Required | -| ----- | ----------- | ------ | -------- | -| description | Description for the check | string | | -| exactreply | | \[\]string | | -| icon | Icon for overwriting default icon on the dashboard | string | | -| minrecords | | int | | -| name | Name of the check | string | | -| port | | int | | -| query | | string | | -| querytype | | string | | -| **server** | | string | Yes | -| thresholdMillis | | int | | -| timeout | | int | | - - -## DockerPull - -??? example - ```yaml - apiVersion: canaries.flanksource.com/v1 - kind: Canary - metadata: - name: docker-pass - spec: - interval: 30 - docker: - - image: docker.io/library/busybox:1.31.1@sha256:b20c55f6bfac8828690ec2f4e2da29790c80aa3d7801a119f0ea6b045d2d2da1 - expectedDigest: sha256:b20c55f6bfac8828690ec2f4e2da29790c80aa3d7801a119f0ea6b045d2d2da1 - - ``` - -| Field | Description | Scheme | Required | -| ----- | ----------- | ------ | -------- | -| auth | | *[Authentication](#authentication) | | -| description | Description for the check | string | | -| **expectedDigest** | | string | Yes | -| **expectedSize** | | int64 | Yes | -| icon | Icon for overwriting default icon on the dashboard | string | | -| **image** | | string | Yes | -| name | Name of the check | string | | - - -## DockerPush - -DockerPush check will try to push a Docker image to specified registry. -/* -??? example - ```yaml - apiVersion: canaries.flanksource.com/v1 - kind: Canary - metadata: - name: docker-push0-pass - spec: - interval: 30 - dockerPush: - - image: ttl.sh/flanksource-busybox:1.30 - auth: - username: - value: test - password: - value: pass - - ``` - -| Field | Description | Scheme | Required | -| ----- | ----------- | ------ | -------- | -| auth | | *[Authentication](#authentication) | | -| description | Description for the check | string | | -| icon | Icon for overwriting default icon on the dashboard | string | | -| **image** | | string | Yes | -| name | Name of the check | string | | - - -## EC2 - -??? example - ```yaml - apiVersion: canaries.flanksource.com/v1 - kind: Canary - metadata: - name: ec2-pass - spec: - interval: 30 - spec: - ec2: - - description: test instance - accessKeyID: - valueFrom: - secretKeyRef: - name: aws-credentials - key: AWS_ACCESS_KEY_ID - secretKey: - valueFrom: - secretKeyRef: - name: aws-credentials - key: AWS_SECRET_ACCESS_KEY - region: af-south-1 - userData: | - #!/bin/bash - yum install -y httpd - systemctl start httpd - systemctl enable httpd - usermod -a -G apache ec2-user - chown -R ec2-user:apache /var/www - chmod 2775 /var/www - find /var/www -type d -exec chmod 2775 {} \; - find /var/www -type f -exec chmod 0664 {} \; - securityGroup: WebAccess - - ``` - -| Field | Description | Scheme | Required | -| ----- | ----------- | ------ | -------- | -| **accessKey** | | [kommons.EnvVar](https://pkg.go.dev/github.com/flanksource/kommons#EnvVar) | Yes | -| ami | | string | | -| canaryRef | | \[\][v1.LocalObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.20/#localobjectreference-v1-core) | | -| description | Description for the check | string | | -| endpoint | | string | | -| icon | Icon for overwriting default icon on the dashboard | string | | -| keepAlive | | bool | | -| name | Name of the check | string | | -| region | | string | | -| **secretKey** | | [kommons.EnvVar](https://pkg.go.dev/github.com/flanksource/kommons#EnvVar) | Yes | -| securityGroup | | string | | -| skipTLSVerify | Skip TLS verify when connecting to aws | bool | | -| timeOut | | int | | -| userData | | string | | -| waitTime | | int | | - - -## GCSBucket - -??? example - ```yaml - - ``` - -| Field | Description | Scheme | Required | -| ----- | ----------- | ------ | -------- | -| **bucket** | | string | Yes | -| **credentials** | | *[kommons.EnvVar](https://pkg.go.dev/github.com/flanksource/kommons#EnvVar) | Yes | -| description | Description for the check | string | | -| display | | [Template](#template) | | -| **endpoint** | | string | Yes | -| filter | | [FolderFilter](#folderfilter) | | -| icon | Icon for overwriting default icon on the dashboard | string | | -| maxAge | MaxAge the latest object should be younger than defined age | Duration | | -| maxCount | MinCount the minimum number of files inside the searchPath | *int | | -| maxSize | MaxSize of the files inside the searchPath | Size | | -| minAge | MinAge the latest object should be older than defined age | Duration | | -| minCount | MinCount the minimum number of files inside the searchPath | *int | | -| minSize | MinSize of the files inside the searchPath | Size | | -| name | Name of the check | string | | -| test | | [Template](#template) | | - - -## HTTP - -??? example - ```yaml - apiVersion: canaries.flanksource.com/v1 - kind: Canary - metadata: - name: http-pass - spec: - interval: 30 - http: - - endpoint: http://status.savanttools.com/?code=200 - thresholdMillis: 3000 - responseCodes: [201, 200, 301] - responseContent: "" - maxSSLExpiry: 7 - - endpoint: http://status.savanttools.com/?code=404 - thresholdMillis: 3000 - responseCodes: [404] - responseContent: "" - maxSSLExpiry: 7 - - endpoint: http://status.savanttools.com/?code=500 - thresholdMillis: 3000 - responseCodes: [500] - responseContent: "" - maxSSLExpiry: 7 - - ``` - -| Field | Description | Scheme | Required | -| ----- | ----------- | ------ | -------- | -| authentication | Credentials for authentication headers | *[Authentication](#authentication) | | -| body | Request Body Contents | string | | -| description | Description for the check | string | | -| display | | [Template](#template) | | -| **endpoint** | HTTP endpoint to check. Mutually exclusive with Namespace | string | Yes | -| headers | Header fields to be used in the query | \[\][kommons.EnvVar](https://pkg.go.dev/github.com/flanksource/kommons#EnvVar) | | -| icon | Icon for overwriting default icon on the dashboard | string | | -| maxSSLExpiry | Maximum number of days until the SSL Certificate expires. | int | | -| method | Method to use - defaults to GET | string | | -| name | Name of the check | string | | -| namespace | Namespace to crawl for TLS endpoints. Mutually exclusive with Endpoint | string | | -| ntlm | NTLM when set to true will do authentication using NTLM v1 protocol | bool | | -| ntlmv2 | NTLM when set to true will do authentication using NTLM v2 protocol | bool | | -| responseCodes | Expected response codes for the HTTP Request. | \[\]int | | -| responseContent | Exact response content expected to be returned by the endpoint. | string | | -| responseJSONContent | Path and value to of expect JSON response by the endpoint | [JSONCheck](#jsoncheck) | | -| test | | [Template](#template) | | -| thresholdMillis | Maximum duration in milliseconds for the HTTP request. It will fail the check if it takes longer. | int | | - - -## Helm - -??? example - ```yaml - apiVersion: canaries.flanksource.com/v1 - kind: Canary - metadata: - name: helm-pass - spec: - interval: 30 - helm: - - chartmuseum: http://chartmuseum.default:8080 - project: library - auth: - username: - value: admin - password: - value: passwd - - ``` - -| Field | Description | Scheme | Required | -| ----- | ----------- | ------ | -------- | -| auth | | *[Authentication](#authentication) | | -| cafile | | string | | -| **chartmuseum** | | string | Yes | -| description | Description for the check | string | | -| icon | Icon for overwriting default icon on the dashboard | string | | -| name | Name of the check | string | | -| project | | string | | - - -## ICMP - -This test will check ICMP packet loss and duration. - -??? example - ```yaml - apiVersion: canaries.flanksource.com/v1 - kind: Canary - metadata: - name: icmp - spec: - interval: 30 - icmp: - - endpoint: https://api.github.com - thresholdMillis: 600 - packetLossThreshold: 10 - packetCount: 2 - - ``` - -| Field | Description | Scheme | Required | -| ----- | ----------- | ------ | -------- | -| description | Description for the check | string | | -| **endpoint** | | string | Yes | -| icon | Icon for overwriting default icon on the dashboard | string | | -| name | Name of the check | string | | -| packetCount | | int | | -| packetLossThreshold | | int64 | | -| thresholdMillis | | int64 | | - - -## Jmeter - -Jmeter check will run jmeter cli against the supplied host -??? example - ```yaml - - ``` - -| Field | Description | Scheme | Required | -| ----- | ----------- | ------ | -------- | -| description | Description for the check | string | | -| host | Host is the server against which test plan needs to be executed | string | | -| icon | Icon for overwriting default icon on the dashboard | string | | -| **jmx** | Jmx defines tge ConfigMap or Secret reference to get the JMX test plan | [kommons.EnvVar](https://pkg.go.dev/github.com/flanksource/kommons#EnvVar) | Yes | -| name | Name of the check | string | | -| port | Port on which the server is running | int32 | | -| properties | Properties defines the local Jmeter properties | \[\]string | | -| responseDuration | ResponseDuration under which the all the test should pass | string | | -| systemProperties | SystemProperties defines the java system property | \[\]string | | - - -## Junit - -Junit check will wait for the given pod to be completed than parses all the xml files present in the defined testResults directory - -??? example - ```yaml - apiVersion: canaries.flanksource.com/v1 - kind: Canary - metadata: - name: junit-pass - annotations: - trace: "true" - spec: - interval: 120 - owner: DBAdmin - severity: high - junit: - - testResults: "/tmp/junit-results/" - display: - template: | - ✅ {{.results.passed}} ❌ {{.results.failed}} in 🕑 {{.results.duration}} - {{ range $r := .results.suites}} - {{- if gt (conv.ToInt $r.failed) 0 }} - {{$r.name}} ✅ {{$r.passed}} ❌ {{$r.failed}} in 🕑 {{$r.duration}} - {{- end }} - {{- end }} - spec: - containers: - - name: jes - image: docker.io/tarun18/junit-test-pass - command: ["/start.sh"] - - ``` - -| Field | Description | Scheme | Required | -| ----- | ----------- | ------ | -------- | -| description | Description for the check | string | | -| display | | [Template](#template) | | -| icon | Icon for overwriting default icon on the dashboard | string | | -| name | Name of the check | string | | -| **spec** | | [v1.PodSpec](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.20/#podspec-v1-core) | Yes | -| test | | [Template](#template) | | -| **testResults** | | string | Yes | -| timeout | Timeout in minutes to wait for specified container to finish its job. Defaults to 5 minutes | int | | - - -## LDAP - -The LDAP check will: - -* bind using provided user/password to the ldap host. Supports ldap/ldaps protocols. -* search an object type in the provided bind DN.s - -??? example - ```yaml - apiVersion: canaries.flanksource.com/v1 - kind: Canary - metadata: - name: ldap-pass - spec: - interval: 30 - ldap: - - host: ldap://apacheds.ldap.svc:10389 - auth: - username: - value: uid=admin,ou=system - password: - value: secret - bindDN: ou=users,dc=example,dc=com - userSearch: "(&(objectClass=organizationalPerson))" - - host: ldap://apacheds.ldap.svc:10389 - auth: - username: - value: uid=admin,ou=system - password: - value: secret - bindDN: ou=groups,dc=example,dc=com - userSearch: "(&(objectClass=groupOfNames))" - - ``` - -| Field | Description | Scheme | Required | -| ----- | ----------- | ------ | -------- | -| **auth** | | *[Authentication](#authentication) | Yes | -| **bindDN** | | string | Yes | -| description | Description for the check | string | | -| **host** | | string | Yes | -| icon | Icon for overwriting default icon on the dashboard | string | | -| name | Name of the check | string | | -| skipTLSVerify | | bool | | -| userSearch | | string | | - - -## Mongo - -??? example - ```yaml - apiVersion: canaries.flanksource.com/v1 - kind: Canary - metadata: - name: mongo - spec: - interval: 30 - mongodb: - - connection: mongodb://$(username):$(password)@mongo.default.svc:27017/?authSource=admin - description: mongo ping - auth: - username: - value: mongoadmin - password: - value: secret - dns: - - query: mongo.default.svc - - ``` - -| Field | Description | Scheme | Required | -| ----- | ----------- | ------ | -------- | -| auth | | [Authentication](#authentication) | | -| **connection** | | string | Yes | -| description | Description for the check | string | | -| icon | Icon for overwriting default icon on the dashboard | string | | -| name | Name of the check | string | | - - -## MsSQL - -This check will try to connect to a specified MsSQL database, run a query against it and verify the results. - -??? example - ```yaml - apiVersion: canaries.flanksource.com/v1 - kind: Canary - metadata: - name: mssql-pass - spec: - interval: 30 - mssql: - - connection: "server=mssql.default.svc;user id=$(username);password=$(password);port=1433;database=master" - auth: - username: - value: sa - password: - value: S0m3p@sswd - query: "SELECT 1" - results: 1 - - ``` - -| Field | Description | Scheme | Required | -| ----- | ----------- | ------ | -------- | -| auth | | [Authentication](#authentication) | | -| **connection** | | string | Yes | -| description | Description for the check | string | | -| display | | [Template](#template) | | -| icon | Icon for overwriting default icon on the dashboard | string | | -| name | Name of the check | string | | -| **query** | | string | Yes | -| **results** | Number rows to check for | int | Yes | -| test | | [Template](#template) | | - - -## Namespace - -The Namespace check will: - -* create a new namespace using the labels/annotations provided - -??? example - ```yaml - apiVersion: canaries.flanksource.com/v1 - kind: Canary - metadata: - name: namespace-pass - spec: - interval: 30 - namespace: - - checkName: check - namespaceNamePrefix: "test-foo-" - podSpec: | - apiVersion: v1 - kind: Pod - metadata: - name: test-namespace - namespace: default - labels: - app: hello-world-golang - spec: - containers: - - name: hello - image: quay.io/toni0/hello-webserver-golang:latest - port: 8080 - path: /foo/bar - ingressName: test-namespace-pod - ingressHost: "test-namespace-pod.127.0.0.1.nip.io" - readyTimeout: 5000 - httpTimeout: 15000 - deleteTimeout: 12000 - ingressTimeout: 20000 - deadline: 29000 - httpRetryInterval: 200 - expectedContent: bar - expectedHttpStatuses: [200, 201, 202] - - ``` - -| Field | Description | Scheme | Required | -| ----- | ----------- | ------ | -------- | -| **checkName** | | string | Yes | -| deadline | | int64 | | -| deleteTimeout | | int64 | | -| description | Description for the check | string | | -| expectedContent | | string | | -| expectedHttpStatuses | | \[\]int64 | | -| httpRetryInterval | | int64 | | -| httpTimeout | | int64 | | -| icon | Icon for overwriting default icon on the dashboard | string | | -| ingressHost | | string | | -| ingressName | | string | | -| ingressTimeout | | int64 | | -| name | Name of the check | string | | -| namespaceAnnotations | | map[string]string | | -| namespaceLabels | | map[string]string | | -| namespaceNamePrefix | | string | | -| path | | string | | -| **podSpec** | | string | Yes | -| port | | int64 | | -| priorityClass | | string | | -| readyTimeout | | int64 | | -| scheduleTimeout | | int64 | | - - -## Pod - -??? example - ```yaml - apiVersion: canaries.flanksource.com/v1 - kind: Canary - metadata: - name: pod-pass - spec: - interval: 30 - pod: - - name: golang - namespace: default - spec: | - apiVersion: v1 - kind: Pod - metadata: - name: hello-world-golang - namespace: default - labels: - app: hello-world-golang - spec: - containers: - - name: hello - image: quay.io/toni0/hello-webserver-golang:latest - port: 8080 - path: /foo/bar - ingressName: hello-world-golang - ingressHost: "hello-world-golang.127.0.0.1.nip.io" - scheduleTimeout: 20000 - readyTimeout: 10000 - httpTimeout: 7000 - deleteTimeout: 12000 - ingressTimeout: 10000 - deadline: 60000 - httpRetryInterval: 200 - expectedContent: bar - expectedHttpStatuses: [200, 201, 202] - priorityClass: canary-checker-priority - - name: ruby - namespace: default - spec: | - apiVersion: v1 - kind: Pod - metadata: - name: hello-world-ruby - namespace: default - labels: - app: hello-world-ruby - spec: - containers: - - name: hello - image: quay.io/toni0/hello-webserver-ruby:latest - imagePullPolicy: Always - port: 8080 - path: /foo/bar - ingressName: hello-world-ruby - ingressHost: "hello-world-ruby.127.0.0.1.nip.io" - scheduleTimeout: 30000 - readyTimeout: 12000 - httpTimeout: 7000 - deleteTimeout: 12000 - ingressTimeout: 10000 - deadline: 29000 - httpRetryInterval: 200 - expectedContent: hello, you've hit /foo/bar - expectedHttpStatuses: [200, 201, 202] - - ``` - -| Field | Description | Scheme | Required | -| ----- | ----------- | ------ | -------- | -| deadline | | int64 | | -| deleteTimeout | | int64 | | -| description | Description for the check | string | | -| expectedContent | | string | | -| expectedHttpStatuses | | \[\]int | | -| httpRetryInterval | | int64 | | -| httpTimeout | | int64 | | -| icon | Icon for overwriting default icon on the dashboard | string | | -| **ingressHost** | | string | Yes | -| **ingressName** | | string | Yes | -| ingressTimeout | | int64 | | -| name | Name of the check | string | | -| **namespace** | | string | Yes | -| path | | string | | -| port | | int64 | | -| priorityClass | | string | | -| readyTimeout | | int64 | | -| scheduleTimeout | | int64 | | -| **spec** | | string | Yes | - - -## Postgres - -This check will try to connect to a specified Postgresql database, run a query against it and verify the results. - -??? example - ```yaml - apiVersion: canaries.flanksource.com/v1 - kind: Canary - metadata: - name: postgres-succeed - spec: - interval: 30 - postgres: - - connection: "postgres://$(username):$(password)@postgres.default.svc:5432/postgres?sslmode=disable" - auth: - username: - value: postgresadmin - password: - value: admin123 - query: SELECT current_schemas(true) - display: - template: | - {{- range $r := .results.rows }} - {{- $r.current_schemas}} - {{- end}} - results: 1 - - ``` - -| Field | Description | Scheme | Required | -| ----- | ----------- | ------ | -------- | -| auth | | [Authentication](#authentication) | | -| **connection** | | string | Yes | -| description | Description for the check | string | | -| display | | [Template](#template) | | -| icon | Icon for overwriting default icon on the dashboard | string | | -| name | Name of the check | string | | -| **query** | | string | Yes | -| **results** | Number rows to check for | int | Yes | -| test | | [Template](#template) | | - - -## Prometheus - -??? example - ```yaml - apiVersion: canaries.flanksource.com/v1 - kind: Canary - metadata: - name: prometheus - spec: - interval: 30 - prometheus: - - host: http://prometheus-k8s.monitoring.svc:9090 - query: kubernetes_build_info{job!~"kube-dns|coredns"} - display: - template: "{{ (index .results 0).git_version }}" - test: - template: "true" - - ``` - -| Field | Description | Scheme | Required | -| ----- | ----------- | ------ | -------- | -| description | Description for the check | string | | -| display | | [Template](#template) | | -| **host** | Address of the prometheus server | string | Yes | -| icon | Icon for overwriting default icon on the dashboard | string | | -| name | Name of the check | string | | -| **query** | PromQL query | string | Yes | -| test | | [Template](#template) | | - - -## Redis - - - -| Field | Description | Scheme | Required | -| ----- | ----------- | ------ | -------- | -| **addr** | | string | Yes | -| auth | | *[Authentication](#authentication) | | -| **db** | | int | Yes | -| description | Description for the check | string | | -| icon | Icon for overwriting default icon on the dashboard | string | | -| name | Name of the check | string | | - - -## Restic - - - -| Field | Description | Scheme | Required | -| ----- | ----------- | ------ | -------- | -| accessKey | AccessKey access key id for connection with aws s3, minio, wasabi, alibaba oss | *[kommons.EnvVar](https://pkg.go.dev/github.com/flanksource/kommons#EnvVar) | | -| caCert | CaCert path to the root cert. In case of self-signed certificates | string | | -| checkIntegrity | CheckIntegrity when enabled will check the Integrity and consistency of the restic reposiotry | bool | | -| description | Description for the check | string | | -| icon | Icon for overwriting default icon on the dashboard | string | | -| **maxAge** | MaxAge for backup freshness | string | Yes | -| name | Name of the check | string | | -| **password** | Password for the restic repository | *[kommons.EnvVar](https://pkg.go.dev/github.com/flanksource/kommons#EnvVar) | Yes | -| **repository** | Repository The restic repository path eg: rest:https://user:pass@host:8000/ or rest:https://host:8000/ or s3:s3.amazonaws.com/bucket_name | string | Yes | -| secretKey | SecretKey secret access key for connection with aws s3, minio, wasabi, alibaba oss | *[kommons.EnvVar](https://pkg.go.dev/github.com/flanksource/kommons#EnvVar) | | - - -## S3 - -S3 check will: - -* list objects in the bucket to check for Read permissions -* PUT an object into the bucket for Write permissions -* download previous uploaded object to check for Get permissions - -??? example - ```yaml - apiVersion: canaries.flanksource.com/v1 - kind: Canary - metadata: - name: s3-bucket-pass - annotations: - trace: "false" - spec: - interval: 30 - s3Bucket: - # Check for any backup not older than 7 days and min size 25 bytes - - bucket: flanksource-public - region: eu-central-1 - minSize: 50M - maxAge: 10d - filter: - regex: .*.ova - minSize: 100M - # maxAge: 18760h - display: - template: | - {{- range $f := .results.Files }} - {{- if gt $f.Size 0 }} - Name: {{$f.Name}} {{$f.ModTime | humanizeTime }} {{ $f.Size | humanizeBytes}} - {{- end}} - {{- end }} - - ``` - -| Field | Description | Scheme | Required | -| ----- | ----------- | ------ | -------- | -| **accessKey** | | string | Yes | -| **bucket** | | [Bucket](#bucket) | Yes | -| description | Description for the check | string | | -| icon | Icon for overwriting default icon on the dashboard | string | | -| name | Name of the check | string | | -| **objectPath** | | string | Yes | -| **secretKey** | | string | Yes | -| skipTLSVerify | Skip TLS verify when connecting to s3 | bool | | - - -## S3Bucket - -This check will - -- search objects matching the provided object path pattern -- check that latest object is no older than provided MaxAge value in seconds -- check that latest object size is not smaller than provided MinSize value in bytes. - -??? example - ```yaml - apiVersion: canaries.flanksource.com/v1 - kind: Canary - metadata: - name: s3-bucket-pass - spec: - interval: 30 - s3Bucket: - # Check for any backup not older than 7 days and min size 25 bytes - - bucket: tests-e2e-1 - accessKey: - valueFrom: - secretKeyRef: - name: aws-credentials - key: AWS_ACCESS_KEY_ID - secretKey: - valueFrom: - secretKeyRef: - name: aws-credentials - key: AWS_SECRET_ACCESS_KEY - region: "minio" - endpoint: "http://minio.minio:9000" - filter: - regex: "(.*)backup.zip$" - maxAge: 7d - minSize: 25b - usePathStyle: true - skipTLSVerify: true - # Check for any mysql backup not older than 7 days and min size 25 bytes - - bucket: tests-e2e-1 - accessKey: - valueFrom: - secretKeyRef: - name: aws-credentials - key: AWS_ACCESS_KEY_ID - secretKey: - valueFrom: - secretKeyRef: - name: aws-credentials - key: AWS_SECRET_ACCESS_KEY - region: "minio" - endpoint: "http://minio.minio:9000" - filter: - regex: "mysql\\/backups\\/(.*)\\/mysql.zip$" - maxAge: 7d - minSize: 25b - usePathStyle: true - skipTLSVerify: true - # Check for any pg backup not older than 7 days and min size 50 bytes - - bucket: tests-e2e-1 - accessKey: - valueFrom: - secretKeyRef: - name: aws-credentials - key: AWS_ACCESS_KEY_ID - secretKey: - valueFrom: - secretKeyRef: - name: aws-credentials - key: AWS_SECRET_ACCESS_KEY - region: "minio" - endpoint: "http://minio.minio:9000" - filter: - regex: "pg\\/backups\\/(.*)\\/backup.zip$" - maxAge: 7d - minSize: 25b - usePathStyle: true - skipTLSVerify: true - - ``` - -| Field | Description | Scheme | Required | -| ----- | ----------- | ------ | -------- | -| **accessKey** | | [kommons.EnvVar](https://pkg.go.dev/github.com/flanksource/kommons#EnvVar) | Yes | -| **bucket** | | string | Yes | -| description | Description for the check | string | | -| display | | [Template](#template) | | -| endpoint | | string | | -| filter | | [FolderFilter](#folderfilter) | | -| icon | Icon for overwriting default icon on the dashboard | string | | -| maxAge | MaxAge the latest object should be younger than defined age | Duration | | -| maxCount | MinCount the minimum number of files inside the searchPath | *int | | -| maxSize | MaxSize of the files inside the searchPath | Size | | -| minAge | MinAge the latest object should be older than defined age | Duration | | -| minCount | MinCount the minimum number of files inside the searchPath | *int | | -| minSize | MinSize of the files inside the searchPath | Size | | -| name | Name of the check | string | | -| objectPath | glob path to restrict matches to a subset | string | | -| region | | string | | -| **secretKey** | | [kommons.EnvVar](https://pkg.go.dev/github.com/flanksource/kommons#EnvVar) | Yes | -| skipTLSVerify | Skip TLS verify when connecting to aws | bool | | -| test | | [Template](#template) | | -| usePathStyle | Use path style path: http://s3.amazonaws.com/BUCKET/KEY instead of http://BUCKET.s3.amazonaws.com/KEY | bool | | - - -## Smb - -Smb check will connect to the given samba server with given credentials -find the age of the latest updated file and compare it with minAge -count the number of file present and compare with minCount if defined - -??? example - ```yaml - - ``` - -| Field | Description | Scheme | Required | -| ----- | ----------- | ------ | -------- | -| **auth** | | *[Authentication](#authentication) | Yes | -| description | Description for the check | string | | -| display | | [Template](#template) | | -| domain | Domain... | string | | -| filter | | [FolderFilter](#folderfilter) | | -| icon | Icon for overwriting default icon on the dashboard | string | | -| maxAge | MaxAge the latest object should be younger than defined age | Duration | | -| maxCount | MinCount the minimum number of files inside the searchPath | *int | | -| maxSize | MaxSize of the files inside the searchPath | Size | | -| minAge | MinAge the latest object should be older than defined age | Duration | | -| minCount | MinCount the minimum number of files inside the searchPath | *int | | -| minSize | MinSize of the files inside the searchPath | Size | | -| name | Name of the check | string | | -| port | Port on which smb server is running. Defaults to 445 | int | | -| searchPath | SearchPath sub-path inside the mount location | string | | -| **server** | Server location of smb server. Can be `hostname/ip` or in `\\server\e$\a\b\c` syntax -Where server is the `hostname` `e$`` is the sharename and `a/b/c` is the searchPath location | string | Yes | -| sharename | Sharename to mount from the samba server | string | | -| test | | [Template](#template) | | -| workstation | Workstation... | string | | - - -## Template - - - -| Field | Description | Scheme | Required | -| ----- | ----------- | ------ | -------- | -| jsonPath | | string | | -| template | | string | | - - -## Connection - - - -| Field | Description | Scheme | Required | -| ----- | ----------- | ------ | -------- | -| auth | | [Authentication](#authentication) | | -| **connection** | | string | Yes | - - -## AWSConnection - - - -| Field | Description | Scheme | Required | -| ----- | ----------- | ------ | -------- | -| **accessKey** | | [kommons.EnvVar](https://pkg.go.dev/github.com/flanksource/kommons#EnvVar) | Yes | -| endpoint | | string | | -| region | | string | | -| **secretKey** | | [kommons.EnvVar](https://pkg.go.dev/github.com/flanksource/kommons#EnvVar) | Yes | -| skipTLSVerify | Skip TLS verify when connecting to aws | bool | | - - -## Bucket - - - -| Field | Description | Scheme | Required | -| ----- | ----------- | ------ | -------- | -| **endpoint** | | string | Yes | -| **name** | | string | Yes | -| **region** | | string | Yes | - - -## FolderFilter - - - -| Field | Description | Scheme | Required | -| ----- | ----------- | ------ | -------- | -| maxAge | | Duration | | -| maxSize | | Size | | -| minAge | | Duration | | -| minSize | | Size | | -| regex | | string | | - - -## GCPConnection - - - -| Field | Description | Scheme | Required | -| ----- | ----------- | ------ | -------- | -| **credentials** | | *[kommons.EnvVar](https://pkg.go.dev/github.com/flanksource/kommons#EnvVar) | Yes | -| **endpoint** | | string | Yes | - - -## Authentication - - - -| Field | Description | Scheme | Required | -| ----- | ----------- | ------ | -------- | -| **password** | | [kommons.EnvVar](https://pkg.go.dev/github.com/flanksource/kommons#EnvVar) | Yes | -| **username** | | [kommons.EnvVar](https://pkg.go.dev/github.com/flanksource/kommons#EnvVar) | Yes | - - -## Display - - - -| Field | Description | Scheme | Required | -| ----- | ----------- | ------ | -------- | - - -## VarSource - -VarSource represents a source for a value - -| Field | Description | Scheme | Required | -| ----- | ----------- | ------ | -------- | -| **ConfigMapKeyRef** | Selects a key of a ConfigMap. | *corev1.ConfigMapKeySelector | Yes | -| **FieldRef** | Selects a field of the pod: supports metadata.name, metadata.namespace, metadata.labels, metadata.annotations, -spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. | *corev1.ObjectFieldSelector | Yes | -| **SecretKeyRef** | Selects a key of a secret in the pod's namespace | *corev1.SecretKeySelector | Yes | -| **Value** | | string | Yes | - - -## CloudWatchFilter - - - -| Field | Description | Scheme | Required | -| ----- | ----------- | ------ | -------- | -| actionPrefix | | *string | | -| alarmPrefix | | *string | | -| alarms | | \[\]string | | -| state | | string | | - diff --git a/docs/canary-checker.png b/docs/canary-checker.png deleted file mode 100644 index 85cae7f3d..000000000 Binary files a/docs/canary-checker.png and /dev/null differ diff --git a/docs/dev-guide.md b/docs/dev-guide.md deleted file mode 100644 index 026c79297..000000000 --- a/docs/dev-guide.md +++ /dev/null @@ -1,68 +0,0 @@ -# Dev Guide - -The guide provides steps to configure your local setup with running canary-checker. - -## Set up a Kubernetes Cluster - -Before proceeding one must have access to a functioning Kubernetes cluster. - -In this guide we'll be working with [kind](https://kind.sigs.k8s.io/). - -### Create a cluster - -- Install latest version of [kind](https://kind.sigs.k8s.io/docs/user/quick-start/#installation). -- Create the cluster with `kind create cluster --name `. - -### Install Metrics Server and Prometheus - -For installing and configuring metrics server and prometheus please see the [prereqs](prereqs.md). - -## Install Node - -The built-in dashboard of canary-checker uses node v12. Developers will need to install the compatible version: -- Install [nvm](https://github.com/nvm-sh/nvm) to install and manage different versions of node. -- After nvm is installed one can install node v12 by running `nvm install v12`. - -## Build the canary-checker binary - -**Note**: The following commands needs to be run from the root of canary-checker repo. - -For most development work, it makes sense to build the binary and run the operator directly, rather than building and running a container image. With this in mind, this is how we can build and use the binary: -- Based on your current distro build the binaries: `make linux|darwin-arm64|darwin-amd64|windows` -- After building the binary one needs to apply the canary-checker CRD inside the cluster: `kubectl apply -f config/deploy/crd.yaml` -- Once the CRDs are present in the cluster one can start the operator using the binary by: `./.bin/canary-checker-amd64 operator` - -The above command will also start the canary-dashboard on `0.0.0.0:8080`. - -Now you can deploy the canary-checks in any namespace of the cluster and they'll be reconciled by the operator. - -You can test if your operator is working correctly by deploying a sample Canary (by `kubectl` applying the following template): - -```yaml -cat < - - diff --git a/docs/images/cc-white.svg b/docs/images/cc-white.svg deleted file mode 100644 index e07c1a3b2..000000000 --- a/docs/images/cc-white.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/docs/images/dashboard-http-pass-canary.png b/docs/images/dashboard-http-pass-canary.png deleted file mode 100644 index 68a9529e3..000000000 Binary files a/docs/images/dashboard-http-pass-canary.png and /dev/null differ diff --git a/docs/images/ui01.png b/docs/images/ui01.png deleted file mode 100644 index 041b915e8..000000000 Binary files a/docs/images/ui01.png and /dev/null differ diff --git a/docs/index.md b/docs/index.md deleted file mode 120000 index 32d46ee88..000000000 --- a/docs/index.md +++ /dev/null @@ -1 +0,0 @@ -../README.md \ No newline at end of file diff --git a/docs/installation.md b/docs/installation.md deleted file mode 100644 index 5776abdc6..000000000 --- a/docs/installation.md +++ /dev/null @@ -1,33 +0,0 @@ -# Installation - - -=== "Linux" - ```bash - wget https://github.com/flanksource/canary-checker/releases/latest/download/canary-checker \ - -O /usr/bin/canary-checker && \ - chmod +x /usr/bin/canary-checker - ``` - -=== "MacOSX" - ```bash - wget https://github.com/flanksource/canary-checker/releases/latest/download/canary-checker_osx \ - -O /usr/local/bin/canary-checker && \ - chmod +x /usr/local/bin/canary-checker - ``` - -=== "Windows" - ```bash - wget -nv -nc -O https://github.com/flanksource/canary-checker/releases/latest/download/canary-checker.exe - ``` - -## Windows Service - -Canary Checker can be installed as a service in Windows environment using the `install-service.ps1` which is available at the root of the repo. -The script accepts the following parameters to define the service. - -- configfile: Path to the config file with canaries. Defaults to "$pwd\canary-checker.yaml" -- httpPort: port to start the server on. -- metricsPort: port to expose the metrics on -- name: name of the server -- uninstall: A switch flag. Used to uninstall the service. For example: `.\install-service.ps1 -uninstall` -- pushServers: A comma separated list of servers to push the check data diff --git a/docs/introduction.md b/docs/introduction.md deleted file mode 100644 index 6df5a281e..000000000 --- a/docs/introduction.md +++ /dev/null @@ -1,31 +0,0 @@ -# Introduction - -Canary Checker is a Kubernetes native [Synthetic Monitoring](https://en.wikipedia.org/wiki/Synthetic_monitoring) system. It works with standard Kubernetes monitoring tools like [Prometheus](https://prometheus.io) to proactively monitor your applications across multi-tenant environments to ensure application availability. - -Today many applications are written as microservices with service dependencies. This is especially true for applications that run on Kubernetes. For example, you may have a microservice running as a deployment that requires access to a database like [MongoDB](https://www.mongodb.com/kubernetes) or [Postgres](https://www.postgresql.org/). As an [SRE](https://en.wikipedia.org/wiki/Site_Reliability_Engineering) you can create a few canary checks that alert you if the system were about to experience any major issues: - -* You could create a check that ensures the PostgreSQL service responds within `3000` milliseconds -* You could create a check that ensures you can run a query on Postgres and ensure the query result is as expected. - -If any one of these checks fails, (e.g: the service doesn't respond after 3000 milliseconds) you would know that something is not performing as expected in your environment. You could then take actions to remediate the issues before your end users are even aware there was an issue. - -## Features - -![dashboard](images/ui01.png) - -* Built-in UI/Dashboard with multi-cluster aggregation -* CRD based configuration and status reporting -* Prometheus Integration -* Runnable as a CLI for once-off checks or as a standalone server outside kubernetes -* Many built-in check types - - -## Comparisons - - -| App | Comparison | -| ------------------------------------------------------- | ------------------------------------------------------------ | -| Prometheus | canary-checker is not a replacement for prometheus, rather a companion. While prometheus provides persistent time series storage, canary-checker only has a small in-memory cache of recent checks. Canary-checker also exposes metrics via `/metrics` that are scraped by prometheus. | -| Grafana | The built-in UI provides a mechanism to display check results across 1 or more instances without a dependency on grafana/prometheus running. The UI will also display long-term graphs of check results by quering prometheus. | -| [Kuberhealthy](https://github.com/Comcast/kuberhealthy) | Very similar goals, but Kuberhealthy relies on external containers to implement checks and does not provide a UI or multi-cluster/instance aggregation. | -| [Cloudprober](https://cloudprober.org/) | Very similar goals, but Cloudprober is designed for very high scale, not multi-tenancy. Only has ICMP,DNS,HTTP,UDP built-in checks. | \ No newline at end of file diff --git a/docs/operator.md b/docs/operator.md deleted file mode 100644 index b36e7788c..000000000 --- a/docs/operator.md +++ /dev/null @@ -1,133 +0,0 @@ ---- -hide: -- toc ---- - -# Installation - -## Helm - -Canary Checker can be deployed to a Kubernetes cluster via Helm. - -```bash -helm repo add flanksource https://flanksource.github.io/charts -helm repo update flanksource -``` - -Create a values file based on -[values.yaml](https://github.com/flanksource/canary-checker/blob/master/chart/values.yaml). -You only need to define things that are different from the defaults listed in -that file. After configuring the values.yaml file, install Canary Checker with - -```bash -helm install --namespace canary-checker -f flanksource/canary-checker -``` - -## Manually - -=== "kubectl" - ```bash - kubectl apply -f https://github.com/flanksource/canary-checker/releases/latest/download/release.yaml - ``` - -=== "kustomize" - `kustomization.yaml` - ```yaml - resources: - - https://raw.githubusercontent.com/flanksource/canary-checker/v0.38.30/config/deploy/base.yaml - - https://raw.githubusercontent.com/flanksource/canary-checker/v0.38.30/config/deploy/crd.yaml - images: - - name: docker.io/flanksource/canary-checker:latest - newTag: v0.38.30 - patchesStrategicMerge: - - |- - apiVersion: networking.k8s.io/v1 - kind: Ingress - metadata: - name: canary-checker - namespace: canary-checker - spec: - tls: - - hosts: - - - rules: - - host: - ``` - - ```bash - kubectl apply -f kustomization.yaml - ``` - -## Karina - -When deploying Canary Checker via -[Karina](https://karina.docs.flanksource.com/), the versions of -Canary Checker and Flanksource UI are specified in `karina.yml`. The configured -persistence will define how Canary Checker stores its database. - -```yaml -canaryChecker: - version: v0.38.194 - uiVersion: v1.0.201 - persistence: - capacity: 20Gi - storageClass: standard -``` - -## Installing without a database - -Canary Checker ships with a database by default, which keeps a history of -checks. If Canary Checker doesn't require persistence, it can be disabled by -setting `db.embedded.persist` to `false` in the values configuration file. - -In Karina-based deployments, the database can be disabled by setting -`canaryChecker.persistence.disabled` to `true` in `karina.yml` (for Karina -versions >= v0.70.0). For versions older than this, the following patch will -achieve the same result: - -```yaml -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: canary-checker - namespace: platform-system -spec: - template: - spec: - volumes: - - name: canarychecker-database - emptyDir: {} - volumeClaimTemplates: null -``` - -# Running Manually - -The operator can also be started manually outside of cluster (it will still need a kubeconfig) using: - -```bash -canary-checker operator [flags] -``` - -### Options - -``` - --dev Run in development mode - --devGuiPort int Port used by a local npm server in development mode (default 3004) - --enable-leader-election Enabling this will ensure there is only one active controller manager - -h, --help help for operator - --httpPort int Port to expose a health dashboard (default 8080) - --include-check string Run matching canaries - useful for debugging - --log-fail Log every failing check (default true) - --log-pass Log every passing check - --maxStatusCheckCount int Maximum number of past checks in the status page (default 5) - --metricsPort int Port to expose a health dashboard (default 8081) - --name string Server name shown in aggregate dashboard (default "local") - -n, --namespace string Watch only specified namespaces, otherwise watch all - --prometheus string URL of the prometheus server that is scraping this instance - --pull-servers strings push check results to multiple canary servers - --push-servers strings push check results to multiple canary servers - --webhookPort int Port for webhooks (default 8082) - --expose-env Expose environment variables for use in all templates. Note this has serious security implications with untrusted canaries - --json-logs Print logs in json format to stderr - -v, --loglevel count Increase logging level -``` diff --git a/docs/prereqs.md b/docs/prereqs.md deleted file mode 100644 index 28ebe7613..000000000 --- a/docs/prereqs.md +++ /dev/null @@ -1,103 +0,0 @@ -# Optional Prerequisites - -Canary Checker can integrate with Prometheous and ships with a few defined promethues service monitors. While not strictly required this guide explains how to install the optional dependencies. - -## A Kubernetes Cluster - -This is pretty obvious, but first [install](https://github.com/flanksource/karina) a kubernetes cluster and ensure you are able to run basic `kubectl` commands to create pods, services, and that cluster DNS is functioning properly. - -## Metrics Server - -For many environments, Prometheus requires the [Kubernetes Metrics Server](https://github.com/kubernetes-sigs/metrics-server) to get metrics from the worker nodes. How this is deployed is slightly different for different Kubernetes environments. [Here is an example of how to install the Metrics Server on AWS EKS](https://docs.aws.amazon.com/eks/latest/userguide/metrics-server.html). If you are using GKE, you can skip this step as Prometheus is already installed using Stack Driver metrics. - -To ensure you are getting metrics run: - -``` -kubectl get --raw /metrics -``` -The command will give display metrics something like this: -```shell -workqueue_work_duration_seconds_bucket{name="open_api_aggregation_controller",le="0.01"} 966 -workqueue_work_duration_seconds_bucket{name="open_api_aggregation_controller",le="0.1"} 966 -workqueue_work_duration_seconds_bucket{name="open_api_aggregation_controller",le="1"} 967 -workqueue_work_duration_seconds_bucket{name="open_api_aggregation_controller",le="10"} 967 -workqueue_work_duration_seconds_bucket{name="open_api_aggregation_controller",le="+Inf"} 967 -workqueue_work_duration_seconds_sum{name="open_api_aggregation_controller"} 0.8046582159999999 -workqueue_work_duration_seconds_count{name="open_api_aggregation_controller"} 967 -workqueue_work_duration_seconds_bucket{name="priority_and_fairness_config_queue",le="1e-08"} 0 -workqueue_work_duration_seconds_bucket{name="priority_and_fairness_config_queue",le="1e-07"} 0 -workqueue_work_duration_seconds_bucket{name="priority_and_fairness_config_queue",le="1e-06"} 0 -workqueue_work_duration_seconds_bucket{name="priority_and_fairness_config_queue",le="9.999999999999999e-06"} 0 -workqueue_work_duration_seconds_bucket{name="priority_and_fairness_config_queue",le="9.999999999999999e-05"} 0 -workqueue_work_duration_seconds_bucket{name="priority_and_fairness_config_queue",le="0.001"} 1 -workqueue_work_duration_seconds_bucket{name="priority_and_fairness_config_queue",le="0.01"} 1 -workqueue_work_duration_seconds_bucket{name="priority_and_fairness_config_queue",le="0.1"} 1 -workqueue_work_duration_seconds_bucket{name="priority_and_fairness_config_queue",le="1"} 1 -workqueue_work_duration_seconds_bucket{name="priority_and_fairness_config_queue",le="10"} 1 -workqueue_work_duration_seconds_bucket{name="priority_and_fairness_config_queue",le="+Inf"} 1 -workqueue_work_duration_seconds_sum{name="priority_and_fairness_config_queue"} 0.000160916 -workqueue_work_duration_seconds_count{name="priority_and_fairness_config_queue"} 1 -``` - - -## Prometheus Operator - -You can install the operator by cloning the [Prometheus Operator](https://github.com/prometheus-operator/kube-prometheus) repository with: - -``` -git clone https://github.com/prometheus-operator/kube-prometheus -``` - -Find the appropriate release for your version of Kubernetes in the table. For example, if you were using Kubernetes 1.17 (run `kubectl version` to see what you are running) you would see the [README](https://github.com/prometheus-operator/kube-prometheus/blob/master/README.md) shows I should be running `release-0.4`. So to install we run: - -``` -cd kube-prometheus -git branch -a -``` -Here we see all the branch names. To switch to the release branch run: - -``` -git checkout remotes/origin/release-0.4 -``` - -Now we can install the operator with: - -``` -kubectl create -f manifests/setup -``` - -You should then be able to see custom resources, `servicemonitors` by running: - -``` -kubectl get crd -``` -And see there is a `servicemonitors.monitoring.coreos.com` custom resource definition. - -Once that is defined you can install the rest of the monitoring components: - -``` -kubectl create -f manifests/ -``` - -You'll be able to see all the resources defined in the `monitoring` namespace with: - -``` -kubectl get pods -n monitoring -``` - -Output looks as follows: - -``` -NAME READY STATUS RESTARTS AGE -alertmanager-main-0 2/2 Running 0 3m15s -alertmanager-main-1 2/2 Running 0 3m15s -alertmanager-main-2 2/2 Running 0 3m15s -grafana-58dc7468d7-vvcnc 1/1 Running 0 3m12s -kube-state-metrics-765c7c7f95-kxddc 3/3 Running 0 3m12s -node-exporter-cnhm6 2/2 Running 0 2m15s -node-exporter-vnh9r 2/2 Running 0 3m13s -prometheus-adapter-5cd5798d96-j8xnn 1/1 Running 0 3m13s -prometheus-k8s-0 3/3 Running 1 3m13s -prometheus-k8s-1 3/3 Running 1 3m13s -prometheus-operator-5f75d76f9f-n9krn 1/1 Running 0 7m2s -``` diff --git a/docs/reference.md b/docs/reference.md deleted file mode 100644 index 454c008e2..000000000 --- a/docs/reference.md +++ /dev/null @@ -1,20 +0,0 @@ -generate documentation - -Usage: - canary-checker docs [command] - -Available Commands: - cli generate CLI documentation - -Flags: - -h, --help help for docs - -Global Flags: - --expose-env Expose environment variables for use in all templates. Note this has serious security implications with untrusted canaries - --json-logs Print logs in json format to stderr - -v, --loglevel count Increase logging level - -Use "canary-checker docs [command] --help" for more information about a command. - -version: dev - \ No newline at end of file diff --git a/docs/run.md b/docs/run.md deleted file mode 100644 index e12fa274e..000000000 --- a/docs/run.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -hide: -- toc ---- - - -# Installation - -=== "Linux (amd64)" - ```bash - wget https://github.com/flanksource/canary-checker/releases/latest/download/canary-checker_linux_amd64 \ - -O /usr/bin/canary-checker && \ - chmod +x /usr/bin/canary-checker - ``` - -=== "MacOSX (amd64)" - ```bash - wget https://github.com/flanksource/canary-checker/releases/latest/download/canary-checker_darwin_amd64 \ - -O /usr/local/bin/canary-checker && \ - chmod +x /usr/local/bin/canary-checker - ``` - -=== "Makefile" - ```Makefile - OS = $(shell uname -s | tr '[:upper:]' '[:lower:]') - ARCH = $(shell uname -m | sed 's/x86_64/amd64/') - wget -nv -nc https://github.com/flanksource/canary-checker/releases/latest/download/canary-checker_$(OS)_$(ARCH) \ - -O /usr/local/bin/canary-checker && \ - chmod +x /usr/local/bin/canary-checker - - ``` -=== "Windows" - ```bash - wget -nv -nc -O https://github.com/flanksource/canary-checker/releases/latest/download/canary-checker.exe - ``` - - - - - -# Running -Execute checks and return - -```bash -canary-checker run [flags] -``` - -### Options - -``` - -h, --help help for run - -j, --junit string Export JUnit XML formatted results to this file e.g: junit.xml - -n, --namespace string Specify namespace - --expose-env Expose environment variables for use in all templates. Note this has serious security implications with untrusted canaries - --json-logs Print logs in json format to stderr - -v, --loglevel count Increase logging level -``` diff --git a/docs/server.md b/docs/server.md deleted file mode 100644 index 2f488eacc..000000000 --- a/docs/server.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -hide: -- toc ---- - - -# Installation - -=== "Linux" - ```bash - wget https://github.com/flanksource/canary-checker/releases/latest/download/canary-checker \ - -O /usr/bin/canary-checker && \ - chmod +x /usr/bin/canary-checker - ``` - -=== "MacOSX" - ```bash - wget https://github.com/flanksource/canary-checker/releases/latest/download/canary-checker_osx \ - -O /usr/local/bin/canary-checker && \ - chmod +x /usr/local/bin/canary-checker - ``` - -=== "Windows" - ```bash - wget -nv -nc -O https://github.com/flanksource/canary-checker/releases/latest/download/canary-checker.exe - ``` - - -# Running -Start a server to execute checks - -``` -canary-checker serve [flags] -``` - -### Options - -``` - -c, --configfile string Specify configfile - --dev Run in development mode - --devGuiPort int Port used by a local npm server in development mode (default 3004) - -h, --help help for serve - --httpPort int Port to expose a health dashboard (default 8080) - --include-check string Run matching canaries - useful for debugging - --log-fail Log every failing check (default true) - --log-pass Log every passing check - --maxStatusCheckCount int Maximum number of past checks in the status page (default 5) - --metricsPort int Port to expose a health dashboard (default 8081) - --name string Server name shown in aggregate dashboard (default "local") - -n, --namespace string Watch only specified namespaces, otherwise watch all - --prometheus string URL of the prometheus server that is scraping this instance - --pull-servers strings push check results to multiple canary servers - --push-servers strings push check results to multiple canary servers - -s, --schedule string schedule to run checks on. Supports all cron expression and golang duration support in format: '@every duration' - --expose-env Expose environment variables for use in all templates. Note this has serious security implications with untrusted canaries - --json-logs Print logs in json format to stderr - -v, --loglevel count Increase logging level -``` diff --git a/docs/swagger.yaml b/docs/swagger.yaml deleted file mode 100644 index 4ff9cca0d..000000000 --- a/docs/swagger.yaml +++ /dev/null @@ -1,296 +0,0 @@ -basePath: / -definitions: - Check: - properties: - canary_id: - type: string - canary_name: - type: string - checkStatuses: - items: - $ref: '#/definitions/CheckStatus' - type: array - createdAt: - type: string - deletedAt: - type: string - description: - type: string - displayType: - type: string - icon: - type: string - id: - type: string - labels: - type: object - lastRuntime: - type: string - latency: - $ref: '#/definitions/Latency' - name: - type: string - namespace: - type: string - nextRuntime: - type: string - owner: - type: string - severity: - type: string - status: - type: string - type: - type: string - updatedAt: - type: string - uptime: - $ref: '#/definitions/Uptime' - type: object - CheckStatus: - properties: - duration: - type: integer - error: - type: string - invalid: - type: boolean - message: - type: string - status: - type: boolean - time: - type: string - type: object - Component: - properties: - checks: - items: - $ref: '#/definitions/Check' - type: array - components: - $ref: '#/definitions/Components' - configs: - items: - $ref: '#/definitions/Config' - type: array - created_at: - type: string - external_id: - description: nolint - type: string - icon: - type: string - id: - description: nolint - type: string - labels: - type: object - lifecycle: - description: The lifecycle state of the component e.g. production, staging, - dev, etc. - type: string - name: - type: string - namespace: - type: string - order: - type: integer - owner: - type: string - parent_id: - description: nolint - type: string - path: - type: string - properties: - items: - $ref: '#/definitions/Property' - type: array - schedule: - type: string - status: - type: string - statusReason: - type: string - summary: - $ref: '#/definitions/Summary' - topology_id: - description: nolint - type: string - text: - type: string - tooltip: - type: string - topology_type: - type: string - type: - description: The type of component, e.g. service, API, website, library, database, - etc. - type: string - updated_at: - type: string - type: object - Components: - items: - $ref: '#/definitions/Component' - type: array - Config: - properties: - config_class: - type: string - external_id: - items: - type: string - type: array - type: - type: string - id: - type: string - name: - type: string - namespace: - type: string - spec: - type: object - type: object - Latency: - properties: - p95: - type: number - p97: - type: number - p99: - type: number - rolling1h: - type: number - type: object - Property: - properties: - color: - type: string - headline: - type: boolean - icon: - type: string - label: - type: string - lastTransition: - type: string - links: - items: - $ref: '#/definitions/Link' - type: array - max: - type: integer - min: - type: integer - name: - type: string - order: - type: integer - status: - type: string - text: - description: Either text or value is required, but not both. - type: string - tooltip: - type: string - type: - type: string - unit: - description: e.g. milliseconds, bytes, millicores, epoch etc. - type: string - value: - type: integer - type: object - Uptime: - properties: - failed: - type: integer - p100: - type: number - passed: - type: integer - type: object - Link: - properties: - icon: - type: string - label: - type: string - text: - type: string - tooltip: - type: string - type: - description: e.g. documentation, support, playbook - type: string - url: - type: string - type: object - Summary: - properties: - healthy: - type: integer - info: - type: integer - unhealthy: - type: integer - warning: - type: integer - type: object -info: - contact: {} - license: - name: Apache 2.0 - url: http://www.apache.org/licenses/LICENSE-2.0.html - title: Canary Checker API - version: 1..1 -paths: - /api/topology: - get: - description: Query the topology graph - operationId: TopologyQuery - parameters: - - description: Topology ID - in: query - name: id - type: string - - description: Topology ID - in: query - name: topologyId - type: string - - description: Component ID - in: query - name: componentId - type: string - - description: Owner - in: query - name: owner - type: string - - description: Comma seperated list of status - in: query - name: status - type: string - - description: Comma seperated list of types - in: query - name: types - type: string - - description: Flatten the topology - in: query - name: flatten - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/Component' - type: array - summary: Topology query - tags: - - topology -swagger: "2.0" diff --git a/fixtures/aws/ec2_pass.yaml b/fixtures/aws/ec2_pass.yaml index b70ea01ea..618dfe225 100644 --- a/fixtures/aws/ec2_pass.yaml +++ b/fixtures/aws/ec2_pass.yaml @@ -7,7 +7,7 @@ spec: spec: ec2: - description: test instance - accessKeyID: + accessKey: valueFrom: secretKeyRef: name: aws-credentials diff --git a/fixtures/azure/devops.yaml b/fixtures/azure/devops.yaml index 3c1f0062b..db6095f49 100644 --- a/fixtures/azure/devops.yaml +++ b/fixtures/azure/devops.yaml @@ -7,7 +7,8 @@ spec: azureDevops: - project: Demo1 pipeline: ^windows- - personalAccessToken: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + personalAccessToken: + value: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx organization: flanksource variable: env: prod diff --git a/fixtures/datasources/SFTP/sftp_pass.yaml b/fixtures/datasources/SFTP/sftp_pass.yaml index 7f956fc4a..79d7c459f 100644 --- a/fixtures/datasources/SFTP/sftp_pass.yaml +++ b/fixtures/datasources/SFTP/sftp_pass.yaml @@ -9,9 +9,8 @@ spec: name: sample sftp check sftpConnection: host: 192.168.1.5 - auth: - username: - value: - password: - value: - maxCount: 10 \ No newline at end of file + username: + value: + password: + value: + maxCount: 10 diff --git a/fixtures/datasources/elasticsearch_fail.yaml b/fixtures/datasources/elasticsearch_fail.yaml index e2fac9271..db0ed8422 100644 --- a/fixtures/datasources/elasticsearch_fail.yaml +++ b/fixtures/datasources/elasticsearch_fail.yaml @@ -18,14 +18,13 @@ spec: } results: 1 name: elasticsearch-fail - auth: - username: - valueFrom: - secretKeyRef: - name: search - key: ELASTIC_SEARCH_USERNAME - password: - valueFrom: - secretKeyRef: - name: search - key: ELASTIC_SEARCH_PASSWORD + username: + valueFrom: + secretKeyRef: + name: search + key: ELASTIC_SEARCH_USERNAME + password: + valueFrom: + secretKeyRef: + name: search + key: ELASTIC_SEARCH_PASSWORD diff --git a/fixtures/datasources/elasticsearch_pass.yaml b/fixtures/datasources/elasticsearch_pass.yaml index 7cee8c31f..5981488c8 100644 --- a/fixtures/datasources/elasticsearch_pass.yaml +++ b/fixtures/datasources/elasticsearch_pass.yaml @@ -18,14 +18,13 @@ spec: } results: 1 name: elasticsearch_pass - auth: - username: - valueFrom: - secretKeyRef: - name: search - key: ELASTIC_SEARCH_USERNAME - password: - valueFrom: - secretKeyRef: - name: search - key: ELASTIC_SEARCH_PASSWORD \ No newline at end of file + username: + valueFrom: + secretKeyRef: + name: search + key: ELASTIC_SEARCH_USERNAME + password: + valueFrom: + secretKeyRef: + name: search + key: ELASTIC_SEARCH_PASSWORD diff --git a/fixtures/datasources/ldap_pass.yaml b/fixtures/datasources/ldap_pass.yaml index 4804ef707..199a2e282 100644 --- a/fixtures/datasources/ldap_pass.yaml +++ b/fixtures/datasources/ldap_pass.yaml @@ -5,21 +5,19 @@ metadata: spec: interval: 30 ldap: - - host: ldap://apacheds.ldap.svc.cluster.local:10389 + - url: ldap://apacheds.ldap.svc.cluster.local:10389 name: ldap user login - auth: - username: - value: uid=admin,ou=system - password: - value: secret + username: + value: uid=admin,ou=system + password: + value: secret bindDN: ou=users,dc=example,dc=com userSearch: "(&(objectClass=organizationalPerson))" - - host: ldap://apacheds.ldap.svc.cluster.local:10389 + - url: ldap://apacheds.ldap.svc.cluster.local:10389 name: ldap group login - auth: - username: - value: uid=admin,ou=system - password: - value: secret + username: + value: uid=admin,ou=system + password: + value: secret bindDN: ou=groups,dc=example,dc=com userSearch: "(&(objectClass=groupOfNames))" diff --git a/fixtures/datasources/mongo_fail.yaml b/fixtures/datasources/mongo_fail.yaml index e1ba27aca..69492e5c2 100644 --- a/fixtures/datasources/mongo_fail.yaml +++ b/fixtures/datasources/mongo_fail.yaml @@ -7,11 +7,10 @@ metadata: spec: interval: 30 mongodb: - - connection: mongodb://mongo2.default.svc.cluster.local:27017/?authSource=admin + - url: mongodb://mongo2.default.svc.cluster.local:27017/?authSource=admin name: mongo wrong password description: test mongo instance - auth: - username: - value: mongoadmin - password: - value: wronghere2 + username: + value: mongoadmin + password: + value: wronghere2 diff --git a/fixtures/datasources/mongo_pass.yaml b/fixtures/datasources/mongo_pass.yaml index 5c037a646..46e4dabd6 100644 --- a/fixtures/datasources/mongo_pass.yaml +++ b/fixtures/datasources/mongo_pass.yaml @@ -5,14 +5,9 @@ metadata: spec: interval: 30 mongodb: - - connection: mongodb://$(username):$(password)@mongo.default.svc.cluster.local:27017/?authSource=admin + - url: mongodb://$(username):$(password)@mongo.default.svc.cluster.local:27017/?authSource=admin name: mongo ping check - description: mongo ping - auth: - username: - value: mongoadmin - password: - value: secret - dns: - - query: mongo.default.svc.cluster.local - name: mongo dns check + username: + value: mongoadmin + password: + value: secret diff --git a/fixtures/datasources/mssql_fail.yaml b/fixtures/datasources/mssql_fail.yaml index 2027f9565..fb784396e 100644 --- a/fixtures/datasources/mssql_fail.yaml +++ b/fixtures/datasources/mssql_fail.yaml @@ -7,7 +7,7 @@ metadata: spec: interval: 30 mssql: - - connection: "server=mssql.platformsystem;user id=sa;password=S0m3p@sswd;port=32010;database=master" #wrong server name for failure + - url: "server=mssql.platformsystem;user id=sa;password=S0m3p@sswd;port=32010;database=master" #wrong server name for failure name: mssql servername query: "SELECT 1" results: 1 diff --git a/fixtures/datasources/mssql_pass.yaml b/fixtures/datasources/mssql_pass.yaml index d318f833b..032a1e867 100644 --- a/fixtures/datasources/mssql_pass.yaml +++ b/fixtures/datasources/mssql_pass.yaml @@ -5,12 +5,11 @@ metadata: spec: interval: 30 mssql: - - connection: "server=mssql.default.svc.cluster.local;user id=$(username);password=$(password);port=1433;database=master" + - url: "server=mssql.default.svc.cluster.local;user id=$(username);password=$(password);port=1433;database=master" name: mssql pass - auth: - username: - value: sa - password: - value: S0m3p@sswd + username: + value: sa + password: + value: S0m3p@sswd query: "SELECT 1" results: 1 diff --git a/fixtures/datasources/mysql_fail.yaml b/fixtures/datasources/mysql_fail.yaml index 4b1f947e0..e11bcf9a6 100644 --- a/fixtures/datasources/mysql_fail.yaml +++ b/fixtures/datasources/mysql_fail.yaml @@ -5,12 +5,11 @@ metadata: spec: interval: 30 mysql: - - connection: "$(username):$(password)@tcp(mysql.default.svc.cluster.local:3306)/mysqldb" + - url: "$(username):$(password)@tcp(mysql.default.svc.cluster.local:3306)/mysqldb" name: mysql wrong password - auth: - username: - value: mysqladmin - password: - value: wrongpassword + username: + value: mysqladmin + password: + value: wrongpassword query: "SELECT 1" results: 1 diff --git a/fixtures/datasources/mysql_pass.yaml b/fixtures/datasources/mysql_pass.yaml index ba8d9a5cb..4d785721e 100644 --- a/fixtures/datasources/mysql_pass.yaml +++ b/fixtures/datasources/mysql_pass.yaml @@ -5,12 +5,11 @@ metadata: spec: interval: 30 mysql: - - connection: "$(username):$(password)@tcp(mysql.default.svc.cluster.local:3306)/mysqldb" + - url: "$(username):$(password)@tcp(mysql.default.svc.cluster.local:3306)/mysqldb" name: mysql ping check - auth: - username: - value: mysqladmin - password: - value: admin123 + username: + value: mysqladmin + password: + value: admin123 query: "SELECT 1" results: 1 diff --git a/fixtures/datasources/opensearch_fail.yaml b/fixtures/datasources/opensearch_fail.yaml index 58269133f..8b3659bf6 100644 --- a/fixtures/datasources/opensearch_fail.yaml +++ b/fixtures/datasources/opensearch_fail.yaml @@ -21,14 +21,13 @@ spec: } } results: 100 - auth: - username: - valueFrom: - secretKeyRef: - name: search - key: OPENSEARCH_USERNAME - password: - valueFrom: - secretKeyRef: - name: search - key: OPENSEARCH_PASSWORD + username: + valueFrom: + secretKeyRef: + name: search + key: OPENSEARCH_USERNAME + password: + valueFrom: + secretKeyRef: + name: search + key: OPENSEARCH_PASSWORD diff --git a/fixtures/datasources/opensearch_pass.yaml b/fixtures/datasources/opensearch_pass.yaml index cd88474bd..14b1dbe51 100644 --- a/fixtures/datasources/opensearch_pass.yaml +++ b/fixtures/datasources/opensearch_pass.yaml @@ -20,14 +20,13 @@ spec: } } results: 1 - auth: - username: - valueFrom: - secretKeyRef: - name: search - key: OPENSEARCH_USERNAME - password: - valueFrom: - secretKeyRef: - name: search - key: OPENSEARCH_PASSWORD + username: + valueFrom: + secretKeyRef: + name: search + key: OPENSEARCH_USERNAME + password: + valueFrom: + secretKeyRef: + name: search + key: OPENSEARCH_PASSWORD diff --git a/fixtures/datasources/postgres_fail.yaml b/fixtures/datasources/postgres_fail.yaml index 1eb171236..07bedc172 100644 --- a/fixtures/datasources/postgres_fail.yaml +++ b/fixtures/datasources/postgres_fail.yaml @@ -8,12 +8,11 @@ metadata: spec: interval: 30 postgres: - - connection: "user=$(username) dbname=pqgotest sslmode=verify-full" + - url: "user=$(username) dbname=pqgotest sslmode=verify-full" name: postgres blank password - auth: - username: - value: pqgotest - password: - value: "" + username: + value: pqgotest + password: + value: "" query: "SELECT 1" results: 1 diff --git a/fixtures/datasources/postgres_pass.yaml b/fixtures/datasources/postgres_pass.yaml index b3a4909b3..1663cbed7 100644 --- a/fixtures/datasources/postgres_pass.yaml +++ b/fixtures/datasources/postgres_pass.yaml @@ -5,13 +5,12 @@ metadata: spec: interval: 30 postgres: - - connection: "postgres://$(username):$(password)@postgres.default.svc.cluster.local:5432/postgres?sslmode=disable" + - url: "postgres://$(username):$(password)@postgres.default.svc.cluster.local:5432/postgres?sslmode=disable" name: postgres schemas check - auth: - username: - value: postgresadmin - password: - value: admin123 + username: + value: postgresadmin + password: + value: admin123 query: SELECT current_schemas(true) display: template: | diff --git a/fixtures/datasources/prometheus.yaml b/fixtures/datasources/prometheus.yaml index f87ed8974..85ca519e0 100644 --- a/fixtures/datasources/prometheus.yaml +++ b/fixtures/datasources/prometheus.yaml @@ -5,10 +5,8 @@ metadata: spec: interval: 30 prometheus: - - host: https://prometheus.demo.aws.flanksource.com/ + - url: https://prometheus.demo.aws.flanksource.com/ name: prometheus-check query: kubernetes_build_info{job!~"kube-dns|coredns"} display: - template: "{{ (index .results 0).git_version }}" - test: - template: "true" + expr: results[0].git_version diff --git a/fixtures/k8s/http_auth_configmap.yaml b/fixtures/k8s/http_auth_configmap.yaml index 6080740b9..803ec0cc2 100644 --- a/fixtures/k8s/http_auth_configmap.yaml +++ b/fixtures/k8s/http_auth_configmap.yaml @@ -6,14 +6,13 @@ spec: http: - endpoint: https://httpbin.demo.aws.flanksource.com/basic-auth/hello/world responseCodes: [200] - authentication: - username: - valueFrom: - configMapKeyRef: - name: basic-auth - key: user - password: - valueFrom: - configMapKeyRef: - name: basic-auth - key: pass + username: + valueFrom: + configMapKeyRef: + name: basic-auth + key: user + password: + valueFrom: + configMapKeyRef: + name: basic-auth + key: pass diff --git a/fixtures/k8s/http_auth_secret.yaml b/fixtures/k8s/http_auth_secret.yaml index 431c960c2..20290d7d4 100644 --- a/fixtures/k8s/http_auth_secret.yaml +++ b/fixtures/k8s/http_auth_secret.yaml @@ -8,14 +8,13 @@ spec: http: - endpoint: https://httpbin.demo.aws.flanksource.com/basic-auth/hello/world responseCodes: [200] - authentication: - username: - valueFrom: - secretKeyRef: - name: basic-auth - key: user - password: - valueFrom: - secretKeyRef: - name: basic-auth - key: pass + username: + valueFrom: + secretKeyRef: + name: basic-auth + key: user + password: + valueFrom: + secretKeyRef: + name: basic-auth + key: pass diff --git a/fixtures/minimal/http_auth.yaml b/fixtures/minimal/http_auth.yaml index 562aca01e..d557779f1 100644 --- a/fixtures/minimal/http_auth.yaml +++ b/fixtures/minimal/http_auth.yaml @@ -8,8 +8,7 @@ spec: responseCodes: [401] - endpoint: https://httpbin.demo.aws.flanksource.com/basic-auth/hello/world responseCodes: [200] - authentication: - username: - value: hello - password: - value: world + username: + value: hello + password: + value: world diff --git a/fixtures/minimal/http_pass_results_mode_pass.yaml b/fixtures/minimal/http_pass_results_mode_pass.yaml index eb68efac3..95335ff03 100644 --- a/fixtures/minimal/http_pass_results_mode_pass.yaml +++ b/fixtures/minimal/http_pass_results_mode_pass.yaml @@ -6,14 +6,14 @@ spec: resultMode: "junit" interval: 30 http: - - endpoint: https://httpbin.demo.aws.flanksource.com/status/200 + - url: https://httpbin.demo.aws.flanksource.com/status/200 name: http pass response 200 status code thresholdMillis: 30000 responseCodes: [201, 301, 200] responseContent: "" maxSSLExpiry: 7 description: "HTTP dummy test 2" - - endpoint: https://httpbin.demo.aws.flanksource.com/status/201 + - url: https://httpbin.demo.aws.flanksource.com/status/201 name: http pass response 201 status code thresholdMillis: 30000 responseCodes: [201] diff --git a/fixtures/minimal/http_pass_single.yaml b/fixtures/minimal/http_pass_single.yaml index 0781868a2..a3619f58c 100644 --- a/fixtures/minimal/http_pass_single.yaml +++ b/fixtures/minimal/http_pass_single.yaml @@ -8,10 +8,17 @@ spec: interval: 30 http: - endpoint: https://httpbin.demo.aws.flanksource.com/status/200 - name: sample-check - thresholdMillis: 3000 + name: http-deprecated-endpoint + - name: http-minimal-check + url: https://httpbin.demo.aws.flanksource.com/status/200 + - name: http-param-tests + url: https://httpbin.demo.aws.flanksource.com/status/200 responseCodes: [201, 200, 301] responseContent: "" maxSSLExpiry: 7 + - name: http-expr-tests + url: https://httpbin.demo.aws.flanksource.com/status/200 test: - expr: "code == 200" + expr: "code in [200,201,301] and sslAge > Duration('7d')" + display: + template: "code={{.code}}, age={{.sslAge}}" diff --git a/fixtures/quarantine/smb_pass.yaml b/fixtures/quarantine/smb_pass.yaml index 6733a4e3c..612dde49b 100644 --- a/fixtures/quarantine/smb_pass.yaml +++ b/fixtures/quarantine/smb_pass.yaml @@ -8,17 +8,16 @@ spec: # Check for any backup not older than 7 days and min size 25 bytes - path: \\windows-server\sharename\folder smbConnection: - auth: - username: - valueFrom: - secretKeyRef: - name: smb-credentials - key: USERNAME - password: - valueFrom: - secretKeyRef: - name: ssmb-credentials - key: PASSWORD + username: + valueFrom: + secretKeyRef: + name: smb-credentials + key: USERNAME + password: + valueFrom: + secretKeyRef: + name: ssmb-credentials + key: PASSWORD filter: regex: "(.*)backup.zip$" maxAge: 7d diff --git a/go.mod b/go.mod index b8473af16..2cfd94cff 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,8 @@ require ( github.com/elastic/go-elasticsearch/v8 v8.1.0 github.com/fergusstrange/embedded-postgres v1.21.0 github.com/flanksource/commons v1.10.0 - github.com/flanksource/duty v1.0.113 + github.com/flanksource/duty v1.0.121 + github.com/flanksource/is-healthy v0.0.0-20230705092916-3b4cf510c5fc github.com/flanksource/kommons v0.31.1 github.com/friendsofgo/errors v0.9.2 github.com/go-ldap/ldap/v3 v3.4.1 diff --git a/go.sum b/go.sum index deb0c11f5..1260ca9fc 100644 --- a/go.sum +++ b/go.sum @@ -1091,11 +1091,13 @@ github.com/fergusstrange/embedded-postgres v1.21.0 h1:Sups0nR31+OB4iOZ0ZU4IwUDsB github.com/fergusstrange/embedded-postgres v1.21.0/go.mod h1:wL562t1V+iuFwq0UcgMi2e9rp8CROY9wxWZEfP8Y874= github.com/flanksource/commons v1.10.0 h1:Mc+fzxq1rOJ08lapF0cc0bo9ZKNDxA7/81q2D/5jt0Q= github.com/flanksource/commons v1.10.0/go.mod h1:HpVjPtNe7v0UPk97kO/uUhOrYQ8yFD/mGglrTCkc9Ag= -github.com/flanksource/duty v1.0.113 h1:iQeMhn/Vjz+Rap4TpniGEwLOXcFeg9+X1GtcUsWp3+g= -github.com/flanksource/duty v1.0.113/go.mod h1:RJ/kcZ7dbL8/52tem757szVIA3IomS8bOAZIK0xb4rk= +github.com/flanksource/duty v1.0.121 h1:pSFCbwV+ic9gKklwCtJxKsrR5M9CJuooK37l34gja6o= +github.com/flanksource/duty v1.0.121/go.mod h1:RJ/kcZ7dbL8/52tem757szVIA3IomS8bOAZIK0xb4rk= github.com/flanksource/gomplate/v3 v3.20.1/go.mod h1:LPpzujBIg9HBXRUngDKK/zNmEjHpEUieKa/2oRjkCzI= github.com/flanksource/gomplate/v3 v3.20.3 h1:mnNaO37uwvv8Kvi4Xswj1tHKP5UMre3FLNaKvAwqhSw= github.com/flanksource/gomplate/v3 v3.20.3/go.mod h1:l4iCvp30TdhZk89eRGuNkPwlRjJLXdUSblr+VyuZfAk= +github.com/flanksource/is-healthy v0.0.0-20230705092916-3b4cf510c5fc h1:CPUNUw2pHnlF4ucBHx44vLTcCa4FlEEu6PkNo5rCvD4= +github.com/flanksource/is-healthy v0.0.0-20230705092916-3b4cf510c5fc/go.mod h1:4pQhmF+TnVqJroQKY8wSnSp+T18oLson6YQ2M0qPHfQ= github.com/flanksource/kommons v0.31.1 h1:WZjrIYbSAR7xzIvP2uSRQcn5wPi4W9gAasuOM5CD854= github.com/flanksource/kommons v0.31.1/go.mod h1:kJfMnFWiqsfE8koab54W2GsmgvrlESDrcUtwvbQS9aY= github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= @@ -2292,8 +2294,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= diff --git a/hack/generate-schemas/go.mod b/hack/generate-schemas/go.mod index 276823dba..04357b847 100644 --- a/hack/generate-schemas/go.mod +++ b/hack/generate-schemas/go.mod @@ -73,7 +73,7 @@ require ( github.com/dustin/go-humanize v1.0.1 // indirect github.com/dustin/gojson v0.0.0-20160307161227-2e71ec9dd5ad // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/flanksource/duty v1.0.113 // indirect + github.com/flanksource/duty v1.0.121 // indirect github.com/ghodss/yaml v1.0.0 // indirect github.com/go-logr/logr v1.2.4 // indirect github.com/go-openapi/inflect v0.19.0 // indirect diff --git a/hack/generate-schemas/go.sum b/hack/generate-schemas/go.sum index cd4aa426e..bade3e1af 100644 --- a/hack/generate-schemas/go.sum +++ b/hack/generate-schemas/go.sum @@ -811,8 +811,8 @@ github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSw github.com/fergusstrange/embedded-postgres v1.21.0 h1:Sups0nR31+OB4iOZ0ZU4IwUDsB+dVGmcqj4S2ko0qTI= github.com/flanksource/commons v1.10.0 h1:Mc+fzxq1rOJ08lapF0cc0bo9ZKNDxA7/81q2D/5jt0Q= github.com/flanksource/commons v1.10.0/go.mod h1:HpVjPtNe7v0UPk97kO/uUhOrYQ8yFD/mGglrTCkc9Ag= -github.com/flanksource/duty v1.0.113 h1:iQeMhn/Vjz+Rap4TpniGEwLOXcFeg9+X1GtcUsWp3+g= -github.com/flanksource/duty v1.0.113/go.mod h1:RJ/kcZ7dbL8/52tem757szVIA3IomS8bOAZIK0xb4rk= +github.com/flanksource/duty v1.0.121 h1:pSFCbwV+ic9gKklwCtJxKsrR5M9CJuooK37l34gja6o= +github.com/flanksource/duty v1.0.121/go.mod h1:RJ/kcZ7dbL8/52tem757szVIA3IomS8bOAZIK0xb4rk= github.com/flanksource/gomplate/v3 v3.20.1/go.mod h1:LPpzujBIg9HBXRUngDKK/zNmEjHpEUieKa/2oRjkCzI= github.com/flanksource/gomplate/v3 v3.20.3 h1:mnNaO37uwvv8Kvi4Xswj1tHKP5UMre3FLNaKvAwqhSw= github.com/flanksource/gomplate/v3 v3.20.3/go.mod h1:l4iCvp30TdhZk89eRGuNkPwlRjJLXdUSblr+VyuZfAk= @@ -1481,8 +1481,8 @@ github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= -github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU= github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk= diff --git a/pkg/api.go b/pkg/api.go index 2d61d7b7d..3a0b4aadb 100644 --- a/pkg/api.go +++ b/pkg/api.go @@ -202,6 +202,11 @@ type Check struct { DeletedAt *time.Time `json:"deletedAt,omitempty"` SilencedAt *time.Time `json:"silencedAt,omitempty"` Canary *v1.Canary `json:"-" gorm:"-"` + + // These are calculated for the selected date range + EarliestRuntime *time.Time `json:"earliestRuntime,omitempty" gorm:"-"` + LatestRuntime *time.Time `json:"latestRuntime,omitempty" gorm:"-"` + TotalRuns int `json:"totalRuns,omitempty" gorm:"-"` } func FromExternalCheck(canary Canary, check external.Check) Check { diff --git a/pkg/api/api.go b/pkg/api/api.go index 5b72e7474..4e4465dd5 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -12,7 +12,27 @@ import ( "github.com/flanksource/canary-checker/pkg" ) -var DefaultWindow = "1h" +// The number of data points that should be strived for +// when aggregating check statuses. +const desiredNumOfCheckStatuses = 100 + +var ( + DefaultWindow = "1h" + + // allowed list of window durations that are used when aggregating check statuses. + allowedWindows = []time.Duration{ + time.Minute, // 1m + time.Minute * 5, // 5m + time.Minute * 15, // 15m + time.Minute * 30, // 30m + time.Hour, // 1h + time.Hour * 3, // 3h + time.Hour * 6, // 6h + time.Hour * 12, // 12h + time.Hour * 24, // 24h + time.Hour * 24 * 7, // 1w + } +) type Response struct { Duration int `json:"duration,omitempty"` @@ -20,10 +40,13 @@ type Response struct { Checks pkg.Checks `json:"checks"` ChecksSummary models.Checks `json:"checks_summary,omitempty"` } + type DetailResponse struct { Duration int `json:"duration,omitempty"` RunnerName string `json:"runnerName"` Status []pkg.Timeseries `json:"status"` + Latency pkg.Latency `json:"latency"` + Uptime pkg.Uptime `json:"uptime"` } func About(c echo.Context) error { @@ -41,15 +64,34 @@ func CheckDetails(c echo.Context) error { } start := time.Now() - results, err := cache.PostgresCache.QueryStatus(*q) + + summary, err := cache.PostgresCache.Query(*q) + if err != nil { + return errorResonse(c, err, http.StatusInternalServerError) + } + if len(summary) == 0 { + return c.JSON(http.StatusOK, DetailResponse{}) + } + + checkSummary := summary[0] + totalChecks := checkSummary.TotalRuns + + rangeDuration := checkSummary.LatestRuntime.Sub(*checkSummary.EarliestRuntime) + q.WindowDuration = getBestPartitioner(totalChecks, rangeDuration) + + results, err := cache.PostgresCache.QueryStatus(c.Request().Context(), *q) if err != nil { return errorResonse(c, err, http.StatusInternalServerError) } + apiResponse := &DetailResponse{ RunnerName: runner.RunnerName, Status: results, Duration: int(time.Since(start).Milliseconds()), + Latency: checkSummary.Latency, + Uptime: checkSummary.Uptime, } + return c.JSON(http.StatusOK, apiResponse) } @@ -87,3 +129,37 @@ func HealthSummary(c echo.Context) error { } return c.JSON(http.StatusOK, apiResponse) } + +func getBestPartitioner(totalChecks int, rangeDuration time.Duration) time.Duration { + if totalChecks <= desiredNumOfCheckStatuses { + return 0 // No need to perform window aggregation + } + + bestDelta := 100000000 // sufficiently large delta to begin with + bestWindow := allowedWindows[0] + + for _, wp := range allowedWindows { + numWindows := int(rangeDuration / wp) + delta := abs(desiredNumOfCheckStatuses - numWindows) + + if delta < bestDelta { + bestDelta = delta + bestWindow = wp + } else { + // as soon as we notice that the delta gets worse, we break the loop + break + } + } + + numWindows := int(rangeDuration / bestWindow) + if abs(desiredNumOfCheckStatuses-totalChecks) <= abs(desiredNumOfCheckStatuses-numWindows) { + // If this best partition creates windows such that the resulting number of data points deviate more + // from the desired data points than the actual data points, then we do not aggregate. + // Example: if there are 144 checks for the duration of 6 days, + // then the best partition, 1 hour, would generate 144 data points. + // But the original data points (120) are closer to 100, so we do not aggregate. + return 0 + } + + return bestWindow +} diff --git a/pkg/api/api_test.go b/pkg/api/api_test.go new file mode 100644 index 000000000..9721e3653 --- /dev/null +++ b/pkg/api/api_test.go @@ -0,0 +1,40 @@ +package api + +import ( + "testing" + "time" +) + +func Test_getMostSuitableWindowDuration(t *testing.T) { + day := time.Hour * 24 + + tests := []struct { + schedule time.Duration // how often the check is run + rangeDuration time.Duration + expected time.Duration // the best duration to partition the range + }{ + {time.Second * 30, time.Minute * 5, 0}, + {time.Second * 30, time.Minute * 30, 0}, + {time.Second * 30, time.Hour * 2, time.Minute}, + {time.Second * 30, time.Hour * 12, time.Minute * 5}, + {time.Second * 30, day * 2, time.Minute * 30}, + {time.Hour, day * 4, 0}, + {time.Hour, day * 5, 0}, + {time.Hour, day * 6, 0}, + {time.Hour, day * 12, time.Hour * 3}, + {time.Second * 30, day * 8, time.Hour * 3}, + {time.Second * 30, day * 30, time.Hour * 6}, + {time.Second * 30, day * 90, day}, + {time.Second * 30, day * 365, day * 7}, + } + + for _, td := range tests { + t.Run(td.rangeDuration.String(), func(t *testing.T) { + totalChecks := int(td.rangeDuration / td.schedule) + result := getBestPartitioner(totalChecks, td.rangeDuration) + if result != td.expected { + t.Errorf("expected %v, but got %v", td.expected, result) + } + }) + } +} diff --git a/pkg/api/utils.go b/pkg/api/utils.go index bf8e2b9dc..242cc276d 100644 --- a/pkg/api/utils.go +++ b/pkg/api/utils.go @@ -8,3 +8,14 @@ func errorResonse(c echo.Context, err error, code int) error { e := map[string]string{"error": err.Error()} return c.JSON(code, e) } + +// abs returns the absolute value of i. +// math.Abs only supports float64 and this avoids the needless type conversions +// and ugly expression. +func abs(n int) int { + if n > 0 { + return n + } + + return -n +} diff --git a/pkg/cache/cache.go b/pkg/cache/cache.go index 1e360090e..699e7de16 100644 --- a/pkg/cache/cache.go +++ b/pkg/cache/cache.go @@ -28,6 +28,7 @@ type QueryParams struct { StatusCount int Labels map[string]string Trace bool + WindowDuration time.Duration } func (q QueryParams) Validate() error { @@ -57,10 +58,10 @@ func (q QueryParams) GetStartTime() *time.Time { func (q QueryParams) GetEndTime() *time.Time { if q._end != nil || q.End == "" { - return q._start + return q._end } - q._start, _ = timeV(q.Start) - return q._start + q._end, _ = timeV(q.End) + return q._end } func (q QueryParams) String() string { @@ -80,6 +81,7 @@ func ParseQuery(c echo.Context) (*QueryParams, error) { } else { cacheCount = int64(DefaultCacheCount) } + since := queryParams.Get("since") if since == "" { since = queryParams.Get("start") @@ -87,10 +89,15 @@ func ParseQuery(c echo.Context) (*QueryParams, error) { if since == "" { since = DefaultWindow } + until := queryParams.Get("until") if until == "" { until = queryParams.Get("end") } + if until == "" { + until = "0s" + } + q := QueryParams{ Start: since, End: until, diff --git a/pkg/cache/postgres.go b/pkg/cache/postgres.go index 40665c4fa..3e1d9c0cb 100644 --- a/pkg/cache/postgres.go +++ b/pkg/cache/postgres.go @@ -111,8 +111,8 @@ func (c *postgresCache) QuerySummary() (models.Checks, error) { return duty.QueryCheckSummary(context.Background(), db.Pool) } -func (c *postgresCache) QueryStatus(q QueryParams) ([]pkg.Timeseries, error) { - return q.ExecuteDetails(db.Pool) +func (c *postgresCache) QueryStatus(ctx context.Context, q QueryParams) ([]pkg.Timeseries, error) { + return q.ExecuteDetails(ctx, db.Pool) } func (c *postgresCache) GetDetails(checkkey string, time string) interface{} { diff --git a/pkg/cache/postgres_query.go b/pkg/cache/postgres_query.go index 9ee342754..fb4fa43c9 100644 --- a/pkg/cache/postgres_query.go +++ b/pkg/cache/postgres_query.go @@ -79,33 +79,38 @@ func (q QueryParams) GetWhereClause() (string, map[string]interface{}, error) { return strings.TrimSpace(clause), args, nil } -func (q QueryParams) ExecuteDetails(db Querier) ([]pkg.Timeseries, error) { - clause, namedArgs, err := q.GetWhereClause() - if err != nil { - return nil, err - } - namedArgs["limit"] = q.StatusCount - keyIndex := 3 - messageIndex := 4 - errorIndex := 5 +func (q QueryParams) ExecuteDetails(ctx context.Context, db Querier) ([]pkg.Timeseries, error) { + start := q.GetStartTime().Format(time.RFC3339) + end := q.GetEndTime().Format(time.RFC3339) - sql := "SELECT time,duration,status " - if q.Check == "" { - sql += ", check_key" - } - if q.IncludeMessages { - sql += ", message, error" - if q.Check != "" { - messageIndex -= 1 - errorIndex -= 1 - } - } - sql += fmt.Sprintf(` + query := ` +With grouped_by_window AS ( + SELECT + duration, + status, + to_timestamp(floor((extract(epoch FROM time) + $1) / $2) * $2) AS time FROM check_statuses - WHERE %s - LIMIT :limit -`, clause) - rows, err := exec(db, q, sql, namedArgs) + WHERE + time >= $3 AND + time <= $4 AND + check_id = $5 +) +SELECT + time, + bool_and(status), + AVG(duration)::integer as duration +FROM + grouped_by_window +GROUP BY time +` + args := []any{q.WindowDuration.Seconds() / 2, q.WindowDuration.Seconds(), start, end, q.Check} + + if q.WindowDuration == 0 { + query = `SELECT time, status, duration FROM check_statuses WHERE time >= $1 AND time <= $2 AND check_id = $3` + args = []any{start, end, q.Check} + } + + rows, err := db.Query(ctx, query, args...) if err != nil { return nil, err } @@ -113,24 +118,16 @@ func (q QueryParams) ExecuteDetails(db Querier) ([]pkg.Timeseries, error) { var results []pkg.Timeseries for rows.Next() { - vals, err := rows.Values() - if err != nil { + var datapoint pkg.Timeseries + var ts time.Time + if err := rows.Scan(&ts, &datapoint.Status, &datapoint.Duration); err != nil { return nil, err } - result := pkg.Timeseries{ - Time: vals[0].(time.Time).Format(time.RFC3339), - Duration: intV(vals[1]), - Status: vals[2].(bool), - } - if q.Check == "" { - result.Key = vals[keyIndex].(string) - } - if q.IncludeMessages { - result.Message = vals[messageIndex].(string) - result.Error = vals[errorIndex].(string) - } - results = append(results, result) + + datapoint.Time = ts.Format(time.RFC3339) + results = append(results, datapoint) } + return results, nil } @@ -193,9 +190,11 @@ SELECT checks.created_at, checks.updated_at, checks.deleted_at, - status + status, + stats.max_time, + stats.min_time, + stats.total_checks FROM checks checks - RIGHT JOIN ( SELECT check_id, @@ -203,7 +202,10 @@ RIGHT JOIN ( percentile_disc(0.97) within group (order by filtered_check_status.duration) as p97, percentile_disc(0.05) within group (order by filtered_check_status.duration) as p95, COUNT(*) FILTER (WHERE filtered_check_status.status = TRUE) as passed, - COUNT(*) FILTER (WHERE filtered_check_status.status = FALSE) as failed + COUNT(*) FILTER (WHERE filtered_check_status.status = FALSE) as failed, + COUNT(*) total_checks, + MIN(filtered_check_status.time) as min_time, + MAX(filtered_check_status.time) as max_time FROM filtered_check_status GROUP BY check_id @@ -273,6 +275,10 @@ WHERE (stats.passed > 0 OR stats.failed > 0) %s check.DeletedAt, _ = timeV(vals[20]) } check.Status = vals[21].(string) + check.LatestRuntime, _ = timeV(vals[22]) + check.EarliestRuntime, _ = timeV(vals[23]) + check.TotalRuns = intV(vals[24]) + if vals[7] != nil { for _, status := range vals[7].([]interface{}) { s := status.(map[string]interface{}) diff --git a/pkg/topology/checks/component_check_test.go b/pkg/topology/checks/component_check_test.go new file mode 100644 index 000000000..5f9b6d64a --- /dev/null +++ b/pkg/topology/checks/component_check_test.go @@ -0,0 +1,73 @@ +package checks + +import ( + v1 "github.com/flanksource/canary-checker/api/v1" + "github.com/flanksource/canary-checker/pkg" + "github.com/flanksource/canary-checker/pkg/db" + "github.com/flanksource/duty/models" + "github.com/google/uuid" + ginkgo "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +var _ = ginkgo.Describe("Test component check sync job", ginkgo.Ordered, func() { + component := pkg.Component{ + Name: "Component", + ComponentChecks: []v1.ComponentCheck{{ + Selector: v1.ResourceSelector{ + Name: "ComponentCheckSelector", + LabelSelector: "check-target=api", + }, + }}, + } + canary := models.Canary{ + ID: uuid.New(), + Name: "Canary", + Spec: []byte(`{"spec": {}}`), + } + + ginkgo.BeforeAll(func() { + err := db.Gorm.Create(&component).Error + Expect(err).To(BeNil()) + + err = db.Gorm.Create(&canary).Error + Expect(err).To(BeNil()) + + check1 := pkg.Check{ + Name: "Check-1", + CanaryID: canary.ID, + Labels: map[string]string{ + "check-target": "api", + "name": "check-1", + }, + } + check2 := pkg.Check{ + Name: "Check-2", + CanaryID: canary.ID, + Labels: map[string]string{ + "check-target": "ui", + "name": "check-2", + }, + } + check3 := pkg.Check{ + Name: "Check-3", + CanaryID: canary.ID, + Labels: map[string]string{ + "check-target": "api", + "name": "check-3", + }, + } + + err = db.Gorm.Create([]pkg.Check{check1, check2, check3}).Error + Expect(err).To(BeNil()) + }) + + ginkgo.It("should create check component relationships", func() { + ComponentCheckRun() + cr, err := db.GetCheckRelationshipsForComponent(component.ID) + Expect(err).To(BeNil()) + + // Check-1 and Check-3 should be present but not Check-2 + Expect(len(cr)).To(Equal(2)) + }) +}) diff --git a/pkg/topology/checks/suite_test.go b/pkg/topology/checks/suite_test.go new file mode 100644 index 000000000..a464679fc --- /dev/null +++ b/pkg/topology/checks/suite_test.go @@ -0,0 +1,96 @@ +package checks + +import ( + "context" + "fmt" + "io" + "os" + "testing" + + embeddedPG "github.com/fergusstrange/embedded-postgres" + "github.com/flanksource/canary-checker/pkg/db" + "github.com/flanksource/commons/logger" + "github.com/flanksource/duty" + "github.com/jackc/pgx/v5/pgxpool" + "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "gorm.io/gorm" +) + +var ( + postgresServer *embeddedPG.EmbeddedPostgres +) + +func TestComponentCheckRun(t *testing.T) { + RegisterFailHandler(ginkgo.Fail) + ginkgo.RunSpecs(t, "Test component check runs") +} + +var _ = ginkgo.BeforeSuite(func() { + port := 9841 + config := GetPGConfig("test_component_check", port) + postgresServer = embeddedPG.NewDatabase(config) + if err := postgresServer.Start(); err != nil { + ginkgo.Fail(err.Error()) + } + logger.Infof("Started postgres on port: %d", port) + + db.Gorm, db.Pool = setupDB(fmt.Sprintf("postgres://postgres:postgres@localhost:%d/test_component_check?sslmode=disable", port)) +}) + +var _ = ginkgo.AfterSuite(func() { + logger.Infof("Stopping postgres") + if err := postgresServer.Stop(); err != nil { + ginkgo.Fail(err.Error()) + } +}) + +func setupDB(connectionString string) (*gorm.DB, *pgxpool.Pool) { + pgxpool, err := duty.NewPgxPool(connectionString) + if err != nil { + ginkgo.Fail(err.Error()) + } + + conn, err := pgxpool.Acquire(context.Background()) + if err != nil { + ginkgo.Fail(err.Error()) + } + defer conn.Release() + + gormDB, err := duty.NewGorm(connectionString, duty.DefaultGormConfig()) + if err != nil { + ginkgo.Fail(err.Error()) + } + + if err = duty.Migrate(connectionString, nil); err != nil { + ginkgo.Fail(err.Error()) + } + + return gormDB, pgxpool +} + +func GetPGConfig(database string, port int) embeddedPG.Config { + // We are firing up multiple instances of the embedded postgres server at once when running tests in parallel. + // + // By default fergusstrange/embedded-postgres directly extracts the Postgres binary to a set location + // (/home/runner/.embedded-postgres-go/extracted/bin/initdb) and starts it. + // If two instances try to do this at the same time, they conflict, and throw the error + // "unable to extract postgres archive: open /home/runner/.embedded-postgres-go/extracted/bin/initdb: text file busy." + // + // This is a way to have separate instances of the running postgres servers. + + var runTimePath string + homeDir, err := os.UserHomeDir() + if err != nil { + logger.Errorf("error getting user home dir: %v", err) + runTimePath = fmt.Sprintf("/tmp/.embedded-postgres-go/extracted-%d", port) + } else { + runTimePath = fmt.Sprintf("%s/.embedded-postgres-go/extracted-%d", homeDir, port) + } + + return embeddedPG.DefaultConfig(). + Database(database). + Port(uint32(port)). + RuntimePath(runTimePath). + Logger(io.Discard) +} diff --git a/templating/js/k8s.js b/templating/js/k8s.js index 7f91018b4..4f53b5156 100644 --- a/templating/js/k8s.js +++ b/templating/js/k8s.js @@ -1,21 +1,7 @@ k8s = { conditions: { getMessage: function(v) { - message = "" - if (v.status == null) { - return "No status found" - } - status = v.status - if (status.conditions == null) { - return "no conditions found" - } - status.conditions.forEach(function(state) { - if (state.status != "True") { - message += state.type - message += " " - } - }) - return message.trim() + return v.healthStatus.message.trim(); }, getError: function(v) { active = [] @@ -45,22 +31,7 @@ k8s = { return errorMessage }, isReady: function(v) { - if (v.status == null) { - return false - } - status = v.status - if (status.conditions == null) { - return false - } - ready = true - status.conditions.forEach(function(state) { - if (state.type == "Ready") { - if (state.status != "True") { - ready = false - } - } - }) - return ready + return v.healthStatus.status.toLowerCase() === "healthy" ? true : false; }, }, getAlertName: function(v) {