Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
ba279a3
Pipelines are cool
espenwobbes Feb 12, 2026
32574a4
fix: now stores more data, refined repositories
espenwobbes Feb 12, 2026
5dfa651
chore: formatting
espenwobbes Feb 12, 2026
9cf4596
feat: storing more service information, need to fix override API endp…
espenwobbes Feb 16, 2026
e5bb19c
feat: saving state on shutdown, and registering new services with con…
espenwobbes Feb 16, 2026
27f39f1
feat: roundtrip time for service prioritization in a service group
espenwobbes Feb 17, 2026
b37e055
feat: shutdown functionality to preserve runtime state
espenwobbes Feb 17, 2026
041a826
pipelines, and fixed tests
espenwobbes Feb 19, 2026
b4d0a10
set fixed golang version
espenwobbes Feb 19, 2026
8741508
reposority ci-cd basically in place
espenwobbes Feb 19, 2026
fa2d050
started work for metrics collection
espenwobbes Feb 20, 2026
d48b53a
added charts and updated release pipeline
espenwobbes Feb 20, 2026
aebbf56
feat: helm-chart for deployment and release
espenwobbes Feb 20, 2026
1b1ab08
necessary changes for k8s deployment
espenwobbes Feb 24, 2026
8866df1
test version for k8s deployment
espenwobbes Feb 24, 2026
9846477
fix: permissions
espenwobbes Feb 24, 2026
21ff4bc
fix permissions in release pipeline
espenwobbes Feb 24, 2026
521f15f
fix: helmchart yq stuff
espenwobbes Feb 24, 2026
6479eb5
fix: helm commands again
espenwobbes Feb 24, 2026
0dcf2e7
fix: HELM
espenwobbes Feb 24, 2026
c3b37a7
HELM
espenwobbes Feb 24, 2026
57eb79c
fix: repository url for deployment image
espenwobbes Feb 25, 2026
dd8f1f4
fix: checking if file is directory before continuing in loading plain…
espenwobbes Feb 25, 2026
b1b9e0c
fix: Dockerfile permissions on sandbox, and helm (again)
espenwobbes Feb 25, 2026
d7382b3
fix: remove runasnonroot and runasuser handled in the Dockerfile instead
espenwobbes Feb 25, 2026
5c89111
helm deployment with test load to track resource metrics
espenwobbes Feb 25, 2026
22a9d21
feat: metrics collection for prometheus
espenwobbes Feb 26, 2026
d873dbd
feature: metrics collection
espenwobbes Feb 26, 2026
d138420
fix (servicegroup): correct locking on RemoveService
espenwobbes Feb 26, 2026
73b6dd5
fix: correct locking in service group remove service
espenwobbes Feb 26, 2026
fe3d7aa
fix(worker-pool): fixed locking when checking blocked queue
espenwobbes Feb 27, 2026
be959df
fix: worker pool scaling on high load
espenwobbes Feb 27, 2026
76a2ea0
feat: dnsdist updates directly from operator instead of HTTP - call t…
espenwobbes Mar 3, 2026
34cbd5f
Merge pull request #11 from vitistack/feature/dnsdist-updater
espenwobbes Mar 3, 2026
d05b939
fix (metrics): better label utilization on healthchecks
espenwobbes Mar 4, 2026
0175bd2
Merge pull request #12 from vitistack/fix/better-metrics
espenwobbes Mar 4, 2026
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
33 changes: 33 additions & 0 deletions .github/workflows/build_test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Build and Test

on:
push:
branches: ["main", "develop"]
pull_request:
branches: ["main", "develop"]

jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- name: checkout code
uses: actions/checkout@v4

- name: setup Go
uses: actions/setup-go@v5
with:
go-version: 1.25
cache: true
cache-dependency-path: go.sum

- name: install dependencies
run: go mod download

- name: build
run: |
#test version not in use for release
export VERSION=test-$(git rev-parse --short HEAD)
make build

- name: test
run: go test -v ./...
89 changes: 89 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
name: Release

on:
push:
tags:
- "v*"

permissions:
contents: read
packages: write

jobs:
create-oci-image:
runs-on: ubuntu-latest
steps:
- name: checkout code
uses: actions/checkout@v4

- name: Set up QEMU
uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/vitistack/gslb-operator
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=sha

- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Set release date
id: date
run: echo "DATE=$(date +%Y-%m-%d)" >> $GITHUB_OUTPUT

- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args: |
VERSION=${{ github.ref_name }}
DATE=${{ steps.date.outputs.DATE }}
platforms: linux/amd64,linux/arm64
cache-from: type=gha
cache-to: type=gha,mode=max
build-and-publish-helm-chart:
needs:
- create-oci-image
runs-on: ubuntu-latest
steps:
- name: checkout code
uses: actions/checkout@v4

- name: Install helm
uses: azure/setup-helm@v1
with:
version: v3.16.4

- name: install-yq
env:
VERSION: v4.44.5
BINARY: yq_linux_amd64
run: |
wget https://github.com/mikefarah/yq/releases/download/${VERSION}/${BINARY}.tar.gz -O - | tar xz && mv ${BINARY} yq && chmod +x yq

