Skip to content
Merged
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
22 changes: 14 additions & 8 deletions pkg/cni/cni_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"log/slog"
"os"
"path/filepath"
"runtime"
)

//go:embed all:embed
Expand Down Expand Up @@ -79,21 +80,26 @@ func (m *Manager) Extract() error {
return nil
}

// findTarball selects the CNI plugins archive matching this binary's arch.
// The macOS build cross-compiles ephemerd-linux for arm64, but the embed dir
// can hold BOTH cni-plugins-linux-amd64 and -arm64 (the amd64 one lingers
// from the CI cache). `//go:embed all:embed` then bundles both, so a naive
// "first entry" pick returns amd64 and the arm64 Linux VM fails every CNI
// exec with "exec format error". Select by runtime.GOARCH instead.
func (m *Manager) findTarball() (string, error) {
entries, err := cniFS.ReadDir("embed")
if err != nil {
return "", fmt.Errorf("reading embedded files: %w", err)
}

names := make([]string, 0, len(entries))
for _, e := range entries {
name := e.Name()
if name == ".gitkeep" {
continue
}
return filepath.Join("embed", name), nil
names = append(names, e.Name())
}

return "", fmt.Errorf("no CNI plugins archive found in embedded files (did you run 'make download-cni'?)")
name, err := selectCNITarball(names, runtime.GOARCH)
if err != nil {
return "", err
}
return filepath.Join("embed", name), nil
}

func extractTarGz(r io.Reader, dest string) error {
Expand Down
30 changes: 30 additions & 0 deletions pkg/cni/select.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package cni

import (
"fmt"
"strings"
)

// selectCNITarball picks the CNI plugins archive matching goarch from the
// embed listing. The macOS build cross-compiles ephemerd-linux for arm64 but
// the embed dir can hold BOTH cni-plugins-linux-amd64 and -arm64 (the amd64
// one lingers from the CI cache). `//go:embed all:embed` then bundles both,
// so a naive "first entry" pick returns amd64 and the arm64 Linux VM fails
// every CNI exec with "exec format error". Select by arch instead.
func selectCNITarball(names []string, goarch string) (string, error) {
want := "cni-plugins-linux-" + goarch + "-"
var found []string
for _, name := range names {
if name == ".gitkeep" {
continue
}
found = append(found, name)
if strings.HasPrefix(name, want) {
return name, nil
}
}
if len(found) == 0 {
return "", fmt.Errorf("no CNI plugins archive found in embedded files (did you run the download targets?)")
}
return "", fmt.Errorf("no CNI plugins archive for linux/%s in embedded files (have: %s)", goarch, strings.Join(found, ", "))
}
39 changes: 39 additions & 0 deletions pkg/cni/select_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package cni

import "testing"

func TestSelectCNITarball(t *testing.T) {
both := []string{"cni-plugins-linux-amd64-v1.6.2.tgz", "cni-plugins-linux-arm64-v1.6.2.tgz"}

tests := []struct {
name string
names []string
goarch string
want string
wantErr bool
}{
{"arm64 picks arm64 from both", both, "arm64", "cni-plugins-linux-arm64-v1.6.2.tgz", false},
{"amd64 picks amd64 from both", both, "amd64", "cni-plugins-linux-amd64-v1.6.2.tgz", false},
{"amd64 alone", both[:1], "amd64", "cni-plugins-linux-amd64-v1.6.2.tgz", false},
{"skips gitkeep", []string{".gitkeep", "cni-plugins-linux-arm64-v1.6.2.tgz"}, "arm64", "cni-plugins-linux-arm64-v1.6.2.tgz", false},
{"no match errors", both[:1], "arm64", "", true},
{"empty errors", []string{".gitkeep"}, "arm64", "", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := selectCNITarball(tt.names, tt.goarch)
if tt.wantErr {
if err == nil {
t.Fatalf("expected error, got %q", got)
}
return
}
if err != nil {
t.Fatal(err)
}
if got != tt.want {
t.Errorf("got %q, want %q", got, tt.want)
}
})
}
}