diff --git a/VERSION-openeuler b/VERSION-openeuler index 9ae7772..ae1eb99 100644 --- a/VERSION-openeuler +++ b/VERSION-openeuler @@ -1 +1 @@ -0.9.5-13 +0.9.5-14 diff --git a/git-commit b/git-commit index febcde7..be7f8c6 100644 --- a/git-commit +++ b/git-commit @@ -1 +1 @@ -8742b763287fdb565d6044154318a2447bad171f +530b4f0737b75f72ff4dfc8ab15494a6064b1a73 diff --git a/isula-build.spec b/isula-build.spec index 820a0b3..fc0043f 100644 --- a/isula-build.spec +++ b/isula-build.spec @@ -2,7 +2,7 @@ Name: isula-build Version: 0.9.5 -Release: 13 +Release: 14 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 +* Mon Oct 25 2021 DCCooper <1866858@gmail.com> - 0.9.5-14 +- Type:enhancement +- CVE:NA +- SUG:restart +- DESC:sync patches from upstream, including relocate export package, clean code for tests and golint + * Thu Oct 14 2021 DCCooper <1866858@gmail.com> - 0.9.5-13 - Type:bugfix - CVE:NA diff --git a/patch/0062-clean-code-staticcheck-fix-of-S1020-S1023-SA9003-S10.patch b/patch/0062-clean-code-staticcheck-fix-of-S1020-S1023-SA9003-S10.patch new file mode 100644 index 0000000..15c4aca --- /dev/null +++ b/patch/0062-clean-code-staticcheck-fix-of-S1020-S1023-SA9003-S10.patch @@ -0,0 +1,401 @@ +From 6c355a7c9393982e648d79701a6c33ea0911a33a Mon Sep 17 00:00:00 2001 +From: xingweizheng +Date: Sat, 28 Aug 2021 21:55:14 +0800 +Subject: [PATCH 13/20] clean code: staticcheck fix of S1020, S1023, SA9003, + S1002 and some U1000 + +--- + builder/dockerfile/add_copy_test.go | 1 - + builder/dockerfile/builder.go | 2 +- + builder/dockerfile/builder_test.go | 7 ++----- + builder/dockerfile/container/help.go | 2 +- + builder/dockerfile/parser/command.go | 4 ++-- + builder/dockerfile/parser/parser.go | 14 +++++++------- + builder/dockerfile/parser/util.go | 1 - + builder/dockerfile/stage_builder.go | 2 +- + cmd/cli/logout_test.go | 3 +-- + daemon/info.go | 4 ++-- + daemon/remove.go | 6 +++--- + image/image.go | 12 ++++++------ + pkg/logger/logger.go | 2 +- + pkg/manifest/list.go | 2 +- + pkg/opts/opts.go | 2 +- + pkg/stack/stack.go | 2 +- + util/cipher.go | 6 +++--- + util/common.go | 2 +- + 18 files changed, 34 insertions(+), 40 deletions(-) + +diff --git a/builder/dockerfile/add_copy_test.go b/builder/dockerfile/add_copy_test.go +index 05fac1f3..8873872a 100644 +--- a/builder/dockerfile/add_copy_test.go ++++ b/builder/dockerfile/add_copy_test.go +@@ -158,7 +158,6 @@ func TestResolveCopySource(t *testing.T) { + isAdd bool + rawSources []string + dest string +- contextDir string + } + tests := []struct { + name string +diff --git a/builder/dockerfile/builder.go b/builder/dockerfile/builder.go +index cbd1e589..1e1e24dc 100644 +--- a/builder/dockerfile/builder.go ++++ b/builder/dockerfile/builder.go +@@ -559,7 +559,7 @@ func (b *Builder) export(imageID string) error { + } + + func (b *Builder) applyTag(imageID string) error { +- tags := make([]string, 0, 0) ++ tags := make([]string, 0) + if b.buildOpts.Tag != "" { + tags = append(tags, b.buildOpts.Tag) + } +diff --git a/builder/dockerfile/builder_test.go b/builder/dockerfile/builder_test.go +index 3b7513be..60668e1e 100644 +--- a/builder/dockerfile/builder_test.go ++++ b/builder/dockerfile/builder_test.go +@@ -21,7 +21,6 @@ import ( + "os" + "path/filepath" + "reflect" +- "regexp" + "strings" + "testing" + +@@ -725,8 +724,7 @@ func TestGetFlagsAndArgs(t *testing.T) { + // FROM alpine@digest@digest <- fail + func TestResolveImageName(t *testing.T) { + type args struct { +- s string +- reg *regexp.Regexp ++ s string + } + tests := []struct { + name string +@@ -882,8 +880,7 @@ func TestResolveImageName(t *testing.T) { + // FROM $imageName@${digest}$${digest2} <- fail + func TestResolveImageNameWithArgs(t *testing.T) { + type args struct { +- s string +- reg *regexp.Regexp ++ s string + } + tests := []struct { + name string +diff --git a/builder/dockerfile/container/help.go b/builder/dockerfile/container/help.go +index 475b479d..c2d5bd87 100644 +--- a/builder/dockerfile/container/help.go ++++ b/builder/dockerfile/container/help.go +@@ -69,7 +69,7 @@ func (ref *Reference) createConfigsAndManifests() (docker.Image, docker.Manifest + } + + func (ref *Reference) getContainerLayers() ([]string, error) { +- layers := make([]string, 0, 0) ++ layers := make([]string, 0) + layerID := ref.layerID + layer, err := ref.store.Layer(layerID) + if err != nil { +diff --git a/builder/dockerfile/parser/command.go b/builder/dockerfile/parser/command.go +index 1d62303d..635159ee 100644 +--- a/builder/dockerfile/parser/command.go ++++ b/builder/dockerfile/parser/command.go +@@ -322,7 +322,7 @@ func extractFlags(line *parser.Line, cmd string) (string, error) { + flagRegs := cmdFlagRegs[cmd] + parts := strings.Fields(line.Raw) + +- existFlags := make(map[string]bool, 0) ++ existFlags := make(map[string]bool) + var i int + for ; i <= len(parts)-1; i++ { + if !strings.HasPrefix(parts[i], "--") { +@@ -545,7 +545,7 @@ func parseKeyValue(line *parser.Line) error { + } + + func parseKeyEqualValuePairs(str string) []string { +- kvPairs := make([]string, 0, 0) ++ kvPairs := make([]string, 0) + + for i := 0; i <= len(str)-1; i++ { + word := []byte{} +diff --git a/builder/dockerfile/parser/parser.go b/builder/dockerfile/parser/parser.go +index a21a3f59..650c5e5c 100644 +--- a/builder/dockerfile/parser/parser.go ++++ b/builder/dockerfile/parser/parser.go +@@ -109,7 +109,7 @@ func newRowLine(num int, content string) *rowLine { + + // preprocess the Dockerfile and get the effective physical line + func preProcess(r io.Reader) []*rowLine { +- rowLines := make([]*rowLine, 0, 0) ++ rowLines := make([]*rowLine, 0) + scanner := bufio.NewScanner(r) + lineNum := 1 + for scanner.Scan() { +@@ -134,7 +134,7 @@ func format(rows []*rowLine, d *directive) ([]*parser.Line, error) { + text := rows[i].content + line := &parser.Line{ + Begin: rows[i].lineNum, +- Flags: make(map[string]string, 0), ++ Flags: make(map[string]string), + } + + var logicLine string +@@ -193,7 +193,7 @@ func constructPages(lines []*parser.Line, onbuild bool) ([]*parser.Page, error) + + var ( + pageMap = make(map[string]*parser.Page) +- pages = make([]*parser.Page, 0, 0) ++ pages = make([]*parser.Page, 0) + currentPage *parser.Page + pageNum int + ) +@@ -204,7 +204,7 @@ func constructPages(lines []*parser.Line, onbuild bool) ([]*parser.Page, error) + } + if onbuild && currentPage == nil { + currentPage = &parser.Page{ +- Lines: make([]*parser.Line, 0, 0), ++ Lines: make([]*parser.Line, 0), + Begin: line.Begin, + End: line.End, + } +@@ -227,7 +227,7 @@ func constructPages(lines []*parser.Line, onbuild bool) ([]*parser.Page, error) + Name: name, + Begin: line.Begin, + End: line.End, +- Lines: make([]*parser.Line, 0, 0), ++ Lines: make([]*parser.Line, 0), + } + // page name comes from the last cell from "FROM {image} AS {name} + // or named it with the index of stage in this dockerfile +@@ -266,7 +266,7 @@ func constructPages(lines []*parser.Line, onbuild bool) ([]*parser.Page, error) + // truncHeadingArgs Handle those ARGs before first FROM in the file + // returns the truncated lines and converted heading args + func truncHeadingArgs(lines *[]*parser.Line, onbuild bool) ([]string, error) { +- args := make([]string, 0, 0) ++ args := make([]string, 0) + if onbuild { + return args, nil + } +@@ -295,7 +295,7 @@ const ignoreFile = ".dockerignore" + // ParseIgnore parses the .dockerignore file in the provide dir, which + // must be the context directory + func (df *dockerfile) ParseIgnore(dir string) ([]string, error) { +- var ignores = make([]string, 0, 0) ++ var ignores = make([]string, 0) + + fullPath := path.Join(dir, ignoreFile) + if _, err := os.Stat(fullPath); err != nil { +diff --git a/builder/dockerfile/parser/util.go b/builder/dockerfile/parser/util.go +index bac13fbd..b8867f7f 100644 +--- a/builder/dockerfile/parser/util.go ++++ b/builder/dockerfile/parser/util.go +@@ -136,7 +136,6 @@ func (r *resolver) noDollar() { + // not "\$", this must be hyphen between args, such as '/' in "hub/image" or '_' in 'module_arch' + r.resolved += string(r.origin[r.idx]) + r.idx++ +- return + } + + func (r *resolver) noBrace() error { +diff --git a/builder/dockerfile/stage_builder.go b/builder/dockerfile/stage_builder.go +index 23f488cb..f01bad54 100644 +--- a/builder/dockerfile/stage_builder.go ++++ b/builder/dockerfile/stage_builder.go +@@ -330,7 +330,7 @@ func (s *stageBuilder) updateStageBuilder() error { + onbuildData = append(onbuildData, []byte(fmt.Sprintf("%s\n", item))...) + } + // OnBuild is handled, clean it here so that we can add new ONBUILDs on cmd builder if needed +- s.docker.Config.OnBuild = make([]string, 0, 0) ++ s.docker.Config.OnBuild = make([]string, 0) + + p, err := parser.NewParser(parser.DefaultParser) + if err != nil { +diff --git a/cmd/cli/logout_test.go b/cmd/cli/logout_test.go +index f5f09057..1328c2a1 100644 +--- a/cmd/cli/logout_test.go ++++ b/cmd/cli/logout_test.go +@@ -157,9 +157,8 @@ func TestNewLogoutCmd(t *testing.T) { + cmd.SetArgs(strings.Split(tt.args, " ")) + err := cmd.Execute() + if err != nil { +- ++ assert.ErrorContains(t, err, tt.errString) + } +- assert.ErrorContains(t, err, tt.errString) + }) + } + } +diff --git a/daemon/info.go b/daemon/info.go +index 8462be1b..cfc658c1 100644 +--- a/daemon/info.go ++++ b/daemon/info.go +@@ -108,8 +108,8 @@ func (b *Backend) Info(ctx context.Context, req *pb.InfoRequest) (*pb.InfoRespon + } + + func getRegistryInfo() ([]string, []string, []string, error) { +- registriesInsecure := make([]string, 0, 0) +- registriesBlock := make([]string, 0, 0) ++ registriesInsecure := make([]string, 0) ++ registriesBlock := make([]string, 0) + systemContext := image.GetSystemContext() + + registriesSearch, err := sysregistriesv2.UnqualifiedSearchRegistries(systemContext) +diff --git a/daemon/remove.go b/daemon/remove.go +index 89e68cfc..4d90bf53 100644 +--- a/daemon/remove.go ++++ b/daemon/remove.go +@@ -73,7 +73,7 @@ func (b *Backend) Remove(req *pb.RemoveRequest, stream pb.Control_RemoveServer) + continue + } + +- if removed == true { ++ if removed { + imageString := fmt.Sprintf("Untagged image: %v", imageID) + logrus.Debug(imageString) + if err = stream.Send(&pb.RemoveResponse{LayerMessage: imageString}); err != nil { +@@ -118,7 +118,7 @@ func (b *Backend) Remove(req *pb.RemoveRequest, stream pb.Control_RemoveServer) + } + + func untagImage(imageID string, store storage.Store, image *storage.Image) (bool, error) { +- newNames := make([]string, 0, 0) ++ newNames := make([]string, 0) + removed := false + for _, imgName := range image.Names { + if imgName == imageID { +@@ -128,7 +128,7 @@ func untagImage(imageID string, store storage.Store, image *storage.Image) (bool + newNames = append(newNames, imgName) + } + +- if removed == true { ++ if removed { + if err := store.SetNames(image.ID, newNames); err != nil { + return false, errors.Wrapf(err, "remove name %v from image %v error", imageID, image.ID) + } +diff --git a/image/image.go b/image/image.go +index e06d2530..1f3944d1 100644 +--- a/image/image.go ++++ b/image/image.go +@@ -287,19 +287,19 @@ func createScratchV2Image() *docker.Image { + ContainerConfig: docker.Config{}, + Config: &docker.Config{ + ExposedPorts: make(docker.PortSet), +- Env: make([]string, 0, 0), +- Cmd: make([]string, 0, 0), ++ Env: make([]string, 0), ++ Cmd: make([]string, 0), + Healthcheck: nil, + Volumes: make(map[string]struct{}), +- Entrypoint: make([]string, 0, 0), +- OnBuild: make([]string, 0, 0), ++ Entrypoint: make([]string, 0), ++ OnBuild: make([]string, 0), + Labels: make(map[string]string), + StopTimeout: nil, +- Shell: make([]string, 0, 0), ++ Shell: make([]string, 0), + }, + }, + RootFS: &docker.RootFS{}, +- History: make([]docker.History, 0, 0), ++ History: make([]docker.History, 0), + } + } + +diff --git a/pkg/logger/logger.go b/pkg/logger/logger.go +index 2e4dbdd1..1d9a61df 100644 +--- a/pkg/logger/logger.go ++++ b/pkg/logger/logger.go +@@ -45,7 +45,7 @@ type Logger struct { + // NewRunTimer return an instance of RunTimer + func NewRunTimer() *RunTimer { + return &RunTimer{ +- commands: make([]string, 0, 0), ++ commands: make([]string, 0), + cmdMap: make(map[string]time.Duration), + } + } +diff --git a/pkg/manifest/list.go b/pkg/manifest/list.go +index bc6037fc..10907e1d 100644 +--- a/pkg/manifest/list.go ++++ b/pkg/manifest/list.go +@@ -53,7 +53,7 @@ func NewManifestList() *List { + SchemaVersion: container.SchemaVersion, + MediaType: manifest.DockerV2ListMediaType, + }, +- instances: make(map[digest.Digest]string, 0), ++ instances: make(map[digest.Digest]string), + } + } + +diff --git a/pkg/opts/opts.go b/pkg/opts/opts.go +index 4664d50d..8fb3b308 100644 +--- a/pkg/opts/opts.go ++++ b/pkg/opts/opts.go +@@ -61,7 +61,7 @@ func (opts *ListOpts) Type() string { + + // NewListOpts creates a new ListOpts + func NewListOpts(validator validatorFunc) ListOpts { +- values := make(map[string]string, 0) ++ values := make(map[string]string) + return ListOpts{ + Values: values, + validator: validator, +diff --git a/pkg/stack/stack.go b/pkg/stack/stack.go +index b2100ce6..8343b6b0 100644 +--- a/pkg/stack/stack.go ++++ b/pkg/stack/stack.go +@@ -64,7 +64,7 @@ func dumpStack(path string) { + ) + + for { +- stackBuf = make([]byte, bufSize, bufSize) ++ stackBuf = make([]byte, bufSize) + stackSize = runtime.Stack(stackBuf, true) + // if these two sizes equal, which means the allocated buf is not large enough to carry all + // stacks back, so enlarge the buf and try again +diff --git a/util/cipher.go b/util/cipher.go +index 8e62e76b..b2aea2a9 100644 +--- a/util/cipher.go ++++ b/util/cipher.go +@@ -61,7 +61,7 @@ func GenerateCryptoKey(s int) ([]byte, error) { + } else { + size = aesKeyLenLowerBound + } +- key := make([]byte, size, size) ++ key := make([]byte, size) + if _, err := io.ReadFull(rand.Reader, key); err != nil { + return nil, errGenCryptoKey + } +@@ -105,7 +105,7 @@ func EncryptAES(data string, aeskey string) (string, error) { + return "", errors.Errorf("generate rand data for iv failed: %v", err) + } + mode := cipher.NewCFBEncrypter(block, iv) +- encryptData := make([]byte, len(plainText), len(plainText)) ++ encryptData := make([]byte, len(plainText)) + mode.XORKeyStream(encryptData, plainText) + encryptData = append(iv, encryptData...) + +@@ -134,7 +134,7 @@ func DecryptAES(data string, aeskey string) (string, error) { + } + + decrypter := cipher.NewCFBDecrypter(block, cipherText[:block.BlockSize()]) +- decryptData := make([]byte, len(cipherText)-block.BlockSize(), len(cipherText)-block.BlockSize()) ++ decryptData := make([]byte, len(cipherText)-block.BlockSize()) + decrypter.XORKeyStream(decryptData, cipherText[block.BlockSize():]) + + return string(decryptData), nil +diff --git a/util/common.go b/util/common.go +index d0cd9d06..00b1b941 100644 +--- a/util/common.go ++++ b/util/common.go +@@ -44,7 +44,7 @@ func CopyMapStringString(m map[string]string) map[string]string { + + // CopyStrings copies all strings in a slice to a new slice + func CopyStrings(str []string) []string { +- result := make([]string, len(str), len(str)) ++ result := make([]string, len(str)) + copy(result, str) + return result + } +-- +2.31.1 + diff --git a/patch/0063-relocation-exporter-package-and-remove-unused-const.patch b/patch/0063-relocation-exporter-package-and-remove-unused-const.patch new file mode 100644 index 0000000..461fd2b --- /dev/null +++ b/patch/0063-relocation-exporter-package-and-remove-unused-const.patch @@ -0,0 +1,153 @@ +From 0715aadaf5a5850d5ff1e6f74f7abafc4418f4d5 Mon Sep 17 00:00:00 2001 +From: xingweizheng +Date: Sun, 29 Aug 2021 05:05:10 +0800 +Subject: [PATCH 14/20] relocation exporter package and remove unused const + +--- + exporter/common.go | 91 +++++++++++++++++++++------------------------- + 1 file changed, 42 insertions(+), 49 deletions(-) + +diff --git a/exporter/common.go b/exporter/common.go +index cd976d21..b58f59cb 100644 +--- a/exporter/common.go ++++ b/exporter/common.go +@@ -27,7 +27,6 @@ import ( + "github.com/containers/image/v5/manifest" + "github.com/containers/image/v5/signature" + "github.com/containers/image/v5/types" +- "github.com/containers/storage/pkg/archive" + securejoin "github.com/cyphar/filepath-securejoin" + "github.com/docker/distribution/reference" + "github.com/opencontainers/go-digest" +@@ -40,11 +39,6 @@ import ( + "isula.org/isula-build/util" + ) + +-const ( +- // Uncompressed represents uncompressed +- Uncompressed = archive.Uncompressed +-) +- + // ExportOptions is a struct for exporter + type ExportOptions struct { + SystemContext *types.SystemContext +@@ -56,6 +50,28 @@ type ExportOptions struct { + ImageListSelection cp.ImageListSelection + } + ++// parseExporter parses an exporter instance and inits it with the src and dest reference. ++func parseExporter(opts ExportOptions, src, destSpec string, localStore *store.Store) (Exporter, error) { ++ const partsNum = 2 ++ // 1. parse exporter ++ parts := strings.SplitN(destSpec, ":", partsNum) ++ if len(parts) != partsNum { ++ return nil, errors.Errorf(`invalid dest spec %q, expected colon-separated exporter:reference`, destSpec) ++ } ++ ++ ept := GetAnExporter(parts[0]) ++ if ept == nil { ++ return nil, errors.Errorf(`invalid image name: %q, unknown exporter "%s"`, src, parts[0]) ++ } ++ ++ // 2. Init exporter reference ++ err := ept.Init(opts, src, destSpec, localStore) ++ if err != nil { ++ return nil, errors.Wrap(err, `fail to Init exporter"`) ++ } ++ return ept, nil ++} ++ + // Export exports an image to an output destination + func Export(imageID, outputDest string, opts ExportOptions, localStore *store.Store) error { + eLog := logrus.WithField(util.LogKeySessionID, opts.Ctx.Value(util.LogFieldKey(util.LogKeySessionID))) +@@ -89,26 +105,6 @@ func Export(imageID, outputDest string, opts ExportOptions, localStore *store.St + return nil + } + +-func exportToIsulad(ctx context.Context, tarPath string) error { +- // no tarPath need to export +- if len(tarPath) == 0 { +- return nil +- } +- defer func() { +- if rErr := os.Remove(tarPath); rErr != nil { +- logrus.Errorf("Remove file %s failed: %v", tarPath, rErr) +- } +- }() +- // dest here will not be influenced by external input, no security risk +- cmd := exec.CommandContext(ctx, "isula", "load", "-i", tarPath) // nolint:gosec +- if bytes, lErr := cmd.CombinedOutput(); lErr != nil { +- logrus.Errorf("Load image to isulad failed, stderr: %v, err: %v", string(bytes), lErr) +- return errors.Errorf("load image to isulad failed, stderr: %v, err: %v", string(bytes), lErr) +- } +- +- return nil +-} +- + func export(e Exporter, exOpts ExportOptions) (reference.Canonical, digest.Digest, error) { + var ( + ref reference.Canonical +@@ -158,28 +154,6 @@ func export(e Exporter, exOpts ExportOptions) (reference.Canonical, digest.Diges + return ref, manifestDigest, nil + } + +-// parseExporter parses an exporter instance and inits it with the src and dest reference. +-func parseExporter(opts ExportOptions, src, destSpec string, localStore *store.Store) (Exporter, error) { +- const partsNum = 2 +- // 1. parse exporter +- parts := strings.SplitN(destSpec, ":", partsNum) +- if len(parts) != partsNum { +- return nil, errors.Errorf(`invalid dest spec %q, expected colon-separated exporter:reference`, destSpec) +- } +- +- ept := GetAnExporter(parts[0]) +- if ept == nil { +- return nil, errors.Errorf(`invalid image name: %q, unknown exporter "%s"`, src, parts[0]) +- } +- +- // 2. Init exporter reference +- err := ept.Init(opts, src, destSpec, localStore) +- if err != nil { +- return nil, errors.Wrap(err, `fail to Init exporter"`) +- } +- return ept, nil +-} +- + // NewCopyOptions will return copy options + func NewCopyOptions(opts ExportOptions) *cp.Options { + cpOpts := &cp.Options{} +@@ -206,6 +180,26 @@ func NewPolicyContext(sc *types.SystemContext) (*signature.PolicyContext, error) + return policyContext, nil + } + ++func exportToIsulad(ctx context.Context, tarPath string) error { ++ // no tarPath need to export ++ if len(tarPath) == 0 { ++ return nil ++ } ++ defer func() { ++ if rErr := os.Remove(tarPath); rErr != nil { ++ logrus.Errorf("Remove file %s failed: %v", tarPath, rErr) ++ } ++ }() ++ // dest here will not be influenced by external input, no security risk ++ cmd := exec.CommandContext(ctx, "isula", "load", "-i", tarPath) // nolint:gosec ++ if bytes, lErr := cmd.CombinedOutput(); lErr != nil { ++ logrus.Errorf("Load image to isulad failed, stderr: %v, err: %v", string(bytes), lErr) ++ return errors.Errorf("load image to isulad failed, stderr: %v, err: %v", string(bytes), lErr) ++ } ++ ++ return nil ++} ++ + // CheckArchiveFormat used to check if save or load image format is either docker-archive or oci-archive + func CheckArchiveFormat(format string) error { + switch format { +@@ -237,4 +231,3 @@ func GetManifestType(format string) (string, error) { + } + return manifestType, nil + } +- +-- +2.31.1 + diff --git a/patch/0064-clean-code-tidy-FindImage-function.patch b/patch/0064-clean-code-tidy-FindImage-function.patch new file mode 100644 index 0000000..d63fb15 --- /dev/null +++ b/patch/0064-clean-code-tidy-FindImage-function.patch @@ -0,0 +1,236 @@ +From 9b1191dafa500bc55b37912898e3ebb8e9d6ec24 Mon Sep 17 00:00:00 2001 +From: xingweizheng +Date: Sat, 28 Aug 2021 23:27:49 +0800 +Subject: [PATCH 15/20] clean code: tidy FindImage function + +--- + daemon/images.go | 2 +- + daemon/images_test.go | 2 +- + daemon/push_test.go | 2 +- + daemon/remove.go | 2 +- + daemon/save.go | 2 +- + daemon/save_test.go | 2 +- + exporter/docker/archive/archive.go | 4 +- + image/image.go | 67 ++++++------------------------ + image/image_test.go | 2 +- + 9 files changed, 21 insertions(+), 64 deletions(-) + +diff --git a/daemon/images.go b/daemon/images.go +index e61817cc..baeb375c 100644 +--- a/daemon/images.go ++++ b/daemon/images.go +@@ -70,7 +70,7 @@ 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) ++ return nil, errors.Wrapf(err, "find local image %q failed", opts.imageName) + } + + result := make([]*pb.ListResponse_ImageInfo, 0, len(image.Names)) +diff --git a/daemon/images_test.go b/daemon/images_test.go +index a970ce0b..efbf6f14 100644 +--- a/daemon/images_test.go ++++ b/daemon/images_test.go +@@ -96,7 +96,7 @@ func TestList(t *testing.T) { + ImageName: "coffee:costa", + }, + wantErr: true, +- errString: "failed to parse image", ++ errString: "not found in local store", + }, + { + name: "abnormal case no repository", +diff --git a/daemon/push_test.go b/daemon/push_test.go +index f4a9e2b1..7358d0cd 100644 +--- a/daemon/push_test.go ++++ b/daemon/push_test.go +@@ -69,7 +69,7 @@ func TestPush(t *testing.T) { + Format: "docker", + }, + wantErr: true, +- errString: "failed to parse image", ++ errString: "not found in local store", + }, + { + name: "manifestNotExist", +diff --git a/daemon/remove.go b/daemon/remove.go +index 89e68cfc..d4e0bbd9 100644 +--- a/daemon/remove.go ++++ b/daemon/remove.go +@@ -49,7 +49,7 @@ func (b *Backend) Remove(req *pb.RemoveRequest, stream pb.Control_RemoveServer) + } + + for _, imageID := range rmImageIDs { +- _, img, err := image.FindImageLocally(s, imageID) ++ _, img, err := image.FindImage(s, imageID) + if err != nil { + rmFailed = true + errMsg := fmt.Sprintf("Find local image %q failed: %v", imageID, err) +diff --git a/daemon/save.go b/daemon/save.go +index 7ad12851..1a2d3fed 100644 +--- a/daemon/save.go ++++ b/daemon/save.go +@@ -186,7 +186,7 @@ func filterImageName(opts *saveOptions) error { + } + visitedImage[imageName] = true + +- _, img, err := image.FindImageLocally(opts.localStore, imageName) ++ _, img, err := image.FindImage(opts.localStore, imageName) + if err != nil { + return errors.Wrapf(err, "filter image name failed when finding image name %q", imageName) + } +diff --git a/daemon/save_test.go b/daemon/save_test.go +index a59086a8..c1b37342 100644 +--- a/daemon/save_test.go ++++ b/daemon/save_test.go +@@ -129,7 +129,7 @@ func TestSave(t *testing.T) { + Format: "docker", + }, + wantErr: true, +- errString: "failed to parse image", ++ errString: "not found in local store", + }, + { + name: "abnormal case wrong image format", +diff --git a/exporter/docker/archive/archive.go b/exporter/docker/archive/archive.go +index cc6b8721..36a28811 100644 +--- a/exporter/docker/archive/archive.go ++++ b/exporter/docker/archive/archive.go +@@ -60,7 +60,7 @@ func (d *dockerArchiveExporter) Init(opts exporter.ExportOptions, src, destSpec + // destSpec could be "file:name:tag" or "file:name" or just "file" with transport "docker-archive", such as docker-archive:output.tar:name:tag + // When more than two parts, build must be called + if parts := strings.Split(destSpec, ":"); len(parts) > partsNum { +- srcReference, _, err = image.FindImageLocally(localStore, src) ++ srcReference, _, err = image.FindImage(localStore, src) + if err != nil { + return errors.Wrapf(err, "find src image: %q failed with transport %q", src, d.Name()) + } +@@ -89,7 +89,7 @@ func (d *dockerArchiveExporter) Init(opts exporter.ExportOptions, src, destSpec + DockerArchiveExporter.InitArchiveWriter(opts.ExportID, archWriter) + } + +- srcReference, _, err = image.FindImageLocally(localStore, src) ++ srcReference, _, err = image.FindImage(localStore, src) + if err != nil { + return errors.Wrapf(err, "find src image: %q failed with transport %q", src, d.Name()) + } +diff --git a/image/image.go b/image/image.go +index 5ae7245e..4a1ca881 100644 +--- a/image/image.go ++++ b/image/image.go +@@ -468,71 +468,29 @@ func ResolveImageName(s string, resolveArg func(string) string) (string, error) + return newStr, nil + } + +-// FindImage get the image from storage by image describe ++// FindImage get the image from local storage by image describe + func FindImage(store *store.Store, image string) (types.ImageReference, *storage.Image, error) { +- names, _, err := ResolveName(image, nil, store) +- if err != nil { +- return nil, nil, errors.Wrapf(err, "error parsing name %q", image) +- } +- +- ref, img, err := ParseImagesToReference(store, names) +- if err != nil { +- return nil, nil, errors.Wrapf(err, "locating image %q failed", image) +- } +- return ref, img, nil +-} +- +-// FindImageLocally get the image from local storage by image describe +-func FindImageLocally(store *store.Store, image string) (types.ImageReference, *storage.Image, error) { + // 1. check name valid +- if image == "" { +- return nil, nil, errors.Errorf("image name %q cannot be empty string", image) ++ if _, err := reference.Parse(image); err != nil { ++ return nil, nil, errors.Wrapf(err, "parse image %q failed", image) + } + + // 2. try to find image with name or id in local store + localName := tryResolveNameInStore(image, store) + if localName == "" { +- return nil, nil, errors.Errorf("no image %q in local store", image) ++ return nil, nil, errors.Errorf("image %q not found in local store", image) + } + +- // 3. parse to image reference +- ref, img, err := ParseImagesToReference(store, []string{localName}) ++ // 3. get image reference and storage.Image ++ ref, err := is.Transport.ParseStoreReference(store, localName) + if err != nil { +- return nil, nil, errors.Wrapf(err, "locating image %q locally failed", image) +- } +- return ref, img, nil +-} +- +-// ParseImagesToReference get the image reference in store +-func ParseImagesToReference(store *store.Store, names []string) (types.ImageReference, *storage.Image, error) { +- var ( +- ref types.ImageReference +- img *storage.Image +- err error +- ) +- for _, name := range names { +- ref, err = is.Transport.ParseStoreReference(store, name) +- if err != nil { +- logrus.Debugf("Error parsing reference to image %q: %v", name, err) +- continue +- } +- +- var gErr error +- img, gErr = is.Transport.GetStoreImage(store, ref) +- // When name is the format of name[:rag] with out registry domain, err is storage.ErrImageUnknown +- if gErr != nil { +- img2, err2 := store.Image(name) +- if err2 != nil { +- logrus.Debugf("Error locating image %q: %v", name, err2) +- continue +- } +- img = img2 +- } +- break ++ return nil, nil, errors.Wrapf(err, "error parsing reference to image %q", localName) + } +- if ref == nil || img == nil || err != nil { +- return nil, nil, errors.Errorf("failed to parse image %v in local store", names) ++ img, err := is.Transport.GetStoreImage(store, ref) ++ if err != nil { ++ return nil, nil, errors.Wrapf(err, "failed to parse image %q in local store", localName) + } ++ + return ref, img, nil + } + +@@ -572,14 +530,13 @@ 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 + } + ++ defaultTag := "latest" + 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 { +diff --git a/image/image_test.go b/image/image_test.go +index c698b4d8..43d936f5 100644 +--- a/image/image_test.go ++++ b/image/image_test.go +@@ -51,7 +51,7 @@ func TestFindImageWhenImageNameIsEmpty(t *testing.T) { + + src := "" + srcReference, _, err := FindImage(&localStore, src) +- assert.ErrorContains(t, err, "locating image") ++ assert.ErrorContains(t, err, "repository name must have at least one component") + assert.Assert(t, cmp.Nil(srcReference)) + } + +-- +2.31.1 + diff --git a/patch/0065-clean-code-delete-channel-within-the-same-goroutine.patch b/patch/0065-clean-code-delete-channel-within-the-same-goroutine.patch new file mode 100644 index 0000000..b93d908 --- /dev/null +++ b/patch/0065-clean-code-delete-channel-within-the-same-goroutine.patch @@ -0,0 +1,89 @@ +From 7050a0ec5cdff61cd289bc8d03dbdd7d46bcda0d Mon Sep 17 00:00:00 2001 +From: xingweizheng +Date: Sat, 28 Aug 2021 21:56:02 +0800 +Subject: [PATCH 16/20] clean code: delete channel within the same goroutine + +--- + daemon/manifest.go | 13 ++----------- + daemon/pull.go | 13 ++----------- + daemon/push.go | 13 ++----------- + 3 files changed, 6 insertions(+), 33 deletions(-) + +diff --git a/daemon/manifest.go b/daemon/manifest.go +index fc28998f..36e76749 100644 +--- a/daemon/manifest.go ++++ b/daemon/manifest.go +@@ -212,18 +212,9 @@ func (b *Backend) ManifestPush(req *pb.ManifestPushRequest, stream pb.Control_Ma + eg, egCtx := errgroup.WithContext(stream.Context()) + eg.Go(manifestPushHandler(egCtx, opt)) + eg.Go(manifestPushMessageHandler(stream, cliLogger)) +- errC := make(chan error, 1) + +- errC <- eg.Wait() +- defer close(errC) +- +- err, ok := <-errC +- if !ok { +- logrus.WithField(util.LogKeySessionID, manifestName).Info("Channel errC closed") +- return nil +- } +- if err != nil { +- logrus.WithField(util.LogKeySessionID, manifestName).Warnf("Stream closed with: %v", err) ++ if err := eg.Wait(); err != nil { ++ logrus.WithField(util.LogKeySessionID, manifestName).Warnf("Manifest push stream closed with: %v", err) + return err + } + +diff --git a/daemon/pull.go b/daemon/pull.go +index 6d2e33d9..90be2a91 100644 +--- a/daemon/pull.go ++++ b/daemon/pull.go +@@ -62,18 +62,9 @@ func (b *Backend) Pull(req *pb.PullRequest, stream pb.Control_PullServer) error + eg, egCtx := errgroup.WithContext(ctx) + eg.Go(pullHandler(egCtx, opt)) + eg.Go(pullMessageHandler(stream, opt.logger)) +- errC := make(chan error, 1) + +- errC <- eg.Wait() +- defer close(errC) +- +- err, ok := <-errC +- if !ok { +- logrus.WithField(util.LogKeySessionID, opt.pullID).Info("Channel errC closed") +- return nil +- } +- if err != nil { +- logrus.WithField(util.LogKeySessionID, opt.pullID).Warnf("Stream closed with: %v", err) ++ if err := eg.Wait(); err != nil { ++ logrus.WithField(util.LogKeySessionID, opt.pullID).Warnf("Pull stream closed with: %v", err) + return err + } + +diff --git a/daemon/push.go b/daemon/push.go +index e36198dc..d3f5571e 100644 +--- a/daemon/push.go ++++ b/daemon/push.go +@@ -84,18 +84,9 @@ func (b *Backend) Push(req *pb.PushRequest, stream pb.Control_PushServer) error + + eg.Go(pushHandler(egCtx, opt)) + eg.Go(pushMessageHandler(stream, opt.logger)) +- errC := make(chan error, 1) + +- errC <- eg.Wait() +- defer close(errC) +- +- err, ok := <-errC +- if !ok { +- logrus.WithField(util.LogKeySessionID, opt.pushID).Info("Channel errC closed") +- return nil +- } +- if err != nil { +- logrus.WithField(util.LogKeySessionID, opt.pushID).Warnf("Stream closed with: %v", err) ++ if err := eg.Wait(); err != nil { ++ logrus.WithField(util.LogKeySessionID, opt.pushID).Warnf("Push stream closed with: %v", err) + return err + } + +-- +2.31.1 + diff --git a/patch/0067-fix-golangci-lint-warnings.patch b/patch/0067-fix-golangci-lint-warnings.patch new file mode 100644 index 0000000..3b8815d --- /dev/null +++ b/patch/0067-fix-golangci-lint-warnings.patch @@ -0,0 +1,43 @@ +From f08b682ec8caab1a50aff1d37c10729e941d4721 Mon Sep 17 00:00:00 2001 +From: xingweizheng +Date: Tue, 31 Aug 2021 11:52:29 +0800 +Subject: [PATCH 17/20] fix golangci-lint warnings + +--- + builder/dockerfile/run.go | 6 +++--- + cmd/cli/grpc_client.go | 2 +- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/builder/dockerfile/run.go b/builder/dockerfile/run.go +index 828fe676..d33573f9 100644 +--- a/builder/dockerfile/run.go ++++ b/builder/dockerfile/run.go +@@ -97,9 +97,9 @@ func (c *cmdBuilder) setupRuntimeSpec(command []string) (*specs.Spec, error) { + // set specific runtime spec config + user := c.stage.docker.Config.User + if user != "" { +- pair, err := util.GetChownOptions(user, c.stage.mountpoint) +- if err != nil { +- return nil, err ++ pair, gErr := util.GetChownOptions(user, c.stage.mountpoint) ++ if gErr != nil { ++ return nil, gErr + } + g.SetProcessUID(uint32(pair.UID)) + g.SetProcessGID(uint32(pair.GID)) +diff --git a/cmd/cli/grpc_client.go b/cmd/cli/grpc_client.go +index cab59503..44c00c09 100644 +--- a/cmd/cli/grpc_client.go ++++ b/cmd/cli/grpc_client.go +@@ -82,7 +82,7 @@ func NewClient(ctx context.Context) (*GrpcClient, error) { + defer cancel() + connected, err := cli.HealthCheck(healthCtx) + if !connected || err != nil { +- return nil, errors.Errorf( "Cannot connect to the isula-builder at %s. Is the isula-builder running?\nError: %v", constant.DefaultGRPCAddress, err) ++ return nil, errors.Errorf("Cannot connect to the isula-builder at %s. Is the isula-builder running?\nError: %v", constant.DefaultGRPCAddress, err) + } + + return cli, nil +-- +2.31.1 + diff --git a/patch/0068-change-golangci-lint-config-and-remove-redundant-che.patch b/patch/0068-change-golangci-lint-config-and-remove-redundant-che.patch new file mode 100644 index 0000000..16e7ae2 --- /dev/null +++ b/patch/0068-change-golangci-lint-config-and-remove-redundant-che.patch @@ -0,0 +1,97 @@ +From 0b2d60bd700378eea88641cdb2d6fd3ff5bdc6ee Mon Sep 17 00:00:00 2001 +From: xingweizheng +Date: Wed, 1 Sep 2021 01:12:11 +0800 +Subject: [PATCH 19/20] change golangci-lint config and remove redundant check + +--- + .golangci.yml | 12 ++---------- + image/image.go | 18 +++++------------- + util/util.go | 3 ++- + 3 files changed, 9 insertions(+), 24 deletions(-) + +diff --git a/.golangci.yml b/.golangci.yml +index 46ef20b3..50a31292 100644 +--- a/.golangci.yml ++++ b/.golangci.yml +@@ -38,16 +38,7 @@ linters: + - misspell + - goconst + disable: +- - lll +- - wsl +- - depguard +- - stylecheck +- - dupl +- - interfacer +- - gosimple + - unused +- - rowserrcheck +- - goprintffuncname + fast: false + + output: +@@ -68,7 +59,8 @@ linters-settings: + gomnd: + settings: + mnd: +- checks: argument, case, condition, return ++ checks: argument, case, condition, operation, return, assign ++ ignored-numbers: 2 + gocritic: + disabled-checks: + - ifElseChain +diff --git a/image/image.go b/image/image.go +index 892f2593..b5a3757c 100644 +--- a/image/image.go ++++ b/image/image.go +@@ -254,28 +254,20 @@ func getLocalImageNameFromRef(store storage.Store, srcRef types.ImageReference) + if err := exporter.CheckArchiveFormat(srcRef.Transport().Name()); err == nil { + return stringid.GenerateRandomID() + ":" + stringid.GenerateRandomID(), nil + } +- + if srcRef.Transport().Name() != constant.DockerTransport { + return "", errors.Errorf("the %s transport is not supported yet", srcRef.Transport().Name()) + } + +- var name string + ref := srcRef.DockerReference() + if ref == nil { + return "", errors.New("get the docker reference associated with source reference failed") + } +- +- if named, ok := ref.(reference.Named); ok { +- name = named.Name() +- if tag, ok := ref.(reference.NamedTagged); ok { +- name = name + ":" + tag.Tag() +- } +- if dig, ok := ref.(reference.Canonical); ok { +- name = name + "@" + dig.Digest().String() +- } ++ name := ref.Name() ++ if tag, ok := ref.(reference.NamedTagged); ok { ++ name = name + ":" + tag.Tag() + } +- if _, err := is.Transport.ParseStoreReference(store, name); err != nil { +- return "", errors.Wrapf(err, "parsing image name %q failed", name) ++ if dig, ok := ref.(reference.Canonical); ok { ++ name = name + "@" + dig.Digest().String() + } + + return name, nil +diff --git a/util/util.go b/util/util.go +index f5276080..8c1e09e4 100644 +--- a/util/util.go ++++ b/util/util.go +@@ -318,7 +318,8 @@ func ChangeGroup(path, g string) error { + + // GenerateNonCryptoID generate none crypto id with length 32 + func GenerateNonCryptoID() string { +- b := make([]byte, 32) ++ nonCryptoIDLength := 32 ++ b := make([]byte, nonCryptoIDLength) + _, err := rand.Read(b) + if err != nil { + panic(err) // This shouldn't happen +-- +2.31.1 + diff --git a/patch/0069-make-add-make-info-for-Makefile.patch b/patch/0069-make-add-make-info-for-Makefile.patch new file mode 100644 index 0000000..a44c251 --- /dev/null +++ b/patch/0069-make-add-make-info-for-Makefile.patch @@ -0,0 +1,151 @@ +From a7c81c6997cb6f9eb25b227430789555f700fa4c Mon Sep 17 00:00:00 2001 +From: DCCooper <1866858@gmail.com> +Date: Wed, 15 Sep 2021 11:32:16 +0800 +Subject: [PATCH 20/20] make: add make info for Makefile + +Signed-off-by: DCCooper <1866858@gmail.com> +--- + Makefile | 73 +++++++++++++++++++++++++++++++++----------------------- + 1 file changed, 43 insertions(+), 30 deletions(-) + +diff --git a/Makefile b/Makefile +index d5b1c537..d41a9fdb 100644 +--- a/Makefile ++++ b/Makefile +@@ -39,22 +39,30 @@ else + export GO_BUILD=$(GO) build + endif + ++##@ Help ++.PHONY: help ++help: ## Display the help info ++ @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-20s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) ++ ++##@ Build ++ ++.PHONY: all ## Build both isula-build and isula-builder + all: isula-build isula-builder + + .PHONY: isula-build +-isula-build: ./cmd/cli ++isula-build: ./cmd/cli ## Build isula-build only + @echo "Making isula-build..." + $(GO_BUILD) -ldflags '$(LDFLAGS)' -o bin/isula-build $(BUILDFLAGS) ./cmd/cli + @echo "isula-build done!" + + .PHONY: isula-builder +-isula-builder: ./cmd/daemon ++isula-builder: ./cmd/daemon ## Build isula-builder only + @echo "Making isula-builder..." + $(GO_BUILD) -ldflags '$(LDFLAGS)' -o bin/isula-builder $(BUILDFLAGS) ./cmd/daemon + @echo "isula-builder done!" + + .PHONY: safe +-safe: ++safe: ## Build binary with secure compile flag enabled + @echo "Safe building isula-build..." + mkdir -p ${TMPDIR} + $(GO_BUILD) -ldflags '$(SAFEBUILDFLAGS) $(STATIC_LDFLAGS)' -o bin/isula-build $(BUILDFLAGS) ./cmd/cli 2>/dev/null +@@ -62,7 +70,7 @@ safe: + @echo "Safe build isula-build done!" + + .PHONY: debug +-debug: ++debug: ## Build binary with debug info inside + @echo "Debug building isula-build..." + @cp -f ./hack/profiling ./daemon/profiling.go + $(GO_BUILD) -ldflags '$(LDFLAGS)' -gcflags="all=-N -l" -o bin/isula-build $(BUILDFLAGS) ./cmd/cli +@@ -70,59 +78,64 @@ debug: + @rm -f ./daemon/profiling.go + @echo "Debug build isula-build done!" + +-.PHONY: build-image +-build-image: +- isula-build ctr-img build -f Dockerfile.proto ${IMAGE_BUILDARGS} -o isulad:${IMAGE_NAME}:latest . ++.PHONY: install ++install: ## Install binary and configs ++ install -D -m0550 bin/isula-build $(BINDIR) ++ install -D -m0550 bin/isula-builder $(BINDIR) ++ @( getent group isula > /dev/null ) || ( groupadd --system isula ) ++ @[ ! -d ${CONFIG_DIR}/${CONFIG_FILE} ] && install -dm0650 ${CONFIG_DIR} ++ @( [ -f ${CONFIG_DIR}/${CONFIG_FILE} ] && printf "%-20s %s\n" "${CONFIG_FILE}" "already exist in ${CONFIG_DIR}, please replace it manually." ) || install -D -m0600 ${LOCAL_CONF_PREFIX}/${CONFIG_FILE} ${CONFIG_DIR}/${CONFIG_FILE} ++ @( [ -f ${CONFIG_DIR}/${POLICY_FILE} ] && printf "%-20s %s\n" "${POLICY_FILE}" "already exist in ${CONFIG_DIR}, please replace it manually." ) || install -D -m0600 ${LOCAL_CONF_PREFIX}/${POLICY_FILE} ${CONFIG_DIR}/${POLICY_FILE} ++ @( [ -f ${CONFIG_DIR}/${REGIST_FILE} ] && printf "%-20s %s\n" "${REGIST_FILE}" "already exist in ${CONFIG_DIR}, please replace it manually." ) || install -D -m0600 ${LOCAL_CONF_PREFIX}/${REGIST_FILE} ${CONFIG_DIR}/${REGIST_FILE} ++ @( [ -f ${CONFIG_DIR}/${STORAGE_FILE} ] && printf "%-20s %s\n" "${STORAGE_FILE}" "already exist in ${CONFIG_DIR}, please replace it manually." ) || install -D -m0600 ${LOCAL_CONF_PREFIX}/${STORAGE_FILE} ${CONFIG_DIR}/${STORAGE_FILE} ++ ++ ++##@ Test + +-tests: test-unit test-integration ++tests: test-base test-unit test-integration ## Test all + + .PHONY: test-base +-test-base: ++test-base: ## Test base case + @echo "Base test starting..." + @./tests/test.sh base + @echo "Base test done!" + + .PHONY: test-unit +-test-unit: ++test-unit: ## Test unit case + @echo "Unit test starting..." + @./hack/unit_test.sh + @echo "Unit test done!" + + .PHONY: test-integration +-test-integration: debug install ++test-integration: ## Test integration case + @echo "Integration test starting..." +- @./tests/test.sh base + @./tests/test.sh integration + @echo "Integration test done!" + ++##@ Development ++ ++.PHONY: build-image ++build-image: ## Build protobuf compile environment container image ++ isula-build ctr-img build -f Dockerfile.proto ${IMAGE_BUILDARGS} -o isulad:${IMAGE_NAME}:latest . ++ + .PHONY: proto +-proto: ++proto: ## Generate protobuf file + @echo "Generating protobuf..." + isula run -i --rm --runtime runc -v ${PWD}:/go/src/isula.org/isula-build ${IMAGE_NAME} ./hack/generate_proto.sh + @echo "Protobuf files have been generated!" + +-.PHONY: install +-install: +- install -D -m0550 bin/isula-build $(BINDIR) +- install -D -m0550 bin/isula-builder $(BINDIR) +- @( getent group isula > /dev/null ) || ( groupadd --system isula ) +- @[ ! -d ${CONFIG_DIR}/${CONFIG_FILE} ] && install -dm0650 ${CONFIG_DIR} +- @( [ -f ${CONFIG_DIR}/${CONFIG_FILE} ] && printf "%-20s %s\n" "${CONFIG_FILE}" "already exist in ${CONFIG_DIR}, please replace it manually." ) || install -D -m0600 ${LOCAL_CONF_PREFIX}/${CONFIG_FILE} ${CONFIG_DIR}/${CONFIG_FILE} +- @( [ -f ${CONFIG_DIR}/${POLICY_FILE} ] && printf "%-20s %s\n" "${POLICY_FILE}" "already exist in ${CONFIG_DIR}, please replace it manually." ) || install -D -m0600 ${LOCAL_CONF_PREFIX}/${POLICY_FILE} ${CONFIG_DIR}/${POLICY_FILE} +- @( [ -f ${CONFIG_DIR}/${REGIST_FILE} ] && printf "%-20s %s\n" "${REGIST_FILE}" "already exist in ${CONFIG_DIR}, please replace it manually." ) || install -D -m0600 ${LOCAL_CONF_PREFIX}/${REGIST_FILE} ${CONFIG_DIR}/${REGIST_FILE} +- @( [ -f ${CONFIG_DIR}/${STORAGE_FILE} ] && printf "%-20s %s\n" "${STORAGE_FILE}" "already exist in ${CONFIG_DIR}, please replace it manually." ) || install -D -m0600 ${LOCAL_CONF_PREFIX}/${STORAGE_FILE} ${CONFIG_DIR}/${STORAGE_FILE} ++.PHONY: check ++check: ## Static check for current commit ++ @echo "Static check start for last commit" ++ @./hack/static_check.sh last ++ @echo "Static check last commit finished" + + .PHONY: checkall +-checkall: ++checkall: ## Static check for whole project + @echo "Static check start for whole project" + @./hack/static_check.sh all + @echo "Static check project finished" +-.PHONY: check +-check: +- @echo "Static check start for last commit" +- @./hack/static_check.sh last +- @echo "Static check last commit finished" + + .PHONY: clean +-clean: ++clean: ## Clean project + rm -rf ./bin +-- +2.31.1 + diff --git a/patch/0070-clean-code-all-latest-tag-checks-take-the-FindImage-.patch b/patch/0070-clean-code-all-latest-tag-checks-take-the-FindImage-.patch new file mode 100644 index 0000000..324d4fb --- /dev/null +++ b/patch/0070-clean-code-all-latest-tag-checks-take-the-FindImage-.patch @@ -0,0 +1,391 @@ +From d6c6a81dd3cb73685c5cdf029cf9dd5602d3d44d Mon Sep 17 00:00:00 2001 +From: xingweizheng +Date: Sun, 29 Aug 2021 01:07:58 +0800 +Subject: [PATCH 4/5] clean code: all latest tag checks take the FindImage as + the entrance + +--- + builder/dockerfile/builder.go | 2 +- + constant.go | 2 + + daemon/push.go | 6 --- + daemon/save.go | 24 ++++------ + exporter/docker/archive/archive.go | 56 +++++++++++++--------- + image/image.go | 40 ++++++++-------- + image/image_test.go | 96 ++++++++++++++++++++++++++++++++++++++ + 7 files changed, 160 insertions(+), 66 deletions(-) + +diff --git a/builder/dockerfile/builder.go b/builder/dockerfile/builder.go +index 1e1e24d..e28fac9 100644 +--- a/builder/dockerfile/builder.go ++++ b/builder/dockerfile/builder.go +@@ -646,7 +646,7 @@ func CheckAndExpandTag(tag string) (reference.Named, string, error) { + if sepLastIndex == -1 || (sepLastIndex < slashLastIndex) { + // isula + // localhost:5000/isula +- newTag += ":latest" ++ newTag = fmt.Sprintf("%s:%s", newTag, constant.DefaultTag) + } + + const longestTagFieldsLen = 3 +diff --git a/constant.go b/constant.go +index bfe399b..4d1596a 100644 +--- a/constant.go ++++ b/constant.go +@@ -89,6 +89,8 @@ const ( + IsuladTransport = "isulad" + // ManifestTransport used to export manifest list + ManifestTransport = "manifest" ++ // DefaultTag is latest ++ DefaultTag = "latest" + ) + + var ( +diff --git a/daemon/push.go b/daemon/push.go +index d3f5571..ac05383 100644 +--- a/daemon/push.go ++++ b/daemon/push.go +@@ -68,12 +68,6 @@ 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/save.go b/daemon/save.go +index 35b67de..ee70691 100644 +--- a/daemon/save.go ++++ b/daemon/save.go +@@ -16,6 +16,7 @@ package daemon + import ( + "context" + "os" ++ "strings" + + "github.com/containers/image/v5/docker/reference" + "github.com/containers/image/v5/types" +@@ -76,7 +77,7 @@ func (b *Backend) Save(req *pb.SaveRequest, stream pb.Control_SaveServer) error + var err error + opts := b.getSaveOptions(req) + +- if err = checkFormatAndExpandTag(&opts); err != nil { ++ if err = checkFormat(&opts); err != nil { + return err + } + if err = filterImageName(&opts); err != nil { +@@ -159,7 +160,7 @@ func messageHandler(stream pb.Control_SaveServer, cliLogger *logger.Logger) func + } + } + +-func checkFormatAndExpandTag(opts *saveOptions) error { ++func checkFormat(opts *saveOptions) error { + switch opts.format { + case constant.DockerTransport: + opts.format = constant.DockerArchiveTransport +@@ -169,14 +170,6 @@ func checkFormatAndExpandTag(opts *saveOptions) error { + return errors.New("wrong image format provided") + } + +- for i, imageName := range opts.oriImgList { +- nameWithTag, err := image.CheckAndAddDefaultTag(imageName, opts.localStore) +- if err != nil { +- return errors.Wrapf(err, "check format and expand tag failed with image name %q", imageName) +- } +- opts.oriImgList[i] = nameWithTag +- } +- + return nil + } + +@@ -205,12 +198,11 @@ func filterImageName(opts *saveOptions) error { + opts.finalImageOrdered = append(opts.finalImageOrdered, img.ID) + } + +- ref, err := reference.Parse(imageName) +- if err != nil { +- return errors.Wrapf(err, "filter image name failed when parsing name %q", imageName) +- } +- tagged, withTag := ref.(reference.NamedTagged) +- if withTag { ++ if !strings.HasPrefix(img.ID, imageName) { ++ tagged, _, err := image.GetNamedTaggedReference(imageName) ++ if err != nil { ++ return errors.Wrapf(err, "get named tagged reference failed when saving image %q", imageName) ++ } + finalImage.tags = append(finalImage.tags, tagged) + } + opts.finalImageSet[img.ID] = finalImage +diff --git a/exporter/docker/archive/archive.go b/exporter/docker/archive/archive.go +index 36a2881..60e67fd 100644 +--- a/exporter/docker/archive/archive.go ++++ b/exporter/docker/archive/archive.go +@@ -19,7 +19,6 @@ import ( + "sync" + + "github.com/containers/image/v5/docker/archive" +- "github.com/containers/image/v5/transports/alltransports" + "github.com/containers/image/v5/types" + "github.com/pkg/errors" + +@@ -50,24 +49,47 @@ func (d *dockerArchiveExporter) Name() string { + } + + func (d *dockerArchiveExporter) Init(opts exporter.ExportOptions, src, destSpec string, localStore *store.Store) error { +- var ( +- srcReference types.ImageReference +- destReference types.ImageReference +- err error +- ) ++ var archiveFilePath string ++ + const partsNum = 2 +- // src could be form of ImageID digest or name[:tag] ++ ++ // src is an imageid digest + // destSpec could be "file:name:tag" or "file:name" or just "file" with transport "docker-archive", such as docker-archive:output.tar:name:tag +- // When more than two parts, build must be called ++ if parts := strings.Split(destSpec, ":"); len(parts) < partsNum { ++ return errors.Errorf("image name %q is invalid", destSpec) ++ } else if len(parts) == partsNum { ++ archiveFilePath = strings.SplitN(destSpec, ":", partsNum)[1] ++ } else { ++ fileNameTag := strings.SplitN(destSpec, ":", partsNum)[1] ++ archiveFilePath = strings.SplitN(fileNameTag, ":", partsNum)[0] ++ } ++ ++ if DockerArchiveExporter.GetArchiveWriter(opts.ExportID) == nil { ++ archWriter, err := archive.NewWriter(opts.SystemContext, archiveFilePath) ++ if err != nil { ++ return errors.Wrapf(err, "create archive writer failed") ++ } ++ DockerArchiveExporter.InitArchiveWriter(opts.ExportID, archWriter) ++ } ++ ++ // when destSpec is more than two parts, build operation must be called + if parts := strings.Split(destSpec, ":"); len(parts) > partsNum { +- srcReference, _, err = image.FindImage(localStore, src) ++ srcReference, _, err := image.FindImage(localStore, src) + if err != nil { + return errors.Wrapf(err, "find src image: %q failed with transport %q", src, d.Name()) + } +- destReference, err = alltransports.ParseImageName(destSpec) ++ ++ // removing docker.io/library/ prefix by not using alltransports.ParseImageName ++ namedTagged, _, err := image.GetNamedTaggedReference(strings.Join(parts[2:], ":")) ++ if err != nil { ++ return errors.Wrapf(err, "get named tagged reference of image %q failed", strings.Join(parts[2:], ":")) ++ } ++ archiveWriter := DockerArchiveExporter.GetArchiveWriter(opts.ExportID) ++ destReference, err := archiveWriter.NewReference(namedTagged) + if err != nil { + return errors.Wrapf(err, "parse dest spec: %q failed with transport %q", destSpec, d.Name()) + } ++ + d.Lock() + d.items[opts.ExportID] = exporter.Bus{ + SrcRef: srcReference, +@@ -79,23 +101,13 @@ func (d *dockerArchiveExporter) Init(opts exporter.ExportOptions, src, destSpec + } + + // from build or save, we can get path from the other part +- archiveFilePath := strings.SplitN(destSpec, ":", partsNum)[1] +- +- if DockerArchiveExporter.GetArchiveWriter(opts.ExportID) == nil { +- archWriter, wErr := archive.NewWriter(opts.SystemContext, archiveFilePath) +- if wErr != nil { +- return errors.Wrapf(wErr, "create archive writer failed") +- } +- DockerArchiveExporter.InitArchiveWriter(opts.ExportID, archWriter) +- } +- +- srcReference, _, err = image.FindImage(localStore, src) ++ srcReference, _, err := image.FindImage(localStore, src) + if err != nil { + return errors.Wrapf(err, "find src image: %q failed with transport %q", src, d.Name()) + } + + archiveWriter := DockerArchiveExporter.GetArchiveWriter(opts.ExportID) +- destReference, err = archiveWriter.NewReference(nil) ++ destReference, err := archiveWriter.NewReference(nil) + if err != nil { + return errors.Wrapf(err, "parse dest spec: %q failed", destSpec) + } +diff --git a/image/image.go b/image/image.go +index b6210f2..5dda185 100644 +--- a/image/image.go ++++ b/image/image.go +@@ -482,7 +482,7 @@ func FindImage(store *store.Store, image string) (types.ImageReference, *storage + if err != nil { + return nil, nil, errors.Wrapf(err, "failed to parse image %q in local store", localName) + } +- ++ + return ref, img, nil + } + +@@ -528,9 +528,8 @@ func tryResolveNameInStore(name string, store *store.Store) string { + return img.ID + } + +- defaultTag := "latest" +- logrus.Infof("Try to find image: %s:%s in local storage", name, defaultTag) +- img, err = store.Image(fmt.Sprintf("%s:%s", name, defaultTag)) ++ logrus.Infof("Try to find image: %s:%s in local storage", name, constant.DefaultTag) ++ img, err = store.Image(fmt.Sprintf("%s:%s", name, constant.DefaultTag)) + if err != nil { + return "" + } +@@ -621,25 +620,24 @@ func tryResolveNameInRegistries(name string, sc *types.SystemContext) ([]string, + return candidates, constant.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) ++// GetNamedTaggedReference checks an image name, if it does not include a tag, default tag "latest" will be added to it. ++func GetNamedTaggedReference(image string) (reference.NamedTagged, string, error) { ++ if image == "" { ++ return nil, "", nil + } + +- 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 +- } ++ if slashLastIndex, sepLastIndex := strings.LastIndex(image, "/"), strings.LastIndex(image, ":"); sepLastIndex == -1 || (sepLastIndex < slashLastIndex) { ++ image = fmt.Sprintf("%s:%s", image, constant.DefaultTag) ++ } ++ ++ ref, err := reference.Parse(image) ++ if err != nil { ++ return nil, "", errors.Wrapf(err, "filter image name failed when parsing name %q", image) ++ } ++ tagged, withTag := ref.(reference.NamedTagged) ++ if !withTag { ++ return nil, "", errors.Errorf("image %q does not contain a tag even though the default tag is added", image) + } + +- // for imageName is the format of imageID +- return imageName, nil ++ return tagged, image, nil + } +diff --git a/image/image_test.go b/image/image_test.go +index 43d936f..15b13e1 100644 +--- a/image/image_test.go ++++ b/image/image_test.go +@@ -123,3 +123,99 @@ registries = [] + assert.Assert(t, cmp.Contains(candidates, "localhost/busybox:latest")) + assert.Equal(t, transport, constant.DockerTransport) + } ++ ++func TestGetNamedTaggedReference(t *testing.T) { ++ type testcase struct { ++ name string ++ tag string ++ output string ++ wantErr bool ++ errString string ++ } ++ testcases := []testcase{ ++ { ++ name: "test 1", ++ tag: "isula/test", ++ output: "isula/test:latest", ++ wantErr: false, ++ }, ++ { ++ name: "test 2", ++ tag: "localhost:5000/test", ++ output: "localhost:5000/test:latest", ++ wantErr: false, ++ }, ++ { ++ name: "test 3", ++ tag: "isula/test:latest", ++ output: "isula/test:latest", ++ wantErr: false, ++ }, ++ { ++ name: "test 4", ++ tag: "localhost:5000/test:latest", ++ output: "localhost:5000/test:latest", ++ wantErr: false, ++ }, ++ { ++ name: "test 5", ++ tag: "localhost:5000:aaa/test:latest", ++ output: "", ++ wantErr: true, ++ errString: "invalid reference format", ++ }, ++ { ++ name: "test 6", ++ tag: "localhost:5000:aaa/test", ++ output: "", ++ wantErr: true, ++ errString: "invalid reference format", ++ }, ++ { ++ name: "test 7", ++ tag: "localhost:5000/test:latest:latest", ++ output: "", ++ wantErr: true, ++ errString: "invalid reference format", ++ }, ++ { ++ name: "test 8", ++ tag: "test:latest:latest", ++ output: "", ++ wantErr: true, ++ errString: "invalid reference format", ++ }, ++ { ++ name: "test 9", ++ tag: "", ++ output: "", ++ wantErr: false, ++ }, ++ { ++ name: "test 10", ++ tag: "abc efg:latest", ++ output: "", ++ wantErr: true, ++ errString: "invalid reference format", ++ }, ++ { ++ name: "test 11", ++ tag: "abc!@#:latest", ++ output: "", ++ wantErr: true, ++ errString: "invalid reference format", ++ }, ++ } ++ for _, tc := range testcases { ++ t.Run(tc.name, func(t *testing.T) { ++ _, tag, err := GetNamedTaggedReference(tc.tag) ++ if !tc.wantErr { ++ assert.Equal(t, tag, tc.output, tc.name) ++ } ++ if tc.wantErr { ++ assert.ErrorContains(t, err, tc.errString) ++ } ++ }) ++ ++ } ++} +-- +1.8.3.1 + diff --git a/patch/0071-use-image.GetNamedTaggedReference-instead-of-dockerf.patch b/patch/0071-use-image.GetNamedTaggedReference-instead-of-dockerf.patch new file mode 100644 index 0000000..9e19dc8 --- /dev/null +++ b/patch/0071-use-image.GetNamedTaggedReference-instead-of-dockerf.patch @@ -0,0 +1,236 @@ +From 7117427081e16b18eca768bf4e3274bd3e1fbb2b Mon Sep 17 00:00:00 2001 +From: xingweizheng +Date: Wed, 1 Sep 2021 22:29:12 +0800 +Subject: [PATCH 5/5] use image.GetNamedTaggedReference instead of + dockerfile.CheckAndExpandTag + +--- + builder/dockerfile/builder.go | 44 +------------------- + builder/dockerfile/builder_test.go | 84 -------------------------------------- + daemon/import.go | 2 +- + daemon/manifest.go | 3 +- + daemon/tag.go | 3 +- + 5 files changed, 5 insertions(+), 131 deletions(-) + +diff --git a/builder/dockerfile/builder.go b/builder/dockerfile/builder.go +index e28fac9..df8c6ce 100644 +--- a/builder/dockerfile/builder.go ++++ b/builder/dockerfile/builder.go +@@ -27,7 +27,6 @@ import ( + "strings" + "time" + +- "github.com/containers/image/v5/docker/reference" + "github.com/containers/image/v5/manifest" + securejoin "github.com/cyphar/filepath-securejoin" + "github.com/opencontainers/go-digest" +@@ -203,14 +202,14 @@ func parseTag(output, additionalTag string) (string, string, error) { + addTag string + ) + if tag = parseOutputTag(output); tag != "" { +- _, tag, err = CheckAndExpandTag(tag) ++ _, tag, err = image.GetNamedTaggedReference(tag) + if err != nil { + return "", "", err + } + } + + if additionalTag != "" { +- _, addTag, err = CheckAndExpandTag(additionalTag) ++ _, addTag, err = image.GetNamedTaggedReference(additionalTag) + if err != nil { + return "", "", err + } +@@ -633,42 +632,3 @@ func parseOutputTag(output string) string { + + return tag + } +- +-// 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, "", nil +- } +- +- newTag := tag +- slashLastIndex := strings.LastIndex(newTag, "/") +- sepLastIndex := strings.LastIndex(newTag, ":") +- if sepLastIndex == -1 || (sepLastIndex < slashLastIndex) { +- // isula +- // localhost:5000/isula +- newTag = fmt.Sprintf("%s:%s", newTag, constant.DefaultTag) +- } +- +- const longestTagFieldsLen = 3 +- if len(strings.Split(newTag, ":")) > longestTagFieldsLen { +- // localhost:5000:5000/isula:latest +- return nil, "", errors.Errorf("invalid tag: %v", newTag) +- } +- +- oriRef, err := reference.ParseNormalizedNamed(newTag) +- if err != nil { +- return nil, "", errors.Wrapf(err, "parse tag err, invalid tag: %v", newTag) +- } +- +- tagWithoutRepo := newTag[slashLastIndex+1:] +- _, err = reference.ParseNormalizedNamed(tagWithoutRepo) +- if err != nil { +- // isula:latest:latest +- // localhost/isula:latest:latest +- // isula!@#:latest +- // isula :latest +- return nil, "", errors.Wrapf(err, "parse tag err, invalid tag: %v", newTag) +- } +- +- return oriRef, newTag, nil +-} +diff --git a/builder/dockerfile/builder_test.go b/builder/dockerfile/builder_test.go +index 60668e1..c2fec6c 100644 +--- a/builder/dockerfile/builder_test.go ++++ b/builder/dockerfile/builder_test.go +@@ -1470,87 +1470,3 @@ func TestNewBuilder(t *testing.T) { + }) + } + } +- +-func TestCheckAndExpandTag(t *testing.T) { +- type testcase struct { +- name string +- tag string +- output string +- wantErr bool +- } +- testcases := []testcase{ +- { +- name: "test 1", +- tag: "isula/test", +- output: "isula/test:latest", +- wantErr: false, +- }, +- { +- name: "test 2", +- tag: "localhost:5000/test", +- output: "localhost:5000/test:latest", +- wantErr: false, +- }, +- { +- name: "test 3", +- tag: "isula/test:latest", +- output: "isula/test:latest", +- wantErr: false, +- }, +- { +- name: "test 4", +- tag: "localhost:5000/test:latest", +- output: "localhost:5000/test:latest", +- wantErr: false, +- }, +- { +- name: "test 5", +- tag: "localhost:5000:aaa/test:latest", +- output: "", +- wantErr: true, +- }, +- { +- name: "test 6", +- tag: "localhost:5000:aaa/test", +- output: "", +- wantErr: true, +- }, +- { +- name: "test 7", +- tag: "localhost:5000/test:latest:latest", +- output: "", +- wantErr: true, +- }, +- { +- name: "test 8", +- tag: "test:latest:latest", +- output: "", +- wantErr: true, +- }, +- { +- name: "test 9", +- tag: "", +- output: "", +- wantErr: false, +- }, +- { +- name: "test 10", +- tag: "abc efg:latest", +- output: "", +- wantErr: true, +- }, +- { +- name: "test 10", +- tag: "abc!@#:latest", +- output: "", +- wantErr: true, +- }, +- } +- for _, tc := range testcases { +- _, tag, err := CheckAndExpandTag(tc.tag) +- assert.Equal(t, tag, tc.output, tc.name) +- if (err != nil) != tc.wantErr { +- t.Errorf("getCheckAndExpandTag() error = %v, wantErr %v", err, tc.wantErr) +- } +- } +-} +diff --git a/daemon/import.go b/daemon/import.go +index 40a0a92..2da36be 100644 +--- a/daemon/import.go ++++ b/daemon/import.go +@@ -62,7 +62,7 @@ func (b *Backend) Import(req *pb.ImportRequest, stream pb.Control_ImportServer) + logEntry.Error(err) + return err + } +- _, reference, err = dockerfile.CheckAndExpandTag(reference) ++ _, reference, err = image.GetNamedTaggedReference(reference) + if err != nil { + logEntry.Error(err) + return err +diff --git a/daemon/manifest.go b/daemon/manifest.go +index 36e7674..940850e 100644 +--- a/daemon/manifest.go ++++ b/daemon/manifest.go +@@ -26,7 +26,6 @@ import ( + + constant "isula.org/isula-build" + pb "isula.org/isula-build/api/services" +- "isula.org/isula-build/builder/dockerfile" + "isula.org/isula-build/exporter" + "isula.org/isula-build/image" + "isula.org/isula-build/pkg/logger" +@@ -61,7 +60,7 @@ func (b *Backend) ManifestCreate(ctx context.Context, req *pb.ManifestCreateRequ + } + + // expand list name +- _, imageName, err := dockerfile.CheckAndExpandTag(manifestName) ++ _, imageName, err := image.GetNamedTaggedReference(manifestName) + if err != nil { + logrus.WithField(util.LogKeySessionID, manifestName).Errorf("Check and expand list name err: %v", err) + return &pb.ManifestCreateResponse{}, err +diff --git a/daemon/tag.go b/daemon/tag.go +index fe6a5a2..57de15c 100644 +--- a/daemon/tag.go ++++ b/daemon/tag.go +@@ -21,7 +21,6 @@ import ( + "github.com/sirupsen/logrus" + + pb "isula.org/isula-build/api/services" +- "isula.org/isula-build/builder/dockerfile" + "isula.org/isula-build/image" + ) + +@@ -40,7 +39,7 @@ func (b *Backend) Tag(ctx context.Context, req *pb.TagRequest) (*gogotypes.Empty + return emptyResp, errors.Wrapf(err, "find local image %v error", req.Image) + } + +- _, imageName, err := dockerfile.CheckAndExpandTag(req.Tag) ++ _, imageName, err := image.GetNamedTaggedReference(req.Tag) + if err != nil { + return emptyResp, err + } +-- +1.8.3.1 + diff --git a/series.conf b/series.conf index 3273efb..822a1f6 100644 --- a/series.conf +++ b/series.conf @@ -25,3 +25,12 @@ patch/0058-shellcheck-fix-of-common.sh.patch patch/0059-bugfix-fix-save-multiple-tags-single-image-failed.patch patch/0060-add-integration-test-for-saving-one-image-with-multi.patch patch/0061-fix-save-single-image-error-when-id-first-with-its-n.patch +patch/0062-clean-code-staticcheck-fix-of-S1020-S1023-SA9003-S10.patch +patch/0063-relocation-exporter-package-and-remove-unused-const.patch +patch/0064-clean-code-tidy-FindImage-function.patch +patch/0065-clean-code-delete-channel-within-the-same-goroutine.patch +patch/0067-fix-golangci-lint-warnings.patch +patch/0068-change-golangci-lint-config-and-remove-redundant-che.patch +patch/0069-make-add-make-info-for-Makefile.patch +patch/0070-clean-code-all-latest-tag-checks-take-the-FindImage-.patch +patch/0071-use-image.GetNamedTaggedReference-instead-of-dockerf.patch