Skip to content

Commit 9d123af

Browse files
authored
Merge pull request #255 from datum-cloud/fix/cni-stdin-tty-hang
fix(cni): avoid hang on empty stdin, log CNI config in debug mode
2 parents 7180519 + f0554ea commit 9d123af

7 files changed

Lines changed: 27 additions & 203 deletions

File tree

cmd/galactic-cni/main.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515

1616
"github.com/containernetworking/cni/pkg/version"
1717
"github.com/spf13/cobra"
18+
"golang.org/x/term"
1819

1920
"go.datum.net/galactic/internal/cni"
2021
"go.datum.net/galactic/internal/installer"
@@ -93,6 +94,18 @@ func newRootCommand() *cobra.Command {
9394
return version.All.Encode(os.Stdout)
9495
}
9596

97+
// Real CNI runtimes (containerd, CRI-O) always pipe the network
98+
// config JSON on stdin and close it. If stdin is an interactive
99+
// terminal instead, no config will ever arrive, and both skel's
100+
// blocking stdin read and the io.ReadAll below would hang
101+
// forever. Detect that case up front and print version info
102+
// rather than hanging.
103+
if term.IsTerminal(int(os.Stdin.Fd())) {
104+
fmt.Printf("galactic-cni version %s\n", metadata.Version)
105+
fmt.Printf("CNI protocol versions supported: %s\n", strings.Join(version.All.SupportedVersions(), ", "))
106+
return nil
107+
}
108+
96109
// Read stdin once so we can inspect the CNI config before the
97110
// library runs its netns validation. We pipe the buffered bytes
98111
// back as os.Stdin so the CNI library can still read them.

docs/cni/configuration.md

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
(or any CNI manager), plus node-local settings resolved at runtime from the
55
conflist, environment variables, and (as a last resort) the Kubernetes API.
66

7-
> Last verified: 2026-07-16 against the current working tree of `internal/cni/config.go`
7+
> Last verified: 2026-07-24 against the current working tree of `internal/cni/config.go`
88
> and `internal/installer/installer.go`.
99
1010
## Runtime Configuration
@@ -102,7 +102,11 @@ the standard CNI `PluginConf` with Galactic-specific fields.
102102
| `ipam` | No* | `IPAM` | IP address management configuration (see IPAM sub-fields below). *Required unless `GALACTIC_CNI_ENABLE_LOCAL_IPAM` is set — applies identically in `veth` and `tap` mode. In `tap` mode `cmdAdd` (`internal/cni/ops_add.go`) calls `allocateIPAM` unconditionally (unlike `veth` mode, which checks first), so omitting both `ipam` and `GALACTIC_CNI_ENABLE_LOCAL_IPAM` currently produces a nil-pointer panic in `tap` mode rather than a clean validation error — always set one or the other for tap. |
103103

104104
Standard CNI fields (`cniVersion`, `name`, `dns`, `runtimeConfig`) are also
105-
supported via the embedded `types.PluginConf`.
105+
supported via the embedded `types.PluginConf`. `galactic-cni` declares support
106+
for the full CNI spec range (`version.All`, from `github.com/containernetworking/cni`
107+
v1.3.0 in `go.mod`) and returns CNI Result `1.0.0` (`type100`); generated
108+
configs (the installer's default conflist, Multus `NetworkAttachmentDefinition`
109+
manifests) use `"cniVersion": "1.0.0"`.
106110

107111
### Interface Types
108112

@@ -176,7 +180,7 @@ entry. Deleted in `cmdDel` in reverse order.
176180

