!80 isula-build:Sync upstream patches

From: @DCCooper
Reviewed-by: @jingxiaolu
Signed-off-by: @jingxiaolu
This commit is contained in:
openeuler-ci-bot 2021-03-04 09:44:06 +08:00 committed by Gitee
commit 9eae1d51d2
11 changed files with 1469 additions and 3 deletions

View File

@ -1 +1 @@
0.9.5-5
0.9.5-6

View File

@ -1 +1 @@
4678e505019fae52f1801e172fd19c84ddfc0a70
b82408f23540642f79ab000483086997321305bf

View File

@ -2,7 +2,7 @@
Name: isula-build
Version: 0.9.5
Release: 5
Release: 6
Summary: A tool to build container images
License: Mulan PSL V2
URL: https://gitee.com/openeuler/isula-build
@ -85,6 +85,12 @@ fi
/usr/share/bash-completion/completions/isula-build
%changelog
* Wed Mar 03 2021 lixiang <lixiang172@huawei.com> - 0.9.5-6
- Type:enhancement
- CVE:NA
- SUG:restart
- DESC:sync patches from upstream
* Wed Feb 10 2021 lixiang <lixiang172@huawei.com> - 0.9.5-5
- Type:enhancement
- CVE:NA

View File

@ -0,0 +1,136 @@
From 34fdae49f82410a8bcc9c6f5940af01a24538de6 Mon Sep 17 00:00:00 2001
From: meilier <xingweizheng@huawei.com>
Date: Thu, 4 Feb 2021 18:40:31 +0800
Subject: [PATCH 01/10] fix some make checkall golangci-lint flaws
---
builder/dockerfile/container/container_src.go | 2 +-
builder/dockerfile/container/help.go | 2 +-
daemon/load.go | 4 ++--
daemon/login.go | 4 ++--
daemon/logout.go | 4 ++--
daemon/save.go | 2 --
pkg/manifest/list.go | 2 +-
util/util.go | 2 --
8 files changed, 9 insertions(+), 13 deletions(-)
diff --git a/builder/dockerfile/container/container_src.go b/builder/dockerfile/container/container_src.go
index ff52ee2c..9426ec76 100644
--- a/builder/dockerfile/container/container_src.go
+++ b/builder/dockerfile/container/container_src.go
@@ -98,7 +98,7 @@ func (i *containerImageSource) GetBlob(ctx context.Context, blob types.BlobInfo,
return nil, -1, errors.Wrapf(err, "blob file %q is not exit", blobFile)
}
- layerFile, err := os.OpenFile(blobFile, os.O_RDONLY, constant.DefaultRootFileMode)
+ layerFile, err := os.OpenFile(filepath.Clean(blobFile), os.O_RDONLY, constant.DefaultRootFileMode)
if err != nil {
return nil, -1, errors.Wrapf(err, "open the blob file %q failed", blobFile)
}
diff --git a/builder/dockerfile/container/help.go b/builder/dockerfile/container/help.go
index c5aa381d..475b479d 100644
--- a/builder/dockerfile/container/help.go
+++ b/builder/dockerfile/container/help.go
@@ -170,7 +170,7 @@ func (ref *Reference) saveLayerToStorage(path string, layer *storage.Layer) (dif
}()
filename := filepath.Join(path, "layer")
- layerFile, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY, constant.DefaultRootFileMode)
+ layerFile, err := os.OpenFile(filepath.Clean(filename), os.O_CREATE|os.O_WRONLY, constant.DefaultRootFileMode)
if err != nil {
return "", des, errors.Wrapf(err, "error opening file: %s", filename)
}
diff --git a/daemon/load.go b/daemon/load.go
index 08fb5b1f..d756f9ed 100644
--- a/daemon/load.go
+++ b/daemon/load.go
@@ -55,8 +55,8 @@ func (b *Backend) Load(req *pb.LoadRequest, stream pb.Control_LoadServer) error
)
opts := b.getLoadOptions(req)
- if err := util.CheckLoadFile(req.Path); err != nil {
- return err
+ if cErr := util.CheckLoadFile(req.Path); cErr != nil {
+ return cErr
}
repoTags, err = tryToParseImageFormatFromTarball(b.daemon.opts.DataRoot, &opts)
diff --git a/daemon/login.go b/daemon/login.go
index e3399983..6eeda28e 100644
--- a/daemon/login.go
+++ b/daemon/login.go
@@ -60,8 +60,8 @@ func (b *Backend) Login(ctx context.Context, req *pb.LoginRequest) (*pb.LoginRes
}
if loginWithAuthFile(req) {
- auth, err := config.GetCredentials(sysCtx, req.Server)
- if err != nil || auth.Password == "" {
+ auth, gErr := config.GetCredentials(sysCtx, req.Server)
+ if gErr != nil || auth.Password == "" {
auth = types.DockerAuthConfig{}
return &pb.LoginResponse{Content: errTryToUseAuth}, errors.Errorf("failed to read auth file: %v", errTryToUseAuth)
}
diff --git a/daemon/logout.go b/daemon/logout.go
index 355b1f7a..d1fbebcb 100644
--- a/daemon/logout.go
+++ b/daemon/logout.go
@@ -47,8 +47,8 @@ func (b *Backend) Logout(ctx context.Context, req *pb.LogoutRequest) (*pb.Logout
}
if req.All {
- if err := config.RemoveAllAuthentication(sysCtx); err != nil {
- return &pb.LogoutResponse{Result: "Remove authentications failed"}, err
+ if rErr := config.RemoveAllAuthentication(sysCtx); rErr != nil {
+ return &pb.LogoutResponse{Result: "Remove authentications failed"}, rErr
}
logrus.Info("Success logout from all servers")
diff --git a/daemon/save.go b/daemon/save.go
index 3dce7bdf..c6411e04 100644
--- a/daemon/save.go
+++ b/daemon/save.go
@@ -17,7 +17,6 @@ import (
"context"
"os"
- "github.com/containers/image/v5/docker/archive"
"github.com/containers/image/v5/types"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@@ -34,7 +33,6 @@ import (
)
type saveOptions struct {
- writer *archive.Writer
sysCtx *types.SystemContext
logger *logger.Logger
localStore *store.Store
diff --git a/pkg/manifest/list.go b/pkg/manifest/list.go
index 3f8b2fed..381746f7 100644
--- a/pkg/manifest/list.go
+++ b/pkg/manifest/list.go
@@ -129,7 +129,7 @@ func (l *List) SaveListToImage(store *store.Store, imageID, name string) (string
return "", errors.Wrapf(err, "save manifest list to image %v error", imageID)
}
- //marshal list instance information
+ // marshal list instance information
instancesBytes, err := json.Marshal(&l.instances)
if err != nil {
return "", errors.Wrap(err, "marshall list instances error")
diff --git a/util/util.go b/util/util.go
index 61458c73..3f46d796 100644
--- a/util/util.go
+++ b/util/util.go
@@ -57,8 +57,6 @@ const (
var (
// DefaultRegistryPathPrefix is the map for registry and path
DefaultRegistryPathPrefix map[string]string
- // clientExporters to map exporter whether will export the image to client
- clientExporters map[string]bool
)
func init() {
--
2.27.0

View File

@ -0,0 +1,66 @@
From c0d4159d7719fb94b4b421415b8f367c6f61c68e Mon Sep 17 00:00:00 2001
From: DCCooper <1866858@gmail.com>
Date: Mon, 8 Feb 2021 10:22:33 +0800
Subject: [PATCH 02/10] enhancement: add go test for RUN panic problem
Signed-off-by: DCCooper <1866858@gmail.com>
---
builder/dockerfile/parser/parser_test.go | 18 ++++++++++++++----
.../testfiles/preprocess/run_with_directive | 2 ++
2 files changed, 16 insertions(+), 4 deletions(-)
create mode 100644 builder/dockerfile/parser/testfiles/preprocess/run_with_directive
diff --git a/builder/dockerfile/parser/parser_test.go b/builder/dockerfile/parser/parser_test.go
index f0cce1e9..3da5bea6 100644
--- a/builder/dockerfile/parser/parser_test.go
+++ b/builder/dockerfile/parser/parser_test.go
@@ -69,8 +69,9 @@ func TestPreProcess(t *testing.T) {
func TestFormat(t *testing.T) {
type testcase struct {
- name string
- expect int
+ name string
+ expect int
+ wantErr bool
}
var testcases = []testcase{
{
@@ -89,6 +90,10 @@ func TestFormat(t *testing.T) {
name: "yum_config",
expect: 8,
},
+ {
+ name: "run_with_directive",
+ wantErr: true,
+ },
}
for _, tc := range testcases {
@@ -103,8 +108,13 @@ func TestFormat(t *testing.T) {
d, err := newDirective(bytes.NewReader(buf.Bytes()))
assert.NilError(t, err)
lines, err := format(rows, d)
- assert.NilError(t, err)
- assert.Equal(t, len(lines), tc.expect)
+ if (err != nil) != tc.wantErr {
+ t.Errorf("Testing failed. Expected: %v, got: %v", tc.wantErr, err)
+ }
+ if !tc.wantErr {
+ assert.NilError(t, err, file)
+ assert.Equal(t, len(lines), tc.expect)
+ }
})
}
}
diff --git a/builder/dockerfile/parser/testfiles/preprocess/run_with_directive b/builder/dockerfile/parser/testfiles/preprocess/run_with_directive
new file mode 100644
index 00000000..3f3465d3
--- /dev/null
+++ b/builder/dockerfile/parser/testfiles/preprocess/run_with_directive
@@ -0,0 +1,2 @@
+FROM scratch
+RUN \
--
2.27.0

View File

@ -0,0 +1,340 @@
From 947fc1ef0c103f687e195c467ddabd3cf0aa746f Mon Sep 17 00:00:00 2001
From: meilier <xingweizheng@huawei.com>
Date: Sat, 20 Feb 2021 00:42:55 +0800
Subject: [PATCH 06/10] fix load oci image panic
---
cmd/cli/save.go | 3 +
cmd/cli/save_test.go | 18 +++++
daemon/load.go | 11 +--
daemon/load_test.go | 188 +++++++++++++++++++++++++++++++++++--------
4 files changed, 181 insertions(+), 39 deletions(-)
diff --git a/cmd/cli/save.go b/cmd/cli/save.go
index 64dc8acc..fe676731 100644
--- a/cmd/cli/save.go
+++ b/cmd/cli/save.go
@@ -72,6 +72,9 @@ func saveCommand(cmd *cobra.Command, args []string) error {
if len(args) == 0 {
return errors.New("save accepts at least one image")
}
+ if saveOpts.format == exporter.OCITransport && len(args) >= 2 {
+ return errors.New("oci image format now only supports saving single image")
+ }
if err := exporter.CheckImageFormat(saveOpts.format); err != nil {
return err
}
diff --git a/cmd/cli/save_test.go b/cmd/cli/save_test.go
index 4183aa8b..3fe6bf81 100644
--- a/cmd/cli/save_test.go
+++ b/cmd/cli/save_test.go
@@ -38,6 +38,8 @@ func TestSaveCommand(t *testing.T) {
wantErr bool
}
+ // For normal cases, default err is "invalid socket path: unix:///var/run/isula_build.sock".
+ // As daemon is not running as we run unit test.
var testcases = []testcase{
{
name: "TC1 - normal case with format docker",
@@ -103,6 +105,22 @@ func TestSaveCommand(t *testing.T) {
errString: "colon in path",
format: "docker",
},
+ {
+ name: "TC9 - normal case save multiple images with format docker",
+ path: tmpDir.Join("test9"),
+ args: []string{"testImage1", "testImage2"},
+ wantErr: true,
+ errString: "isula_build.sock",
+ format: "docker",
+ },
+ {
+ name: "TC10 - abnormal case save multiple images with format oci",
+ path: tmpDir.Join("test10"),
+ args: []string{"testImage1", "testImage2"},
+ wantErr: true,
+ errString: "oci image format now only supports saving single image",
+ format: "oci",
+ },
}
for _, tc := range testcases {
diff --git a/daemon/load.go b/daemon/load.go
index d756f9ed..b557d386 100644
--- a/daemon/load.go
+++ b/daemon/load.go
@@ -147,7 +147,6 @@ func tryToParseImageFormatFromTarball(dataRoot string, opts *loadOptions) ([][]s
func getDockerRepoTagFromImageTar(systemContext *types.SystemContext, path string) ([][]string, error) {
// tmp dir will be removed after NewSourceFromFileWithContext
-
tarfileSource, err := tarfile.NewSourceFromFileWithContext(systemContext, path)
if err != nil {
return nil, errors.Wrapf(err, "failed to get the source of loading tar file")
@@ -168,8 +167,7 @@ func getDockerRepoTagFromImageTar(systemContext *types.SystemContext, path strin
func getOCIRepoTagFromImageTar(systemContext *types.SystemContext, path string) ([][]string, error) {
var (
- allRepoTags [][]string
- err error
+ err error
)
srcRef, err := alltransports.ParseImageName(exporter.FormatTransport(exporter.OCIArchiveTransport, path))
@@ -179,14 +177,13 @@ func getOCIRepoTagFromImageTar(systemContext *types.SystemContext, path string)
tarManifest, err := ociarchive.LoadManifestDescriptorWithContext(systemContext, srcRef)
if err != nil {
- return nil, errors.Wrapf(err, "failed to loadmanifest descriptor of oci image format")
+ return nil, errors.Wrapf(err, "failed to load manifest descriptor of oci image format")
}
- // If index.json has no reference name, compute the image digest instead
// For now, we only support load single image in archive file
if _, ok := tarManifest.Annotations[imgspecv1.AnnotationRefName]; ok {
- allRepoTags = [][]string{{tarManifest.Annotations[imgspecv1.AnnotationRefName]}}
+ return [][]string{{tarManifest.Annotations[imgspecv1.AnnotationRefName]}}, nil
}
- return allRepoTags, nil
+ return [][]string{{}}, nil
}
diff --git a/daemon/load_test.go b/daemon/load_test.go
index 0513a889..cbcb5d8f 100644
--- a/daemon/load_test.go
+++ b/daemon/load_test.go
@@ -30,6 +30,12 @@ import (
"isula.org/isula-build/store"
)
+const (
+ loadedTarFile = "load.tar"
+ manifestJSONFile = "manifest.json"
+ indexJSONFile = "index.json"
+)
+
var (
localStore store.Store
daemon *Daemon
@@ -51,10 +57,10 @@ func (x *controlLoadServer) Context() context.Context {
return context.Background()
}
-func prepareLoadTar(dir *fs.Dir) error {
- manifest := dir.Join("manifest.json")
+func prepareLoadTar(dir *fs.Dir, jsonFile string) error {
+ manifest := dir.Join(jsonFile)
- fi, err := os.Create(dir.Join("load.tar"))
+ fi, err := os.Create(dir.Join(loadedTarFile))
if err != nil {
return nil
}
@@ -88,9 +94,9 @@ func prepareLoadTar(dir *fs.Dir) error {
}
-func prepareForLoad(t *testing.T, manifest string) *fs.Dir {
- tmpDir := fs.NewDir(t, t.Name(), fs.WithFile("manifest.json", manifest))
- if err := prepareLoadTar(tmpDir); err != nil {
+func prepareForLoad(t *testing.T, jsonFile, manifest string) *fs.Dir {
+ tmpDir := fs.NewDir(t, t.Name(), fs.WithFile(jsonFile, manifest))
+ if err := prepareLoadTar(tmpDir, jsonFile); err != nil {
tmpDir.Remove()
return nil
}
@@ -119,34 +125,152 @@ func clean(dir *fs.Dir) {
dir.Remove()
}
-func TestLoad(t *testing.T) {
- manifestJSON :=
- `[
- {
- "Config":"76a4dd2d5d6a18323ac8d90f959c3c8562bf592e2a559bab9b462ab600e9e5fc.json",
- "RepoTags":[
- "hello:latest"
- ],
- "Layers":[
- "6eb4c21cc3fcb729a9df230ae522c1d3708ca66e5cf531713dbfa679837aa287.tar",
- "37841116ad3b1eeea972c75ab8bad05f48f721a7431924bc547fc91c9076c1c8.tar"
- ]
+func TestLoadSingleImage(t *testing.T) {
+ testcases := []struct {
+ name string
+ manifest string
+ format string
+ tarPath string
+ withTag bool
+ wantErr bool
+ errString string
+ }{
+ {
+ name: "TC1 normal case load docker tar",
+ manifest: `[
+ {
+ "Config":"76a4dd2d5d6a18323ac8d90f959c3c8562bf592e2a559bab9b462ab600e9e5fc.json",
+ "RepoTags":[
+ "hello:latest"
+ ],
+ "Layers":[
+ "6eb4c21cc3fcb729a9df230ae522c1d3708ca66e5cf531713dbfa679837aa287.tar",
+ "37841116ad3b1eeea972c75ab8bad05f48f721a7431924bc547fc91c9076c1c8.tar"
+ ]
+ }
+ ]`,
+ format: "docker",
+ withTag: true,
+ },
+ {
+ name: "TC2 normal case load oci tar",
+ manifest: `{
+ "schemaVersion": 2,
+ "manifests": [
+ {
+ "mediaType": "application/vnd.oci.image.manifest.v1+json",
+ "digest": "sha256:a65db259a719d915df30c82ce554ab3880ea567e2150d6288580408c2629b802",
+ "size": 347,
+ "annotations": {
+ "org.opencontainers.image.ref.name": "hello:latest"
+ }
+ }
+ ]
+ }`,
+ format: "oci",
+ withTag: true,
+ },
+ {
+ name: "TC3 normal case load docker tar with no RepoTags",
+ manifest: `[
+ {
+ "Config":"76a4dd2d5d6a18323ac8d90f959c3c8562bf592e2a559bab9b462ab600e9e5fc.json",
+ "RepoTags":[],
+ "Layers":[
+ "6eb4c21cc3fcb729a9df230ae522c1d3708ca66e5cf531713dbfa679837aa287.tar",
+ "37841116ad3b1eeea972c75ab8bad05f48f721a7431924bc547fc91c9076c1c8.tar"
+ ]
+ }
+ ]`,
+ format: "docker",
+ withTag: false,
+ },
+ {
+ name: "TC4 normal case load oci tar with no annotations",
+ manifest: `{
+ "schemaVersion": 2,
+ "manifests": [
+ {
+ "mediaType": "application/vnd.oci.image.manifest.v1+json",
+ "digest": "sha256:a65db259a719d915df30c82ce554ab3880ea567e2150d6288580408c2629b802",
+ "size": 347
+ }
+ ]
+ }`,
+ format: "oci",
+ withTag: false,
+ },
+ {
+ name: "TC5 abnormal case load docker tar with wrong manifestJSON",
+ manifest: `[
+ {
+ :"76a4dd2d5d6a18323ac8d90f959c3c8562bf592e2a559bab9b462ab600e9e5fc.json",
+ "RepoTags":[
+ "hello:latest"
+ ],
+ "Layers":[
+ "6eb4c21cc3fcb729a9df230ae522c1d3708ca66e5cf531713dbfa679837aa287.tar",
+ "37841116ad3b1eeea972c75ab8bad05f48f721a7431924bc547fc91c9076c1c8.tar"
+ ]
+ }
+ ]`,
+ format: "docker",
+ withTag: true,
+ wantErr: true,
+ errString: "error loading index",
+ },
+ {
+ name: "TC6 abnormal case with wrong tar path",
+ manifest: `[
+ {
+ "Config":"76a4dd2d5d6a18323ac8d90f959c3c8562bf592e2a559bab9b462ab600e9e5fc.json",
+ "RepoTags":[
+ "hello:latest"
+ ],
+ "Layers":[
+ "6eb4c21cc3fcb729a9df230ae522c1d3708ca66e5cf531713dbfa679837aa287.tar",
+ "37841116ad3b1eeea972c75ab8bad05f48f721a7431924bc547fc91c9076c1c8.tar"
+ ]
+ }
+ ]`,
+
+ tarPath: "/path/that/not/exist/load.tar",
+ format: "docker",
+ withTag: true,
+ wantErr: true,
+ errString: "no such file or directory",
+ },
+ }
+
+ for _, tc := range testcases {
+ t.Run(tc.name, func(t *testing.T) {
+ var jsonFile string
+ if tc.format == "docker" {
+ jsonFile = manifestJSONFile
}
- ]`
- dir := prepareForLoad(t, manifestJSON)
- assert.Equal(t, dir != nil, true)
- defer clean(dir)
+ if tc.format == "oci" {
+ jsonFile = indexJSONFile
+ }
+ dir := prepareForLoad(t, jsonFile, tc.manifest)
+ assert.Equal(t, dir != nil, true)
+ defer clean(dir)
- path := dir.Join("load.tar")
- repoTags, err := tryToParseImageFormatFromTarball(daemon.opts.DataRoot, &loadOptions{path: path})
- assert.NilError(t, err)
- assert.Equal(t, repoTags[0][0], "hello:latest")
+ path := dir.Join(loadedTarFile)
+ if tc.tarPath == "" {
+ tc.tarPath = path
+ }
+ req := &pb.LoadRequest{Path: tc.tarPath}
+ stream := &controlLoadServer{}
- req := &pb.LoadRequest{Path: path}
- stream := &controlLoadServer{}
+ err := daemon.backend.Load(req, stream)
+ if tc.wantErr {
+ assert.ErrorContains(t, err, tc.errString)
+ return
+ }
+ assert.ErrorContains(t, err, "failed to get the image")
+ })
+ }
- err = daemon.backend.Load(req, stream)
- assert.ErrorContains(t, err, "failed to get the image")
}
func TestLoadMultipleImages(t *testing.T) {
@@ -181,11 +305,11 @@ func TestLoadMultipleImages(t *testing.T) {
]
}
]`
- dir := prepareForLoad(t, manifestJSON)
+ dir := prepareForLoad(t, manifestJSONFile, manifestJSON)
assert.Equal(t, dir != nil, true)
defer clean(dir)
- path := dir.Join("load.tar")
+ path := dir.Join(loadedTarFile)
repoTags, err := tryToParseImageFormatFromTarball(daemon.opts.DataRoot, &loadOptions{path: path})
assert.NilError(t, err)
assert.Equal(t, repoTags[0][0], "registry.example.com/sayhello:first")
--
2.27.0

View File

@ -0,0 +1,409 @@
From 4e71f4409e53eadea0aa39383fba3e249072a932 Mon Sep 17 00:00:00 2001
From: meilier <xingweizheng@huawei.com>
Date: Tue, 2 Feb 2021 00:46:23 +0800
Subject: [PATCH 07/10] fix images command when only give repository
---
daemon/images.go | 145 +++++++++++++++++++++-------------
daemon/images_test.go | 178 ++++++++++++++++++++++++++++++++++++++++++
image/image.go | 9 ++-
3 files changed, 277 insertions(+), 55 deletions(-)
create mode 100644 daemon/images_test.go
diff --git a/daemon/images.go b/daemon/images.go
index 5560d18c..e61817cc 100644
--- a/daemon/images.go
+++ b/daemon/images.go
@@ -15,9 +15,11 @@ package daemon
import (
"context"
+ "fmt"
"sort"
"strings"
+ "github.com/containers/storage"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@@ -29,79 +31,114 @@ import (
)
const (
- none = "<none>"
- decimalPrefixBase = 1000
+ none = "<none>"
+ decimalPrefixBase = 1000
+ minImageFieldLenWithTag = 2
)
+type listOptions struct {
+ localStore *store.Store
+ logEntry *logrus.Entry
+ imageName string
+}
+
+func (b *Backend) getListOptions(req *pb.ListRequest) listOptions {
+ return listOptions{
+ localStore: b.daemon.localStore,
+ logEntry: logrus.WithFields(logrus.Fields{"ImageName": req.GetImageName()}),
+ imageName: req.GetImageName(),
+ }
+}
+
// List lists all images
func (b *Backend) List(ctx context.Context, req *pb.ListRequest) (*pb.ListResponse, error) {
- logEntry := logrus.WithFields(logrus.Fields{"ImageName": req.GetImageName()})
- logEntry.Info("ListRequest received")
-
- var reqRepository, reqTag string
- const minImageFieldLenWithTag = 2
- if req.ImageName != "" {
- imageName := req.ImageName
- _, img, err := image.FindImage(b.daemon.localStore, imageName)
- if err != nil {
- logEntry.Error(err)
- return nil, errors.Wrapf(err, "find local image %v error", imageName)
- }
+ logrus.WithFields(logrus.Fields{
+ "ImageName": req.GetImageName(),
+ }).Info("ListRequest received")
- parts := strings.Split(imageName, ":")
- if len(parts) >= minImageFieldLenWithTag {
- reqRepository, reqTag = strings.Join(parts[0:len(parts)-1], ":"), parts[len(parts)-1]
- }
+ opts := b.getListOptions(req)
- imageInfo := &pb.ListResponse_ImageInfo{
- Repository: reqRepository,
- Tag: reqTag,
- Id: img.ID,
- Created: img.Created.Format(constant.LayoutTime),
- Size_: getImageSize(b.daemon.localStore, img.ID),
- }
+ slashLastIndex := strings.LastIndex(opts.imageName, "/")
+ colonLastIndex := strings.LastIndex(opts.imageName, ":")
+ if opts.imageName != "" && strings.Contains(opts.imageName, ":") && colonLastIndex > slashLastIndex {
+ return listOneImage(opts)
+ }
+ return listImages(opts)
+}
- return &pb.ListResponse{Images: []*pb.ListResponse_ImageInfo{imageInfo}}, nil
+func listOneImage(opts listOptions) (*pb.ListResponse, error) {
+ _, image, err := image.FindImage(opts.localStore, opts.imageName)
+ if err != nil {
+ opts.logEntry.Error(err)
+ return nil, errors.Wrapf(err, "find local image %v error", opts.imageName)
}
- images, err := b.daemon.localStore.Images()
+ result := make([]*pb.ListResponse_ImageInfo, 0, len(image.Names))
+ appendImageToResult(&result, image, opts.localStore)
+
+ for _, info := range result {
+ if opts.imageName == fmt.Sprintf("%s:%s", info.Repository, info.Tag) {
+ result = []*pb.ListResponse_ImageInfo{info}
+ }
+ }
+
+ return &pb.ListResponse{Images: result}, nil
+}
+
+func listImages(opts listOptions) (*pb.ListResponse, error) {
+ images, err := opts.localStore.Images()
if err != nil {
- logEntry.Error(err)
+ opts.logEntry.Error(err)
return &pb.ListResponse{}, errors.Wrap(err, "failed list images from local storage")
}
+
sort.Slice(images, func(i, j int) bool {
return images[i].Created.After(images[j].Created)
})
result := make([]*pb.ListResponse_ImageInfo, 0, len(images))
- for _, image := range images {
- names := image.Names
- if len(names) == 0 {
- names = []string{none}
+ for i := range images {
+ appendImageToResult(&result, &images[i], opts.localStore)
+ }
+
+ if opts.imageName == "" {
+ return &pb.ListResponse{Images: result}, nil
+ }
+
+ sameRepositoryResult := make([]*pb.ListResponse_ImageInfo, 0, len(images))
+ for _, info := range result {
+ if opts.imageName == info.Repository || strings.HasPrefix(info.Id, opts.imageName) {
+ sameRepositoryResult = append(sameRepositoryResult, info)
+ }
+ }
+
+ if len(sameRepositoryResult) == 0 {
+ return &pb.ListResponse{}, errors.Errorf("failed to list images with repository %q in local storage", opts.imageName)
+ }
+ return &pb.ListResponse{Images: sameRepositoryResult}, nil
+}
+
+func appendImageToResult(result *[]*pb.ListResponse_ImageInfo, image *storage.Image, store *store.Store) {
+ names := image.Names
+ if len(names) == 0 {
+ names = []string{none}
+ }
+
+ for _, name := range names {
+ repository, tag := name, none
+ parts := strings.Split(name, ":")
+ if len(parts) >= minImageFieldLenWithTag {
+ repository, tag = strings.Join(parts[0:len(parts)-1], ":"), parts[len(parts)-1]
}
- for _, name := range names {
- repository, tag := name, none
- parts := strings.Split(name, ":")
- if len(parts) >= minImageFieldLenWithTag {
- repository, tag = strings.Join(parts[0:len(parts)-1], ":"), parts[len(parts)-1]
- }
- if reqRepository != "" && reqRepository != repository {
- continue
- }
- if reqTag != "" && reqTag != tag {
- continue
- }
-
- imageInfo := &pb.ListResponse_ImageInfo{
- Repository: repository,
- Tag: tag,
- Id: image.ID,
- Created: image.Created.Format(constant.LayoutTime),
- Size_: getImageSize(b.daemon.localStore, image.ID),
- }
- result = append(result, imageInfo)
+
+ imageInfo := &pb.ListResponse_ImageInfo{
+ Repository: repository,
+ Tag: tag,
+ Id: image.ID,
+ Created: image.Created.Format(constant.LayoutTime),
+ Size_: getImageSize(store, image.ID),
}
+ *result = append(*result, imageInfo)
}
- return &pb.ListResponse{Images: result}, nil
}
func getImageSize(store *store.Store, id string) string {
diff --git a/daemon/images_test.go b/daemon/images_test.go
new file mode 100644
index 00000000..a970ce0b
--- /dev/null
+++ b/daemon/images_test.go
@@ -0,0 +1,178 @@
+// Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved.
+// isula-build licensed under the Mulan PSL v2.
+// You can use this software according to the terms and conditions of the Mulan PSL v2.
+// You may obtain a copy of Mulan PSL v2 at:
+// http://license.coscl.org.cn/MulanPSL2
+// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+// PURPOSE.
+// See the Mulan PSL v2 for more details.
+// Author: Weizheng Xing
+// Create: 2021-02-03
+// Description: This file tests List interface
+
+package daemon
+
+import (
+ "context"
+ "fmt"
+ "testing"
+
+ "github.com/bndr/gotabulate"
+ "github.com/containers/storage"
+ "github.com/containers/storage/pkg/stringid"
+ "gotest.tools/v3/assert"
+
+ constant "isula.org/isula-build"
+ pb "isula.org/isula-build/api/services"
+)
+
+func TestList(t *testing.T) {
+ d := prepare(t)
+ defer tmpClean(d)
+
+ options := &storage.ImageOptions{}
+ img, err := d.Daemon.localStore.CreateImage(stringid.GenerateRandomID(), []string{"image:test1"}, "", "", options)
+ if err != nil {
+ t.Fatalf("create image with error: %v", err)
+ }
+ _, err = d.Daemon.localStore.CreateImage(stringid.GenerateRandomID(), []string{"image:test2"}, "", "", options)
+ if err != nil {
+ t.Fatalf("create image with error: %v", err)
+ }
+ _, err = d.Daemon.localStore.CreateImage(stringid.GenerateRandomID(), []string{"egami:test"}, "", "", options)
+ if err != nil {
+ t.Fatalf("create image with error: %v", err)
+ }
+ // image with no name and tag
+ _, err = d.Daemon.localStore.CreateImage(stringid.GenerateRandomID(), []string{}, "", "", options)
+ if err != nil {
+ t.Fatalf("create image with error: %v", err)
+ }
+ d.Daemon.localStore.SetNames(img.ID, append(img.Names, "image:test1-backup"))
+ // image who's repo contains port
+ _, err = d.Daemon.localStore.CreateImage(stringid.GenerateRandomID(), []string{"hub.example.com:8080/image:test"}, "", "", options)
+ if err != nil {
+ t.Fatalf("create image with error: %v", err)
+ }
+
+ testcases := []struct {
+ name string
+ req *pb.ListRequest
+ wantErr bool
+ errString string
+ }{
+ {
+ name: "normal case list specific image with repository[:tag]",
+ req: &pb.ListRequest{
+ ImageName: "image:test1",
+ },
+ wantErr: false,
+ },
+ {
+ name: "normal case list specific image with image id",
+ req: &pb.ListRequest{
+ ImageName: img.ID,
+ },
+ wantErr: false,
+ },
+ {
+ name: "normal case list all images",
+ req: &pb.ListRequest{
+ ImageName: "",
+ },
+ wantErr: false,
+ },
+ {
+ name: "normal case list all images with repository",
+ req: &pb.ListRequest{
+ ImageName: "image",
+ },
+ wantErr: false,
+ },
+ {
+ name: "abnormal case no image found in local store",
+ req: &pb.ListRequest{
+ ImageName: "coffee:costa",
+ },
+ wantErr: true,
+ errString: "failed to parse image",
+ },
+ {
+ name: "abnormal case no repository",
+ req: &pb.ListRequest{
+ ImageName: "coffee",
+ },
+ wantErr: true,
+ errString: "failed to list images with repository",
+ },
+ {
+ name: "abnormal case ImageName only contains latest tag",
+ req: &pb.ListRequest{
+ ImageName: ":latest",
+ },
+ wantErr: true,
+ errString: "invalid reference format",
+ },
+ {
+ name: "normal case ImageName contains port number and tag",
+ req: &pb.ListRequest{
+ ImageName: "hub.example.com:8080/image:test",
+ },
+ wantErr: false,
+ },
+ {
+ name: "normal case ImageName contains port number",
+ req: &pb.ListRequest{
+ ImageName: "hub.example.com:8080/image",
+ },
+ wantErr: false,
+ },
+ {
+ name: "abnormal case wrong ImageName",
+ req: &pb.ListRequest{
+ ImageName: "hub.example.com:8080/",
+ },
+ wantErr: true,
+ errString: "failed to list images with repository",
+ },
+ }
+
+ for _, tc := range testcases {
+ t.Run(tc.name, func(t *testing.T) {
+ ctx := context.TODO()
+ resp, err := d.Daemon.backend.List(ctx, tc.req)
+
+ if tc.wantErr == true {
+ assert.ErrorContains(t, err, tc.errString)
+ }
+ if tc.wantErr == false {
+ assert.NilError(t, err)
+ formatAndPrint(resp.Images)
+ }
+ })
+ }
+}
+
+func formatAndPrint(images []*pb.ListResponse_ImageInfo) {
+ emptyStr := `----------- ---- --------- --------
+ REPOSITORY TAG IMAGE ID CREATED
+ ----------- ---- --------- --------`
+ lines := make([][]string, 0, len(images))
+ title := []string{"REPOSITORY", "TAG", "IMAGE ID", "CREATED", "SIZE"}
+ for _, image := range images {
+ if image == nil {
+ continue
+ }
+ line := []string{image.Repository, image.Tag, image.Id[:constant.DefaultIDLen], image.Created, image.Size_}
+ lines = append(lines, line)
+ }
+ if len(lines) == 0 {
+ fmt.Println(emptyStr)
+ return
+ }
+ tabulate := gotabulate.Create(lines)
+ tabulate.SetHeaders(title)
+ tabulate.SetAlign("left")
+ fmt.Print(tabulate.Render("simple"))
+}
diff --git a/image/image.go b/image/image.go
index bbbc7b94..36785bdf 100644
--- a/image/image.go
+++ b/image/image.go
@@ -590,12 +590,19 @@ func ResolveName(name string, sc *types.SystemContext, store *store.Store) ([]st
}
func tryResolveNameInStore(name string, store *store.Store) string {
+ defaultTag := "latest"
+
logrus.Infof("Try to find image: %s in local storage", name)
img, err := store.Image(name)
+ if err == nil {
+ return img.ID
+ }
+
+ logrus.Infof("Try to find image: %s:%s in local storage", name, defaultTag)
+ img, err = store.Image(fmt.Sprintf("%s:%s", name, defaultTag))
if err != nil {
return ""
}
-
return img.ID
}
--
2.27.0

View File

@ -0,0 +1,336 @@
From 6ce9d998d0b8e15d7a673626a54477a0bfc9f768 Mon Sep 17 00:00:00 2001
From: meilier <xingweizheng@huawei.com>
Date: Wed, 3 Feb 2021 01:04:17 +0800
Subject: [PATCH 08/10] check if add default tag to image name when using push
and save command
---
daemon/pull_test.go | 6 +-
daemon/push.go | 6 ++
daemon/push_test.go | 13 ++-
daemon/save.go | 8 ++
daemon/save_test.go | 193 ++++++++++++++++++++++++++++++++++++++++++++
image/image.go | 23 ++++++
6 files changed, 246 insertions(+), 3 deletions(-)
create mode 100644 daemon/save_test.go
diff --git a/daemon/pull_test.go b/daemon/pull_test.go
index 67459d19..27a4d6e8 100644
--- a/daemon/pull_test.go
+++ b/daemon/pull_test.go
@@ -58,7 +58,6 @@ func (c *controlPullServer) Send(response *pb.PullResponse) error {
func init() {
reexec.Init()
-
}
func prepare(t *testing.T) daemonTestOptions {
@@ -100,7 +99,10 @@ func TestPull(t *testing.T) {
defer tmpClean(d)
options := &storage.ImageOptions{}
- d.Daemon.localStore.CreateImage(stringid.GenerateRandomID(), []string{"image:test"}, "", "", options)
+ _, err := d.Daemon.localStore.CreateImage(stringid.GenerateRandomID(), []string{"image:test"}, "", "", options)
+ if err != nil {
+ t.Fatalf("create image with error: %v", err)
+ }
testcases := []struct {
name string
diff --git a/daemon/push.go b/daemon/push.go
index e6053dd8..4e3a6ed9 100644
--- a/daemon/push.go
+++ b/daemon/push.go
@@ -63,6 +63,12 @@ func (b *Backend) Push(req *pb.PushRequest, stream pb.Control_PushServer) error
return err
}
+ imageName, err := image.CheckAndAddDefaultTag(opt.imageName, opt.localStore)
+ if err != nil {
+ return err
+ }
+ opt.imageName = imageName
+
manifestType, gErr := exporter.GetManifestType(opt.format)
if gErr != nil {
return gErr
diff --git a/daemon/push_test.go b/daemon/push_test.go
index 573e97fe..f4a9e2b1 100644
--- a/daemon/push_test.go
+++ b/daemon/push_test.go
@@ -79,10 +79,21 @@ func TestPush(t *testing.T) {
Format: "oci",
},
},
+ {
+ name: "manifestNotExist fine without tag latest",
+ pushRequest: &pb.PushRequest{
+ PushID: stringid.GenerateNonCryptoID()[:constant.DefaultIDLen],
+ ImageName: "127.0.0.1/no-repository/no-name",
+ Format: "oci",
+ },
+ },
}
options := &storage.ImageOptions{}
- d.Daemon.localStore.CreateImage(stringid.GenerateRandomID(), []string{"127.0.0.1/no-repository/no-name:latest"}, "", "", options)
+ _, err := d.Daemon.localStore.CreateImage(stringid.GenerateRandomID(), []string{"127.0.0.1/no-repository/no-name:latest"}, "", "", options)
+ if err != nil {
+ t.Fatalf("create image with error: %v", err)
+ }
for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
diff --git a/daemon/save.go b/daemon/save.go
index c6411e04..fd6174b4 100644
--- a/daemon/save.go
+++ b/daemon/save.go
@@ -79,6 +79,14 @@ func (b *Backend) Save(req *pb.SaveRequest, stream pb.Control_SaveServer) error
return errors.New("wrong image format provided")
}
+ for i, imageName := range opts.oriImgList {
+ nameWithTag, cErr := image.CheckAndAddDefaultTag(imageName, opts.localStore)
+ if cErr != nil {
+ return cErr
+ }
+ opts.oriImgList[i] = nameWithTag
+ }
+
defer func() {
if err != nil {
if rErr := os.Remove(opts.outputPath); rErr != nil && !os.IsNotExist(rErr) {
diff --git a/daemon/save_test.go b/daemon/save_test.go
new file mode 100644
index 00000000..a59086a8
--- /dev/null
+++ b/daemon/save_test.go
@@ -0,0 +1,193 @@
+// Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved.
+// isula-build licensed under the Mulan PSL v2.
+// You can use this software according to the terms and conditions of the Mulan PSL v2.
+// You may obtain a copy of Mulan PSL v2 at:
+// http://license.coscl.org.cn/MulanPSL2
+// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+// PURPOSE.
+// See the Mulan PSL v2 for more details.
+// Author: Weizheng Xing
+// Create: 2020-02-03
+// Description: This file tests Save interface
+
+package daemon
+
+import (
+ "context"
+ "testing"
+
+ "github.com/containers/storage"
+ "github.com/containers/storage/pkg/reexec"
+ "github.com/containers/storage/pkg/stringid"
+ "github.com/pkg/errors"
+ "golang.org/x/sync/errgroup"
+ "google.golang.org/grpc"
+ "gotest.tools/v3/assert"
+ "gotest.tools/v3/fs"
+
+ constant "isula.org/isula-build"
+ pb "isula.org/isula-build/api/services"
+ _ "isula.org/isula-build/exporter/register"
+ "isula.org/isula-build/pkg/logger"
+)
+
+type controlSaveServer struct {
+ grpc.ServerStream
+}
+
+func (c *controlSaveServer) Context() context.Context {
+ return context.Background()
+}
+
+func (c *controlSaveServer) Send(response *pb.SaveResponse) error {
+ if response.Log == "error" {
+ return errors.New("error happened")
+ }
+ return nil
+}
+
+func init() {
+ reexec.Init()
+}
+
+func TestSave(t *testing.T) {
+ d := prepare(t)
+ defer tmpClean(d)
+
+ //TODO: create image manually and save
+ options := &storage.ImageOptions{}
+ img, err := d.Daemon.localStore.CreateImage(stringid.GenerateRandomID(), []string{"image:latest"}, "", "", options)
+ if err != nil {
+ t.Fatalf("create image with error: %v", err)
+ }
+
+ _, err = d.Daemon.localStore.CreateImage(stringid.GenerateRandomID(), []string{"image2:test"}, "", "", options)
+ if err != nil {
+ t.Fatalf("create image with error: %v", err)
+ }
+
+ tempTarfileDir := fs.NewDir(t, t.Name())
+ defer tempTarfileDir.Remove()
+
+ testcases := []struct {
+ name string
+ req *pb.SaveRequest
+ wantErr bool
+ errString string
+ }{
+ {
+ name: "normal case save with repository[:tag]",
+ req: &pb.SaveRequest{
+ SaveID: stringid.GenerateNonCryptoID()[:constant.DefaultIDLen],
+ Images: []string{"image:latest"},
+ Path: tempTarfileDir.Join("repotag.tar"),
+ Format: "docker",
+ },
+ wantErr: true,
+ errString: "file does not exist",
+ },
+ {
+ name: "normal case save with repository add default latest",
+ req: &pb.SaveRequest{
+ SaveID: stringid.GenerateNonCryptoID()[:constant.DefaultIDLen],
+ Images: []string{"image"},
+ Path: tempTarfileDir.Join("repolatest.tar"),
+ Format: "oci",
+ },
+ wantErr: true,
+ errString: "file does not exist",
+ },
+ {
+ name: "normal case with imageid",
+ req: &pb.SaveRequest{
+ SaveID: stringid.GenerateNonCryptoID()[:constant.DefaultIDLen],
+ Images: []string{img.ID},
+ Path: tempTarfileDir.Join("imageid.tar"),
+ Format: "docker",
+ },
+ wantErr: true,
+ errString: "file does not exist",
+ },
+ {
+ name: "normal case save multiple images with repository and ID",
+ req: &pb.SaveRequest{
+ SaveID: stringid.GenerateNonCryptoID()[:constant.DefaultIDLen],
+ Images: []string{"image2:test", img.ID},
+ Path: tempTarfileDir.Join("double.tar"),
+ Format: "docker",
+ },
+ wantErr: true,
+ errString: "file does not exist",
+ },
+ {
+ name: "abnormal case save image that not exist in local store",
+ req: &pb.SaveRequest{
+ SaveID: stringid.GenerateNonCryptoID()[:constant.DefaultIDLen],
+ Images: []string{"noexist", img.ID},
+ Path: tempTarfileDir.Join("notexist.tar"),
+ Format: "docker",
+ },
+ wantErr: true,
+ errString: "failed to parse image",
+ },
+ {
+ name: "abnormal case wrong image format",
+ req: &pb.SaveRequest{
+ SaveID: stringid.GenerateNonCryptoID()[:constant.DefaultIDLen],
+ Images: []string{"image", img.ID},
+ Path: tempTarfileDir.Join("image.tar"),
+ Format: "dock",
+ },
+ wantErr: true,
+ errString: "wrong image format provided",
+ },
+ }
+
+ for _, tc := range testcases {
+ t.Run(tc.name, func(t *testing.T) {
+ stream := &controlSaveServer{}
+
+ err := d.Daemon.backend.Save(tc.req, stream)
+ if tc.wantErr == true {
+ assert.ErrorContains(t, err, tc.errString)
+ }
+ if tc.wantErr == false {
+ assert.NilError(t, err)
+ }
+ })
+ }
+
+}
+
+func TestSaveHandler(t *testing.T) {
+ ctx := context.TODO()
+ eg, _ := errgroup.WithContext(ctx)
+
+ eg.Go(saveHandlerPrint("Push Response"))
+ eg.Go(saveHandlerPrint(""))
+ eg.Go(saveHandlerPrint("error"))
+
+ eg.Wait()
+}
+
+func saveHandlerPrint(message string) func() error {
+ return func() error {
+ stream := &controlSaveServer{}
+ cliLogger := logger.NewCliLogger(constant.CliLogBufferLen)
+
+ ctx := context.TODO()
+ eg, _ := errgroup.WithContext(ctx)
+
+ eg.Go(messageHandler(stream, cliLogger))
+ eg.Go(func() error {
+ cliLogger.Print(message)
+ cliLogger.CloseContent()
+ return nil
+ })
+
+ eg.Wait()
+
+ return nil
+ }
+}
diff --git a/image/image.go b/image/image.go
index 36785bdf..1e480391 100644
--- a/image/image.go
+++ b/image/image.go
@@ -689,3 +689,26 @@ func tryResolveNameInRegistries(name string, sc *types.SystemContext) ([]string,
}
return candidates, exporter.DockerTransport
}
+
+// CheckAndAddDefaultTag checks if src is format of repository[:tag], add default tag if src without tag
+func CheckAndAddDefaultTag(imageName string, store *store.Store) (string, error) {
+ _, img, err := FindImage(store, imageName)
+ if err != nil {
+ return "", errors.Wrapf(err, "find src image: %q failed", imageName)
+ }
+
+ defaultTag := "latest"
+ for _, name := range img.Names {
+ // for imageName is the format of repository[:tag]
+ if imageName == name {
+ return imageName, nil
+ }
+ // for name is the format of repository
+ if fmt.Sprintf("%s:%s", imageName, defaultTag) == name {
+ return name, nil
+ }
+ }
+
+ // for imageName is the format of imageID
+ return imageName, nil
+}
--
2.27.0

View File

@ -0,0 +1,55 @@
From 04dc1756a397edcf99caffd22a85902973a7c40f Mon Sep 17 00:00:00 2001
From: meilier <xingweizheng@huawei.com>
Date: Wed, 3 Feb 2021 01:05:37 +0800
Subject: [PATCH 09/10] checkAndExpandTag return empty when tag is empty
---
builder/dockerfile/builder.go | 2 +-
builder/dockerfile/builder_test.go | 2 +-
daemon/import.go | 4 +++-
3 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/builder/dockerfile/builder.go b/builder/dockerfile/builder.go
index f860e60b..42229746 100644
--- a/builder/dockerfile/builder.go
+++ b/builder/dockerfile/builder.go
@@ -637,7 +637,7 @@ func parseOutputTag(output string) string {
// CheckAndExpandTag checks tag name. If it not include a tag, "latest" will be added.
func CheckAndExpandTag(tag string) (reference.Named, string, error) {
if tag == "" {
- return nil, "<none>:<none>", nil
+ return nil, "", nil
}
newTag := tag
diff --git a/builder/dockerfile/builder_test.go b/builder/dockerfile/builder_test.go
index f8de41f1..3b7513be 100644
--- a/builder/dockerfile/builder_test.go
+++ b/builder/dockerfile/builder_test.go
@@ -1533,7 +1533,7 @@ func TestCheckAndExpandTag(t *testing.T) {
{
name: "test 9",
tag: "",
- output: "<none>:<none>",
+ output: "",
wantErr: false,
},
{
diff --git a/daemon/import.go b/daemon/import.go
index 21ffeaa3..3d7c0d03 100644
--- a/daemon/import.go
+++ b/daemon/import.go
@@ -121,7 +121,9 @@ func (b *Backend) Import(req *pb.ImportRequest, stream pb.Control_ImportServer)
return errors.Wrapf(err, "error locating image %q in local storage after import", transports.ImageName(dstRef))
}
imageID = img.ID
- img.Names = append(img.Names, reference)
+ if reference != "" {
+ img.Names = append(img.Names, reference)
+ }
newNames := util.CopyStringsWithoutSpecificElem(img.Names, tmpName)
if err = localStore.SetNames(img.ID, newNames); err != nil {
return errors.Wrapf(err, "failed to prune temporary name from image %q", imageID)
--
2.27.0

View File

@ -0,0 +1,111 @@
From af2e9918063d2797ba9f16306a4e7d2bbb0e85f7 Mon Sep 17 00:00:00 2001
From: DCCooper <1866858@gmail.com>
Date: Tue, 2 Mar 2021 15:48:52 +0800
Subject: [PATCH 10/10] trim space when counting length of fields to avoid
panic
Signed-off-by: DCCooper <1866858@gmail.com>
---
builder/dockerfile/parser/parser.go | 2 +-
builder/dockerfile/parser/parser_test.go | 22 ++++++++++++++++++-
.../testfiles/preprocess/cmd_with_directive | 2 ++
.../preprocess/cmd_with_directive_with_space | 2 ++
.../preprocess/entrypoint_with_directive | 2 ++
.../entrypoint_with_directive_with_space | 2 ++
.../preprocess/run_with_directive_with_space | 2 ++
7 files changed, 32 insertions(+), 2 deletions(-)
create mode 100644 builder/dockerfile/parser/testfiles/preprocess/cmd_with_directive
create mode 100644 builder/dockerfile/parser/testfiles/preprocess/cmd_with_directive_with_space
create mode 100644 builder/dockerfile/parser/testfiles/preprocess/entrypoint_with_directive
create mode 100644 builder/dockerfile/parser/testfiles/preprocess/entrypoint_with_directive_with_space
create mode 100644 builder/dockerfile/parser/testfiles/preprocess/run_with_directive_with_space
diff --git a/builder/dockerfile/parser/parser.go b/builder/dockerfile/parser/parser.go
index 3caa516a..a21a3f59 100644
--- a/builder/dockerfile/parser/parser.go
+++ b/builder/dockerfile/parser/parser.go
@@ -161,7 +161,7 @@ func format(rows []*rowLine, d *directive) ([]*parser.Line, error) {
fields := strings.SplitN(logicLine, " ", 2)
const validLineLen = 2
// we do not allow empty raw command been passed
- if len(fields) < validLineLen || len(fields[1]) == 0 {
+ if len(fields) < validLineLen || len(strings.TrimSpace(fields[1])) == 0 {
return nil, errors.Errorf("line %q should have at least two fields", logicLine)
}
line.Command = strings.ToUpper(fields[0])
diff --git a/builder/dockerfile/parser/parser_test.go b/builder/dockerfile/parser/parser_test.go
index 3da5bea6..870132f1 100644
--- a/builder/dockerfile/parser/parser_test.go
+++ b/builder/dockerfile/parser/parser_test.go
@@ -91,7 +91,27 @@ func TestFormat(t *testing.T) {
expect: 8,
},
{
- name: "run_with_directive",
+ name: "run_with_directive",
+ wantErr: true,
+ },
+ {
+ name: "run_with_directive_with_space",
+ wantErr: true,
+ },
+ {
+ name: "cmd_with_directive",
+ wantErr: true,
+ },
+ {
+ name: "cmd_with_directive_with_space",
+ wantErr: true,
+ },
+ {
+ name: "entrypoint_with_directive",
+ wantErr: true,
+ },
+ {
+ name: "entrypoint_with_directive_with_space",
wantErr: true,
},
}
diff --git a/builder/dockerfile/parser/testfiles/preprocess/cmd_with_directive b/builder/dockerfile/parser/testfiles/preprocess/cmd_with_directive
new file mode 100644
index 00000000..545c278c
--- /dev/null
+++ b/builder/dockerfile/parser/testfiles/preprocess/cmd_with_directive
@@ -0,0 +1,2 @@
+FROM scratch
+CMD \
diff --git a/builder/dockerfile/parser/testfiles/preprocess/cmd_with_directive_with_space b/builder/dockerfile/parser/testfiles/preprocess/cmd_with_directive_with_space
new file mode 100644
index 00000000..fc309502
--- /dev/null
+++ b/builder/dockerfile/parser/testfiles/preprocess/cmd_with_directive_with_space
@@ -0,0 +1,2 @@
+FROM scratch
+CMD \
diff --git a/builder/dockerfile/parser/testfiles/preprocess/entrypoint_with_directive b/builder/dockerfile/parser/testfiles/preprocess/entrypoint_with_directive
new file mode 100644
index 00000000..59369bea
--- /dev/null
+++ b/builder/dockerfile/parser/testfiles/preprocess/entrypoint_with_directive
@@ -0,0 +1,2 @@
+FROM scratch
+ENTRYPOINT \
diff --git a/builder/dockerfile/parser/testfiles/preprocess/entrypoint_with_directive_with_space b/builder/dockerfile/parser/testfiles/preprocess/entrypoint_with_directive_with_space
new file mode 100644
index 00000000..172aa714
--- /dev/null
+++ b/builder/dockerfile/parser/testfiles/preprocess/entrypoint_with_directive_with_space
@@ -0,0 +1,2 @@
+FROM scratch
+ENTRYPOINT \
diff --git a/builder/dockerfile/parser/testfiles/preprocess/run_with_directive_with_space b/builder/dockerfile/parser/testfiles/preprocess/run_with_directive_with_space
new file mode 100644
index 00000000..c742c4c3
--- /dev/null
+++ b/builder/dockerfile/parser/testfiles/preprocess/run_with_directive_with_space
@@ -0,0 +1,2 @@
+FROM scratch
+RUN \
--
2.27.0

View File

@ -5,3 +5,10 @@ patch/0037-isula-build-fix-goroutine-leak-problem.patch
patch/0039-bugfix-remove-Healthcheck-field-when-build-from-scra.patch
patch/0040-vendor-update-tabulate-vendor-to-support-eliminate-s.patch
patch/0041-enhancement-remove-empty-lines-when-showing-image-li.patch
patch/0042-fix-some-make-checkall-golangci-lint-flaws.patch
patch/0043-enhancement-add-go-test-for-RUN-panic-problem.patch
patch/0044-fix-load-oci-image-panic.patch
patch/0045-fix-images-command-when-only-give-repository.patch
patch/0046-check-if-add-default-tag-to-image-name-when-using-pu.patch
patch/0047-checkAndExpandTag-return-empty-when-tag-is-empty.patch
patch/0048-trim-space-when-counting-length-of-fields-to-avoid-p.patch