Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
cef60cc
feat: add a chart for the network mapper
roderik Sep 17, 2025
0364ec5
chore(deps): update dependencies in package.json and bun.lock
roderik Sep 17, 2025
445531f
chore: update build and test commands in documentation and configurat…
roderik Sep 17, 2025
3f3def9
docs: update README and chart documentation with default values for C…
roderik Sep 17, 2025
5aca0d5
chore: update Chart.yaml and README with maintainer information
roderik Sep 17, 2025
1c10c4f
chore: update GitHub Actions workflow for versioning and build process
roderik Sep 17, 2025
2b87e79
chore: update Helm chart values and CLI command handling for output type
roderik Sep 17, 2025
2b70427
chore: update README and service account template for network bootstr…
roderik Sep 17, 2025
920c801
chore: update Renovate configuration and improve Kubernetes output ha…
roderik Sep 17, 2025
ba687ab
chore: update Chart.yaml to include apiVersion and description for ne…
roderik Sep 17, 2025
e5dc483
chore: update CI configuration and linting settings in .github/ct.yaml
roderik Sep 17, 2025
21b25ff
chore: update CI configuration and package scripts in package.json an…
roderik Sep 17, 2025
6bc831f
chore: update QA workflow to streamline Harbor login and notification…
roderik Sep 17, 2025
9ce0166
chore: update Kubernetes output tests to include secrets handling and…
roderik Sep 17, 2025
982a8cb
chore: update CI configuration in .github/ct.yaml and qa.yml to enhan…
roderik Sep 17, 2025
393681b
chore: update CI configuration in .github/ct.yaml to enhance Helm com…
roderik Sep 17, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/qa.yml
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@ jobs:
if: github.event_name == 'pull_request' || github.event_name == 'push'
run: bun typecheck

- name: Set version
if: github.event_name == 'pull_request' || github.event_name == 'push'
run: bun run tools/version.ts

- name: Docker meta
if: github.event_name == 'pull_request' || github.event_name == 'push'
id: meta
Expand Down
6 changes: 6 additions & 0 deletions biome.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@
"rules": {
"suspicious": {
"noConsole": "off"
},
"complexity": {
"noExcessiveCognitiveComplexity": "off"
},
"nursery": {
"useMaxParams": "off"
}
}
},
Expand Down
3 changes: 3 additions & 0 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 23 additions & 0 deletions charts/network-bootstrapper/.helmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/
6 changes: 6 additions & 0 deletions charts/network-bootstrapper/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
apiVersion: v2
name: network-bootstrapper
description: A Helm chart for Kubernetes
type: application
version: 0.1.0
appVersion: "0.1.0"
35 changes: 35 additions & 0 deletions charts/network-bootstrapper/templates/NOTES.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
1. Get the application URL by running these commands:
{{- if .Values.httpRoute.enabled }}
{{- if .Values.httpRoute.hostnames }}
export APP_HOSTNAME={{ .Values.httpRoute.hostnames | first }}
{{- else }}
export APP_HOSTNAME=$(kubectl get --namespace {{(first .Values.httpRoute.parentRefs).namespace | default .Release.Namespace }} gateway/{{ (first .Values.httpRoute.parentRefs).name }} -o jsonpath="{.spec.listeners[0].hostname}")
{{- end }}
{{- if and .Values.httpRoute.rules (first .Values.httpRoute.rules).matches (first (first .Values.httpRoute.rules).matches).path.value }}
echo "Visit http://$APP_HOSTNAME{{ (first (first .Values.httpRoute.rules).matches).path.value }} to use your application"

NOTE: Your HTTPRoute depends on the listener configuration of your gateway and your HTTPRoute rules.
The rules can be set for path, method, header and query parameters.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Consider changing 'header' to 'headers' for consistency.

This aligns with standard terminology in both HTTP and Kubernetes documentation.

Suggested change
The rules can be set for path, method, header and query parameters.
The rules can be set for path, method, headers and query parameters.

