@@ -15,6 +15,7 @@ import (
1515 "strings"
1616 "time"
1717
18+ "al.essio.dev/pkg/shellescape"
1819 exec2 "github.com/alexellis/go-execute/pkg/v1"
1920 "github.com/containerd/containerd/log"
2021 v1 "k8s.io/api/core/v1"
@@ -184,36 +185,79 @@ func (h *SidecarHandler) LoadJIDs() error {
184185 return nil
185186}
186187
187- // prepareEnvs reads all Environment variables from a container and append them to a slice of strings.
188- // It returns the slice containing all envs in the form of key=value.
189- func prepareEnvs (Ctx context.Context , container v1.Container ) []string {
188+ func createEnvFile (Ctx context.Context , config SlurmConfig , podData commonIL.RetrievedPodData , container v1.Container ) ([]string , []string , error ) {
189+ envs := []string {}
190+ // For debugging purpose only
191+ envs_data := []string {}
192+
193+ envfilePath := (config .DataRootFolder + podData .Pod .Namespace + "-" + string (podData .Pod .UID ) + "/" + "envfile.properties" )
194+ log .G (Ctx ).Info ("-- Appending envs using envfile " + envfilePath )
195+ envs = append (envs , "--env-file" )
196+ envs = append (envs , envfilePath )
197+
198+ envfile , err := os .Create (envfilePath )
199+ if err != nil {
200+ log .G (Ctx ).Error (err )
201+ return nil , nil , err
202+ }
203+ defer envfile .Close ()
204+
205+ for _ , envVar := range container .Env {
206+ // The environment variable values can contains all sort of simple/double quote and space and any arbitrary values.
207+ // singularity reads the env-file and parse it like a bash string, so shellescape will escape any quote properly.
208+ tmpValue := shellescape .Quote (envVar .Value )
209+ tmp := (envVar .Name + "=" + tmpValue )
210+
211+ envs_data = append (envs_data , tmp )
212+
213+ _ , err := envfile .WriteString (tmp + "\n " )
214+ if err != nil {
215+ log .G (Ctx ).Error (err )
216+ return nil , nil , err
217+ } else {
218+ log .G (Ctx ).Debug ("---- Written envfile file " + envfilePath + " key " + envVar .Name + " value " + tmpValue )
219+ }
220+ }
221+
222+ // All env variables are written, we flush it now.
223+ err = envfile .Sync ()
224+ if err != nil {
225+ log .G (Ctx ).Error (err )
226+ return nil , nil , err
227+ }
228+
229+ // Calling Close() in case of error. If not error, the defer will close it again but it should be idempotent.
230+ envfile .Close ()
231+
232+ return envs , envs_data , nil
233+ }
234+
235+ // prepareEnvs reads all Environment variables from a container and append them to a envfile.properties. The values are bash-escaped.
236+ // It returns the slice containing, if there are Environment variables, the arguments for envfile and its path, or else an empty array.
237+ func prepareEnvs (Ctx context.Context , config SlurmConfig , podData commonIL.RetrievedPodData , container v1.Container ) []string {
190238 start := time .Now ().UnixMicro ()
191239 span := trace .SpanFromContext (Ctx )
192240 span .AddEvent ("Preparing ENVs for container " + container .Name )
193- var envs []string
241+ var envs []string = []string {}
242+ // For debugging purpose only
243+ envs_data := []string {}
244+ var err error
194245
195246 if len (container .Env ) > 0 {
196- log .G (Ctx ).Info ("-- Appending envs" )
197- envs = append (envs , "--env" )
198- env_data := ""
199- for _ , envVar := range container .Env {
200- tmp := (envVar .Name + "=" + envVar .Value + "," )
201- env_data += tmp
202- }
203- if last := len (env_data ) - 1 ; last >= 0 && env_data [last ] == ',' {
204- env_data = env_data [:last ]
205- }
206- if env_data == "" {
207- envs = []string {}
247+ envs , envs_data , err = createEnvFile (Ctx , config , podData , container )
248+ if err != nil {
249+ log .G (Ctx ).Error (err )
250+ return nil
208251 }
209- envs = append (envs , env_data )
210252 }
211253
212254 duration := time .Now ().UnixMicro () - start
213255 span .AddEvent ("Prepared ENVs for container " + container .Name , trace .WithAttributes (
214256 attribute .String ("prepareenvs.container.name" , container .Name ),
215257 attribute .Int64 ("prepareenvs.duration" , duration ),
216- attribute .StringSlice ("prepareenvs.container.envs" , envs )))
258+ attribute .StringSlice ("prepareenvs.container.envs" , envs ),
259+ attribute .StringSlice ("prepareenvs.container.envs_data" , envs_data )))
260+
217261 return envs
218262}
219263
0 commit comments