@@ -17,6 +17,7 @@ limitations under the License.
1717package envtest
1818
1919import (
20+ "errors"
2021 "fmt"
2122 "os"
2223 "path/filepath"
@@ -43,7 +44,6 @@ It's possible to override some defaults, by setting the following environment va
4344 KUBEBUILDER_CONTROLPLANE_START_TIMEOUT (string supported by time.ParseDuration): timeout for test control plane to start. Defaults to 20s.
4445 KUBEBUILDER_CONTROLPLANE_STOP_TIMEOUT (string supported by time.ParseDuration): timeout for test control plane to start. Defaults to 20s.
4546 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-
4747*/
4848const (
4949 envUseExistingCluster = "USE_EXISTING_CLUSTER"
@@ -58,18 +58,32 @@ const (
5858 StartTimeout = 60
5959 StopTimeout = 60
6060
61+ // rquired binaries to run env test
62+ kubeApiserverBin = "kube-apiserver"
63+ etcdBin = "etcd"
64+ kubectlBin = "kubectl"
65+
6166 defaultKubebuilderControlPlaneStartTimeout = 20 * time .Second
6267 defaultKubebuilderControlPlaneStopTimeout = 20 * time .Second
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 required binaries
71+ // if the KUBEBUILDER_ASSETS is not set and the Directory is not informed in the
72+ // config as well. Then, a default fixed value will be returned
73+ func (te * Environment ) getBinAssetPath () string {
74+ assetPath := defaultKubebuilderPath
75+
76+ valueFromEnvVar := os .Getenv (envKubebuilderPath )
77+ if strings .TrimSpace (valueFromEnvVar ) != "" {
78+ assetPath = valueFromEnvVar
79+ }
80+
81+ valueFromEnvConfig := te .BinaryDirectoryPath
82+ if strings .TrimSpace (valueFromEnvConfig ) != "" {
83+ assetPath = valueFromEnvConfig
7084 }
71- return filepath .Join (assetPath , binary )
7285
86+ return assetPath
7387}
7488
7589// ControlPlane is the re-exported ControlPlane type from the internal integration package
@@ -113,6 +127,10 @@ type Environment struct {
113127 // values are merged.
114128 CRDDirectoryPaths []string
115129
130+ // BinaryDirectoryPath is the path where the binaries required for the envtest are
131+ // locate in the environment
132+ BinaryDirectoryPath string
133+
116134 // UseExisting indicates that this environments should use an
117135 // existing kubeconfig, instead of trying to stand up a new control plane.
118136 // This is useful in cases that need aggregated API servers and the like.
@@ -217,18 +235,24 @@ func (te *Environment) Start() (*rest.Config, error) {
217235 }
218236
219237 if os .Getenv (envKubeAPIServerBin ) == "" {
220- te .ControlPlane .APIServer .Path = defaultAssetPath ("kube-apiserver" )
238+ te .ControlPlane .APIServer .Path = filepath .Join (te .getBinAssetPath (), kubeApiserverBin )
239+
221240 }
222241 if os .Getenv (envEtcdBin ) == "" {
223- te .ControlPlane .Etcd .Path = defaultAssetPath ("etcd" )
242+ te .ControlPlane .Etcd .Path = filepath .Join (te .getBinAssetPath (), etcdBin )
243+
224244 }
225245 if os .Getenv (envKubectlBin ) == "" {
226246 // 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 {
247+ if err := os .Setenv (envKubectlBin , filepath . Join ( te . getBinAssetPath (), kubectlBin )); err != nil {
228248 return nil , err
229249 }
230250 }
231251
252+ if err := te .validateRequiredBinaries (); err != nil {
253+ return nil , err
254+ }
255+
232256 if err := te .defaultTimeouts (); err != nil {
233257 return nil , fmt .Errorf ("failed to default controlplane timeouts: %w" , err )
234258 }
@@ -267,6 +291,22 @@ func (te *Environment) Start() (*rest.Config, error) {
267291 return te .Config , err
268292}
269293
294+ // validateRequiredBinaries will return an error if the required binaries are not found
295+ func (te * Environment ) validateRequiredBinaries () error {
296+ if _ , err := os .Stat (te .ControlPlane .APIServer .Path ); os .IsNotExist (err ) {
297+ return errors .New (fmt .Sprintf ("unable to find the %v" , te .ControlPlane .APIServer .Path ))
298+ }
299+
300+ if _ , err := os .Stat (te .ControlPlane .Etcd .Path ); os .IsNotExist (err ) {
301+ return errors .New (fmt .Sprintf ("unable to find the %v" , te .ControlPlane .Etcd .Path ))
302+ }
303+
304+ if _ , err := os .Stat (os .Getenv (envKubectlBin )); os .IsNotExist (err ) {
305+ return errors .New (fmt .Sprintf ("unable to find the %v" , os .Getenv (envKubectlBin )))
306+ }
307+ return nil
308+ }
309+
270310func (te * Environment ) startControlPlane () error {
271311 numTries , maxRetries := 0 , 5
272312 var err error
0 commit comments