github.com/caos/orbos@v1.5.14-0.20221103111702-e6cd0cea7ad4/internal/operator/nodeagent/dep/package-manager-install.go (about) 1 package dep 2 3 import ( 4 "bytes" 5 "fmt" 6 "os" 7 "os/exec" 8 "strings" 9 10 "github.com/caos/orbos/mntr" 11 ) 12 13 func (p *PackageManager) rembasedInstall(install ...*Software) error { 14 15 if len(install) == 0 { 16 return nil 17 } 18 19 errBuf := new(bytes.Buffer) 20 defer errBuf.Reset() 21 22 installPkgs := make([]string, 0) 23 for _, sw := range install { 24 25 _, ok := p.installed[sw.Package] 26 if ok && sw.Version == "" { 27 continue 28 } 29 30 if sw.Version == "" { 31 installPkgs = append(installPkgs, sw.Package) 32 continue 33 } 34 35 installPkg := fmt.Sprintf("%s-%s", sw.Package, sw.Version) 36 installPkgs = append(installPkgs, installPkg) 37 cmd := exec.Command("yum", "versionlock", "delete", sw.Package) 38 cmd.Stderr = errBuf 39 if p.monitor.IsVerbose() { 40 fmt.Println(strings.Join(cmd.Args, " ")) 41 cmd.Stdout = os.Stdout 42 } 43 err := cmd.Run() 44 stderr := errBuf.String() 45 if err != nil && !strings.Contains(stderr, "versionlock delete: no matches") { 46 return fmt.Errorf("unlocking package %s failed with stderr %s: %w", sw.Package, stderr, err) 47 } 48 errBuf.Reset() 49 50 cmd = exec.Command("yum", "versionlock", "add", "-y", installPkg) 51 cmd.Stderr = errBuf 52 if p.monitor.IsVerbose() { 53 fmt.Println(strings.Join(cmd.Args, " ")) 54 cmd.Stdout = os.Stdout 55 } 56 if err := cmd.Run(); err != nil { 57 return fmt.Errorf("locking package %s at version %s failed with stderr %s: %w", sw.Package, sw.Version, errBuf.String(), err) 58 } 59 errBuf.Reset() 60 } 61 62 for _, pkg := range installPkgs { 63 if err := rembasedInstallPkg(p.monitor, pkg); err != nil { 64 return err 65 } 66 } 67 return nil 68 } 69 70 func rembasedInstallPkg(monitor mntr.Monitor, pkg string) error { 71 errBuf := new(bytes.Buffer) 72 defer errBuf.Reset() 73 outBuf := new(bytes.Buffer) 74 defer outBuf.Reset() 75 cmd := exec.Command("yum", "install", "-y", pkg) 76 cmd.Stderr = errBuf 77 cmd.Stdout = outBuf 78 err := cmd.Run() 79 errStr := errBuf.String() 80 outStr := outBuf.String() 81 monitor.WithFields(map[string]interface{}{ 82 "command": fmt.Sprintf("'%s'", strings.Join(cmd.Args, "' '")), 83 "stdout": outStr, 84 "stderr": errStr, 85 }).Debug("Executed yum install") 86 if err != nil && !strings.Contains(errStr+outStr, "is already installed") { 87 return fmt.Errorf("installing yum package %s failed with stderr %s: %w", pkg, errStr, err) 88 } 89 return nil 90 } 91 92 // TODO: Use lower level apt instead of apt-get? 93 func (p *PackageManager) debbasedInstall(install ...*Software) error { 94 95 errBuf := new(bytes.Buffer) 96 defer errBuf.Reset() 97 98 pkgs := make([]string, len(install)) 99 hold := make([]string, 0) 100 for idx, sw := range install { 101 pkgs[idx] = sw.Package 102 if sw.Version == "" { 103 continue 104 } 105 pkgs[idx] = fmt.Sprintf("%s=%s", sw.Package, sw.Version) 106 hold = append(hold, sw.Package) 107 108 cmd := exec.Command("apt-mark", "unhold", sw.Package) 109 cmd.Stderr = errBuf 110 if p.monitor.IsVerbose() { 111 fmt.Println(strings.Join(cmd.Args, " ")) 112 cmd.Stdout = os.Stdout 113 } 114 if err := cmd.Run(); err != nil { 115 return fmt.Errorf("unholding installed package failed with stderr %s: %w", errBuf.String(), err) 116 } 117 errBuf.Reset() 118 } 119 120 cmd := exec.Command("dpkg", "--configure", "-a") 121 cmd.Stderr = errBuf 122 if p.monitor.IsVerbose() { 123 fmt.Println(strings.Join(cmd.Args, " ")) 124 cmd.Stdout = os.Stdout 125 } 126 if err := cmd.Run(); err != nil { 127 return fmt.Errorf("cleaning up dpkg failed with stderr %s: %w", errBuf.String(), err) 128 } 129 errBuf.Reset() 130 131 cmd = exec.Command("apt-get", append(strings.Fields( 132 "--assume-yes --allow-downgrades install -y"), pkgs...)...) 133 cmd.Stderr = errBuf 134 if p.monitor.IsVerbose() { 135 fmt.Println(strings.Join(cmd.Args, " ")) 136 cmd.Stdout = os.Stdout 137 } 138 if err := cmd.Run(); err != nil { 139 return fmt.Errorf("installing package failed with stderr %s: %w", errBuf.String(), err) 140 } 141 errBuf.Reset() 142 143 for _, pkg := range hold { 144 cmd = exec.Command("apt-mark", "hold", pkg) 145 cmd.Stderr = errBuf 146 if p.monitor.IsVerbose() { 147 fmt.Println(strings.Join(cmd.Args, " ")) 148 cmd.Stdout = os.Stdout 149 } 150 if err := cmd.Run(); err != nil { 151 return fmt.Errorf("holding package failed with stderr %s: %w", errBuf.String(), err) 152 } 153 errBuf.Reset() 154 155 p.monitor.WithFields(map[string]interface{}{ 156 "software": pkg, 157 }).Debug("Holded package") 158 } 159 return nil 160 }