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
91 changes: 91 additions & 0 deletions pkg/crd/issue1063_alias_not_directly_imported_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package crd_test
Copy link
Member

Choose a reason for hiding this comment

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

Sorry not sure I follow why this test cannot be added like all our other tests

Copy link
Author

Choose a reason for hiding this comment

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

Thanks for taking a look! The only reason this test runs controller-gen from pkg/crd/testdata is that pkg/crd/testdata is its own Go module (module testdata.kubebuilder.io/cronjob in pkg/crd/testdata/go.mod).

The repro packages live under that module (testdata.kubebuilder.io/cronjob/issue1063/...). If the test runs controller-gen with cmd.Dir set to the repo root (main module), go/packages ends up trying to resolve those imports from the main module and fails with “no required module provides package …/issue1063/repro2”. Running from the testdata module root makes the imports resolve exactly as intended and matches how this repository already structures other fixtures under pkg/crd/testdata.

I can add a short comment in the test explaining this (pkg/crd/testdata is a separate module; run controller-gen from there so package resolution uses that go.mod) if that helps readability.

If you prefer a different pattern that keeps cmd.Dir at repo root (e.g. setting GOMOD/-C), I’m happy to adjust, but I wasn’t able to make that work reliably with go/packages without executing inside the testdata module.

Copy link
Member

Choose a reason for hiding this comment

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

I was just naively wondering what makes this test different from the ones in parser_integration_test.go


import (
"bytes"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"testing"
)

// repoRoot walks up from this test file until it finds the repository go.mod.
func repoRoot(t *testing.T) string {
t.Helper()

_, thisFile, _, ok := runtime.Caller(0)
if !ok {
t.Fatal("runtime.Caller failed")
}
dir := filepath.Dir(thisFile)

for {
if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil {
return dir
}
parent := filepath.Dir(dir)
if parent == dir {
t.Fatalf("could not find go.mod walking up from %s", thisFile)
}
dir = parent
}
}

func buildControllerGen(t *testing.T, root string) string {
t.Helper()

bin := filepath.Join(t.TempDir(), "controller-gen")
cmd := exec.Command("go", "build", "-o", bin, "./cmd/controller-gen")
cmd.Dir = root

var stderr bytes.Buffer
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
t.Fatalf("failed to build controller-gen: %v\nstderr:\n%s", err, stderr.String())
}
return bin
}

func TestIssue1063_AliasToPackageNotDirectlyImported(t *testing.T) {
root := repoRoot(t)
bin := buildControllerGen(t, root)

fixtureRoot := filepath.Join(root, "pkg", "crd", "testdata")
repro1Rel := "./issue1063/repro1"

cmd := exec.Command(bin,
"crd",
"paths="+repro1Rel,
"output:crd:stdout",
)
// Run within the testdata module (module testdata.kubebuilder.io/cronjob).
cmd.Dir = fixtureRoot

var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr

err := cmd.Run()
if err != nil {
t.Fatalf("controller-gen failed: %v\nstderr:\n%s\nstdout:\n%s", err, stderr.String(), stdout.String())
}

out := stdout.String()
errOut := stderr.String()

if strings.Contains(errOut, "panic:") {
t.Fatalf("unexpected panic output:\n%s", errOut)
}

if !strings.Contains(out, "kind: CustomResourceDefinition") {
t.Fatalf("expected CRD output, got:\n%s", out)
}

// The struct field is `Repro string `json:"repro"``, so YAML schema should mention `repro:`.
if !strings.Contains(out, "\n repro:\n") &&
!strings.Contains(out, "\n repro:\n") &&
!strings.Contains(out, "\n repro:\n") {
t.Fatalf("expected schema to include 'repro' property, got:\n%s", out)
}
}
4 changes: 4 additions & 0 deletions pkg/crd/testdata/issue1063/repro1/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Package repro1 contains API Schema definitions.
// +kubebuilder:object:generate=true
// +groupName=repro.io
package repro1
27 changes: 27 additions & 0 deletions pkg/crd/testdata/issue1063/repro1/repro1.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package repro1

import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"testdata.kubebuilder.io/cronjob/issue1063/repro2"
)

// +kubebuilder:object:root=true
// +kubebuilder:resource:scope=Namespaced,path=reproes
type Repro struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Spec ReproSpec `json:"spec,omitempty"`
}

type ReproSpec struct {
Reproducer repro2.MyReproAlias `json:"reproducer"`
}

// +kubebuilder:object:root=true
type ReproList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []Repro `json:"items"`
}
5 changes: 5 additions & 0 deletions pkg/crd/testdata/issue1063/repro2/repro2.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package repro2

import "testdata.kubebuilder.io/cronjob/issue1063/repro3"

type MyReproAlias = repro3.MyReproStruct
5 changes: 5 additions & 0 deletions pkg/crd/testdata/issue1063/repro3/repro3.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package repro3

type MyReproStruct struct {
Repro string `json:"repro"`
}