github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/cloudconfig/cloudinit/utils.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Copyright 2015 Cloudbase Solutions SRL 3 // Licensed under the AGPLv3, see LICENCE file for details. 4 5 package cloudinit 6 7 import ( 8 "encoding/base64" 9 "fmt" 10 "path/filepath" 11 12 "github.com/juju/packaging/v3" 13 "github.com/juju/packaging/v3/config" 14 "github.com/juju/utils/v3" 15 16 jujupackaging "github.com/juju/juju/packaging" 17 ) 18 19 // addPackageSourceCmds is a helper function that returns the corresponding 20 // runcmds to apply the package source settings on a CentOS machine. 21 func addPackageSourceCmds(cfg CloudConfig, src packaging.PackageSource) []string { 22 cmds := []string{} 23 24 // if keyfile is required, add it first 25 if src.Key != "" { 26 keyFilePath := config.YumKeyfileDir + src.KeyFileName() 27 cmds = append(cmds, addFileCmds(keyFilePath, []byte(src.Key), 0644, false)...) 28 } 29 30 repoPath := filepath.Join(config.YumSourcesDir, src.Name+".repo") 31 sourceFile, _ := cfg.getPackagingConfigurer(jujupackaging.YumPackageManager).RenderSource(src) 32 data := []byte(sourceFile) 33 cmds = append(cmds, addFileCmds(repoPath, data, 0644, false)...) 34 35 return cmds 36 } 37 38 // addFile is a helper function returns all the required shell commands to write 39 // a file (be it text or binary) with regards to the given parameters 40 // NOTE: if the file already exists, it will be overwritten. 41 func addFileCmds(filename string, data []byte, mode uint, binary bool) []string { 42 // Note: recent versions of cloud-init have the "write_files" 43 // module, which can write arbitrary files. We currently support 44 // 12.04 LTS, which uses an older version of cloud-init without 45 // this module. 46 // TODO (aznashwan): eagerly await 2017 and to do the right thing here 47 p := utils.ShQuote(filename) 48 49 cmds := []string{fmt.Sprintf("install -D -m %o /dev/null %s", mode, p)} 50 // Don't use the shell's echo builtin here; the interpretation 51 // of escape sequences differs between shells, namely bash and 52 // dash. Instead, we use printf (or we could use /bin/echo). 53 if binary { 54 encoded := base64.StdEncoding.EncodeToString(data) 55 cmds = append(cmds, fmt.Sprintf(`echo -n %s | base64 -d > %s`, encoded, p)) 56 } else { 57 cmds = append(cmds, fmt.Sprintf(`echo %s > %s`, utils.ShQuote(string(data)), p)) 58 } 59 60 return cmds 61 } 62 63 // addFileCopyCmds is a helper function returns all the required shell commands to copy 64 // a file (be it text or binary) with regards to the given parameters 65 // NOTE: if the file already exists, it will be overwritten. 66 func addFileCopyCmds(source string, filename string, mode uint) []string { 67 s := utils.ShQuote(source) 68 p := utils.ShQuote(filename) 69 70 cmds := []string{fmt.Sprintf("install -D -m %o /dev/null %s", mode, p)} 71 cmds = append(cmds, fmt.Sprintf(`cat %s > %s`, s, p)) 72 73 return cmds 74 } 75 76 // removeStringFromSlice is a helper function which removes a given string from 77 // the given slice, if it exists it returns the slice, be it modified or unmodified 78 func removeStringFromSlice(slice []string, val string) []string { 79 for i, str := range slice { 80 if str == val { 81 slice = append(slice[:i], slice[i+1:]...) 82 } 83 } 84 85 return slice 86 }