internal/containerd/install.go (107 lines of code) (raw):

package containerd import ( "context" "fmt" "os" "os/exec" "time" "github.com/pkg/errors" "github.com/aws/eks-hybrid/internal/artifact" "github.com/aws/eks-hybrid/internal/daemon" "github.com/aws/eks-hybrid/internal/system" "github.com/aws/eks-hybrid/internal/tracker" "github.com/aws/eks-hybrid/internal/util/cmd" ) type SourceName string const ( ContainerdSourceNone SourceName = "none" ContainerdSourceDistro SourceName = "distro" ContainerdSourceDocker SourceName = "docker" // pin containerd to major version 1.x ContainerdVersion = "1.*" containerdPackageName = "containerd" runcPackageName = "runc" ) // Source represents a source that serves a containerd binary. type Source interface { GetContainerd(version string) artifact.Package } func Install(ctx context.Context, tracker *tracker.Tracker, source Source, containerdSource SourceName) error { if containerdSource == ContainerdSourceNone { return nil } if isContainerdNotInstalled() { containerd := source.GetContainerd(ContainerdVersion) // Sometimes install fails due to conflicts with other processes // updating packages, specially when automating at machine startup. // We assume errors are transient and just retry for a bit. if err := cmd.Retry(ctx, containerd.InstallCmd, 5*time.Second); err != nil { return errors.Wrap(err, "failed to install containerd") } tracker.MarkContainerd(string(containerdSource)) } return nil } func Uninstall(ctx context.Context, source Source) error { if isContainerdInstalled() { containerd := source.GetContainerd(ContainerdVersion) if err := cmd.Retry(ctx, containerd.UninstallCmd, 5*time.Second); err != nil { return errors.Wrap(err, "failed to uninstall containerd") } if err := os.RemoveAll(containerdConfigDir); err != nil { return errors.Wrap(err, "failed to uninstall containerd config files") } } return nil } func Upgrade(ctx context.Context, source Source) error { containerd := source.GetContainerd(ContainerdVersion) if err := cmd.Retry(ctx, containerd.UpgradeCmd, 5*time.Second); err != nil { return errors.Wrap(err, "upgrading containerd") } return nil } func ValidateContainerdSource(source SourceName) error { osName := system.GetOsName() switch source { case ContainerdSourceNone: return nil case ContainerdSourceDocker: if osName == system.AmazonOsName { return fmt.Errorf("docker source for containerd is not supported on AL2023. Please provide `none` or `distro` to the --containerd-source flag") } case ContainerdSourceDistro: if osName == system.RhelOsName { return fmt.Errorf("distro source for containerd is not supported on RHEL. Please provide `none` or `docker` to the --containerd-source flag") } } return nil } func ValidateSystemdUnitFile() error { daemonManager, err := daemon.NewDaemonManager() if err != nil { return err } if err := daemonManager.DaemonReload(); err != nil { return err } daemonStatus, err := daemonManager.GetDaemonStatus(ContainerdDaemonName) if daemonStatus == daemon.DaemonStatusUnknown || err != nil { return fmt.Errorf("containerd daemon not found") } return nil } func GetContainerdSource(containerdSource string) SourceName { switch containerdSource { case string(ContainerdSourceDistro): return ContainerdSourceDistro case string(ContainerdSourceDocker): return ContainerdSourceDocker default: return ContainerdSourceNone } } func isContainerdInstalled() bool { _, containerdNotFoundErr := exec.LookPath(containerdPackageName) return containerdNotFoundErr == nil } // isContainerdNotInstalled returns true only if both containerd and runc are not installed func isContainerdNotInstalled() bool { _, containerdNotFoundErr := exec.LookPath(containerdPackageName) _, runcNotFoundErr := exec.LookPath(runcPackageName) return containerdNotFoundErr != nil || runcNotFoundErr != nil }