You can check the gateway configuration with 'kubectl get --namespace {{(first .Values.httpRoute.parentRefs).namespace | default .Release.Namespace }} gateway/{{ (first .Values.httpRoute.parentRefs).name }} -o yaml'
{{- end }}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The logic to extract the path from httpRoute.rules is very fragile. It uses first multiple times and direct property access without checking for existence. If .Values.httpRoute.rules or any of the nested properties are empty or nil, the template rendering will fail, causing the entire Helm operation to abort. This should be made more robust to avoid installation failures.

{{- $path := "" }}
{{- with .Values.httpRoute.rules | first }}
  {{- with .matches | first }}
    {{- with .path }}
      {{- $path = .value }}
    {{- end }}
  {{- end }}
{{- end }}
{{- if $path }}
    echo "Visit http://$APP_HOSTNAME{{ $path }} to use your application"

    NOTE: Your HTTPRoute depends on the listener configuration of your gateway and your HTTPRoute rules.
    The rules can be set for path, method, header and query parameters.
    You can check the gateway configuration with 'kubectl get --namespace {{(first .Values.httpRoute.parentRefs).namespace | default .Release.Namespace }} gateway/{{ (first .Values.httpRoute.parentRefs).name }} -o yaml'
{{- end }}

{{- else if .Values.ingress.enabled }}
{{- range $host := .Values.ingress.hosts }}
{{- range .paths }}
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
{{- end }}
{{- end }}
{{- else if contains "NodePort" .Values.service.type }}
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "network-bootstrapper.fullname" . }})
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT
{{- else if contains "LoadBalancer" .Values.service.type }}
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
You can watch its status by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "network-bootstrapper.fullname" . }}'
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "network-bootstrapper.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
echo http://$SERVICE_IP:{{ .Values.service.port }}
{{- else if contains "ClusterIP" .Values.service.type }}
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "network-bootstrapper.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
{{- end }}
62 changes: 62 additions & 0 deletions charts/network-bootstrapper/templates/_helpers.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "network-bootstrapper.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "network-bootstrapper.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}

{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "network-bootstrapper.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
Common labels
*/}}
{{- define "network-bootstrapper.labels" -}}
helm.sh/chart: {{ include "network-bootstrapper.chart" . }}
{{ include "network-bootstrapper.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}

{{/*
Selector labels
*/}}
{{- define "network-bootstrapper.selectorLabels" -}}
app.kubernetes.io/name: {{ include "network-bootstrapper.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}

{{/*
Create the name of the service account to use
*/}}
{{- define "network-bootstrapper.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "network-bootstrapper.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}
78 changes: 78 additions & 0 deletions charts/network-bootstrapper/templates/deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "network-bootstrapper.fullname" . }}
labels:
{{- include "network-bootstrapper.labels" . | nindent 4 }}
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
{{- end }}
selector:
matchLabels:
{{- include "network-bootstrapper.selectorLabels" . | nindent 6 }}
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "network-bootstrapper.labels" . | nindent 8 }}
{{- with .Values.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "network-bootstrapper.serviceAccountName" . }}
{{- with .Values.podSecurityContext }}
securityContext:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: {{ .Chart.Name }}
{{- with .Values.securityContext }}
securityContext:
{{- toYaml . | nindent 12 }}
{{- end }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: {{ .Values.service.port }}
protocol: TCP
{{- with .Values.livenessProbe }}
livenessProbe:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.readinessProbe }}
readinessProbe:
{{- toYaml . | nindent 12 }}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential bug: The Helm chart is misconfigured for a CLI tool, using HTTP probes and a default nginx image, which will cause either deployment failure or deployment of the wrong application.
  • Description: The Helm chart is configured to deploy a long-running web service, but the network-bootstrapper application is a command-line tool that runs to completion and then exits. The deployment.yaml specifies HTTP livenessProbe and readinessProbe. If the correct application image were used, these probes would fail because the container does not run an HTTP server, causing the pod to enter a restart loop and the deployment to fail. Additionally, the default image specified in values.yaml is nginx, which is incorrect. This would result in deploying an nginx web server instead of the intended application.

  • Suggested fix: The workload should be refactored to use a Kubernetes Job resource, which is designed for run-to-completion tasks. If a Deployment must be used, the HTTP livenessProbe and readinessProbe should be removed. The default image in values.yaml must also be updated to point to the correct network-bootstrapper container image.
    severity: 0.9, confidence: 0.95

