mirror of
https://github.com/malarinv/iperf3-monitor.git
synced 2026-03-08 05:22:35 +00:00
Compare commits
10 Commits
109d8a0fab
...
exporter-e
| Author | SHA1 | Date | |
|---|---|---|---|
| 77daeee1ca | |||
| e54a02ad8c | |||
| 0a3249f30b | |||
| 1eeb4b20df | |||
| 0c490e95d2 | |||
| 81b771d1ee | |||
| 3e21f978ee | |||
| 458b786ff4 | |||
| 96be13a23c | |||
| 8d51afc24e |
28
.github/workflows/ci.yaml
vendored
28
.github/workflows/ci.yaml
vendored
@@ -27,23 +27,49 @@ jobs:
|
||||
build:
|
||||
name: Build Docker Image
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read # Needed to checkout the repository
|
||||
packages: write # Needed to push Docker images to GHCR
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
|
||||
- name: Extract metadata (tags, labels) for Docker
|
||||
id: meta
|
||||
uses: docker/metadata-action@v4
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
tags: |
|
||||
# Tag with the PR number if it's a pull request event
|
||||
type=match,pattern=pull_request,value=pr-{{number}}
|
||||
# Tag with the git SHA
|
||||
type=sha,prefix=
|
||||
# Tag with 'latest' if on the main branch (though this workflow only runs on PRs to main)
|
||||
type=ref,event=branch,pattern=main,value=latest
|
||||
|
||||
- name: Log in to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build Docker image
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
context: ./exporter
|
||||
push: false # Do not push on PRs
|
||||
# Push the image if the event is a pull request.
|
||||
# The workflow currently only triggers on pull_request events.
|
||||
push: ${{ github.event_name == 'pull_request' }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
platforms: linux/amd64,linux/arm64
|
||||
|
||||
test:
|
||||
name: Run Tests
|
||||
|
||||
7
.github/workflows/release.yml
vendored
7
.github/workflows/release.yml
vendored
@@ -36,6 +36,12 @@ jobs:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
|
||||
- name: Log in to GitHub Container Registry
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
@@ -56,6 +62,7 @@ jobs:
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
platforms: linux/amd64,linux/arm64
|
||||
|
||||
package-and-publish-chart:
|
||||
name: Package and Publish Helm Chart
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -36,4 +36,4 @@ Thumbs.db
|
||||
|
||||
# Helm
|
||||
!charts/iperf3-monitor/.helmignore
|
||||
charts/*.tgz # Ignore packaged chart files
|
||||
charts/iperf3-monitor/charts/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,5 +2,8 @@ dependencies:
|
||||
- name: kube-prometheus-stack
|
||||
repository: https://prometheus-community.github.io/helm-charts
|
||||
version: 75.3.6
|
||||
digest: sha256:d15acd48bfc0b842654ae025e1bd1969e636a66508020312d555db84f381c379
|
||||
generated: "2025-06-19T20:40:53.415529365Z"
|
||||
- name: prometheus-operator
|
||||
repository: oci://tccr.io/truecharts
|
||||
version: 11.5.1
|
||||
digest: sha256:3000e63445f8ba8df601cb483f4f77d14c5c4662bff2d16ffcf5cf1f7def314b
|
||||
generated: "2025-06-20T17:25:44.538372209+05:30"
|
||||
|
||||
@@ -27,4 +27,8 @@ dependencies:
|
||||
- name: kube-prometheus-stack # Example dependency if you package the whole stack
|
||||
version: ">=30.0.0" # Specify a compatible version range
|
||||
repository: https://prometheus-community.github.io/helm-charts
|
||||
condition: serviceMonitor.enabled # Only include if ServiceMonitor is enabled (assuming Prometheus Operator)
|
||||
condition: "dependencies.install, serviceMonitor.enabled, !dependencies.useTrueChartsPrometheusOperator"
|
||||
- name: prometheus-operator
|
||||
version: ">=8.11.1"
|
||||
repository: "oci://tccr.io/truecharts"
|
||||
condition: "dependencies.install, serviceMonitor.enabled, dependencies.useTrueChartsPrometheusOperator"
|
||||
|
||||
Binary file not shown.
@@ -47,9 +47,9 @@ app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
Create the name of the service account to use
|
||||
*/}}
|
||||
{{- define "iperf3-monitor.serviceAccountName" -}}
|
||||
{{- if .Values.serviceAccount.create -}}
|
||||
{{- if .Values.rbac.create -}}
|
||||
{{- default (include "iperf3-monitor.fullname" .) .Values.serviceAccount.name -}}
|
||||
{{- else -}}
|
||||
{{- default "default" .Values.serviceAccount.name -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
@@ -20,7 +20,7 @@ spec:
|
||||
serviceAccountName: {{ include "iperf3-monitor.serviceAccountName" . }}
|
||||
containers:
|
||||
- name: iperf3-exporter
|
||||
image: "{{ .Values.exporter.image.repository }}:{{ .Values.exporter.image.tag | default .Chart.AppVersion }}"
|
||||
image: "{{ .Values.exporter.image.repository }}:{{ .Values.exporter.image.tag | default (printf "v%s" .Chart.AppVersion) }}"
|
||||
imagePullPolicy: {{ .Values.exporter.image.pullPolicy }}
|
||||
ports:
|
||||
- containerPort: {{ .Values.service.targetPort }}
|
||||
@@ -34,6 +34,8 @@ spec:
|
||||
value: "{{ .Values.exporter.testInterval }}"
|
||||
- name: IPERF_TEST_PROTOCOL
|
||||
value: "{{ .Values.exporter.testProtocol }}"
|
||||
- name: LOG_LEVEL
|
||||
value: "{{ .Values.exporter.logLevel }}"
|
||||
- name: IPERF_SERVER_PORT
|
||||
value: "5201" # Hardcoded as per server DaemonSet
|
||||
- name: IPERF_SERVER_NAMESPACE
|
||||
|
||||
@@ -24,6 +24,9 @@ exporter:
|
||||
# -- Interval in seconds between complete test cycles (i.e., testing all server nodes).
|
||||
testInterval: 300
|
||||
|
||||
# -- Log level for the iperf3 exporter (e.g., DEBUG, INFO, WARNING, ERROR, CRITICAL).
|
||||
logLevel: INFO
|
||||
|
||||
# -- Timeout in seconds for a single iperf3 test run.
|
||||
testTimeout: 10
|
||||
|
||||
@@ -85,7 +88,7 @@ rbac:
|
||||
serviceAccount:
|
||||
# -- The name of the ServiceAccount to use for the exporter pod.
|
||||
# Only used if rbac.create is false. If not set, it defaults to the chart's fullname.
|
||||
name: ""
|
||||
name: "iperf3-monitor"
|
||||
|
||||
serviceMonitor:
|
||||
# -- If true, create a ServiceMonitor resource for integration with Prometheus Operator.
|
||||
@@ -118,3 +121,19 @@ networkPolicy:
|
||||
namespaceSelector: {}
|
||||
# -- Specify pod selectors if needed.
|
||||
podSelector: {}
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Dependency Configuration
|
||||
# -----------------------------------------------------------------------------
|
||||
dependencies:
|
||||
# -- Set to true to install Prometheus operator dependency if serviceMonitor.enabled is also true.
|
||||
# -- Set to false to disable the installation of Prometheus operator dependency,
|
||||
# -- regardless of serviceMonitor.enabled. This is useful if you have Prometheus
|
||||
# -- Operator installed and managed separately in your cluster.
|
||||
install: true
|
||||
|
||||
# -- Set to true to use the TrueCharts Prometheus Operator instead of kube-prometheus-stack.
|
||||
# This chart's ServiceMonitor resources require a Prometheus Operator to be functional.
|
||||
# If serviceMonitor.enabled is true and dependencies.install is true,
|
||||
# one of these two dependencies will be pulled based on this flag.
|
||||
useTrueChartsPrometheusOperator: false
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
# Stage 1: Build stage with dependencies
|
||||
FROM python:3.9-slim as builder
|
||||
|
||||
# Declare TARGETARCH for use in this stage
|
||||
ARG TARGETARCH
|
||||
WORKDIR /app
|
||||
|
||||
# Install iperf3 and build dependencies
|
||||
# Minimal dependencies for builder stage if any Python packages had C extensions.
|
||||
# Assuming requirements.txt does not need gcc or other build tools for now.
|
||||
# If pip install fails later, add necessary build tools (e.g., gcc, python3-dev) here.
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends gcc iperf3 libiperf-dev && \
|
||||
# apt-get install -y --no-install-recommends gcc python3-dev # Example if needed
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install Python dependencies
|
||||
@@ -17,9 +21,11 @@ FROM python:3.9-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy iperf3 binary and library from the builder stage
|
||||
COPY --from=builder /usr/bin/iperf3 /usr/bin/iperf3
|
||||
COPY --from=builder /usr/lib/x86_64-linux-gnu/libiperf.so.0 /usr/lib/x86_64-linux-gnu/libiperf.so.0
|
||||
# Install iperf3 and its runtime dependency libsctp1 directly in the final stage.
|
||||
# This simplifies the Dockerfile by removing the need to copy iperf3 components from the builder.
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends iperf3 libsctp1 && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Copy installed Python packages from the builder stage
|
||||
COPY --from=builder /usr/local/lib/python3.9/site-packages /usr/local/lib/python3.9/site-packages
|
||||
@@ -31,4 +37,4 @@ COPY exporter.py .
|
||||
EXPOSE 9876
|
||||
|
||||
# Set the entrypoint
|
||||
CMD ["python", "exporter.py"]
|
||||
CMD ["python", "exporter.py"]
|
||||
|
||||
@@ -1,28 +1,60 @@
|
||||
"""
|
||||
Prometheus exporter for iperf3 network performance monitoring.
|
||||
|
||||
This script runs iperf3 tests between the node it's running on (source) and
|
||||
other iperf3 server pods discovered in a Kubernetes cluster. It then exposes
|
||||
these metrics for Prometheus consumption.
|
||||
|
||||
Configuration is primarily through environment variables and command-line arguments
|
||||
for log level.
|
||||
"""
|
||||
import os
|
||||
import time
|
||||
import logging
|
||||
import argparse
|
||||
import sys
|
||||
from kubernetes import client, config
|
||||
from prometheus_client import start_http_server, Gauge
|
||||
import iperf3
|
||||
|
||||
# --- Configuration ---
|
||||
# Configure logging
|
||||
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
||||
# --- Global Configuration & Setup ---
|
||||
|
||||
# Argument parsing for log level configuration
|
||||
# The command-line --log-level argument takes precedence over the LOG_LEVEL env var.
|
||||
# Defaults to INFO if neither is set.
|
||||
parser = argparse.ArgumentParser(description="iperf3 Prometheus exporter.")
|
||||
parser.add_argument(
|
||||
'--log-level',
|
||||
default=os.environ.get('LOG_LEVEL', 'INFO').upper(),
|
||||
choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'],
|
||||
help='Set the logging level. Overrides LOG_LEVEL environment variable. (Default: INFO)'
|
||||
)
|
||||
args = parser.parse_args()
|
||||
log_level_str = args.log_level
|
||||
|
||||
# Convert log level string (e.g., 'INFO') to its numeric representation (e.g., logging.INFO)
|
||||
numeric_level = getattr(logging, log_level_str.upper(), None)
|
||||
if not isinstance(numeric_level, int):
|
||||
# This case should ideally not be reached if choices in argparse are respected.
|
||||
logging.error(f"Invalid log level: {log_level_str}. Defaulting to INFO.")
|
||||
numeric_level = logging.INFO
|
||||
logging.basicConfig(level=numeric_level, format='%(asctime)s - %(levelname)s - %(message)s')
|
||||
|
||||
# --- Prometheus Metrics Definition ---
|
||||
# These gauges will be used to expose iperf3 test results.
|
||||
IPERF_BANDWIDTH_MBPS = Gauge(
|
||||
'iperf_network_bandwidth_mbps',
|
||||
'Network bandwidth measured by iperf3 in Megabits per second',
|
||||
'Network bandwidth measured by iperf3 in Megabits per second (Mbps)',
|
||||
['source_node', 'destination_node', 'protocol']
|
||||
)
|
||||
IPERF_JITTER_MS = Gauge(
|
||||
'iperf_network_jitter_ms',
|
||||
'Network jitter measured by iperf3 in milliseconds',
|
||||
'Network jitter measured by iperf3 in milliseconds (ms) for UDP tests',
|
||||
['source_node', 'destination_node', 'protocol']
|
||||
)
|
||||
IPERF_PACKETS_TOTAL = Gauge(
|
||||
'iperf_network_packets_total',
|
||||
'Total packets transmitted or received during the iperf3 test',
|
||||
'Total packets transmitted/received during the iperf3 UDP test',
|
||||
['source_node', 'destination_node', 'protocol']
|
||||
)
|
||||
IPERF_LOST_PACKETS = Gauge(
|
||||
@@ -38,12 +70,21 @@ IPERF_TEST_SUCCESS = Gauge(
|
||||
|
||||
def discover_iperf_servers():
|
||||
"""
|
||||
Discover iperf3 server pods in the cluster using the Kubernetes API.
|
||||
Discovers iperf3 server pods within a Kubernetes cluster.
|
||||
|
||||
It uses the in-cluster Kubernetes configuration to connect to the API.
|
||||
The target namespace and label selector for iperf3 server pods are configured
|
||||
via environment variables:
|
||||
- IPERF_SERVER_NAMESPACE (default: 'default')
|
||||
- IPERF_SERVER_LABEL_SELECTOR (default: 'app=iperf3-server')
|
||||
|
||||
Returns:
|
||||
list: A list of dictionaries, where each dictionary contains the 'ip'
|
||||
and 'node_name' of a discovered iperf3 server pod. Returns an
|
||||
empty list if discovery fails or no servers are found.
|
||||
"""
|
||||
try:
|
||||
# Load in-cluster configuration
|
||||
# Assumes the exporter runs in a pod with a service account having permissions
|
||||
config.load_incluster_config()
|
||||
config.load_incluster_config() # Assumes running inside a Kubernetes pod
|
||||
v1 = client.CoreV1Api()
|
||||
|
||||
namespace = os.getenv('IPERF_SERVER_NAMESPACE', 'default')
|
||||
@@ -51,110 +92,206 @@ def discover_iperf_servers():
|
||||
|
||||
logging.info(f"Discovering iperf3 servers with label '{label_selector}' in namespace '{namespace}'")
|
||||
|
||||
# List pods across all namespaces with the specified label selector
|
||||
# Note: list_pod_for_all_namespaces requires cluster-wide permissions
|
||||
ret = v1.list_pod_for_all_namespaces(label_selector=label_selector, watch=False)
|
||||
|
||||
servers = []
|
||||
for i in ret.items:
|
||||
# Ensure pod has an IP and is running
|
||||
if i.status.pod_ip and i.status.phase == 'Running':
|
||||
for item in ret.items:
|
||||
if item.status.pod_ip and item.status.phase == 'Running':
|
||||
servers.append({
|
||||
'ip': i.status.pod_ip,
|
||||
'node_name': i.spec.node_name
|
||||
'ip': item.status.pod_ip,
|
||||
'node_name': item.spec.node_name # Node where the iperf server pod is running
|
||||
})
|
||||
logging.info(f"Discovered {len(servers)} iperf3 server pods.")
|
||||
return servers
|
||||
except config.ConfigException as e:
|
||||
logging.error(f"Kubernetes config error: {e}. Is the exporter running in a cluster with RBAC permissions?")
|
||||
return []
|
||||
except Exception as e:
|
||||
logging.error(f"Error discovering iperf servers: {e}")
|
||||
return [] # Return empty list on error to avoid crashing the loop
|
||||
return [] # Return empty list on error to avoid crashing the main loop
|
||||
|
||||
def run_iperf_test(server_ip, server_port, protocol, source_node, dest_node):
|
||||
def run_iperf_test(server_ip, server_port, protocol, source_node_name, dest_node_name):
|
||||
"""
|
||||
Runs a single iperf3 test and updates Prometheus metrics.
|
||||
Runs a single iperf3 test against a specified server and publishes metrics.
|
||||
|
||||
Args:
|
||||
server_ip (str): The IP address of the iperf3 server.
|
||||
server_port (int): The port number of the iperf3 server.
|
||||
protocol (str): The protocol to use ('tcp' or 'udp').
|
||||
source_node_name (str): The name of the source node (where this exporter is running).
|
||||
dest_node_name (str): The name of the destination node (where the server is running).
|
||||
|
||||
The test duration is controlled by the IPERF_TEST_DURATION environment variable
|
||||
(default: 5 seconds).
|
||||
"""
|
||||
logging.info(f"Running iperf3 test from {source_node} to {dest_node} ({server_ip}:{server_port}) using {protocol.upper()}")
|
||||
logging.info(f"Running iperf3 {protocol.upper()} test from {source_node_name} to {dest_node_name} ({server_ip}:{server_port})")
|
||||
|
||||
client = iperf3.Client()
|
||||
client.server_hostname = server_ip
|
||||
client.port = server_port
|
||||
client.protocol = protocol
|
||||
# Duration of the test (seconds)
|
||||
client.duration = int(os.getenv('IPERF_TEST_DURATION', 5))
|
||||
# Output results as JSON for easy parsing
|
||||
client.json_output = True
|
||||
iperf_client = iperf3.Client()
|
||||
iperf_client.server_hostname = server_ip
|
||||
iperf_client.port = server_port
|
||||
iperf_client.protocol = protocol
|
||||
iperf_client.duration = int(os.getenv('IPERF_TEST_DURATION', 5)) # Test duration in seconds
|
||||
iperf_client.json_output = True # Enables easy parsing of results
|
||||
|
||||
result = client.run()
|
||||
|
||||
# Parse results and update metrics
|
||||
parse_and_publish_metrics(result, source_node, dest_node, protocol)
|
||||
|
||||
def parse_and_publish_metrics(result, source_node, dest_node, protocol):
|
||||
"""
|
||||
Parses the iperf3 result and updates Prometheus gauges.
|
||||
Handles both successful and failed tests.
|
||||
"""
|
||||
labels = {'source_node': source_node, 'destination_node': dest_node, 'protocol': protocol}
|
||||
|
||||
if result and result.error:
|
||||
logging.error(f"Test from {source_node} to {dest_node} failed: {result.error}")
|
||||
try:
|
||||
result = iperf_client.run()
|
||||
parse_and_publish_metrics(result, source_node_name, dest_node_name, protocol)
|
||||
except Exception as e:
|
||||
# Catch unexpected errors during client.run() or parsing
|
||||
logging.error(f"Exception during iperf3 test or metric parsing for {dest_node_name}: {e}")
|
||||
labels = {'source_node': source_node_name, 'destination_node': dest_node_name, 'protocol': protocol}
|
||||
IPERF_TEST_SUCCESS.labels(**labels).set(0)
|
||||
# Set metrics to 0 on failure
|
||||
try:
|
||||
IPERF_BANDWIDTH_MBPS.labels(**labels).set(0)
|
||||
IPERF_JITTER_MS.labels(**labels).set(0)
|
||||
IPERF_PACKETS_TOTAL.labels(**labels).set(0)
|
||||
IPERF_LOST_PACKETS.labels(**labels).set(0)
|
||||
except KeyError:
|
||||
# Labels might not be registered yet if this is the first failure
|
||||
pass
|
||||
logging.debug(f"KeyError setting failure metrics for {labels} after client.run() exception.")
|
||||
|
||||
|
||||
def parse_and_publish_metrics(result, source_node, dest_node, protocol):
|
||||
"""
|
||||
Parses the iperf3 test result and updates Prometheus gauges.
|
||||
|
||||
Args:
|
||||
result (iperf3.TestResult): The result object from the iperf3 client.
|
||||
source_node (str): Name of the source node.
|
||||
dest_node (str): Name of the destination node.
|
||||
protocol (str): Protocol used for the test ('tcp' or 'udp').
|
||||
"""
|
||||
labels = {'source_node': source_node, 'destination_node': dest_node, 'protocol': protocol}
|
||||
|
||||
# Handle failed tests (e.g., server unreachable) or missing result object
|
||||
if not result or result.error:
|
||||
error_message = result.error if result and result.error else "No result object from iperf3 client"
|
||||
logging.warning(f"Test from {source_node} to {dest_node} ({protocol.upper()}) failed: {error_message}")
|
||||
IPERF_TEST_SUCCESS.labels(**labels).set(0)
|
||||
# Set all relevant metrics to 0 on failure to clear stale values from previous successes
|
||||
try:
|
||||
IPERF_BANDWIDTH_MBPS.labels(**labels).set(0)
|
||||
IPERF_JITTER_MS.labels(**labels).set(0) # Applicable for UDP, zeroed for TCP later
|
||||
IPERF_PACKETS_TOTAL.labels(**labels).set(0) # Applicable for UDP, zeroed for TCP later
|
||||
IPERF_LOST_PACKETS.labels(**labels).set(0) # Applicable for UDP, zeroed for TCP later
|
||||
except KeyError:
|
||||
# This can happen if labels were never registered due to continuous failures
|
||||
logging.debug(f"KeyError when setting failure metrics for {labels}. Gauges might not be initialized.")
|
||||
return
|
||||
|
||||
if not result:
|
||||
logging.error(f"Test from {source_node} to {dest_node} failed to return a result object.")
|
||||
IPERF_TEST_SUCCESS.labels(**labels).set(0)
|
||||
try:
|
||||
IPERF_BANDWIDTH_MBPS.labels(**labels).set(0)
|
||||
IPERF_JITTER_MS.labels(**labels).set(0)
|
||||
IPERF_PACKETS_TOTAL.labels(**labels).set(0)
|
||||
IPERF_LOST_PACKETS.labels(**labels).set(0)
|
||||
except KeyError:
|
||||
pass
|
||||
return
|
||||
|
||||
|
||||
# If we reach here, the test itself was successful in execution
|
||||
IPERF_TEST_SUCCESS.labels(**labels).set(1)
|
||||
|
||||
# The summary data is typically in result.json['end']['sum_sent'] or result.json['end']['sum_received']
|
||||
# The iperf3-python client often exposes this directly as attributes like sent_Mbps or received_Mbps
|
||||
# For TCP, we usually care about the received bandwidth on the client side (which is the exporter)
|
||||
# For UDP, the client report contains jitter, lost packets, etc.
|
||||
# Determine bandwidth:
|
||||
# Order of preference: received_Mbps, sent_Mbps, Mbps, then JSON fallbacks.
|
||||
# received_Mbps is often most relevant for TCP client perspective.
|
||||
# sent_Mbps can be relevant for UDP or as a TCP fallback.
|
||||
bandwidth_mbps = 0
|
||||
if hasattr(result, 'received_Mbps') and result.received_Mbps is not None:
|
||||
bandwidth_mbps = result.received_Mbps
|
||||
elif hasattr(result, 'sent_Mbps') and result.sent_Mbps is not None:
|
||||
# Fallback, though received_Mbps is usually more relevant for TCP client
|
||||
bandwidth_mbps = result.sent_Mbps
|
||||
# Add a check for the raw JSON output structure as a fallback
|
||||
elif result.json and 'end' in result.json and 'sum_received' in result.json['end'] and result.json['end']['sum_received']['bits_per_second'] is not None:
|
||||
bandwidth_mbps = result.json['end']['sum_received']['bits_per_second'] / 1000000
|
||||
elif result.json and 'end' in result.json and 'sum_sent' in result.json['end'] and result.json['end']['sum_sent']['bits_per_second'] is not None:
|
||||
bandwidth_mbps = result.json['end']['sum_sent']['bits_per_second'] / 1000000
|
||||
|
||||
elif hasattr(result, 'Mbps') and result.Mbps is not None: # General attribute from iperf3 library
|
||||
bandwidth_mbps = result.Mbps
|
||||
# Fallback to raw JSON if direct attributes are None or missing
|
||||
elif result.json:
|
||||
# Prefer received sum, then sent sum from the JSON output's 'end' summary
|
||||
if 'end' in result.json and 'sum_received' in result.json['end'] and \
|
||||
result.json['end']['sum_received'].get('bits_per_second') is not None:
|
||||
bandwidth_mbps = result.json['end']['sum_received']['bits_per_second'] / 1000000.0
|
||||
elif 'end' in result.json and 'sum_sent' in result.json['end'] and \
|
||||
result.json['end']['sum_sent'].get('bits_per_second') is not None:
|
||||
bandwidth_mbps = result.json['end']['sum_sent']['bits_per_second'] / 1000000.0
|
||||
|
||||
IPERF_BANDWIDTH_MBPS.labels(**labels).set(bandwidth_mbps)
|
||||
|
||||
# UDP specific metrics
|
||||
if protocol == 'udp':
|
||||
# iperf3-python exposes UDP results directly
|
||||
IPERF_JITTER_MS.labels(**labels).set(result.jitter_ms if hasattr(result, 'jitter_ms') and result.jitter_ms is not None else 0)
|
||||
IPERF_PACKETS_TOTAL.labels(**labels).set(result.packets if hasattr(result, 'packets') and result.packets is not None else 0)
|
||||
IPERF_LOST_PACKETS.labels(**labels).set(result.lost_packets if hasattr(result, 'lost_packets') and result.lost_packets is not None else 0)
|
||||
# These attributes are specific to UDP tests in iperf3
|
||||
IPERF_JITTER_MS.labels(**labels).set(getattr(result, 'jitter_ms', 0) if result.jitter_ms is not None else 0)
|
||||
IPERF_PACKETS_TOTAL.labels(**labels).set(getattr(result, 'packets', 0) if result.packets is not None else 0)
|
||||
IPERF_LOST_PACKETS.labels(**labels).set(getattr(result, 'lost_packets', 0) if result.lost_packets is not None else 0)
|
||||
else:
|
||||
# Ensure UDP metrics are zeroed or absent for TCP tests
|
||||
# For TCP tests, ensure UDP-specific metrics are set to 0
|
||||
try:
|
||||
IPERF_JITTER_MS.labels(**labels).set(0)
|
||||
IPERF_PACKETS_TOTAL.labels(**labels).set(0)
|
||||
IPERF_LOST_PACKETS.labels(**labels).set(0)
|
||||
except KeyError:
|
||||
# Can occur if labels not yet registered (e.g. first test is TCP)
|
||||
logging.debug(f"KeyError for {labels} when zeroing UDP metrics for TCP test.")
|
||||
pass
|
||||
|
||||
def main_loop():
|
||||
"""
|
||||
Main operational loop of the iperf3 exporter.
|
||||
|
||||
This loop periodically:
|
||||
1. Fetches configuration from environment variables:
|
||||
- IPERF_TEST_INTERVAL (default: 300s): Time between test cycles.
|
||||
- IPERF_SERVER_PORT (default: 5201): Port for iperf3 servers.
|
||||
- IPERF_TEST_PROTOCOL (default: 'tcp'): 'tcp' or 'udp'.
|
||||
- SOURCE_NODE_NAME (critical): Name of the node this exporter runs on.
|
||||
2. Discovers iperf3 server pods in the Kubernetes cluster.
|
||||
3. Runs iperf3 tests against each discovered server (unless it's on the same node).
|
||||
4. Sleeps for the configured test interval.
|
||||
|
||||
If SOURCE_NODE_NAME is not set, the script will log an error and exit.
|
||||
"""
|
||||
# Fetch operational configuration from environment variables
|
||||
test_interval = int(os.getenv('IPERF_TEST_INTERVAL', 300))
|
||||
server_port = int(os.getenv('IPERF_SERVER_PORT', 5201))
|
||||
protocol = os.getenv('IPERF_TEST_PROTOCOL', 'tcp').lower() # Ensure lowercase
|
||||
source_node_name = os.getenv('SOURCE_NODE_NAME')
|
||||
|
||||
# SOURCE_NODE_NAME is crucial for labeling metrics correctly.
|
||||
if not source_node_name:
|
||||
logging.error("CRITICAL: SOURCE_NODE_NAME environment variable not set. This is required. Exiting.")
|
||||
sys.exit(1)
|
||||
|
||||
logging.info(
|
||||
f"Exporter configured. Source Node: {source_node_name}, "
|
||||
f"Test Interval: {test_interval}s, Server Port: {server_port}, Protocol: {protocol.upper()}"
|
||||
)
|
||||
|
||||
while True:
|
||||
logging.info("Starting new iperf test cycle...")
|
||||
servers = discover_iperf_servers()
|
||||
|
||||
if not servers:
|
||||
logging.warning("No iperf servers discovered in this cycle. Check K8s setup and RBAC permissions.")
|
||||
else:
|
||||
for server in servers:
|
||||
dest_node_name = server.get('node_name', 'unknown_destination_node') # Default if key missing
|
||||
server_ip = server.get('ip')
|
||||
|
||||
if not server_ip:
|
||||
logging.warning(f"Discovered server entry missing an IP: {server}. Skipping.")
|
||||
continue
|
||||
|
||||
# Avoid testing a node against itself
|
||||
if dest_node_name == source_node_name:
|
||||
logging.info(f"Skipping test to self: {source_node_name} to {server_ip} (on same node: {dest_node_name}).")
|
||||
continue
|
||||
|
||||
run_iperf_test(server_ip, server_port, protocol, source_node_name, dest_node_name)
|
||||
|
||||
logging.info(f"Test cycle completed. Sleeping for {test_interval} seconds.")
|
||||
time.sleep(test_interval)
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Initial logging (like log level) is configured globally at the start of the script.
|
||||
|
||||
# Fetch Prometheus exporter listen port from environment variable
|
||||
listen_port = int(os.getenv('LISTEN_PORT', 9876))
|
||||
|
||||
try:
|
||||
# Start the Prometheus HTTP server to expose metrics.
|
||||
start_http_server(listen_port)
|
||||
logging.info(f"Prometheus exporter listening on port {listen_port}")
|
||||
except Exception as e:
|
||||
logging.error(f"Failed to start Prometheus HTTP server on port {listen_port}: {e}")
|
||||
sys.exit(1) # Exit if the metrics server cannot start
|
||||
|
||||
# Enter the main operational loop.
|
||||
# main_loop() contains its own critical checks (e.g., SOURCE_NODE_NAME) and will exit if necessary.
|
||||
main_loop()
|
||||
|
||||
347
get_helm.sh
347
get_helm.sh
@@ -1,347 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright The Helm Authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# The install script is based off of the MIT-licensed script from glide,
|
||||
# the package manager for Go: https://github.com/Masterminds/glide.sh/blob/master/get
|
||||
|
||||
: ${BINARY_NAME:="helm"}
|
||||
: ${USE_SUDO:="true"}
|
||||
: ${DEBUG:="false"}
|
||||
: ${VERIFY_CHECKSUM:="true"}
|
||||
: ${VERIFY_SIGNATURES:="false"}
|
||||
: ${HELM_INSTALL_DIR:="/usr/local/bin"}
|
||||
: ${GPG_PUBRING:="pubring.kbx"}
|
||||
|
||||
HAS_CURL="$(type "curl" &> /dev/null && echo true || echo false)"
|
||||
HAS_WGET="$(type "wget" &> /dev/null && echo true || echo false)"
|
||||
HAS_OPENSSL="$(type "openssl" &> /dev/null && echo true || echo false)"
|
||||
HAS_GPG="$(type "gpg" &> /dev/null && echo true || echo false)"
|
||||
HAS_GIT="$(type "git" &> /dev/null && echo true || echo false)"
|
||||
HAS_TAR="$(type "tar" &> /dev/null && echo true || echo false)"
|
||||
|
||||
# initArch discovers the architecture for this system.
|
||||
initArch() {
|
||||
ARCH=$(uname -m)
|
||||
case $ARCH in
|
||||
armv5*) ARCH="armv5";;
|
||||
armv6*) ARCH="armv6";;
|
||||
armv7*) ARCH="arm";;
|
||||
aarch64) ARCH="arm64";;
|
||||
x86) ARCH="386";;
|
||||
x86_64) ARCH="amd64";;
|
||||
i686) ARCH="386";;
|
||||
i386) ARCH="386";;
|
||||
esac
|
||||
}
|
||||
|
||||
# initOS discovers the operating system for this system.
|
||||
initOS() {
|
||||
OS=$(echo `uname`|tr '[:upper:]' '[:lower:]')
|
||||
|
||||
case "$OS" in
|
||||
# Minimalist GNU for Windows
|
||||
mingw*|cygwin*) OS='windows';;
|
||||
esac
|
||||
}
|
||||
|
||||
# runs the given command as root (detects if we are root already)
|
||||
runAsRoot() {
|
||||
if [ $EUID -ne 0 -a "$USE_SUDO" = "true" ]; then
|
||||
sudo "${@}"
|
||||
else
|
||||
"${@}"
|
||||
fi
|
||||
}
|
||||
|
||||
# verifySupported checks that the os/arch combination is supported for
|
||||
# binary builds, as well whether or not necessary tools are present.
|
||||
verifySupported() {
|
||||
local supported="darwin-amd64\ndarwin-arm64\nlinux-386\nlinux-amd64\nlinux-arm\nlinux-arm64\nlinux-ppc64le\nlinux-s390x\nlinux-riscv64\nwindows-amd64\nwindows-arm64"
|
||||
if ! echo "${supported}" | grep -q "${OS}-${ARCH}"; then
|
||||
echo "No prebuilt binary for ${OS}-${ARCH}."
|
||||
echo "To build from source, go to https://github.com/helm/helm"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "${HAS_CURL}" != "true" ] && [ "${HAS_WGET}" != "true" ]; then
|
||||
echo "Either curl or wget is required"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "${VERIFY_CHECKSUM}" == "true" ] && [ "${HAS_OPENSSL}" != "true" ]; then
|
||||
echo "In order to verify checksum, openssl must first be installed."
|
||||
echo "Please install openssl or set VERIFY_CHECKSUM=false in your environment."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "${VERIFY_SIGNATURES}" == "true" ]; then
|
||||
if [ "${HAS_GPG}" != "true" ]; then
|
||||
echo "In order to verify signatures, gpg must first be installed."
|
||||
echo "Please install gpg or set VERIFY_SIGNATURES=false in your environment."
|
||||
exit 1
|
||||
fi
|
||||
if [ "${OS}" != "linux" ]; then
|
||||
echo "Signature verification is currently only supported on Linux."
|
||||
echo "Please set VERIFY_SIGNATURES=false or verify the signatures manually."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "${HAS_GIT}" != "true" ]; then
|
||||
echo "[WARNING] Could not find git. It is required for plugin installation."
|
||||
fi
|
||||
|
||||
if [ "${HAS_TAR}" != "true" ]; then
|
||||
echo "[ERROR] Could not find tar. It is required to extract the helm binary archive."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# checkDesiredVersion checks if the desired version is available.
|
||||
checkDesiredVersion() {
|
||||
if [ "x$DESIRED_VERSION" == "x" ]; then
|
||||
# Get tag from release URL
|
||||
local latest_release_url="https://get.helm.sh/helm-latest-version"
|
||||
local latest_release_response=""
|
||||
if [ "${HAS_CURL}" == "true" ]; then
|
||||
latest_release_response=$( curl -L --silent --show-error --fail "$latest_release_url" 2>&1 || true )
|
||||
elif [ "${HAS_WGET}" == "true" ]; then
|
||||
latest_release_response=$( wget "$latest_release_url" -q -O - 2>&1 || true )
|
||||
fi
|
||||
TAG=$( echo "$latest_release_response" | grep '^v[0-9]' )
|
||||
if [ "x$TAG" == "x" ]; then
|
||||
printf "Could not retrieve the latest release tag information from %s: %s\n" "${latest_release_url}" "${latest_release_response}"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
TAG=$DESIRED_VERSION
|
||||
fi
|
||||
}
|
||||
|
||||
# checkHelmInstalledVersion checks which version of helm is installed and
|
||||
# if it needs to be changed.
|
||||
checkHelmInstalledVersion() {
|
||||
if [[ -f "${HELM_INSTALL_DIR}/${BINARY_NAME}" ]]; then
|
||||
local version=$("${HELM_INSTALL_DIR}/${BINARY_NAME}" version --template="{{ .Version }}")
|
||||
if [[ "$version" == "$TAG" ]]; then
|
||||
echo "Helm ${version} is already ${DESIRED_VERSION:-latest}"
|
||||
return 0
|
||||
else
|
||||
echo "Helm ${TAG} is available. Changing from version ${version}."
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# downloadFile downloads the latest binary package and also the checksum
|
||||
# for that binary.
|
||||
downloadFile() {
|
||||
HELM_DIST="helm-$TAG-$OS-$ARCH.tar.gz"
|
||||
DOWNLOAD_URL="https://get.helm.sh/$HELM_DIST"
|
||||
CHECKSUM_URL="$DOWNLOAD_URL.sha256"
|
||||
HELM_TMP_ROOT="$(mktemp -dt helm-installer-XXXXXX)"
|
||||
HELM_TMP_FILE="$HELM_TMP_ROOT/$HELM_DIST"
|
||||
HELM_SUM_FILE="$HELM_TMP_ROOT/$HELM_DIST.sha256"
|
||||
echo "Downloading $DOWNLOAD_URL"
|
||||
if [ "${HAS_CURL}" == "true" ]; then
|
||||
curl -SsL "$CHECKSUM_URL" -o "$HELM_SUM_FILE"
|
||||
curl -SsL "$DOWNLOAD_URL" -o "$HELM_TMP_FILE"
|
||||
elif [ "${HAS_WGET}" == "true" ]; then
|
||||
wget -q -O "$HELM_SUM_FILE" "$CHECKSUM_URL"
|
||||
wget -q -O "$HELM_TMP_FILE" "$DOWNLOAD_URL"
|
||||
fi
|
||||
}
|
||||
|
||||
# verifyFile verifies the SHA256 checksum of the binary package
|
||||
# and the GPG signatures for both the package and checksum file
|
||||
# (depending on settings in environment).
|
||||
verifyFile() {
|
||||
if [ "${VERIFY_CHECKSUM}" == "true" ]; then
|
||||
verifyChecksum
|
||||
fi
|
||||
if [ "${VERIFY_SIGNATURES}" == "true" ]; then
|
||||
verifySignatures
|
||||
fi
|
||||
}
|
||||
|
||||
# installFile installs the Helm binary.
|
||||
installFile() {
|
||||
HELM_TMP="$HELM_TMP_ROOT/$BINARY_NAME"
|
||||
mkdir -p "$HELM_TMP"
|
||||
tar xf "$HELM_TMP_FILE" -C "$HELM_TMP"
|
||||
HELM_TMP_BIN="$HELM_TMP/$OS-$ARCH/helm"
|
||||
echo "Preparing to install $BINARY_NAME into ${HELM_INSTALL_DIR}"
|
||||
runAsRoot cp "$HELM_TMP_BIN" "$HELM_INSTALL_DIR/$BINARY_NAME"
|
||||
echo "$BINARY_NAME installed into $HELM_INSTALL_DIR/$BINARY_NAME"
|
||||
}
|
||||
|
||||
# verifyChecksum verifies the SHA256 checksum of the binary package.
|
||||
verifyChecksum() {
|
||||
printf "Verifying checksum... "
|
||||
local sum=$(openssl sha1 -sha256 ${HELM_TMP_FILE} | awk '{print $2}')
|
||||
local expected_sum=$(cat ${HELM_SUM_FILE})
|
||||
if [ "$sum" != "$expected_sum" ]; then
|
||||
echo "SHA sum of ${HELM_TMP_FILE} does not match. Aborting."
|
||||
exit 1
|
||||
fi
|
||||
echo "Done."
|
||||
}
|
||||
|
||||
# verifySignatures obtains the latest KEYS file from GitHub main branch
|
||||
# as well as the signature .asc files from the specific GitHub release,
|
||||
# then verifies that the release artifacts were signed by a maintainer's key.
|
||||
verifySignatures() {
|
||||
printf "Verifying signatures... "
|
||||
local keys_filename="KEYS"
|
||||
local github_keys_url="https://raw.githubusercontent.com/helm/helm/main/${keys_filename}"
|
||||
if [ "${HAS_CURL}" == "true" ]; then
|
||||
curl -SsL "${github_keys_url}" -o "${HELM_TMP_ROOT}/${keys_filename}"
|
||||
elif [ "${HAS_WGET}" == "true" ]; then
|
||||
wget -q -O "${HELM_TMP_ROOT}/${keys_filename}" "${github_keys_url}"
|
||||
fi
|
||||
local gpg_keyring="${HELM_TMP_ROOT}/keyring.gpg"
|
||||
local gpg_homedir="${HELM_TMP_ROOT}/gnupg"
|
||||
mkdir -p -m 0700 "${gpg_homedir}"
|
||||
local gpg_stderr_device="/dev/null"
|
||||
if [ "${DEBUG}" == "true" ]; then
|
||||
gpg_stderr_device="/dev/stderr"
|
||||
fi
|
||||
gpg --batch --quiet --homedir="${gpg_homedir}" --import "${HELM_TMP_ROOT}/${keys_filename}" 2> "${gpg_stderr_device}"
|
||||
gpg --batch --no-default-keyring --keyring "${gpg_homedir}/${GPG_PUBRING}" --export > "${gpg_keyring}"
|
||||
local github_release_url="https://github.com/helm/helm/releases/download/${TAG}"
|
||||
if [ "${HAS_CURL}" == "true" ]; then
|
||||
curl -SsL "${github_release_url}/helm-${TAG}-${OS}-${ARCH}.tar.gz.sha256.asc" -o "${HELM_TMP_ROOT}/helm-${TAG}-${OS}-${ARCH}.tar.gz.sha256.asc"
|
||||
curl -SsL "${github_release_url}/helm-${TAG}-${OS}-${ARCH}.tar.gz.asc" -o "${HELM_TMP_ROOT}/helm-${TAG}-${OS}-${ARCH}.tar.gz.asc"
|
||||
elif [ "${HAS_WGET}" == "true" ]; then
|
||||
wget -q -O "${HELM_TMP_ROOT}/helm-${TAG}-${OS}-${ARCH}.tar.gz.sha256.asc" "${github_release_url}/helm-${TAG}-${OS}-${ARCH}.tar.gz.sha256.asc"
|
||||
wget -q -O "${HELM_TMP_ROOT}/helm-${TAG}-${OS}-${ARCH}.tar.gz.asc" "${github_release_url}/helm-${TAG}-${OS}-${ARCH}.tar.gz.asc"
|
||||
fi
|
||||
local error_text="If you think this might be a potential security issue,"
|
||||
error_text="${error_text}\nplease see here: https://github.com/helm/community/blob/master/SECURITY.md"
|
||||
local num_goodlines_sha=$(gpg --verify --keyring="${gpg_keyring}" --status-fd=1 "${HELM_TMP_ROOT}/helm-${TAG}-${OS}-${ARCH}.tar.gz.sha256.asc" 2> "${gpg_stderr_device}" | grep -c -E '^\[GNUPG:\] (GOODSIG|VALIDSIG)')
|
||||
if [[ ${num_goodlines_sha} -lt 2 ]]; then
|
||||
echo "Unable to verify the signature of helm-${TAG}-${OS}-${ARCH}.tar.gz.sha256!"
|
||||
echo -e "${error_text}"
|
||||
exit 1
|
||||
fi
|
||||
local num_goodlines_tar=$(gpg --verify --keyring="${gpg_keyring}" --status-fd=1 "${HELM_TMP_ROOT}/helm-${TAG}-${OS}-${ARCH}.tar.gz.asc" 2> "${gpg_stderr_device}" | grep -c -E '^\[GNUPG:\] (GOODSIG|VALIDSIG)')
|
||||
if [[ ${num_goodlines_tar} -lt 2 ]]; then
|
||||
echo "Unable to verify the signature of helm-${TAG}-${OS}-${ARCH}.tar.gz!"
|
||||
echo -e "${error_text}"
|
||||
exit 1
|
||||
fi
|
||||
echo "Done."
|
||||
}
|
||||
|
||||
# fail_trap is executed if an error occurs.
|
||||
fail_trap() {
|
||||
result=$?
|
||||
if [ "$result" != "0" ]; then
|
||||
if [[ -n "$INPUT_ARGUMENTS" ]]; then
|
||||
echo "Failed to install $BINARY_NAME with the arguments provided: $INPUT_ARGUMENTS"
|
||||
help
|
||||
else
|
||||
echo "Failed to install $BINARY_NAME"
|
||||
fi
|
||||
echo -e "\tFor support, go to https://github.com/helm/helm."
|
||||
fi
|
||||
cleanup
|
||||
exit $result
|
||||
}
|
||||
|
||||
# testVersion tests the installed client to make sure it is working.
|
||||
testVersion() {
|
||||
set +e
|
||||
HELM="$(command -v $BINARY_NAME)"
|
||||
if [ "$?" = "1" ]; then
|
||||
echo "$BINARY_NAME not found. Is $HELM_INSTALL_DIR on your "'$PATH?'
|
||||
exit 1
|
||||
fi
|
||||
set -e
|
||||
}
|
||||
|
||||
# help provides possible cli installation arguments
|
||||
help () {
|
||||
echo "Accepted cli arguments are:"
|
||||
echo -e "\t[--help|-h ] ->> prints this help"
|
||||
echo -e "\t[--version|-v <desired_version>] . When not defined it fetches the latest release tag from the Helm CDN"
|
||||
echo -e "\te.g. --version v3.0.0 or -v canary"
|
||||
echo -e "\t[--no-sudo] ->> install without sudo"
|
||||
}
|
||||
|
||||
# cleanup temporary files to avoid https://github.com/helm/helm/issues/2977
|
||||
cleanup() {
|
||||
if [[ -d "${HELM_TMP_ROOT:-}" ]]; then
|
||||
rm -rf "$HELM_TMP_ROOT"
|
||||
fi
|
||||
}
|
||||
|
||||
# Execution
|
||||
|
||||
#Stop execution on any error
|
||||
trap "fail_trap" EXIT
|
||||
set -e
|
||||
|
||||
# Set debug if desired
|
||||
if [ "${DEBUG}" == "true" ]; then
|
||||
set -x
|
||||
fi
|
||||
|
||||
# Parsing input arguments (if any)
|
||||
export INPUT_ARGUMENTS="${@}"
|
||||
set -u
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
'--version'|-v)
|
||||
shift
|
||||
if [[ $# -ne 0 ]]; then
|
||||
export DESIRED_VERSION="${1}"
|
||||
if [[ "$1" != "v"* ]]; then
|
||||
echo "Expected version arg ('${DESIRED_VERSION}') to begin with 'v', fixing..."
|
||||
export DESIRED_VERSION="v${1}"
|
||||
fi
|
||||
else
|
||||
echo -e "Please provide the desired version. e.g. --version v3.0.0 or -v canary"
|
||||
exit 0
|
||||
fi
|
||||
;;
|
||||
'--no-sudo')
|
||||
USE_SUDO="false"
|
||||
;;
|
||||
'--help'|-h)
|
||||
help
|
||||
exit 0
|
||||
;;
|
||||
*) exit 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
set +u
|
||||
|
||||
initArch
|
||||
initOS
|
||||
verifySupported
|
||||
checkDesiredVersion
|
||||
if ! checkHelmInstalledVersion; then
|
||||
downloadFile
|
||||
verifyFile
|
||||
installFile
|
||||
fi
|
||||
testVersion
|
||||
cleanup
|
||||
402
index.yaml
402
index.yaml
@@ -1,402 +0,0 @@
|
||||
apiVersion: v1
|
||||
entries:
|
||||
iperf3-monitor:
|
||||
- annotations:
|
||||
artifacthub.io/category: networking
|
||||
artifacthub.io/changes: |
|
||||
- Add initial Helm chart structure.
|
||||
apiVersion: v2
|
||||
appVersion: 0.2.4
|
||||
created: "2025-07-02T08:39:13.621609745Z"
|
||||
dependencies:
|
||||
- condition: dependencies.install, serviceMonitor.enabled, !dependencies.useTrueChartsPrometheusOperator
|
||||
name: kube-prometheus-stack
|
||||
repository: https://prometheus-community.github.io/helm-charts
|
||||
version: '>=30.0.0'
|
||||
- condition: dependencies.install, serviceMonitor.enabled, dependencies.useTrueChartsPrometheusOperator
|
||||
name: prometheus-operator
|
||||
repository: oci://tccr.io/truecharts
|
||||
version: '>=8.11.1'
|
||||
- name: common
|
||||
repository: https://bjw-s-labs.github.io/helm-charts/
|
||||
version: 4.1.2
|
||||
description: A Helm chart for deploying a Kubernetes-native iperf3 network performance
|
||||
monitoring service with Prometheus and Grafana.
|
||||
digest: 3929933b0e4b46d4a3e4274e495b27a467baa1cc59e0457f488b1fef834e815d
|
||||
home: https://github.com/malarinv/iperf3-monitor
|
||||
icon: https://raw.githubusercontent.com/malarinv/iperf3-monitor/main/icon.png
|
||||
keywords:
|
||||
- iperf3
|
||||
- network
|
||||
- performance
|
||||
- monitoring
|
||||
- kubernetes
|
||||
- prometheus
|
||||
- grafana
|
||||
maintainers:
|
||||
- email: malarkannan.invention@gmail.com
|
||||
name: Malar Invention
|
||||
name: iperf3-monitor
|
||||
sources:
|
||||
- https://github.com/malarinv/iperf3-monitor
|
||||
type: application
|
||||
urls:
|
||||
- https://malarinv.github.io/iperf3-monitor/iperf3-monitor-0.2.4.tgz
|
||||
version: 0.2.4
|
||||
- annotations:
|
||||
artifacthub.io/category: networking
|
||||
artifacthub.io/changes: |
|
||||
- Add initial Helm chart structure.
|
||||
apiVersion: v2
|
||||
appVersion: 0.2.3
|
||||
created: "2025-07-02T08:02:44.490472865Z"
|
||||
dependencies:
|
||||
- condition: dependencies.install, serviceMonitor.enabled, !dependencies.useTrueChartsPrometheusOperator
|
||||
name: kube-prometheus-stack
|
||||
repository: https://prometheus-community.github.io/helm-charts
|
||||
version: '>=30.0.0'
|
||||
- condition: dependencies.install, serviceMonitor.enabled, dependencies.useTrueChartsPrometheusOperator
|
||||
name: prometheus-operator
|
||||
repository: oci://tccr.io/truecharts
|
||||
version: '>=8.11.1'
|
||||
- name: common
|
||||
repository: https://bjw-s-labs.github.io/helm-charts/
|
||||
version: 4.1.2
|
||||
description: A Helm chart for deploying a Kubernetes-native iperf3 network performance
|
||||
monitoring service with Prometheus and Grafana.
|
||||
digest: dbd898b7c57c41e19e1abe46285ed0f8353b11bf7ab3d618c09101e5f50624a2
|
||||
home: https://github.com/malarinv/iperf3-monitor
|
||||
icon: https://raw.githubusercontent.com/malarinv/iperf3-monitor/main/icon.png
|
||||
keywords:
|
||||
- iperf3
|
||||
- network
|
||||
- performance
|
||||
- monitoring
|
||||
- kubernetes
|
||||
- prometheus
|
||||
- grafana
|
||||
maintainers:
|
||||
- email: malarkannan.invention@gmail.com
|
||||
name: Malar Invention
|
||||
name: iperf3-monitor
|
||||
sources:
|
||||
- https://github.com/malarinv/iperf3-monitor
|
||||
type: application
|
||||
urls:
|
||||
- https://malarinv.github.io/iperf3-monitor/iperf3-monitor-0.2.3.tgz
|
||||
version: 0.2.3
|
||||
- annotations:
|
||||
artifacthub.io/category: networking
|
||||
artifacthub.io/changes: |
|
||||
- Add initial Helm chart structure.
|
||||
apiVersion: v2
|
||||
appVersion: 0.2.2
|
||||
created: "2025-07-02T07:30:10.740811061Z"
|
||||
dependencies:
|
||||
- condition: dependencies.install, serviceMonitor.enabled, !dependencies.useTrueChartsPrometheusOperator
|
||||
name: kube-prometheus-stack
|
||||
repository: https://prometheus-community.github.io/helm-charts
|
||||
version: '>=30.0.0'
|
||||
- condition: dependencies.install, serviceMonitor.enabled, dependencies.useTrueChartsPrometheusOperator
|
||||
name: prometheus-operator
|
||||
repository: oci://tccr.io/truecharts
|
||||
version: '>=8.11.1'
|
||||
- name: common
|
||||
repository: https://bjw-s-labs.github.io/helm-charts/
|
||||
version: 4.1.2
|
||||
description: A Helm chart for deploying a Kubernetes-native iperf3 network performance
|
||||
monitoring service with Prometheus and Grafana.
|
||||
digest: 9404cc9b70c01370727cd6aabbe634698d6c2b86188853c5e7ea020547e839c3
|
||||
home: https://github.com/malarinv/iperf3-monitor
|
||||
icon: https://raw.githubusercontent.com/malarinv/iperf3-monitor/main/icon.png
|
||||
keywords:
|
||||
- iperf3
|
||||
- network
|
||||
- performance
|
||||
- monitoring
|
||||
- kubernetes
|
||||
- prometheus
|
||||
- grafana
|
||||
maintainers:
|
||||
- email: malarkannan.invention@gmail.com
|
||||
name: Malar Invention
|
||||
name: iperf3-monitor
|
||||
sources:
|
||||
- https://github.com/malarinv/iperf3-monitor
|
||||
type: application
|
||||
urls:
|
||||
- https://malarinv.github.io/iperf3-monitor/iperf3-monitor-0.2.2.tgz
|
||||
version: 0.2.2
|
||||
- annotations:
|
||||
artifacthub.io/category: networking
|
||||
artifacthub.io/changes: |
|
||||
- Add initial Helm chart structure.
|
||||
apiVersion: v2
|
||||
appVersion: 0.2.1
|
||||
created: "2025-07-02T06:29:50.048523169Z"
|
||||
dependencies:
|
||||
- condition: dependencies.install, serviceMonitor.enabled, !dependencies.useTrueChartsPrometheusOperator
|
||||
name: kube-prometheus-stack
|
||||
repository: https://prometheus-community.github.io/helm-charts
|
||||
version: '>=30.0.0'
|
||||
- condition: dependencies.install, serviceMonitor.enabled, dependencies.useTrueChartsPrometheusOperator
|
||||
name: prometheus-operator
|
||||
repository: oci://tccr.io/truecharts
|
||||
version: '>=8.11.1'
|
||||
- name: common
|
||||
repository: https://bjw-s-labs.github.io/helm-charts/
|
||||
version: 4.1.2
|
||||
description: A Helm chart for deploying a Kubernetes-native iperf3 network performance
|
||||
monitoring service with Prometheus and Grafana.
|
||||
digest: 78018c1dcdafe6768f874a524005e535e1744a9a76f026d8027f2ac69bf49c4c
|
||||
home: https://github.com/malarinv/iperf3-monitor
|
||||
icon: https://raw.githubusercontent.com/malarinv/iperf3-monitor/main/icon.png
|
||||
keywords:
|
||||
- iperf3
|
||||
- network
|
||||
- performance
|
||||
- monitoring
|
||||
- kubernetes
|
||||
- prometheus
|
||||
- grafana
|
||||
maintainers:
|
||||
- email: malarkannan.invention@gmail.com
|
||||
name: Malar Invention
|
||||
name: iperf3-monitor
|
||||
sources:
|
||||
- https://github.com/malarinv/iperf3-monitor
|
||||
type: application
|
||||
urls:
|
||||
- https://malarinv.github.io/iperf3-monitor/iperf3-monitor-0.2.1.tgz
|
||||
version: 0.2.1
|
||||
- annotations:
|
||||
artifacthub.io/category: networking
|
||||
artifacthub.io/changes: |
|
||||
- Add initial Helm chart structure.
|
||||
apiVersion: v2
|
||||
appVersion: 0.1.9
|
||||
created: "2025-07-01T20:10:45.681665311Z"
|
||||
dependencies:
|
||||
- condition: dependencies.install, serviceMonitor.enabled, !dependencies.useTrueChartsPrometheusOperator
|
||||
name: kube-prometheus-stack
|
||||
repository: https://prometheus-community.github.io/helm-charts
|
||||
version: '>=30.0.0'
|
||||
- condition: dependencies.install, serviceMonitor.enabled, dependencies.useTrueChartsPrometheusOperator
|
||||
name: prometheus-operator
|
||||
repository: oci://tccr.io/truecharts
|
||||
version: '>=8.11.1'
|
||||
description: A Helm chart for deploying a Kubernetes-native iperf3 network performance
|
||||
monitoring service with Prometheus and Grafana.
|
||||
digest: ba71668f2e79f143971758eddf2c1ccb81e8fa8dd681748f4a34718af83c523c
|
||||
home: https://github.com/malarinv/iperf3-monitor
|
||||
icon: https://raw.githubusercontent.com/malarinv/iperf3-monitor/main/icon.png
|
||||
keywords:
|
||||
- iperf3
|
||||
- network
|
||||
- performance
|
||||
- monitoring
|
||||
- kubernetes
|
||||
- prometheus
|
||||
- grafana
|
||||
maintainers:
|
||||
- email: malarkannan.invention@gmail.com
|
||||
name: Malar Invention
|
||||
name: iperf3-monitor
|
||||
sources:
|
||||
- https://github.com/malarinv/iperf3-monitor
|
||||
type: application
|
||||
urls:
|
||||
- https://malarinv.github.io/iperf3-monitor/iperf3-monitor-0.1.9.tgz
|
||||
version: 0.1.9
|
||||
- annotations:
|
||||
artifacthub.io/category: networking
|
||||
artifacthub.io/changes: |
|
||||
- Add initial Helm chart structure.
|
||||
apiVersion: v2
|
||||
appVersion: 0.1.8
|
||||
created: "2025-06-20T20:43:41.906216787Z"
|
||||
dependencies:
|
||||
- condition: dependencies.install, serviceMonitor.enabled, !dependencies.useTrueChartsPrometheusOperator
|
||||
name: kube-prometheus-stack
|
||||
repository: https://prometheus-community.github.io/helm-charts
|
||||
version: '>=30.0.0'
|
||||
- condition: dependencies.install, serviceMonitor.enabled, dependencies.useTrueChartsPrometheusOperator
|
||||
name: prometheus-operator
|
||||
repository: oci://tccr.io/truecharts
|
||||
version: '>=8.11.1'
|
||||
description: A Helm chart for deploying a Kubernetes-native iperf3 network performance
|
||||
monitoring service with Prometheus and Grafana.
|
||||
digest: dd1707ef16c06a1a3c4979983a0141c0f19bbd51b7b95a3bda22033780a517ba
|
||||
home: https://github.com/malarinv/iperf3-monitor
|
||||
icon: https://raw.githubusercontent.com/malarinv/iperf3-monitor/main/icon.png
|
||||
keywords:
|
||||
- iperf3
|
||||
- network
|
||||
- performance
|
||||
- monitoring
|
||||
- kubernetes
|
||||
- prometheus
|
||||
- grafana
|
||||
maintainers:
|
||||
- email: malarkannan.invention@gmail.com
|
||||
name: Malar Invention
|
||||
name: iperf3-monitor
|
||||
sources:
|
||||
- https://github.com/malarinv/iperf3-monitor
|
||||
type: application
|
||||
urls:
|
||||
- https://malarinv.github.io/iperf3-monitor/iperf3-monitor-0.1.8.tgz
|
||||
version: 0.1.8
|
||||
- annotations:
|
||||
artifacthub.io/category: networking
|
||||
artifacthub.io/changes: |
|
||||
- Add initial Helm chart structure.
|
||||
apiVersion: v2
|
||||
appVersion: 0.1.6
|
||||
created: "2025-06-20T19:36:24.8256252Z"
|
||||
dependencies:
|
||||
- condition: dependencies.install, serviceMonitor.enabled, !dependencies.useTrueChartsPrometheusOperator
|
||||
name: kube-prometheus-stack
|
||||
repository: https://prometheus-community.github.io/helm-charts
|
||||
version: '>=30.0.0'
|
||||
- condition: dependencies.install, serviceMonitor.enabled, dependencies.useTrueChartsPrometheusOperator
|
||||
name: prometheus-operator
|
||||
repository: oci://tccr.io/truecharts
|
||||
version: '>=8.11.1'
|
||||
description: A Helm chart for deploying a Kubernetes-native iperf3 network performance
|
||||
monitoring service with Prometheus and Grafana.
|
||||
digest: e23e2801a298edf8c345fcce210f7186a2304cf8321f315a244e44f0ef83e4bd
|
||||
home: https://github.com/malarinv/iperf3-monitor
|
||||
icon: https://raw.githubusercontent.com/malarinv/iperf3-monitor/main/icon.png
|
||||
keywords:
|
||||
- iperf3
|
||||
- network
|
||||
- performance
|
||||
- monitoring
|
||||
- kubernetes
|
||||
- prometheus
|
||||
- grafana
|
||||
maintainers:
|
||||
- email: malarkannan.invention@gmail.com
|
||||
name: Malar Invention
|
||||
name: iperf3-monitor
|
||||
sources:
|
||||
- https://github.com/malarinv/iperf3-monitor
|
||||
type: application
|
||||
urls:
|
||||
- https://malarinv.github.io/iperf3-monitor/iperf3-monitor-0.1.6.tgz
|
||||
version: 0.1.6
|
||||
- annotations:
|
||||
artifacthub.io/category: networking
|
||||
artifacthub.io/changes: |
|
||||
- Add initial Helm chart structure.
|
||||
apiVersion: v2
|
||||
appVersion: 0.1.5
|
||||
created: "2025-06-20T13:41:15.223267266Z"
|
||||
dependencies:
|
||||
- condition: dependencies.install, serviceMonitor.enabled, !dependencies.useTrueChartsPrometheusOperator
|
||||
name: kube-prometheus-stack
|
||||
repository: https://prometheus-community.github.io/helm-charts
|
||||
version: '>=30.0.0'
|
||||
- condition: dependencies.install, serviceMonitor.enabled, dependencies.useTrueChartsPrometheusOperator
|
||||
name: prometheus-operator
|
||||
repository: oci://tccr.io/truecharts
|
||||
version: '>=8.11.1'
|
||||
description: A Helm chart for deploying a Kubernetes-native iperf3 network performance
|
||||
monitoring service with Prometheus and Grafana.
|
||||
digest: 565b4615cbfa166cb5b158d43bc0f79fb2482c6213e8d9c67b32cd2e2dac6103
|
||||
home: https://github.com/malarinv/iperf3-monitor
|
||||
icon: https://raw.githubusercontent.com/malarinv/iperf3-monitor/main/icon.png
|
||||
keywords:
|
||||
- iperf3
|
||||
- network
|
||||
- performance
|
||||
- monitoring
|
||||
- kubernetes
|
||||
- prometheus
|
||||
- grafana
|
||||
maintainers:
|
||||
- email: malarkannan.invention@gmail.com
|
||||
name: Malar Invention
|
||||
name: iperf3-monitor
|
||||
sources:
|
||||
- https://github.com/malarinv/iperf3-monitor
|
||||
type: application
|
||||
urls:
|
||||
- https://malarinv.github.io/iperf3-monitor/iperf3-monitor-0.1.5.tgz
|
||||
version: 0.1.5
|
||||
- annotations:
|
||||
artifacthub.io/category: networking
|
||||
artifacthub.io/changes: |
|
||||
- Add initial Helm chart structure.
|
||||
apiVersion: v2
|
||||
appVersion: 0.1.4
|
||||
created: "2025-06-20T12:13:54.388432454Z"
|
||||
dependencies:
|
||||
- condition: serviceMonitor.enabled, !dependencies.useTrueChartsPrometheusOperator
|
||||
name: kube-prometheus-stack
|
||||
repository: https://prometheus-community.github.io/helm-charts
|
||||
version: '>=30.0.0'
|
||||
- condition: serviceMonitor.enabled, dependencies.useTrueChartsPrometheusOperator
|
||||
name: prometheus-operator
|
||||
repository: oci://tccr.io/truecharts
|
||||
version: '>=8.11.1'
|
||||
description: A Helm chart for deploying a Kubernetes-native iperf3 network performance
|
||||
monitoring service with Prometheus and Grafana.
|
||||
digest: 6c0dbe54f696cdc2d98ecb54cff5c5b3c9eaea913e3caa798ad81c587ef5d199
|
||||
home: https://github.com/malarinv/iperf3-monitor
|
||||
icon: https://raw.githubusercontent.com/malarinv/iperf3-monitor/main/icon.png
|
||||
keywords:
|
||||
- iperf3
|
||||
- network
|
||||
- performance
|
||||
- monitoring
|
||||
- kubernetes
|
||||
- prometheus
|
||||
- grafana
|
||||
maintainers:
|
||||
- email: malarkannan.invention@gmail.com
|
||||
name: Malar Invention
|
||||
name: iperf3-monitor
|
||||
sources:
|
||||
- https://github.com/malarinv/iperf3-monitor
|
||||
type: application
|
||||
urls:
|
||||
- https://malarinv.github.io/iperf3-monitor/iperf3-monitor-0.1.4.tgz
|
||||
version: 0.1.4
|
||||
- annotations:
|
||||
artifacthub.io/category: networking
|
||||
artifacthub.io/changes: |
|
||||
- Add initial Helm chart structure.
|
||||
apiVersion: v2
|
||||
appVersion: 0.1.1
|
||||
created: "2025-06-19T21:43:47.560731092Z"
|
||||
dependencies:
|
||||
- condition: serviceMonitor.enabled
|
||||
name: kube-prometheus-stack
|
||||
repository: https://prometheus-community.github.io/helm-charts
|
||||
version: '>=30.0.0'
|
||||
description: A Helm chart for deploying a Kubernetes-native iperf3 network performance
|
||||
monitoring service with Prometheus and Grafana.
|
||||
digest: e334d11e50f6303486830cc1384bfe21eecfe803f665868eaeb294d5ef168559
|
||||
home: https://github.com/malarinv/iperf3-monitor
|
||||
icon: https://raw.githubusercontent.com/malarinv/iperf3-monitor/main/icon.png
|
||||
keywords:
|
||||
- iperf3
|
||||
- network
|
||||
- performance
|
||||
- monitoring
|
||||
- kubernetes
|
||||
- prometheus
|
||||
- grafana
|
||||
maintainers:
|
||||
- email: malarkannan.invention@gmail.com
|
||||
name: Malar Invention
|
||||
name: iperf3-monitor
|
||||
sources:
|
||||
- https://github.com/malarinv/iperf3-monitor
|
||||
type: application
|
||||
urls:
|
||||
- https://malarinv.github.io/iperf3-monitor/iperf3-monitor-0.1.1.tgz
|
||||
version: 0.1.1
|
||||
generated: "2025-07-02T08:39:13.550399875Z"
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user