Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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 .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ coverage.html
/galactic
/galactic-router
/galactic-cni
/galactic-tap-cni
/galactic-ipam
/galactic-bgp
/galactic-route

# Go workspace
go.work
Expand Down
1 change: 1 addition & 0 deletions Taskfile.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ tasks:
cmds:
- go build -ldflags "{{.LDFLAGS}}" -o bin/galactic-cni ./cmd/galactic-cni
- go build -ldflags "{{.LDFLAGS}}" -o bin/galactic-tap-cni ./cmd/galactic-tap-cni
- go build -ldflags "{{.LDFLAGS}}" -o bin/galactic-ipam ./cmd/galactic-ipam
- go build -ldflags "{{.LDFLAGS}}" -o bin/galactic-router ./cmd/galactic-router
- go build -ldflags "{{.LDFLAGS}}" -o bin/vmtap-cni ./cmd/vmtap-cni
- GOBIN={{.LOCALBIN}} go install github.com/containernetworking/plugins/plugins/main/host-device@v1.9.1
Expand Down
79 changes: 79 additions & 0 deletions cmd/galactic-ipam/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Copyright 2026 Datum Cloud, Inc.
//
// SPDX-License-Identifier: AGPL-3.0-or-later

package main

import (
"fmt"
"log"
"os"
"strings"

"github.com/containernetworking/cni/pkg/version"
"github.com/spf13/cobra"
"golang.org/x/term"

"go.datum.net/galactic/internal/cniipam"
"go.datum.net/galactic/internal/metadata"
)

const (
appName = "galactic-ipam"

appDesc = `Galactic IPAM CNI Plugin

The delegated CNI IPAM plugin in the galactic CNI chain — invoked by
galactic-cni/galactic-tap-cni's own "ipam" block via the CNI IPAM
delegation protocol (github.com/containernetworking/cni/pkg/ipam), never
run directly from a conflist. Has no Kubernetes dependency at all:
allocation state persists in on-disk marker files under this node's own
filesystem.

Find more information at: https://www.datum.net/docs`
)

func newRootCommand() *cobra.Command {
cmd := &cobra.Command{
Use: appName,
Short: strings.Split(appDesc, "\n")[0],
Long: appDesc,
RunE: func(cmd *cobra.Command, _ []string) error {
if ok, _ := cmd.Flags().GetBool("build-info"); ok {
fmt.Println(metadata.BuildInfo(appName))
return nil
}
if ok, _ := cmd.Flags().GetBool("version"); ok {
fmt.Printf("%s version %s\n", appName, metadata.Version)
return nil
}
if os.Getenv("CNI_COMMAND") == "VERSION" {
return version.All.Encode(os.Stdout)
}

// Real CNI runtimes (via IPAM delegation's ExecAdd/ExecDel/
// ExecCheck) always pipe the netconf JSON on stdin and close
// it. If stdin is an interactive terminal instead, no config
// will ever arrive and skel's blocking stdin read would hang
// forever — print version info instead.
if term.IsTerminal(int(os.Stdin.Fd())) {
fmt.Printf("%s version %s\n", appName, metadata.Version)
fmt.Printf("CNI protocol versions supported: %s\n", strings.Join(version.All.SupportedVersions(), ", "))
return nil
}

cniipam.RunPlugin()
return nil
},
}

cmd.Flags().Bool("build-info", false, "Print build information and exit")
cmd.Flags().BoolP("version", "V", false, "Print version and exit")
return cmd
}

func main() {
if err := newRootCommand().Execute(); err != nil {
log.Fatalf("error: %v", err)
}
}
15 changes: 15 additions & 0 deletions containers/galactic-cni/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,19 @@ RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build \
-X go.datum.net/galactic/internal/metadata.GitURL=${GIT_URL}" \
-o galactic-tap-cni cmd/galactic-tap-cni/main.go

# Build galactic-ipam, the delegated CNI IPAM plugin in the galactic CNI
# chain. Ships in this same image/binary set for the same reason
# galactic-tap-cni does — see its own comment above.
RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build \
-ldflags "-s -w \
-X go.datum.net/galactic/internal/metadata.Version=${VERSION} \
-X go.datum.net/galactic/internal/metadata.GitCommit=${GIT_COMMIT} \
-X go.datum.net/galactic/internal/metadata.GitTreeState=${GIT_TREE_STATE} \
-X go.datum.net/galactic/internal/metadata.BuildDate=${BUILD_DATE} \
-X go.datum.net/galactic/internal/metadata.SPDXLicense=${SPDX_LICENSE} \
-X go.datum.net/galactic/internal/metadata.GitURL=${GIT_URL}" \
-o galactic-ipam cmd/galactic-ipam/main.go

