/* * Copyright 2026 Oleg Borodin * * This work is published and licensed under a Creative Commons * Attribution-NonCommercial-NoDerivatives 4.0 International License. * * Distribution of this work is permitted, but commercial use and * modifications are strictly prohibited. */ package client import ( "context" "fmt" "os" "mstore/pkg/auxtool" "mstore/pkg/auxutar" "github.com/google/go-containerregistry/pkg/authn" "github.com/google/go-containerregistry/pkg/crane" "github.com/google/go-containerregistry/pkg/name" pkg "github.com/google/go-containerregistry/pkg/v1" "github.com/google/go-containerregistry/pkg/v1/layout" "github.com/google/go-containerregistry/pkg/v1/remote/transport" ) func (cli *Client) PushImage(ctx context.Context, filepath, imagepath string) error { var err error imagepath, username, password, err := repackReference(imagepath) if err != nil { return err } options := make([]crane.Option, 0) options = append(options, crane.WithContext(ctx)) if username != "" && password != "" { ref, err := name.ParseReference(imagepath) if err != nil { return err } repo := ref.Context() if err != nil { return err } defaultTransport := NewRoundTripper(cli.skipTLSVerify) scopes := []string{ repo.Scope(transport.PushScope), repo.Scope(transport.PullScope), } regName := repo.RegistryStr() reg, err := name.NewRegistry(regName) if err != nil { return err } basicAuth := &authn.Basic{ Username: username, Password: password, } authTransport, err := transport.NewWithContext(ctx, reg, basicAuth, defaultTransport, scopes) if err != nil { return err } options = append(options, crane.WithTransport(authTransport)) } else { defaultTransport := NewRoundTripper(cli.skipTLSVerify) options = append(options, crane.WithTransport(defaultTransport)) } dstdir := auxtool.MakeTmpFilename(filepath) err = auxutar.Unarchive(filepath, dstdir) if err != nil { os.RemoveAll(dstdir) return err } image, err := imageLoader(dstdir) if err != nil { return err } err = crane.Push(image, imagepath, options...) if err != nil { return err } err = os.RemoveAll(dstdir) if err != nil { return err } return err } func imageLoader(dirPath string) (pkg.Image, error) { var err error var res pkg.Image layoutPath, err := layout.FromPath(dirPath) if err != nil { return res, err } imageIndex, err := layoutPath.ImageIndex() if err != nil { return res, err } indexManifest, err := imageIndex.IndexManifest() if err != nil { return res, err } if indexManifest == nil { err := fmt.Errorf("Empty indexManifest referency") return res, err } manifest := indexManifest.Manifests[0] image, err := layoutPath.Image(manifest.Digest) if err != nil { return res, err } res = image return res, err }