From 6fe7f7c15ed33cf8b09708e4bcb230078f786f32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9E=D0=BB=D0=B5=D0=B3=20=D0=91=D0=BE=D1=80=D0=BE=D0=B4?= =?UTF-8?q?=D0=B8=D0=BD?= Date: Wed, 11 Feb 2026 12:53:31 +0200 Subject: [PATCH] working commit --- app/handler/response.go | 16 +- cmd/mstorectl/imagecmd.go | 52 ++++- pkg/auxhttp/basic.go | 5 + pkg/{client/fileaux.go => auxtool/tmpfile.go} | 9 +- pkg/client/account.go | 131 +++++++++++++ pkg/client/cliaux.go | 79 -------- pkg/client/client.go | 35 ++-- pkg/client/file.go | 181 ++++++++++++------ pkg/client/imageaux.go | 25 +++ pkg/client/imageinfo.go | 17 +- pkg/client/imagepull.go | 14 +- pkg/client/imagepush.go | 14 +- 12 files changed, 392 insertions(+), 186 deletions(-) rename pkg/{client/fileaux.go => auxtool/tmpfile.go} (80%) create mode 100644 pkg/client/account.go delete mode 100644 pkg/client/cliaux.go diff --git a/app/handler/response.go b/app/handler/response.go index 5a7e01e..482dbbe 100644 --- a/app/handler/response.go +++ b/app/handler/response.go @@ -15,20 +15,18 @@ import ( "mstore/app/router" ) -type xxxResponse struct { - Error bool `json:"error" yaml:"error"` - Message string `json:"message,omitempty" yaml:"message,omitempty"` - Result any `json:"result,omitempty" yaml:"result,result"` -} - -type GenericResponse[T any] struct { +type Response[T any] struct { Error bool `json:"error" yaml:"error"` Message string `json:"message,omitempty" yaml:"message,omitempty"` Result T `json:"result,omitempty" yaml:"result,result"` } +func NewResponse[T any]() *Response[T] { + return &Response[T]{} +} + func (hand *Handler) SendResult(rctx *router.Context, result any) { - response := &GenericResponse[any]{ + response := &Response[any]{ Error: false, Result: result, } @@ -36,7 +34,7 @@ func (hand *Handler) SendResult(rctx *router.Context, result any) { } func (hand *Handler) SendError(rctx *router.Context, err error) { - response := &GenericResponse[any]{ + response := &Response[any]{ Error: true, Message: err.Error(), } diff --git a/cmd/mstorectl/imagecmd.go b/cmd/mstorectl/imagecmd.go index 1e1bd29..d020e7b 100644 --- a/cmd/mstorectl/imagecmd.go +++ b/cmd/mstorectl/imagecmd.go @@ -11,6 +11,9 @@ package main import ( "context" + "net/url" + "path" + "strings" "time" "mstore/pkg/client" @@ -18,6 +21,24 @@ import ( "github.com/spf13/cobra" ) +func packUserinfo(resurseuri, username, password string) (string, error) { + var err error + var res string + if !strings.Contains(resurseuri, "://") { + resurseuri = "https://" + resurseuri + } + uri, err := url.Parse(resurseuri) + if err != nil { + return res, err + } + uri.Path = path.Clean(uri.Path) + if username != "" && password != "" { + uri.User = url.UserPassword(username, password) + } + res = uri.String() + return res, err +} + func (util *ImageUtil) CreateImageCmds() *cobra.Command { const defaultTimeout uint64 = 30 // Second @@ -101,10 +122,17 @@ func (util *ImageUtil) imageInfo(params *ImageInfoParams) (*ImageInfoResult, err res := &ImageInfoResult{} ctx := context.Background() - cli := client.NewClientWithAuth(params.Username, params.Password) + cli := client.NewClient() timeout := time.Duration(params.Timeout) * time.Second - opres, err := cli.ImageInfo(ctx, params.Imagepath, timeout) + params.Imagepath, err = packUserinfo(params.Imagepath, params.Username, params.Password) + if err != nil { + return res, err + } + opres, err := cli.ImageInfo(ctx, params.Imagepath, timeout) + if err != nil { + return res, err + } res.ImageInfo = opres return res, err } @@ -131,10 +159,16 @@ func (util *ImageUtil) pullImage(params *PullImageParams) (*PullImageResult, err ctx := context.Background() res := &PullImageResult{} - cli := client.NewClientWithAuth(params.Username, params.Password) + cli := client.NewClient() timeout := time.Duration(params.Timeout) * time.Second + params.Imagepath, err = packUserinfo(params.Imagepath, params.Username, params.Password) + if err != nil { + return res, err + } err = cli.PullImage(ctx, params.Imagepath, params.Filepath, timeout) - + if err != nil { + return res, err + } return res, err } @@ -159,9 +193,15 @@ func (util *ImageUtil) pushImage(params *PushImageParams) (*PushImageResult, err ctx := context.Background() res := &PushImageResult{} - cli := client.NewClientWithAuth(params.Username, params.Password) + cli := client.NewClient() timeout := time.Duration(params.Timeout) * time.Second + params.Imagepath, err = packUserinfo(params.Imagepath, params.Username, params.Password) + if err != nil { + return res, err + } err = cli.PushImage(ctx, params.Filepath, params.Imagepath, timeout) - + if err != nil { + return res, err + } return res, err } diff --git a/pkg/auxhttp/basic.go b/pkg/auxhttp/basic.go index e63dc57..a143005 100644 --- a/pkg/auxhttp/basic.go +++ b/pkg/auxhttp/basic.go @@ -16,6 +16,11 @@ import ( "strings" ) +func EncodeBasicAuth(username, password string) string { + auth := username + ":" + password + return "Basic " + base64.StdEncoding.EncodeToString([]byte(auth)) +} + func ParseBasicAuth(basicFields string) (string, string, error) { var err error var username string diff --git a/pkg/client/fileaux.go b/pkg/auxtool/tmpfile.go similarity index 80% rename from pkg/client/fileaux.go rename to pkg/auxtool/tmpfile.go index 64b4dc5..5fd7083 100644 --- a/pkg/client/fileaux.go +++ b/pkg/auxtool/tmpfile.go @@ -7,15 +7,20 @@ * Distribution of this work is permitted, but commercial use and * modifications are strictly prohibited. */ -package client +package auxtool import ( "encoding/hex" "fmt" "math/rand" + "time" ) -func makeTmpFileName(prefix string) string { +func init() { + rand.Seed(time.Now().UnixNano()) +} + +func MakeTmpFilename(prefix string) string { randBytes := make([]byte, 6) rand.Read(randBytes) suffix := hex.EncodeToString(randBytes) diff --git a/pkg/client/account.go b/pkg/client/account.go new file mode 100644 index 0000000..17002f1 --- /dev/null +++ b/pkg/client/account.go @@ -0,0 +1,131 @@ +/* + * 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 ( + "bytes" + "context" + "crypto/tls" + "encoding/json" + "fmt" + "io" + "net/http" + "net/url" + + "mstore/app/handler" + "mstore/app/operator" + "mstore/pkg/auxhttp" +) + +func (cli *Client) CreateAccount(ctx context.Context, hosturi, username, password string) error { + var err error + + apiuri, err := url.JoinPath(hosturi, "/v3/api/account/get") + if err != nil { + return err + } + operParams := operator.CreateAccountParams{ + Username: username, + Password: password, + } + paramsJson, err := json.Marshal(operParams) + if err != nil { + return err + } + respBytes, err := doHTTPCall(ctx, apiuri, paramsJson) + if err != nil { + return err + } + + operRes := handler.NewResponse[operator.CreateAccountResult]() + err = json.Unmarshal(respBytes, operRes) + if err != nil { + return err + } + if !operRes.Error { + err = fmt.Errorf("%s", operRes.Message) + return err + } + return err +} + +func (cli *Client) GetAccount(ctx context.Context, hosturi, id, username string) error { + var err error + + apipath, err := url.JoinPath(hosturi, "/v3/api/account/get") + if err != nil { + return err + } + operParams := operator.GetAccountParams{ + Username: username, + AccountID: id, + } + paramsJson, err := json.Marshal(operParams) + if err != nil { + return err + } + respBytes, err := doHTTPCall(ctx, apipath, paramsJson) + if err != nil { + return err + } + + operRes := handler.NewResponse[operator.CreateAccountResult]() + err = json.Unmarshal(respBytes, operRes) + if err != nil { + return err + } + if !operRes.Error { + err = fmt.Errorf("%s", operRes.Message) + return err + } + return err +} + +func doHTTPCall(ctx context.Context, apiuri string, reqBytes []byte) ([]byte, error) { + var err error + respBytes := make([]byte, 0) + + apiuri, username, password, err := repackServiceURI(apiuri) + if err != nil { + return respBytes, err + } + reqBuffer := bytes.NewBuffer(reqBytes) + httpReq, err := http.NewRequestWithContext(ctx, http.MethodPost, apiuri, reqBuffer) + if err != nil { + return respBytes, err + } + httpReq.Header.Set("Content-Type", "application/json") + if username != "" && password != "" { + basicHeader := auxhttp.EncodeBasicAuth(username, password) + httpReq.Header.Add("Authorization", basicHeader) + } + transport := &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + } + httpClient := &http.Client{ + Transport: transport, + } + httpResp, err := httpClient.Do(httpReq) + if err != nil { + return respBytes, err + } + defer httpResp.Body.Close() + if httpResp.StatusCode != http.StatusOK { + err := fmt.Errorf("Wrong StatusCode header: %s", httpResp.Status) + return respBytes, err + } + respBuffer := bytes.NewBuffer(nil) + _, err = io.Copy(respBuffer, httpResp.Body) + if err != nil { + return respBytes, err + } + respBytes = respBuffer.Bytes() + return respBytes, err +} diff --git a/pkg/client/cliaux.go b/pkg/client/cliaux.go deleted file mode 100644 index a319804..0000000 --- a/pkg/client/cliaux.go +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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 ( - "encoding/base64" - "net/url" - "path" - "strings" -) - -const ( - serviceAPI = "/v3/api/service/" - fileAPI = "/v3/api/file/" - filesAPI = "/v3/api/files/" -) - -func encodeBasicAuth(username, password string) string { - auth := username + ":" + password - return "Basic " + base64.StdEncoding.EncodeToString([]byte(auth)) -} - -func convertServiceRefer(ref string) (string, error) { - var err error - var res string - if !strings.Contains(ref, "://") { - ref = "https://" + ref - } - url, err := url.Parse(ref) - if err != nil { - return res, err - } - url.Path = path.Clean(url.Path) - url.Path = path.Join(serviceAPI, url.Path) - url.User = nil - res = url.String() - return res, err -} - -func convertFileRefer(ref string) (string, error) { - var err error - var res string - if !strings.Contains(ref, "://") { - ref = "https://" + ref - } - url, err := url.Parse(ref) - if err != nil { - return res, err - } - url.Path = path.Clean(url.Path) - url.Path = path.Join(fileAPI, url.Path) - url.User = nil - res = url.String() - return res, err -} - -func convertFilesRefer(ref string) (string, error) { - var err error - var res string - if !strings.Contains(ref, "://") { - ref = "https://" + ref - } - url, err := url.Parse(ref) - if err != nil { - return res, err - } - url.Path = path.Clean(url.Path) - url.Path = path.Join(filesAPI, url.Path) - url.User = nil - res = url.String() - return res, err -} diff --git a/pkg/client/client.go b/pkg/client/client.go index a752d07..027058b 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -13,40 +13,47 @@ import ( "context" "crypto/tls" "net/http" + "net/url" "time" ) -type Client struct { - username string - password string -} +type Client struct{} func NewClient() *Client { return &Client{} } -func NewClientWithAuth(username, password string) *Client { - return &Client{ - username: username, - password: password, +func convertServiceURI(ref string) (string, error) { + var err error + var res string + const serviceAPI = "/v3/api/service/" + const serviceScheme = "https" + uri, err := url.Parse(ref) + if err != nil { + return res, err } + uri.Path = serviceAPI + uri.Scheme = serviceScheme + res = uri.String() + return res, err } -func (cli *Client) ServiceHello(ctx context.Context, ref string, timeout time.Duration) (bool, error) { +func (cli *Client) ServiceHello(ctx context.Context, serviceuri string, timeout time.Duration) (bool, error) { var res bool var err error - ctx, _ = context.WithTimeout(ctx, timeout) - - ref, err = convertServiceRefer(ref) + serviceuri, _, _, err = repackServiceURI(serviceuri) if err != nil { return res, err } - req, err := http.NewRequestWithContext(ctx, http.MethodGet, ref, nil) + serviceuri, err = convertServiceURI(serviceuri) + if err != nil { + return res, err + } + req, err := http.NewRequestWithContext(ctx, http.MethodGet, serviceuri, nil) if err != nil { return res, err } - transport := &http.Transport{ TLSClientConfig: &tls.Config{ InsecureSkipVerify: true, diff --git a/pkg/client/file.go b/pkg/client/file.go index 717ff19..405ebf6 100644 --- a/pkg/client/file.go +++ b/pkg/client/file.go @@ -15,28 +15,17 @@ import ( "fmt" "io" "net/http" + "net/url" "os" + "path" "path/filepath" "strconv" + "strings" + + "mstore/pkg/auxhttp" ) -func (cli *Client) FileExists(ctx context.Context, ref string) (bool, error) { - var res bool - var err error - - ref, err = convertFileRefer(ref) - if err != nil { - return res, err - } - req, err := http.NewRequestWithContext(ctx, http.MethodHead, ref, nil) - if err != nil { - return res, err - } - - if cli.username != "" && cli.password != "" { - req.Header.Add("Authorization", encodeBasicAuth(cli.username, cli.password)) - } - +func makeHTTPClient() *http.Client { transport := &http.Transport{ TLSClientConfig: &tls.Config{ InsecureSkipVerify: true, @@ -45,6 +34,80 @@ func (cli *Client) FileExists(ctx context.Context, ref string) (bool, error) { client := &http.Client{ Transport: transport, } + return client +} + +func convertFileURI(fileuri string) (string, error) { + var err error + var res string + uri, err := url.Parse(fileuri) + if err != nil { + return res, err + } + const fileAPI = "/v3/api/file/" + uri.Path, err = url.JoinPath(fileAPI, uri.Path) + if err != nil { + return res, err + } + + res = uri.String() + return res, err +} + +func convertFilesURI(fileuri string) (string, error) { + var err error + var res string + uri, err := url.Parse(fileuri) + const filesAPI = "/v3/api/files/" + uri.Path, err = url.JoinPath(filesAPI, uri.Path) + if err != nil { + return res, err + } + res = uri.String() + return res, err +} + +func repackServiceURI(fileuri string) (string, string, string, error) { + var err error + var res, username, password string + if !strings.Contains(fileuri, "://") { + fileuri = "https://" + fileuri + } + uri, err := url.Parse(fileuri) + if err != nil { + return res, username, password, err + } + uri.Path = path.Clean(uri.Path) + if uri.User != nil { + username = uri.User.Username() + password, _ = uri.User.Password() + } + uri.User = nil + uri.Scheme = "https" + res = uri.String() + return res, username, password, err +} + +func (cli *Client) FileExists(ctx context.Context, fileuri string) (bool, error) { + var res bool + var err error + fileuri, username, password, err := repackServiceURI(fileuri) + if err != nil { + return res, err + } + fileuri, err = convertFileURI(fileuri) + if err != nil { + return res, err + } + req, err := http.NewRequestWithContext(ctx, http.MethodHead, fileuri, nil) + if err != nil { + return res, err + } + if username != "" && password != "" { + basic := auxhttp.EncodeBasicAuth(username, password) + req.Header.Add("Authorization", basic) + } + client := makeHTTPClient() resp, err := client.Do(req) if err != nil { return res, err @@ -56,9 +119,14 @@ func (cli *Client) FileExists(ctx context.Context, ref string) (bool, error) { return res, err } -func (cli *Client) PutFile(ctx context.Context, filename, ref string) error { +func (cli *Client) PutFile(ctx context.Context, filename, fileuri string) error { var err error - ref, err = convertFileRefer(ref) + fileuri, username, password, err := repackServiceURI(fileuri) + if err != nil { + return err + } + + fileuri, err = convertFileURI(fileuri) if err != nil { return err } @@ -68,23 +136,10 @@ func (cli *Client) PutFile(ctx context.Context, filename, ref string) error { } defer file.Close() - req, err := http.NewRequestWithContext(ctx, http.MethodPut, ref, file) + req, err := http.NewRequestWithContext(ctx, http.MethodPut, fileuri, file) if err != nil { return err } - - if cli.username != "" && cli.password != "" { - req.Header.Add("Authorization", encodeBasicAuth(cli.username, cli.password)) - } - - transport := &http.Transport{ - TLSClientConfig: &tls.Config{ - InsecureSkipVerify: true, - }, - } - client := &http.Client{ - Transport: transport, - } fileinfo, err := os.Stat(filename) if err != nil { return err @@ -93,6 +148,11 @@ func (cli *Client) PutFile(ctx context.Context, filename, ref string) error { req.ContentLength = filesize req.Header.Set("Content-Type", "application/octet-stream") + if username != "" && password != "" { + basic := auxhttp.EncodeBasicAuth(username, password) + req.Header.Add("Authorization", basic) + } + client := makeHTTPClient() resp, err := client.Do(req) if err != nil { @@ -107,31 +167,31 @@ func (cli *Client) PutFile(ctx context.Context, filename, ref string) error { return err } -func (cli *Client) GetFile(ctx context.Context, ref, filename string) (int64, error) { +func (cli *Client) GetFile(ctx context.Context, fileuri, filename string) (int64, error) { var err error var size int64 - ref, err = convertFileRefer(ref) + + fileuri, username, password, err := repackServiceURI(fileuri) if err != nil { return size, err } - req, err := http.NewRequestWithContext(ctx, http.MethodGet, ref, nil) + fileuri, err = convertFileURI(fileuri) if err != nil { return size, err } - if cli.username != "" && cli.password != "" { - req.Header.Add("Authorization", encodeBasicAuth(cli.username, cli.password)) + req, err := http.NewRequestWithContext(ctx, http.MethodGet, fileuri, nil) + if err != nil { + return size, err } - transport := &http.Transport{ - TLSClientConfig: &tls.Config{ - InsecureSkipVerify: true, - }, - } - client := &http.Client{ - Transport: transport, + if username != "" && password != "" { + basic := auxhttp.EncodeBasicAuth(username, password) + req.Header.Add("Authorization", basic) } + + client := makeHTTPClient() resp, err := client.Do(req) if err != nil { return size, err @@ -172,29 +232,28 @@ func (cli *Client) GetFile(ctx context.Context, ref, filename string) (int64, er return size, err } -func (cli *Client) DeleteFile(ctx context.Context, ref, filename string) error { +func (cli *Client) DeleteFile(ctx context.Context, fileuri, filename string) error { var err error - ref, err = convertFileRefer(ref) - if err != nil { - return err - } - req, err := http.NewRequestWithContext(ctx, http.MethodDelete, ref, nil) + + fileuri, username, password, err := repackServiceURI(fileuri) if err != nil { return err } - if cli.username != "" && cli.password != "" { - req.Header.Add("Authorization", encodeBasicAuth(cli.username, cli.password)) + fileuri, err = convertFileURI(fileuri) + if err != nil { + return err + } + req, err := http.NewRequestWithContext(ctx, http.MethodDelete, fileuri, nil) + if err != nil { + return err + } + if username != "" && password != "" { + basic := auxhttp.EncodeBasicAuth(username, password) + req.Header.Add("Authorization", basic) } - transport := &http.Transport{ - TLSClientConfig: &tls.Config{ - InsecureSkipVerify: true, - }, - } - client := &http.Client{ - Transport: transport, - } + client := makeHTTPClient() resp, err := client.Do(req) if err != nil { return err diff --git a/pkg/client/imageaux.go b/pkg/client/imageaux.go index dadbfc4..dd177a4 100644 --- a/pkg/client/imageaux.go +++ b/pkg/client/imageaux.go @@ -12,6 +12,8 @@ package client import ( "crypto/tls" "net/http" + "net/url" + "strings" ) type roundTripper struct{} @@ -25,3 +27,26 @@ func (t *roundTripper) RoundTrip(r *http.Request) (*http.Response, error) { } return httpTransport.RoundTrip(r) } + +func repackReference(ref string) (string, string, string, error) { + var err error + var username string + var password string + if !strings.Contains(ref, `://`) { + ref = "https://" + ref + } + uri, err := url.Parse(ref) + if err != nil { + return ref, username, password, err + } + username = uri.User.Username() + password, _ = uri.User.Password() + uri.User = nil + + uri.Path, _ = url.JoinPath("/", uri.Path) + if err != nil { + return ref, username, password, err + } + ref = uri.Host + uri.Path + return ref, username, password, err +} diff --git a/pkg/client/imageinfo.go b/pkg/client/imageinfo.go index 3440ed7..3738758 100644 --- a/pkg/client/imageinfo.go +++ b/pkg/client/imageinfo.go @@ -31,8 +31,11 @@ func (cli *Client) ImageInfo(ctx context.Context, imagepath string, timeout time var err error res := &ImageDescr{} + imagepath, username, password, err := repackReference(imagepath) + if err != nil { + return res, err + } ctx, _ = context.WithTimeout(ctx, timeout) - options := make([]crane.Option, 0) options = append(options, crane.WithContext(ctx)) @@ -45,7 +48,7 @@ func (cli *Client) ImageInfo(ctx context.Context, imagepath string, timeout time return res, err } - if cli.username != "" && cli.password != "" { + if username != "" && password != "" { defaultTransport := &roundTripper{} scopes := []string{repo.Scope(transport.PullScope)} @@ -55,8 +58,8 @@ func (cli *Client) ImageInfo(ctx context.Context, imagepath string, timeout time return res, err } basicAuth := &authn.Basic{ - Username: cli.username, - Password: cli.password, + Username: username, + Password: password, } authTransport, err := transport.NewWithContext(ctx, reg, basicAuth, defaultTransport, scopes) if err != nil { @@ -90,7 +93,7 @@ func (cli *Client) ImageInfo(ctx context.Context, imagepath string, timeout time remoteOptions := make([]remote.Option, 0) remoteOptions = append(remoteOptions, remote.WithContext(ctx)) - if cli.username != "" && cli.password != "" { + if username != "" && password != "" { defaultTransport := &roundTripper{} scopes := []string{repo.Scope(transport.PullScope)} @@ -100,8 +103,8 @@ func (cli *Client) ImageInfo(ctx context.Context, imagepath string, timeout time return res, err } basicAuth := &authn.Basic{ - Username: cli.username, - Password: cli.password, + Username: username, + Password: password, } authTransport, err := transport.NewWithContext(ctx, reg, basicAuth, defaultTransport, scopes) if err != nil { diff --git a/pkg/client/imagepull.go b/pkg/client/imagepull.go index 878960e..2f00f6c 100644 --- a/pkg/client/imagepull.go +++ b/pkg/client/imagepull.go @@ -14,6 +14,7 @@ import ( "os" "time" + "mstore/pkg/auxtool" "mstore/pkg/auxutar" "github.com/google/go-containerregistry/pkg/authn" @@ -26,10 +27,15 @@ func (cli *Client) PullImage(ctx context.Context, filepath, imagepath string, ti var err error ctx, _ = context.WithTimeout(ctx, timeout) + imagepath, username, password, err := repackReference(imagepath) + if err != nil { + return err + } + options := make([]crane.Option, 0) options = append(options, crane.WithContext(ctx)) - if cli.username != "" && cli.password != "" { + if username != "" && password != "" { ref, err := name.ParseReference(imagepath) if err != nil { return err @@ -48,8 +54,8 @@ func (cli *Client) PullImage(ctx context.Context, filepath, imagepath string, ti return err } basicAuth := &authn.Basic{ - Username: cli.username, - Password: cli.password, + Username: username, + Password: password, } authTransport, err := transport.NewWithContext(ctx, reg, basicAuth, defaultTransport, scopes) if err != nil { @@ -65,7 +71,7 @@ func (cli *Client) PullImage(ctx context.Context, filepath, imagepath string, ti if err != nil { return err } - dstdir := makeTmpFileName(filepath) + dstdir := auxtool.MakeTmpFilename(filepath) err = os.MkdirAll(dstdir, 0750) if err != nil { return err diff --git a/pkg/client/imagepush.go b/pkg/client/imagepush.go index 0c79a77..35ffbfe 100644 --- a/pkg/client/imagepush.go +++ b/pkg/client/imagepush.go @@ -15,6 +15,7 @@ import ( "os" "time" + "mstore/pkg/auxtool" "mstore/pkg/auxutar" "github.com/google/go-containerregistry/pkg/authn" @@ -29,9 +30,14 @@ func (cli *Client) PushImage(ctx context.Context, filepath, imagepath string, ti var err error ctx, _ = context.WithTimeout(ctx, timeout) + imagepath, username, password, err := repackReference(imagepath) + if err != nil { + return err + } + options := make([]crane.Option, 0) options = append(options, crane.WithContext(ctx)) - if cli.username != "" && cli.password != "" { + if username != "" && password != "" { ref, err := name.ParseReference(imagepath) if err != nil { return err @@ -53,8 +59,8 @@ func (cli *Client) PushImage(ctx context.Context, filepath, imagepath string, ti return err } basicAuth := &authn.Basic{ - Username: cli.username, - Password: cli.password, + Username: username, + Password: password, } authTransport, err := transport.NewWithContext(ctx, reg, basicAuth, defaultTransport, scopes) @@ -67,7 +73,7 @@ func (cli *Client) PushImage(ctx context.Context, filepath, imagepath string, ti options = append(options, crane.WithTransport(defaultTransport)) } - dstdir := makeTmpFileName(filepath) + dstdir := auxtool.MakeTmpFilename(filepath) err = auxutar.Unarchive(filepath, dstdir) if err != nil { os.RemoveAll(dstdir)