working commit

This commit is contained in:
2026-03-16 20:55:36 +02:00
parent 5c1da77f4c
commit 13b1905e05
31 changed files with 177 additions and 151 deletions
+3 -3
View File
@@ -41,8 +41,8 @@ EXTRA_mstorectl_SOURCES = \
cmd/mstorectl/imagecmd/imagetags.go \
cmd/mstorectl/imagecmd/printresp.go \
cmd/mstorectl/imagecmd/gcrimageconf.go \
cmd/mstorectl/imagecmd/gcrpullimage.go \
cmd/mstorectl/imagecmd/gcrpushimage.go
cmd/mstorectl/imagecmd/pullimage.go \
cmd/mstorectl/imagecmd/pushimage.go
mstored_SOURCES = cmd/mstored/main.go
@@ -55,7 +55,7 @@ mstored$(EXEEXT): $(mstored_SOURCES) $(EXTRA_mstored_SOURCES)
env CGO_ENABLED=1 $(GO) build $(GOFLAGS) -o mstored$(EXEEXT) $(mstored_SOURCES)
run: $(mstored_SOURCES)
cd cmd/mstored && env CGO_ENABLED=1 $(GO) run . --asDaemon=false
cd cmd/mstored && env CGO_ENABLED=1 $(GO) run . --asDaemon=false --port=443
CWD=$(shell pwd)
+3 -3
View File
@@ -387,8 +387,8 @@ EXTRA_mstorectl_SOURCES = \
cmd/mstorectl/imagecmd/imagetags.go \
cmd/mstorectl/imagecmd/printresp.go \
cmd/mstorectl/imagecmd/gcrimageconf.go \
cmd/mstorectl/imagecmd/gcrpullimage.go \
cmd/mstorectl/imagecmd/gcrpushimage.go
cmd/mstorectl/imagecmd/pullimage.go \
cmd/mstorectl/imagecmd/pushimage.go
mstored_SOURCES = cmd/mstored/main.go
EXTRA_mstored_SOURCES = cmd/mstored/starter/starter.go \
@@ -1130,7 +1130,7 @@ mstored$(EXEEXT): $(mstored_SOURCES) $(EXTRA_mstored_SOURCES)
env CGO_ENABLED=1 $(GO) build $(GOFLAGS) -o mstored$(EXEEXT) $(mstored_SOURCES)
run: $(mstored_SOURCES)
cd cmd/mstored && env CGO_ENABLED=1 $(GO) run . --asDaemon=false
cd cmd/mstored && env CGO_ENABLED=1 $(GO) run . --asDaemon=false --port=443
\
docs/helm-chart-manifest.json.txt \
docs/mstore.drawio \
-1
View File
@@ -77,7 +77,6 @@ func (oper *Operator) CreateGrant(ctx context.Context, operatorID string, params
err := fmt.Errorf("Grant with this right already exists")
return res, err
}
oper.logg.Debugf("Call CreateGrant")
now := auxtool.TimeNow()
grantDescr := &descr.Grant{
ID: auxuuid.NewUUID(),
+1 -1
View File
@@ -52,7 +52,7 @@ func NewConfig() *Config {
logfile := fmt.Sprintf("%s.log", srvname)
logpath := filepath.Join(logdir, logfile)
runfile := fmt.Sprintf("%s.run", srvname)
runfile := fmt.Sprintf("%s.pid", srvname)
runpath := filepath.Join(rundir, runfile)
//certpath := fmt.Sprintf("%s.crt", srvname)
+4 -4
View File
@@ -1,10 +1,10 @@
package config
const (
confdir = "/home/ziggi/Projects/mstore/etc/mstore"
rundir = "/home/ziggi/Projects/mstore/tmp/run"
logdir = "/home/ziggi/Projects/mstore/tmp/log"
datadir = "/home/ziggi/Projects/mstore/tmp/data"
confdir = "/etc/mstore"
rundir = "/var/run/mstore"
logdir = "/var/log/mstore"
datadir = "/var/lib/mstore"
version = "0.2.0"
srvname = "mstored"
)
-1
View File
@@ -92,7 +92,6 @@ func (oper *Operator) GetFile(ctx context.Context, operatorID string, params *Ge
for _, descr := range fileDescrs {
if descr.Type == hcMediaType {
meta := &chart.Metadata{}
oper.logg.Debugf("=== %s", descr.HelmMeta)
err = json.Unmarshal([]byte(descr.HelmMeta), meta)
if err != nil {
code := http.StatusInternalServerError
+1 -1
View File
@@ -54,7 +54,7 @@ func (hand *Handler) CheckAccess(rctx *router.Context) (bool, string, error) {
//hand.logg.Debugf("URL: %s", rctx.URL().String())
authHeader := rctx.GetHeader("Authorization")
hand.logg.Debugf("Authorization: %s", authHeader)
hand.logg.Debugf("Authorization: [%s]", authHeader)
if authHeader != "" {
username, password, err = auxhttp.ParseBasicAuth(authHeader)
if err != nil {
-2
View File
@@ -25,7 +25,6 @@ func (hand *Handler) BlobExists(rctx *router.Context) {
digest, _ := rctx.GetSubpath("digest")
//hand.DumpHeaders("BlobExists", rctx)
params := &imageoper.BlobExistsParams{
Name: name,
Digest: digest,
@@ -63,7 +62,6 @@ func (hand *Handler) PostUpload(rctx *router.Context) {
name, _ := rctx.GetSubpath("name")
//hand.DumpHeaders("PostUploads", rctx)
authorization := rctx.GetHeader("Authorization")
if authorization == "" {
rctx.SetHeader("WWW-Authenticate", `Basic realm="mstore"`)
+1 -2
View File
@@ -24,7 +24,6 @@ type BlobExistsResult struct {
DockerContentDigest string
ContentLength string
ContentType string
//Exists bool
}
func (oper *Operator) BlobExists(ctx context.Context, operatorID string, params *BlobExistsParams) (*BlobExistsResult, int, error) {
@@ -45,7 +44,7 @@ func (oper *Operator) BlobExists(ctx context.Context, operatorID string, params
defer oper.iLock.Done(resName)
// Check blob descriptor
descrExists, blobDescr, err := oper.mdb.GetBlobByNameDigest(ctx, params.Digest, params.Digest)
descrExists, blobDescr, err := oper.mdb.GetBlobByNameDigest(ctx, params.Name, params.Digest)
if err != nil {
return res, http.StatusInternalServerError, err
}
+5 -3
View File
@@ -50,8 +50,8 @@ func (oper *Operator) GetManifest(ctx context.Context, params *GetManifestParams
manDescr := descr.Manifest{}
var exists bool
digobj, err := ocidigest.Parse(params.Reference)
if err == nil {
digobj, parseErr := ocidigest.Parse(params.Reference)
if parseErr == nil {
exists, manDescr, err = oper.mdb.GetManifestByDigest(ctx, params.Name, digobj.String())
if err != nil {
return res, http.StatusInternalServerError, err
@@ -75,6 +75,7 @@ func (oper *Operator) GetManifest(ctx context.Context, params *GetManifestParams
return res, http.StatusNotFound, err
}
if len(manDescrs) == 1 {
manDescr = manDescrs[0]
res.DockerContentDigest = manDescr.Digest
size := int64(len(manDescr.Payload))
res.ContentLength = strconv.FormatInt(size, 10)
@@ -85,8 +86,9 @@ func (oper *Operator) GetManifest(ctx context.Context, params *GetManifestParams
if err != nil {
return res, http.StatusInternalServerError, err
}
digobj := ocidigest.SHA256.FromBytes(indexdata)
digobj := ocidigest.FromBytes(indexdata)
res.DockerContentDigest = digobj.String()
size := int64(len(indexdata))
res.ContentLength = strconv.FormatInt(size, 10)
res.ContentType = oiiMediaType
+3 -4
View File
@@ -15,7 +15,6 @@ import (
"net/http"
"strconv"
//"mstore/pkg/auxoci"
"mstore/pkg/descr"
ocidigest "github.com/opencontainers/go-digest"
@@ -48,8 +47,8 @@ func (oper *Operator) ManifestExists(ctx context.Context, params *ManifestExists
var man descr.Manifest
var exist bool
digobj, err := ocidigest.Parse(params.Reference)
if err == nil {
digobj, parseErr := ocidigest.Parse(params.Reference)
if parseErr == nil {
exist, man, err = oper.mdb.GetManifestByDigest(ctx, params.Name, digobj.String())
if err != nil {
return res, http.StatusInternalServerError, err
@@ -75,7 +74,7 @@ func (oper *Operator) ManifestExists(ctx context.Context, params *ManifestExists
if err != nil {
return res, http.StatusInternalServerError, err
}
digobj := ocidigest.SHA256.FromBytes(indexdata)
digobj := ocidigest.FromBytes(indexdata)
res.DockerContentDigest = digobj.String()
size := int64(len(indexdata))
res.ContentLength = strconv.FormatInt(size, 10)
+10 -1
View File
@@ -19,6 +19,7 @@ import (
"net/http"
"strconv"
ocidigest "github.com/opencontainers/go-digest"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)
@@ -74,6 +75,14 @@ func (oper *Operator) PutManifest(ctx context.Context, params *PutManifestParams
return res, http.StatusInternalServerError, err
}
inManData := buffer.Bytes()
var digstr string
digobj, parseErr := ocidigest.Parse(params.Reference)
if parseErr == nil {
digstr = digobj.String()
} else {
digobj := ocidigest.FromBytes(inManData)
digstr = digobj.String()
}
if int64(len(inManData)) != contentLength {
err = fmt.Errorf("Mismatch Content-Length and received manifest size: %d vs %d",
contentLength, len(inManData))
@@ -112,6 +121,7 @@ func (oper *Operator) PutManifest(ctx context.Context, params *PutManifestParams
}
inManDescr, inlayerdescrs, err := descrsFromManifest(name, reference, inMan, inManData)
inManDescr.Digest = digstr
// Always check layer files for availability
var blobError error
for _, blobDescr := range inlayerdescrs {
@@ -178,7 +188,6 @@ func (oper *Operator) PutManifest(ctx context.Context, params *PutManifestParams
}
}
}
for _, blobDescr := range inlayerdescrs {
// TODO: move the requests to db layer transaction
blobDescrExists, _, err := oper.mdb.GetBlobByNameDigest(ctx, blobDescr.Name, blobDescr.Digest)
+2 -2
View File
@@ -21,14 +21,14 @@ import (
type Database struct {
datapath string
log *logger.Logger
logg *logger.Logger
db *sqlx.DB
}
func NewDatabase(datapath string) *Database {
return &Database{
datapath: datapath,
log: logger.NewLoggerWithSubject("maindb"),
logg: logger.NewLoggerWithSubject("maindb"),
}
}
+1 -1
View File
@@ -89,7 +89,7 @@ func (srv *Server) SetAsDaemon(asDaemon bool) {
func (srv *Server) Configure() error {
var err error
srv.logg.Infof("Configuration server")
//srv.logg.Infof("Configuration server")
srv.conf = config.NewConfig()
if err != nil {
return err
+2 -2
View File
@@ -70,6 +70,8 @@ func (svc *Service) Build() error {
svc.rout.Use(router.NewCorsMiddleware())
svc.rout.Use(svc.hand.AuthMiddleware)
svc.rout.Head(`/v2/{name}/blobs/{digest}`, svc.hand.BlobExists)
svc.rout.Get(`/v3/api/service/hello`, svc.hand.SendHello)
svc.rout.Head(`/v3/api/file/{filepath}`, svc.hand.FileInfo)
@@ -93,8 +95,6 @@ func (svc *Service) Build() error {
svc.rout.Get(`/v2/{name}/manifests/{reference}`, svc.hand.GetManifest)
svc.rout.Delete(`/v2/{name}/manifests/{reference}`, svc.hand.DeleteManifest)
svc.rout.Head(`/v2/{name}/blobs/{digest}`, svc.hand.BlobExists)
svc.rout.Post(`/v2/{name}/blobs/uploads/`, svc.hand.PostUpload)
svc.rout.Patch(`/v2/{name}/blobs/uploads/{reference}`, svc.hand.PatchUpload)
svc.rout.Put(`/v2/{name}/blobs/uploads/{reference}`, svc.hand.PutUpload)
+1
View File
@@ -45,6 +45,7 @@ func (util *ImageUtil) catalogImages(common *CommonImageParams, params *CatalogI
if err != nil {
return res, err
}
ref.SetUserinfo(common.Username, common.Password)
mw := repocli.NewBasicAuthMiddleware(ref.Userinfo())
cli := repocli.NewClient(nil, mw)
opres, err := cli.GetCatalog(ctx, ref.Raw())
+1
View File
@@ -43,6 +43,7 @@ func (util *ImageUtil) deleteImage(common *CommonImageParams, params *DeleteImag
if err != nil {
return res, err
}
ref.SetUserinfo(common.Username, common.Password)
mw := repocli.NewBasicAuthMiddleware(ref.Userinfo())
cli := repocli.NewClient(nil, mw)
_, err = cli.DeleteImage(ctx, ref.Raw())
-59
View File
@@ -1,59 +0,0 @@
/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*
* 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 imagecmd
import (
"context"
"time"
"github.com/spf13/cobra"
"mstore/pkg/gcrcli"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)
// ImageConfig
type ImageConfigParams struct {
Imagepath string
}
type ImageConfigResult struct {
ImageConfig *ocispec.Image `json:"imageConfig"`
}
func (util *ImageUtil) ImageConfig(cmd *cobra.Command, args []string) {
util.imageConfigParams.Imagepath = args[0]
res, err := util.imageConfig(&util.commonImageParams, &util.imageConfigParams)
printResponse(res, err)
}
func (util *ImageUtil) imageConfig(common *CommonImageParams, params *ImageConfigParams) (*ImageConfigResult, error) {
var err error
res := &ImageConfigResult{
ImageConfig: &ocispec.Image{},
}
ctx := context.Background()
cli := gcrcli.NewClient(common.SkipTLSVerify)
timeout := time.Duration(common.Timeout) * time.Second
params.Imagepath, err = packUserinfo(params.Imagepath, common.Username, common.Password)
if err != nil {
return res, err
}
ctx, _ = context.WithTimeout(ctx, timeout)
opres, err := cli.ImageConfig(ctx, params.Imagepath)
if err != nil {
return res, err
}
res.ImageConfig = opres
return res, err
}
-9
View File
@@ -102,14 +102,6 @@ func (util *ImageUtil) CreateImageCmds() *cobra.Command {
}
subCmd.AddCommand(imageTagsCmd)
// ImageConfig
var imageConfigCmd = &cobra.Command{
Use: "config [user:pass@]hostname[:port]/path:tag",
Short: "Show container image config info",
Args: cobra.ExactArgs(1),
Run: util.ImageConfig,
}
subCmd.AddCommand(imageConfigCmd)
// CatalogImages
var catalogImagesCmd = &cobra.Command{
Use: "catalog [user:pass@]hostname[:port]",
@@ -125,7 +117,6 @@ func (util *ImageUtil) CreateImageCmds() *cobra.Command {
type ImageUtil struct {
imageManifestParams ImageManifestParams
imageTagsParams ImageTagsParams
imageConfigParams ImageConfigParams
catalogImagesParams CatalogImagesParams
pullImageParams PullImageParams
+1
View File
@@ -53,6 +53,7 @@ func (util *ImageUtil) imageManifest(common *CommonImageParams, params *ImageMan
if err != nil {
return res, err
}
ref.SetUserinfo(common.Username, common.Password)
mw := repocli.NewBasicAuthMiddleware(ref.Userinfo())
cli := repocli.NewClient(nil, mw)
exists, mime, man, _, err := cli.GetRawManifest(ctx, ref.RawRepo())
+1
View File
@@ -47,6 +47,7 @@ func (util *ImageUtil) imageTags(common *CommonImageParams, params *ImageTagsPar
if err != nil {
return res, err
}
ref.SetUserinfo(common.Username, common.Password)
mw := repocli.NewBasicAuthMiddleware(ref.Userinfo())
cli := repocli.NewClient(nil, mw)
opres, err := cli.GetTags(ctx, ref.Raw())
@@ -16,7 +16,10 @@ import (
"github.com/spf13/cobra"
"mstore/pkg/auxtool"
"mstore/pkg/auxutar"
"mstore/pkg/gcrcli"
"mstore/pkg/repocli"
)
// PullImage
@@ -39,6 +42,45 @@ func (util *ImageUtil) PullImage(cmd *cobra.Command, args []string) {
func (util *ImageUtil) pullImage(common *CommonImageParams, params *PullImageParams) (*PullImageResult, error) {
var err error
res := &PullImageResult{}
timeout := time.Duration(common.Timeout) * time.Second
ctx, _ := context.WithTimeout(context.Background(), timeout)
ref, err := repocli.NewReferer(params.Imagepath)
if err != nil {
return res, err
}
ref.SetUserinfo(common.Username, common.Password)
mw := repocli.NewBasicAuthMiddleware(ref.Userinfo())
cli := repocli.NewClient(nil, mw)
load := repocli.NewLoader(cli)
if err != nil {
return res, err
}
imageDir := auxtool.MakeTmpFilename(params.Filepath)
err = load.Pull(ctx, ref.Raw(), imageDir, "", "")
if err != nil {
return res, err
}
err = auxutar.Archive(imageDir, params.Filepath)
defer os.RemoveAll(imageDir)
if err != nil {
return res, err
}
filestat, err := os.Stat(params.Filepath)
if err != nil {
return res, err
}
res.Size = filestat.Size()
res.Filepath = params.Filepath
return res, err
}
func (util *ImageUtil) XXXpullImage(common *CommonImageParams, params *PullImageParams) (*PullImageResult, error) {
var err error
ctx := context.Background()
res := &PullImageResult{}
@@ -60,6 +102,5 @@ func (util *ImageUtil) pullImage(common *CommonImageParams, params *PullImagePar
}
res.Size = filestat.Size()
res.Filepath = params.Filepath
return res, err
}
@@ -11,11 +11,15 @@ package imagecmd
import (
"context"
"os"
"time"
"github.com/spf13/cobra"
"mstore/pkg/auxtool"
"mstore/pkg/auxutar"
"mstore/pkg/gcrcli"
"mstore/pkg/repocli"
)
// PushImage
@@ -35,6 +39,36 @@ func (util *ImageUtil) PushImage(cmd *cobra.Command, args []string) {
}
func (util *ImageUtil) pushImage(common *CommonImageParams, params *PushImageParams) (*PushImageResult, error) {
var err error
res := &PushImageResult{}
timeout := time.Duration(common.Timeout) * time.Second
ctx, _ := context.WithTimeout(context.Background(), timeout)
ref, err := repocli.NewReferer(params.Imagepath)
if err != nil {
return res, err
}
ref.SetUserinfo(common.Username, common.Password)
mw := repocli.NewBasicAuthMiddleware(ref.Userinfo())
cli := repocli.NewClient(nil, mw)
load := repocli.NewLoader(cli)
imageDir := auxtool.MakeTmpFilename(params.Filepath)
err = auxutar.Unarchive(params.Filepath, imageDir)
defer os.RemoveAll(imageDir)
if err != nil {
return res, err
}
err = load.Push(ctx, imageDir, ref.Raw(), "", "")
if err != nil {
return res, err
}
return res, err
}
func (util *ImageUtil) XXXpushImage(common *CommonImageParams, params *PushImageParams) (*PushImageResult, error) {
var err error
ctx := context.Background()
res := &PushImageResult{}
Vendored
+1 -1
View File
@@ -3826,7 +3826,7 @@ printf "%s\n" "$as_me: srv_libdir set as ${SRV_LIBDIR}" >&6;}
SRV_DATADIR="/var/data/${PACKAGE}"
SRV_DATADIR="/var/lib/${PACKAGE}"
# Check whether --with-datadir was given.
+1 -1
View File
@@ -213,7 +213,7 @@ AC_MSG_NOTICE(srv_libdir set as ${SRV_LIBDIR})
dnl --------------------------------------------------------------------------------------
SRV_DATADIR="/var/data/${PACKAGE}"
SRV_DATADIR="/var/lib/${PACKAGE}"
AC_ARG_WITH(datadir,
AS_HELP_STRING([--with-datadir=PATH],[set path for datadir (default: $SRV_DATADIR)]),
+1 -1
View File
@@ -4,7 +4,7 @@ Description=mstored
[Service]
Type=forking
PIDFile=@srv_rundir@/mstored.pid
ExecStart=@prefix@/sbin/mstored -daemon=true
ExecStart=@prefix@/sbin/mstored --asDaemon=true --port=443
ExecReload=/bin/kill -HUP $MAINPID
[Install]
+31 -31
View File
@@ -30,7 +30,7 @@ type Referer struct {
}
func ParsePath(rawpath string) (*Referer, error) {
repo := &Referer{
ref := &Referer{
values: url.Values{},
}
if !strings.Contains(rawpath, "://") {
@@ -38,71 +38,71 @@ func ParsePath(rawpath string) (*Referer, error) {
}
urlobj, err := url.Parse(rawpath)
if err != nil {
return repo, err
return ref, err
}
if urlobj.User != nil {
repo.user = urlobj.User.Username()
repo.pass, _ = urlobj.User.Password()
ref.user = urlobj.User.Username()
ref.pass, _ = urlobj.User.Password()
urlobj.User = nil
}
repo.resource = path.Join("/", urlobj.Path)
ref.resource = path.Join("/", urlobj.Path)
urlobj.Path = "/"
repo.urlobj = urlobj
repo.values = urlobj.Query()
return repo, err
ref.urlobj = urlobj
ref.values = urlobj.Query()
return ref, err
}
func (repo *Referer) Raw() string {
res := path.Join(repo.urlobj.Host, repo.resource)
query := repo.values.Encode()
func (ref *Referer) Raw() string {
res := path.Join(ref.urlobj.Host, ref.resource)
query := ref.values.Encode()
if query != "" {
return res + "?" + query
}
return res
}
func (repo *Referer) SetResource(resource string) {
repo.resource = path.Join("/", resource)
func (ref *Referer) SetResource(resource string) {
ref.resource = path.Join("/", resource)
}
func (repo *Referer) JoinResource(resource string) {
repo.resource = path.Join("/", repo.resource, resource)
func (ref *Referer) JoinResource(resource string) {
ref.resource = path.Join("/", ref.resource, resource)
}
func (repo *Referer) PathType(typ string) {
repo.values.Set("pathType", typ)
func (ref *Referer) PathType(typ string) {
ref.values.Set("pathType", typ)
}
func (repo *Referer) DryRun(yesno bool) {
repo.values.Set("dryRun", strconv.FormatBool(yesno))
func (ref *Referer) DryRun(yesno bool) {
ref.values.Set("dryRun", strconv.FormatBool(yesno))
}
func (repo *Referer) FileEP() string {
curl := repo.urlobj.JoinPath("/v3/api/file/", repo.resource)
func (ref *Referer) FileEP() string {
curl := ref.urlobj.JoinPath("/v3/api/file/", ref.resource)
return curl.String()
}
func (repo *Referer) FilesEP() string {
curl := repo.urlobj.JoinPath("/v3/api/files/", repo.resource)
func (ref *Referer) FilesEP() string {
curl := ref.urlobj.JoinPath("/v3/api/files/", ref.resource)
return curl.String()
}
func (repo *Referer) CollectionEP() string {
curl := repo.urlobj.JoinPath("/v3/api/collection/", repo.resource)
func (ref *Referer) CollectionEP() string {
curl := ref.urlobj.JoinPath("/v3/api/collection/", ref.resource)
return curl.String()
}
func (repo *Referer) CollectionsEP() string {
curl := repo.urlobj.JoinPath("/v3/api/collections/", repo.resource)
func (ref *Referer) CollectionsEP() string {
curl := ref.urlobj.JoinPath("/v3/api/collections/", ref.resource)
return curl.String()
}
func (repo *Referer) Userinfo() (string, string) {
return repo.user, repo.pass
func (ref *Referer) Userinfo() (string, string) {
return ref.user, ref.pass
}
func (repo *Referer) SetUserinfo(user, pass string) {
func (ref *Referer) SetUserinfo(user, pass string) {
if user != "" && pass != "" {
repo.user, repo.pass = user, pass
ref.user, ref.pass = user, pass
}
}
-2
View File
@@ -27,8 +27,6 @@ func (cli *Client) BlobExists(ctx context.Context, rawrepo string, digest string
return exist, size, err
}
uri := ref.BlobEP(digest)
fmt.Println(uri)
req, err := http.NewRequestWithContext(ctx, http.MethodHead, uri, nil)
if err != nil {
return exist, size, err
+20 -14
View File
@@ -17,7 +17,7 @@ import (
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)
func (down *Loader) Push(ctx context.Context, rawref, dir, osname, arch string) error {
func (down *Loader) Push(ctx context.Context, dir, rawref, osname, arch string) error {
var err error
ref, err := NewReferer(rawref)
@@ -45,23 +45,29 @@ func (down *Loader) Push(ctx context.Context, rawref, dir, osname, arch string)
layers = append(layers, man.Layers...)
layers = append(layers, man.Config)
for _, layer := range layers {
id, _, err := down.cli.GetUpload(ctx, ref.RawRepo())
if err != nil {
return err
}
digstr := layer.Digest.String()
size, reader, err := imager.LayerReader(ctx, digstr)
exists, _, err := down.cli.BlobExists(ctx, ref.RawRepo(), digstr)
if err != nil {
return err
}
defer reader.Close()
_, err = down.cli.PatchUpload(ctx, ref.RawRepo(), reader, id, size)
if err != nil {
return err
}
_, err = down.cli.PutUpload(ctx, ref.RawRepo(), nil, id, digstr, size)
if err != nil {
return err
if !exists {
id, _, err := down.cli.GetUpload(ctx, ref.RawRepo())
if err != nil {
return err
}
size, reader, err := imager.LayerReader(ctx, digstr)
if err != nil {
return err
}
defer reader.Close()
_, err = down.cli.PatchUpload(ctx, ref.RawRepo(), reader, id, size)
if err != nil {
return err
}
_, err = down.cli.PutUpload(ctx, ref.RawRepo(), nil, id, digstr, size)
if err != nil {
return err
}
}
}
err = down.cli.PutManifest(ctx, ref.Raw(), mandata, mime)
+1 -1
View File
@@ -28,7 +28,7 @@ func TestPushImage(t *testing.T) {
load := NewLoader(cli)
require.NotNil(t, load)
err := load.Push(ctx, "localhost:1025/test:v1.0", "test-oci", "", "")
err := load.Push(ctx, "test-oci", "localhost:1025/test:v1.0", "", "")
require.NoError(t, err)
}
//return
+6
View File
@@ -144,3 +144,9 @@ func (ref *Referer) CatalogEP() string {
func (ref *Referer) Userinfo() (string, string) {
return ref.user, ref.pass
}
func (ref *Referer) SetUserinfo(user, pass string) {
if user != "" && pass != "" {
ref.user, ref.pass = user, pass
}
}