11package devcontainers
22
33import (
4- "bytes"
54 "encoding/json"
65 "fmt"
76 "io/ioutil"
@@ -225,7 +224,7 @@ func addFolderSnippetToDevContainer(projectFolder string, snippet *DevcontainerS
225224 return fmt .Errorf ("content must be set for %s actions" , action .Type )
226225 }
227226 dockerfileFilename := filepath .Join (projectFolder , ".devcontainer" , "Dockerfile" )
228- err = insertDockerfileSnippet (dockerfileFilename , action .Content + "\n " )
227+ err = insertDockerfileSnippet (projectFolder , dockerfileFilename , action .Content + "\n " )
229228 if err != nil {
230229 return err
231230 }
@@ -251,11 +250,11 @@ RUN /tmp/%[2]s
251250` , snippet .Name , scriptFilename )
252251 dockerfileFilename := filepath .Join (projectFolder , ".devcontainer" , "Dockerfile" )
253252
254- err := insertDockerfileSnippet (dockerfileFilename , snippetContent )
253+ err := insertDockerfileSnippet (projectFolder , dockerfileFilename , snippetContent )
255254 return err
256255}
257256
258- func insertDockerfileSnippet (dockerfileFilename string , snippetContent string ) error {
257+ func insertDockerfileSnippet (projectFolder string , dockerfileFilename string , snippetContent string ) error {
259258
260259 buf , err := ioutil .ReadFile (dockerfileFilename )
261260 if err != nil {
@@ -266,7 +265,7 @@ func insertDockerfileSnippet(dockerfileFilename string, snippetContent string) e
266265 dockerFileLines := strings .Split (dockerfileContent , "\n " )
267266 addSeparator := false
268267 addedSnippetContent := false
269- var newContent bytes. Buffer
268+ var newContent strings. Builder
270269 for _ , line := range dockerFileLines {
271270 if addSeparator {
272271 if _ , err = newContent .WriteString ("\n " ); err != nil {
@@ -301,7 +300,14 @@ func insertDockerfileSnippet(dockerfileFilename string, snippetContent string) e
301300 }
302301 }
303302
304- err = ioutil .WriteFile (dockerfileFilename , newContent .Bytes (), 0 )
303+ content := newContent .String ()
304+ values , err := getSubstitutionValuesFromFile (filepath .Join (projectFolder , ".devcontainer/devcontainer.json" ))
305+ if err != nil {
306+ return fmt .Errorf ("failed to get dev container values: %s" , err )
307+ }
308+ content = performSubstitutionString (values , content )
309+
310+ err = ioutil .WriteFile (dockerfileFilename , []byte (content ), 0 )
305311
306312 return err
307313
@@ -333,21 +339,11 @@ func mergeJSON(projectFolder string, snippet *DevcontainerSnippet, relativeMerge
333339 return err
334340 }
335341
336- // replace __DEVCONTAINER_NAME__ with name
337- devcontainerName , devcontainerUserName := getDevcontainerNameAndUserName (filepath .Join (projectFolder , ".devcontainer/devcontainer.json" ))
338- if devcontainerName == "" {
339- return fmt .Errorf ("failed to get dev container name" )
340- }
341- resultJSON = strings .ReplaceAll (resultJSON , "__DEVCONTAINER_NAME__" , devcontainerName )
342- if devcontainerUserName == "" {
343- devcontainerUserName = "root"
344- }
345- devcontainerHome := "/home/" + devcontainerUserName
346- if devcontainerUserName == "root" {
347- devcontainerHome = "/root"
342+ values , err := getSubstitutionValuesFromFile (filepath .Join (projectFolder , ".devcontainer/devcontainer.json" ))
343+ if err != nil {
344+ return fmt .Errorf ("failed to get dev container values: %s" , err )
348345 }
349- resultJSON = strings .ReplaceAll (resultJSON , "__DEVCONTAINER_USER_NAME__" , devcontainerUserName )
350- resultJSON = strings .ReplaceAll (resultJSON , "__DEVCONTAINER_HOME__" , devcontainerHome )
346+ resultJSON = performSubstitutionString (values , resultJSON )
351347
352348 err = ioutil .WriteFile (basePath , []byte (resultJSON ), 0666 )
353349 if err != nil {
@@ -372,17 +368,23 @@ func loadJSONDocument(path string) (*dora_ast.RootNode, error) {
372368 return & baseDocument , nil
373369}
374370
375- func getDevcontainerNameAndUserName (devContainerJsonPath string ) (string , string ) {
371+ type SubstitutionValues struct {
372+ Name string
373+ UserName string
374+ HomeFolder string
375+ }
376+
377+ func getSubstitutionValuesFromFile (devContainerJsonPath string ) (* SubstitutionValues , error ) {
376378 // This doesn't use standard `json` pkg as devcontainer.json permits comments (and the default templates include them!)
377379
378380 buf , err := ioutil .ReadFile (devContainerJsonPath )
379381 if err != nil {
380- return "" , ""
382+ return nil , err
381383 }
382384
383385 c , err := dora .NewFromBytes (buf )
384386 if err != nil {
385- return "" , ""
387+ return nil , err
386388 }
387389
388390 name , err := c .GetString ("$.name" )
@@ -391,8 +393,24 @@ func getDevcontainerNameAndUserName(devContainerJsonPath string) (string, string
391393 }
392394 userName , err := c .GetString ("$.remoteUser" )
393395 if err != nil {
394- userName = ""
396+ userName = "root "
395397 }
398+ homeFolder := "/home/" + userName
399+ if userName == "root" {
400+ homeFolder = "/root"
401+ }
402+
403+ return & SubstitutionValues {
404+ Name : name ,
405+ UserName : userName ,
406+ HomeFolder : homeFolder ,
407+ }, nil
408+ }
396409
397- return name , userName
410+ func performSubstitutionString (substitutionValues * SubstitutionValues , content string ) string {
411+ // replace __DEVCONTAINER_NAME__ with name etc
412+ content = strings .ReplaceAll (content , "__DEVCONTAINER_NAME__" , substitutionValues .Name )
413+ content = strings .ReplaceAll (content , "__DEVCONTAINER_USER_NAME__" , substitutionValues .UserName )
414+ content = strings .ReplaceAll (content , "__DEVCONTAINER_HOME__" , substitutionValues .HomeFolder )
415+ return content
398416}
0 commit comments