mirror of
https://github.com/siderolabs/talos.git
synced 2025-08-20 22:21:13 +02:00
This moves from translating a config into an internal config representation, to using an interface. The idea is that an interface gives us stronger compile time checks, and will prevent us from having to copy from on struct to another. As long as a concrete type implements the Configurator interface, it can be used to provide instructions to Talos. Signed-off-by: Andrew Rynhard <andrew@andrewrynhard.com>
87 lines
2.6 KiB
Go
87 lines
2.6 KiB
Go
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
package install
|
|
|
|
import (
|
|
"context"
|
|
"log"
|
|
|
|
"github.com/containerd/containerd"
|
|
"github.com/containerd/containerd/cio"
|
|
"github.com/containerd/containerd/namespaces"
|
|
"github.com/containerd/containerd/oci"
|
|
"github.com/opencontainers/runtime-spec/specs-go"
|
|
"github.com/pkg/errors"
|
|
|
|
"github.com/talos-systems/talos/internal/pkg/kernel"
|
|
"github.com/talos-systems/talos/pkg/constants"
|
|
)
|
|
|
|
// Install performs an installation via the installer container.
|
|
func Install(ref string, disk string, platform string) error {
|
|
ctx := namespaces.WithNamespace(context.Background(), constants.SystemContainerdNamespace)
|
|
client, err := containerd.New(constants.SystemContainerdAddress)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
log.Printf("running install via %q", ref)
|
|
image, err := client.Pull(ctx, ref, []containerd.RemoteOpt{containerd.WithPullUnpack}...)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
mounts := []specs.Mount{
|
|
{Type: "bind", Destination: "/dev", Source: "/dev", Options: []string{"rbind", "rshared", "rw"}},
|
|
}
|
|
|
|
// TODO(andrewrynhard): To handle cases when the newer version changes the
|
|
// platform name, this should be determined in the installer container.
|
|
var config *string
|
|
if config = kernel.ProcCmdline().Get(constants.KernelParamConfig).First(); config == nil {
|
|
return errors.Errorf("no config option was found")
|
|
}
|
|
|
|
specOpts := []oci.SpecOpts{
|
|
oci.WithImageConfig(image),
|
|
oci.WithProcessArgs([]string{"/bin/entrypoint.sh", "install", "-d", disk, "-p", platform, "-u", *config}...),
|
|
oci.WithHostNamespace(specs.NetworkNamespace),
|
|
oci.WithHostNamespace(specs.PIDNamespace),
|
|
oci.WithMounts(mounts),
|
|
oci.WithHostHostsFile,
|
|
oci.WithHostResolvconf,
|
|
oci.WithParentCgroupDevices,
|
|
oci.WithPrivileged,
|
|
}
|
|
containerOpts := []containerd.NewContainerOpts{
|
|
containerd.WithImage(image),
|
|
containerd.WithNewSnapshot("upgrade", image),
|
|
containerd.WithNewSpec(specOpts...),
|
|
}
|
|
|
|
container, err := client.NewContainer(ctx, "upgrade", containerOpts...)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
t, err := container.NewTask(ctx, cio.LogFile("/dev/kmsg"))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err = t.Start(ctx); err != nil {
|
|
return errors.Wrapf(err, "failed to start task: %q", "upgrade")
|
|
}
|
|
statusC, err := t.Wait(ctx)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "failed waiting for task: %q", "upgrade")
|
|
}
|
|
|
|
status := <-statusC
|
|
code := status.ExitCode()
|
|
if code != 0 {
|
|
return errors.Errorf("task %q failed: exit code %d", "upgrade", code)
|
|
}
|
|
|
|
return nil
|
|
}
|