@@ -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*/
4847const (
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+
270314func (te * Environment ) startControlPlane () error {
271315 numTries , maxRetries := 0 , 5
272316 var err error
@@ -287,7 +331,7 @@ func (te *Environment) startControlPlane() error {
287331func (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
313357func (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