# Build vmtap-cni. It ships in this image rather than one of its own so the
# vmtap DaemonSet (config/vmtap/) can reference the same published
# ghcr.io/datum-cloud/galactic-cni image instead of a second, separately
Expand Down Expand Up @@ -97,6 +110,7 @@ FROM gcr.io/distroless/static:nonroot AS production
# Copy binaries from builder into the distroless production image
COPY --from=builder /workspace/galactic-cni /galactic-cni
COPY --from=builder /workspace/galactic-tap-cni /galactic-tap-cni
COPY --from=builder /workspace/galactic-ipam /galactic-ipam
COPY --from=builder /workspace/vmtap-cni /vmtap-cni
COPY --from=builder /workspace/host-device /host-device
COPY --from=builder /var/run/galactic-cni /var/run/galactic-cni
Expand All @@ -110,6 +124,7 @@ FROM docker.io/library/alpine:latest
# Copy binaries from the production (distroless) image
COPY --from=production /galactic-cni /galactic-cni
COPY --from=production /galactic-tap-cni /galactic-tap-cni
COPY --from=production /galactic-ipam /galactic-ipam
COPY --from=production /vmtap-cni /vmtap-cni
COPY --from=production /host-device /host-device
COPY --from=production /var/run/galactic-cni /var/run/galactic-cni
Expand Down
7 changes: 5 additions & 2 deletions deploy/containerlab/resources/tenants/ns10/dfw/nad.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ spec:
"vpc": "10",
"vpcattachment": "10",
"namespace": "galactic-system",
"ipv6_subnet": "fd20:10:ff01::/48",
"address_families": ["ipv6"]
"ipam": {
"type": "galactic-ipam",
"ipv6_subnet": "fd20:10:ff01::/48",
"address_families": ["ipv6"]
}
}
7 changes: 5 additions & 2 deletions deploy/containerlab/resources/tenants/ns10/iad/nad.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ spec:
"vpc": "10",
"vpcattachment": "10",
"namespace": "galactic-system",
"ipv6_subnet": "fd20:10:ff03::/48",
"address_families": ["ipv6"]
"ipam": {
"type": "galactic-ipam",
"ipv6_subnet": "fd20:10:ff03::/48",
"address_families": ["ipv6"]
}
}
7 changes: 5 additions & 2 deletions deploy/containerlab/resources/tenants/ns10/sjc/nad.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ spec:
"vpc": "10",
"vpcattachment": "10",
"namespace": "galactic-system",
"ipv6_subnet": "fd20:10:ff02::/48",
"address_families": ["ipv6"]
"ipam": {
"type": "galactic-ipam",
"ipv6_subnet": "fd20:10:ff02::/48",
"address_families": ["ipv6"]
}
}
9 changes: 6 additions & 3 deletions deploy/containerlab/resources/tenants/ns20/dfw/nad.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ spec:
"vpc": "20",
"vpcattachment": "20",
"namespace": "galactic-system",
"ipv6_subnet": "fd20:20:ff01::/48",
"ipv4_subnet": "172.21.1.0/24",
"address_families": ["ipv6", "ipv4"]
"ipam": {
"type": "galactic-ipam",
"ipv6_subnet": "fd20:20:ff01::/48",
"ipv4_subnet": "172.21.1.0/24",
"address_families": ["ipv6", "ipv4"]
}
}
9 changes: 6 additions & 3 deletions deploy/containerlab/resources/tenants/ns20/iad/nad.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ spec:
"vpc": "20",
"vpcattachment": "20",
"namespace": "galactic-system",
"ipv6_subnet": "fd20:20:ff03::/48",
"ipv4_subnet": "172.21.10.0/24",
"address_families": ["ipv6", "ipv4"]
"ipam": {
"type": "galactic-ipam",
"ipv6_subnet": "fd20:20:ff03::/48",
"ipv4_subnet": "172.21.10.0/24",
"address_families": ["ipv6", "ipv4"]
}
}
9 changes: 6 additions & 3 deletions deploy/containerlab/resources/tenants/ns20/sjc/nad.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ spec:
"vpc": "20",
"vpcattachment": "20",
"namespace": "galactic-system",
"ipv6_subnet": "fd20:20:ff02::/48",
"ipv4_subnet": "172.21.20.0/24",
"address_families": ["ipv6", "ipv4"]
"ipam": {
"type": "galactic-ipam",
"ipv6_subnet": "fd20:20:ff02::/48",
"ipv4_subnet": "172.21.20.0/24",
"address_families": ["ipv6", "ipv4"]
}
}
7 changes: 5 additions & 2 deletions deploy/containerlab/resources/tenants/ns30/dfw/nad.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ spec:
"vpc": "30",
"vpcattachment": "30",
"namespace": "galactic-system",
"ipv6_subnet": "fd20:30:ff01::/48",
"address_families": ["ipv6"]
"ipam": {
"type": "galactic-ipam",
"ipv6_subnet": "fd20:30:ff01::/48",
"address_families": ["ipv6"]
}
}
7 changes: 5 additions & 2 deletions deploy/containerlab/resources/tenants/ns40/iad/nad.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ spec:
"vpc": "40",
"vpcattachment": "40",
"namespace": "galactic-system",
"ipv4_subnet": "172.40.10.0/24",
"address_families": ["ipv4"]
"ipam": {
"type": "galactic-ipam",
"ipv4_subnet": "172.40.10.0/24",
"address_families": ["ipv4"]
}
}
7 changes: 5 additions & 2 deletions deploy/containerlab/resources/tenants/ns50/dfw/nad.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@ spec:
"vpc": "50",
"vpcattachment": "50",
"namespace": "galactic-system",
"ipv4_subnet": "172.20.1.0/24",
"address_families": ["ipv4"]
"ipam": {
"type": "galactic-ipam",
"ipv4_subnet": "172.20.1.0/24",
"address_families": ["ipv4"]
}
}

