diff --git a/.github/workflows/charts-release.yaml b/.github/workflows/charts-release.yaml index 0e42a0acfc0..6d1050c2ae4 100644 --- a/.github/workflows/charts-release.yaml +++ b/.github/workflows/charts-release.yaml @@ -93,7 +93,7 @@ jobs: - name: Fix Pre-Commit issues shell: bash - if: needs.check_changes.outputs.changes_detected == 'true' + if: needs.check_changes.outputs.changes_detected == 'true' run: | echo "Running pre-commit test-and-cleanup..." pre-commit run --all ||: @@ -101,7 +101,7 @@ jobs: find . -name '*.sh' | xargs chmod +x - name: Install Helm - if: needs.check_changes.outputs.changes_detected == 'true' + if: needs.check_changes.outputs.changes_detected == 'true' uses: azure/setup-helm@5119fcb9089d432beecbf79bb2c7915207344b78 # tag=v3 with: version: v3.14.0 @@ -145,7 +145,7 @@ jobs: run: helm registry logout quay.io - name: Copy docs to website - if: needs.check_changes.outputs.changes_detected == 'true' + if: needs.check_changes.outputs.changes_detected == 'true' shell: bash run: | #!/bin/bash @@ -196,7 +196,7 @@ jobs: - name: Prefetch contributor icons shell: bash - if: needs.check_changes.outputs.changes_detected == 'true' + if: needs.check_changes.outputs.changes_detected == 'true' run: | #!/bin/bash @@ -221,7 +221,7 @@ jobs: #done < src/assets/contributors.json - name: Setup astro Cache - if: needs.check_changes.outputs.changes_detected == 'true' + if: needs.check_changes.outputs.changes_detected == 'true' uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4 with: # Cache for build and optimized images. @@ -230,7 +230,7 @@ jobs: restore-keys: astro- - name: Setup npm Cache - if: needs.check_changes.outputs.changes_detected == 'true' + if: needs.check_changes.outputs.changes_detected == 'true' uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4 with: # Cache for npm @@ -240,7 +240,7 @@ jobs: - name: Setup node_modules Cache id: modulescache - if: needs.check_changes.outputs.changes_detected == 'true' + if: needs.check_changes.outputs.changes_detected == 'true' uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4 with: # Cache for npm and optimized images. @@ -254,19 +254,19 @@ jobs: node-version-file: ./website/.nvmrc - name: Install Packages - if: steps.modulescache.outputs.cache-hit != 'true' && needs.check_changes.outputs.changes_detected == 'true' + if: steps.modulescache.outputs.cache-hit != 'true' && needs.check_changes.outputs.changes_detected == 'true' run: cd website && npm ci - name: Check - if: needs.check_changes.outputs.changes_detected == 'true' + if: needs.check_changes.outputs.changes_detected == 'true' run: cd website && npm run check - name: Build - if: needs.check_changes.outputs.changes_detected == 'true' + if: needs.check_changes.outputs.changes_detected == 'true' run: cd website && npm run build - name: Publish to Cloudflare Pages - if: needs.check_changes.outputs.changes_detected == 'true' + if: needs.check_changes.outputs.changes_detected == 'true' id: cloudflare continue-on-error: true uses: cloudflare/pages-action@f0a1cd58cd66095dee69bfa18fa5efd1dde93bca # v1 @@ -299,5 +299,5 @@ jobs: --- - name: Release-and-Website Completed - if: needs.check_changes.outputs.changes_detected == 'true' + if: needs.check_changes.outputs.changes_detected == 'true' run: echo "DONE" diff --git a/.github/workflows/charts-test.yaml b/.github/workflows/charts-test.yaml index 50106bd3a08..d9c985ef2f0 100644 --- a/.github/workflows/charts-test.yaml +++ b/.github/workflows/charts-test.yaml @@ -151,6 +151,19 @@ jobs: - name: Set up chart-testing uses: helm/chart-testing-action@e6669bcd63d7cb57cb4380c33043eebe5d111992 # v2.6.1 + - name: Update containerd config + if: contains(matrix.chart, 'Spegel') + run: | + sudo mkdir -p /var/lib/rancher/k3s/agent/etc/containerd/ + sudo tee /var/lib/rancher/k3s/agent/etc/containerd/config.toml.tmpl > /dev/null < /dev/null < /dev/null < /dev/null < /dev/null < /dev/null <=1.24.0-0' +maintainers: + - name: TrueCharts + email: info@truecharts.org + url: https://truecharts.org +name: spegel +sources: + - https://github.com/truecharts/charts/tree/master/charts/system/spegel +type: application +version: 2.0.0 diff --git a/charts/incubator/spegel/README.md b/charts/incubator/spegel/README.md new file mode 100644 index 00000000000..44bbdfa70d7 --- /dev/null +++ b/charts/incubator/spegel/README.md @@ -0,0 +1,61 @@ +--- +title: README +--- + +## General Info + +TrueCharts can be installed as both _normal_ Helm Charts or as TrueNAS SCALE Apps. +Both solutions are fully supported, but we heavily advice the use of normal Helm Charts where possible + +For more information about this Chart, please check the docs on the TrueCharts [website](https://truecharts.org/charts/system/spegel) + +**This chart is not maintained by the upstream project and any issues with the chart should be raised [here](https://github.com/truecharts/charts/issues/new/choose)** + +## Installation + +### Helm-Chart installation + +To install TrueCharts Helm charts using Helm, you can use our OCI Repository. + +`helm install mychart oci://tccr.io/truecharts/spegel` + +For more information on how to install TrueCharts Helm charts, checkout the [instructions on the website](/guides) + + +### TrueNAS SCALE Apps + +For more information on how to use TrueCharts as TrueNAS SCALE Apps, please checkout the [quick-start guides for TrueNAS SCALE](/deprecated/scale). + +## Chart Specific Guides and information + +All our charts have dedicated documentation pages. +The documentation for this chart can be found here: +https://truecharts.org/charts/system/spegel + +## Configuration Options + +Please note: For TrueNAS SCALE, only options available in the GUI are supported. +Hence most of these docs do not apply to TrueNAS SCALE + +To view the chart specific options, please view Values.yaml included in the chart. +The most recent version of which, is available here: https://github.com/truecharts/public/blob/master/charts/system/spegel/values.yaml + +All our Charts use a shared "common" library chart that contains most of the templating and options. +For the complete overview of all available options, please checkout the documentation for them on the [common docs on our website](/common) + +For information about the common chart and all defaults included with it, please review its values.yaml file available here: https://github.com/truecharts/public/blob/master/charts/library/common/values.yaml + +## Support + +- See the [Website](https://truecharts.org) +- Check our [Discord](https://discord.gg/tVsPTHWTtr) +- Open a [issue](https://github.com/truecharts/charts/issues/new/choose) + +--- + +## Sponsor TrueCharts + +TrueCharts can only exist due to the incredible effort of our staff. +Please consider making a [donation](/general/sponsor) or contributing back to the project any way you can! + +_All Rights Reserved - The TrueCharts Project_ diff --git a/charts/incubator/spegel/ci/ci-values.yaml b/charts/incubator/spegel/ci/ci-values.yaml new file mode 100644 index 00000000000..92bf13bb2b3 --- /dev/null +++ b/charts/incubator/spegel/ci/ci-values.yaml @@ -0,0 +1,9 @@ +spegel: + # -- Minimum log level to output. Value should be DEBUG, INFO, WARN, or ERROR. + logLevel: "INFO" + # -- Path to Containerd socket. + containerdSock: "/run/k3s/containerd/containerd.sock" + # -- Path to Containerd mirror configuration. + containerdRegistryConfigPath: "/var/lib/rancher/k3s/agent/etc/containerd/certs.d" + # -- Path to Containerd content store.. + containerdContentPath: "/var/lib/containerd/io.containerd.content.v1.content" diff --git a/charts/incubator/spegel/dashboard.json b/charts/incubator/spegel/dashboard.json new file mode 100644 index 00000000000..b0ea4cd529f --- /dev/null +++ b/charts/incubator/spegel/dashboard.json @@ -0,0 +1,1280 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "Prometheus", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + } + ], + "__elements": {}, + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "9.3.6" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "stat", + "name": "Stat", + "version": "" + }, + { + "type": "panel", + "id": "table", + "name": "Table", + "version": "" + }, + { + "type": "panel", + "id": "text", + "name": "Text", + "version": "" + }, + { + "type": "panel", + "id": "timeseries", + "name": "Time series", + "version": "" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": null, + "links": [], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 24, + "panels": [], + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 0, + "y": 1 + }, + "id": 11, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.3.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "count(spegel_advertised_keys{instance=~\"$instance\"})", + "hide": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Registry", + "transparent": true, + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 3, + "y": 1 + }, + "id": 29, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.3.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "sum(kubelet_node_name{job=\"kubelet\"})", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Running Nodes", + "transparent": true, + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 6, + "y": 1 + }, + "id": 22, + "links": [], + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.3.6", + "targets": [ + { + "datasource": { + "uid": "$datasource" + }, + "editorMode": "code", + "expr": "sum(kubelet_running_containers)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{instance}}", + "range": true, + "refId": "A" + } + ], + "title": "Running Containers", + "transparent": true, + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 9, + "y": 1 + }, + "id": 20, + "options": { + "colorMode": "none", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.3.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "sum(kubelet_running_pods)", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Running Pods", + "transparent": true, + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "green", + "mode": "fixed" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 12, + "y": 1 + }, + "id": 12, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.3.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "max(rate(http_request_duration_seconds_bucket{job=\"spegel\"}[$__interval]))", + "format": "table", + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "A" + } + ], + "title": "Max Request Duration", + "transparent": true, + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 18, + "y": 1 + }, + "id": 2, + "options": { + "code": { + "language": "plaintext", + "showLineNumbers": false, + "showMiniMap": false + }, + "content": "
\n\n\n", + "mode": "html" + }, + "pluginVersion": "9.3.6", + "title": "Github link", + "transparent": true, + "type": "text" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 5 + }, + "id": 9, + "panels": [], + "repeat": "datasource", + "repeatDirection": "h", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "center", + "displayMode": "auto", + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "instance" + }, + "properties": [ + { + "id": "custom.width", + "value": 226 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "prometheus" + }, + "properties": [ + { + "id": "custom.width", + "value": 296 + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 6 + }, + "id": 16, + "options": { + "footer": { + "enablePagination": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "frameIndex": 0, + "showHeader": true, + "sortBy": [] + }, + "pluginVersion": "9.3.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "spegel_advertised_images{job=~\"spegel\",instance=~\"$instance\"}", + "format": "table", + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "spegel_advertised_keys{job=~\"spegel\",instance=~\"$instance\"} ", + "format": "table", + "hide": false, + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "B" + } + ], + "transformations": [ + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "pod", + "Value #A", + "Value #B" + ] + } + } + }, + { + "id": "merge", + "options": {} + }, + { + "id": "renameByRegex", + "options": { + "regex": "Value #A", + "renamePattern": "Container cache" + } + }, + { + "id": "renameByRegex", + "options": { + "regex": "Value #B", + "renamePattern": "Layers cache" + } + } + ], + "transparent": true, + "type": "table" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "series", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 2, + "pointSize": 1, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 6 + }, + "id": 6, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "9.3.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "spegel_advertised_images{job=~\"spegel\",instance=~\"$instance\"}", + "format": "time_series", + "instant": false, + "legendFormat": "{{ instance }}", + "range": true, + "refId": "A" + } + ], + "title": "Container Images Advertised ", + "transparent": true, + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "series", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 36, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "requests" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F2495C", + "mode": "fixed" + } + }, + { + "id": "custom.fillOpacity", + "value": 0 + }, + { + "id": "custom.lineWidth", + "value": 2 + }, + { + "id": "custom.stacking", + "value": { + "group": false, + "mode": "normal" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "limits" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FF9830", + "mode": "fixed" + } + }, + { + "id": "custom.fillOpacity", + "value": 0 + }, + { + "id": "custom.lineWidth", + "value": 2 + }, + { + "id": "custom.stacking", + "value": { + "group": false, + "mode": "normal" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 13 + }, + "id": 28, + "interval": "1m", + "links": [], + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.3.6", + "targets": [ + { + "datasource": { + "uid": "$datasource" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(node_namespace_pod_container:container_cpu_usage_seconds_total:sum_irate{container=\"$container\"}) by (pod)", + "format": "time_series", + "instant": false, + "intervalFactor": 2, + "legendFormat": "{{ container }}", + "range": true, + "refId": "A", + "step": 10 + } + ], + "title": "CPU Usage", + "transparent": true, + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "series", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "smooth", + "lineWidth": 2, + "pointSize": 1, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 13 + }, + "id": 7, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "9.3.6", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "spegel_advertised_keys{job=~\"spegel\",instance=~\"$instance\"} ", + "format": "time_series", + "instant": false, + "legendFormat": "{{ instance }}", + "range": true, + "refId": "A" + } + ], + "title": "Images Layer Advertised ", + "transparent": true, + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 20 + }, + "id": 35, + "panels": [], + "title": "Kubelet", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 6, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ops" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 21 + }, + "id": 31, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "sum(rate(kubelet_runtime_operations_total{job=\"kubelet\", metrics_path=\"/metrics\", operation_type=~\"list_images|pull_image|start_container|list_images|list_containers|version|exec_sync|create_container\"}[$__rate_interval])) by (operation_type)", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Kubelet Operation Rate", + "transparent": true, + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "$datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ops" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 21 + }, + "id": 33, + "links": [], + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.3.6", + "targets": [ + { + "datasource": { + "uid": "$datasource" + }, + "editorMode": "code", + "expr": "sum(rate(kubelet_runtime_operations_errors_total{job=\"kubelet\", metrics_path=\"/metrics\",operation_type=~\"list_images|pull_image|start_container|list_images|list_containers|version|exec_sync|create_container\"}[$__rate_interval])) by (operation_type)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{instance}} {{operation_type}}", + "range": true, + "refId": "A" + } + ], + "title": "Kubelet Operation Error Rate", + "transparent": true, + "type": "timeseries" + } + ], + "refresh": "30s", + "schemaVersion": 37, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "includeAll": false, + "label": "Data Source", + "multi": false, + "name": "datasource", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": { + "selected": false, + "text": "registry", + "value": "registry" + }, + "description": "", + "hide": 2, + "includeAll": false, + "label": "container", + "multi": false, + "name": "container", + "options": [ + { + "selected": true, + "text": "registry", + "value": "registry" + } + ], + "query": "registry", + "queryValue": "", + "skipUrlSync": false, + "type": "custom" + }, + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "definition": "label_values(spegel_advertised_images,pod)", + "description": "", + "hide": 2, + "includeAll": false, + "label": "pod", + "multi": false, + "name": "pod", + "options": [], + "query": { + "query": "label_values(spegel_advertised_images,pod)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "definition": "label_values(spegel_advertised_keys,instance) ", + "hide": 0, + "includeAll": true, + "label": "instance", + "multi": true, + "name": "instance", + "options": [], + "query": { + "query": "label_values(spegel_advertised_keys,instance) ", + "refId": "StandardVariableQuery" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + } + ] + }, + "time": { + "from": "now-3h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Spegel stateless cluster local OCI registry mirror", + "uid": "1iY4QMJVk-psee", + "version": 1, + "weekStart": "", + "gnetId": 18089, + "description": "Spegel is a pull only OCI registry which runs locally on every Node in the Kubernetes cluster. Containerd is configured to use the local registry as a mirror, which would serve the image from within the cluster or from the source registry." + } diff --git a/charts/incubator/spegel/icon.webp b/charts/incubator/spegel/icon.webp new file mode 100644 index 00000000000..c876cb18cc1 Binary files /dev/null and b/charts/incubator/spegel/icon.webp differ diff --git a/charts/incubator/spegel/templates/NOTES.txt b/charts/incubator/spegel/templates/NOTES.txt new file mode 100644 index 00000000000..efcb74cb772 --- /dev/null +++ b/charts/incubator/spegel/templates/NOTES.txt @@ -0,0 +1 @@ +{{- include "tc.v1.common.lib.chart.notes" $ -}} diff --git a/charts/incubator/spegel/templates/_args.tpl b/charts/incubator/spegel/templates/_args.tpl new file mode 100644 index 00000000000..270403b447c --- /dev/null +++ b/charts/incubator/spegel/templates/_args.tpl @@ -0,0 +1,54 @@ +{{/* Define the args */}} +{{- define "spegel.args.init" -}} + args: + - configuration + - --log-level={{ .Values.spegel.logLevel }} + - --containerd-registry-config-path={{ .Values.spegel.containerdRegistryConfigPath }} + {{- with .Values.spegel.registries }} + - --registries + {{- range . }} + - {{ . | quote }} + {{- end }} + {{- end }} + - --mirror-registries + - http://$(NODE_IP):{{ .Values.service.main.ports.main.hostPort }} + - http://$(NODE_IP):{{ .Values.service.main.ports.main.nodePort }} + - http://$(NODE_IP):{{ .Values.service.main.ports.main.port }} + {{- with .Values.spegel.additionalMirrorRegistries }} + {{- range . }} + - {{ . | quote }} + {{- end }} + {{- end }} + - --resolve-tags={{ .Values.spegel.resolveTags }} + - --append-mirrors={{ .Values.spegel.appendMirrors }} +{{- end -}} +{{- define "spegel.args.main" -}} + args: + - registry + - --log-level={{ .Values.spegel.logLevel }} + - --mirror-resolve-retries={{ .Values.spegel.mirrorResolveRetries }} + - --mirror-resolve-timeout={{ .Values.spegel.mirrorResolveTimeout }} + - --registry-addr=:{{ .Values.service.main.ports.main.port }} + - --router-addr=:{{ .Values.service.router.ports.router.port }} + - --metrics-addr=:{{ .Values.service.metrics.ports.metrics.port}} + {{- with .Values.spegel.registries }} + - --registries + {{- range . }} + - {{ . | quote }} + {{- end }} + {{- end }} + - --containerd-sock={{ .Values.spegel.containerdSock }} + - --containerd-namespace={{ .Values.spegel.containerdNamespace }} + - --containerd-registry-config-path={{ .Values.spegel.containerdRegistryConfigPath }} + - --bootstrap-kind=kubernetes + {{- with .Values.spegel.kubeconfigPath }} + - --kubeconfig-path={{ . }} + {{- end }} + - '--leader-election-namespace={{ include "tc.v1.common.lib.metadata.namespace" (dict "rootCtx" $ "objectData" $.Values.workload.main.podSpec.containers.main "caller" "Deployment") }}' + - --leader-election-name={{ .Release.Name }}-leader-election + - --resolve-latest-tag={{ .Values.spegel.resolveLatestTag }} + - --local-addr=$(NODE_IP):{{ .Values.service.main.ports.main.hostPort }} + {{- with .Values.spegel.containerdContentPath }} + - --containerd-content-path={{ . }} + {{- end }} +{{- end -}} diff --git a/charts/incubator/spegel/templates/common.yaml b/charts/incubator/spegel/templates/common.yaml new file mode 100644 index 00000000000..1f966938937 --- /dev/null +++ b/charts/incubator/spegel/templates/common.yaml @@ -0,0 +1,13 @@ +{{/* Make sure all variables are set properly */}} +{{- include "tc.v1.common.loader.init" . }} +{{- $newArgsInit := (include "spegel.args.init" . | fromYaml) }} +{{- $_ := set .Values "newArgsInit" $newArgsInit -}} +{{- $mergedargsInit := concat $.Values.workload.main.podSpec.initContainers.configuration.args .Values.newArgsInit.args }} +{{- $_ := set $.Values.workload.main.podSpec.initContainers.configuration "args" $mergedargsInit -}} + +{{- $newArgs := (include "spegel.args.main" . | fromYaml) }} +{{- $_ := set .Values "newArgs" $newArgs -}} +{{- $mergedargs := concat $.Values.workload.main.podSpec.containers.main.args .Values.newArgs.args }} +{{- $_ := set $.Values.workload.main.podSpec.containers.main "args" $mergedargs -}} + +{{- include "tc.v1.common.loader.apply" . }} diff --git a/charts/incubator/spegel/values.yaml b/charts/incubator/spegel/values.yaml new file mode 100644 index 00000000000..29d94dcf294 --- /dev/null +++ b/charts/incubator/spegel/values.yaml @@ -0,0 +1,175 @@ +image: + repository: ghcr.io/spegel-org/spegel + pullPolicy: IfNotPresent + tag: v0.0.27 + +securityContext: + container: + runAsUser: 0 + runAsGroup: 0 + readOnlyRootFilesystem: false + pod: + fsGroup: 0 + +service: + main: + ports: + main: + port: 5000 + targetPort: 5000 + hostPort: 30020 + nodePort: 30021 + router: + enabled: true + ports: + router: + enabled: true + port: 5001 + targetPort: 5001 + metrics: + enabled: true + ports: + metrics: + enabled: true + port: 9090 + targetPort: 9090 + +workload: + main: + podSpec: + type: DaemonSet + initContainers: + configuration: + enabled: true + type: init + args: [] + env: + NODE_IP: + fieldRef: + fieldPath: status.hostIP + containers: + main: + args: [] + env: + NODE_IP: + fieldRef: + fieldPath: status.hostIP + probes: + liveness: + path: /healthz + readiness: + path: /healthz + startup: + path: /healthz + +configmap: + dashboard: + enabled: true + labels: + grafana_dashboard: "1" + data: + traefik.json: >- + {{ .Files.Get "dashboard.json" | indent 8 }} + +podOptions: + automountServiceAccountToken: true + priorityClassName: "system-node-critical" + nodeSelector: + kubernetes.io/arch: "" + tolerations: + - key: CriticalAddonsOnly + operator: Exists + - effect: NoExecute + operator: Exists + - effect: NoSchedule + operator: Exists + +metrics: + main: + enabled: true + type: servicemonitor + endpoints: + - port: metrics + targetSelector: metrics + +portal: + open: + enabled: false + +persistence: + containerd-sock: + enabled: true + type: hostPath + mountPath: "{{ .Values.spegel.containerdSock }}" + hostPath: "{{ .Values.spegel.containerdSock }}" + hostPathType: Socket + containerd-content: + enabled: "{{ if .Values.spegel.containerdContentPath }}true{{else}}false{{end}}}}" + type: hostPath + mountPath: "{{ .Values.spegel.containerdContentPath }}" + hostPath: "{{ .Values.spegel.containerdContentPath }}" + hostPathType: Directory + readOnly: true + containerd-config: + enabled: "{{ if .Values.spegel.containerdMirrorAdd }}true{{else}}false{{end}}}}" + type: hostPath + mountPath: "{{ .Values.spegel.containerdRegistryConfigPath }}" + hostPath: "{{ .Values.spegel.containerdRegistryConfigPath }}" + hostPathType: DirectoryOrCreate + +spegel: + # -- Minimum log level to output. Value should be DEBUG, INFO, WARN, or ERROR. + logLevel: "INFO" + # -- Registries for which mirror configuration will be created. + registries: + - https://cgr.dev + - https://docker.io + - https://ghcr.io + - https://quay.io + - https://mcr.microsoft.com + - https://public.ecr.aws + - https://gcr.io + - https://registry.k8s.io + - https://k8s.gcr.io + - https://tccr.io + - https://factory.talos.dev + # -- Additional target mirror registries other than Spegel. + additionalMirrorRegistries: [] + # -- Max ammount of mirrors to attempt. + mirrorResolveRetries: 3 + # -- Max duration spent finding a mirror. + mirrorResolveTimeout: "20ms" + # -- Path to Containerd socket. + containerdSock: "/run/containerd/containerd.sock" + # -- Containerd namespace where images are stored. + containerdNamespace: "k8s.io" + # -- Path to Containerd mirror configuration. + containerdRegistryConfigPath: "/etc/cri/conf.d/hosts" + # -- Path to Containerd content store.. + containerdContentPath: "/var/lib/containerd/io.containerd.content.v1.content" + # -- If true Spegel will add mirror configuration to the node. + containerdMirrorAdd: true + # -- Path to Kubeconfig credentials, should only be set if Spegel is run in an environment without RBAC. + kubeconfigPath: "" + # -- When true Spegel will resolve tags to digests. + resolveTags: true + # -- When true latest tags will be resolved to digests. + resolveLatestTag: true + # -- When true existing mirror configuration will be appended to instead of replaced. + appendMirrors: false + +# -- Whether Role Based Access Control objects like roles and rolebindings should be created +rbac: + main: + enabled: true + primary: true + clusterWide: true + rules: + - apiGroups: ["coordination.k8s.io"] + resources: ["leases"] + verbs: ["get", "list", "watch", "create", "update"] +# -- The service account the pods will use to interact with the Kubernetes API +serviceAccount: + main: + enabled: true + primary: true diff --git a/clustertool/embed/generic/base/clusterenv.yaml b/clustertool/embed/generic/base/clusterenv.yaml index f48b615ae06..128c2c6a585 100644 --- a/clustertool/embed/generic/base/clusterenv.yaml +++ b/clustertool/embed/generic/base/clusterenv.yaml @@ -7,8 +7,10 @@ MASTER1IP: 192.168.20.210 GATEWAY: 192.168.20.1 # Defines the ip range metallb is allowed to use METALLB_RANGE: 192.168.20.211-192.168.20.219 +# Sets the IP on which Spegel using loadbalancer is made available +SPEGEL_IP: 192.168.20.211 # Sets the Kubernetes Dashboard IP. Has to be within METALLB_RANGE and not in use -DASHBOARD_IP: 192.168.20.211 +DASHBOARD_IP: 192.168.20.212 # Used to automatically generate a sshkey-pair for FluxCD # Has to start with ssh:// GITHUB_REPOSITORY: "" diff --git a/clustertool/embed/generic/kubernetes/system/spegel/app/helm-release.yaml b/clustertool/embed/generic/kubernetes/system/spegel/app/helm-release.yaml index b3799acdc6b..0dec4f5d0f6 100644 --- a/clustertool/embed/generic/kubernetes/system/spegel/app/helm-release.yaml +++ b/clustertool/embed/generic/kubernetes/system/spegel/app/helm-release.yaml @@ -10,10 +10,10 @@ spec: chart: spec: chart: spegel - version: v0.0.27 + version: 2.0.0 sourceRef: kind: HelmRepository - name: spegel + name: truecharts namespace: flux-system install: remediation: @@ -24,26 +24,7 @@ spec: strategy: rollback retries: 3 values: - grafanaDashboard: - enabled: true - serviceMonitor: - enabled: false - spegel: - containerdSock: /run/containerd/containerd.sock - containerdRegistryConfigPath: /etc/cri/conf.d/hosts - appendMirrors: true - registries: - - https://tccr.io - - https://cgr.dev - - https://docker.io - - https://ghcr.io - - https://quay.io - - https://mcr.microsoft.com - - https://public.ecr.aws - - https://gcr.io - - https://registry.k8s.io - - https://k8s.gcr.io - - https://lscr.io service: - registry: - hostPort: 29999 + main: + type: LoadBalancer + loadBalancerIP: ${SPEGEL_IP} diff --git a/clustertool/pkg/initfiles/clusterenv.go b/clustertool/pkg/initfiles/clusterenv.go index 97f21123afd..95d8d382b72 100644 --- a/clustertool/pkg/initfiles/clusterenv.go +++ b/clustertool/pkg/initfiles/clusterenv.go @@ -28,7 +28,7 @@ func LoadTalEnv() error { clusterName() PostProcessTalEnv() clusterEnvtoEnv() - log.Info().Msgf("ClusterEnv loaded successfully\n", ) + log.Info().Msgf("ClusterEnv loaded successfully\n") return nil } diff --git a/clustertool/pkg/initfiles/initfiles.go b/clustertool/pkg/initfiles/initfiles.go index 364b386c56e..c4081194274 100644 --- a/clustertool/pkg/initfiles/initfiles.go +++ b/clustertool/pkg/initfiles/initfiles.go @@ -274,49 +274,9 @@ func GenPatches() error { log.Fatal().Err(err).Msg("Error: %s") } - // Assuming this is part of your function - if helper.TalEnv["DOCKERHUB_USER"] != "" && helper.TalEnv["DOCKERHUB_PASSWORD"] != "" { - // Prepare the content to append - configContent := fmt.Sprintf(`# Add Dockerhub Login -- operation: replace - path: /machine/registries/config/registry-1.docker.io - value: - auth: - username: %s - password: %s -- operation: replace - path: /machine/registries/config/docker.io - value: - auth: - username: %s - password: %s -`, helper.TalEnv["DOCKERHUB_USER"], helper.TalEnv["DOCKERHUB_PASSWORD"], helper.TalEnv["DOCKERHUB_USER"], helper.TalEnv["DOCKERHUB_PASSWORD"]) + setDocker() - // Open the file in append mode or create it if it doesn't exist - file, err := os.OpenFile(filepath.Join(helper.ClusterPath+"/talos/patches", "all.yaml"), os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) - if err != nil { - log.Fatal().Err(err).Msg("Error opening file: %s") - } - defer file.Close() - - // Write the content to the file - if _, err := file.Write([]byte(configContent)); err != nil { - log.Fatal().Err(err).Msg("Error writing to file: %s") - } - } else { - // Optional: Append a note if the environment variables are not set - emptyContent := `# No DockerHub credentials provided -` - file, err := os.OpenFile(filepath.Join(helper.ClusterPath+"/talos/patches", "all.yaml"), os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) - if err != nil { - log.Fatal().Err(err).Msg("Error opening file: %s") - } - defer file.Close() - - if _, err := file.Write([]byte(emptyContent)); err != nil { - log.Fatal().Err(err).Msg("Error writing to file: %s") - } - } + setSpegel() // Read the content of the talenv.yaml file talenvContent, err := os.ReadFile(helper.ClusterPath + "/clusterenv.yaml") @@ -344,6 +304,123 @@ func GenPatches() error { return nil } +func setDocker() { + // Assuming this is part of your function + if helper.TalEnv["DOCKERHUB_USER"] != "" && helper.TalEnv["DOCKERHUB_PASSWORD"] != "" { + // Prepare the content to append + configContent := fmt.Sprintf(`# Add Dockerhub Login + - operation: replace + path: /machine/registries/config/registry-1.docker.io + value: + auth: + username: %s + password: %s + - operation: replace + path: /machine/registries/config/docker.io + value: + auth: + username: %s + password: %s + `, helper.TalEnv["DOCKERHUB_USER"], helper.TalEnv["DOCKERHUB_PASSWORD"], helper.TalEnv["DOCKERHUB_USER"], helper.TalEnv["DOCKERHUB_PASSWORD"]) + + // Open the file in append mode or create it if it doesn't exist + file, err := os.OpenFile(filepath.Join(helper.ClusterPath+"/talos/patches", "all.yaml"), os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) + if err != nil { + log.Fatal().Err(err).Msg("Error opening file: %s") + } + defer file.Close() + + // Write the content to the file + if _, err := file.Write([]byte(configContent)); err != nil { + log.Fatal().Err(err).Msg("Error writing to file: %s") + } + } else { + // Optional: Append a note if the environment variables are not set + emptyContent := `# No DockerHub credentials provided + ` + file, err := os.OpenFile(filepath.Join(helper.ClusterPath+"/talos/patches", "all.yaml"), os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) + if err != nil { + log.Fatal().Err(err).Msg("Error opening file: %s") + } + defer file.Close() + + if _, err := file.Write([]byte(emptyContent)); err != nil { + log.Fatal().Err(err).Msg("Error writing to file: %s") + } + } +} + +func setSpegel() { + // Assuming this is part of your function + if helper.TalEnv["SPEGEL_IP"] != "" && helper.TalEnv["SPEGEL_IP"] != "" { + // Prepare the content to append + configContent := fmt.Sprintf(`# Add Dockerhub Login +- operation: replace + path: /machine/registries/mirrors/ + value: + cgr.dev: + endpoints: + - http://%s:5000 + docker.io: + endpoints: + - http://%s:5000 + ghcr.io: + endpoints: + - http://%s:5000 + quay.io: + endpoints: + - http://%s:5000 + mcr.microsoft.com: + endpoints: + - http://%s:5000 + public.ecr.aws: + endpoints: + - http://%s:5000 + gcr.io: + endpoints: + - http://%s:5000 + registry.k8s.io: + endpoints: + - http://%s:5000 + k8s.gcr.io: + endpoints: + - http://%s:5000 + tccr.io: + endpoints: + - http://%s:5000 + factory.talos.dev: + endpoints: + - http://%s:5000 + +`, helper.TalEnv["SPEGEL_IP"], helper.TalEnv["SPEGEL_IP"], helper.TalEnv["SPEGEL_IP"], helper.TalEnv["SPEGEL_IP"], helper.TalEnv["SPEGEL_IP"], helper.TalEnv["SPEGEL_IP"], helper.TalEnv["SPEGEL_IP"], helper.TalEnv["SPEGEL_IP"], helper.TalEnv["SPEGEL_IP"], helper.TalEnv["SPEGEL_IP"], helper.TalEnv["SPEGEL_IP"]) + + // Open the file in append mode or create it if it doesn't exist + file, err := os.OpenFile(filepath.Join(helper.ClusterPath+"/talos/patches", "all.yaml"), os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) + if err != nil { + log.Fatal().Err(err).Msg("Error opening file: %s") + } + defer file.Close() + + // Write the content to the file + if _, err := file.Write([]byte(configContent)); err != nil { + log.Fatal().Err(err).Msg("Error writing to file: %s") + } + } else { + // Optional: Append a note if the environment variables are not set + emptyContent := `# No Spegel_IP provided +` + file, err := os.OpenFile(filepath.Join(helper.ClusterPath+"/talos/patches", "all.yaml"), os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) + if err != nil { + log.Fatal().Err(err).Msg("Error opening file: %s") + } + defer file.Close() + + if _, err := file.Write([]byte(emptyContent)); err != nil { + log.Fatal().Err(err).Msg("Error writing to file: %s") + } + } +} + func ageGen() error { outFlag := "age.agekey"