- name: build and push chart
env:
VERSION: ${{ github.ref_name }}
run: |
export HELM_VERSION=${VERSION#v*}
./yq e -i '.version = strenv(HELM_VERSION),.appVersion = strenv(VERSION)' charts/gslb-operator/Chart.yaml
./yq e -i '.image.tag = strenv(HELM_VERSION),.image.repository = "ncr.sky.nhn.no/ghcr/vitistack/gslb-operator"' charts/gslb-operator/values.yaml
helm package charts/gslb-operator
echo ${{ secrets.GITHUB_TOKEN }} | helm registry login -u ${{ github.actor }} ghcr.io --password-stdin
helm push gslb-operator-${HELM_VERSION}.tgz oci://ghcr.io/vitistack/helm/
2 changes: 1 addition & 1 deletion .github/workflows/security_scan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.

name: "Security Scan"
name: Security Scan

on:
push:
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
*.so
*.dylib

/bin

# Test binary, built with `go test -c`
*.test

Expand All @@ -26,6 +28,7 @@ go.work.sum

# env file
*.env
secrets

store.json
# Editor/IDE
Expand Down
33 changes: 33 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
FROM golang:1.26 AS build

LABEL MAINTAINER="espen.wobbes@nhn.no"

ARG VERSION
ARG DATE

WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download

COPY . .
# build image
RUN CGO_ENABLED=0 go build -ldflags "-s -w -X main.version=${VERSION} -X main.buildDate=${DATE}" -o gslb-operator ./cmd/main.go


FROM alpine:3.23

WORKDIR /app

RUN addgroup -S gslb-group && adduser -S gslb-operator -G gslb-group

COPY --from=build /app/gslb-operator /app/gslb-operator
COPY sandbox.lua /app

# change ownership of directory
RUN chown -R gslb-operator:gslb-group /app

# sandbox is read-only
RUN chmod 440 sandbox.lua
USER gslb-operator

CMD [ "./gslb-operator" ]
81 changes: 81 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
.PHONY: help
help: ## Display this help.
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)

# Variables
GO_VERSION := $(shell go version | cut -d' ' -f3)
DOCKER_COMPOSE := docker compose
HELM := helm
KUBECTL := kubectl
DATE := $(shell date +%Y-%m-%d)
VERSION ?= "test"


##@ Build
.PHONY: build run
build: check-tools ## Build the Go application.
@echo "Building GSLB - Operator binary..."
@echo "Version: $(VERSION)"
@echo "Date: $(DATE)"
@go build -ldflags "-s -w -X main.version=$(VERSION) -X main.buildDate=$(DATE)" -o ./bin/ ./cmd/main.go

run:
@echo "Running GSLB - Operator"
@go run -ldflags "-X main.version=0.0.0-test -X main.buildDate=$(DATE)" ./cmd/main.go

test: ## Run tests
@echo "Running tests..."
@go test -v ./...
@echo "Tests complete!"

deps: ## Download and verify dependencies
@echo "Downloading dependencies..."
@go mod download
@go mod verify
@go mod tidy
@echo "Dependencies updated!"

update-deps: ## Update dependencies
@echo "Updating dependencies..."
@go get -u ./...
@go mod tidy
@echo "Dependencies updated!"

##@ Code Quality
.PHONY: lint format security-scan bench
lint: ## Run Go linters
@echo "Running Go linters..."
@command -v golangci-lint >/dev/null 2>&1 || { echo "Installing golangci-lint..."; go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest; }
@golangci-lint run ./...
@echo "Linting complete!"

format: ## Format Go code
@echo "Formatting Go code..."
@go fmt ./...
@echo "Code formatted!"

go-security-scan: ## Run security scan
@echo "Running security scan..."
@command -v govulncheck >/dev/null 2>&1 || { echo "Installing govulncheck..."; go install golang.org/x/vuln/cmd/govulncheck@latest; }
@gosec ./...
@echo "Security scan complete!"

bench: ## Run benchmarks
@echo "Running benchmarks..."
@go test -bench=. -benchmem ./...
@echo "Benchmarks complete!"


##@ Tools
.PHONY: check-tools install-tools
# Check if required tools are installed
check-tools:
@command -v go >/dev/null 2>&1 || { echo "Go is required but not installed. Aborting." >&2; exit 1; }
@command -v docker >/dev/null 2>&1 || { echo "Docker is required but not installed. Aborting." >&2; exit 1; }
@command -v $(DOCKER_COMPOSE) >/dev/null 2>&1 || { echo "Docker Compose is required but not installed. Aborting." >&2; exit 1; }

install-tools: ## Install development tools
@echo "Installing development tools..."
@go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
@go install golang.org/x/vuln/cmd/govulncheck@latest;
@echo "Development tools installed!"
9 changes: 6 additions & 3 deletions TODOS.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@

- flags loader for config variables

- OnShutDown functions to save current state on shutdown
- OnShutDown functions to save current state on shutdown ✅
- expand to OnStart (unsure if this is necessary if handled correctly when registering services)

- If svc not in DC, then roundtrip decides priority
- AUTH

- AUTH
- Webhooks notifies on event?

- worker pool stats handling from manager
23 changes: 23 additions & 0 deletions charts/gslb-operator/.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/
27 changes: 27 additions & 0 deletions charts/gslb-operator/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
apiVersion: v2
name: gslb-operator
description: A Helm chart for Kubernetes

# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
# to be deployed.
#
# Library charts provide useful utilities or functions for the chart developer. They're included as
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
type: application

# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.1.0

# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: "1.16.0"

# Chart icon - displayed in Helm repository UIs like ArtifactHub
icon: https://vitistack.io/images/viti1.svg
29 changes: 29 additions & 0 deletions charts/gslb-operator/templates/NOTES.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
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.
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 contains "NodePort" .Values.service.type }}
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "gslb-operator.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 "gslb-operator.fullname" . }}'
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "gslb-operator.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 "gslb-operator.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 }}
Loading
Loading