mirror of
				https://github.com/siderolabs/talos.git
				synced 2025-10-27 06:21:11 +01:00 
			
		
		
		
	See #7230 Refactor more config interfaces, move config accessor interfaces to different package to break the dependency loop. Make `.RawV1Alpha1()` method typed to avoid type assertions everywhere. No functional changes. Signed-off-by: Andrey Smirnov <andrey.smirnov@talos-systems.com>
		
			
				
	
	
		
			121 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			121 lines
		
	
	
		
			3.1 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 extensions
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"fmt"
 | |
| 	"log"
 | |
| 	"os"
 | |
| 	"path/filepath"
 | |
| 	"strings"
 | |
| 
 | |
| 	"github.com/containerd/containerd"
 | |
| 	"github.com/containerd/containerd/mount"
 | |
| 	"github.com/opencontainers/image-spec/identity"
 | |
| 
 | |
| 	"github.com/siderolabs/talos/internal/pkg/containers/image"
 | |
| 	"github.com/siderolabs/talos/pkg/machinery/config/config"
 | |
| 	"github.com/siderolabs/talos/pkg/machinery/constants"
 | |
| )
 | |
| 
 | |
| // Puller pulls, unpacks and mounts extensions images.
 | |
| type Puller struct {
 | |
| 	client    *containerd.Client
 | |
| 	snapshots []string
 | |
| 	mounts    []string
 | |
| }
 | |
| 
 | |
| // NewPuller creates a new instance of system extensions puller helper.
 | |
| func NewPuller(client *containerd.Client) (*Puller, error) {
 | |
| 	// prepare by ensuring empty extension directory
 | |
| 	if _, err := os.Stat(constants.SystemExtensionsPath); err == nil {
 | |
| 		if err = os.RemoveAll(constants.SystemExtensionsPath); err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if err := os.MkdirAll(constants.SystemExtensionsPath, 0o700); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	return &Puller{
 | |
| 		client: client,
 | |
| 	}, nil
 | |
| }
 | |
| 
 | |
| // PullAndMount pulls the system extension images, unpacks them and mounts under well known path (constants.SystemExtensionsPath).
 | |
| func (puller *Puller) PullAndMount(ctx context.Context, registryConfig config.Registries, extensions []config.Extension) error {
 | |
| 	snapshotService := puller.client.SnapshotService(containerd.DefaultSnapshotter)
 | |
| 
 | |
| 	for i, ext := range extensions {
 | |
| 		extensionImage := ext.Image()
 | |
| 
 | |
| 		// use numeric prefix to keep extensions sorted in a proper way
 | |
| 		path := fmt.Sprintf("%03d.%s", i, strings.ReplaceAll(strings.ReplaceAll(extensionImage, ":", "-"), "/", "-"))
 | |
| 
 | |
| 		log.Printf("pulling extension %q", extensionImage)
 | |
| 
 | |
| 		var extImg containerd.Image
 | |
| 
 | |
| 		extImg, err := image.Pull(ctx, registryConfig, puller.client, extensionImage, image.WithSkipIfAlreadyPulled())
 | |
| 		if err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 
 | |
| 		diffs, err := extImg.RootFS(ctx)
 | |
| 		if err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 
 | |
| 		chainID := identity.ChainID(diffs)
 | |
| 
 | |
| 		_, err = snapshotService.Stat(ctx, chainID.String())
 | |
| 		if err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 
 | |
| 		mounts, err := snapshotService.Prepare(ctx, path, chainID.String())
 | |
| 		if err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 
 | |
| 		puller.snapshots = append(puller.snapshots, path)
 | |
| 
 | |
| 		mountTarget := filepath.Join(constants.SystemExtensionsPath, path)
 | |
| 
 | |
| 		if err = os.Mkdir(mountTarget, 0o700); err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 
 | |
| 		if err = mount.All(mounts, mountTarget); err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 
 | |
| 		puller.mounts = append(puller.mounts, mountTarget)
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // Cleanup the temporary stuff created by the puller process.
 | |
| func (puller *Puller) Cleanup(ctx context.Context) error {
 | |
| 	for _, target := range puller.mounts {
 | |
| 		if err := mount.UnmountAll(target, 0); err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	snapshotService := puller.client.SnapshotService(containerd.DefaultSnapshotter)
 | |
| 
 | |
| 	for _, key := range puller.snapshots {
 | |
| 		if err := snapshotService.Remove(ctx, key); err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return os.RemoveAll(constants.SystemExtensionsPath)
 | |
| }
 |