1
2
3 package envtest
4
5 import (
6 "errors"
7 "flag"
8 "fmt"
9 "os"
10 "path/filepath"
11 "time"
12
13 "github.com/bazelbuild/rules_go/go/runfiles"
14 v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
15 "sigs.k8s.io/controller-runtime/pkg/envtest"
16
17 "edge-infra.dev/pkg/lib/build/bazel"
18 "edge-infra.dev/test/f2/integration"
19 "edge-infra.dev/test/fixtures"
20 )
21
22
23 type Environment = envtest.Environment
24
25 var (
26 ControlPlaneStartTimeout time.Duration
27 ControlPlaneStopTimeout time.Duration
28 AttachControlPlaneOutput bool
29 )
30
31 func BindFlags(fs *flag.FlagSet) {
32 fs.DurationVar(&ControlPlaneStartTimeout,
33 "envtest-start-timeout",
34 time.Second*60,
35 "timeout for envtest control plane to start up",
36 )
37 fs.DurationVar(&ControlPlaneStopTimeout,
38 "envtest-stop-timeout",
39 time.Second*60,
40 "timeout for envtest control plane to shut down",
41 )
42 fs.BoolVar(&AttachControlPlaneOutput,
43 "envtest-attach-control-plane-output",
44 false,
45 "whether or not to attach kube-apiserver + etcd output to test output",
46 )
47 }
48
49
50
51
52
53 func SetupEnvtestTools() error {
54 return errors.Join(
55 maybeSetEnv("TEST_ASSET_ETCD", "etcd", "hack/tools/etcd"),
56 maybeSetEnv("TEST_ASSET_KUBE_APISERVER", "kube-apiserver", "hack/tools/kube-apiserver"),
57 maybeSetEnv("TEST_ASSET_KUBECTL", "kubectl", "hack/tools/kubectl"),
58 )
59 }
60
61 func maybeSetEnv(key, bin, runfilePath string) error {
62
63
64
65 if os.Getenv(key) != "" || os.Getenv("KUBEBUILDER_ASSETS") != "" {
66 return nil
67 }
68 if !bazel.IsBazelTest() {
69 return fmt.Errorf(`failed to find integration test dependency %q.
70 Either re-run this test using "bazel test" or set the %s environment variable`, bin, key)
71 }
72 p, err := runfiles.Rlocation(filepath.Join(os.Getenv(bazel.TestWorkspace), runfilePath))
73 if err != nil {
74 return fmt.Errorf("failed to look up test dependency %q: %w. ensure that "+
75 "it is present in this test targets 'data' attribute", bin, err)
76 }
77 os.Setenv(key, p)
78 return nil
79 }
80
81
82 type Option func(*envtestOpts)
83
84 type envtestOpts struct {
85 loadCRDs bool
86 }
87
88
89
90 func WithoutCRDs() Option {
91 return func(o *envtestOpts) {
92 o.loadCRDs = false
93 }
94 }
95
96
97
98
99
100
101 func New(opts ...Option) (*envtest.Environment, error) {
102 o := envtestOpts{loadCRDs: true}
103 for _, opt := range opts {
104 opt(&o)
105 }
106
107 crds := []*v1.CustomResourceDefinition{}
108
109 if o.loadCRDs {
110 var err error
111 crds, err = loadCRDs()
112 if err != nil {
113 return nil, err
114 }
115 }
116
117 n := false
118 env := &envtest.Environment{
119 CRDs: crds,
120 ControlPlaneStartTimeout: ControlPlaneStartTimeout,
121 ControlPlaneStopTimeout: ControlPlaneStopTimeout,
122 AttachControlPlaneOutput: AttachControlPlaneOutput,
123 UseExistingCluster: &n,
124 }
125
126 if integration.IsL2() {
127 y := true
128 env.UseExistingCluster = &y
129 }
130
131 return env, nil
132 }
133
134
135
136
137
138
139 func loadCRDs() ([]*v1.CustomResourceDefinition, error) {
140 if integration.IsL2() {
141 return fixtures.LoadCRDs(fixtures.Only("edge"))
142 }
143 return fixtures.LoadCRDs()
144 }
145
146
147
148 func Setup(opts ...Option) (*envtest.Environment, error) {
149
150
151
152 if err := SetupEnvtestTools(); err != nil {
153 return nil, err
154 }
155
156
157 testEnv, err := New(opts...)
158 if err != nil {
159 return nil, fmt.Errorf("failed to create envtest Environment: %w", err)
160 }
161
162 _, err = testEnv.Start()
163 if err != nil {
164 return nil, fmt.Errorf("failed to start envtest Environment: %w", err)
165 }
166
167
168
169 testEnv.Config.Timeout = 20 * time.Second
170
171 return testEnv, nil
172 }
173
View as plain text