From c9f008e46463b635a96dbd66c3ee4d5cff59d20c Mon Sep 17 00:00:00 2001 From: Ignas Baranauskas Date: Wed, 11 Oct 2023 16:44:33 +0100 Subject: [PATCH 1/5] Policy attachment metrics backendtlspolicy --- config/default/custom-resource-state.yaml | 152 +++++- config/examples/dashboards/policies.json | 386 ++++++++++++++ config/examples/dashboards/policies.yaml | 10 + config/examples/enterprise/all.yaml | 122 +++++ config/examples/kube-prometheus/bundle.yaml | 165 ++++++ .../grafana_deployment_patch.yaml | 12 + .../ksm_clusterrole_patch.yaml | 12 + .../kube-state-metrics/cluster-role.yaml | 9 + ....networking.k8s.io_backendtlspolicies.yaml | 481 ++++++++++++++++++ .../kuadrant.io_ratelimitpolicies.yaml | 397 +++++++++++++++ .../crd/standard/kuadrant.io_tlspolicies.yaml | 313 ++++++++++++ config/gateway-api/kustomization.yaml | 1 + src/dashboards/lib/gwapi/gwapi.libsonnet | 23 + src/dashboards/policies.jsonnet | 21 + 14 files changed, 2103 insertions(+), 1 deletion(-) create mode 100644 config/examples/dashboards/policies.json create mode 100644 config/examples/dashboards/policies.yaml create mode 100644 config/gateway-api/crd/standard/gateway.networking.k8s.io_backendtlspolicies.yaml create mode 100644 config/gateway-api/crd/standard/kuadrant.io_ratelimitpolicies.yaml create mode 100644 config/gateway-api/crd/standard/kuadrant.io_tlspolicies.yaml create mode 100644 src/dashboards/policies.jsonnet diff --git a/config/default/custom-resource-state.yaml b/config/default/custom-resource-state.yaml index fd8c479..c6b5070 100644 --- a/config/default/custom-resource-state.yaml +++ b/config/default/custom-resource-state.yaml @@ -457,4 +457,154 @@ spec: parent_name: ["parentRef", "name"] parent_namespace: ["parentRef", "namespace"] parent_section_name: ["parentRef", "sectionName"] - parent_port: ["parentRef", "port"] \ No newline at end of file + parent_port: ["parentRef", "port"] + - groupVersionKind: + group: kuadrant.io + kind: "TLSPolicy" + version: "v1alpha1" + metricNamePrefix: gatewayapi_tlspolicy + labelsFromPath: + name: + - metadata + - name + namespace: + - metadata + - namespace + metrics: + - name: "labels" + help: "Kubernetes labels converted to Prometheus labels." + each: + type: Info + info: + path: [metadata] + labelsFromPath: + "*": [labels] + - name: "created" + help: "created timestamp" + each: + type: Gauge + gauge: + path: [metadata, creationTimestamp] + - name: "deleted" + help: "deletion timestamp" + each: + type: Gauge + gauge: + path: [metadata, deletionTimestamp] + - name: "target_info" + help: "Target references that the tlspolicy wants to be attached to" + each: + type: Info + info: + path: [spec, targetRef] + labelsFromPath: + target_group: ["group"] + target_kind: ["kind"] + target_name: ["name"] + target_namespace: ["namespace"] + - name: "status" + help: "status condition" + each: + type: Gauge + gauge: + path: [status, conditions] + labelsFromPath: + type: ["type"] + valueFrom: ["status"] + - groupVersionKind: + group: kuadrant.io + kind: "RateLimitPolicy" + version: "v1beta2" + metricNamePrefix: gatewayapi_ratelimitpolicy + labelsFromPath: + name: + - metadata + - name + namespace: + - metadata + - namespace + metrics: + - name: "labels" + help: "Kubernetes labels converted to Prometheus labels." + each: + type: Info + info: + path: [metadata] + labelsFromPath: + "*": [labels] + - name: "created" + help: "created timestamp" + each: + type: Gauge + gauge: + path: [metadata, creationTimestamp] + - name: "deleted" + help: "deletion timestamp" + each: + type: Gauge + gauge: + path: [metadata, deletionTimestamp] + - name: "target_info" + help: "Target references that the tlspolicy wants to be attached to" + each: + type: Info + info: + path: [spec, targetRef] + labelsFromPath: + target_group: ["group"] + target_kind: ["kind"] + target_name: ["name"] + target_namespace: ["namespace"] + - name: "status" + help: "status condition" + each: + type: Gauge + gauge: + path: [status, conditions] + labelsFromPath: + type: ["type"] + valueFrom: ["status"] + - groupVersionKind: + group: gateway.networking.k8s.io + kind: "BackendTLSPolicy" + version: "v1alpha2" + metricNamePrefix: gatewayapi_backendtlspolicy + labelsFromPath: + name: + - metadata + - name + namespace: + - metadata + - namespace + metrics: + - name: "labels" + help: "Kubernetes labels converted to Prometheus labels." + each: + type: Info + info: + path: [metadata] + labelsFromPath: + "*": [labels] + - name: "created" + help: "created timestamp" + each: + type: Gauge + gauge: + path: [metadata, creationTimestamp] + - name: "deleted" + help: "deletion timestamp" + each: + type: Gauge + gauge: + path: [metadata, deletionTimestamp] + - name: "target_info" + help: "Target references that the backendtlspolicy wants to be attached to" + each: + type: Info + info: + path: [spec, targetRef] + labelsFromPath: + target_group: ["group"] + target_kind: ["kind"] + target_name: ["name"] + target_namespace: ["namespace"] \ No newline at end of file diff --git a/config/examples/dashboards/policies.json b/config/examples/dashboards/policies.json new file mode 100644 index 0000000..6d1f984 --- /dev/null +++ b/config/examples/dashboards/policies.json @@ -0,0 +1,386 @@ +{ + "editable": false, + "links": [ + { + "asDropdown": false, + "includeVars": true, + "keepTime": true, + "tags": [ + "gateway-api-state" + ], + "targetBlank": false, + "title": "Gateway Dashboards", + "type": "dashboards" + } + ], + "panels": [ + { + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 1, + "title": "TLSPolicy", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "description": "Total number of TLSPolicy across all clusters", + "gridPos": { + "h": 3, + "w": 2, + "x": 0, + "y": 1 + }, + "id": 2, + "pluginVersion": "v10.0.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "expr": "count(gatewayapi_tlspolicy_status)", + "instant": true + } + ], + "title": "Total", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "description": "Total TLSPolicy with an Ready state", + "gridPos": { + "h": 3, + "w": 2, + "x": 2, + "y": 1 + }, + "id": 3, + "pluginVersion": "v10.0.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "expr": "count(gatewayapi_tlspolicy_status{type=\"Ready\"})", + "instant": true + } + ], + "title": "Ready", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "gridPos": { + "h": 6, + "w": 10, + "x": 4, + "y": 1 + }, + "id": 4, + "pluginVersion": "v10.0.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "expr": "gatewayapi_tlspolicy_target_info", + "format": "table", + "instant": true, + "range": false + } + ], + "title": "TLSPolicy", + "transformations": [ + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "name", + "target_kind", + "target_name" + ] + } + } + }, + { + "id": "organize", + "options": { + "renameByName": { + "name": "Name", + "target_kind": "Target Kind", + "target_name": "Target Name" + } + } + } + ], + "type": "table" + }, + { + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 2 + }, + "id": 5, + "title": "RateLimitPolicy", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "description": "Total number of RateLimitPolicy across all clusters", + "gridPos": { + "h": 3, + "w": 2, + "x": 0, + "y": 3 + }, + "id": 6, + "pluginVersion": "v10.0.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "expr": "count(gatewayapi_ratelimitpolicy_status)", + "instant": true + } + ], + "title": "Total", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "description": "Total RateLimitPolicy with an Available state", + "gridPos": { + "h": 3, + "w": 2, + "x": 2, + "y": 3 + }, + "id": 7, + "pluginVersion": "v10.0.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "expr": "count(gatewayapi_ratelimitpolicy_status{type=\"Available\"})", + "instant": true + } + ], + "title": "Available", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "gridPos": { + "h": 6, + "w": 10, + "x": 4, + "y": 7 + }, + "id": 8, + "pluginVersion": "v10.0.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "expr": "gatewayapi_ratelimitpolicy_target_info", + "format": "table", + "instant": true, + "range": false + } + ], + "title": "RateLimitPolicy", + "transformations": [ + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "name", + "target_kind", + "target_name" + ] + } + } + }, + { + "id": "organize", + "options": { + "renameByName": { + "name": "Name", + "target_kind": "Target Kind", + "target_name": "Target Name" + } + } + } + ], + "type": "table" + }, + { + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 8 + }, + "id": 9, + "title": "BackendTLSPolicy", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "gridPos": { + "h": 6, + "w": 10, + "x": 4, + "y": 9 + }, + "id": 10, + "pluginVersion": "v10.0.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "expr": "gatewayapi_backendtlspolicy_target_info", + "format": "table", + "instant": true, + "range": false + } + ], + "title": "BackendTLSPolicy", + "transformations": [ + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "name", + "target_kind", + "target_name" + ] + } + } + }, + { + "id": "organize", + "options": { + "renameByName": { + "name": "Name", + "target_kind": "Target Kind", + "target_name": "Target Name" + } + } + } + ], + "type": "table" + } + ], + "schemaVersion": 36, + "style": "dark", + "tags": [ + "gateway-api", + "gateway-api-state" + ], + "templating": { + "list": [ + { + "label": "Data Source", + "name": "datasource", + "query": "prometheus", + "type": "datasource" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "includeAll": true, + "label": "TLSPolicy", + "multi": true, + "name": "tlspolicy", + "query": { + "query": "label_values(gatewayapi_tlspolicy_created, name)", + "refId": "StandardVariableQuery" + }, + "regex": "/(.*)/", + "type": "query" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "includeAll": true, + "label": "RateLimitPolicy", + "multi": true, + "name": "ratelimitpolicy", + "query": { + "query": "label_values(gatewayapi_ratelimitpolicy_created, name)", + "refId": "StandardVariableQuery" + }, + "regex": "/(.*)/", + "type": "query" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "includeAll": true, + "label": "BackendTLSPolicy", + "multi": true, + "name": "backendtlspolicy", + "query": { + "query": "label_values(gatewayapi_backendtlspolicy_created, name)", + "refId": "StandardVariableQuery" + }, + "regex": "/(.*)/", + "type": "query" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timezone": "utc", + "title": "Gateway API State / Policies", + "uid": "gatewayapipolicies" +} diff --git a/config/examples/dashboards/policies.yaml b/config/examples/dashboards/policies.yaml new file mode 100644 index 0000000..3ee86b6 --- /dev/null +++ b/config/examples/dashboards/policies.yaml @@ -0,0 +1,10 @@ +apiVersion: grafana.integreatly.org/v1beta1 +kind: GrafanaDashboard +metadata: + name: policies +spec: + instanceSelector: + matchLabels: + dashboards: "grafana" + json: > + {"editable":false,"links":[{"asDropdown":false,"includeVars":true,"keepTime":true,"tags":["gateway-api-state"],"targetBlank":false,"title":"Gateway Dashboards","type":"dashboards"}],"panels":[{"gridPos":{"h":1,"w":24,"x":0,"y":0},"id":1,"title":"TLSPolicy","type":"row"},{"datasource":{"type":"prometheus","uid":"$datasource"},"description":"Total number of TLSPolicy across all clusters","gridPos":{"h":3,"w":2,"x":0,"y":1},"id":2,"pluginVersion":"v10.0.0","targets":[{"datasource":{"type":"prometheus","uid":"$datasource"},"expr":"count(gatewayapi_tlspolicy_status)","instant":true}],"title":"Total","type":"stat"},{"datasource":{"type":"prometheus","uid":"$datasource"},"description":"Total TLSPolicy with an Ready state","gridPos":{"h":3,"w":2,"x":2,"y":1},"id":3,"pluginVersion":"v10.0.0","targets":[{"datasource":{"type":"prometheus","uid":"$datasource"},"expr":"count(gatewayapi_tlspolicy_status{type=\"Ready\"})","instant":true}],"title":"Ready","type":"stat"},{"datasource":{"type":"prometheus","uid":"$datasource"},"gridPos":{"h":6,"w":10,"x":4,"y":1},"id":4,"pluginVersion":"v10.0.0","targets":[{"datasource":{"type":"prometheus","uid":"$datasource"},"expr":"gatewayapi_tlspolicy_target_info","format":"table","instant":true,"range":false}],"title":"TLSPolicy","transformations":[{"id":"filterFieldsByName","options":{"include":{"names":["name","target_kind","target_name"]}}},{"id":"organize","options":{"renameByName":{"name":"Name","target_kind":"Target Kind","target_name":"Target Name"}}}],"type":"table"},{"gridPos":{"h":1,"w":24,"x":0,"y":2},"id":5,"title":"RateLimitPolicy","type":"row"},{"datasource":{"type":"prometheus","uid":"$datasource"},"description":"Total number of RateLimitPolicy across all clusters","gridPos":{"h":3,"w":2,"x":0,"y":3},"id":6,"pluginVersion":"v10.0.0","targets":[{"datasource":{"type":"prometheus","uid":"$datasource"},"expr":"count(gatewayapi_ratelimitpolicy_status)","instant":true}],"title":"Total","type":"stat"},{"datasource":{"type":"prometheus","uid":"$datasource"},"description":"Total RateLimitPolicy with an Available state","gridPos":{"h":3,"w":2,"x":2,"y":3},"id":7,"pluginVersion":"v10.0.0","targets":[{"datasource":{"type":"prometheus","uid":"$datasource"},"expr":"count(gatewayapi_ratelimitpolicy_status{type=\"Available\"})","instant":true}],"title":"Available","type":"stat"},{"datasource":{"type":"prometheus","uid":"$datasource"},"gridPos":{"h":6,"w":10,"x":4,"y":7},"id":8,"pluginVersion":"v10.0.0","targets":[{"datasource":{"type":"prometheus","uid":"$datasource"},"expr":"gatewayapi_ratelimitpolicy_target_info","format":"table","instant":true,"range":false}],"title":"RateLimitPolicy","transformations":[{"id":"filterFieldsByName","options":{"include":{"names":["name","target_kind","target_name"]}}},{"id":"organize","options":{"renameByName":{"name":"Name","target_kind":"Target Kind","target_name":"Target Name"}}}],"type":"table"},{"gridPos":{"h":1,"w":24,"x":0,"y":8},"id":9,"title":"BackendTLSPolicy","type":"row"},{"datasource":{"type":"prometheus","uid":"$datasource"},"gridPos":{"h":6,"w":10,"x":4,"y":9},"id":10,"pluginVersion":"v10.0.0","targets":[{"datasource":{"type":"prometheus","uid":"$datasource"},"expr":"gatewayapi_backendtlspolicy_target_info","format":"table","instant":true,"range":false}],"title":"BackendTLSPolicy","transformations":[{"id":"filterFieldsByName","options":{"include":{"names":["name","target_kind","target_name"]}}},{"id":"organize","options":{"renameByName":{"name":"Name","target_kind":"Target Kind","target_name":"Target Name"}}}],"type":"table"}],"schemaVersion":36,"style":"dark","tags":["gateway-api","gateway-api-state"],"templating":{"list":[{"label":"Data Source","name":"datasource","query":"prometheus","type":"datasource"},{"datasource":{"type":"prometheus","uid":"${datasource}"},"includeAll":true,"label":"TLSPolicy","multi":true,"name":"tlspolicy","query":{"query":"label_values(gatewayapi_tlspolicy_created, name)","refId":"StandardVariableQuery"},"regex":"/(.*)/","type":"query"},{"datasource":{"type":"prometheus","uid":"${datasource}"},"includeAll":true,"label":"RateLimitPolicy","multi":true,"name":"ratelimitpolicy","query":{"query":"label_values(gatewayapi_ratelimitpolicy_created, name)","refId":"StandardVariableQuery"},"regex":"/(.*)/","type":"query"},{"datasource":{"type":"prometheus","uid":"${datasource}"},"includeAll":true,"label":"BackendTLSPolicy","multi":true,"name":"backendtlspolicy","query":{"query":"label_values(gatewayapi_backendtlspolicy_created, name)","refId":"StandardVariableQuery"},"regex":"/(.*)/","type":"query"}]},"time":{"from":"now-1h","to":"now"},"timezone":"utc","title":"Gateway API State / Policies","uid":"gatewayapipolicies"} diff --git a/config/examples/enterprise/all.yaml b/config/examples/enterprise/all.yaml index 040412a..045f1ca 100644 --- a/config/examples/enterprise/all.yaml +++ b/config/examples/enterprise/all.yaml @@ -625,6 +625,128 @@ status: - group: gateway.networking.k8s.io kind: GRPCRoute --- +apiVersion: kuadrant.io/v1alpha1 +kind: TLSPolicy +metadata: + name: external + namespace: istio-system +spec: + targetRef: + name: external + group: gateway.networking.k8s.io + kind: Gateway + issuerRef: + group: cert-manager.io + kind: ClusterIssuer + name: selfsigned-cluster-issuer +status: + conditions: + - lastTransitionTime: "2023-08-21T22:53:08Z" + message: Gateway is TLS Enabled + reason: GatewayTLSEnabled + status: "True" + type: Ready +--- +apiVersion: kuadrant.io/v1alpha1 +kind: TLSPolicy +metadata: + name: internal + namespace: istio-system +spec: + targetRef: + name: internal + group: gateway.networking.k8s.io + kind: Gateway + issuerRef: + group: cert-manager.io + kind: ClusterIssuer + name: selfsigned-cluster-issuer +status: + conditions: + - lastTransitionTime: "2023-08-21T22:53:08Z" + message: Gateway is TLS Enabled + reason: GatewayTLSEnabled + status: "True" + type: Ready +--- +apiVersion: kuadrant.io/v1beta2 +kind: RateLimitPolicy +metadata: + name: rlp-www +spec: + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: www + limits: + "global": + rates: + - limit: 5 + duration: 10 + unit: second +status: + conditions: + - lastTransitionTime: "2023-08-21T22:53:08Z" + message: HTTPRoute is ratelimited + reason: HTTPRouteProtected + status: "True" + type: Available +--- +apiVersion: kuadrant.io/v1beta2 +kind: RateLimitPolicy +metadata: + name: rlp-cdn +spec: + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: cdn + limits: + "global": + rates: + - limit: 5 + duration: 10 + unit: second +status: + conditions: + - lastTransitionTime: "2023-08-21T22:53:08Z" + message: HTTPRoute is ratelimited + reason: HTTPRouteProtected + status: "True" + type: Available +--- +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: BackendTLSPolicy +metadata: + name: btp-grafana +spec: + targetRef: + group: "" + kind: Service + name: grafana-service + tls: + caCertRefs: + - group: "" + name: "grafana" + kind: "ConfigMap" + hostname: grafana.example.com +--- +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: BackendTLSPolicy +metadata: + name: btp-kubernetes +spec: + targetRef: + group: "" + kind: Service + name: kubernetes + tls: + caCertRefs: + - group: "" + name: "kubernetes" + kind: "ConfigMap" + hostname: kubernetes.example.com +--- apiVersion: gateway.networking.k8s.io/v1beta1 kind: HTTPRoute metadata: diff --git a/config/examples/kube-prometheus/bundle.yaml b/config/examples/kube-prometheus/bundle.yaml index 31da0c3..01aa0b4 100644 --- a/config/examples/kube-prometheus/bundle.yaml +++ b/config/examples/kube-prometheus/bundle.yaml @@ -490,6 +490,15 @@ rules: - tcproutes - tlsroutes - udproutes + - backendtlspolicies + verbs: + - list + - watch +- apiGroups: + - kuadrant.io + resources: + - tlspolicies + - ratelimitpolicies verbs: - list - watch @@ -1442,6 +1451,156 @@ data: parent_namespace: ["parentRef", "namespace"] parent_section_name: ["parentRef", "sectionName"] parent_port: ["parentRef", "port"] + - groupVersionKind: + group: kuadrant.io + kind: "TLSPolicy" + version: "v1alpha1" + metricNamePrefix: gatewayapi_tlspolicy + labelsFromPath: + name: + - metadata + - name + namespace: + - metadata + - namespace + metrics: + - name: "labels" + help: "Kubernetes labels converted to Prometheus labels." + each: + type: Info + info: + path: [metadata] + labelsFromPath: + "*": [labels] + - name: "created" + help: "created timestamp" + each: + type: Gauge + gauge: + path: [metadata, creationTimestamp] + - name: "deleted" + help: "deletion timestamp" + each: + type: Gauge + gauge: + path: [metadata, deletionTimestamp] + - name: "target_info" + help: "Target references that the tlspolicy wants to be attached to" + each: + type: Info + info: + path: [spec, targetRef] + labelsFromPath: + target_group: ["group"] + target_kind: ["kind"] + target_name: ["name"] + target_namespace: ["namespace"] + - name: "status" + help: "status condition" + each: + type: Gauge + gauge: + path: [status, conditions] + labelsFromPath: + type: ["type"] + valueFrom: ["status"] + - groupVersionKind: + group: kuadrant.io + kind: "RateLimitPolicy" + version: "v1beta2" + metricNamePrefix: gatewayapi_ratelimitpolicy + labelsFromPath: + name: + - metadata + - name + namespace: + - metadata + - namespace + metrics: + - name: "labels" + help: "Kubernetes labels converted to Prometheus labels." + each: + type: Info + info: + path: [metadata] + labelsFromPath: + "*": [labels] + - name: "created" + help: "created timestamp" + each: + type: Gauge + gauge: + path: [metadata, creationTimestamp] + - name: "deleted" + help: "deletion timestamp" + each: + type: Gauge + gauge: + path: [metadata, deletionTimestamp] + - name: "target_info" + help: "Target references that the tlspolicy wants to be attached to" + each: + type: Info + info: + path: [spec, targetRef] + labelsFromPath: + target_group: ["group"] + target_kind: ["kind"] + target_name: ["name"] + target_namespace: ["namespace"] + - name: "status" + help: "status condition" + each: + type: Gauge + gauge: + path: [status, conditions] + labelsFromPath: + type: ["type"] + valueFrom: ["status"] + - groupVersionKind: + group: gateway.networking.k8s.io + kind: "BackendTLSPolicy" + version: "v1alpha2" + metricNamePrefix: gatewayapi_backendtlspolicy + labelsFromPath: + name: + - metadata + - name + namespace: + - metadata + - namespace + metrics: + - name: "labels" + help: "Kubernetes labels converted to Prometheus labels." + each: + type: Info + info: + path: [metadata] + labelsFromPath: + "*": [labels] + - name: "created" + help: "created timestamp" + each: + type: Gauge + gauge: + path: [metadata, creationTimestamp] + - name: "deleted" + help: "deletion timestamp" + each: + type: Gauge + gauge: + path: [metadata, deletionTimestamp] + - name: "target_info" + help: "Target references that the backendtlspolicy wants to be attached to" + each: + type: Info + info: + path: [spec, targetRef] + labelsFromPath: + target_group: ["group"] + target_kind: ["kind"] + target_name: ["name"] + target_namespace: ["namespace"] kind: ConfigMap metadata: name: custom-resource-state @@ -43677,6 +43836,8 @@ spec: name: grafana-tcproutes - mountPath: /grafana-dashboard-definitions/0/grafana-udproutes name: grafana-udproutes + - mountPath: /grafana-dashboard-definitions/0/grafana-tlspolicy + name: grafana-tlspolicy nodeSelector: kubernetes.io/os: linux securityContext: @@ -43791,6 +43952,10 @@ spec: defaultMode: 420 name: grafana-tlsroutes-fg5726f7k9 name: grafana-tlsroutes + - configMap: + defaultMode: 420 + name: grafana-tlspolicy + name: grafana-tlspolicy - configMap: defaultMode: 420 name: grafana-tcproutes-d7tt7t272g diff --git a/config/examples/kube-prometheus/grafana_deployment_patch.yaml b/config/examples/kube-prometheus/grafana_deployment_patch.yaml index 5d3a5ea..f773ae2 100644 --- a/config/examples/kube-prometheus/grafana_deployment_patch.yaml +++ b/config/examples/kube-prometheus/grafana_deployment_patch.yaml @@ -33,6 +33,13 @@ configMap: defaultMode: 420 name: grafana-tlsroutes +- op: add + path: /spec/template/spec/volumes/- + value: + name: grafana-tlspolicy + configMap: + defaultMode: 420 + name: grafana-tlspolicy - op: add path: /spec/template/spec/volumes/- value: @@ -82,3 +89,8 @@ value: name: grafana-udproutes mountPath: /grafana-dashboard-definitions/0/grafana-udproutes +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + name: grafana-tlspolicy + mountPath: /grafana-dashboard-definitions/0/grafana-tlspolicy diff --git a/config/examples/kube-prometheus/ksm_clusterrole_patch.yaml b/config/examples/kube-prometheus/ksm_clusterrole_patch.yaml index 93995b8..0f7a09b 100644 --- a/config/examples/kube-prometheus/ksm_clusterrole_patch.yaml +++ b/config/examples/kube-prometheus/ksm_clusterrole_patch.yaml @@ -21,6 +21,18 @@ - tcproutes - tlsroutes - udproutes + - backendtlspolicies + verbs: + - list + - watch +- op: add + path: /rules/- + value: + apiGroups: + - "kuadrant.io" + resources: + - tlspolicies + - ratelimitpolicies verbs: - list - watch diff --git a/config/examples/kube-state-metrics/cluster-role.yaml b/config/examples/kube-state-metrics/cluster-role.yaml index 40f6a0f..9be9447 100644 --- a/config/examples/kube-state-metrics/cluster-role.yaml +++ b/config/examples/kube-state-metrics/cluster-role.yaml @@ -143,6 +143,15 @@ rules: - tcproutes - tlsroutes - udproutes + - backendtlspolicies + verbs: + - list + - watch +- apiGroups: + - "kuadrant.io" + resources: + - tlspolicies + - ratelimitpolicies verbs: - list - watch diff --git a/config/gateway-api/crd/standard/gateway.networking.k8s.io_backendtlspolicies.yaml b/config/gateway-api/crd/standard/gateway.networking.k8s.io_backendtlspolicies.yaml new file mode 100644 index 0000000..c617f00 --- /dev/null +++ b/config/gateway-api/crd/standard/gateway.networking.k8s.io_backendtlspolicies.yaml @@ -0,0 +1,481 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: https://github.com/kubernetes-sigs/gateway-api/pull/2466 + gateway.networking.k8s.io/bundle-version: v0.8.0 + gateway.networking.k8s.io/channel: experimental + creationTimestamp: null + labels: + gateway.networking.k8s.io/policy: Direct + name: backendtlspolicies.gateway.networking.k8s.io +spec: + group: gateway.networking.k8s.io + names: + categories: + - gateway-api + kind: BackendTLSPolicy + listKind: BackendTLSPolicyList + plural: backendtlspolicies + shortNames: + - btlspolicy + singular: backendtlspolicy + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha2 + schema: + openAPIV3Schema: + description: BackendTLSPolicy provides a way to configure how a Gateway connects + to a Backend via TLS. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of BackendTLSPolicy. + properties: + targetRef: + description: "TargetRef identifies an API object to apply the policy + to. Only Services have Extended support. Implementations MAY support + additional objects, with Implementation Specific support. Note that + this config applies to the entire referenced resource by default, + but this default may change in the future to provide a more granular + application of the policy. \n Support: Extended for Kubernetes Service + \n Support: Implementation-specific for any other resource" + properties: + group: + description: Group is the group of the target resource. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the target resource. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the target resource. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: Namespace is the namespace of the referent. When + unspecified, the local namespace is inferred. Even when policy + targets a resource in a different namespace, it MUST only apply + to traffic originating from the same namespace as the policy. + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + sectionName: + description: "SectionName is the name of a section within the + target resource. When unspecified, this targetRef targets the + entire resource. In the following resources, SectionName is + interpreted as the following: \n * Gateway: Listener Name * + Service: Port Name \n If a SectionName is specified, but does + not exist on the targeted object, the Policy must fail to attach, + and the policy implementation should record a `ResolvedRefs` + or similar Condition in the Policy's status." + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - group + - kind + - name + type: object + tls: + description: TLS contains backend TLS policy configuration. + properties: + caCertRefs: + description: "CACertRefs contains one or more references to Kubernetes + objects that contain a PEM-encoded TLS CA certificate bundle, + which is used to validate a TLS handshake between the Gateway + and backend Pod. \n If CACertRefs is empty or unspecified, then + WellKnownCACerts must be specified. Only one of CACertRefs or + WellKnownCACerts may be specified, not both. If CACertRefs is + empty or unspecified, the configuration for WellKnownCACerts + MUST be honored instead. \n References to a resource in a different + namespace are invalid for the moment, although we will revisit + this in the future. \n A single CACertRef to a Kubernetes ConfigMap + kind has \"Core\" support. Implementations MAY choose to support + attaching multiple certificates to a backend, but this behavior + is implementation-specific. \n Support: Core - An optional single + reference to a Kubernetes ConfigMap, with the CA certificate + in a key named `ca.crt`. \n Support: Implementation-specific + (More than one reference, or other kinds of resources)." + items: + description: "LocalObjectReference identifies an API object + within the namespace of the referrer. The API object must + be valid in the cluster; the Group and Kind must be registered + in the cluster for this reference to be valid. \n References + to objects with invalid Group and Kind are not valid, and + must be rejected by the implementation, with appropriate Conditions + set on the containing object." + properties: + group: + description: Group is the group of the referent. For example, + "gateway.networking.k8s.io". When unspecified or empty + string, core API group is inferred. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the referent. For example "HTTPRoute" + or "Service". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + maxItems: 8 + type: array + hostname: + description: "Hostname is used for two purposes in the connection + between Gateways and backends: \n 1. Hostname MUST be used as + the SNI to connect to the backend (RFC 6066). 2. Hostname MUST + be used for authentication and MUST match the certificate served + by the matching backend. \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + wellKnownCACerts: + description: "WellKnownCACerts specifies whether system CA certificates + may be used in the TLS handshake between the gateway and backend + pod. \n If WellKnownCACerts is unspecified or empty (\"\"), + then CACertRefs must be specified with at least one entry for + a valid configuration. Only one of CACertRefs or WellKnownCACerts + may be specified, not both. \n Support: Core for \"System\"" + enum: + - System + type: string + required: + - hostname + type: object + x-kubernetes-validations: + - message: must not contain both CACertRefs and WellKnownCACerts + rule: '!(has(self.caCertRefs) && size(self.caCertRefs) > 0 && has(self.wellKnownCACerts) + && self.wellKnownCACerts != "")' + - message: must specify either CACertRefs or WellKnownCACerts + rule: '(has(self.caCertRefs) && size(self.caCertRefs) > 0 || has(self.wellKnownCACerts) + && self.wellKnownCACerts != "")' + required: + - targetRef + - tls + type: object + status: + description: Status defines the current state of BackendTLSPolicy. + properties: + ancestors: + description: "Ancestors is a list of ancestor resources (usually Gateways) + that are associated with the policy, and the status of the policy + with respect to each ancestor. When this policy attaches to a parent, + the controller that manages the parent and the ancestors MUST add + an entry to this list when the controller first sees the policy + and SHOULD update the entry as appropriate when the relevant ancestor + is modified. \n Note that choosing the relevant ancestor is left + to the Policy designers; an important part of Policy design is designing + the right object level at which to namespace this status. \n Note + also that implementations MUST ONLY populate ancestor status for + the Ancestor resources they are responsible for. Implementations + MUST use the ControllerName field to uniquely identify the entries + in this list that they are responsible for. \n Note that to achieve + this, the list of PolicyAncestorStatus structs MUST be treated as + a map with a composite key, made up of the AncestorRef and ControllerName + fields combined. \n A maximum of 16 ancestors will be represented + in this list. An empty list means the Policy is not relevant for + any ancestors. \n If this slice is full, implementations MUST NOT + add further entries. Instead they MUST consider the policy unimplementable + and signal that on any related resources such as the ancestor that + would be referenced here. For example, if this list was full on + BackendTLSPolicy, no additional Gateways would be able to reference + the Service targeted by the BackendTLSPolicy." + items: + description: "PolicyAncestorStatus describes the status of a route + with respect to an associated Ancestor. \n Ancestors refer to + objects that are either the Target of a policy or above it in + terms of object hierarchy. For example, if a policy targets a + Service, the Policy's Ancestors are, in order, the Service, the + HTTPRoute, the Gateway, and the GatewayClass. Almost always, in + this hierarchy, the Gateway will be the most useful object to + place Policy status on, so we recommend that implementations SHOULD + use Gateway as the PolicyAncestorStatus object unless the designers + have a _very_ good reason otherwise. \n In the context of policy + attachment, the Ancestor is used to distinguish which resource + results in a distinct application of this policy. For example, + if a policy targets a Service, it may have a distinct result per + attached Gateway. \n Policies targeting the same resource may + have different effects depending on the ancestors of those resources. + For example, different Gateways targeting the same Service may + have different capabilities, especially if they have different + underlying implementations. \n For example, in BackendTLSPolicy, + the Policy attaches to a Service that is used as a backend in + a HTTPRoute that is itself attached to a Gateway. In this case, + the relevant object for status is the Gateway, and that is the + ancestor object referred to in this status. \n Note that a parent + is also an ancestor, so for objects where the parent is the relevant + object for status, this struct SHOULD still be used. \n This struct + is intended to be used in a slice that's effectively a map, with + a composite key made up of the AncestorRef and the ControllerName." + properties: + ancestorRef: + description: AncestorRef corresponds with a ParentRef in the + spec that this PolicyAncestorStatus struct describes the status + of. + properties: + group: + default: gateway.networking.k8s.io + description: "Group is the group of the referent. When unspecified, + \"gateway.networking.k8s.io\" is inferred. To set the + core API group (such as for a \"Service\" kind referent), + Group must be explicitly set to \"\" (empty string). \n + Support: Core" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: "Kind is kind of the referent. \n There are + two kinds of parent resources with \"Core\" support: \n + * Gateway (Gateway conformance profile) * Service (Mesh + conformance profile, experimental, ClusterIP Services + only) \n Support for other resources is Implementation-Specific." + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: "Name is the name of the referent. \n Support: + Core" + maxLength: 253 + minLength: 1 + type: string + namespace: + description: "Namespace is the namespace of the referent. + When unspecified, this refers to the local namespace of + the Route. \n Note that there are specific rules for ParentRefs + which cross namespace boundaries. Cross-namespace references + are only valid if they are explicitly allowed by something + in the namespace they are referring to. For example: Gateway + has the AllowedRoutes field, and ReferenceGrant provides + a generic way to enable any other kind of cross-namespace + reference. \n ParentRefs from a Route to a Service in + the same namespace are \"producer\" routes, which apply + default routing rules to inbound connections from any + namespace to the Service. \n ParentRefs from a Route to + a Service in a different namespace are \"consumer\" routes, + and these routing rules are only applied to outbound connections + originating from the same namespace as the Route, for + which the intended destination of the connections are + a Service targeted as a ParentRef of the Route. \n Support: + Core" + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + description: "Port is the network port this Route targets. + It can be interpreted differently based on the type of + parent resource. \n When the parent resource is a Gateway, + this targets all listeners listening on the specified + port that also support this kind of Route(and select this + Route). It's not recommended to set `Port` unless the + networking behaviors specified in a Route must apply to + a specific port as opposed to a listener(s) whose port(s) + may be changed. When both Port and SectionName are specified, + the name and port of the selected listener must match + both specified values. \n When the parent resource is + a Service, this targets a specific port in the Service + spec. When both Port (experimental) and SectionName are + specified, the name and port of the selected port must + match both specified values. \n Implementations MAY choose + to support other parent resources. Implementations supporting + other types of parent resources MUST clearly document + how/if Port is interpreted. \n For the purpose of status, + an attachment is considered successful as long as the + parent resource accepts it partially. For example, Gateway + listeners can restrict which Routes can attach to them + by Route kind, namespace, or hostname. If 1 of 2 Gateway + listeners accept attachment from the referencing Route, + the Route MUST be considered successfully attached. If + no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + \n Support: Extended \n " + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + description: "SectionName is the name of a section within + the target resource. In the following resources, SectionName + is interpreted as the following: \n * Gateway: Listener + Name. When both Port (experimental) and SectionName are + specified, the name and port of the selected listener + must match both specified values. * Service: Port Name. + When both Port (experimental) and SectionName are specified, + the name and port of the selected listener must match + both specified values. Note that attaching Routes to Services + as Parents is part of experimental Mesh support and is + not supported for any other purpose. \n Implementations + MAY choose to support attaching Routes to other resources. + If that is the case, they MUST clearly document how SectionName + is interpreted. \n When unspecified (empty string), this + will reference the entire resource. For the purpose of + status, an attachment is considered successful if at least + one section in the parent resource accepts it. For example, + Gateway listeners can restrict which Routes can attach + to them by Route kind, namespace, or hostname. If 1 of + 2 Gateway listeners accept attachment from the referencing + Route, the Route MUST be considered successfully attached. + If no Gateway listeners accept attachment from this Route, + the Route MUST be considered detached from the Gateway. + \n Support: Core" + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + conditions: + description: Conditions describes the status of the Policy with + respect to the given Ancestor. + items: + description: "Condition contains details for one aspect of + the current state of this API Resource. --- This struct + is intended for direct use as an array at the field path + .status.conditions. For example, \n type FooStatus struct{ + // Represents the observations of a foo's current state. + // Known .status.conditions.type are: \"Available\", \"Progressing\", + and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields + }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should + be when the underlying condition changed. If that is + not known, then using the time when the API field changed + is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, + if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the + current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier + indicating the reason for the condition's last transition. + Producers of specific condition types may define expected + values and meanings for this field, and whether the + values are considered a guaranteed API. The value should + be a CamelCase string. This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, + Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across + resources like Available, but because arbitrary conditions + can be useful (see .node.status.conditions), the ability + to deconflict is important. The regex it matches is + (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + controllerName: + description: "ControllerName is a domain/path string that indicates + the name of the controller that wrote this status. This corresponds + with the controllerName field on GatewayClass. \n Example: + \"example.net/gateway-controller\". \n The format of this + field is DOMAIN \"/\" PATH, where DOMAIN and PATH are valid + Kubernetes names (https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names). + \n Controllers MUST populate this field when writing status. + Controllers should ensure that entries to status populated + with their ControllerName are cleaned up when they are no + longer necessary." + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*\/[A-Za-z0-9\/\-._~%!$&'()*+,;=:]+$ + type: string + required: + - ancestorRef + - controllerName + type: object + maxItems: 16 + type: array + required: + - ancestors + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null diff --git a/config/gateway-api/crd/standard/kuadrant.io_ratelimitpolicies.yaml b/config/gateway-api/crd/standard/kuadrant.io_ratelimitpolicies.yaml new file mode 100644 index 0000000..a5c6b16 --- /dev/null +++ b/config/gateway-api/crd/standard/kuadrant.io_ratelimitpolicies.yaml @@ -0,0 +1,397 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.10.0 + creationTimestamp: null + name: ratelimitpolicies.kuadrant.io +spec: + group: kuadrant.io + names: + kind: RateLimitPolicy + listKind: RateLimitPolicyList + plural: ratelimitpolicies + singular: ratelimitpolicy + scope: Namespaced + versions: + - name: v1beta2 + schema: + openAPIV3Schema: + description: RateLimitPolicy is the Schema for the ratelimitpolicies API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: RateLimitPolicySpec defines the desired state of RateLimitPolicy + properties: + limits: + additionalProperties: + description: Limit represents a complete rate limit configuration + properties: + counters: + description: Counters defines additional rate limit counters + based on context qualifiers and well known selectors TODO + Document properly "Well-known selector" https://github.com/Kuadrant/architecture/blob/main/rfcs/0001-rlp-v2.md#well-known-selectors + items: + description: 'ContextSelector defines one item from the well + known attributes Attributes: https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/advanced/attributes + Well-known selectors: https://github.com/Kuadrant/architecture/blob/main/rfcs/0001-rlp-v2.md#well-known-selectors + They are named by a dot-separated path (e.g. request.path) + Example: "request.path" -> The path portion of the URL' + maxLength: 253 + minLength: 1 + type: string + type: array + rates: + description: Rates holds the list of limit rates + items: + description: Rate defines the actual rate limit that will + be used when there is a match + properties: + duration: + description: Duration defines the time period for which + the Limit specified above applies. + type: integer + limit: + description: Limit defines the max value allowed for a + given period of time + type: integer + unit: + description: 'Duration defines the time uni Possible values + are: "second", "minute", "hour", "day"' + enum: + - second + - minute + - hour + - day + type: string + required: + - duration + - limit + - unit + type: object + type: array + routeSelectors: + description: RouteSelectors defines semantics for matching an + HTTP request based on conditions + items: + description: RouteSelector defines semantics for matching + an HTTP request based on conditions https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1beta1.HTTPRouteSpec + properties: + hostnames: + description: Hostnames defines a set of hostname that + should match against the HTTP Host header to select + a HTTPRoute to process the request https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1beta1.HTTPRouteSpec + items: + description: "Hostname is the fully qualified domain + name of a network host. This matches the RFC 1123 + definition of a hostname with 2 notable exceptions: + \n 1. IPs are not allowed. 2. A hostname may be prefixed + with a wildcard label (`*.`). The wildcard label must + appear by itself as the first label. \n Hostname can + be \"precise\" which is a domain name without the + terminating dot of a network host (e.g. \"foo.example.com\") + or \"wildcard\", which is a domain name prefixed with + a single wildcard label (e.g. `*.example.com`). \n + Note that as per RFC1035 and RFC1123, a *label* must + consist of lower case alphanumeric characters or '-', + and must start and end with an alphanumeric character. + No other punctuation is allowed." + type: string + type: array + matches: + description: Matches define conditions used for matching + the rule against incoming HTTP requests. https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1beta1.HTTPRouteSpec + items: + description: "HTTPRouteMatch defines the predicate used + to match requests to a given action. Multiple match + types are ANDed together, i.e. the match will evaluate + to true only if all conditions are satisfied. \n For + example, the match below will match a HTTP request + only if its path starts with `/foo` AND it contains + the `version: v1` header: \n ``` match: \n path: value: + \"/foo\" headers: - name: \"version\" value \"v1\" + \n ```" + properties: + headers: + description: Headers specifies HTTP request header + matchers. Multiple match values are ANDed together, + meaning, a request must match all the specified + headers to select the route. + items: + description: HTTPHeaderMatch describes how to + select a HTTP route by matching HTTP request + headers. + properties: + name: + description: "Name is the name of the HTTP + Header to be matched. Name matching MUST + be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). + \n If multiple entries specify equivalent + header names, only the first entry with + an equivalent name MUST be considered for + a match. Subsequent entries with an equivalent + header name MUST be ignored. Due to the + case-insensitivity of header names, \"foo\" + and \"Foo\" are considered equivalent. \n + When a header is repeated in an HTTP request, + it is implementation-specific behavior as + to how this is represented. Generally, proxies + should follow the guidance from the RFC: + https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 + regarding processing a repeated header, + with special handling for \"Set-Cookie\"." + type: string + type: + description: "Type specifies how to match + against the value of the header. \n Support: + Core (Exact) \n Support: Implementation-specific + (RegularExpression) \n Since RegularExpression + HeaderMatchType has implementation-specific + conformance, implementations can support + POSIX, PCRE or any other dialects of regular + expressions. Please read the implementation's + documentation to determine the supported + dialect." + type: string + value: + description: Value is the value of HTTP Header + to be matched. + type: string + required: + - name + - value + type: object + type: array + method: + description: "Method specifies HTTP method matcher. + When specified, this route will be matched only + if the request has the specified method. \n Support: + Extended" + type: string + path: + description: Path specifies a HTTP request path + matcher. If this field is not specified, a default + prefix match on the "/" path is provided. + properties: + type: + description: "Type specifies how to match against + the path Value. \n Support: Core (Exact, PathPrefix) + \n Support: Implementation-specific (RegularExpression)" + type: string + value: + description: Value of the HTTP path to match + against. + type: string + type: object + queryParams: + description: "QueryParams specifies HTTP query parameter + matchers. Multiple match values are ANDed together, + meaning, a request must match all the specified + query parameters to select the route. \n Support: + Extended" + items: + description: HTTPQueryParamMatch describes how + to select a HTTP route by matching HTTP query + parameters. + properties: + name: + description: "Name is the name of the HTTP + query param to be matched. This must be + an exact string match. (See https://tools.ietf.org/html/rfc7230#section-2.7.3). + \n If multiple entries specify equivalent + query param names, only the first entry + with an equivalent name MUST be considered + for a match. Subsequent entries with an + equivalent query param name MUST be ignored. + \n If a query param is repeated in an HTTP + request, the behavior is purposely left + undefined, since different data planes have + different capabilities. However, it is *recommended* + that implementations should match against + the first value of the param if the data + plane supports it, as this behavior is expected + in other load balancing contexts outside + of the Gateway API. \n Users SHOULD NOT + route traffic based on repeated query params + to guard themselves against potential differences + in the implementations." + type: string + type: + description: "Type specifies how to match + against the value of the query parameter. + \n Support: Extended (Exact) \n Support: + Implementation-specific (RegularExpression) + \n Since RegularExpression QueryParamMatchType + has Implementation-specific conformance, + implementations can support POSIX, PCRE + or any other dialects of regular expressions. + Please read the implementation's documentation + to determine the supported dialect." + type: string + value: + description: Value is the value of HTTP query + param to be matched. + type: string + required: + - name + - value + type: object + type: array + type: object + type: array + type: object + type: array + when: + description: When holds the list of conditions for the policy + to be enforced. Called also "soft" conditions as route selectors + must also match + items: + description: RouteSelector defines semantics for matching + an HTTP request based on conditions https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1beta1.HTTPRouteSpec + properties: + operator: + description: 'The binary operator to be applied to the + content fetched from the selector Possible values are: + "eq" (equal to), "neq" (not equal to)' + enum: + - eq + - neq + - startswith + - endswith + - incl + - excl + - matches + type: string + selector: + description: Selector defines one item from the well known + selectors TODO Document properly "Well-known selector" + https://github.com/Kuadrant/architecture/blob/main/rfcs/0001-rlp-v2.md#well-known-selectors + maxLength: 253 + minLength: 1 + type: string + value: + description: The value of reference for the comparison. + type: string + required: + - operator + - selector + - value + type: object + type: array + type: object + description: Limits holds the struct of limits indexed by a unique + name + type: object + targetRef: + description: TargetRef identifies an API object to apply policy to. + properties: + group: + description: Group is the group of the target resource. + type: string + kind: + description: Kind is kind of the target resource. + type: string + name: + description: Name is the name of the target resource. + type: string + namespace: + description: Namespace is the namespace of the referent. When + unspecified, the local namespace is inferred. Even when policy + targets a resource in a different namespace, it MUST only apply + to traffic originating from the same namespace as the policy. + type: string + required: + - group + - kind + - name + type: object + required: + - targetRef + type: object + status: + description: RateLimitPolicyStatus defines the observed state of RateLimitPolicy + properties: + conditions: + description: 'Represents the observations of a foo''s current state. + Known .status.conditions.type are: "Available"' + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + type: string + status: + description: status of the condition, one of True, False, Unknown. + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + observedGeneration: + description: ObservedGeneration reflects the generation of the most + recently observed spec. + format: int64 + type: integer + type: object + type: object + served: true + storage: true + subresources: + status: {} \ No newline at end of file diff --git a/config/gateway-api/crd/standard/kuadrant.io_tlspolicies.yaml b/config/gateway-api/crd/standard/kuadrant.io_tlspolicies.yaml new file mode 100644 index 0000000..0b55aa1 --- /dev/null +++ b/config/gateway-api/crd/standard/kuadrant.io_tlspolicies.yaml @@ -0,0 +1,313 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.10.0 + gateway.networking.k8s.io/policy: direct + creationTimestamp: null + name: tlspolicies.kuadrant.io +spec: + group: kuadrant.io + names: + kind: TLSPolicy + listKind: TLSPolicyList + plural: tlspolicies + singular: tlspolicy + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: TLSPolicy ready. + jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: TLSPolicy is the Schema for the tlspolicies API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: TLSPolicySpec defines the desired state of TLSPolicy + properties: + commonName: + description: 'CommonName is a common name to be used on the Certificate. + The CommonName should have a length of 64 characters or fewer to + avoid generating invalid CSRs. This value is ignored by TLS clients + when any subject alt name is set. This is x509 behaviour: https://tools.ietf.org/html/rfc6125#section-6.4.4' + type: string + duration: + description: The requested 'duration' (i.e. lifetime) of the Certificate. + This option may be ignored/overridden by some issuer types. If unset + this defaults to 90 days. Certificate will be renewed either 2/3 + through its duration or `renewBefore` period before its expiry, + whichever is later. Minimum accepted duration is 1 hour. Value must + be in units accepted by Go time.ParseDuration https://golang.org/pkg/time/#ParseDuration + type: string + issuerRef: + description: IssuerRef is a reference to the issuer for this certificate. + If the `kind` field is not set, or set to `Issuer`, an Issuer resource + with the given name in the same namespace as the Certificate will + be used. If the `kind` field is set to `ClusterIssuer`, a ClusterIssuer + with the provided name will be used. The `name` field in this stanza + is required at all times. + properties: + group: + description: Group of the resource being referred to. + type: string + kind: + description: Kind of the resource being referred to. + type: string + name: + description: Name of the resource being referred to. + type: string + required: + - name + type: object + privateKey: + description: Options to control private keys used for the Certificate. + properties: + algorithm: + description: Algorithm is the private key algorithm of the corresponding + private key for this certificate. If provided, allowed values + are either `RSA`,`Ed25519` or `ECDSA` If `algorithm` is specified + and `size` is not provided, key size of 256 will be used for + `ECDSA` key algorithm and key size of 2048 will be used for + `RSA` key algorithm. key size is ignored when using the `Ed25519` + key algorithm. + enum: + - RSA + - ECDSA + - Ed25519 + type: string + encoding: + description: The private key cryptography standards (PKCS) encoding + for this certificate's private key to be encoded in. If provided, + allowed values are `PKCS1` and `PKCS8` standing for PKCS#1 and + PKCS#8, respectively. Defaults to `PKCS1` if not specified. + enum: + - PKCS1 + - PKCS8 + type: string + rotationPolicy: + description: RotationPolicy controls how private keys should be + regenerated when a re-issuance is being processed. If set to + Never, a private key will only be generated if one does not + already exist in the target `spec.secretName`. If one does exists + but it does not have the correct algorithm or size, a warning + will be raised to await user intervention. If set to Always, + a private key matching the specified requirements will be generated + whenever a re-issuance occurs. Default is 'Never' for backward + compatibility. + type: string + size: + description: Size is the key bit size of the corresponding private + key for this certificate. If `algorithm` is set to `RSA`, valid + values are `2048`, `4096` or `8192`, and will default to `2048` + if not specified. If `algorithm` is set to `ECDSA`, valid values + are `256`, `384` or `521`, and will default to `256` if not + specified. If `algorithm` is set to `Ed25519`, Size is ignored. + No other values are allowed. + type: integer + type: object + renewBefore: + description: How long before the currently issued certificate's expiry + cert-manager should renew the certificate. The default is 2/3 of + the issued certificate's duration. Minimum accepted value is 5 minutes. + Value must be in units accepted by Go time.ParseDuration https://golang.org/pkg/time/#ParseDuration + type: string + revisionHistoryLimit: + description: RevisionHistoryLimit is the maximum number of CertificateRequest + revisions that are maintained in the Certificate's history. Each + revision represents a single `CertificateRequest` created by this + Certificate, either when it was created, renewed, or Spec was changed. + Revisions will be removed by oldest first if the number of revisions + exceeds this number. If set, revisionHistoryLimit must be a value + of `1` or greater. If unset (`nil`), revisions will not be garbage + collected. Default value is `nil`. + format: int32 + type: integer + targetRef: + description: PolicyTargetReference identifies an API object to apply + policy to. This should be used as part of Policy resources that + can target Gateway API resources. For more information on how this + policy attachment model works, and a sample Policy resource, refer + to the policy attachment documentation for Gateway API. + properties: + group: + description: Group is the group of the target resource. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the target resource. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the target resource. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: Namespace is the namespace of the referent. When + unspecified, the local namespace is inferred. Even when policy + targets a resource in a different namespace, it MUST only apply + to traffic originating from the same namespace as the policy. + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - group + - kind + - name + type: object + usages: + description: Usages is the set of x509 usages that are requested for + the certificate. Defaults to `digital signature` and `key encipherment` + if not specified. + items: + description: 'KeyUsage specifies valid usage contexts for keys. + See: https://tools.ietf.org/html/rfc5280#section-4.2.1.3 https://tools.ietf.org/html/rfc5280#section-4.2.1.12 + Valid KeyUsage values are as follows: "signing", "digital signature", + "content commitment", "key encipherment", "key agreement", "data + encipherment", "cert sign", "crl sign", "encipher only", "decipher + only", "any", "server auth", "client auth", "code signing", "email + protection", "s/mime", "ipsec end system", "ipsec tunnel", "ipsec + user", "timestamping", "ocsp signing", "microsoft sgc", "netscape + sgc"' + enum: + - signing + - digital signature + - content commitment + - key encipherment + - key agreement + - data encipherment + - cert sign + - crl sign + - encipher only + - decipher only + - any + - server auth + - client auth + - code signing + - email protection + - s/mime + - ipsec end system + - ipsec tunnel + - ipsec user + - timestamping + - ocsp signing + - microsoft sgc + - netscape sgc + type: string + type: array + required: + - issuerRef + - targetRef + type: object + status: + description: TLSPolicyStatus defines the observed state of TLSPolicy + properties: + conditions: + description: "conditions are any conditions associated with the policy + \n If configuring the policy fails, the \"Failed\" condition will + be set with a reason and message describing the cause of the failure." + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + observedGeneration: + description: observedGeneration is the most recently observed generation + of the TLSPolicy. When the TLSPolicy is updated, the controller + updates the corresponding configuration. If an update fails, that + failure is recorded in the status condition + format: int64 + type: integer + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null diff --git a/config/gateway-api/kustomization.yaml b/config/gateway-api/kustomization.yaml index bf91648..3649661 100644 --- a/config/gateway-api/kustomization.yaml +++ b/config/gateway-api/kustomization.yaml @@ -6,4 +6,5 @@ resources: - crd/standard/gateway.networking.k8s.io_tcproutes.yaml - crd/standard/gateway.networking.k8s.io_tlsroutes.yaml - crd/standard/gateway.networking.k8s.io_udproutes.yaml +- crd/standart/gateway.networking.k8s.io_backendtlspolicies.yaml # From https://github.com/kubernetes-sigs/gateway-api/blob/v0.6.2/config/crd/kustomization.yaml \ No newline at end of file diff --git a/src/dashboards/lib/gwapi/gwapi.libsonnet b/src/dashboards/lib/gwapi/gwapi.libsonnet index 07c696c..3c13685 100644 --- a/src/dashboards/lib/gwapi/gwapi.libsonnet +++ b/src/dashboards/lib/gwapi/gwapi.libsonnet @@ -277,4 +277,27 @@ local var = import './variables.libsonnet'; }, }), ]), + + policyPanel(title, h, w, x, y, expr): + self.table(title, h, w, x, y, expr) + + g.panel.table.queryOptions.withTransformations([ + g.panel.table.transformation.withId('filterFieldsByName') + + g.panel.table.transformation.withOptions({ + include: { + names: [ + 'name', + 'target_kind', + 'target_name', + ], + }, + }), + g.panel.table.transformation.withId('organize') + + g.panel.table.transformation.withOptions({ + renameByName: { + name: 'Name', + target_kind: 'Target Kind', + target_name: 'Target Name', + }, + }), + ]), } \ No newline at end of file diff --git a/src/dashboards/policies.jsonnet b/src/dashboards/policies.jsonnet new file mode 100644 index 0000000..85d5042 --- /dev/null +++ b/src/dashboards/policies.jsonnet @@ -0,0 +1,21 @@ +local g = import 'lib/g.libsonnet'; +local gwapi = import 'lib/gwapi/gwapi.libsonnet'; +local var = import 'lib/gwapi/variables.libsonnet'; + +gwapi.dashboard('Policies', 'gatewayapipolicies', [ + var.routes('tlspolicy', 'TLSPolicy'), + var.routes('ratelimitpolicy', 'RateLimitPolicy'), + var.routes('backendtlspolicy', 'BackendTLSPolicy') +]) ++ g.dashboard.withPanels([ + gwapi.row('TLSPolicy', 1, 24, 0, 0), + gwapi.stat('Total', 3, 2, 0, 1, 'Total number of TLSPolicy across all clusters', 'count(gatewayapi_tlspolicy_status)'), + gwapi.stat('Ready', 3, 2, 2, 1, 'Total TLSPolicy with an Ready state', 'count(gatewayapi_tlspolicy_status{type="Ready"})'), + gwapi.policyPanel('TLSPolicy',6,10,4,1,'gatewayapi_tlspolicy_target_info'), + gwapi.row('RateLimitPolicy', 1, 24, 0, 2), + gwapi.stat('Total', 3, 2, 0, 3, 'Total number of RateLimitPolicy across all clusters', 'count(gatewayapi_ratelimitpolicy_status)'), + gwapi.stat('Available', 3, 2, 2, 3, 'Total RateLimitPolicy with an Available state', 'count(gatewayapi_ratelimitpolicy_status{type="Available"})'), + gwapi.policyPanel('RateLimitPolicy',6,10,4,7,'gatewayapi_ratelimitpolicy_target_info'), + gwapi.row('BackendTLSPolicy', 1, 24, 0, 8), + gwapi.policyPanel('BackendTLSPolicy',6,10,4,9,'gatewayapi_backendtlspolicy_target_info'), +]) \ No newline at end of file From bdb9d69510848ffdfbe7cdb740294d24c30beec4 Mon Sep 17 00:00:00 2001 From: Ignas Baranauskas Date: Thu, 12 Oct 2023 14:07:26 +0100 Subject: [PATCH 2/5] Updated test for the new metrics --- tests/e2e.sh | 3 + tests/e2e/main_test.go | 107 +++++++++++++++++++++ tests/manifests/testbackendtlspolicy1.yaml | 15 +++ tests/manifests/testratelimitpolicy.yaml | 22 +++++ tests/manifests/testtlspolicy.yaml | 21 ++++ 5 files changed, 168 insertions(+) create mode 100644 tests/manifests/testbackendtlspolicy1.yaml create mode 100644 tests/manifests/testratelimitpolicy.yaml create mode 100644 tests/manifests/testtlspolicy.yaml diff --git a/tests/e2e.sh b/tests/e2e.sh index 4d1497d..6139049 100755 --- a/tests/e2e.sh +++ b/tests/e2e.sh @@ -130,6 +130,7 @@ trap finish EXIT # create Gateway API CRDs kubectl create -f ./config/gateway-api/crd/standard/ +kubectl create -f ./config/kuadrant/crd/ # create gateway-api customresourcestatemetrics configmap kubectl create configmap custom-resource-state --from-file=./config/default/custom-resource-state.yaml --dry-run=client -o yaml | kubectl -n kube-system apply -f - @@ -144,6 +145,8 @@ kubectl create -f ./config/examples/kube-state-metrics/deployment.yaml kubectl create -f ./config/examples/kube-state-metrics/service.yaml +kubectl patch clusterrole kube-state-metrics --type=json -p "$(cat ./config/kuadrant/clusterrole-patch.yaml)" + # Create test Gateway API resources kubectl create -f ./tests/manifests/ # Set statuses as well to mock different controller behaviour diff --git a/tests/e2e/main_test.go b/tests/e2e/main_test.go index 75d930b..31a70fc 100644 --- a/tests/e2e/main_test.go +++ b/tests/e2e/main_test.go @@ -86,6 +86,9 @@ func TestGatewayMetricsAvailable(t *testing.T) { testTCPRoute(t, gatewayapiMetrics) testUDPRoute(t, gatewayapiMetrics) testTLSRoute(t, gatewayapiMetrics) + testBackendTLSPolicy(t, gatewayapiMetrics) + testRateLimitPolicy(t, gatewayapiMetrics) + testTLSPolicy(t, gatewayapiMetrics) } func testGatewayClasses(t *testing.T, metrics map[string][][]string) { @@ -481,6 +484,110 @@ func testUDPRoute(t *testing.T, metrics map[string][][]string) { expectEqual(t, udproute1ParentStatusInfo1Labels["parent_name"], "testgateway1", "gatewayapi_udproute_status_parent_info__1 parent_name") } +func testBackendTLSPolicy(t *testing.T, metrics map[string][][]string) { + // gatewayapi_backendtlspolicy_created + backendtlspolicyCreated := metrics["gatewayapi_backendtlspolicy_created"] + backendtlspolicy1Created := backendtlspolicyCreated[0] + expectValidTimestampInPast(t, backendtlspolicy1Created[3], "gatewayapi_backendtlspolicy_created__1 value") + backendtlspolicy1CreatedLabels := parseLabels(string(backendtlspolicy1Created[2])) + expectEqual(t, backendtlspolicy1CreatedLabels["customresource_group"], "gateway.networking.k8s.io", "gatewayapi_backendtlspolicy_created__1 customresource_group") + expectEqual(t, backendtlspolicy1CreatedLabels["customresource_kind"], "BackendTLSPolicy", "gatewayapi_backendtlspolicy_created__1 customresource_kind") + expectEqual(t, backendtlspolicy1CreatedLabels["customresource_version"], "v1alpha2", "gatewayapi_backendtlspolicy_created__1 customresource_version") + expectEqual(t, backendtlspolicy1CreatedLabels["name"], "testbackendtlspolicy1", "gatewayapi_backendtlspolicy_created__1 name") + expectEqual(t, backendtlspolicy1CreatedLabels["namespace"], "default", "gatewayapi_backendtlspolicy_created__1 namespace") + + //gatewayapi_backendtlspolicy_target_info + backendtlspolicyParentInfo := metrics["gatewayapi_backendtlspolicy_target_info"] + backendtlspolicy1ParentInfo1 := backendtlspolicyParentInfo[0] + expectEqual(t, backendtlspolicy1ParentInfo1[3], "1", "gatewayapi_backendtlspolicy_target_info__1 value") + backendtlspolicy1ParentInfo1Labels := parseLabels(string(backendtlspolicy1ParentInfo1[2])) + expectEqual(t, backendtlspolicy1ParentInfo1Labels["customresource_group"], "gateway.networking.k8s.io", "gatewayapi_backendtlspolicy_target_info__1 customresource_group") + expectEqual(t, backendtlspolicy1ParentInfo1Labels["customresource_kind"], "BackendTLSPolicy", "gatewayapi_backendtlspolicy_target_info__1 customresource_kind") + expectEqual(t, backendtlspolicy1ParentInfo1Labels["customresource_version"], "v1alpha2", "gatewayapi_backendtlspolicy_target_info__1 customresource_version") + expectEqual(t, backendtlspolicy1ParentInfo1Labels["name"], "testbackendtlspolicy1", "gatewayapi_backendtlspolicy_target_info__1 name") + expectEqual(t, backendtlspolicy1ParentInfo1Labels["namespace"], "default", "gatewayapi_backendtlspolicy_target_info__1 namespace") + expectEqual(t, backendtlspolicy1ParentInfo1Labels["target_group"], "", "gatewayapi_backendtlspolicy_target_info__1 target_group") + expectEqual(t, backendtlspolicy1ParentInfo1Labels["target_kind"], "Service", "gatewayapi_backendtlspolicy_target_info__1 target_kind") +} + +func testRateLimitPolicy(t *testing.T, metrics map[string][][]string) { + // gatewayapi_ratelimitpolicy_created + ratelimitpolicyCreated := metrics["gatewayapi_ratelimitpolicy_created"] + ratelimitpolicy1Created := ratelimitpolicyCreated[0] + expectValidTimestampInPast(t, ratelimitpolicy1Created[3], "gatewayapi_ratelimitpolicy_created__1 value") + ratelimitpolicy1CreatedLabels := parseLabels(string(ratelimitpolicy1Created[2])) + expectEqual(t, ratelimitpolicy1CreatedLabels["customresource_group"], "kuadrant.io", "gatewayapi_ratelimitpolicy_created__1 customresource_group") + expectEqual(t, ratelimitpolicy1CreatedLabels["customresource_kind"], "RateLimitPolicy", "gatewayapi_ratelimitpolicy_created__1 customresource_kind") + expectEqual(t, ratelimitpolicy1CreatedLabels["customresource_version"], "v1beta2", "gatewayapi_ratelimitpolicy_created__1 customresource_version") + expectEqual(t, ratelimitpolicy1CreatedLabels["name"], "testratelimitpolicy1", "gatewayapi_ratelimitpolicy_created__1 name") + expectEqual(t, ratelimitpolicy1CreatedLabels["namespace"], "default", "gatewayapi_ratelimitpolicy_created__1 namespace") + + //gatewayapi_ratelimitpolicy_target_info + ratelimitpolicyParentInfo := metrics["gatewayapi_ratelimitpolicy_target_info"] + ratelimitpolicy1ParentInfo1 := ratelimitpolicyParentInfo[0] + expectEqual(t, ratelimitpolicy1ParentInfo1[3], "1", "gatewayapi_ratelimitpolicy_target_info__1 value") + ratelimitpolicy1ParentInfo1Labels := parseLabels(string(ratelimitpolicy1ParentInfo1[2])) + expectEqual(t, ratelimitpolicy1ParentInfo1Labels["customresource_group"], "kuadrant.io", "gatewayapi_ratelimitpolicy_target_info__1 customresource_group") + expectEqual(t, ratelimitpolicy1ParentInfo1Labels["customresource_kind"], "RateLimitPolicy", "gatewayapi_ratelimitpolicy_target_info__1 customresource_kind") + expectEqual(t, ratelimitpolicy1ParentInfo1Labels["customresource_version"], "v1beta2", "gatewayapi_ratelimitpolicy_target_info__1 customresource_version") + expectEqual(t, ratelimitpolicy1ParentInfo1Labels["name"], "testratelimitpolicy1", "gatewayapi_ratelimitpolicy_target_info__1 name") + expectEqual(t, ratelimitpolicy1ParentInfo1Labels["namespace"], "default", "gatewayapi_ratelimitpolicy_target_info__1 namespace") + expectEqual(t, ratelimitpolicy1ParentInfo1Labels["target_group"], "gateway.networking.k8s.io", "gatewayapi_ratelimitpolicy_target_info__1 target_group") + expectEqual(t, ratelimitpolicy1ParentInfo1Labels["target_kind"], "HTTPRoute", "gatewayapi_ratelimitpolicy_target_info__1 target_kind") + expectEqual(t, ratelimitpolicy1ParentInfo1Labels["target_name"], "testname1", "gatewayapi_ratelimitpolicy_target_info__1 target_name") + + //gatewayapi_ratelimitpolicy_status + ratelimitpolicyStatus := metrics["gatewayapi_ratelimitpolicy_status"] + ratelimitpolicy1Status1 := ratelimitpolicyStatus[0] + expectEqual(t, ratelimitpolicy1Status1[3], "1", "gatewayapi_ratelimitpolicy_status__1 value") + ratelimitpolicy1Status1Labels := parseLabels(string(ratelimitpolicy1Status1[2])) + expectEqual(t, ratelimitpolicy1Status1Labels["customresource_group"], "kuadrant.io", "gatewayapi_ratelimitpolicy_status__1 customresource_group") + expectEqual(t, ratelimitpolicy1Status1Labels["customresource_kind"], "RateLimitPolicy", "gatewayapi_ratelimitpolicy_status__1 customresource_kind") + expectEqual(t, ratelimitpolicy1Status1Labels["customresource_version"], "v1beta2", "gatewayapi_ratelimitpolicy_status__1 customresource_version") + expectEqual(t, ratelimitpolicy1Status1Labels["name"], "testratelimitpolicy1", "gatewayapi_ratelimitpolicy_status__1 name") + expectEqual(t, ratelimitpolicy1Status1Labels["namespace"], "default", "gatewayapi_ratelimitpolicy_status__1 namespace") + expectEqual(t, ratelimitpolicy1Status1Labels["type"], "Available", "gatewayapi_ratelimitpolicy_status__1 type") +} + +func testTLSPolicy(t *testing.T, metrics map[string][][]string) { + // gatewayapi_tlspolicy_created + tlspolicyCreated := metrics["gatewayapi_tlspolicy_created"] + tlspolicy1Created := tlspolicyCreated[0] + expectValidTimestampInPast(t, tlspolicy1Created[3], "gatewayapi_tlspolicy_created__1 value") + tlspolicy1CreatedLabels := parseLabels(string(tlspolicy1Created[2])) + expectEqual(t, tlspolicy1CreatedLabels["customresource_group"], "kuadrant.io", "gatewayapi_tlspolicy_created__1 customresource_group") + expectEqual(t, tlspolicy1CreatedLabels["customresource_kind"], "TLSPolicy", "gatewayapi_tlspolicy_created__1 customresource_kind") + expectEqual(t, tlspolicy1CreatedLabels["customresource_version"], "v1alpha1", "gatewayapi_tlspolicy_created__1 customresource_version") + expectEqual(t, tlspolicy1CreatedLabels["name"], "testtlspolicy1", "gatewayapi_tlspolicy_created__1 name") + expectEqual(t, tlspolicy1CreatedLabels["namespace"], "default", "gatewayapi_tlspolicy_created__1 namespace") + + //gatewayapi_tlspolicy_target_info + tlspolicyParentInfo := metrics["gatewayapi_tlspolicy_target_info"] + tlspolicy1ParentInfo1 := tlspolicyParentInfo[0] + expectEqual(t, tlspolicy1ParentInfo1[3], "1", "gatewayapi_tlspolicy_target_info__1 value") + tlspolicy1ParentInfo1Labels := parseLabels(string(tlspolicy1ParentInfo1[2])) + expectEqual(t, tlspolicy1ParentInfo1Labels["customresource_group"], "kuadrant.io", "gatewayapi_tlspolicy_target_info__1 customresource_group") + expectEqual(t, tlspolicy1ParentInfo1Labels["customresource_kind"], "TLSPolicy", "gatewayapi_tlspolicy_target_info__1 customresource_kind") + expectEqual(t, tlspolicy1ParentInfo1Labels["customresource_version"], "v1alpha1", "gatewayapi_tlspolicy_target_info__1 customresource_version") + expectEqual(t, tlspolicy1ParentInfo1Labels["name"], "testtlspolicy1", "gatewayapi_tlspolicy_target_info__1 name") + expectEqual(t, tlspolicy1ParentInfo1Labels["namespace"], "default", "gatewayapi_tlspolicy_target_info__1 namespace") + expectEqual(t, tlspolicy1ParentInfo1Labels["target_group"], "gateway.networking.k8s.io", "gatewayapi_tlspolicy_target_info__1 target_group") + expectEqual(t, tlspolicy1ParentInfo1Labels["target_kind"], "Gateway", "gatewayapi_tlspolicy_target_info__1 target_kind") + expectEqual(t, tlspolicy1ParentInfo1Labels["target_name"], "testgateway1", "gatewayapi_tlspolicy_target_info__1 target_name") + + //gatewayapi_tlspolicy_status + tlspolicyStatus := metrics["gatewayapi_tlspolicy_status"] + tlspolicy1Status1 := tlspolicyStatus[0] + expectEqual(t, tlspolicy1Status1[3], "1", "gatewayapi_tlspolicy_status__1 value") + tlspolicy1Status1Labels := parseLabels(string(tlspolicy1Status1[2])) + expectEqual(t, tlspolicy1Status1Labels["customresource_group"], "kuadrant.io", "gatewayapi_tlspolicy_status__1 customresource_group") + expectEqual(t, tlspolicy1Status1Labels["customresource_kind"], "TLSPolicy", "gatewayapi_tlspolicy_status__1 customresource_kind") + expectEqual(t, tlspolicy1Status1Labels["customresource_version"], "v1alpha1", "gatewayapi_tlspolicy_status__1 customresource_version") + expectEqual(t, tlspolicy1Status1Labels["name"], "testtlspolicy1", "gatewayapi_tlspolicy_status__1 name") + expectEqual(t, tlspolicy1Status1Labels["namespace"], "default", "gatewayapi_tlspolicy_status__1 namespace") + expectEqual(t, tlspolicy1Status1Labels["type"], "Ready", "gatewayapi_tlspolicy_status__1 type") +} + func parseLabels(labelsRaw string) map[string]string { // simple label parsing assuming no special chars/escaping // fmt.Printf("labelsRaw=%s\n", labelsRaw) diff --git a/tests/manifests/testbackendtlspolicy1.yaml b/tests/manifests/testbackendtlspolicy1.yaml new file mode 100644 index 0000000..89ab3e6 --- /dev/null +++ b/tests/manifests/testbackendtlspolicy1.yaml @@ -0,0 +1,15 @@ +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: BackendTLSPolicy +metadata: + name: testbackendtlspolicy1 +spec: + targetRef: + group: "" + kind: Service + name: testname1 + tls: + caCertRefs: + - group: "" + name: "grafana" + kind: "ConfigMap" + hostname: grafana.example.com \ No newline at end of file diff --git a/tests/manifests/testratelimitpolicy.yaml b/tests/manifests/testratelimitpolicy.yaml new file mode 100644 index 0000000..ef8a745 --- /dev/null +++ b/tests/manifests/testratelimitpolicy.yaml @@ -0,0 +1,22 @@ +apiVersion: kuadrant.io/v1beta2 +kind: RateLimitPolicy +metadata: + name: testratelimitpolicy1 +spec: + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: testname1 + limits: + "global": + rates: + - limit: 5 + duration: 10 + unit: second +status: + conditions: + - lastTransitionTime: "2023-08-21T22:53:08Z" + message: HTTPRoute is ratelimited + reason: HTTPRouteProtected + status: "True" + type: Available \ No newline at end of file diff --git a/tests/manifests/testtlspolicy.yaml b/tests/manifests/testtlspolicy.yaml new file mode 100644 index 0000000..a1f9cb3 --- /dev/null +++ b/tests/manifests/testtlspolicy.yaml @@ -0,0 +1,21 @@ +apiVersion: kuadrant.io/v1alpha1 +kind: TLSPolicy +metadata: + name: testtlspolicy1 + namespace: default +spec: + targetRef: + name: testgateway1 + group: gateway.networking.k8s.io + kind: Gateway + issuerRef: + group: cert-manager.io + kind: ClusterIssuer + name: selfsigned-cluster-issuer +status: + conditions: + - lastTransitionTime: "2023-08-21T22:53:08Z" + message: Gateway is TLS Enabled + reason: GatewayTLSEnabled + status: "True" + type: Ready \ No newline at end of file From 195aa000753704942ae4efcc29830d692bd11393 Mon Sep 17 00:00:00 2001 From: Ignas Baranauskas Date: Mon, 16 Oct 2023 12:23:49 +0100 Subject: [PATCH 3/5] Separated kuadrant policies --- config/examples/dashboards/kustomization.yaml | 4 + config/examples/enterprise/README.md | 4 + config/examples/enterprise/all.yaml | 90 ---- config/examples/kube-prometheus/bundle.yaml | 411 +++++++++++++++++- .../grafana_deployment_patch.yaml | 8 +- .../ksm_clusterrole_patch.yaml | 11 - .../kube-state-metrics/cluster-role.yaml | 8 - .../kuadrant.io_ratelimitpolicies.yaml | 397 ----------------- .../crd/standard/kuadrant.io_tlspolicies.yaml | 313 ------------- config/kuadrant/README.md | 43 ++ config/kuadrant/clusterrole-patch.yaml | 21 + .../crd/kuadrant.io_ratelimitpolicies.yaml | 245 +++++++++++ .../kuadrant/crd/kuadrant.io_tlspolicies.yaml | 216 +++++++++ config/kuadrant/kuadrant.yaml | 89 ++++ hack/local_dev.sh | 6 + 15 files changed, 1031 insertions(+), 835 deletions(-) delete mode 100644 config/gateway-api/crd/standard/kuadrant.io_ratelimitpolicies.yaml delete mode 100644 config/gateway-api/crd/standard/kuadrant.io_tlspolicies.yaml create mode 100644 config/kuadrant/README.md create mode 100644 config/kuadrant/clusterrole-patch.yaml create mode 100644 config/kuadrant/crd/kuadrant.io_ratelimitpolicies.yaml create mode 100644 config/kuadrant/crd/kuadrant.io_tlspolicies.yaml create mode 100644 config/kuadrant/kuadrant.yaml diff --git a/config/examples/dashboards/kustomization.yaml b/config/examples/dashboards/kustomization.yaml index 1d3a222..7c8b8c1 100644 --- a/config/examples/dashboards/kustomization.yaml +++ b/config/examples/dashboards/kustomization.yaml @@ -31,3 +31,7 @@ configMapGenerator: namespace: monitoring files: - ./udproutes.json +- name: grafana-policies + namespace: monitoring + files: + - ./policies.json diff --git a/config/examples/enterprise/README.md b/config/examples/enterprise/README.md index 7efaad9..c6da202 100644 --- a/config/examples/enterprise/README.md +++ b/config/examples/enterprise/README.md @@ -72,10 +72,14 @@ There are 3 Gateways with various services attached. ```bash kind create cluster kubectl create -f ../../gateway-api/crd/standard/ +kubectl apply -f ../../kuadrant/crd/ kubectl create -f ./all.yaml kubectl replace --subresource=status -f ./all.yaml +kubectl apply -f ../../kuadrant/kuadrant.yaml +kubectl replace --subresource=status -f ../../kuadrant/kuadrant.yaml kubectl apply --server-side -f ../kube-prometheus/bundle_crd.yaml kubectl apply -f ../kube-prometheus/bundle.yaml +kubectl patch clusterrole kube-state-metrics --type=json -p "$(cat ../../kuadrant/clusterrole-patch.yaml)" kubectl -n monitoring wait --timeout=5m deployment/grafana --for=condition=Available kubectl -n monitoring port-forward service/grafana 3000:3000 > /dev/null & kubectl -n monitoring rollout status --watch --timeout=5m statefulset/prometheus-k8s diff --git a/config/examples/enterprise/all.yaml b/config/examples/enterprise/all.yaml index 045f1ca..887b831 100644 --- a/config/examples/enterprise/all.yaml +++ b/config/examples/enterprise/all.yaml @@ -625,96 +625,6 @@ status: - group: gateway.networking.k8s.io kind: GRPCRoute --- -apiVersion: kuadrant.io/v1alpha1 -kind: TLSPolicy -metadata: - name: external - namespace: istio-system -spec: - targetRef: - name: external - group: gateway.networking.k8s.io - kind: Gateway - issuerRef: - group: cert-manager.io - kind: ClusterIssuer - name: selfsigned-cluster-issuer -status: - conditions: - - lastTransitionTime: "2023-08-21T22:53:08Z" - message: Gateway is TLS Enabled - reason: GatewayTLSEnabled - status: "True" - type: Ready ---- -apiVersion: kuadrant.io/v1alpha1 -kind: TLSPolicy -metadata: - name: internal - namespace: istio-system -spec: - targetRef: - name: internal - group: gateway.networking.k8s.io - kind: Gateway - issuerRef: - group: cert-manager.io - kind: ClusterIssuer - name: selfsigned-cluster-issuer -status: - conditions: - - lastTransitionTime: "2023-08-21T22:53:08Z" - message: Gateway is TLS Enabled - reason: GatewayTLSEnabled - status: "True" - type: Ready ---- -apiVersion: kuadrant.io/v1beta2 -kind: RateLimitPolicy -metadata: - name: rlp-www -spec: - targetRef: - group: gateway.networking.k8s.io - kind: HTTPRoute - name: www - limits: - "global": - rates: - - limit: 5 - duration: 10 - unit: second -status: - conditions: - - lastTransitionTime: "2023-08-21T22:53:08Z" - message: HTTPRoute is ratelimited - reason: HTTPRouteProtected - status: "True" - type: Available ---- -apiVersion: kuadrant.io/v1beta2 -kind: RateLimitPolicy -metadata: - name: rlp-cdn -spec: - targetRef: - group: gateway.networking.k8s.io - kind: HTTPRoute - name: cdn - limits: - "global": - rates: - - limit: 5 - duration: 10 - unit: second -status: - conditions: - - lastTransitionTime: "2023-08-21T22:53:08Z" - message: HTTPRoute is ratelimited - reason: HTTPRouteProtected - status: "True" - type: Available ---- apiVersion: gateway.networking.k8s.io/v1alpha2 kind: BackendTLSPolicy metadata: diff --git a/config/examples/kube-prometheus/bundle.yaml b/config/examples/kube-prometheus/bundle.yaml index 01aa0b4..de5e935 100644 --- a/config/examples/kube-prometheus/bundle.yaml +++ b/config/examples/kube-prometheus/bundle.yaml @@ -494,14 +494,6 @@ rules: verbs: - list - watch -- apiGroups: - - kuadrant.io - resources: - - tlspolicies - - ratelimitpolicies - verbs: - - list - - watch --- apiVersion: rbac.authorization.k8s.io/v1 @@ -41202,6 +41194,401 @@ metadata: name: grafana-httproutes-mhg79c4bbk namespace: monitoring +--- +apiVersion: v1 +data: + policies.json: | + { + "editable": false, + "links": [ + { + "asDropdown": false, + "includeVars": true, + "keepTime": true, + "tags": [ + "gateway-api-state" + ], + "targetBlank": false, + "title": "Gateway Dashboards", + "type": "dashboards" + } + ], + "panels": [ + { + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 1, + "title": "TLSPolicy", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "description": "Total number of TLSPolicy across all clusters", + "gridPos": { + "h": 3, + "w": 2, + "x": 0, + "y": 1 + }, + "id": 2, + "pluginVersion": "v10.0.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "expr": "count(gatewayapi_tlspolicy_status)", + "instant": true + } + ], + "title": "Total", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "description": "Total TLSPolicy with an Ready state", + "gridPos": { + "h": 3, + "w": 2, + "x": 2, + "y": 1 + }, + "id": 3, + "pluginVersion": "v10.0.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "expr": "count(gatewayapi_tlspolicy_status{type=\"Ready\"})", + "instant": true + } + ], + "title": "Ready", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "gridPos": { + "h": 6, + "w": 10, + "x": 4, + "y": 1 + }, + "id": 4, + "pluginVersion": "v10.0.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "expr": "gatewayapi_tlspolicy_target_info", + "format": "table", + "instant": true, + "range": false + } + ], + "title": "TLSPolicy", + "transformations": [ + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "name", + "target_kind", + "target_name" + ] + } + } + }, + { + "id": "organize", + "options": { + "renameByName": { + "name": "Name", + "target_kind": "Target Kind", + "target_name": "Target Name" + } + } + } + ], + "type": "table" + }, + { + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 2 + }, + "id": 5, + "title": "RateLimitPolicy", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "description": "Total number of RateLimitPolicy across all clusters", + "gridPos": { + "h": 3, + "w": 2, + "x": 0, + "y": 3 + }, + "id": 6, + "pluginVersion": "v10.0.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "expr": "count(gatewayapi_ratelimitpolicy_status)", + "instant": true + } + ], + "title": "Total", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "description": "Total RateLimitPolicy with an Available state", + "gridPos": { + "h": 3, + "w": 2, + "x": 2, + "y": 3 + }, + "id": 7, + "pluginVersion": "v10.0.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "expr": "count(gatewayapi_ratelimitpolicy_status{type=\"Available\"})", + "instant": true + } + ], + "title": "Available", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "gridPos": { + "h": 6, + "w": 10, + "x": 4, + "y": 7 + }, + "id": 8, + "pluginVersion": "v10.0.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "expr": "gatewayapi_ratelimitpolicy_target_info", + "format": "table", + "instant": true, + "range": false + } + ], + "title": "RateLimitPolicy", + "transformations": [ + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "name", + "target_kind", + "target_name" + ] + } + } + }, + { + "id": "organize", + "options": { + "renameByName": { + "name": "Name", + "target_kind": "Target Kind", + "target_name": "Target Name" + } + } + } + ], + "type": "table" + }, + { + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 8 + }, + "id": 9, + "title": "BackendTLSPolicy", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "gridPos": { + "h": 6, + "w": 10, + "x": 4, + "y": 9 + }, + "id": 10, + "pluginVersion": "v10.0.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "expr": "gatewayapi_backendtlspolicy_target_info", + "format": "table", + "instant": true, + "range": false + } + ], + "title": "BackendTLSPolicy", + "transformations": [ + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "name", + "target_kind", + "target_name" + ] + } + } + }, + { + "id": "organize", + "options": { + "renameByName": { + "name": "Name", + "target_kind": "Target Kind", + "target_name": "Target Name" + } + } + } + ], + "type": "table" + } + ], + "schemaVersion": 36, + "style": "dark", + "tags": [ + "gateway-api", + "gateway-api-state" + ], + "templating": { + "list": [ + { + "label": "Data Source", + "name": "datasource", + "query": "prometheus", + "type": "datasource" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "includeAll": true, + "label": "TLSPolicy", + "multi": true, + "name": "tlspolicy", + "query": { + "query": "label_values(gatewayapi_tlspolicy_created, name)", + "refId": "StandardVariableQuery" + }, + "regex": "/(.*)/", + "type": "query" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "includeAll": true, + "label": "RateLimitPolicy", + "multi": true, + "name": "ratelimitpolicy", + "query": { + "query": "label_values(gatewayapi_ratelimitpolicy_created, name)", + "refId": "StandardVariableQuery" + }, + "regex": "/(.*)/", + "type": "query" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "includeAll": true, + "label": "BackendTLSPolicy", + "multi": true, + "name": "backendtlspolicy", + "query": { + "query": "label_values(gatewayapi_backendtlspolicy_created, name)", + "refId": "StandardVariableQuery" + }, + "regex": "/(.*)/", + "type": "query" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timezone": "utc", + "title": "Gateway API State / Policies", + "uid": "gatewayapipolicies" + } +kind: ConfigMap +metadata: + name: grafana-policies-bggb44htkm + namespace: monitoring + --- apiVersion: v1 data: @@ -43836,8 +44223,8 @@ spec: name: grafana-tcproutes - mountPath: /grafana-dashboard-definitions/0/grafana-udproutes name: grafana-udproutes - - mountPath: /grafana-dashboard-definitions/0/grafana-tlspolicy - name: grafana-tlspolicy + - mountPath: /grafana-dashboard-definitions/0/grafana-policies + name: grafana-policies nodeSelector: kubernetes.io/os: linux securityContext: @@ -43954,8 +44341,8 @@ spec: name: grafana-tlsroutes - configMap: defaultMode: 420 - name: grafana-tlspolicy - name: grafana-tlspolicy + name: grafana-policies-bggb44htkm + name: grafana-policies - configMap: defaultMode: 420 name: grafana-tcproutes-d7tt7t272g diff --git a/config/examples/kube-prometheus/grafana_deployment_patch.yaml b/config/examples/kube-prometheus/grafana_deployment_patch.yaml index f773ae2..07550b7 100644 --- a/config/examples/kube-prometheus/grafana_deployment_patch.yaml +++ b/config/examples/kube-prometheus/grafana_deployment_patch.yaml @@ -36,10 +36,10 @@ - op: add path: /spec/template/spec/volumes/- value: - name: grafana-tlspolicy + name: grafana-policies configMap: defaultMode: 420 - name: grafana-tlspolicy + name: grafana-policies - op: add path: /spec/template/spec/volumes/- value: @@ -92,5 +92,5 @@ - op: add path: /spec/template/spec/containers/0/volumeMounts/- value: - name: grafana-tlspolicy - mountPath: /grafana-dashboard-definitions/0/grafana-tlspolicy + name: grafana-policies + mountPath: /grafana-dashboard-definitions/0/grafana-policies diff --git a/config/examples/kube-prometheus/ksm_clusterrole_patch.yaml b/config/examples/kube-prometheus/ksm_clusterrole_patch.yaml index 0f7a09b..d27de11 100644 --- a/config/examples/kube-prometheus/ksm_clusterrole_patch.yaml +++ b/config/examples/kube-prometheus/ksm_clusterrole_patch.yaml @@ -25,14 +25,3 @@ verbs: - list - watch -- op: add - path: /rules/- - value: - apiGroups: - - "kuadrant.io" - resources: - - tlspolicies - - ratelimitpolicies - verbs: - - list - - watch diff --git a/config/examples/kube-state-metrics/cluster-role.yaml b/config/examples/kube-state-metrics/cluster-role.yaml index 9be9447..dfc6514 100644 --- a/config/examples/kube-state-metrics/cluster-role.yaml +++ b/config/examples/kube-state-metrics/cluster-role.yaml @@ -147,11 +147,3 @@ rules: verbs: - list - watch -- apiGroups: - - "kuadrant.io" - resources: - - tlspolicies - - ratelimitpolicies - verbs: - - list - - watch diff --git a/config/gateway-api/crd/standard/kuadrant.io_ratelimitpolicies.yaml b/config/gateway-api/crd/standard/kuadrant.io_ratelimitpolicies.yaml deleted file mode 100644 index a5c6b16..0000000 --- a/config/gateway-api/crd/standard/kuadrant.io_ratelimitpolicies.yaml +++ /dev/null @@ -1,397 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.10.0 - creationTimestamp: null - name: ratelimitpolicies.kuadrant.io -spec: - group: kuadrant.io - names: - kind: RateLimitPolicy - listKind: RateLimitPolicyList - plural: ratelimitpolicies - singular: ratelimitpolicy - scope: Namespaced - versions: - - name: v1beta2 - schema: - openAPIV3Schema: - description: RateLimitPolicy is the Schema for the ratelimitpolicies API - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: RateLimitPolicySpec defines the desired state of RateLimitPolicy - properties: - limits: - additionalProperties: - description: Limit represents a complete rate limit configuration - properties: - counters: - description: Counters defines additional rate limit counters - based on context qualifiers and well known selectors TODO - Document properly "Well-known selector" https://github.com/Kuadrant/architecture/blob/main/rfcs/0001-rlp-v2.md#well-known-selectors - items: - description: 'ContextSelector defines one item from the well - known attributes Attributes: https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/advanced/attributes - Well-known selectors: https://github.com/Kuadrant/architecture/blob/main/rfcs/0001-rlp-v2.md#well-known-selectors - They are named by a dot-separated path (e.g. request.path) - Example: "request.path" -> The path portion of the URL' - maxLength: 253 - minLength: 1 - type: string - type: array - rates: - description: Rates holds the list of limit rates - items: - description: Rate defines the actual rate limit that will - be used when there is a match - properties: - duration: - description: Duration defines the time period for which - the Limit specified above applies. - type: integer - limit: - description: Limit defines the max value allowed for a - given period of time - type: integer - unit: - description: 'Duration defines the time uni Possible values - are: "second", "minute", "hour", "day"' - enum: - - second - - minute - - hour - - day - type: string - required: - - duration - - limit - - unit - type: object - type: array - routeSelectors: - description: RouteSelectors defines semantics for matching an - HTTP request based on conditions - items: - description: RouteSelector defines semantics for matching - an HTTP request based on conditions https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1beta1.HTTPRouteSpec - properties: - hostnames: - description: Hostnames defines a set of hostname that - should match against the HTTP Host header to select - a HTTPRoute to process the request https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1beta1.HTTPRouteSpec - items: - description: "Hostname is the fully qualified domain - name of a network host. This matches the RFC 1123 - definition of a hostname with 2 notable exceptions: - \n 1. IPs are not allowed. 2. A hostname may be prefixed - with a wildcard label (`*.`). The wildcard label must - appear by itself as the first label. \n Hostname can - be \"precise\" which is a domain name without the - terminating dot of a network host (e.g. \"foo.example.com\") - or \"wildcard\", which is a domain name prefixed with - a single wildcard label (e.g. `*.example.com`). \n - Note that as per RFC1035 and RFC1123, a *label* must - consist of lower case alphanumeric characters or '-', - and must start and end with an alphanumeric character. - No other punctuation is allowed." - type: string - type: array - matches: - description: Matches define conditions used for matching - the rule against incoming HTTP requests. https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1beta1.HTTPRouteSpec - items: - description: "HTTPRouteMatch defines the predicate used - to match requests to a given action. Multiple match - types are ANDed together, i.e. the match will evaluate - to true only if all conditions are satisfied. \n For - example, the match below will match a HTTP request - only if its path starts with `/foo` AND it contains - the `version: v1` header: \n ``` match: \n path: value: - \"/foo\" headers: - name: \"version\" value \"v1\" - \n ```" - properties: - headers: - description: Headers specifies HTTP request header - matchers. Multiple match values are ANDed together, - meaning, a request must match all the specified - headers to select the route. - items: - description: HTTPHeaderMatch describes how to - select a HTTP route by matching HTTP request - headers. - properties: - name: - description: "Name is the name of the HTTP - Header to be matched. Name matching MUST - be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). - \n If multiple entries specify equivalent - header names, only the first entry with - an equivalent name MUST be considered for - a match. Subsequent entries with an equivalent - header name MUST be ignored. Due to the - case-insensitivity of header names, \"foo\" - and \"Foo\" are considered equivalent. \n - When a header is repeated in an HTTP request, - it is implementation-specific behavior as - to how this is represented. Generally, proxies - should follow the guidance from the RFC: - https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 - regarding processing a repeated header, - with special handling for \"Set-Cookie\"." - type: string - type: - description: "Type specifies how to match - against the value of the header. \n Support: - Core (Exact) \n Support: Implementation-specific - (RegularExpression) \n Since RegularExpression - HeaderMatchType has implementation-specific - conformance, implementations can support - POSIX, PCRE or any other dialects of regular - expressions. Please read the implementation's - documentation to determine the supported - dialect." - type: string - value: - description: Value is the value of HTTP Header - to be matched. - type: string - required: - - name - - value - type: object - type: array - method: - description: "Method specifies HTTP method matcher. - When specified, this route will be matched only - if the request has the specified method. \n Support: - Extended" - type: string - path: - description: Path specifies a HTTP request path - matcher. If this field is not specified, a default - prefix match on the "/" path is provided. - properties: - type: - description: "Type specifies how to match against - the path Value. \n Support: Core (Exact, PathPrefix) - \n Support: Implementation-specific (RegularExpression)" - type: string - value: - description: Value of the HTTP path to match - against. - type: string - type: object - queryParams: - description: "QueryParams specifies HTTP query parameter - matchers. Multiple match values are ANDed together, - meaning, a request must match all the specified - query parameters to select the route. \n Support: - Extended" - items: - description: HTTPQueryParamMatch describes how - to select a HTTP route by matching HTTP query - parameters. - properties: - name: - description: "Name is the name of the HTTP - query param to be matched. This must be - an exact string match. (See https://tools.ietf.org/html/rfc7230#section-2.7.3). - \n If multiple entries specify equivalent - query param names, only the first entry - with an equivalent name MUST be considered - for a match. Subsequent entries with an - equivalent query param name MUST be ignored. - \n If a query param is repeated in an HTTP - request, the behavior is purposely left - undefined, since different data planes have - different capabilities. However, it is *recommended* - that implementations should match against - the first value of the param if the data - plane supports it, as this behavior is expected - in other load balancing contexts outside - of the Gateway API. \n Users SHOULD NOT - route traffic based on repeated query params - to guard themselves against potential differences - in the implementations." - type: string - type: - description: "Type specifies how to match - against the value of the query parameter. - \n Support: Extended (Exact) \n Support: - Implementation-specific (RegularExpression) - \n Since RegularExpression QueryParamMatchType - has Implementation-specific conformance, - implementations can support POSIX, PCRE - or any other dialects of regular expressions. - Please read the implementation's documentation - to determine the supported dialect." - type: string - value: - description: Value is the value of HTTP query - param to be matched. - type: string - required: - - name - - value - type: object - type: array - type: object - type: array - type: object - type: array - when: - description: When holds the list of conditions for the policy - to be enforced. Called also "soft" conditions as route selectors - must also match - items: - description: RouteSelector defines semantics for matching - an HTTP request based on conditions https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1beta1.HTTPRouteSpec - properties: - operator: - description: 'The binary operator to be applied to the - content fetched from the selector Possible values are: - "eq" (equal to), "neq" (not equal to)' - enum: - - eq - - neq - - startswith - - endswith - - incl - - excl - - matches - type: string - selector: - description: Selector defines one item from the well known - selectors TODO Document properly "Well-known selector" - https://github.com/Kuadrant/architecture/blob/main/rfcs/0001-rlp-v2.md#well-known-selectors - maxLength: 253 - minLength: 1 - type: string - value: - description: The value of reference for the comparison. - type: string - required: - - operator - - selector - - value - type: object - type: array - type: object - description: Limits holds the struct of limits indexed by a unique - name - type: object - targetRef: - description: TargetRef identifies an API object to apply policy to. - properties: - group: - description: Group is the group of the target resource. - type: string - kind: - description: Kind is kind of the target resource. - type: string - name: - description: Name is the name of the target resource. - type: string - namespace: - description: Namespace is the namespace of the referent. When - unspecified, the local namespace is inferred. Even when policy - targets a resource in a different namespace, it MUST only apply - to traffic originating from the same namespace as the policy. - type: string - required: - - group - - kind - - name - type: object - required: - - targetRef - type: object - status: - description: RateLimitPolicyStatus defines the observed state of RateLimitPolicy - properties: - conditions: - description: 'Represents the observations of a foo''s current state. - Known .status.conditions.type are: "Available"' - items: - description: "Condition contains details for one aspect of the current - state of this API Resource. --- This struct is intended for direct - use as an array at the field path .status.conditions. For example, - \n type FooStatus struct{ // Represents the observations of a - foo's current state. // Known .status.conditions.type are: \"Available\", - \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge - // +listType=map // +listMapKey=type Conditions []metav1.Condition - `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" - protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" - properties: - lastTransitionTime: - description: lastTransitionTime is the last time the condition - transitioned from one status to another. This should be when - the underlying condition changed. If that is not known, then - using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: message is a human readable message indicating - details about the transition. This may be an empty string. - type: string - observedGeneration: - description: observedGeneration represents the .metadata.generation - that the condition was set based upon. For instance, if .metadata.generation - is currently 12, but the .status.conditions[x].observedGeneration - is 9, the condition is out of date with respect to the current - state of the instance. - format: int64 - type: integer - reason: - description: reason contains a programmatic identifier indicating - the reason for the condition's last transition. Producers - of specific condition types may define expected values and - meanings for this field, and whether the values are considered - a guaranteed API. The value should be a CamelCase string. - This field may not be empty. - type: string - status: - description: status of the condition, one of True, False, Unknown. - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - --- Many .condition.type values are consistent across resources - like Available, but because arbitrary conditions can be useful - (see .node.status.conditions), the ability to deconflict is - important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - observedGeneration: - description: ObservedGeneration reflects the generation of the most - recently observed spec. - format: int64 - type: integer - type: object - type: object - served: true - storage: true - subresources: - status: {} \ No newline at end of file diff --git a/config/gateway-api/crd/standard/kuadrant.io_tlspolicies.yaml b/config/gateway-api/crd/standard/kuadrant.io_tlspolicies.yaml deleted file mode 100644 index 0b55aa1..0000000 --- a/config/gateway-api/crd/standard/kuadrant.io_tlspolicies.yaml +++ /dev/null @@ -1,313 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.10.0 - gateway.networking.k8s.io/policy: direct - creationTimestamp: null - name: tlspolicies.kuadrant.io -spec: - group: kuadrant.io - names: - kind: TLSPolicy - listKind: TLSPolicyList - plural: tlspolicies - singular: tlspolicy - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: TLSPolicy ready. - jsonPath: .status.conditions[?(@.type=="Ready")].status - name: Ready - type: string - name: v1alpha1 - schema: - openAPIV3Schema: - description: TLSPolicy is the Schema for the tlspolicies API - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: TLSPolicySpec defines the desired state of TLSPolicy - properties: - commonName: - description: 'CommonName is a common name to be used on the Certificate. - The CommonName should have a length of 64 characters or fewer to - avoid generating invalid CSRs. This value is ignored by TLS clients - when any subject alt name is set. This is x509 behaviour: https://tools.ietf.org/html/rfc6125#section-6.4.4' - type: string - duration: - description: The requested 'duration' (i.e. lifetime) of the Certificate. - This option may be ignored/overridden by some issuer types. If unset - this defaults to 90 days. Certificate will be renewed either 2/3 - through its duration or `renewBefore` period before its expiry, - whichever is later. Minimum accepted duration is 1 hour. Value must - be in units accepted by Go time.ParseDuration https://golang.org/pkg/time/#ParseDuration - type: string - issuerRef: - description: IssuerRef is a reference to the issuer for this certificate. - If the `kind` field is not set, or set to `Issuer`, an Issuer resource - with the given name in the same namespace as the Certificate will - be used. If the `kind` field is set to `ClusterIssuer`, a ClusterIssuer - with the provided name will be used. The `name` field in this stanza - is required at all times. - properties: - group: - description: Group of the resource being referred to. - type: string - kind: - description: Kind of the resource being referred to. - type: string - name: - description: Name of the resource being referred to. - type: string - required: - - name - type: object - privateKey: - description: Options to control private keys used for the Certificate. - properties: - algorithm: - description: Algorithm is the private key algorithm of the corresponding - private key for this certificate. If provided, allowed values - are either `RSA`,`Ed25519` or `ECDSA` If `algorithm` is specified - and `size` is not provided, key size of 256 will be used for - `ECDSA` key algorithm and key size of 2048 will be used for - `RSA` key algorithm. key size is ignored when using the `Ed25519` - key algorithm. - enum: - - RSA - - ECDSA - - Ed25519 - type: string - encoding: - description: The private key cryptography standards (PKCS) encoding - for this certificate's private key to be encoded in. If provided, - allowed values are `PKCS1` and `PKCS8` standing for PKCS#1 and - PKCS#8, respectively. Defaults to `PKCS1` if not specified. - enum: - - PKCS1 - - PKCS8 - type: string - rotationPolicy: - description: RotationPolicy controls how private keys should be - regenerated when a re-issuance is being processed. If set to - Never, a private key will only be generated if one does not - already exist in the target `spec.secretName`. If one does exists - but it does not have the correct algorithm or size, a warning - will be raised to await user intervention. If set to Always, - a private key matching the specified requirements will be generated - whenever a re-issuance occurs. Default is 'Never' for backward - compatibility. - type: string - size: - description: Size is the key bit size of the corresponding private - key for this certificate. If `algorithm` is set to `RSA`, valid - values are `2048`, `4096` or `8192`, and will default to `2048` - if not specified. If `algorithm` is set to `ECDSA`, valid values - are `256`, `384` or `521`, and will default to `256` if not - specified. If `algorithm` is set to `Ed25519`, Size is ignored. - No other values are allowed. - type: integer - type: object - renewBefore: - description: How long before the currently issued certificate's expiry - cert-manager should renew the certificate. The default is 2/3 of - the issued certificate's duration. Minimum accepted value is 5 minutes. - Value must be in units accepted by Go time.ParseDuration https://golang.org/pkg/time/#ParseDuration - type: string - revisionHistoryLimit: - description: RevisionHistoryLimit is the maximum number of CertificateRequest - revisions that are maintained in the Certificate's history. Each - revision represents a single `CertificateRequest` created by this - Certificate, either when it was created, renewed, or Spec was changed. - Revisions will be removed by oldest first if the number of revisions - exceeds this number. If set, revisionHistoryLimit must be a value - of `1` or greater. If unset (`nil`), revisions will not be garbage - collected. Default value is `nil`. - format: int32 - type: integer - targetRef: - description: PolicyTargetReference identifies an API object to apply - policy to. This should be used as part of Policy resources that - can target Gateway API resources. For more information on how this - policy attachment model works, and a sample Policy resource, refer - to the policy attachment documentation for Gateway API. - properties: - group: - description: Group is the group of the target resource. - maxLength: 253 - pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ - type: string - kind: - description: Kind is kind of the target resource. - maxLength: 63 - minLength: 1 - pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ - type: string - name: - description: Name is the name of the target resource. - maxLength: 253 - minLength: 1 - type: string - namespace: - description: Namespace is the namespace of the referent. When - unspecified, the local namespace is inferred. Even when policy - targets a resource in a different namespace, it MUST only apply - to traffic originating from the same namespace as the policy. - maxLength: 63 - minLength: 1 - pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ - type: string - required: - - group - - kind - - name - type: object - usages: - description: Usages is the set of x509 usages that are requested for - the certificate. Defaults to `digital signature` and `key encipherment` - if not specified. - items: - description: 'KeyUsage specifies valid usage contexts for keys. - See: https://tools.ietf.org/html/rfc5280#section-4.2.1.3 https://tools.ietf.org/html/rfc5280#section-4.2.1.12 - Valid KeyUsage values are as follows: "signing", "digital signature", - "content commitment", "key encipherment", "key agreement", "data - encipherment", "cert sign", "crl sign", "encipher only", "decipher - only", "any", "server auth", "client auth", "code signing", "email - protection", "s/mime", "ipsec end system", "ipsec tunnel", "ipsec - user", "timestamping", "ocsp signing", "microsoft sgc", "netscape - sgc"' - enum: - - signing - - digital signature - - content commitment - - key encipherment - - key agreement - - data encipherment - - cert sign - - crl sign - - encipher only - - decipher only - - any - - server auth - - client auth - - code signing - - email protection - - s/mime - - ipsec end system - - ipsec tunnel - - ipsec user - - timestamping - - ocsp signing - - microsoft sgc - - netscape sgc - type: string - type: array - required: - - issuerRef - - targetRef - type: object - status: - description: TLSPolicyStatus defines the observed state of TLSPolicy - properties: - conditions: - description: "conditions are any conditions associated with the policy - \n If configuring the policy fails, the \"Failed\" condition will - be set with a reason and message describing the cause of the failure." - items: - description: "Condition contains details for one aspect of the current - state of this API Resource. --- This struct is intended for direct - use as an array at the field path .status.conditions. For example, - \n type FooStatus struct{ // Represents the observations of a - foo's current state. // Known .status.conditions.type are: \"Available\", - \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge - // +listType=map // +listMapKey=type Conditions []metav1.Condition - `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" - protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" - properties: - lastTransitionTime: - description: lastTransitionTime is the last time the condition - transitioned from one status to another. This should be when - the underlying condition changed. If that is not known, then - using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: message is a human readable message indicating - details about the transition. This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: observedGeneration represents the .metadata.generation - that the condition was set based upon. For instance, if .metadata.generation - is currently 12, but the .status.conditions[x].observedGeneration - is 9, the condition is out of date with respect to the current - state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: reason contains a programmatic identifier indicating - the reason for the condition's last transition. Producers - of specific condition types may define expected values and - meanings for this field, and whether the values are considered - a guaranteed API. The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - --- Many .condition.type values are consistent across resources - like Available, but because arbitrary conditions can be useful - (see .node.status.conditions), the ability to deconflict is - important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - observedGeneration: - description: observedGeneration is the most recently observed generation - of the TLSPolicy. When the TLSPolicy is updated, the controller - updates the corresponding configuration. If an update fails, that - failure is recorded in the status condition - format: int64 - type: integer - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: null - storedVersions: null diff --git a/config/kuadrant/README.md b/config/kuadrant/README.md new file mode 100644 index 0000000..92b561e --- /dev/null +++ b/config/kuadrant/README.md @@ -0,0 +1,43 @@ +```bash +kubectl apply -f ./config/kuadrant/crd/ +kubectl patch clusterrole kube-state-metrics --type=json -p "$(cat ./config/kuadrant/clusterrole-patch.yaml)" +kubectl apply -f ./config/kuadrant/kuadrant.yaml +kubectl replace --subresource=status -f ./config/kuadrant/kuadrant.yaml +kubectl delete pods -n monitoring -l app.kubernetes.io/name=kube-state-metrics +``` + + +## 1. Apply the Kuadrant Resource Definitions (CRD) + +Apply the custom resource definitions (CRDs) required for Kuadrant + +```bash +kubectl apply -f ./config/kuadrant/crd/ +``` + +## 2. Patch the ClusterRole + +Patching an existing ClusterRole allows you to add specific permissions to it +```bash +kubectl patch clusterrole kube-state-metrics --type=json -p "$(cat ./config/kuadrant/clusterrole-patch.yaml)" +``` + +## 3. Deploy Kuadrant Components + +Deploy Kuadrant components to your cluster +```bash +kubectl apply -f ./config/kuadrant/kuadrant.yaml +``` +## 4. Update Kuadrant Resources + +Update the Kuadrant resources to reflect the desired status +```bash +kubectl replace --subresource=status -f ./config/kuadrant/kuadrant.yaml +``` + +## 5. Restart Pods + +Restart pods in the "monitoring" namespace matching the specified label selector +```bash +kubectl delete pods -n monitoring -l app.kubernetes.io/name=kube-state-metrics +``` \ No newline at end of file diff --git a/config/kuadrant/clusterrole-patch.yaml b/config/kuadrant/clusterrole-patch.yaml new file mode 100644 index 0000000..684cf2e --- /dev/null +++ b/config/kuadrant/clusterrole-patch.yaml @@ -0,0 +1,21 @@ +- op: add + path: /rules/- + value: + apiGroups: + - "apiextensions.k8s.io" + resources: + - customresourcedefinitions + verbs: + - list + - watch +- op: add + path: /rules/- + value: + apiGroups: + - "kuadrant.io" + resources: + - tlspolicies + - ratelimitpolicies + verbs: + - list + - watch diff --git a/config/kuadrant/crd/kuadrant.io_ratelimitpolicies.yaml b/config/kuadrant/crd/kuadrant.io_ratelimitpolicies.yaml new file mode 100644 index 0000000..48e7bf4 --- /dev/null +++ b/config/kuadrant/crd/kuadrant.io_ratelimitpolicies.yaml @@ -0,0 +1,245 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.10.0 + creationTimestamp: null + name: ratelimitpolicies.kuadrant.io +spec: + group: kuadrant.io + names: + kind: RateLimitPolicy + listKind: RateLimitPolicyList + plural: ratelimitpolicies + singular: ratelimitpolicy + scope: Namespaced + versions: + - name: v1beta2 + schema: + openAPIV3Schema: + description: RateLimitPolicy is the Schema for the ratelimitpolicies API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: RateLimitPolicySpec defines the desired state of RateLimitPolicy + properties: + limits: + additionalProperties: + description: Limit represents a complete rate limit configuration + properties: + counters: + description: Counters defines additional rate limit counters based on context qualifiers and well known selectors TODO Document properly "Well-known selector" https://github.com/Kuadrant/architecture/blob/main/rfcs/0001-rlp-v2.md#well-known-selectors + items: + description: 'ContextSelector defines one item from the well known attributes Attributes: https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/advanced/attributes Well-known selectors: https://github.com/Kuadrant/architecture/blob/main/rfcs/0001-rlp-v2.md#well-known-selectors They are named by a dot-separated path (e.g. request.path) Example: "request.path" -> The path portion of the URL' + maxLength: 253 + minLength: 1 + type: string + type: array + rates: + description: Rates holds the list of limit rates + items: + description: Rate defines the actual rate limit that will be used when there is a match + properties: + duration: + description: Duration defines the time period for which the Limit specified above applies. + type: integer + limit: + description: Limit defines the max value allowed for a given period of time + type: integer + unit: + description: 'Duration defines the time uni Possible values are: "second", "minute", "hour", "day"' + enum: + - second + - minute + - hour + - day + type: string + required: + - duration + - limit + - unit + type: object + type: array + routeSelectors: + description: RouteSelectors defines semantics for matching an HTTP request based on conditions + items: + description: RouteSelector defines semantics for matching an HTTP request based on conditions https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1beta1.HTTPRouteSpec + properties: + hostnames: + description: Hostnames defines a set of hostname that should match against the HTTP Host header to select a HTTPRoute to process the request https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1beta1.HTTPRouteSpec + items: + description: "Hostname is the fully qualified domain name of a network host. This matches the RFC 1123 definition of a hostname with 2 notable exceptions: \n 1. IPs are not allowed. 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard label must appear by itself as the first label. \n Hostname can be \"precise\" which is a domain name without the terminating dot of a network host (e.g. \"foo.example.com\") or \"wildcard\", which is a domain name prefixed with a single wildcard label (e.g. `*.example.com`). \n Note that as per RFC1035 and RFC1123, a *label* must consist of lower case alphanumeric characters or '-', and must start and end with an alphanumeric character. No other punctuation is allowed." + type: string + type: array + matches: + description: Matches define conditions used for matching the rule against incoming HTTP requests. https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1beta1.HTTPRouteSpec + items: + description: "HTTPRouteMatch defines the predicate used to match requests to a given action. Multiple match types are ANDed together, i.e. the match will evaluate to true only if all conditions are satisfied. \n For example, the match below will match a HTTP request only if its path starts with `/foo` AND it contains the `version: v1` header: \n ``` match: \n path: value: \"/foo\" headers: - name: \"version\" value \"v1\" \n ```" + properties: + headers: + description: Headers specifies HTTP request header matchers. Multiple match values are ANDed together, meaning, a request must match all the specified headers to select the route. + items: + description: HTTPHeaderMatch describes how to select a HTTP route by matching HTTP request headers. + properties: + name: + description: "Name is the name of the HTTP Header to be matched. Name matching MUST be case insensitive. (See https://tools.ietf.org/html/rfc7230#section-3.2). \n If multiple entries specify equivalent header names, only the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent header name MUST be ignored. Due to the case-insensitivity of header names, \"foo\" and \"Foo\" are considered equivalent. \n When a header is repeated in an HTTP request, it is implementation-specific behavior as to how this is represented. Generally, proxies should follow the guidance from the RFC: https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2 regarding processing a repeated header, with special handling for \"Set-Cookie\"." + type: string + type: + description: "Type specifies how to match against the value of the header. \n Support: Core (Exact) \n Support: Implementation-specific (RegularExpression) \n Since RegularExpression HeaderMatchType has implementation-specific conformance, implementations can support POSIX, PCRE or any other dialects of regular expressions. Please read the implementation's documentation to determine the supported dialect." + type: string + value: + description: Value is the value of HTTP Header to be matched. + type: string + required: + - name + - value + type: object + type: array + method: + description: "Method specifies HTTP method matcher. When specified, this route will be matched only if the request has the specified method. \n Support: Extended" + type: string + path: + description: Path specifies a HTTP request path matcher. If this field is not specified, a default prefix match on the "/" path is provided. + properties: + type: + description: "Type specifies how to match against the path Value. \n Support: Core (Exact, PathPrefix) \n Support: Implementation-specific (RegularExpression)" + type: string + value: + description: Value of the HTTP path to match against. + type: string + type: object + queryParams: + description: "QueryParams specifies HTTP query parameter matchers. Multiple match values are ANDed together, meaning, a request must match all the specified query parameters to select the route. \n Support: Extended" + items: + description: HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP query parameters. + properties: + name: + description: "Name is the name of the HTTP query param to be matched. This must be an exact string match. (See https://tools.ietf.org/html/rfc7230#section-2.7.3). \n If multiple entries specify equivalent query param names, only the first entry with an equivalent name MUST be considered for a match. Subsequent entries with an equivalent query param name MUST be ignored. \n If a query param is repeated in an HTTP request, the behavior is purposely left undefined, since different data planes have different capabilities. However, it is *recommended* that implementations should match against the first value of the param if the data plane supports it, as this behavior is expected in other load balancing contexts outside of the Gateway API. \n Users SHOULD NOT route traffic based on repeated query params to guard themselves against potential differences in the implementations." + type: string + type: + description: "Type specifies how to match against the value of the query parameter. \n Support: Extended (Exact) \n Support: Implementation-specific (RegularExpression) \n Since RegularExpression QueryParamMatchType has Implementation-specific conformance, implementations can support POSIX, PCRE or any other dialects of regular expressions. Please read the implementation's documentation to determine the supported dialect." + type: string + value: + description: Value is the value of HTTP query param to be matched. + type: string + required: + - name + - value + type: object + type: array + type: object + type: array + type: object + type: array + when: + description: When holds the list of conditions for the policy to be enforced. Called also "soft" conditions as route selectors must also match + items: + description: RouteSelector defines semantics for matching an HTTP request based on conditions https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1beta1.HTTPRouteSpec + properties: + operator: + description: 'The binary operator to be applied to the content fetched from the selector Possible values are: "eq" (equal to), "neq" (not equal to)' + enum: + - eq + - neq + - startswith + - endswith + - incl + - excl + - matches + type: string + selector: + description: Selector defines one item from the well known selectors TODO Document properly "Well-known selector" https://github.com/Kuadrant/architecture/blob/main/rfcs/0001-rlp-v2.md#well-known-selectors + maxLength: 253 + minLength: 1 + type: string + value: + description: The value of reference for the comparison. + type: string + required: + - operator + - selector + - value + type: object + type: array + type: object + description: Limits holds the struct of limits indexed by a unique name + type: object + targetRef: + description: TargetRef identifies an API object to apply policy to. + properties: + group: + description: Group is the group of the target resource. + type: string + kind: + description: Kind is kind of the target resource. + type: string + name: + description: Name is the name of the target resource. + type: string + namespace: + description: Namespace is the namespace of the referent. When unspecified, the local namespace is inferred. Even when policy targets a resource in a different namespace, it MUST only apply to traffic originating from the same namespace as the policy. + type: string + required: + - group + - kind + - name + type: object + required: + - targetRef + type: object + status: + description: RateLimitPolicyStatus defines the observed state of RateLimitPolicy + properties: + conditions: + description: 'Represents the observations of a foo''s current state. Known .status.conditions.type are: "Available"' + items: + description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, \n type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating details about the transition. This may be an empty string. + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. + format: int64 + type: integer + reason: + description: reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. + type: string + status: + description: status of the condition, one of True, False, Unknown. + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. --- Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + observedGeneration: + description: ObservedGeneration reflects the generation of the most recently observed spec. + format: int64 + type: integer + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/kuadrant/crd/kuadrant.io_tlspolicies.yaml b/config/kuadrant/crd/kuadrant.io_tlspolicies.yaml new file mode 100644 index 0000000..05d8830 --- /dev/null +++ b/config/kuadrant/crd/kuadrant.io_tlspolicies.yaml @@ -0,0 +1,216 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.10.0 + gateway.networking.k8s.io/policy: direct + creationTimestamp: null + name: tlspolicies.kuadrant.io +spec: + group: kuadrant.io + names: + kind: TLSPolicy + listKind: TLSPolicyList + plural: tlspolicies + singular: tlspolicy + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: TLSPolicy ready. + jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: TLSPolicy is the Schema for the tlspolicies API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: TLSPolicySpec defines the desired state of TLSPolicy + properties: + commonName: + description: 'CommonName is a common name to be used on the Certificate. The CommonName should have a length of 64 characters or fewer to avoid generating invalid CSRs. This value is ignored by TLS clients when any subject alt name is set. This is x509 behaviour: https://tools.ietf.org/html/rfc6125#section-6.4.4' + type: string + duration: + description: The requested 'duration' (i.e. lifetime) of the Certificate. This option may be ignored/overridden by some issuer types. If unset this defaults to 90 days. Certificate will be renewed either 2/3 through its duration or `renewBefore` period before its expiry, whichever is later. Minimum accepted duration is 1 hour. Value must be in units accepted by Go time.ParseDuration https://golang.org/pkg/time/#ParseDuration + type: string + issuerRef: + description: IssuerRef is a reference to the issuer for this certificate. If the `kind` field is not set, or set to `Issuer`, an Issuer resource with the given name in the same namespace as the Certificate will be used. If the `kind` field is set to `ClusterIssuer`, a ClusterIssuer with the provided name will be used. The `name` field in this stanza is required at all times. + properties: + group: + description: Group of the resource being referred to. + type: string + kind: + description: Kind of the resource being referred to. + type: string + name: + description: Name of the resource being referred to. + type: string + required: + - name + type: object + privateKey: + description: Options to control private keys used for the Certificate. + properties: + algorithm: + description: Algorithm is the private key algorithm of the corresponding private key for this certificate. If provided, allowed values are either `RSA`,`Ed25519` or `ECDSA` If `algorithm` is specified and `size` is not provided, key size of 256 will be used for `ECDSA` key algorithm and key size of 2048 will be used for `RSA` key algorithm. key size is ignored when using the `Ed25519` key algorithm. + enum: + - RSA + - ECDSA + - Ed25519 + type: string + encoding: + description: The private key cryptography standards (PKCS) encoding for this certificate's private key to be encoded in. If provided, allowed values are `PKCS1` and `PKCS8` standing for PKCS#1 and PKCS#8, respectively. Defaults to `PKCS1` if not specified. + enum: + - PKCS1 + - PKCS8 + type: string + rotationPolicy: + description: RotationPolicy controls how private keys should be regenerated when a re-issuance is being processed. If set to Never, a private key will only be generated if one does not already exist in the target `spec.secretName`. If one does exists but it does not have the correct algorithm or size, a warning will be raised to await user intervention. If set to Always, a private key matching the specified requirements will be generated whenever a re-issuance occurs. Default is 'Never' for backward compatibility. + type: string + size: + description: Size is the key bit size of the corresponding private key for this certificate. If `algorithm` is set to `RSA`, valid values are `2048`, `4096` or `8192`, and will default to `2048` if not specified. If `algorithm` is set to `ECDSA`, valid values are `256`, `384` or `521`, and will default to `256` if not specified. If `algorithm` is set to `Ed25519`, Size is ignored. No other values are allowed. + type: integer + type: object + renewBefore: + description: How long before the currently issued certificate's expiry cert-manager should renew the certificate. The default is 2/3 of the issued certificate's duration. Minimum accepted value is 5 minutes. Value must be in units accepted by Go time.ParseDuration https://golang.org/pkg/time/#ParseDuration + type: string + revisionHistoryLimit: + description: RevisionHistoryLimit is the maximum number of CertificateRequest revisions that are maintained in the Certificate's history. Each revision represents a single `CertificateRequest` created by this Certificate, either when it was created, renewed, or Spec was changed. Revisions will be removed by oldest first if the number of revisions exceeds this number. If set, revisionHistoryLimit must be a value of `1` or greater. If unset (`nil`), revisions will not be garbage collected. Default value is `nil`. + format: int32 + type: integer + targetRef: + description: PolicyTargetReference identifies an API object to apply policy to. This should be used as part of Policy resources that can target Gateway API resources. For more information on how this policy attachment model works, and a sample Policy resource, refer to the policy attachment documentation for Gateway API. + properties: + group: + description: Group is the group of the target resource. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + description: Kind is kind of the target resource. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the target resource. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: Namespace is the namespace of the referent. When unspecified, the local namespace is inferred. Even when policy targets a resource in a different namespace, it MUST only apply to traffic originating from the same namespace as the policy. + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - group + - kind + - name + type: object + usages: + description: Usages is the set of x509 usages that are requested for the certificate. Defaults to `digital signature` and `key encipherment` if not specified. + items: + description: 'KeyUsage specifies valid usage contexts for keys. See: https://tools.ietf.org/html/rfc5280#section-4.2.1.3 https://tools.ietf.org/html/rfc5280#section-4.2.1.12 Valid KeyUsage values are as follows: "signing", "digital signature", "content commitment", "key encipherment", "key agreement", "data encipherment", "cert sign", "crl sign", "encipher only", "decipher only", "any", "server auth", "client auth", "code signing", "email protection", "s/mime", "ipsec end system", "ipsec tunnel", "ipsec user", "timestamping", "ocsp signing", "microsoft sgc", "netscape sgc"' + enum: + - signing + - digital signature + - content commitment + - key encipherment + - key agreement + - data encipherment + - cert sign + - crl sign + - encipher only + - decipher only + - any + - server auth + - client auth + - code signing + - email protection + - s/mime + - ipsec end system + - ipsec tunnel + - ipsec user + - timestamping + - ocsp signing + - microsoft sgc + - netscape sgc + type: string + type: array + required: + - issuerRef + - targetRef + type: object + status: + description: TLSPolicyStatus defines the observed state of TLSPolicy + properties: + conditions: + description: "conditions are any conditions associated with the policy \n If configuring the policy fails, the \"Failed\" condition will be set with a reason and message describing the cause of the failure." + items: + description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, \n type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. --- Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + observedGeneration: + description: observedGeneration is the most recently observed generation of the TLSPolicy. When the TLSPolicy is updated, the controller updates the corresponding configuration. If an update fails, that failure is recorded in the status condition + format: int64 + type: integer + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null diff --git a/config/kuadrant/kuadrant.yaml b/config/kuadrant/kuadrant.yaml new file mode 100644 index 0000000..932f881 --- /dev/null +++ b/config/kuadrant/kuadrant.yaml @@ -0,0 +1,89 @@ +apiVersion: kuadrant.io/v1alpha1 +kind: TLSPolicy +metadata: + name: external + namespace: istio-system +spec: + targetRef: + name: external + group: gateway.networking.k8s.io + kind: Gateway + issuerRef: + group: cert-manager.io + kind: ClusterIssuer + name: selfsigned-cluster-issuer +status: + conditions: + - lastTransitionTime: "2023-08-21T22:53:08Z" + message: Gateway is TLS Enabled + reason: GatewayTLSEnabled + status: "True" + type: Ready +--- +apiVersion: kuadrant.io/v1alpha1 +kind: TLSPolicy +metadata: + name: internal + namespace: istio-system +spec: + targetRef: + name: internal + group: gateway.networking.k8s.io + kind: Gateway + issuerRef: + group: cert-manager.io + kind: ClusterIssuer + name: selfsigned-cluster-issuer +status: + conditions: + - lastTransitionTime: "2023-08-21T22:53:08Z" + message: Gateway is TLS Enabled + reason: GatewayTLSEnabled + status: "True" + type: Ready +--- +apiVersion: kuadrant.io/v1beta2 +kind: RateLimitPolicy +metadata: + name: rlp-www +spec: + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: www + limits: + "global": + rates: + - limit: 5 + duration: 10 + unit: second +status: + conditions: + - lastTransitionTime: "2023-08-21T22:53:08Z" + message: HTTPRoute is ratelimited + reason: HTTPRouteProtected + status: "True" + type: Available +--- +apiVersion: kuadrant.io/v1beta2 +kind: RateLimitPolicy +metadata: + name: rlp-cdn +spec: + targetRef: + group: gateway.networking.k8s.io + kind: HTTPRoute + name: cdn + limits: + "global": + rates: + - limit: 5 + duration: 10 + unit: second +status: + conditions: + - lastTransitionTime: "2023-08-21T22:53:08Z" + message: HTTPRoute is ratelimited + reason: HTTPRouteProtected + status: "True" + type: Available diff --git a/hack/local_dev.sh b/hack/local_dev.sh index ebecb40..e2b2f0d 100755 --- a/hack/local_dev.sh +++ b/hack/local_dev.sh @@ -12,6 +12,12 @@ kubectl replace --subresource=status -f ./config/examples/enterprise/all.yaml kubectl apply --server-side -f ./config/examples/kube-prometheus/bundle_crd.yaml kubectl apply -f ./config/examples/kube-prometheus/bundle.yaml +echo "Setting up kuadrant" +kubectl apply -f ./config/kuadrant/crd/ +kubectl patch clusterrole kube-state-metrics --type=json -p "$(cat ./config/kuadrant/clusterrole-patch.yaml)" +kubectl apply -f ./config/kuadrant/kuadrant.yaml +kubectl replace --subresource=status -f ./config/kuadrant/kuadrant.yaml + echo "Installing grafana-operator" helm upgrade -i grafana-operator oci://ghcr.io/grafana-operator/helm-charts/grafana-operator --version v5.4.1 From 964d15e3a64b77c2a77cbccbac6d767ab842d48b Mon Sep 17 00:00:00 2001 From: Ignas Baranauskas Date: Tue, 24 Oct 2023 16:37:13 +0100 Subject: [PATCH 4/5] Links back to target kind --- config/examples/dashboards/policies.json | 89 ++++++++++++++++++-- config/examples/dashboards/policies.yaml | 2 +- config/examples/kube-prometheus/bundle.yaml | 93 +++++++++++++++++++-- src/dashboards/policies.jsonnet | 14 ++-- 4 files changed, 174 insertions(+), 24 deletions(-) diff --git a/config/examples/dashboards/policies.json b/config/examples/dashboards/policies.json index 6d1f984..0d3281f 100644 --- a/config/examples/dashboards/policies.json +++ b/config/examples/dashboards/policies.json @@ -45,7 +45,7 @@ "type": "prometheus", "uid": "$datasource" }, - "expr": "count(gatewayapi_tlspolicy_status)", + "expr": "count(gatewayapi_tlspolicy_status{name=~\"${tlspolicy}\"})", "instant": true } ], @@ -72,7 +72,7 @@ "type": "prometheus", "uid": "$datasource" }, - "expr": "count(gatewayapi_tlspolicy_status{type=\"Ready\"})", + "expr": "count(gatewayapi_tlspolicy_status{type=\"Ready\", name=~\"${tlspolicy}\"})", "instant": true } ], @@ -84,6 +84,31 @@ "type": "prometheus", "uid": "$datasource" }, + "fieldConfig": { + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Target Kind" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "color-text" + }, + { + "id": "links", + "value": [ + { + "title": "TLSPolicy Details", + "url": "/d/gatewayapigateways/gateway-api-state-gateways?var-tlspolicy=${__value.text}" + } + ] + } + ] + } + ] + }, "gridPos": { "h": 6, "w": 10, @@ -98,7 +123,7 @@ "type": "prometheus", "uid": "$datasource" }, - "expr": "gatewayapi_tlspolicy_target_info", + "expr": "gatewayapi_tlspolicy_target_info{name=~\"${tlspolicy}\"}", "format": "table", "instant": true, "range": false @@ -162,7 +187,7 @@ "type": "prometheus", "uid": "$datasource" }, - "expr": "count(gatewayapi_ratelimitpolicy_status)", + "expr": "count(gatewayapi_ratelimitpolicy_status{name=~\"${ratelimitpolicy}\"})", "instant": true } ], @@ -189,7 +214,7 @@ "type": "prometheus", "uid": "$datasource" }, - "expr": "count(gatewayapi_ratelimitpolicy_status{type=\"Available\"})", + "expr": "count(gatewayapi_ratelimitpolicy_status{type=\"Available\", name=~\"${ratelimitpolicy}\"})", "instant": true } ], @@ -201,6 +226,31 @@ "type": "prometheus", "uid": "$datasource" }, + "fieldConfig": { + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Target Kind" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "color-text" + }, + { + "id": "links", + "value": [ + { + "title": "RateLimitPolicy Details", + "url": "/d/gatewayapihttproutes/gateway-api-state-httproutes?var-ratelimitpolicy=${__value.text}" + } + ] + } + ] + } + ] + }, "gridPos": { "h": 6, "w": 10, @@ -215,7 +265,7 @@ "type": "prometheus", "uid": "$datasource" }, - "expr": "gatewayapi_ratelimitpolicy_target_info", + "expr": "gatewayapi_ratelimitpolicy_target_info{name=~\"${ratelimitpolicy}\"}", "format": "table", "instant": true, "range": false @@ -264,6 +314,31 @@ "type": "prometheus", "uid": "$datasource" }, + "fieldConfig": { + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Target Kind" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "color-text" + }, + { + "id": "links", + "value": [ + { + "title": "BackendTLSPolicy Details", + "url": "/d/gatewayapipolicies/gateway-api-state-policies?var-backendtlspolicy=${__value.text}" + } + ] + } + ] + } + ] + }, "gridPos": { "h": 6, "w": 10, @@ -278,7 +353,7 @@ "type": "prometheus", "uid": "$datasource" }, - "expr": "gatewayapi_backendtlspolicy_target_info", + "expr": "gatewayapi_backendtlspolicy_target_info{name=~\"${backendtlspolicy}\"}", "format": "table", "instant": true, "range": false diff --git a/config/examples/dashboards/policies.yaml b/config/examples/dashboards/policies.yaml index 3ee86b6..4cb3101 100644 --- a/config/examples/dashboards/policies.yaml +++ b/config/examples/dashboards/policies.yaml @@ -7,4 +7,4 @@ spec: matchLabels: dashboards: "grafana" json: > - {"editable":false,"links":[{"asDropdown":false,"includeVars":true,"keepTime":true,"tags":["gateway-api-state"],"targetBlank":false,"title":"Gateway Dashboards","type":"dashboards"}],"panels":[{"gridPos":{"h":1,"w":24,"x":0,"y":0},"id":1,"title":"TLSPolicy","type":"row"},{"datasource":{"type":"prometheus","uid":"$datasource"},"description":"Total number of TLSPolicy across all clusters","gridPos":{"h":3,"w":2,"x":0,"y":1},"id":2,"pluginVersion":"v10.0.0","targets":[{"datasource":{"type":"prometheus","uid":"$datasource"},"expr":"count(gatewayapi_tlspolicy_status)","instant":true}],"title":"Total","type":"stat"},{"datasource":{"type":"prometheus","uid":"$datasource"},"description":"Total TLSPolicy with an Ready state","gridPos":{"h":3,"w":2,"x":2,"y":1},"id":3,"pluginVersion":"v10.0.0","targets":[{"datasource":{"type":"prometheus","uid":"$datasource"},"expr":"count(gatewayapi_tlspolicy_status{type=\"Ready\"})","instant":true}],"title":"Ready","type":"stat"},{"datasource":{"type":"prometheus","uid":"$datasource"},"gridPos":{"h":6,"w":10,"x":4,"y":1},"id":4,"pluginVersion":"v10.0.0","targets":[{"datasource":{"type":"prometheus","uid":"$datasource"},"expr":"gatewayapi_tlspolicy_target_info","format":"table","instant":true,"range":false}],"title":"TLSPolicy","transformations":[{"id":"filterFieldsByName","options":{"include":{"names":["name","target_kind","target_name"]}}},{"id":"organize","options":{"renameByName":{"name":"Name","target_kind":"Target Kind","target_name":"Target Name"}}}],"type":"table"},{"gridPos":{"h":1,"w":24,"x":0,"y":2},"id":5,"title":"RateLimitPolicy","type":"row"},{"datasource":{"type":"prometheus","uid":"$datasource"},"description":"Total number of RateLimitPolicy across all clusters","gridPos":{"h":3,"w":2,"x":0,"y":3},"id":6,"pluginVersion":"v10.0.0","targets":[{"datasource":{"type":"prometheus","uid":"$datasource"},"expr":"count(gatewayapi_ratelimitpolicy_status)","instant":true}],"title":"Total","type":"stat"},{"datasource":{"type":"prometheus","uid":"$datasource"},"description":"Total RateLimitPolicy with an Available state","gridPos":{"h":3,"w":2,"x":2,"y":3},"id":7,"pluginVersion":"v10.0.0","targets":[{"datasource":{"type":"prometheus","uid":"$datasource"},"expr":"count(gatewayapi_ratelimitpolicy_status{type=\"Available\"})","instant":true}],"title":"Available","type":"stat"},{"datasource":{"type":"prometheus","uid":"$datasource"},"gridPos":{"h":6,"w":10,"x":4,"y":7},"id":8,"pluginVersion":"v10.0.0","targets":[{"datasource":{"type":"prometheus","uid":"$datasource"},"expr":"gatewayapi_ratelimitpolicy_target_info","format":"table","instant":true,"range":false}],"title":"RateLimitPolicy","transformations":[{"id":"filterFieldsByName","options":{"include":{"names":["name","target_kind","target_name"]}}},{"id":"organize","options":{"renameByName":{"name":"Name","target_kind":"Target Kind","target_name":"Target Name"}}}],"type":"table"},{"gridPos":{"h":1,"w":24,"x":0,"y":8},"id":9,"title":"BackendTLSPolicy","type":"row"},{"datasource":{"type":"prometheus","uid":"$datasource"},"gridPos":{"h":6,"w":10,"x":4,"y":9},"id":10,"pluginVersion":"v10.0.0","targets":[{"datasource":{"type":"prometheus","uid":"$datasource"},"expr":"gatewayapi_backendtlspolicy_target_info","format":"table","instant":true,"range":false}],"title":"BackendTLSPolicy","transformations":[{"id":"filterFieldsByName","options":{"include":{"names":["name","target_kind","target_name"]}}},{"id":"organize","options":{"renameByName":{"name":"Name","target_kind":"Target Kind","target_name":"Target Name"}}}],"type":"table"}],"schemaVersion":36,"style":"dark","tags":["gateway-api","gateway-api-state"],"templating":{"list":[{"label":"Data Source","name":"datasource","query":"prometheus","type":"datasource"},{"datasource":{"type":"prometheus","uid":"${datasource}"},"includeAll":true,"label":"TLSPolicy","multi":true,"name":"tlspolicy","query":{"query":"label_values(gatewayapi_tlspolicy_created, name)","refId":"StandardVariableQuery"},"regex":"/(.*)/","type":"query"},{"datasource":{"type":"prometheus","uid":"${datasource}"},"includeAll":true,"label":"RateLimitPolicy","multi":true,"name":"ratelimitpolicy","query":{"query":"label_values(gatewayapi_ratelimitpolicy_created, name)","refId":"StandardVariableQuery"},"regex":"/(.*)/","type":"query"},{"datasource":{"type":"prometheus","uid":"${datasource}"},"includeAll":true,"label":"BackendTLSPolicy","multi":true,"name":"backendtlspolicy","query":{"query":"label_values(gatewayapi_backendtlspolicy_created, name)","refId":"StandardVariableQuery"},"regex":"/(.*)/","type":"query"}]},"time":{"from":"now-1h","to":"now"},"timezone":"utc","title":"Gateway API State / Policies","uid":"gatewayapipolicies"} + {"editable":false,"links":[{"asDropdown":false,"includeVars":true,"keepTime":true,"tags":["gateway-api-state"],"targetBlank":false,"title":"Gateway Dashboards","type":"dashboards"}],"panels":[{"gridPos":{"h":1,"w":24,"x":0,"y":0},"id":1,"title":"TLSPolicy","type":"row"},{"datasource":{"type":"prometheus","uid":"$datasource"},"description":"Total number of TLSPolicy across all clusters","gridPos":{"h":3,"w":2,"x":0,"y":1},"id":2,"pluginVersion":"v10.0.0","targets":[{"datasource":{"type":"prometheus","uid":"$datasource"},"expr":"count(gatewayapi_tlspolicy_status{name=~\"${tlspolicy}\"})","instant":true}],"title":"Total","type":"stat"},{"datasource":{"type":"prometheus","uid":"$datasource"},"description":"Total TLSPolicy with an Ready state","gridPos":{"h":3,"w":2,"x":2,"y":1},"id":3,"pluginVersion":"v10.0.0","targets":[{"datasource":{"type":"prometheus","uid":"$datasource"},"expr":"count(gatewayapi_tlspolicy_status{type=\"Ready\", name=~\"${tlspolicy}\"})","instant":true}],"title":"Ready","type":"stat"},{"datasource":{"type":"prometheus","uid":"$datasource"},"fieldConfig":{"overrides":[{"matcher":{"id":"byName","options":"Target Kind"},"properties":[{"id":"custom.displayMode","value":"color-text"},{"id":"links","value":[{"title":"TLSPolicy Details","url":"/d/gatewayapigateways/gateway-api-state-gateways?var-tlspolicy=${__value.text}"}]}]}]},"gridPos":{"h":6,"w":10,"x":4,"y":1},"id":4,"pluginVersion":"v10.0.0","targets":[{"datasource":{"type":"prometheus","uid":"$datasource"},"expr":"gatewayapi_tlspolicy_target_info{name=~\"${tlspolicy}\"}","format":"table","instant":true,"range":false}],"title":"TLSPolicy","transformations":[{"id":"filterFieldsByName","options":{"include":{"names":["name","target_kind","target_name"]}}},{"id":"organize","options":{"renameByName":{"name":"Name","target_kind":"Target Kind","target_name":"Target Name"}}}],"type":"table"},{"gridPos":{"h":1,"w":24,"x":0,"y":2},"id":5,"title":"RateLimitPolicy","type":"row"},{"datasource":{"type":"prometheus","uid":"$datasource"},"description":"Total number of RateLimitPolicy across all clusters","gridPos":{"h":3,"w":2,"x":0,"y":3},"id":6,"pluginVersion":"v10.0.0","targets":[{"datasource":{"type":"prometheus","uid":"$datasource"},"expr":"count(gatewayapi_ratelimitpolicy_status{name=~\"${ratelimitpolicy}\"})","instant":true}],"title":"Total","type":"stat"},{"datasource":{"type":"prometheus","uid":"$datasource"},"description":"Total RateLimitPolicy with an Available state","gridPos":{"h":3,"w":2,"x":2,"y":3},"id":7,"pluginVersion":"v10.0.0","targets":[{"datasource":{"type":"prometheus","uid":"$datasource"},"expr":"count(gatewayapi_ratelimitpolicy_status{type=\"Available\", name=~\"${ratelimitpolicy}\"})","instant":true}],"title":"Available","type":"stat"},{"datasource":{"type":"prometheus","uid":"$datasource"},"fieldConfig":{"overrides":[{"matcher":{"id":"byName","options":"Target Kind"},"properties":[{"id":"custom.displayMode","value":"color-text"},{"id":"links","value":[{"title":"RateLimitPolicy Details","url":"/d/gatewayapihttproutes/gateway-api-state-httproutes?var-ratelimitpolicy=${__value.text}"}]}]}]},"gridPos":{"h":6,"w":10,"x":4,"y":7},"id":8,"pluginVersion":"v10.0.0","targets":[{"datasource":{"type":"prometheus","uid":"$datasource"},"expr":"gatewayapi_ratelimitpolicy_target_info{name=~\"${ratelimitpolicy}\"}","format":"table","instant":true,"range":false}],"title":"RateLimitPolicy","transformations":[{"id":"filterFieldsByName","options":{"include":{"names":["name","target_kind","target_name"]}}},{"id":"organize","options":{"renameByName":{"name":"Name","target_kind":"Target Kind","target_name":"Target Name"}}}],"type":"table"},{"gridPos":{"h":1,"w":24,"x":0,"y":8},"id":9,"title":"BackendTLSPolicy","type":"row"},{"datasource":{"type":"prometheus","uid":"$datasource"},"fieldConfig":{"overrides":[{"matcher":{"id":"byName","options":"Target Kind"},"properties":[{"id":"custom.displayMode","value":"color-text"},{"id":"links","value":[{"title":"BackendTLSPolicy Details","url":"/d/gatewayapipolicies/gateway-api-state-policies?var-backendtlspolicy=${__value.text}"}]}]}]},"gridPos":{"h":6,"w":10,"x":4,"y":9},"id":10,"pluginVersion":"v10.0.0","targets":[{"datasource":{"type":"prometheus","uid":"$datasource"},"expr":"gatewayapi_backendtlspolicy_target_info{name=~\"${backendtlspolicy}\"}","format":"table","instant":true,"range":false}],"title":"BackendTLSPolicy","transformations":[{"id":"filterFieldsByName","options":{"include":{"names":["name","target_kind","target_name"]}}},{"id":"organize","options":{"renameByName":{"name":"Name","target_kind":"Target Kind","target_name":"Target Name"}}}],"type":"table"}],"schemaVersion":36,"style":"dark","tags":["gateway-api","gateway-api-state"],"templating":{"list":[{"label":"Data Source","name":"datasource","query":"prometheus","type":"datasource"},{"datasource":{"type":"prometheus","uid":"${datasource}"},"includeAll":true,"label":"TLSPolicy","multi":true,"name":"tlspolicy","query":{"query":"label_values(gatewayapi_tlspolicy_created, name)","refId":"StandardVariableQuery"},"regex":"/(.*)/","type":"query"},{"datasource":{"type":"prometheus","uid":"${datasource}"},"includeAll":true,"label":"RateLimitPolicy","multi":true,"name":"ratelimitpolicy","query":{"query":"label_values(gatewayapi_ratelimitpolicy_created, name)","refId":"StandardVariableQuery"},"regex":"/(.*)/","type":"query"},{"datasource":{"type":"prometheus","uid":"${datasource}"},"includeAll":true,"label":"BackendTLSPolicy","multi":true,"name":"backendtlspolicy","query":{"query":"label_values(gatewayapi_backendtlspolicy_created, name)","refId":"StandardVariableQuery"},"regex":"/(.*)/","type":"query"}]},"time":{"from":"now-1h","to":"now"},"timezone":"utc","title":"Gateway API State / Policies","uid":"gatewayapipolicies"} diff --git a/config/examples/kube-prometheus/bundle.yaml b/config/examples/kube-prometheus/bundle.yaml index de5e935..d31fd52 100644 --- a/config/examples/kube-prometheus/bundle.yaml +++ b/config/examples/kube-prometheus/bundle.yaml @@ -41245,7 +41245,7 @@ data: "type": "prometheus", "uid": "$datasource" }, - "expr": "count(gatewayapi_tlspolicy_status)", + "expr": "count(gatewayapi_tlspolicy_status{name=~\"${tlspolicy}\"})", "instant": true } ], @@ -41272,7 +41272,7 @@ data: "type": "prometheus", "uid": "$datasource" }, - "expr": "count(gatewayapi_tlspolicy_status{type=\"Ready\"})", + "expr": "count(gatewayapi_tlspolicy_status{type=\"Ready\", name=~\"${tlspolicy}\"})", "instant": true } ], @@ -41284,6 +41284,31 @@ data: "type": "prometheus", "uid": "$datasource" }, + "fieldConfig": { + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Target Kind" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "color-text" + }, + { + "id": "links", + "value": [ + { + "title": "TLSPolicy Details", + "url": "/d/gatewayapigateways/gateway-api-state-gateways?var-tlspolicy=${__value.text}" + } + ] + } + ] + } + ] + }, "gridPos": { "h": 6, "w": 10, @@ -41298,7 +41323,7 @@ data: "type": "prometheus", "uid": "$datasource" }, - "expr": "gatewayapi_tlspolicy_target_info", + "expr": "gatewayapi_tlspolicy_target_info{name=~\"${tlspolicy}\"}", "format": "table", "instant": true, "range": false @@ -41362,7 +41387,7 @@ data: "type": "prometheus", "uid": "$datasource" }, - "expr": "count(gatewayapi_ratelimitpolicy_status)", + "expr": "count(gatewayapi_ratelimitpolicy_status{name=~\"${ratelimitpolicy}\"})", "instant": true } ], @@ -41389,7 +41414,7 @@ data: "type": "prometheus", "uid": "$datasource" }, - "expr": "count(gatewayapi_ratelimitpolicy_status{type=\"Available\"})", + "expr": "count(gatewayapi_ratelimitpolicy_status{type=\"Available\", name=~\"${ratelimitpolicy}\"})", "instant": true } ], @@ -41401,6 +41426,31 @@ data: "type": "prometheus", "uid": "$datasource" }, + "fieldConfig": { + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Target Kind" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "color-text" + }, + { + "id": "links", + "value": [ + { + "title": "RateLimitPolicy Details", + "url": "/d/gatewayapihttproutes/gateway-api-state-httproutes?var-ratelimitpolicy=${__value.text}" + } + ] + } + ] + } + ] + }, "gridPos": { "h": 6, "w": 10, @@ -41415,7 +41465,7 @@ data: "type": "prometheus", "uid": "$datasource" }, - "expr": "gatewayapi_ratelimitpolicy_target_info", + "expr": "gatewayapi_ratelimitpolicy_target_info{name=~\"${ratelimitpolicy}\"}", "format": "table", "instant": true, "range": false @@ -41464,6 +41514,31 @@ data: "type": "prometheus", "uid": "$datasource" }, + "fieldConfig": { + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Target Kind" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "color-text" + }, + { + "id": "links", + "value": [ + { + "title": "BackendTLSPolicy Details", + "url": "/d/gatewayapipolicies/gateway-api-state-policies?var-backendtlspolicy=${__value.text}" + } + ] + } + ] + } + ] + }, "gridPos": { "h": 6, "w": 10, @@ -41478,7 +41553,7 @@ data: "type": "prometheus", "uid": "$datasource" }, - "expr": "gatewayapi_backendtlspolicy_target_info", + "expr": "gatewayapi_backendtlspolicy_target_info{name=~\"${backendtlspolicy}\"}", "format": "table", "instant": true, "range": false @@ -41586,7 +41661,7 @@ data: } kind: ConfigMap metadata: - name: grafana-policies-bggb44htkm + name: grafana-policies-c2dmf9dm7k namespace: monitoring --- @@ -44341,7 +44416,7 @@ spec: name: grafana-tlsroutes - configMap: defaultMode: 420 - name: grafana-policies-bggb44htkm + name: grafana-policies-c2dmf9dm7k name: grafana-policies - configMap: defaultMode: 420 diff --git a/src/dashboards/policies.jsonnet b/src/dashboards/policies.jsonnet index 85d5042..76b818a 100644 --- a/src/dashboards/policies.jsonnet +++ b/src/dashboards/policies.jsonnet @@ -9,13 +9,13 @@ gwapi.dashboard('Policies', 'gatewayapipolicies', [ ]) + g.dashboard.withPanels([ gwapi.row('TLSPolicy', 1, 24, 0, 0), - gwapi.stat('Total', 3, 2, 0, 1, 'Total number of TLSPolicy across all clusters', 'count(gatewayapi_tlspolicy_status)'), - gwapi.stat('Ready', 3, 2, 2, 1, 'Total TLSPolicy with an Ready state', 'count(gatewayapi_tlspolicy_status{type="Ready"})'), - gwapi.policyPanel('TLSPolicy',6,10,4,1,'gatewayapi_tlspolicy_target_info'), + gwapi.stat('Total', 3, 2, 0, 1, 'Total number of TLSPolicy across all clusters', 'count(gatewayapi_tlspolicy_status{name=~"${tlspolicy}"})'), + gwapi.stat('Ready', 3, 2, 2, 1, 'Total TLSPolicy with an Ready state', 'count(gatewayapi_tlspolicy_status{type="Ready", name=~"${tlspolicy}"})'), + gwapi.policyPanel('TLSPolicy',6,10,4,1,'gatewayapi_tlspolicy_target_info{name=~"${tlspolicy}"}', 'TLSPolicy Details', '/d/gatewayapigateways/gateway-api-state-gateways?var-tlspolicy=${__value.text}'), gwapi.row('RateLimitPolicy', 1, 24, 0, 2), - gwapi.stat('Total', 3, 2, 0, 3, 'Total number of RateLimitPolicy across all clusters', 'count(gatewayapi_ratelimitpolicy_status)'), - gwapi.stat('Available', 3, 2, 2, 3, 'Total RateLimitPolicy with an Available state', 'count(gatewayapi_ratelimitpolicy_status{type="Available"})'), - gwapi.policyPanel('RateLimitPolicy',6,10,4,7,'gatewayapi_ratelimitpolicy_target_info'), + gwapi.stat('Total', 3, 2, 0, 3, 'Total number of RateLimitPolicy across all clusters', 'count(gatewayapi_ratelimitpolicy_status{name=~"${ratelimitpolicy}"})'), + gwapi.stat('Available', 3, 2, 2, 3, 'Total RateLimitPolicy with an Available state', 'count(gatewayapi_ratelimitpolicy_status{type="Available", name=~"${ratelimitpolicy}"})'), + gwapi.policyPanel('RateLimitPolicy',6,10,4,7,'gatewayapi_ratelimitpolicy_target_info{name=~"${ratelimitpolicy}"}', 'RateLimitPolicy Details', '/d/gatewayapihttproutes/gateway-api-state-httproutes?var-ratelimitpolicy=${__value.text}'), gwapi.row('BackendTLSPolicy', 1, 24, 0, 8), - gwapi.policyPanel('BackendTLSPolicy',6,10,4,9,'gatewayapi_backendtlspolicy_target_info'), + gwapi.policyPanel('BackendTLSPolicy',6,10,4,9,'gatewayapi_backendtlspolicy_target_info{name=~"${backendtlspolicy}"}', 'BackendTLSPolicy Details', '/d/gatewayapipolicies/gateway-api-state-policies?var-backendtlspolicy=${__value.text}'), ]) \ No newline at end of file From fca95624ef728e7cc0c35c6aa10dd9a44f39a1a3 Mon Sep 17 00:00:00 2001 From: Ignas Baranauskas Date: Tue, 24 Oct 2023 18:03:56 +0100 Subject: [PATCH 5/5] Links are optional --- config/examples/dashboards/policies.json | 24 +----------------- config/examples/dashboards/policies.yaml | 2 +- config/examples/kube-prometheus/bundle.yaml | 28 +++------------------ src/dashboards/lib/gwapi/gwapi.libsonnet | 21 ++++++++++++++-- src/dashboards/policies.jsonnet | 2 +- 5 files changed, 25 insertions(+), 52 deletions(-) diff --git a/config/examples/dashboards/policies.json b/config/examples/dashboards/policies.json index 0d3281f..7780a90 100644 --- a/config/examples/dashboards/policies.json +++ b/config/examples/dashboards/policies.json @@ -315,29 +315,7 @@ "uid": "$datasource" }, "fieldConfig": { - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Target Kind" - }, - "properties": [ - { - "id": "custom.displayMode", - "value": "color-text" - }, - { - "id": "links", - "value": [ - { - "title": "BackendTLSPolicy Details", - "url": "/d/gatewayapipolicies/gateway-api-state-policies?var-backendtlspolicy=${__value.text}" - } - ] - } - ] - } - ] + "overrides": [ ] }, "gridPos": { "h": 6, diff --git a/config/examples/dashboards/policies.yaml b/config/examples/dashboards/policies.yaml index 4cb3101..9eec624 100644 --- a/config/examples/dashboards/policies.yaml +++ b/config/examples/dashboards/policies.yaml @@ -7,4 +7,4 @@ spec: matchLabels: dashboards: "grafana" json: > - {"editable":false,"links":[{"asDropdown":false,"includeVars":true,"keepTime":true,"tags":["gateway-api-state"],"targetBlank":false,"title":"Gateway Dashboards","type":"dashboards"}],"panels":[{"gridPos":{"h":1,"w":24,"x":0,"y":0},"id":1,"title":"TLSPolicy","type":"row"},{"datasource":{"type":"prometheus","uid":"$datasource"},"description":"Total number of TLSPolicy across all clusters","gridPos":{"h":3,"w":2,"x":0,"y":1},"id":2,"pluginVersion":"v10.0.0","targets":[{"datasource":{"type":"prometheus","uid":"$datasource"},"expr":"count(gatewayapi_tlspolicy_status{name=~\"${tlspolicy}\"})","instant":true}],"title":"Total","type":"stat"},{"datasource":{"type":"prometheus","uid":"$datasource"},"description":"Total TLSPolicy with an Ready state","gridPos":{"h":3,"w":2,"x":2,"y":1},"id":3,"pluginVersion":"v10.0.0","targets":[{"datasource":{"type":"prometheus","uid":"$datasource"},"expr":"count(gatewayapi_tlspolicy_status{type=\"Ready\", name=~\"${tlspolicy}\"})","instant":true}],"title":"Ready","type":"stat"},{"datasource":{"type":"prometheus","uid":"$datasource"},"fieldConfig":{"overrides":[{"matcher":{"id":"byName","options":"Target Kind"},"properties":[{"id":"custom.displayMode","value":"color-text"},{"id":"links","value":[{"title":"TLSPolicy Details","url":"/d/gatewayapigateways/gateway-api-state-gateways?var-tlspolicy=${__value.text}"}]}]}]},"gridPos":{"h":6,"w":10,"x":4,"y":1},"id":4,"pluginVersion":"v10.0.0","targets":[{"datasource":{"type":"prometheus","uid":"$datasource"},"expr":"gatewayapi_tlspolicy_target_info{name=~\"${tlspolicy}\"}","format":"table","instant":true,"range":false}],"title":"TLSPolicy","transformations":[{"id":"filterFieldsByName","options":{"include":{"names":["name","target_kind","target_name"]}}},{"id":"organize","options":{"renameByName":{"name":"Name","target_kind":"Target Kind","target_name":"Target Name"}}}],"type":"table"},{"gridPos":{"h":1,"w":24,"x":0,"y":2},"id":5,"title":"RateLimitPolicy","type":"row"},{"datasource":{"type":"prometheus","uid":"$datasource"},"description":"Total number of RateLimitPolicy across all clusters","gridPos":{"h":3,"w":2,"x":0,"y":3},"id":6,"pluginVersion":"v10.0.0","targets":[{"datasource":{"type":"prometheus","uid":"$datasource"},"expr":"count(gatewayapi_ratelimitpolicy_status{name=~\"${ratelimitpolicy}\"})","instant":true}],"title":"Total","type":"stat"},{"datasource":{"type":"prometheus","uid":"$datasource"},"description":"Total RateLimitPolicy with an Available state","gridPos":{"h":3,"w":2,"x":2,"y":3},"id":7,"pluginVersion":"v10.0.0","targets":[{"datasource":{"type":"prometheus","uid":"$datasource"},"expr":"count(gatewayapi_ratelimitpolicy_status{type=\"Available\", name=~\"${ratelimitpolicy}\"})","instant":true}],"title":"Available","type":"stat"},{"datasource":{"type":"prometheus","uid":"$datasource"},"fieldConfig":{"overrides":[{"matcher":{"id":"byName","options":"Target Kind"},"properties":[{"id":"custom.displayMode","value":"color-text"},{"id":"links","value":[{"title":"RateLimitPolicy Details","url":"/d/gatewayapihttproutes/gateway-api-state-httproutes?var-ratelimitpolicy=${__value.text}"}]}]}]},"gridPos":{"h":6,"w":10,"x":4,"y":7},"id":8,"pluginVersion":"v10.0.0","targets":[{"datasource":{"type":"prometheus","uid":"$datasource"},"expr":"gatewayapi_ratelimitpolicy_target_info{name=~\"${ratelimitpolicy}\"}","format":"table","instant":true,"range":false}],"title":"RateLimitPolicy","transformations":[{"id":"filterFieldsByName","options":{"include":{"names":["name","target_kind","target_name"]}}},{"id":"organize","options":{"renameByName":{"name":"Name","target_kind":"Target Kind","target_name":"Target Name"}}}],"type":"table"},{"gridPos":{"h":1,"w":24,"x":0,"y":8},"id":9,"title":"BackendTLSPolicy","type":"row"},{"datasource":{"type":"prometheus","uid":"$datasource"},"fieldConfig":{"overrides":[{"matcher":{"id":"byName","options":"Target Kind"},"properties":[{"id":"custom.displayMode","value":"color-text"},{"id":"links","value":[{"title":"BackendTLSPolicy Details","url":"/d/gatewayapipolicies/gateway-api-state-policies?var-backendtlspolicy=${__value.text}"}]}]}]},"gridPos":{"h":6,"w":10,"x":4,"y":9},"id":10,"pluginVersion":"v10.0.0","targets":[{"datasource":{"type":"prometheus","uid":"$datasource"},"expr":"gatewayapi_backendtlspolicy_target_info{name=~\"${backendtlspolicy}\"}","format":"table","instant":true,"range":false}],"title":"BackendTLSPolicy","transformations":[{"id":"filterFieldsByName","options":{"include":{"names":["name","target_kind","target_name"]}}},{"id":"organize","options":{"renameByName":{"name":"Name","target_kind":"Target Kind","target_name":"Target Name"}}}],"type":"table"}],"schemaVersion":36,"style":"dark","tags":["gateway-api","gateway-api-state"],"templating":{"list":[{"label":"Data Source","name":"datasource","query":"prometheus","type":"datasource"},{"datasource":{"type":"prometheus","uid":"${datasource}"},"includeAll":true,"label":"TLSPolicy","multi":true,"name":"tlspolicy","query":{"query":"label_values(gatewayapi_tlspolicy_created, name)","refId":"StandardVariableQuery"},"regex":"/(.*)/","type":"query"},{"datasource":{"type":"prometheus","uid":"${datasource}"},"includeAll":true,"label":"RateLimitPolicy","multi":true,"name":"ratelimitpolicy","query":{"query":"label_values(gatewayapi_ratelimitpolicy_created, name)","refId":"StandardVariableQuery"},"regex":"/(.*)/","type":"query"},{"datasource":{"type":"prometheus","uid":"${datasource}"},"includeAll":true,"label":"BackendTLSPolicy","multi":true,"name":"backendtlspolicy","query":{"query":"label_values(gatewayapi_backendtlspolicy_created, name)","refId":"StandardVariableQuery"},"regex":"/(.*)/","type":"query"}]},"time":{"from":"now-1h","to":"now"},"timezone":"utc","title":"Gateway API State / Policies","uid":"gatewayapipolicies"} + {"editable":false,"links":[{"asDropdown":false,"includeVars":true,"keepTime":true,"tags":["gateway-api-state"],"targetBlank":false,"title":"Gateway Dashboards","type":"dashboards"}],"panels":[{"gridPos":{"h":1,"w":24,"x":0,"y":0},"id":1,"title":"TLSPolicy","type":"row"},{"datasource":{"type":"prometheus","uid":"$datasource"},"description":"Total number of TLSPolicy across all clusters","gridPos":{"h":3,"w":2,"x":0,"y":1},"id":2,"pluginVersion":"v10.0.0","targets":[{"datasource":{"type":"prometheus","uid":"$datasource"},"expr":"count(gatewayapi_tlspolicy_status{name=~\"${tlspolicy}\"})","instant":true}],"title":"Total","type":"stat"},{"datasource":{"type":"prometheus","uid":"$datasource"},"description":"Total TLSPolicy with an Ready state","gridPos":{"h":3,"w":2,"x":2,"y":1},"id":3,"pluginVersion":"v10.0.0","targets":[{"datasource":{"type":"prometheus","uid":"$datasource"},"expr":"count(gatewayapi_tlspolicy_status{type=\"Ready\", name=~\"${tlspolicy}\"})","instant":true}],"title":"Ready","type":"stat"},{"datasource":{"type":"prometheus","uid":"$datasource"},"fieldConfig":{"overrides":[{"matcher":{"id":"byName","options":"Target Kind"},"properties":[{"id":"custom.displayMode","value":"color-text"},{"id":"links","value":[{"title":"TLSPolicy Details","url":"/d/gatewayapigateways/gateway-api-state-gateways?var-tlspolicy=${__value.text}"}]}]}]},"gridPos":{"h":6,"w":10,"x":4,"y":1},"id":4,"pluginVersion":"v10.0.0","targets":[{"datasource":{"type":"prometheus","uid":"$datasource"},"expr":"gatewayapi_tlspolicy_target_info{name=~\"${tlspolicy}\"}","format":"table","instant":true,"range":false}],"title":"TLSPolicy","transformations":[{"id":"filterFieldsByName","options":{"include":{"names":["name","target_kind","target_name"]}}},{"id":"organize","options":{"renameByName":{"name":"Name","target_kind":"Target Kind","target_name":"Target Name"}}}],"type":"table"},{"gridPos":{"h":1,"w":24,"x":0,"y":2},"id":5,"title":"RateLimitPolicy","type":"row"},{"datasource":{"type":"prometheus","uid":"$datasource"},"description":"Total number of RateLimitPolicy across all clusters","gridPos":{"h":3,"w":2,"x":0,"y":3},"id":6,"pluginVersion":"v10.0.0","targets":[{"datasource":{"type":"prometheus","uid":"$datasource"},"expr":"count(gatewayapi_ratelimitpolicy_status{name=~\"${ratelimitpolicy}\"})","instant":true}],"title":"Total","type":"stat"},{"datasource":{"type":"prometheus","uid":"$datasource"},"description":"Total RateLimitPolicy with an Available state","gridPos":{"h":3,"w":2,"x":2,"y":3},"id":7,"pluginVersion":"v10.0.0","targets":[{"datasource":{"type":"prometheus","uid":"$datasource"},"expr":"count(gatewayapi_ratelimitpolicy_status{type=\"Available\", name=~\"${ratelimitpolicy}\"})","instant":true}],"title":"Available","type":"stat"},{"datasource":{"type":"prometheus","uid":"$datasource"},"fieldConfig":{"overrides":[{"matcher":{"id":"byName","options":"Target Kind"},"properties":[{"id":"custom.displayMode","value":"color-text"},{"id":"links","value":[{"title":"RateLimitPolicy Details","url":"/d/gatewayapihttproutes/gateway-api-state-httproutes?var-ratelimitpolicy=${__value.text}"}]}]}]},"gridPos":{"h":6,"w":10,"x":4,"y":7},"id":8,"pluginVersion":"v10.0.0","targets":[{"datasource":{"type":"prometheus","uid":"$datasource"},"expr":"gatewayapi_ratelimitpolicy_target_info{name=~\"${ratelimitpolicy}\"}","format":"table","instant":true,"range":false}],"title":"RateLimitPolicy","transformations":[{"id":"filterFieldsByName","options":{"include":{"names":["name","target_kind","target_name"]}}},{"id":"organize","options":{"renameByName":{"name":"Name","target_kind":"Target Kind","target_name":"Target Name"}}}],"type":"table"},{"gridPos":{"h":1,"w":24,"x":0,"y":8},"id":9,"title":"BackendTLSPolicy","type":"row"},{"datasource":{"type":"prometheus","uid":"$datasource"},"fieldConfig":{"overrides":[]},"gridPos":{"h":6,"w":10,"x":4,"y":9},"id":10,"pluginVersion":"v10.0.0","targets":[{"datasource":{"type":"prometheus","uid":"$datasource"},"expr":"gatewayapi_backendtlspolicy_target_info{name=~\"${backendtlspolicy}\"}","format":"table","instant":true,"range":false}],"title":"BackendTLSPolicy","transformations":[{"id":"filterFieldsByName","options":{"include":{"names":["name","target_kind","target_name"]}}},{"id":"organize","options":{"renameByName":{"name":"Name","target_kind":"Target Kind","target_name":"Target Name"}}}],"type":"table"}],"schemaVersion":36,"style":"dark","tags":["gateway-api","gateway-api-state"],"templating":{"list":[{"label":"Data Source","name":"datasource","query":"prometheus","type":"datasource"},{"datasource":{"type":"prometheus","uid":"${datasource}"},"includeAll":true,"label":"TLSPolicy","multi":true,"name":"tlspolicy","query":{"query":"label_values(gatewayapi_tlspolicy_created, name)","refId":"StandardVariableQuery"},"regex":"/(.*)/","type":"query"},{"datasource":{"type":"prometheus","uid":"${datasource}"},"includeAll":true,"label":"RateLimitPolicy","multi":true,"name":"ratelimitpolicy","query":{"query":"label_values(gatewayapi_ratelimitpolicy_created, name)","refId":"StandardVariableQuery"},"regex":"/(.*)/","type":"query"},{"datasource":{"type":"prometheus","uid":"${datasource}"},"includeAll":true,"label":"BackendTLSPolicy","multi":true,"name":"backendtlspolicy","query":{"query":"label_values(gatewayapi_backendtlspolicy_created, name)","refId":"StandardVariableQuery"},"regex":"/(.*)/","type":"query"}]},"time":{"from":"now-1h","to":"now"},"timezone":"utc","title":"Gateway API State / Policies","uid":"gatewayapipolicies"} diff --git a/config/examples/kube-prometheus/bundle.yaml b/config/examples/kube-prometheus/bundle.yaml index d31fd52..3fa64e1 100644 --- a/config/examples/kube-prometheus/bundle.yaml +++ b/config/examples/kube-prometheus/bundle.yaml @@ -41515,29 +41515,7 @@ data: "uid": "$datasource" }, "fieldConfig": { - "overrides": [ - { - "matcher": { - "id": "byName", - "options": "Target Kind" - }, - "properties": [ - { - "id": "custom.displayMode", - "value": "color-text" - }, - { - "id": "links", - "value": [ - { - "title": "BackendTLSPolicy Details", - "url": "/d/gatewayapipolicies/gateway-api-state-policies?var-backendtlspolicy=${__value.text}" - } - ] - } - ] - } - ] + "overrides": [ ] }, "gridPos": { "h": 6, @@ -41661,7 +41639,7 @@ data: } kind: ConfigMap metadata: - name: grafana-policies-c2dmf9dm7k + name: grafana-policies-7kt676htbd namespace: monitoring --- @@ -44416,7 +44394,7 @@ spec: name: grafana-tlsroutes - configMap: defaultMode: 420 - name: grafana-policies-c2dmf9dm7k + name: grafana-policies-7kt676htbd name: grafana-policies - configMap: defaultMode: 420 diff --git a/src/dashboards/lib/gwapi/gwapi.libsonnet b/src/dashboards/lib/gwapi/gwapi.libsonnet index 3c13685..4ca0e7d 100644 --- a/src/dashboards/lib/gwapi/gwapi.libsonnet +++ b/src/dashboards/lib/gwapi/gwapi.libsonnet @@ -278,7 +278,7 @@ local var = import './variables.libsonnet'; }), ]), - policyPanel(title, h, w, x, y, expr): + policyPanel(title, h, w, x, y, expr, linkTitle="", linkUrl=""): self.table(title, h, w, x, y, expr) + g.panel.table.queryOptions.withTransformations([ g.panel.table.transformation.withId('filterFieldsByName') @@ -299,5 +299,22 @@ local var = import './variables.libsonnet'; target_name: 'Target Name', }, }), - ]), + ]) + + g.panel.table.standardOptions.withOverrides((if linkTitle != "" && linkUrl != "" then [ + g.panel.table.fieldOverride.byName.new('Target Kind') + + g.panel.table.fieldOverride.byName.withProperty( + 'custom.displayMode', + 'color-text' + ) + + g.panel.table.fieldOverride.byName.withProperty( + 'links', + [ + { + title: linkTitle, + url: linkUrl, + }, + ] + ), + ]else []) + ), } \ No newline at end of file diff --git a/src/dashboards/policies.jsonnet b/src/dashboards/policies.jsonnet index 76b818a..bad4aa9 100644 --- a/src/dashboards/policies.jsonnet +++ b/src/dashboards/policies.jsonnet @@ -17,5 +17,5 @@ gwapi.dashboard('Policies', 'gatewayapipolicies', [ gwapi.stat('Available', 3, 2, 2, 3, 'Total RateLimitPolicy with an Available state', 'count(gatewayapi_ratelimitpolicy_status{type="Available", name=~"${ratelimitpolicy}"})'), gwapi.policyPanel('RateLimitPolicy',6,10,4,7,'gatewayapi_ratelimitpolicy_target_info{name=~"${ratelimitpolicy}"}', 'RateLimitPolicy Details', '/d/gatewayapihttproutes/gateway-api-state-httproutes?var-ratelimitpolicy=${__value.text}'), gwapi.row('BackendTLSPolicy', 1, 24, 0, 8), - gwapi.policyPanel('BackendTLSPolicy',6,10,4,9,'gatewayapi_backendtlspolicy_target_info{name=~"${backendtlspolicy}"}', 'BackendTLSPolicy Details', '/d/gatewayapipolicies/gateway-api-state-policies?var-backendtlspolicy=${__value.text}'), + gwapi.policyPanel('BackendTLSPolicy',6,10,4,9,'gatewayapi_backendtlspolicy_target_info{name=~"${backendtlspolicy}"}'), ]) \ No newline at end of file