Skip to content

Commit 275d18a

Browse files
✨ allow pass the assets path via the enviroment config
1 parent bd97e08 commit 275d18a

File tree

1 file changed

+76
-32
lines changed

1 file changed

+76
-32
lines changed

pkg/envtest/server.go

Lines changed: 76 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -43,33 +43,56 @@ It's possible to override some defaults, by setting the following environment va
4343
KUBEBUILDER_CONTROLPLANE_START_TIMEOUT (string supported by time.ParseDuration): timeout for test control plane to start. Defaults to 20s.
4444
KUBEBUILDER_CONTROLPLANE_STOP_TIMEOUT (string supported by time.ParseDuration): timeout for test control plane to start. Defaults to 20s.
4545
KUBEBUILDER_ATTACH_CONTROL_PLANE_OUTPUT (boolean): if set to true, the control plane's stdout and stderr are attached to os.Stdout and os.Stderr
46-
4746
*/
4847
const (
49-
envUseExistingCluster = "USE_EXISTING_CLUSTER"
50-
envKubeAPIServerBin = "TEST_ASSET_KUBE_APISERVER"
51-
envEtcdBin = "TEST_ASSET_ETCD"
52-
envKubectlBin = "TEST_ASSET_KUBECTL"
53-
envKubebuilderPath = "KUBEBUILDER_ASSETS"
54-
envStartTimeout = "KUBEBUILDER_CONTROLPLANE_START_TIMEOUT"
55-
envStopTimeout = "KUBEBUILDER_CONTROLPLANE_STOP_TIMEOUT"
56-
envAttachOutput = "KUBEBUILDER_ATTACH_CONTROL_PLANE_OUTPUT"
57-
defaultKubebuilderPath = "/usr/local/kubebuilder/bin"
58-
StartTimeout = 60
59-
StopTimeout = 60
60-
48+
envUseExistingClusterEnvVar = "USE_EXISTING_CLUSTER"
49+
envKubeAPIServerBinEnvVar = "TEST_ASSET_KUBE_APISERVER"
50+
envEtcdBinEnvVar = "TEST_ASSET_ETCD"
51+
envKubectlBinEnvVar = "TEST_ASSET_KUBECTL"
52+
envKubebuilderPathEnvVar = "KUBEBUILDER_ASSETS"
53+
envStartTimeoutEnvVar = "KUBEBUILDER_CONTROLPLANE_START_TIMEOUT"
54+
envStopTimeoutEnvVar = "KUBEBUILDER_CONTROLPLANE_STOP_TIMEOUT"
55+
envAttachOutputEnvVar = "KUBEBUILDER_ATTACH_CONTROL_PLANE_OUTPUT"
56+
57+
// Default values
58+
defaultKubebuilderPath = "/usr/local/kubebuilder/bin"
59+
StartTimeout = 60
60+
StopTimeout = 60
6161
defaultKubebuilderControlPlaneStartTimeout = 20 * time.Second
6262
defaultKubebuilderControlPlaneStopTimeout = 20 * time.Second
63+
64+
// required binaries to run env test
65+
kubeApiserverBinName = "kube-apiserver"
66+
etcdBinName = "etcd"
67+
kubectlBinName = "kubectl"
6368
)
6469

