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  }