Did we get this right? 👍 / 👎 to inform future reviews.

{{- end }}
{{- with .Values.resources }}
resources:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.volumeMounts }}
volumeMounts:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.volumes }}
volumes:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
32 changes: 32 additions & 0 deletions charts/network-bootstrapper/templates/hpa.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{{- if .Values.autoscaling.enabled }}
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: {{ include "network-bootstrapper.fullname" . }}
labels:
{{- include "network-bootstrapper.labels" . | nindent 4 }}
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: {{ include "network-bootstrapper.fullname" . }}
minReplicas: {{ .Values.autoscaling.minReplicas }}
maxReplicas: {{ .Values.autoscaling.maxReplicas }}
metrics:
{{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
{{- end }}
{{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
{{- end }}
{{- end }}
38 changes: 38 additions & 0 deletions charts/network-bootstrapper/templates/httproute.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{{- if .Values.httpRoute.enabled -}}
{{- $fullName := include "network-bootstrapper.fullname" . -}}
{{- $svcPort := .Values.service.port -}}
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: {{ $fullName }}
labels:
{{- include "network-bootstrapper.labels" . | nindent 4 }}
{{- with .Values.httpRoute.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
parentRefs:
{{- with .Values.httpRoute.parentRefs }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.httpRoute.hostnames }}
hostnames:
{{- toYaml . | nindent 4 }}
{{- end }}
rules:
{{- range .Values.httpRoute.rules }}
{{- with .matches }}
- matches:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .filters }}
filters:
{{- toYaml . | nindent 8 }}
{{- end }}
backendRefs:
- name: {{ $fullName }}
port: {{ $svcPort }}
weight: 1
{{- end }}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The current logic for rendering the rules in the HTTPRoute is incorrect. The list item marker - is inside the {{- with .matches }} block. This means if a rule is defined in values.yaml without a matches key, the template will render invalid YAML, as the list item will be missing its - marker. This will cause Helm installation to fail for valid configurations.

{{- range .Values.httpRoute.rules }}
- 
  {{- if .matches }}
  matches:
    {{- toYaml .matches | nindent 8 }}
  {{- end }}
  {{- if .filters }}
  filters:
    {{- toYaml .filters | nindent 8 }}
  {{- end }}
  backendRefs:
    - name: {{ $fullName }}
      port: {{ $svcPort }}
      weight: 1
{{- end }}

{{- end }}
43 changes: 43 additions & 0 deletions charts/network-bootstrapper/templates/ingress.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{{- if .Values.ingress.enabled -}}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "network-bootstrapper.fullname" . }}
labels:
{{- include "network-bootstrapper.labels" . | nindent 4 }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- with .Values.ingress.className }}
ingressClassName: {{ . }}
{{- end }}
{{- if .Values.ingress.tls }}
tls:
{{- range .Values.ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ .path }}
{{- with .pathType }}
pathType: {{ . }}
{{- end }}
backend:
service:
name: {{ include "network-bootstrapper.fullname" $ }}
port:
number: {{ $.Values.service.port }}
{{- end }}
{{- end }}
{{- end }}
15 changes: 15 additions & 0 deletions charts/network-bootstrapper/templates/service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "network-bootstrapper.fullname" . }}
labels:
{{- include "network-bootstrapper.labels" . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
name: http
selector:
{{- include "network-bootstrapper.selectorLabels" . | nindent 4 }}
13 changes: 13 additions & 0 deletions charts/network-bootstrapper/templates/serviceaccount.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "network-bootstrapper.serviceAccountName" . }}
labels:
{{- include "network-bootstrapper.labels" . | nindent 4 }}
{{- with .Values.serviceAccount.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
automountServiceAccountToken: {{ .Values.serviceAccount.automount }}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: AutomountServiceAccountToken may be omitted for default behavior.

Only render automountServiceAccountToken if .Values.serviceAccount.automount is defined to avoid empty fields in the output.

{{- end }}
Loading