65-
// Default binary path for test framework
66-
func defaultAssetPath(binary string) string {
67-
assetPath := os.Getenv(envKubebuilderPath)
68-
if assetPath == "" {
69-
assetPath = defaultKubebuilderPath
70+
// getBinAssetPath will return the path for the binary informed or an error if not be possible.
71+
// to fid the bin. It will try first check if the bin exists in the path informed then if not,
72+
// it will be looking for to try find the bin in the other config options as in the default path.
73+
func (te *Environment) getBinAssetPath(binary, path string) (string, error) {
74+
// If found the bin in the path informed return this path
75+
if strings.TrimSpace(path) != "" && hasBinary(binary, path) {
76+
return filepath.Join(path, binary), nil
7077
}
71-
return filepath.Join(assetPath, binary)
7278

79+
// If a Binary directory as informed in the EnvTest setup try to get the bin from it
80+
if strings.TrimSpace(te.BinaryDirectoryPath) != "" && hasBinary(binary, te.BinaryDirectoryPath) {
81+
return filepath.Join(te.BinaryDirectoryPath, binary), nil
82+
}
83+
84+
// If envKubebuilderPathEnvVar was set via ENV VAR then check if the bin can be found there
85+
valueFromEnvVar := os.Getenv(envKubebuilderPathEnvVar)
86+
if strings.TrimSpace(valueFromEnvVar) != "" && hasBinary(binary, valueFromEnvVar) {
87+
return filepath.Join(valueFromEnvVar, binary), nil
88+
}
89+
90+
// Check if the bin can be found in the default path
91+
if hasBinary(binary, defaultKubebuilderPath) {
92+
return filepath.Join(defaultKubebuilderPath, binary), nil
93+
}
94+
95+
return "", fmt.Errorf("unable to found the required binary %v", binary)
7396
}
7497

7598
// ControlPlane is the re-exported ControlPlane type from the internal integration package
@@ -113,6 +136,10 @@ type Environment struct {
113136
// values are merged.
114137
CRDDirectoryPaths []string
115138

139+
// BinaryDirectoryPath is the path where the binaries required for the envtest are
140+
// locate in the environment
141+
BinaryDirectoryPath string
142+
116143
// UseExisting indicates that this environments should use an
117144
// existing kubeconfig, instead of trying to stand up a new control plane.
118145
// This is useful in cases that need aggregated API servers and the like.
@@ -200,7 +227,7 @@ func (te *Environment) Start() (*rest.Config, error) {
200227
te.ControlPlane.Etcd = &integration.Etcd{}
201228
}
202229

203-
if os.Getenv(envAttachOutput) == "true" {
230+
if os.Getenv(envAttachOutputEnvVar) == "true" {
204231
te.AttachControlPlaneOutput = true
205232
}
206233
if te.ControlPlane.APIServer.Out == nil && te.AttachControlPlaneOutput {
@@ -216,17 +243,26 @@ func (te *Environment) Start() (*rest.Config, error) {
216243
te.ControlPlane.Etcd.Err = os.Stderr
217244
}
218245

219-
if os.Getenv(envKubeAPIServerBin) == "" {
220-
te.ControlPlane.APIServer.Path = defaultAssetPath("kube-apiserver")
246+
// set binaries location and then, if the bin not found throw issue
247+
path, err := te.getBinAssetPath(kubeApiserverBinName, os.Getenv(envKubeAPIServerBinEnvVar))
248+
if err != nil {
249+
return nil, err
250+
}
251+
te.ControlPlane.APIServer.Path = path
252+
253+
path, err = te.getBinAssetPath(etcdBinName, os.Getenv(envEtcdBinEnvVar))
254+
if err != nil {
255+
return nil, err
221256
}
222-
if os.Getenv(envEtcdBin) == "" {
223-
te.ControlPlane.Etcd.Path = defaultAssetPath("etcd")
257+
te.ControlPlane.Etcd.Path = path
258+
259+
path, err = te.getBinAssetPath(kubectlBinName, os.Getenv(envKubectlBinEnvVar))
260+
if err != nil {
261+
return nil, err
224262
}
225-
if os.Getenv(envKubectlBin) == "" {
226-
// we can't just set the path manually (it's behind a function), so set the environment variable instead
227-
if err := os.Setenv(envKubectlBin, defaultAssetPath("kubectl")); err != nil {
228-
return nil, err
229-
}
263+
// we can't just set the path manually (it's behind a function), so set the environment variable instead
264+
if err := os.Setenv(envKubectlBinEnvVar, path); err != nil {
265+
return nil, err
230266
}
231267

232268
if err := te.defaultTimeouts(); err != nil {
@@ -267,6 +303,14 @@ func (te *Environment) Start() (*rest.Config, error) {
267303
return te.Config, err
268304
}
269305

306+
// hasBinary will return true when the binary was found in the path
307+
func hasBinary(bin, path string) bool {
308+
if _, err := os.Stat(filepath.Join(path, bin)); os.IsNotExist(err) {
309+
return false
310+
}
311+
return true
312+
}
313+
270314
func (te *Environment) startControlPlane() error {
271315
numTries, maxRetries := 0, 5
272316
var err error
@@ -287,7 +331,7 @@ func (te *Environment) startControlPlane() error {
287331
func (te *Environment) defaultTimeouts() error {
288332
var err error
289333
if te.ControlPlaneStartTimeout == 0 {
290-
if envVal := os.Getenv(envStartTimeout); envVal != "" {
334+
if envVal := os.Getenv(envStartTimeoutEnvVar); envVal != "" {
291335
te.ControlPlaneStartTimeout, err = time.ParseDuration(envVal)
292336
if err != nil {
293337
return err
@@ -298,7 +342,7 @@ func (te *Environment) defaultTimeouts() error {
298342
}
299343

300344
if te.ControlPlaneStopTimeout == 0 {
301-
if envVal := os.Getenv(envStopTimeout); envVal != "" {
345+
if envVal := os.Getenv(envStopTimeoutEnvVar); envVal != "" {
302346
te.ControlPlaneStopTimeout, err = time.ParseDuration(envVal)
303347
if err != nil {
304348
return err
@@ -312,7 +356,7 @@ func (te *Environment) defaultTimeouts() error {
312356

313357
func (te *Environment) useExistingCluster() bool {
314358
if te.UseExistingCluster == nil {
315-
return strings.ToLower(os.Getenv(envUseExistingCluster)) == "true"
359+
return strings.ToLower(os.Getenv(envUseExistingClusterEnvVar)) == "true"
316360
}
317361
return *te.UseExistingCluster
318362
}

0 commit comments

Comments
 (0)