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
25 changes: 4 additions & 21 deletions cmd/ateapi/internal/controlapi/functional_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ import (
"github.com/agent-substrate/substrate/cmd/ateapi/internal/store/ateredis"
"github.com/agent-substrate/substrate/cmd/ateapi/internal/workercache"
"github.com/agent-substrate/substrate/internal/ateinterceptors"
"github.com/agent-substrate/substrate/internal/envtestbins"
"github.com/agent-substrate/substrate/internal/proto/ateletpb"
"github.com/agent-substrate/substrate/internal/resources"
"github.com/agent-substrate/substrate/internal/testenv"
"github.com/agent-substrate/substrate/internal/volume"
atev1alpha1 "github.com/agent-substrate/substrate/pkg/api/v1alpha1"
"github.com/agent-substrate/substrate/pkg/client/clientset/versioned"
Expand Down Expand Up @@ -61,11 +61,9 @@ import (
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/utils/ptr"
"sigs.k8s.io/controller-runtime/pkg/envtest"
)

var (
testEnv *envtest.Environment
cfg *rest.Config
fakeAtelet = &FakeAteletServer{}
)
Expand All @@ -82,20 +80,8 @@ var (
)

func TestMain(m *testing.M) {
binaryAssetsDirectory, err := envtestbins.BinaryAssetsDir()
if err != nil {
log.Fatalf("%v", err)
}

testEnv = &envtest.Environment{
CRDDirectoryPaths: []string{"../../../../manifests/ate-install/generated"},
BinaryAssetsDirectory: binaryAssetsDirectory,
}

cfg, err = testEnv.Start()
if err != nil {
log.Fatalf("testEnv.Start: %v", err)
}
var stopEnv func()
cfg, stopEnv = testenv.Start()

// Create ate-system namespace
k8sClient, err := kubernetes.NewForConfig(cfg)
Expand Down Expand Up @@ -155,10 +141,7 @@ func TestMain(m *testing.M) {

ateletGrpcServer.Stop()

err = testEnv.Stop()
if err != nil {
log.Fatalf("testEnv.Stop: %v", err)
}
stopEnv()

os.Exit(code)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,41 +35,26 @@ import (
"k8s.io/client-go/util/retry"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/envtest"
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"

"github.com/agent-substrate/substrate/internal/envtestbins"
"github.com/agent-substrate/substrate/internal/testenv"
atev1alpha1 "github.com/agent-substrate/substrate/pkg/api/v1alpha1"
)

var (
testEnv *envtest.Environment
cfg *rest.Config
k8sClient client.Client
)

func TestMain(m *testing.M) {
binaryAssetsDirectory, err := envtestbins.BinaryAssetsDir()
if err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
}

testEnv = &envtest.Environment{
CRDDirectoryPaths: []string{"../../../../manifests/ate-install/generated"},
BinaryAssetsDirectory: binaryAssetsDirectory,
}

cfg, err = testEnv.Start()
if err != nil {
fmt.Fprintf(os.Stderr, "envtest start failed: %v\n", err)
os.Exit(1)
}
var stopEnv func()
cfg, stopEnv = testenv.Start()

scheme := runtime.NewScheme()
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
utilruntime.Must(atev1alpha1.AddToScheme(scheme))

var err error
k8sClient, err = client.New(cfg, client.Options{Scheme: scheme})
if err != nil {
fmt.Fprintf(os.Stderr, "k8s client creation failed: %v\n", err)
Expand Down Expand Up @@ -110,7 +95,7 @@ func TestMain(m *testing.M) {
code := m.Run()

mgrCancel()
_ = testEnv.Stop()
stopEnv()
os.Exit(code)
}

Expand Down
2 changes: 1 addition & 1 deletion hack/run-tool.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ fi
TOOL_NAME="$1"
shift

ROOT="$(git rev-parse --show-toplevel)"
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Why this change?

case "${TOOL_NAME}" in
"client-gen"|"informer-gen"|"lister-gen")
TOOL_DIR="${ROOT}/hack/tools/code-generator"
Expand Down
89 changes: 75 additions & 14 deletions internal/envtestbins/envtestbins.go → internal/testenv/testenv.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,73 @@
// See the License for the specific language governing permissions and
// limitations under the License.

// Package envtestbins resolves the shared envtest (kubebuilder) binary assets
package envtestbins
// Package testenv starts the envtest (kubebuilder) control plane shared by
// the repo's apiserver-backed test packages.
package testenv

import (
"flag"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
"syscall"
"testing"

"k8s.io/client-go/rest"
"sigs.k8s.io/controller-runtime/pkg/envtest"
)

// BinaryAssetsDir resolves the envtest (kubebuilder) binary assets directory,
// kubeVersion pins the envtest control plane to the newest *installed* 1.36
// patch, downloading one only on a cold cache. Keep the minor in
// step with k8s.io/* in go.mod.
const kubeVersion = "1.36.x"

// Start launches a kube-apiserver+etcd pair with the repo CRDs installed and
// returns a client config plus a stop function. Call it from TestMain.
//
// Under -short it exits the test binary with success instead: a cold binary
// cache needs a download, so `go test -short ./...` always works offline.
func Start() (*rest.Config, func()) {
if !flag.Parsed() {
flag.Parse()
}
if testing.Short() {
fmt.Fprintln(os.Stderr, "skipping envtest-backed package in -short mode")
os.Exit(0)
}

root, err := repoRoot()
if err != nil {
fatal(err)
}
binDir, err := binaryAssetsDir(root)
if err != nil {
fatal(err)
}

env := &envtest.Environment{
CRDDirectoryPaths: []string{filepath.Join(root, "manifests", "ate-install", "generated")},
BinaryAssetsDirectory: binDir,
}
cfg, err := env.Start()
if err != nil {
fatal(fmt.Errorf("envtest start: %w", err))
}
return cfg, func() {
if err := env.Stop(); err != nil {
fmt.Fprintf(os.Stderr, "envtest stop: %v\n", err)
}
}
}

func fatal(err error) {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
}

// binaryAssetsDir resolves the envtest (kubebuilder) binary assets directory,
// downloading it on first use via `setup-envtest`, and returns its path.
//
// The setup is guarded by a cross-process file lock. `go test ./...` runs the
Expand All @@ -36,24 +90,20 @@ import (
// failing with "fork/exec .../etcd: text file busy" or "unable to create file
// ... from archive". Serializing the first download makes later callers hit a
// warm cache (a no-op path lookup).
func BinaryAssetsDir() (string, error) {
root, err := repoRoot()
if err != nil {
return "", err
}

func binaryAssetsDir(root string) (string, error) {
unlock, err := lockEnvtestSetup()
if err != nil {
return "", err
}
defer unlock()

cmd := exec.Command("bash", filepath.Join(root, "hack", "run-tool.sh"), "setup-envtest", "use", "--print", "path")
cmd := exec.Command("bash", filepath.Join(root, "hack", "run-tool.sh"),
"setup-envtest", "use", kubeVersion, "--print", "path")
var stderr strings.Builder
cmd.Stderr = &stderr
out, err := cmd.Output()
if err != nil {
return "", fmt.Errorf("setup-envtest: %w (stderr: %s)", err, stderr.String())
return "", fmt.Errorf("setup-envtest: %w (stderr: %s) — offline with no cached binaries? `go test -short ./...` skips envtest-backed packages", err, stderr.String())
}
return strings.TrimSpace(string(out)), nil
}
Expand Down Expand Up @@ -84,10 +134,21 @@ func lockEnvtestSetup() (func(), error) {
}, nil
}

// repoRoot walks up from the CWD (the package directory, under `go test`) to
// the directory holding go.mod.
func repoRoot() (string, error) {
out, err := exec.Command("git", "rev-parse", "--show-toplevel").Output()
dir, err := os.Getwd()
if err != nil {
return "", fmt.Errorf("finding repo root for envtest setup: %w", err)
return "", fmt.Errorf("finding repo root: %w", err)
}
for {
if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil {
return dir, nil
}
parent := filepath.Dir(dir)
if parent == dir {
return "", fmt.Errorf("finding repo root: no go.mod above %s", dir)
}
dir = parent
}
return strings.TrimSpace(string(out)), nil
}
28 changes: 6 additions & 22 deletions pkg/api/v1alpha1/actortemplate_validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
"testing"
"time"

"github.com/agent-substrate/substrate/internal/envtestbins"
"github.com/agent-substrate/substrate/internal/testenv"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand All @@ -32,48 +32,32 @@ import (
"k8s.io/utils/ptr"

"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/envtest"
)

var (
testEnv *envtest.Environment
cfg *rest.Config
k8sClient client.Client
)

func TestMain(m *testing.M) {
binaryAssetsDirectory, err := envtestbins.BinaryAssetsDir()
if err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
}

testEnv = &envtest.Environment{
CRDDirectoryPaths: []string{"../../../manifests/ate-install/generated"},
BinaryAssetsDirectory: binaryAssetsDirectory,
}

cfg, err = testEnv.Start()
if err != nil {
fmt.Fprintf(os.Stderr, "envtest start failed: %v\n", err)
testEnv.Stop()
os.Exit(1)
}
var stopEnv func()
cfg, stopEnv = testenv.Start()

scheme := runtime.NewScheme()
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
utilruntime.Must(AddToScheme(scheme))

var err error
k8sClient, err = client.New(cfg, client.Options{Scheme: scheme})
if err != nil {
fmt.Fprintf(os.Stderr, "k8s client creation failed: %v\n", err)
testEnv.Stop()
stopEnv()
os.Exit(1)
}

code := m.Run()

_ = testEnv.Stop()
stopEnv()
os.Exit(code)
}

Expand Down
Loading