177181
```json
178182
{
179-
"cniVersion": "0.3.1",
183+
"cniVersion": "1.0.0",
180184
"name": "galactic",
181185
"type": "galactic-cni",
182186
"vpc": "1",
@@ -193,7 +197,7 @@ from the built-in pool.
193197

194198
```json
195199
{
196-
"cniVersion": "0.3.1",
200+
"cniVersion": "1.0.0",
197201
"name": "testvpc",
198202
"type": "galactic-cni",
199203
"vpc": "10",
@@ -212,7 +216,7 @@ from the built-in pool.
212216

213217
```json
214218
{
215-
"cniVersion": "0.3.1",
219+
"cniVersion": "1.0.0",
216220
"name": "galactic",
217221
"type": "galactic-cni",
218222
"vpc": "1",
@@ -228,7 +232,7 @@ from the built-in pool.
228232

229233
```json
230234
{
231-
"cniVersion": "0.3.1",
235+
"cniVersion": "1.0.0",
232236
"name": "galactic",
233237
"type": "galactic-cni",
234238
"vpc": "1",
@@ -251,7 +255,7 @@ a link-local route via the host-side device.
251255

252256
```json
253257
{
254-
"cniVersion": "0.3.1",
258+
"cniVersion": "1.0.0",
255259
"name": "galactic-tap",
256260
"type": "galactic-cni",
257261
"vpc": "1",

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ require (
1515
github.com/vishvananda/netlink v1.3.2-0.20260629151558-4e35dc940f49
1616
go.datum.net/network v0.0.0-20260719211723-8caa91ab0b37
1717
golang.org/x/sys v0.47.0
18+
golang.org/x/term v0.42.0
1819
google.golang.org/grpc v1.82.1
1920
k8s.io/api v0.36.0
2021
k8s.io/apimachinery v0.36.1
@@ -78,7 +79,6 @@ require (
7879
golang.org/x/net v0.53.0 // indirect
7980
golang.org/x/oauth2 v0.36.0 // indirect
8081
golang.org/x/sync v0.20.0 // indirect
81-
golang.org/x/term v0.42.0 // indirect
8282
golang.org/x/text v0.36.0 // indirect
8383
golang.org/x/time v0.14.0 // indirect
8484
golang.org/x/tools v0.43.0 // indirect

go.sum

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,6 @@ github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zd
166166
github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
167167
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
168168
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
169-
go.datum.net/network v0.0.0-20260712201947-fb4e1e9705ba h1:6Ve/ao36q85Z5dLt7xHmozvQK67zuxs6p2byWWjsrcY=
170-
go.datum.net/network v0.0.0-20260712201947-fb4e1e9705ba/go.mod h1:dqzM8WZczbiZ9bCvsxjkoI10GJqQ24NVWnc9boXgOkE=
171169
go.datum.net/network v0.0.0-20260719211723-8caa91ab0b37 h1:KldPQuababwYJyw3KToFIPaIfKyjMYbBLE9kTHVtBNM=
172170
go.datum.net/network v0.0.0-20260719211723-8caa91ab0b37/go.mod h1:dqzM8WZczbiZ9bCvsxjkoI10GJqQ24NVWnc9boXgOkE=
173171
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
@@ -212,8 +210,6 @@ golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
212210
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
213211
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
214212
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
215-
golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw=
216-
golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
217213
golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=
218214
golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
219215
golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY=
@@ -235,8 +231,6 @@ gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
235231
gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=
236232
google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478 h1:RmoJA1ujG+/lRGNfUnOMfhCy5EipVMyvUE+KNbPbTlw=
237233
google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
238-
google.golang.org/grpc v1.82.0 h1:vguDnZUPjE26w09A63VoxZPnvPjB5Riyc0mkXPFmAIU=
239-
google.golang.org/grpc v1.82.0/go.mod h1:yzTZ1TB1Z3SG+LIYaI+WiE8D5+PZ3ArnrSp8zF3+/ZA=
240234
google.golang.org/grpc v1.82.1 h1:NnAxzGRA0677vCa4BUkOAnO5+FfQqVl9iUXeD0IqcGE=
241235
google.golang.org/grpc v1.82.1/go.mod h1:yzTZ1TB1Z3SG+LIYaI+WiE8D5+PZ3ArnrSp8zF3+/ZA=
242236
google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af h1:+5/Sw3GsDNlEmu7TfklWKPdQ0Ykja5VEmq2i817+jbI=

internal/cni/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,7 @@ func parseConf(data []byte) (*PluginConf, error) {
387387

388388
// Setup Logging
389389
setupLogging(cniConfig.LogFile, cniConfig.LogLevel)
390+
slog.Debug("CNI config received", "stdin", string(data))
390391

391392
// Resolve local IPAM flag
392393
enableLocalIPAM = config.CNIGetEnableLocalIPAM()

internal/cni/ops_check.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ func cmdStatus(args *skel.CmdArgs) error {
110110

111111
// Setup Logging
112112
setupLogging(cniConfig.LogFile, cniConfig.LogLevel)
113+
slog.Debug("CNI config received", "stdin", string(args.StdinData))
113114

114115
// Config is parseable and API server is reachable.
115116
slog.Info("STATUS: probing API server reachability")

internal/cni/plan.md

Lines changed: 0 additions & 189 deletions
This file was deleted.

0 commit comments

Comments
 (0)