get.porter.sh/porter@v1.3.0/pkg/agent/agent.go (about) 1 package agent 2 3 import ( 4 "fmt" 5 "io" 6 "io/fs" 7 "os" 8 "os/exec" 9 "path/filepath" 10 "strings" 11 12 "get.porter.sh/porter/pkg" 13 ) 14 15 // allow the tests to capture output 16 var ( 17 Stdout io.Writer = os.Stdout 18 Stderr io.Writer = os.Stderr 19 ) 20 21 // The porter agent wraps the porter cli, 22 // handling copying config files from a mounted 23 // volume into PORTER_HOME 24 // Returns any errors and if the porter command was executed 25 func Execute(porterCommand []string, porterHome string, porterConfig string) (error, bool) { 26 porter := porterHome + "/porter" 27 28 // Copy config files into PORTER_HOME 29 err := filepath.Walk(porterConfig, func(path string, info fs.FileInfo, err error) error { 30 // if Walk sends a non nil err, then return it back 31 if err != nil { 32 return err 33 } 34 if info.IsDir() { 35 return nil 36 } 37 38 // Determine the relative path of the file we are copying 39 relPath, err := filepath.Rel(porterConfig, path) 40 if err != nil { 41 return err 42 } 43 44 // Skip hidden files, these are injected by k8s when the config volume is mounted 45 if strings.HasPrefix(relPath, ".") { 46 return nil 47 } 48 49 // If the files are symlinks then resolve them 50 // /porter-config 51 // - config.toml (symlink to the file in ..data) 52 // - ..data/config.toml 53 resolvedPath, err := filepath.EvalSymlinks(path) 54 if err != nil { 55 return err 56 } 57 58 resolvedInfo, err := os.Stat(resolvedPath) 59 if err != nil { 60 return err 61 } 62 63 return copyConfig(relPath, resolvedPath, resolvedInfo, porterHome) 64 }) 65 if err != nil { 66 return err, false 67 } 68 69 // Remind everyone the version of Porter we are using 70 fmt.Fprintf(Stderr, "porter version\n") 71 cmd := exec.Command(porter, "version") 72 cmd.Stdout = Stderr // send all non-bundle output to stderr 73 cmd.Stderr = Stderr 74 if err = cmd.Run(); err != nil { 75 return fmt.Errorf("porter version check failed: %w", err), false 76 } 77 78 // Run the specified porter command 79 fmt.Fprintf(Stderr, "porter %s\n", strings.Join(porterCommand, " ")) 80 cmd = exec.Command(porter, porterCommand...) 81 cmd.Stdout = Stdout 82 cmd.Stderr = Stderr 83 cmd.Stdin = os.Stdin 84 if err := cmd.Start(); err != nil { 85 return err, false 86 } 87 return cmd.Wait(), true 88 } 89 90 func copyConfig(relPath string, configFile string, fi os.FileInfo, porterHome string) error { 91 destFile := filepath.Join(porterHome, relPath) 92 fmt.Fprintln(Stderr, "Loading configuration", relPath, "into", destFile) 93 src, err := os.OpenFile(configFile, os.O_RDONLY, 0) 94 if err != nil { 95 return err 96 } 97 defer src.Close() 98 99 if err = os.MkdirAll(filepath.Dir(destFile), pkg.FileModeDirectory); err != nil { 100 return err 101 } 102 dest, err := os.OpenFile(destFile, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, fi.Mode()) 103 if err != nil { 104 return err 105 } 106 defer dest.Close() 107 108 // Just copy the file 109 _, err = io.Copy(dest, src) 110 return err 111 }