---
Expand Down
7 changes: 5 additions & 2 deletions deploy/containerlab/resources/tenants/ns50/iad/nad.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ spec:
"vpc": "50",
"vpcattachment": "50",
"namespace": "galactic-system",
"ipv4_subnet": "172.20.10.0/24",
"address_families": ["ipv4"]
"ipam": {
"type": "galactic-ipam",
"ipv4_subnet": "172.20.10.0/24",
"address_families": ["ipv4"]
}
}
7 changes: 5 additions & 2 deletions deploy/containerlab/resources/tenants/ns50/sjc/nad.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ spec:
"vpc": "50",
"vpcattachment": "50",
"namespace": "galactic-system",
"ipv4_subnet": "172.20.20.0/24",
"address_families": ["ipv4"]
"ipam": {
"type": "galactic-ipam",
"ipv4_subnet": "172.20.20.0/24",
"address_families": ["ipv4"]
}
}
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,11 @@ require (
github.com/onsi/gomega v1.39.1 // indirect
github.com/orcaman/concurrent-map/v2 v2.0.1 // indirect
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/common v0.67.5 // indirect
github.com/prometheus/procfs v0.19.2 // indirect
github.com/safchain/ethtool v0.6.2 // indirect
github.com/sagikazarmark/locafero v0.11.0 // indirect
github.com/segmentio/fasthash v1.0.3 // indirect
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect
Expand Down Expand Up @@ -96,6 +98,7 @@ require (
k8s.io/kube-openapi v0.0.0-20260317180543-43fb72c5454a // indirect
k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2 // indirect
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
sigs.k8s.io/knftables v0.0.18 // indirect
sigs.k8s.io/randfill v1.0.0 // indirect
sigs.k8s.io/structured-merge-diff/v6 v6.3.3 // indirect
sigs.k8s.io/yaml v1.6.0 // indirect
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ github.com/prometheus/procfs v0.19.2/go.mod h1:M0aotyiemPhBCM0z5w87kL22CxfcH05Zp
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/safchain/ethtool v0.6.2 h1:O3ZPFAKEUEfbtE6J/feEe2Ft7dIJ2Sy8t4SdMRiIMHY=
github.com/safchain/ethtool v0.6.2/go.mod h1:VS7cn+bP3Px3rIq55xImBiZGHVLNyBh5dqG6dDQy8+I=
github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc=
github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik=
github.com/segmentio/fasthash v1.0.3 h1:EI9+KE1EwvMLBWwjpRDc+fEM+prwxDYbslddQGtrmhM=
Expand Down Expand Up @@ -291,6 +293,8 @@ sigs.k8s.io/controller-runtime v0.24.1 h1:miPEwrmirImAvgME1L9qebGHrOnGJoVmVdtOU9
sigs.k8s.io/controller-runtime v0.24.1/go.mod h1:vFkfY5fGt5xAC/sKb8IBFKgWPNKG9OUG29dR8Y2wImw=
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg=
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
sigs.k8s.io/knftables v0.0.18 h1:6Duvmu0s/HwGifKrtl6G3AyAPYlWiZqTgS8bkVMiyaE=
sigs.k8s.io/knftables v0.0.18/go.mod h1:f/5ZLKYEUPUhVjUCg6l80ACdL7CIIyeL0DxfgojGRTk=
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
sigs.k8s.io/structured-merge-diff/v6 v6.3.2 h1:kwVWMx5yS1CrnFWA/2QHyRVJ8jM6dBA80uLmm0wJkk8=
Expand Down
8 changes: 0 additions & 8 deletions internal/cni/cni.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,11 @@ import (
"github.com/containernetworking/cni/pkg/skel"
"github.com/containernetworking/cni/pkg/version"

"go.datum.net/galactic/internal/cniipam"
"go.datum.net/galactic/internal/metadata"
)

const cniTimeout = 10 * time.Second

// SetEnableLocalIPAM sets the local IPAM flag from the CLI. Kept here as a
// thin forwarder so cmd/galactic-cni/main.go doesn't need to know that IPAM
// allocation itself now lives in internal/cniipam.
func SetEnableLocalIPAM(v bool) {
cniipam.SetEnableLocalIPAM(v)
}

// RunPlugin starts the CNI plugin, handling ADD, DEL, CHECK, and STATUS operations.
func RunPlugin() {
skel.PluginMainFuncs(
Expand Down
Loading