@@ -40,11 +40,43 @@ import (
4040 kexec "k8s.io/client-go/util/exec"
4141)
4242
43+ func findFile (file string ) (string , error ) {
44+ stat , err := os .Stat (file )
45+ if err == nil && ! stat .IsDir () {
46+ return file , nil
47+ }
48+
49+ // fallback to path relative to executable
50+ if exePath , err := os .Executable (); err == nil {
51+ exeDir := filepath .Dir (exePath )
52+ fallbackPath := filepath .Join (exeDir , file )
53+ if stat , err := os .Stat (fallbackPath ); err == nil && ! stat .IsDir () {
54+ return fallbackPath , nil
55+ }
56+ }
57+
58+ // fallback to user home
59+ if homeDir , err := os .UserHomeDir (); err == nil {
60+ fallbackPath := filepath .Join (homeDir , file )
61+ if stat , err := os .Stat (fallbackPath ); err == nil && ! stat .IsDir () {
62+ return fallbackPath , nil
63+ }
64+ }
65+
66+ return "" , os .ErrNotExist
67+ }
68+
4369// PodFromFile will read a given file with pod definition and returns a corev1.Pod
4470// accordingly.
4571func PodFromFile (file string ) (* corev1.Pod , error ) {
4672 decode := scheme .Codecs .UniversalDeserializer ().Decode
47- stream , err := os .ReadFile (file )
73+
74+ resolvedPodTemplateFile , err := findFile (file )
75+ if err != nil {
76+ return nil , err
77+ }
78+
79+ stream , err := os .ReadFile (resolvedPodTemplateFile )
4880 if err != nil {
4981 return nil , err
5082 }
@@ -65,7 +97,6 @@ type K8sDriver struct {
6597 KubeConfig * rest.Config
6698 PodTemplate * corev1.Pod
6799 podName string
68- AllowReuse bool
69100 env []unversioned.EnvVar
70101}
71102
@@ -107,21 +138,15 @@ func NewK8sDriver(args DriverConfig) (Driver, error) {
107138 runOpts : args .RunOpts ,
108139 PodTemplate : template ,
109140 KubeConfig : k8sConfig ,
110- AllowReuse : args .AllowReuse ,
111141 podName : "" ,
112142 }, nil
113143}
114144
115145func (d * K8sDriver ) Setup (envVars []unversioned.EnvVar , fullCommands [][]string ) error {
116- // Pod creation will be handled in ProcessCommand
117- logrus .Info ("k8s driver setup, no pod created yet" )
118146 return nil
119147}
120148
121149func (d * K8sDriver ) Teardown (fullCommands [][]string ) error {
122- if d .AllowReuse && d .podName != "" {
123- d .Destroy ()
124- }
125150 return nil
126151}
127152
@@ -131,37 +156,35 @@ func (d *K8sDriver) SetEnv(envVars []unversioned.EnvVar) error {
131156}
132157
133158func (d * K8sDriver ) ProcessCommand (envVars []unversioned.EnvVar , fullCommand []string ) (string , string , int , error ) {
134- if ! d . AllowReuse || d .podName == "" {
159+ if d .podName == "" {
135160 logrus .Infof ("k8s driver creating pod in namespace %s" , d .PodTemplate .ObjectMeta .Namespace )
136161 allEnvs := append (d .env , envVars ... )
137162 // create a pod that waits
138163 pod , err := d .createPod (allEnvs , []string {"sleep" , "99999" })
139164 if err != nil {
140165 return "" , "" , 0 , err
141166 }
142- d .podName = pod .Name
143-
144- if ! d .AllowReuse {
145- defer d .Destroy ()
146- }
147167
148168 // Wait for the pod to be running
149169 err = d .waitForPod ()
150170 if err != nil {
151171 return "" , "" , 0 , err
152172 }
173+
174+ d .podName = pod .Name
175+ logrus .Infof ("k8s driver created pod %s in namespace %s" , d .podName , d .PodTemplate .ObjectMeta .Namespace )
153176 }
154177
155178 return d .execInPod (fullCommand )
156179}
157180
158181func (d * K8sDriver ) StatFile (path string ) (os.FileInfo , error ) {
159- // A better approach would be to have a long-running pod and exec into it.
160182 command := []string {"stat" , "-c" , "%n,%s,%F,%a,%u,%g" , path }
161183 stdout , _ , _ , err := d .ProcessCommand (nil , command )
162184 if err != nil {
163185 return nil , err
164186 }
187+
165188 parts := strings .Split (strings .TrimSpace (stdout ), "," )
166189 if len (parts ) != 6 {
167190 return nil , fmt .Errorf ("unexpected output from stat: %s" , stdout )
@@ -183,18 +206,29 @@ func (d *K8sDriver) StatFile(path string) (os.FileInfo, error) {
183206 }
184207
185208 // Use bitSize 32 because os.FileMode is a uint32
186- fileMode , err := strconv .ParseUint (parts [3 ], 8 , 32 )
209+ fileMode64 , err := strconv .ParseUint (parts [3 ], 8 , 32 )
187210 if err != nil {
188211 return nil , err
189212 }
190213
214+ fileMode := os .FileMode (fileMode64 )
215+
216+ // Manually map the Linux special bits to Go constants
217+ if fileMode64 & 01000 != 0 { // Linux Sticky Bit
218+ fileMode |= os .ModeSticky
219+ }
220+
221+ if isDir {
222+ fileMode |= os .ModeDir
223+ }
224+
191225 return & fileInfo {
192226 name : parts [0 ],
193227 size : size ,
194228 isDir : isDir ,
195229 uid : uid ,
196230 gid : gid ,
197- fileMode : os . FileMode ( fileMode ) ,
231+ fileMode : fileMode ,
198232 }, nil
199233}
200234
@@ -224,10 +258,20 @@ func (fi *fileInfo) IsDir() bool {
224258 return fi .isDir
225259}
226260func (fi * fileInfo ) Sys () interface {} {
227- return & tar.Header {
228- Uid : int (fi .uid ),
229- Gid : int (fi .gid ),
261+ hdr := & tar.Header {
262+ Name : fi .name ,
263+ Size : fi .size ,
264+ Mode : int64 (fi .fileMode ),
265+ Uid : int (fi .uid ),
266+ Gid : int (fi .gid ),
267+ ModTime : fi .ModTime (),
268+ }
269+ if fi .isDir {
270+ hdr .Typeflag = tar .TypeDir
271+ } else {
272+ hdr .Typeflag = tar .TypeReg
230273 }
274+ return hdr
231275}
232276
233277func (d * K8sDriver ) ReadFile (path string ) ([]byte , error ) {
@@ -305,14 +349,20 @@ func (d *K8sDriver) GetConfig() (unversioned.Config, error) {
305349}
306350
307351func (d * K8sDriver ) Destroy () {
352+ d .stopPod ()
353+ }
354+
355+ func (d * K8sDriver ) stopPod () {
308356 if d .podName == "" {
357+ logrus .Info ("k8s driver no pod defined, nothing to clean" )
309358 return
310359 }
311360 err := d .Client .CoreV1 ().Pods (d .PodTemplate .Namespace ).Delete (context .Background (), d .podName , metav1.DeleteOptions {})
312361 if err != nil {
313362 logrus .Warnf ("Error when removing pod %s: %s" , d .podName , err .Error ())
314363 }
315364 d .podName = ""
365+ logrus .Infof ("Stopped pod %s" , d .podName )
316366}
317367
318368func (d * K8sDriver ) createPod (envVars []unversioned.EnvVar , command []string ) (* corev1.Pod , error ) {
@@ -368,7 +418,6 @@ func (d *K8sDriver) waitForPod() error {
368418}
369419
370420func (d * K8sDriver ) execInPod (command []string ) (string , string , int , error ) {
371-
372421 // TTY must be false to keep stdout and stderr separate
373422 req := d .Client .CoreV1 ().RESTClient ().Post ().
374423 Resource ("pods" ).
@@ -405,5 +454,7 @@ func (d *K8sDriver) execInPod(command []string) (string, string, int, error) {
405454 }
406455 }
407456
457+ logrus .Infof ("Executed command %v in %s" , command , d .podName )
458+
408459 return stdout .String (), stderr .String (), exitCode , nil
409460}
0 commit comments