From 91999f5b955333eae87c8121cf3f2883995f86cf Mon Sep 17 00:00:00 2001 From: Pete Wall Date: Tue, 1 Oct 2024 09:28:03 -0500 Subject: [PATCH] add integration feature Signed-off-by: Pete Wall --- .github/workflows/test-feature-charts.yml | 2 +- Makefile | 4 +- .../feature-annotation-autodiscovery/Makefile | 10 +- .../Makefile | 10 +- charts/feature-cluster-events/Makefile | 10 +- charts/feature-cluster-metrics/Makefile | 10 +- .../feature-frontend-observability/Makefile | 10 +- charts/feature-integrations/.helmignore | 5 + charts/feature-integrations/Chart.lock | 3 + charts/feature-integrations/Chart.yaml | 7 + charts/feature-integrations/Makefile | 94 +++++ charts/feature-integrations/README.md | 42 +++ .../alloy-integration.yaml | 105 ++++++ .../default-allow-lists/alloy.yaml | 3 + .../docs/integrations/README.md | 11 + .../docs/integrations/alloy.md | 30 ++ .../docs/integrations/cert-manager.md | 31 ++ .../docs/integrations/etcd.md | 31 ++ .../integrations/alloy-values.yaml | 37 ++ .../integrations/cert-manager-values.yaml | 43 +++ .../integrations/etcd-values.yaml | 42 +++ .../definitions/alloy-integration.schema.json | 43 +++ .../cert-manager-integration.schema.json | 46 +++ .../definitions/etcd-integration.schema.json | 46 +++ .../schema-mods/integration-list.json | 14 + .../templates/_helpers.tpl | 21 ++ .../templates/_integration_alloy.tpl | 327 ++++++++++++++++++ .../templates/_integration_cert-manager.tpl | 67 ++++ .../templates/_integration_etcd.tpl | 67 ++++ .../templates/_integration_helpers.tpl | 21 ++ .../templates/_integration_types.tpl | 6 + .../feature-integrations/templates/_notes.tpl | 8 + .../templates/configmap.yaml | 15 + .../tests/alloy_test.yaml | 302 ++++++++++++++++ .../tests/cert-manager_test.yaml | 82 +++++ .../feature-integrations/tests/etcd_test.yaml | 82 +++++ .../feature-integrations/values.schema.json | 203 +++++++++++ charts/feature-integrations/values.yaml | 35 ++ charts/feature-pod-logs/Makefile | 10 +- charts/feature-profiling/Makefile | 10 +- .../Makefile | 10 +- scripts/docs-and-schema-image/Dockerfile | 11 + scripts/docs-and-schema-image/Makefile | 7 + .../create-docs-and-schema.sh | 65 ++++ 44 files changed, 2011 insertions(+), 27 deletions(-) create mode 100644 charts/feature-integrations/.helmignore create mode 100644 charts/feature-integrations/Chart.lock create mode 100644 charts/feature-integrations/Chart.yaml create mode 100644 charts/feature-integrations/Makefile create mode 100644 charts/feature-integrations/README.md create mode 100644 charts/feature-integrations/default-allow-lists/alloy-integration.yaml create mode 100644 charts/feature-integrations/default-allow-lists/alloy.yaml create mode 100644 charts/feature-integrations/docs/integrations/README.md create mode 100644 charts/feature-integrations/docs/integrations/alloy.md create mode 100644 charts/feature-integrations/docs/integrations/cert-manager.md create mode 100644 charts/feature-integrations/docs/integrations/etcd.md create mode 100644 charts/feature-integrations/integrations/alloy-values.yaml create mode 100644 charts/feature-integrations/integrations/cert-manager-values.yaml create mode 100644 charts/feature-integrations/integrations/etcd-values.yaml create mode 100644 charts/feature-integrations/schema-mods/definitions/alloy-integration.schema.json create mode 100644 charts/feature-integrations/schema-mods/definitions/cert-manager-integration.schema.json create mode 100644 charts/feature-integrations/schema-mods/definitions/etcd-integration.schema.json create mode 100644 charts/feature-integrations/schema-mods/integration-list.json create mode 100644 charts/feature-integrations/templates/_helpers.tpl create mode 100644 charts/feature-integrations/templates/_integration_alloy.tpl create mode 100644 charts/feature-integrations/templates/_integration_cert-manager.tpl create mode 100644 charts/feature-integrations/templates/_integration_etcd.tpl create mode 100644 charts/feature-integrations/templates/_integration_helpers.tpl create mode 100644 charts/feature-integrations/templates/_integration_types.tpl create mode 100644 charts/feature-integrations/templates/_notes.tpl create mode 100644 charts/feature-integrations/templates/configmap.yaml create mode 100644 charts/feature-integrations/tests/alloy_test.yaml create mode 100644 charts/feature-integrations/tests/cert-manager_test.yaml create mode 100644 charts/feature-integrations/tests/etcd_test.yaml create mode 100644 charts/feature-integrations/values.schema.json create mode 100644 charts/feature-integrations/values.yaml create mode 100644 scripts/docs-and-schema-image/Dockerfile create mode 100644 scripts/docs-and-schema-image/Makefile create mode 100755 scripts/docs-and-schema-image/create-docs-and-schema.sh diff --git a/.github/workflows/test-feature-charts.yml b/.github/workflows/test-feature-charts.yml index 4399f9a79..b8e7ec579 100644 --- a/.github/workflows/test-feature-charts.yml +++ b/.github/workflows/test-feature-charts.yml @@ -105,7 +105,7 @@ jobs: run: | echo "Running make all in charts/${{ matrix.dir }}" cd charts/${{ matrix.dir }} - make all + make clean build - name: Check for changes in generated files run: | diff --git a/Makefile b/Makefile index 2121c8cb1..6a455153c 100644 --- a/Makefile +++ b/Makefile @@ -7,9 +7,9 @@ FEATURE_CHARTS = $(shell ls charts | grep -v k8s-monitoring) build: set -e && \ for chart in $(FEATURE_CHARTS); do \ - make -C charts/$$chart all; \ + make -C charts/$$chart build; \ done - #make -C charts/k8s-monitoring all + #make -C charts/k8s-monitoring build .PHONY: test test: build diff --git a/charts/feature-annotation-autodiscovery/Makefile b/charts/feature-annotation-autodiscovery/Makefile index 9bb0eae02..0889e5364 100644 --- a/charts/feature-annotation-autodiscovery/Makefile +++ b/charts/feature-annotation-autodiscovery/Makefile @@ -16,11 +16,15 @@ Chart.lock: Chart.yaml values.schema.json: values.yaml $$(wildcard schema-mods/*) ../../scripts/schema-gen.sh . -.PHONY: all -all: README.md Chart.lock values.schema.json +.PHONY: clean +clean: + rm -f README.md Chart.lock values.schema.json + +.PHONY: build +build: README.md Chart.lock values.schema.json .PHONY: test -test: all +test: build helm lint . ifdef HAS_HELM_UNITTEST helm unittest . diff --git a/charts/feature-application-observability/Makefile b/charts/feature-application-observability/Makefile index 9bb0eae02..0889e5364 100644 --- a/charts/feature-application-observability/Makefile +++ b/charts/feature-application-observability/Makefile @@ -16,11 +16,15 @@ Chart.lock: Chart.yaml values.schema.json: values.yaml $$(wildcard schema-mods/*) ../../scripts/schema-gen.sh . -.PHONY: all -all: README.md Chart.lock values.schema.json +.PHONY: clean +clean: + rm -f README.md Chart.lock values.schema.json + +.PHONY: build +build: README.md Chart.lock values.schema.json .PHONY: test -test: all +test: build helm lint . ifdef HAS_HELM_UNITTEST helm unittest . diff --git a/charts/feature-cluster-events/Makefile b/charts/feature-cluster-events/Makefile index 9bb0eae02..0889e5364 100644 --- a/charts/feature-cluster-events/Makefile +++ b/charts/feature-cluster-events/Makefile @@ -16,11 +16,15 @@ Chart.lock: Chart.yaml values.schema.json: values.yaml $$(wildcard schema-mods/*) ../../scripts/schema-gen.sh . -.PHONY: all -all: README.md Chart.lock values.schema.json +.PHONY: clean +clean: + rm -f README.md Chart.lock values.schema.json + +.PHONY: build +build: README.md Chart.lock values.schema.json .PHONY: test -test: all +test: build helm lint . ifdef HAS_HELM_UNITTEST helm unittest . diff --git a/charts/feature-cluster-metrics/Makefile b/charts/feature-cluster-metrics/Makefile index 9bb0eae02..0889e5364 100644 --- a/charts/feature-cluster-metrics/Makefile +++ b/charts/feature-cluster-metrics/Makefile @@ -16,11 +16,15 @@ Chart.lock: Chart.yaml values.schema.json: values.yaml $$(wildcard schema-mods/*) ../../scripts/schema-gen.sh . -.PHONY: all -all: README.md Chart.lock values.schema.json +.PHONY: clean +clean: + rm -f README.md Chart.lock values.schema.json + +.PHONY: build +build: README.md Chart.lock values.schema.json .PHONY: test -test: all +test: build helm lint . ifdef HAS_HELM_UNITTEST helm unittest . diff --git a/charts/feature-frontend-observability/Makefile b/charts/feature-frontend-observability/Makefile index 9bb0eae02..0889e5364 100644 --- a/charts/feature-frontend-observability/Makefile +++ b/charts/feature-frontend-observability/Makefile @@ -16,11 +16,15 @@ Chart.lock: Chart.yaml values.schema.json: values.yaml $$(wildcard schema-mods/*) ../../scripts/schema-gen.sh . -.PHONY: all -all: README.md Chart.lock values.schema.json +.PHONY: clean +clean: + rm -f README.md Chart.lock values.schema.json + +.PHONY: build +build: README.md Chart.lock values.schema.json .PHONY: test -test: all +test: build helm lint . ifdef HAS_HELM_UNITTEST helm unittest . diff --git a/charts/feature-integrations/.helmignore b/charts/feature-integrations/.helmignore new file mode 100644 index 000000000..8fae60592 --- /dev/null +++ b/charts/feature-integrations/.helmignore @@ -0,0 +1,5 @@ +docs +schema-mods +tests +Makefile +README.md diff --git a/charts/feature-integrations/Chart.lock b/charts/feature-integrations/Chart.lock new file mode 100644 index 000000000..f7e3dac27 --- /dev/null +++ b/charts/feature-integrations/Chart.lock @@ -0,0 +1,3 @@ +dependencies: [] +digest: sha256:643d5437104296e21d906ecb15b2c96ad278f20cfc4af53b12bb6069bd853726 +generated: "2024-09-25T13:47:44.987117-05:00" diff --git a/charts/feature-integrations/Chart.yaml b/charts/feature-integrations/Chart.yaml new file mode 100644 index 000000000..6e7296d58 --- /dev/null +++ b/charts/feature-integrations/Chart.yaml @@ -0,0 +1,7 @@ +apiVersion: v2 +name: integrations +description: Service integrations +icon: https://raw.githubusercontent.com/grafana/grafana/main/public/img/grafana_icon.svg +version: 1.0.0 +appVersion: 1.0.0 +dependencies: [] diff --git a/charts/feature-integrations/Makefile b/charts/feature-integrations/Makefile new file mode 100644 index 000000000..72f53e359 --- /dev/null +++ b/charts/feature-integrations/Makefile @@ -0,0 +1,94 @@ +HAS_HELM_DOCS := $(shell command -v helm-docs;) +HAS_HELM_UNITTEST := $(shell helm plugin list | grep unittest 2> /dev/null) + +SCHEMA_MODS_JSON_FILES = $(shell find schema-mods -name "*.json") +SCHEMA_MODS_JQ_FILES = $(shell find schema-mods -name "*.jq") + +INTEGRATION_VALUES_FILES = $(shell find integrations -name "*-values.yaml") +INTEGRATION_DOCS_FILES = $(INTEGRATION_VALUES_FILES:integrations/%-values.yaml=./docs/integrations/%.md) +INTEGRATION_SCHEMA_FILES = $(INTEGRATION_VALUES_FILES:integrations/%-values.yaml=./schema-mods/definitions/%-integration.schema.json) + +Chart.lock: Chart.yaml + helm dependency update . + touch Chart.lock # Ensure the timestamp is updated + +.SECONDEXPANSION: +docs/integrations/%.md: integrations/%-values.yaml $$(wildcard docs/integrations/.doc_templates/%.gotmpl) + docker run --platform linux/amd64 --rm -v $(shell pwd):/src ghcr.io/grafana/helm-docs-and-schema-gen $(shell echo $< | sed 's/integrations\/\([-a-z]*\)-values.yaml/\1/') integration + +schema-mods/definitions/%-integration.schema.json: integrations/%-values.yaml + docker run --platform linux/amd64 --rm -v $(shell pwd):/src ghcr.io/grafana/helm-docs-and-schema-gen $(shell echo $< | sed 's/integrations\/\([-a-z]*\)-values.yaml/\1/') integration + +NUMBER_OF_INTEGRATION_VALUES_FILES := $(words $(INTEGRATION_VALUES_FILES)) +schema-mods/integration-list.json: $(INTEGRATION_VALUES_FILES) + @echo '{' > $@ + @echo ' "definitions": {' >> $@ + @echo ' "integration-list": {' >> $@ + @echo ' "type": "array",' >> $@ + @echo ' "items": {' >> $@ + @echo ' "anyOf": [' >> $@ + @count=0; \ + for file in $(INTEGRATION_VALUES_FILES); do \ + count=$$((count + 1)); \ + if [ $$count -eq $(NUMBER_OF_INTEGRATION_VALUES_FILES) ]; then \ + echo ' { "$$ref": "#/definitions/'$$(echo $${file} | sed 's/integrations\/\([-a-z]*\)-values.yaml/\1/')'-integration"}' >> $@; \ + else \ + echo ' { "$$ref": "#/definitions/'$$(echo $${file} | sed 's/integrations\/\([-a-z]*\)-values.yaml/\1/')'-integration"},' >> $@; \ + fi; \ + done + @echo ' ]' >> $@ + @echo ' }' >> $@ + @echo ' }' >> $@ + @echo ' }' >> $@ + @echo '}' >> $@ + +templates/_integration_types.tpl: $(INTEGRATION_VALUES_FILES) + echo '{{/* Do not edit this file. It is generated by the Makefile */}}' > $@ + echo '{{- define "integrations.types" -}}' >> $@ + for file in $(INTEGRATION_VALUES_FILES); do \ + echo - $$(echo $${file} | sed 's/integrations\/\([-a-z]*\)-values.yaml/\1/') >> $@; \ + done + echo '{{- end -}}' >> $@ + +values.schema.json: values.yaml $(INTEGRATION_SCHEMA_FILES) $(SCHEMA_MODS_JSON_FILES) $(SCHEMA_MODS_JQ_FILES) schema-mods/integration-list.json + ../../scripts/schema-gen.sh . + +docs/integrations/README.md: $(INTEGRATION_DOCS_FILES) + echo "# Integrations" > $@ + echo "" >> $@ + echo "This directory contains the values files for the integrations that are available." >> $@ + echo "" >> $@ + echo "## Integrations" >> $@ + echo "" >> $@ + echo "| Name | Docs |" >> $@ + echo "|------|------|" >> $@ + for file in $(INTEGRATION_DOCS_FILES); do \ + echo "| $$(echo $${file} | sed 's/\.\/docs\/integrations\/\([-a-z]*\).md/\1/') | [Docs]($$(echo $${file} | sed 's/docs\/integrations\/\([-a-z]*.md\)/\1/')) |" >> $@; \ + done + +README.md: values.yaml Chart.yaml $$(wildcard README.md.gotmpl) +ifdef HAS_HELM_DOCS + helm-docs +else + docker run --rm --volume "$(shell pwd):/helm-docs" -u $(shell id -u) jnorwood/helm-docs:latest +endif + +.PHONY: clean +clean: + rm -f README.md values.schema.json schema-mods/integration-list.json templates/_integration_types.tpl + rm -f $(INTEGRATION_SCHEMA_FILES) + rm -f $(INTEGRATION_DOCS_FILES) + rm -f docs/integrations/README.md + +.PHONY: build +build: README.md Chart.lock values.schema.json templates/_integration_types.tpl docs/integrations/README.md + +.PHONY: test +test: build + helm lint . +ifdef HAS_HELM_UNITTEST + helm unittest . +else + docker run --rm --volume $(shell pwd):/apps helmunittest/helm-unittest . +endif + diff --git a/charts/feature-integrations/README.md b/charts/feature-integrations/README.md new file mode 100644 index 000000000..5cdd5c20d --- /dev/null +++ b/charts/feature-integrations/README.md @@ -0,0 +1,42 @@ +# integrations + +![Version: 1.0.0](https://img.shields.io/badge/Version-1.0.0-informational?style=flat-square) ![AppVersion: 1.0.0](https://img.shields.io/badge/AppVersion-1.0.0-informational?style=flat-square) + +Service integrations + +## Values + +### Integration: Alloy + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| alloy | object | `{"instances":[]}` | Scrape metrics from Grafana Alloy | + +### Integration: cert-manager + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| cert-manager | object | `{"instances":[]}` | Scrape metrics from cert-manager | + +### Integration: etcd + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| etcd | object | `{"instances":[]}` | Scrape metrics from etcd | + +### General settings + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| fullnameOverride | string | `""` | Full name override | +| nameOverride | string | `""` | Name override | + +### Global Settings + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| global.maxCacheSize | int | `100000` | Sets the max_cache_size for every prometheus.relabel component. ([docs](https://grafana.com/docs/alloy/latest/reference/components/prometheus.relabel/#arguments)) This should be at least 2x-5x your largest scrape target or samples appended rate. | +| global.scrapeInterval | string | `"60s"` | How frequently to scrape metrics. | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.14.2](https://github.com/norwoodj/helm-docs/releases/v1.14.2) diff --git a/charts/feature-integrations/default-allow-lists/alloy-integration.yaml b/charts/feature-integrations/default-allow-lists/alloy-integration.yaml new file mode 100644 index 000000000..698d4e8a0 --- /dev/null +++ b/charts/feature-integrations/default-allow-lists/alloy-integration.yaml @@ -0,0 +1,105 @@ +--- +# The set of metrics from Grafana Alloy required for the Grafana Alloy integration +- alloy_build_info +- alloy_component_controller_running_components +- alloy_component_dependencies_wait_seconds +- alloy_component_dependencies_wait_seconds_bucket +- alloy_component_evaluation_seconds +- alloy_component_evaluation_seconds_bucket +- alloy_component_evaluation_seconds_count +- alloy_component_evaluation_seconds_sum +- alloy_component_evaluation_slow_seconds +- alloy_config_hash +- alloy_resources_machine_rx_bytes_total +- alloy_resources_machine_tx_bytes_total +- alloy_resources_process_cpu_seconds_total +- alloy_resources_process_resident_memory_bytes +- alloy_tcp_connections +- alloy_wal_samples_appended_total +- alloy_wal_storage_active_series +- cluster_node_gossip_health_score +- cluster_node_gossip_proto_version +- cluster_node_gossip_received_events_total +- cluster_node_info +- cluster_node_lamport_time +- cluster_node_peers +- cluster_node_update_observers +- cluster_transport_rx_bytes_total +- cluster_transport_rx_packet_queue_length +- cluster_transport_rx_packets_failed_total +- cluster_transport_rx_packets_total +- cluster_transport_stream_rx_bytes_total +- cluster_transport_stream_rx_packets_failed_total +- cluster_transport_stream_rx_packets_total +- cluster_transport_stream_tx_bytes_total +- cluster_transport_stream_tx_packets_failed_total +- cluster_transport_stream_tx_packets_total +- cluster_transport_streams +- cluster_transport_tx_bytes_total +- cluster_transport_tx_packet_queue_length +- cluster_transport_tx_packets_failed_total +- cluster_transport_tx_packets_total +- exporter_send_failed_spans_ratio_total +- exporter_sent_spans_ratio_total +- go_gc_duration_seconds_count +- go_goroutines +- go_memstats_heap_inuse_bytes +- loki_process_dropped_lines_total +- loki_write_batch_retries_total +- loki_write_dropped_bytes_total +- loki_write_dropped_entries_total +- loki_write_encoded_bytes_total +- loki_write_mutated_bytes_total +- loki_write_mutated_entries_total +- loki_write_request_duration_seconds_bucket +- loki_write_sent_bytes_total +- loki_write_sent_entries_total +- process_cpu_seconds_total +- process_start_time_seconds +- processor_batch_batch_send_size_ratio_bucket +- processor_batch_metadata_cardinality_ratio +- processor_batch_timeout_trigger_send_ratio_total +- prometheus_remote_storage_bytes_total +- prometheus_remote_storage_enqueue_retries_total +- prometheus_remote_storage_highest_timestamp_in_seconds +- prometheus_remote_storage_metadata_bytes_total +- prometheus_remote_storage_queue_highest_sent_timestamp_seconds +- prometheus_remote_storage_samples_dropped_total +- prometheus_remote_storage_samples_failed_total +- prometheus_remote_storage_samples_pending +- prometheus_remote_storage_samples_retried_total +- prometheus_remote_storage_samples_total +- prometheus_remote_storage_sent_batch_duration_seconds_bucket +- prometheus_remote_storage_sent_batch_duration_seconds_count +- prometheus_remote_storage_sent_batch_duration_seconds_sum +- prometheus_remote_storage_shard_capacity +- prometheus_remote_storage_shards +- prometheus_remote_storage_shards_desired +- prometheus_remote_storage_shards_max +- prometheus_remote_storage_shards_min +- prometheus_remote_storage_succeeded_samples_total +- prometheus_remote_write_wal_samples_appended_total +- prometheus_remote_write_wal_storage_active_series +- prometheus_sd_discovered_targets +- prometheus_target_interval_length_seconds_count +- prometheus_target_interval_length_seconds_sum +- prometheus_target_scrapes_exceeded_sample_limit_total +- prometheus_target_scrapes_sample_duplicate_timestamp_total +- prometheus_target_scrapes_sample_out_of_bounds_total +- prometheus_target_scrapes_sample_out_of_order_total +- prometheus_target_sync_length_seconds_sum +- prometheus_wal_watcher_current_segment +- receiver_accepted_spans_ratio_total +- receiver_refused_spans_ratio_total +- rpc_server_duration_milliseconds_bucket +- scrape_duration_seconds +- traces_exporter_send_failed_spans +- traces_exporter_send_failed_spans_total +- traces_exporter_sent_spans +- traces_exporter_sent_spans_total +- traces_loadbalancer_backend_outcome +- traces_loadbalancer_num_backends +- traces_receiver_accepted_spans +- traces_receiver_accepted_spans_total +- traces_receiver_refused_spans +- traces_receiver_refused_spans_total diff --git a/charts/feature-integrations/default-allow-lists/alloy.yaml b/charts/feature-integrations/default-allow-lists/alloy.yaml new file mode 100644 index 000000000..75720aa28 --- /dev/null +++ b/charts/feature-integrations/default-allow-lists/alloy.yaml @@ -0,0 +1,3 @@ +--- +# The minimal set of metrics from Grafana Alloy required for Kubernetes Monitoring +- alloy_build_info diff --git a/charts/feature-integrations/docs/integrations/README.md b/charts/feature-integrations/docs/integrations/README.md new file mode 100644 index 000000000..cf8fc95b9 --- /dev/null +++ b/charts/feature-integrations/docs/integrations/README.md @@ -0,0 +1,11 @@ +# Integrations + +This directory contains the values files for the integrations that are available. + +## Integrations + +| Name | Docs | +|------|------| +| etcd | [Docs](./etcd.md) | +| alloy | [Docs](./alloy.md) | +| cert-manager | [Docs](./cert-manager.md) | diff --git a/charts/feature-integrations/docs/integrations/alloy.md b/charts/feature-integrations/docs/integrations/alloy.md new file mode 100644 index 000000000..919c947fe --- /dev/null +++ b/charts/feature-integrations/docs/integrations/alloy.md @@ -0,0 +1,30 @@ +# alloy +## Values + +### Discovery Settings + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| labelSelectors | object | `{"app.kubernetes.io/name":"alloy"}` | Discover Alloy instances based on label selectors. | + +### Metric Processing Settings + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| maxCacheSize | string | `100000` | Sets the max_cache_size for prometheus.relabel component. This should be at least 2x-5x your largest scrape target or samples appended rate. ([docs](https://grafana.com/docs/alloy/latest/reference/components/prometheus.relabel/#arguments)) Overrides global.maxCacheSize | +| metricsTuning.excludeMetrics | list | `[]` | Metrics to drop. Can use regular expressions. | +| metricsTuning.includeMetrics | list | `[]` | Metrics to keep. Can use regular expressions. | +| metricsTuning.useDefaultAllowList | bool | `true` | Filter the list of metrics from Grafana Alloy to the minimal set required for Kubernetes Monitoring. See [Metrics Tuning and Allow Lists](#metrics-tuning-and-allow-lists) | +| metricsTuning.useIntegrationAllowList | bool | `false` | Filter the list of metrics from Grafana Alloy to the minimal set required for Kubernetes Monitoring as well as the Grafana Alloy integration. | + +### General Settings + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| name | string | `""` | Name for this Alloy instance. | + +### Scrape Settings + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| scrapeInterval | string | `60s` | How frequently to scrape metrics from Windows Exporter. | diff --git a/charts/feature-integrations/docs/integrations/cert-manager.md b/charts/feature-integrations/docs/integrations/cert-manager.md new file mode 100644 index 000000000..b9518dac6 --- /dev/null +++ b/charts/feature-integrations/docs/integrations/cert-manager.md @@ -0,0 +1,31 @@ +# cert-manager +## Values + +### Discovery Settings + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| field_selectors | list | `[]` | Discover cert-manager instances based on field selectors. | +| labelSelectors | object | `{"app.kubernetes.io/name":"cert-manager"}` | Discover cert-manager instances based on label selectors. | +| namespaces | list | `[]` | Namespaces to look for cert-manager instances. | +| portName | string | `"http-metrics"` | Name of the port to scrape metrics from. | + +### Metric Processing Settings + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| maxCacheSize | string | `100000` | Sets the max_cache_size for cadvisor prometheus.relabel component. This should be at least 2x-5x your largest scrape target or samples appended rate. ([docs](https://grafana.com/docs/alloy/latest/reference/components/prometheus.relabel/#arguments)) Overrides global.maxCacheSize | +| metricsTuning.excludeMetrics | list | `[]` | Metrics to drop. Can use regular expressions. | +| metricsTuning.includeMetrics | list | `[]` | Metrics to keep. Can use regular expressions. | + +### General Settings + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| name | string | `""` | Name for this cert-manager instance. | + +### Scrape Settings + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| scrapeInterval | string | `60s` | How frequently to scrape metrics from Windows Exporter. | diff --git a/charts/feature-integrations/docs/integrations/etcd.md b/charts/feature-integrations/docs/integrations/etcd.md new file mode 100644 index 000000000..4e16e297b --- /dev/null +++ b/charts/feature-integrations/docs/integrations/etcd.md @@ -0,0 +1,31 @@ +# etcd +## Values + +### Discovery Settings + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| field_selectors | list | `[]` | Discover etcd instances based on field selectors. | +| labelSelectors | object | `{"app.kubernetes.io/component":"etcd"}` | Discover etcd instances based on label selectors. | +| namespaces | list | `[]` | Namespaces to look for etcd instances. | +| portName | string | `"metrics"` | Name of the port to scrape metrics from. | + +### Metric Processing Settings + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| maxCacheSize | string | `100000` | Sets the max_cache_size for cadvisor prometheus.relabel component. This should be at least 2x-5x your largest scrape target or samples appended rate. ([docs](https://grafana.com/docs/alloy/latest/reference/components/prometheus.relabel/#arguments)) Overrides global.maxCacheSize | +| metricsTuning.excludeMetrics | list | `[]` | Metrics to drop. Can use regular expressions. | +| metricsTuning.includeMetrics | list | `[]` | Metrics to keep. Can use regular expressions. | + +### General Settings + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| name | string | `""` | Name for this etcd instance. | + +### Scrape Settings + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| scrapeInterval | string | `60s` | How frequently to scrape metrics from Windows Exporter. | diff --git a/charts/feature-integrations/integrations/alloy-values.yaml b/charts/feature-integrations/integrations/alloy-values.yaml new file mode 100644 index 000000000..7b67fbfaa --- /dev/null +++ b/charts/feature-integrations/integrations/alloy-values.yaml @@ -0,0 +1,37 @@ +# -- Name for this Alloy instance. +# @section -- General Settings +name: "" + +# -- Discover Alloy instances based on label selectors. +# @section -- Discovery Settings +labelSelectors: + app.kubernetes.io/name: alloy + +# -- How frequently to scrape metrics from Windows Exporter. +# @default -- `60s` +# @section -- Scrape Settings +scrapeInterval: + +# Adjustments to the scraped metrics to filter the amount of data sent to storage. +metricsTuning: + # -- Filter the list of metrics from Grafana Alloy to the minimal set required for Kubernetes Monitoring. + # See [Metrics Tuning and Allow Lists](#metrics-tuning-and-allow-lists) + # @section -- Metric Processing Settings + useDefaultAllowList: true + # -- Filter the list of metrics from Grafana Alloy to the minimal set required for Kubernetes Monitoring as well as the Grafana Alloy integration. + # @section -- Metric Processing Settings + useIntegrationAllowList: false + # -- Metrics to keep. Can use regular expressions. + # @section -- Metric Processing Settings + includeMetrics: [] + # -- Metrics to drop. Can use regular expressions. + # @section -- Metric Processing Settings + excludeMetrics: [] + +# -- Sets the max_cache_size for prometheus.relabel component. +# This should be at least 2x-5x your largest scrape target or samples appended rate. +# ([docs](https://grafana.com/docs/alloy/latest/reference/components/prometheus.relabel/#arguments)) +# Overrides global.maxCacheSize +# @default -- `100000` +# @section -- Metric Processing Settings +maxCacheSize: diff --git a/charts/feature-integrations/integrations/cert-manager-values.yaml b/charts/feature-integrations/integrations/cert-manager-values.yaml new file mode 100644 index 000000000..d263377b6 --- /dev/null +++ b/charts/feature-integrations/integrations/cert-manager-values.yaml @@ -0,0 +1,43 @@ +# -- Name for this cert-manager instance. +# @section -- General Settings +name: "" + +# -- Namespaces to look for cert-manager instances. +# @section -- Discovery Settings +namespaces: [] + +# -- Discover cert-manager instances based on field selectors. +# @section -- Discovery Settings +field_selectors: [] + +# -- Discover cert-manager instances based on label selectors. +# @section -- Discovery Settings +labelSelectors: + app.kubernetes.io/name: cert-manager + +# -- Name of the port to scrape metrics from. +# @section -- Discovery Settings +portName: http-metrics + + +# -- How frequently to scrape metrics from Windows Exporter. +# @default -- `60s` +# @section -- Scrape Settings +scrapeInterval: + +# -- Sets the max_cache_size for cadvisor prometheus.relabel component. +# This should be at least 2x-5x your largest scrape target or samples appended rate. +# ([docs](https://grafana.com/docs/alloy/latest/reference/components/prometheus.relabel/#arguments)) +# Overrides global.maxCacheSize +# @default -- `100000` +# @section -- Metric Processing Settings +maxCacheSize: + +# Adjustments to the scraped metrics to filter the amount of data sent to storage. +metricsTuning: + # -- Metrics to keep. Can use regular expressions. + # @section -- Metric Processing Settings + includeMetrics: [] + # -- Metrics to drop. Can use regular expressions. + # @section -- Metric Processing Settings + excludeMetrics: [] diff --git a/charts/feature-integrations/integrations/etcd-values.yaml b/charts/feature-integrations/integrations/etcd-values.yaml new file mode 100644 index 000000000..b6750cd38 --- /dev/null +++ b/charts/feature-integrations/integrations/etcd-values.yaml @@ -0,0 +1,42 @@ +# -- Name for this etcd instance. +# @section -- General Settings +name: "" + +# -- Namespaces to look for etcd instances. +# @section -- Discovery Settings +namespaces: [] + +# -- Discover etcd instances based on field selectors. +# @section -- Discovery Settings +field_selectors: [] + +# -- Discover etcd instances based on label selectors. +# @section -- Discovery Settings +labelSelectors: + app.kubernetes.io/component: etcd + +# -- Name of the port to scrape metrics from. +# @section -- Discovery Settings +portName: metrics + +# -- How frequently to scrape metrics from Windows Exporter. +# @default -- `60s` +# @section -- Scrape Settings +scrapeInterval: + +# -- Sets the max_cache_size for cadvisor prometheus.relabel component. +# This should be at least 2x-5x your largest scrape target or samples appended rate. +# ([docs](https://grafana.com/docs/alloy/latest/reference/components/prometheus.relabel/#arguments)) +# Overrides global.maxCacheSize +# @default -- `100000` +# @section -- Metric Processing Settings +maxCacheSize: + +# Adjustments to the scraped metrics to filter the amount of data sent to storage. +metricsTuning: + # -- Metrics to keep. Can use regular expressions. + # @section -- Metric Processing Settings + includeMetrics: [] + # -- Metrics to drop. Can use regular expressions. + # @section -- Metric Processing Settings + excludeMetrics: [] diff --git a/charts/feature-integrations/schema-mods/definitions/alloy-integration.schema.json b/charts/feature-integrations/schema-mods/definitions/alloy-integration.schema.json new file mode 100644 index 000000000..9a7834220 --- /dev/null +++ b/charts/feature-integrations/schema-mods/definitions/alloy-integration.schema.json @@ -0,0 +1,43 @@ +{ + "type": "object", + "properties": { + "labelSelectors": { + "type": "object", + "properties": { + "app.kubernetes.io/name": { + "type": "string" + } + } + }, + "maxCacheSize": { + "type": "null" + }, + "metricsTuning": { + "type": "object", + "properties": { + "excludeMetrics": { + "type": "array" + }, + "includeMetrics": { + "type": "array" + }, + "useDefaultAllowList": { + "type": "boolean" + }, + "useIntegrationAllowList": { + "type": "boolean" + } + } + }, + "name": { + "type": "string" + }, + "scrapeInterval": { + "type": "null" + }, + "type": { + "type": "string", + "const": "alloy" + } + } +} diff --git a/charts/feature-integrations/schema-mods/definitions/cert-manager-integration.schema.json b/charts/feature-integrations/schema-mods/definitions/cert-manager-integration.schema.json new file mode 100644 index 000000000..0bc8a5ce4 --- /dev/null +++ b/charts/feature-integrations/schema-mods/definitions/cert-manager-integration.schema.json @@ -0,0 +1,46 @@ +{ + "type": "object", + "properties": { + "field_selectors": { + "type": "array" + }, + "labelSelectors": { + "type": "object", + "properties": { + "app.kubernetes.io/name": { + "type": "string" + } + } + }, + "maxCacheSize": { + "type": "null" + }, + "metricsTuning": { + "type": "object", + "properties": { + "excludeMetrics": { + "type": "array" + }, + "includeMetrics": { + "type": "array" + } + } + }, + "name": { + "type": "string" + }, + "namespaces": { + "type": "array" + }, + "portName": { + "type": "string" + }, + "scrapeInterval": { + "type": "null" + }, + "type": { + "type": "string", + "const": "cert-manager" + } + } +} diff --git a/charts/feature-integrations/schema-mods/definitions/etcd-integration.schema.json b/charts/feature-integrations/schema-mods/definitions/etcd-integration.schema.json new file mode 100644 index 000000000..8013b801b --- /dev/null +++ b/charts/feature-integrations/schema-mods/definitions/etcd-integration.schema.json @@ -0,0 +1,46 @@ +{ + "type": "object", + "properties": { + "field_selectors": { + "type": "array" + }, + "labelSelectors": { + "type": "object", + "properties": { + "app.kubernetes.io/component": { + "type": "string" + } + } + }, + "maxCacheSize": { + "type": "null" + }, + "metricsTuning": { + "type": "object", + "properties": { + "excludeMetrics": { + "type": "array" + }, + "includeMetrics": { + "type": "array" + } + } + }, + "name": { + "type": "string" + }, + "namespaces": { + "type": "array" + }, + "portName": { + "type": "string" + }, + "scrapeInterval": { + "type": "null" + }, + "type": { + "type": "string", + "const": "etcd" + } + } +} diff --git a/charts/feature-integrations/schema-mods/integration-list.json b/charts/feature-integrations/schema-mods/integration-list.json new file mode 100644 index 000000000..6bb7a6428 --- /dev/null +++ b/charts/feature-integrations/schema-mods/integration-list.json @@ -0,0 +1,14 @@ +{ + "definitions": { + "integration-list": { + "type": "array", + "items": { + "anyOf": [ + { "$ref": "#/definitions/etcd-integration"}, + { "$ref": "#/definitions/alloy-integration"}, + { "$ref": "#/definitions/cert-manager-integration"} + ] + } + } + } +} diff --git a/charts/feature-integrations/templates/_helpers.tpl b/charts/feature-integrations/templates/_helpers.tpl new file mode 100644 index 000000000..273f4a856 --- /dev/null +++ b/charts/feature-integrations/templates/_helpers.tpl @@ -0,0 +1,21 @@ +{{/* +Create a default fully qualified name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "integrations.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" | lower }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride | lower }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" | lower }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" | lower }} +{{- end }} +{{- end }} +{{- end }} + +{{ define "helper.alloy_name" }} +{{- . | lower | replace "-" "_" -}} +{{ end }} diff --git a/charts/feature-integrations/templates/_integration_alloy.tpl b/charts/feature-integrations/templates/_integration_alloy.tpl new file mode 100644 index 000000000..1f9b2f10f --- /dev/null +++ b/charts/feature-integrations/templates/_integration_alloy.tpl @@ -0,0 +1,327 @@ +{{- define "integrations.alloy.type.metrics" }}true{{- end }} +{{- define "integrations.alloy.type.logs" }}false{{- end }} + +{{/* Returns the allowed metrics */}} +{{/* Inputs: integration (Alloy integration definition) Files (Files object) */}} +{{- define "integrations.alloy.allowList" }} +{{- if .integration.metricsTuning.useDefaultAllowList }} +{{ "integrations/default-allow-lists/alloy.yaml" | .Files.Get }} +{{- end }} +{{- if .integration.metricsTuning.useIntegrationAllowList }} +{{ "integrations/default-allow-lists/alloy-integration.yaml" | .Files.Get }} +{{- end }} +{{- if .integration.metricsTuning.includeMetrics }} +{{ .integration.metricsTuning.includeMetrics | toYaml }} +{{- end }} +{{- end }} + +{{/* Loads the Alloy module and instances */}} +{{/* Inputs: Values (all values), Files (Files object) */}} +{{ define "integrations.alloy.module.metrics" }} +declare "alloy_integration" { + argument "metrics_destinations" { + comment = "Must be a list of metric destinations where collected metrics should be forwarded to" + } + + declare "alloy_integration_discovery" { + argument "namespaces" { + comment = "The namespaces to look for targets in (default: [] is all namespaces)" + optional = true + } + + argument "field_selectors" { + comment = "The field selectors to use to find matching targets (default: [])" + optional = true + } + + argument "label_selectors" { + comment = "The label selectors to use to find matching targets (default: [\"app.kubernetes.io/name=alloy\"])" + optional = true + } + + argument "port_name" { + comment = "The of the port to scrape metrics from (default: http-metrics)" + optional = true + } + + // Alloy service discovery for all of the pods + discovery.kubernetes "alloy_pods" { + role = "pod" + + selectors { + role = "pod" + field = join(coalesce(argument.field_selectors.value, []), ",") + label = join(coalesce(argument.label_selectors.value, ["app.kubernetes.io/name=alloy"]), ",") + } + + namespaces { + names = coalesce(argument.namespaces.value, []) + } + } + + // alloy relabelings (pre-scrape) + discovery.relabel "alloy_pods" { + targets = discovery.kubernetes.alloy_pods.targets + + // keep only the specified metrics port name, and pods that are Running and ready + rule { + source_labels = [ + "__meta_kubernetes_pod_container_port_name", + "__meta_kubernetes_pod_phase", + "__meta_kubernetes_pod_ready", + "__meta_kubernetes_pod_container_init", + ] + separator = "@" + regex = coalesce(argument.port_name.value, "metrics") + "@Running@true@false" + action = "keep" + } + + rule { + source_labels = ["__meta_kubernetes_namespace"] + target_label = "namespace" + } + + rule { + source_labels = ["__meta_kubernetes_pod_name"] + target_label = "pod" + } + + rule { + source_labels = ["__meta_kubernetes_pod_container_name"] + target_label = "container" + } + + rule { + source_labels = [ + "__meta_kubernetes_pod_controller_kind", + "__meta_kubernetes_pod_controller_name", + ] + separator = "/" + target_label = "workload" + } + // remove the hash from the ReplicaSet + rule { + source_labels = ["workload"] + regex = "(ReplicaSet/.+)-.+" + target_label = "workload" + } + + // set the app name if specified as metadata labels "app:" or "app.kubernetes.io/name:" or "k8s-app:" + rule { + action = "replace" + source_labels = [ + "__meta_kubernetes_pod_label_app_kubernetes_io_name", + "__meta_kubernetes_pod_label_k8s_app", + "__meta_kubernetes_pod_label_app", + ] + separator = ";" + regex = "^(?:;*)?([^;]+).*$" + replacement = "$1" + target_label = "app" + } + + // set the component if specified as metadata labels "component:" or "app.kubernetes.io/component:" or "k8s-component:" + rule { + action = "replace" + source_labels = [ + "__meta_kubernetes_pod_label_app_kubernetes_io_component", + "__meta_kubernetes_pod_label_k8s_component", + "__meta_kubernetes_pod_label_component", + ] + regex = "^(?:;*)?([^;]+).*$" + replacement = "$1" + target_label = "component" + } + + // set a source label + rule { + action = "replace" + replacement = "kubernetes" + target_label = "source" + } + } + + export "output" { + value = discovery.relabel.alloy_pods.output + } + } + + declare "alloy_integration_scrape" { + argument "targets" { + comment = "Must be a list() of targets" + } + + argument "forward_to" { + comment = "Must be a list(MetricsReceiver) where collected logs should be forwarded to" + } + + argument "job_label" { + comment = "The job label to add for all alloy metric (default: integrations/alloy)" + optional = true + } + + argument "keep_metrics" { + comment = "A regular expression of metrics to keep (default: see below)" + optional = true + } + + argument "drop_metrics" { + comment = "A regular expression of metrics to drop (default: see below)" + optional = true + } + + argument "scrape_interval" { + comment = "How often to scrape metrics from the targets (default: 60s)" + optional = true + } + + argument "scrape_timeout" { + comment = "How long before a scrape times out (default: 10s)" + optional = true + } + + argument "max_cache_size" { + comment = "The maximum number of elements to hold in the relabeling cache (default: 100000). This should be at least 2x-5x your largest scrape target or samples appended rate." + optional = true + } + + argument "clustering" { + comment = "Whether or not clustering should be enabled (default: false)" + optional = true + } + + prometheus.scrape "alloy" { + job_name = coalesce(argument.job_label.value, "integrations/alloy") + forward_to = [prometheus.relabel.alloy.receiver] + targets = argument.targets.value + scrape_interval = coalesce(argument.scrape_interval.value, "60s") + scrape_timeout = coalesce(argument.scrape_timeout.value, "10s") + + clustering { + enabled = coalesce(argument.clustering.value, false) + } + } + + // alloy metric relabelings (post-scrape) + prometheus.relabel "alloy" { + forward_to = argument.forward_to.value + max_cache_size = coalesce(argument.max_cache_size.value, 100000) + + // drop metrics that match the drop_metrics regex + rule { + source_labels = ["__name__"] + regex = coalesce(argument.drop_metrics.value, "(^(go|process)_.+$)") + action = "drop" + } + + // keep only metrics that match the keep_metrics regex + rule { + source_labels = ["__name__"] + regex = coalesce(argument.keep_metrics.value, ".*") + action = "keep" + } + + // remove the component_id label from any metric that starts with log_bytes or log_lines, these are custom metrics that are generated + // as part of the log annotation modules in this repo + rule { + action = "replace" + source_labels = ["__name__"] + regex = "^log_(bytes|lines).+" + replacement = "" + target_label = "component_id" + } + + // set the namespace label to that of the exported_namespace + rule { + action = "replace" + source_labels = ["__name__", "exported_namespace"] + separator = "@" + regex = "^log_(bytes|lines).+@(.+)" + replacement = "$2" + target_label = "namespace" + } + + // set the pod label to that of the exported_pod + rule { + action = "replace" + source_labels = ["__name__", "exported_pod"] + separator = "@" + regex = "^log_(bytes|lines).+@(.+)" + replacement = "$2" + target_label = "pod" + } + + // set the container label to that of the exported_container + rule { + action = "replace" + source_labels = ["__name__", "exported_container"] + separator = "@" + regex = "^log_(bytes|lines).+@(.+)" + replacement = "$2" + target_label = "container" + } + + // set the job label to that of the exported_job + rule { + action = "replace" + source_labels = ["__name__", "exported_job"] + separator = "@" + regex = "^log_(bytes|lines).+@(.+)" + replacement = "$2" + target_label = "job" + } + + // set the instance label to that of the exported_instance + rule { + action = "replace" + source_labels = ["__name__", "exported_instance"] + separator = "@" + regex = "^log_(bytes|lines).+@(.+)" + replacement = "$2" + target_label = "instance" + } + + rule { + action = "labeldrop" + regex = "exported_(namespace|pod|container|job|instance)" + } + } + } + {{- range $instance := $.Values.alloy.instances }} + {{- include "integrations.alloy.include.metrics" (dict "integration" $instance "Values" $.Values "Files" $.Files) | nindent 2 }} + {{- end }} +} +{{- end }} + +{{/* Instantiates the Alloy integration */}} +{{/* Inputs: integration (Alloy integration definition), Values (all values), Files (Files object) */}} +{{- define "integrations.alloy.include.metrics" }} +{{- $defaultValues := "integrations/alloy-values.yaml" | .Files.Get | fromYaml }} +{{- with merge .integration $defaultValues }} +{{- $metricAllowList := include "integrations.alloy.allowList" (dict "integration" . "Files" $.Files) }} +{{- $metricDenyList := .excludeMetrics }} +{{- $labelSelectors := list }} +{{- range $k, $v := .labelSelectors }} +{{- $labelSelectors = append $labelSelectors (printf "%s=%s" $k $v) }} +{{- end }} + +alloy_integration_discovery {{ include "helper.alloy_name" .name | quote }} { + port_name = "http-metrics" + label_selectors = {{ $labelSelectors | toJson }} +} + +alloy_integration_scrape {{ include "helper.alloy_name" .name | quote }} { + targets = alloy_integration_discovery.{{ include "helper.alloy_name" .name }}.output + clustering = true +{{- if $metricAllowList }} + keep_metrics = "up|{{ $metricAllowList | fromYamlArray | join "|" }}" +{{- end }} +{{- if $metricDenyList }} + drop_metrics = {{ $metricDenyList | join "|" | quote }} +{{- end }} + scrape_interval = {{ .scrapeInterval | default $.Values.global.scrapeInterval | quote }} + max_cache_size = {{ .maxCacheSize | default $.Values.global.maxCacheSize | int }} + forward_to = argument.metrics_destinations.value +} +{{- end }} +{{- end }} diff --git a/charts/feature-integrations/templates/_integration_cert-manager.tpl b/charts/feature-integrations/templates/_integration_cert-manager.tpl new file mode 100644 index 000000000..5c14a7bc2 --- /dev/null +++ b/charts/feature-integrations/templates/_integration_cert-manager.tpl @@ -0,0 +1,67 @@ +{{- define "integrations.cert-manager.type.metrics" }}true{{- end }} +{{- define "integrations.cert-manager.type.logs" }}false{{- end }} + +{{/* Loads the cert-manager module and instances */}} +{{/* Inputs: Values (all values), Files (Files object) */}} +{{- define "integrations.cert-manager.module.metrics" }} +declare "cert_manager_integration" { + argument "metrics_destinations" { + comment = "Must be a list of metric destinations where collected metrics should be forwarded to" + } + + import.git "cert_manager" { + repository = "https://github.com/grafana/alloy-modules.git" + revision = "main" + path = "modules/kubernetes/cert-manager/metrics.alloy" + pull_frequency = "15m" + } + + {{- range $instance := (index $.Values "cert-manager").instances }} + {{- include "integrations.cert-manager.include.metrics" (dict "integration" $instance "Values" $.Values "Files" $.Files) | nindent 2 }} + {{- end }} +} +{{- end }} + +{{/* Instantiates the cert-manager integration */}} +{{/* Inputs: integration (cert-manager integration definition), Values (all values), Files (Files object) */}} +{{- define "integrations.cert-manager.include.metrics" }} +{{- $defaultValues := "integrations/cert-manager-values.yaml" | .Files.Get | fromYaml }} +{{- with merge .integration $defaultValues }} +{{- $metricAllowList := .metricsTuning.includeMetrics }} +{{- $metricDenyList := .metricsTuning.excludeMetrics }} +{{- $labelSelectors := list }} +{{- range $k, $v := .labelSelectors }} +{{- $labelSelectors = append $labelSelectors (printf "%s=%s" $k $v) }} +{{- end }} +{{- $fieldSelectors := list }} +{{- range $k, $v := .fieldSelectors }} +{{- $fieldSelectors = append $fieldSelectors (printf "%s=%s" $k $v) }} +{{- end }} +cert_manager.kubernetes {{ include "helper.alloy_name" .name | quote }} { +{{- if .namespaces }} + namespaces = {{ .namespaces | toJson }} +{{- end }} +{{- if $labelSelectors }} + label_selectors = {{ $labelSelectors | toJson }} +{{- end }} +{{- if $fieldSelectors }} + field_selectors = {{ $fieldSelectors | toJson }} +{{- end }} + port_name = {{ .portName | quote }} +} + +cert_manager.scrape {{ include "helper.alloy_name" .name | quote }} { + targets = cert_manager.kubernetes.{{ include "helper.alloy_name" .name }}.output + clustering = true +{{- if $metricAllowList }} + keep_metrics = "up|{{ $metricAllowList | join "|" | join "|" }}" +{{- end }} +{{- if $metricDenyList }} + drop_metrics = {{ $metricDenyList | join "|" | quote }} +{{- end }} + scrape_interval = {{ .scrapeInterval | default $.Values.global.scrapeInterval | quote }} + max_cache_size = {{ .maxCacheSize | default $.Values.global.maxCacheSize | int }} + forward_to = argument.metrics_destinations.value +} +{{- end }} +{{- end }} diff --git a/charts/feature-integrations/templates/_integration_etcd.tpl b/charts/feature-integrations/templates/_integration_etcd.tpl new file mode 100644 index 000000000..8b35612f3 --- /dev/null +++ b/charts/feature-integrations/templates/_integration_etcd.tpl @@ -0,0 +1,67 @@ +{{- define "integrations.etcd.type.metrics" }}true{{- end }} +{{- define "integrations.etcd.type.logs" }}false{{- end }} + +{{/* Loads the etcd module and instances */}} +{{/* Inputs: Values (all values), Files (Files object) */}} +{{- define "integrations.etcd.module.metrics" }} +declare "etcd_integration" { + argument "metrics_destinations" { + comment = "Must be a list of metric destinations where collected metrics should be forwarded to" + } + + import.git "etcd" { + repository = "https://github.com/grafana/alloy-modules.git" + revision = "main" + path = "modules/databases/kv/etcd/metrics.alloy" + pull_frequency = "15m" + } + + {{- range $instance := (index $.Values "etcd").instances }} + {{- include "integrations.etcd.include.metrics" (dict "integration" $instance "Values" $.Values "Files" $.Files) | nindent 2 }} + {{- end }} +} +{{- end }} + +{{/* Instantiates the etcd integration */}} +{{/* Inputs: integration (etcd integration definition), Values (all values), Files (Files object) */}} +{{- define "integrations.etcd.include.metrics" }} +{{- $defaultValues := "integrations/etcd-values.yaml" | .Files.Get | fromYaml }} +{{- with merge .integration $defaultValues }} +{{- $metricAllowList := .metricsTuning.includeMetrics }} +{{- $metricDenyList := .metricsTuning.excludeMetrics }} +{{- $labelSelectors := list }} +{{- range $k, $v := .labelSelectors }} +{{- $labelSelectors = append $labelSelectors (printf "%s=%s" $k $v) }} +{{- end }} +{{- $fieldSelectors := list }} +{{- range $k, $v := .fieldSelectors }} +{{- $fieldSelectors = append $fieldSelectors (printf "%s=%s" $k $v) }} +{{- end }} +etcd.kubernetes {{ include "helper.alloy_name" .name | quote }} { +{{- if .namespaces }} + namespaces = {{ .namespaces | toJson }} +{{- end }} +{{- if $labelSelectors }} + label_selectors = {{ $labelSelectors | toJson }} +{{- end }} +{{- if $fieldSelectors }} + field_selectors = {{ $fieldSelectors | toJson }} +{{- end }} + port_name = {{ .portName | quote }} +} + +etcd.scrape {{ include "helper.alloy_name" .name | quote }} { + targets = etcd.kubernetes.{{ include "helper.alloy_name" .name }}.output + clustering = true +{{- if $metricAllowList }} + keep_metrics = "up|{{ $metricAllowList | join "|" | join "|" }}" +{{- end }} +{{- if $metricDenyList }} + drop_metrics = {{ $metricDenyList | join "|" | quote }} +{{- end }} + scrape_interval = {{ .scrapeInterval | default $.Values.global.scrapeInterval | quote }} + max_cache_size = {{ .maxCacheSize | default $.Values.global.maxCacheSize | int }} + forward_to = argument.metrics_destinations.value +} +{{- end }} +{{- end }} diff --git a/charts/feature-integrations/templates/_integration_helpers.tpl b/charts/feature-integrations/templates/_integration_helpers.tpl new file mode 100644 index 000000000..3b7760f41 --- /dev/null +++ b/charts/feature-integrations/templates/_integration_helpers.tpl @@ -0,0 +1,21 @@ +{{/* Inputs: . (Values) */}} +{{- define "feature.integrations.configured.metrics" }} + {{- range $type := (include "integrations.types" .) | fromYamlArray }} + {{- if (index $.Values $type).instances }} + {{- if eq (include (printf "integrations.%s.type.metrics" $type) .) "true" }} +- {{ $type }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} + +{{/* Inputs: . (Values) */}} +{{- define "feature.integrations.configured.logs" }} + {{- range $type := (include "integrations.types" .) | fromYamlArray }} + {{- if (index $.Values $type).instances }} + {{- if eq (include (printf "integrations.%s.type.logs" $type) .) "true" }} +- {{ $type }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/charts/feature-integrations/templates/_integration_types.tpl b/charts/feature-integrations/templates/_integration_types.tpl new file mode 100644 index 000000000..ca46ab306 --- /dev/null +++ b/charts/feature-integrations/templates/_integration_types.tpl @@ -0,0 +1,6 @@ +{{/* Do not edit this file. It is generated by the Makefile */}} +{{- define "integrations.types" -}} +- etcd +- alloy +- cert-manager +{{- end -}} diff --git a/charts/feature-integrations/templates/_notes.tpl b/charts/feature-integrations/templates/_notes.tpl new file mode 100644 index 000000000..3042cd3cb --- /dev/null +++ b/charts/feature-integrations/templates/_notes.tpl @@ -0,0 +1,8 @@ +{{- define "feature.integrations.notes.deployments" }}{{- end }} + +{{/* TODO: add details about the actual integrations */}} +{{- define "feature.integrations.notes.task" }} +Gather data from service integrations +{{- end }} + +{{- define "feature.integrations.notes.actions" }}{{- end }} diff --git a/charts/feature-integrations/templates/configmap.yaml b/charts/feature-integrations/templates/configmap.yaml new file mode 100644 index 000000000..9a042761f --- /dev/null +++ b/charts/feature-integrations/templates/configmap.yaml @@ -0,0 +1,15 @@ +{{- if .Values.deployAsConfigMap }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "integrations.fullname" . }} + namespace: {{ .Release.Namespace }} +data: + metrics.alloy: |- +{{- range $type := (include "integrations.types" . | fromYamlArray) }} + {{- if (index $.Values $type).instances }} + {{- include (printf "integrations.%s.module.metrics" $type) (dict "Values" $.Values "Files" $.Files) | indent 4 }} + {{- end }} +{{- end }} +{{- end }} diff --git a/charts/feature-integrations/tests/alloy_test.yaml b/charts/feature-integrations/tests/alloy_test.yaml new file mode 100644 index 000000000..6b18fa5d8 --- /dev/null +++ b/charts/feature-integrations/tests/alloy_test.yaml @@ -0,0 +1,302 @@ +# yamllint disable rule:document-start rule:line-length rule:trailing-spaces +suite: Test Alloy integration +templates: + - configmap.yaml +tests: + - it: should create the alloy config + set: + deployAsConfigMap: true + alloy: + instances: + - name: alloy-metrics + asserts: + - isKind: + of: ConfigMap + - equal: + path: data["metrics.alloy"] + value: |- + declare "alloy_integration" { + argument "metrics_destinations" { + comment = "Must be a list of metric destinations where collected metrics should be forwarded to" + } + + declare "alloy_integration_discovery" { + argument "namespaces" { + comment = "The namespaces to look for targets in (default: [] is all namespaces)" + optional = true + } + + argument "field_selectors" { + comment = "The field selectors to use to find matching targets (default: [])" + optional = true + } + + argument "label_selectors" { + comment = "The label selectors to use to find matching targets (default: [\"app.kubernetes.io/name=alloy\"])" + optional = true + } + + argument "port_name" { + comment = "The of the port to scrape metrics from (default: http-metrics)" + optional = true + } + + // Alloy service discovery for all of the pods + discovery.kubernetes "alloy_pods" { + role = "pod" + + selectors { + role = "pod" + field = join(coalesce(argument.field_selectors.value, []), ",") + label = join(coalesce(argument.label_selectors.value, ["app.kubernetes.io/name=alloy"]), ",") + } + + namespaces { + names = coalesce(argument.namespaces.value, []) + } + } + + // alloy relabelings (pre-scrape) + discovery.relabel "alloy_pods" { + targets = discovery.kubernetes.alloy_pods.targets + + // keep only the specified metrics port name, and pods that are Running and ready + rule { + source_labels = [ + "__meta_kubernetes_pod_container_port_name", + "__meta_kubernetes_pod_phase", + "__meta_kubernetes_pod_ready", + "__meta_kubernetes_pod_container_init", + ] + separator = "@" + regex = coalesce(argument.port_name.value, "metrics") + "@Running@true@false" + action = "keep" + } + + rule { + source_labels = ["__meta_kubernetes_namespace"] + target_label = "namespace" + } + + rule { + source_labels = ["__meta_kubernetes_pod_name"] + target_label = "pod" + } + + rule { + source_labels = ["__meta_kubernetes_pod_container_name"] + target_label = "container" + } + + rule { + source_labels = [ + "__meta_kubernetes_pod_controller_kind", + "__meta_kubernetes_pod_controller_name", + ] + separator = "/" + target_label = "workload" + } + // remove the hash from the ReplicaSet + rule { + source_labels = ["workload"] + regex = "(ReplicaSet/.+)-.+" + target_label = "workload" + } + + // set the app name if specified as metadata labels "app:" or "app.kubernetes.io/name:" or "k8s-app:" + rule { + action = "replace" + source_labels = [ + "__meta_kubernetes_pod_label_app_kubernetes_io_name", + "__meta_kubernetes_pod_label_k8s_app", + "__meta_kubernetes_pod_label_app", + ] + separator = ";" + regex = "^(?:;*)?([^;]+).*$" + replacement = "$1" + target_label = "app" + } + + // set the component if specified as metadata labels "component:" or "app.kubernetes.io/component:" or "k8s-component:" + rule { + action = "replace" + source_labels = [ + "__meta_kubernetes_pod_label_app_kubernetes_io_component", + "__meta_kubernetes_pod_label_k8s_component", + "__meta_kubernetes_pod_label_component", + ] + regex = "^(?:;*)?([^;]+).*$" + replacement = "$1" + target_label = "component" + } + + // set a source label + rule { + action = "replace" + replacement = "kubernetes" + target_label = "source" + } + } + + export "output" { + value = discovery.relabel.alloy_pods.output + } + } + + declare "alloy_integration_scrape" { + argument "targets" { + comment = "Must be a list() of targets" + } + + argument "forward_to" { + comment = "Must be a list(MetricsReceiver) where collected logs should be forwarded to" + } + + argument "job_label" { + comment = "The job label to add for all alloy metric (default: integrations/alloy)" + optional = true + } + + argument "keep_metrics" { + comment = "A regular expression of metrics to keep (default: see below)" + optional = true + } + + argument "drop_metrics" { + comment = "A regular expression of metrics to drop (default: see below)" + optional = true + } + + argument "scrape_interval" { + comment = "How often to scrape metrics from the targets (default: 60s)" + optional = true + } + + argument "scrape_timeout" { + comment = "How long before a scrape times out (default: 10s)" + optional = true + } + + argument "max_cache_size" { + comment = "The maximum number of elements to hold in the relabeling cache (default: 100000). This should be at least 2x-5x your largest scrape target or samples appended rate." + optional = true + } + + argument "clustering" { + comment = "Whether or not clustering should be enabled (default: false)" + optional = true + } + + prometheus.scrape "alloy" { + job_name = coalesce(argument.job_label.value, "integrations/alloy") + forward_to = [prometheus.relabel.alloy.receiver] + targets = argument.targets.value + scrape_interval = coalesce(argument.scrape_interval.value, "60s") + scrape_timeout = coalesce(argument.scrape_timeout.value, "10s") + + clustering { + enabled = coalesce(argument.clustering.value, false) + } + } + + // alloy metric relabelings (post-scrape) + prometheus.relabel "alloy" { + forward_to = argument.forward_to.value + max_cache_size = coalesce(argument.max_cache_size.value, 100000) + + // drop metrics that match the drop_metrics regex + rule { + source_labels = ["__name__"] + regex = coalesce(argument.drop_metrics.value, "(^(go|process)_.+$)") + action = "drop" + } + + // keep only metrics that match the keep_metrics regex + rule { + source_labels = ["__name__"] + regex = coalesce(argument.keep_metrics.value, ".*") + action = "keep" + } + + // remove the component_id label from any metric that starts with log_bytes or log_lines, these are custom metrics that are generated + // as part of the log annotation modules in this repo + rule { + action = "replace" + source_labels = ["__name__"] + regex = "^log_(bytes|lines).+" + replacement = "" + target_label = "component_id" + } + + // set the namespace label to that of the exported_namespace + rule { + action = "replace" + source_labels = ["__name__", "exported_namespace"] + separator = "@" + regex = "^log_(bytes|lines).+@(.+)" + replacement = "$2" + target_label = "namespace" + } + + // set the pod label to that of the exported_pod + rule { + action = "replace" + source_labels = ["__name__", "exported_pod"] + separator = "@" + regex = "^log_(bytes|lines).+@(.+)" + replacement = "$2" + target_label = "pod" + } + + // set the container label to that of the exported_container + rule { + action = "replace" + source_labels = ["__name__", "exported_container"] + separator = "@" + regex = "^log_(bytes|lines).+@(.+)" + replacement = "$2" + target_label = "container" + } + + // set the job label to that of the exported_job + rule { + action = "replace" + source_labels = ["__name__", "exported_job"] + separator = "@" + regex = "^log_(bytes|lines).+@(.+)" + replacement = "$2" + target_label = "job" + } + + // set the instance label to that of the exported_instance + rule { + action = "replace" + source_labels = ["__name__", "exported_instance"] + separator = "@" + regex = "^log_(bytes|lines).+@(.+)" + replacement = "$2" + target_label = "instance" + } + + rule { + action = "labeldrop" + regex = "exported_(namespace|pod|container|job|instance)" + } + } + } + + + alloy_integration_discovery "alloy_metrics" { + port_name = "http-metrics" + label_selectors = ["app.kubernetes.io/name=alloy"] + } + + alloy_integration_scrape "alloy_metrics" { + targets = alloy_integration_discovery.alloy_metrics.output + clustering = true + keep_metrics = "up|" + scrape_interval = "60s" + max_cache_size = 100000 + forward_to = argument.metrics_destinations.value + } + } diff --git a/charts/feature-integrations/tests/cert-manager_test.yaml b/charts/feature-integrations/tests/cert-manager_test.yaml new file mode 100644 index 000000000..6ee9cdd86 --- /dev/null +++ b/charts/feature-integrations/tests/cert-manager_test.yaml @@ -0,0 +1,82 @@ +# yamllint disable rule:document-start rule:line-length rule:trailing-spaces +suite: Test cert-manager integration +templates: + - configmap.yaml +tests: + - it: should create the cert-manager config + set: + deployAsConfigMap: true + cert-manager: + instances: + - name: my-cert-manager + asserts: + - isKind: + of: ConfigMap + - equal: + path: data["metrics.alloy"] + value: |- + declare "cert_manager_integration" { + argument "metrics_destinations" { + comment = "Must be a list of metric destinations where collected metrics should be forwarded to" + } + + import.git "cert_manager" { + repository = "https://github.com/grafana/alloy-modules.git" + revision = "main" + path = "modules/kubernetes/cert-manager/metrics.alloy" + pull_frequency = "15m" + } + + cert_manager.kubernetes "my_cert_manager" { + label_selectors = ["app.kubernetes.io/name=cert-manager"] + port_name = "http-metrics" + } + + cert_manager.scrape "my_cert_manager" { + targets = cert_manager.kubernetes.my_cert_manager.output + clustering = true + scrape_interval = "60s" + max_cache_size = 100000 + forward_to = argument.metrics_destinations.value + } + } + - it: can be restricted to a namespace + set: + deployAsConfigMap: true + cert-manager: + instances: + - name: my-cert-manager + namespaces: + - kube-system + asserts: + - isKind: + of: ConfigMap + - equal: + path: data["metrics.alloy"] + value: |- + declare "cert_manager_integration" { + argument "metrics_destinations" { + comment = "Must be a list of metric destinations where collected metrics should be forwarded to" + } + + import.git "cert_manager" { + repository = "https://github.com/grafana/alloy-modules.git" + revision = "main" + path = "modules/kubernetes/cert-manager/metrics.alloy" + pull_frequency = "15m" + } + + cert_manager.kubernetes "my_cert_manager" { + namespaces = ["kube-system"] + label_selectors = ["app.kubernetes.io/name=cert-manager"] + port_name = "http-metrics" + } + + cert_manager.scrape "my_cert_manager" { + targets = cert_manager.kubernetes.my_cert_manager.output + clustering = true + scrape_interval = "60s" + max_cache_size = 100000 + forward_to = argument.metrics_destinations.value + } + } diff --git a/charts/feature-integrations/tests/etcd_test.yaml b/charts/feature-integrations/tests/etcd_test.yaml new file mode 100644 index 000000000..0f9c79fa2 --- /dev/null +++ b/charts/feature-integrations/tests/etcd_test.yaml @@ -0,0 +1,82 @@ +# yamllint disable rule:document-start rule:line-length rule:trailing-spaces +suite: Test etcd integration +templates: + - configmap.yaml +tests: + - it: should create the etcd config + set: + deployAsConfigMap: true + etcd: + instances: + - name: my-etcd + asserts: + - isKind: + of: ConfigMap + - equal: + path: data["metrics.alloy"] + value: |- + declare "etcd_integration" { + argument "metrics_destinations" { + comment = "Must be a list of metric destinations where collected metrics should be forwarded to" + } + + import.git "etcd" { + repository = "https://github.com/grafana/alloy-modules.git" + revision = "main" + path = "modules/databases/kv/etcd/metrics.alloy" + pull_frequency = "15m" + } + + etcd.kubernetes "my_etcd" { + label_selectors = ["app.kubernetes.io/component=etcd"] + port_name = "metrics" + } + + etcd.scrape "my_etcd" { + targets = etcd.kubernetes.my_etcd.output + clustering = true + scrape_interval = "60s" + max_cache_size = 100000 + forward_to = argument.metrics_destinations.value + } + } + - it: can be restricted to a namespace + set: + deployAsConfigMap: true + etcd: + instances: + - name: my-etcd + namespaces: + - kube-system + asserts: + - isKind: + of: ConfigMap + - equal: + path: data["metrics.alloy"] + value: |- + declare "etcd_integration" { + argument "metrics_destinations" { + comment = "Must be a list of metric destinations where collected metrics should be forwarded to" + } + + import.git "etcd" { + repository = "https://github.com/grafana/alloy-modules.git" + revision = "main" + path = "modules/databases/kv/etcd/metrics.alloy" + pull_frequency = "15m" + } + + etcd.kubernetes "my_etcd" { + namespaces = ["kube-system"] + label_selectors = ["app.kubernetes.io/component=etcd"] + port_name = "metrics" + } + + etcd.scrape "my_etcd" { + targets = etcd.kubernetes.my_etcd.output + clustering = true + scrape_interval = "60s" + max_cache_size = 100000 + forward_to = argument.metrics_destinations.value + } + } diff --git a/charts/feature-integrations/values.schema.json b/charts/feature-integrations/values.schema.json new file mode 100644 index 000000000..de60a71d5 --- /dev/null +++ b/charts/feature-integrations/values.schema.json @@ -0,0 +1,203 @@ +{ + "$schema": "http://json-schema.org/schema#", + "type": "object", + "properties": { + "alloy": { + "type": "object", + "properties": { + "instances": { + "type": "array" + } + } + }, + "cert-manager": { + "type": "object", + "properties": { + "instances": { + "type": "array" + } + } + }, + "deployAsConfigMap": { + "type": "boolean" + }, + "etcd": { + "type": "object", + "properties": { + "instances": { + "type": "array" + } + } + }, + "fullnameOverride": { + "type": "string" + }, + "global": { + "type": "object", + "properties": { + "maxCacheSize": { + "type": "integer" + }, + "scrapeInterval": { + "type": "string" + } + } + }, + "nameOverride": { + "type": "string" + } + }, + "definitions": { + "alloy-integration": { + "type": "object", + "properties": { + "labelSelectors": { + "type": "object", + "properties": { + "app.kubernetes.io/name": { + "type": "string" + } + } + }, + "maxCacheSize": { + "type": "null" + }, + "metricsTuning": { + "type": "object", + "properties": { + "excludeMetrics": { + "type": "array" + }, + "includeMetrics": { + "type": "array" + }, + "useDefaultAllowList": { + "type": "boolean" + }, + "useIntegrationAllowList": { + "type": "boolean" + } + } + }, + "name": { + "type": "string" + }, + "scrapeInterval": { + "type": "null" + }, + "type": { + "type": "string", + "const": "alloy" + } + } + }, + "cert-manager-integration": { + "type": "object", + "properties": { + "field_selectors": { + "type": "array" + }, + "labelSelectors": { + "type": "object", + "properties": { + "app.kubernetes.io/name": { + "type": "string" + } + } + }, + "maxCacheSize": { + "type": "null" + }, + "metricsTuning": { + "type": "object", + "properties": { + "excludeMetrics": { + "type": "array" + }, + "includeMetrics": { + "type": "array" + } + } + }, + "name": { + "type": "string" + }, + "namespaces": { + "type": "array" + }, + "portName": { + "type": "string" + }, + "scrapeInterval": { + "type": "null" + }, + "type": { + "type": "string", + "const": "cert-manager" + } + } + }, + "etcd-integration": { + "type": "object", + "properties": { + "field_selectors": { + "type": "array" + }, + "labelSelectors": { + "type": "object", + "properties": { + "app.kubernetes.io/component": { + "type": "string" + } + } + }, + "maxCacheSize": { + "type": "null" + }, + "metricsTuning": { + "type": "object", + "properties": { + "excludeMetrics": { + "type": "array" + }, + "includeMetrics": { + "type": "array" + } + } + }, + "name": { + "type": "string" + }, + "namespaces": { + "type": "array" + }, + "portName": { + "type": "string" + }, + "scrapeInterval": { + "type": "null" + }, + "type": { + "type": "string", + "const": "etcd" + } + } + }, + "integration-list": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/etcd-integration" + }, + { + "$ref": "#/definitions/alloy-integration" + }, + { + "$ref": "#/definitions/cert-manager-integration" + } + ] + } + } + } +} diff --git a/charts/feature-integrations/values.yaml b/charts/feature-integrations/values.yaml new file mode 100644 index 000000000..90dc2700f --- /dev/null +++ b/charts/feature-integrations/values.yaml @@ -0,0 +1,35 @@ +# -- Name override +# @section -- General settings +nameOverride: "" + +# -- Full name override +# @section -- General settings +fullnameOverride: "" + +global: + # -- How frequently to scrape metrics. + # @section -- Global Settings + scrapeInterval: 60s + + # -- Sets the max_cache_size for every prometheus.relabel component. ([docs](https://grafana.com/docs/alloy/latest/reference/components/prometheus.relabel/#arguments)) + # This should be at least 2x-5x your largest scrape target or samples appended rate. + # @section -- Global Settings + maxCacheSize: 100000 + +# -- Scrape metrics from Grafana Alloy +# @section -- Integration: Alloy +alloy: + instances: [] + +# -- Scrape metrics from cert-manager +# @section -- Integration: cert-manager +cert-manager: + instances: [] + +# -- Scrape metrics from etcd +# @section -- Integration: etcd +etcd: + instances: [] + +# @ignore +deployAsConfigMap: false diff --git a/charts/feature-pod-logs/Makefile b/charts/feature-pod-logs/Makefile index 9bb0eae02..0889e5364 100644 --- a/charts/feature-pod-logs/Makefile +++ b/charts/feature-pod-logs/Makefile @@ -16,11 +16,15 @@ Chart.lock: Chart.yaml values.schema.json: values.yaml $$(wildcard schema-mods/*) ../../scripts/schema-gen.sh . -.PHONY: all -all: README.md Chart.lock values.schema.json +.PHONY: clean +clean: + rm -f README.md Chart.lock values.schema.json + +.PHONY: build +build: README.md Chart.lock values.schema.json .PHONY: test -test: all +test: build helm lint . ifdef HAS_HELM_UNITTEST helm unittest . diff --git a/charts/feature-profiling/Makefile b/charts/feature-profiling/Makefile index 9bb0eae02..0889e5364 100644 --- a/charts/feature-profiling/Makefile +++ b/charts/feature-profiling/Makefile @@ -16,11 +16,15 @@ Chart.lock: Chart.yaml values.schema.json: values.yaml $$(wildcard schema-mods/*) ../../scripts/schema-gen.sh . -.PHONY: all -all: README.md Chart.lock values.schema.json +.PHONY: clean +clean: + rm -f README.md Chart.lock values.schema.json + +.PHONY: build +build: README.md Chart.lock values.schema.json .PHONY: test -test: all +test: build helm lint . ifdef HAS_HELM_UNITTEST helm unittest . diff --git a/charts/feature-prometheus-operator-objects/Makefile b/charts/feature-prometheus-operator-objects/Makefile index 9bb0eae02..0889e5364 100644 --- a/charts/feature-prometheus-operator-objects/Makefile +++ b/charts/feature-prometheus-operator-objects/Makefile @@ -16,11 +16,15 @@ Chart.lock: Chart.yaml values.schema.json: values.yaml $$(wildcard schema-mods/*) ../../scripts/schema-gen.sh . -.PHONY: all -all: README.md Chart.lock values.schema.json +.PHONY: clean +clean: + rm -f README.md Chart.lock values.schema.json + +.PHONY: build +build: README.md Chart.lock values.schema.json .PHONY: test -test: all +test: build helm lint . ifdef HAS_HELM_UNITTEST helm unittest . diff --git a/scripts/docs-and-schema-image/Dockerfile b/scripts/docs-and-schema-image/Dockerfile new file mode 100644 index 000000000..6626c8288 --- /dev/null +++ b/scripts/docs-and-schema-image/Dockerfile @@ -0,0 +1,11 @@ +FROM jnorwood/helm-docs:v1.14.2 AS helm-docs + +FROM alpine/helm:3.15.4 +RUN apk add --no-cache jq + +COPY --from=helm-docs /usr/bin/helm-docs /usr/bin/helm-docs +COPY create-docs-and-schema.sh /usr/bin/create-docs-and-schema.sh + +RUN helm plugin install https://github.com/karuppiah7890/helm-schema-gen.git + +ENTRYPOINT ["/usr/bin/create-docs-and-schema.sh"] diff --git a/scripts/docs-and-schema-image/Makefile b/scripts/docs-and-schema-image/Makefile new file mode 100644 index 000000000..d475a32b1 --- /dev/null +++ b/scripts/docs-and-schema-image/Makefile @@ -0,0 +1,7 @@ +.PHONY: build +build: Dockerfile create-docs-and-schema.sh + docker build --platform linux/amd64 -t ghcr.io/grafana/helm-docs-and-schema-gen . + +.PHONY: push +push: build + docker push ghcr.io/grafana/helm-docs-and-schema-gen diff --git a/scripts/docs-and-schema-image/create-docs-and-schema.sh b/scripts/docs-and-schema-image/create-docs-and-schema.sh new file mode 100755 index 000000000..cbfa2a1bf --- /dev/null +++ b/scripts/docs-and-schema-image/create-docs-and-schema.sh @@ -0,0 +1,65 @@ +#!/bin/bash + +usage() { + echo "USAGE: create-docs-and-schema.sh " + echo "Creates the docs and schema for a values file snippet" + echo "" + echo " is the kind of resource (e.g. destination, integration)" + echo "" + echo "Expects a file at /src/s/-values.yaml" + echo "Looks for an optional file at /src/docs/s/.doc_templates/.gotmpl" + echo "Will write the doc to /src/docs/s/.md" + echo "Will write the schema to /src/schema-mods/definitions/-.schema.json" +} + +NAME=$1 +KIND=$2 +INPUT_VALUES=/src/${KIND}s/${NAME}-values.yaml +INPUT_TEMPLATE=/src/docs/${KIND}s/.doc_templates/${NAME}.gotmpl +OUTPUT_DOCS=/src/docs/${KIND}s/${NAME}.md +OUTPUT_SCHEMA=/src/schema-mods/definitions/${NAME}-${KIND}.schema.json + +if [ -z "${NAME}" ]; then + echo "Name not defined!" + usage + exit 1 +fi + +if [ -z "${KIND}" ]; then + echo "Name not defined!" + usage + exit 1 +fi + +if [ ! -f "${INPUT_VALUES}" ]; then + echo "${INPUT_VALUES} is not a file!" + usage + exit 1 +fi + +set -eo pipefail + +echo "Creating temporary Helm chart for ${NAME}..." +helm create "/tmp/${NAME}" +cd "/tmp/${NAME}" + +echo "Creating docs..." +cp "${INPUT_VALUES}" values.yaml +if [ -f "${INPUT_TEMPLATE}" ]; then + cp "${INPUT_TEMPLATE}" README.md.gotmpl +else + echo "# ${NAME}" > README.md.gotmpl + echo '{{ template "chart.valuesSection" . }}' >> README.md.gotmpl +fi + +helm-docs +mv README.md "${OUTPUT_DOCS}" + +echo "Creating schema..." +helm schema-gen values.yaml > "${OUTPUT_SCHEMA}" +jq --indent 4 --arg name "${NAME}" \ + 'del(.["$schema"]) + | .properties.name = {"type": "string"} + | .properties.type = {"type": "string", "const": $name}' \ + "${OUTPUT_SCHEMA}" > "${OUTPUT_SCHEMA}.tmp" +mv "${OUTPUT_SCHEMA}.tmp" "${OUTPUT_SCHEMA}" \ No newline at end of file