kairos-sdk/utils/image.go
2023-06-20 09:43:43 +03:00

104 lines
2.5 KiB
Go

package utils
import (
"context"
"errors"
"fmt"
"github.com/containerd/containerd/archive"
"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/logs"
"github.com/google/go-containerregistry/pkg/name"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/daemon"
"github.com/google/go-containerregistry/pkg/v1/mutate"
"github.com/google/go-containerregistry/pkg/v1/remote"
"github.com/google/go-containerregistry/pkg/v1/remote/transport"
"io"
"net/http"
"runtime"
"strings"
"syscall"
"time"
)
var defaultRetryBackoff = remote.Backoff{
Duration: 1.0 * time.Second,
Factor: 3.0,
Jitter: 0.1,
Steps: 3,
}
var defaultRetryPredicate = func(err error) bool {
if err == nil {
return false
}
if errors.Is(err, io.ErrUnexpectedEOF) || errors.Is(err, io.EOF) || errors.Is(err, syscall.EPIPE) || errors.Is(err, syscall.ECONNRESET) || strings.Contains(err.Error(), "connection refused") {
logs.Warn.Printf("retrying %v", err)
return true
}
return false
}
// ExtractOCIImage will extract a given targetImage into a given targetDestination
func ExtractOCIImage(targetImage, targetDestination, targetPlatform string) error {
var platform *v1.Platform
var img v1.Image
var err error
if targetPlatform != "" {
platform, err = v1.ParsePlatform(targetPlatform)
if err != nil {
return err
}
} else {
platform, err = v1.ParsePlatform(fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH))
if err != nil {
return err
}
}
ref, err := name.ParseReference(targetImage)
if err != nil {
return err
}
img, err = getimage(ref, *platform)
if err != nil {
return err
}
reader := mutate.Extract(img)
_, err = archive.Apply(context.Background(), targetDestination, reader)
if err != nil {
return err
}
return nil
}
// image returns the proper image to pull with transport and auth
// tries local daemon first and then fallbacks into remote
func getimage(ref name.Reference, platform v1.Platform) (v1.Image, error) {
var image v1.Image
var err error
tr := transport.NewRetry(http.DefaultTransport,
transport.WithRetryBackoff(defaultRetryBackoff),
transport.WithRetryPredicate(defaultRetryPredicate),
)
image, err = daemon.Image(ref)
fmt.Println("lo")
if err != nil {
fmt.Println("re")
image, err = remote.Image(ref,
remote.WithTransport(tr),
remote.WithPlatform(platform),
remote.WithAuthFromKeychain(authn.DefaultKeychain),
)
}
return image, err
}