From b7a8bfbf90d920662e0bf8119c2640ec7a6379ca Mon Sep 17 00:00:00 2001
From: xingweizheng <xingweizheng@huawei.com>
Date: Tue, 31 Aug 2021 22:42:18 +0800
Subject: [PATCH] fix save single image error when id first with its name at
 last

---
 Makefile                                      |  4 +-
 daemon/save.go                                | 27 +++++++++----
 tests/lib/common.sh                           | 22 ++++++++--
 ...on_test_save_single_image_multiple_tags.sh | 40 ++++++++++++++-----
 tests/src/integration_test_set_new_root.sh    |  2 +
 5 files changed, 72 insertions(+), 23 deletions(-)

diff --git a/Makefile b/Makefile
index 1d87625..d5b1c53 100644
--- a/Makefile
+++ b/Makefile
@@ -74,7 +74,7 @@ debug:
 build-image:
 	isula-build ctr-img build -f Dockerfile.proto ${IMAGE_BUILDARGS} -o isulad:${IMAGE_NAME}:latest .
 
-tests: test-base test-unit test-integration
+tests: test-unit test-integration
 
 .PHONY: test-base
 test-base:
@@ -89,7 +89,7 @@ test-unit:
 	@echo "Unit test done!"
 
 .PHONY: test-integration
-test-integration:
+test-integration: debug install
 	@echo "Integration test starting..."
 	@./tests/test.sh base
 	@./tests/test.sh integration
diff --git a/daemon/save.go b/daemon/save.go
index 7ad1285..8ba9dd1 100644
--- a/daemon/save.go
+++ b/daemon/save.go
@@ -33,6 +33,11 @@ import (
 	"isula.org/isula-build/util"
 )
 
+type savedImage struct {
+	exist bool
+	tags  []reference.NamedTagged
+}
+
 type saveOptions struct {
 	sysCtx            *types.SystemContext
 	localStore        *store.Store
@@ -40,7 +45,7 @@ type saveOptions struct {
 	format            string
 	oriImgList        []string
 	finalImageOrdered []string
-	finalImageSet     map[string][]reference.NamedTagged
+	finalImageSet     map[string]*savedImage
 	outputPath        string
 	logger            *logger.Logger
 	logEntry          *logrus.Entry
@@ -54,7 +59,7 @@ func (b *Backend) getSaveOptions(req *pb.SaveRequest) saveOptions {
 		format:            req.GetFormat(),
 		oriImgList:        req.GetImages(),
 		finalImageOrdered: make([]string, 0),
-		finalImageSet:     make(map[string][]reference.NamedTagged),
+		finalImageSet:     make(map[string]*savedImage),
 		outputPath:        req.GetPath(),
 		logger:            logger.NewCliLogger(constant.CliLogBufferLen),
 		logEntry:          logrus.WithFields(logrus.Fields{"SaveID": req.GetSaveID(), "Format": req.GetFormat()}),
@@ -114,8 +119,10 @@ func exportHandler(ctx context.Context, opts *saveOptions) func() error {
 
 		for _, imageID := range opts.finalImageOrdered {
 			copyCtx := *opts.sysCtx
-			// It's ok for DockerArchiveAdditionalTags == nil, as a result, no additional tags will be appended to the final archive file.
-			copyCtx.DockerArchiveAdditionalTags = opts.finalImageSet[imageID]
+			if opts.format == constant.DockerArchiveTransport {
+				// It's ok for DockerArchiveAdditionalTags == nil, as a result, no additional tags will be appended to the final archive file.
+				copyCtx.DockerArchiveAdditionalTags = opts.finalImageSet[imageID].tags
+			}
 
 			exOpts := exporter.ExportOptions{
 				Ctx:           ctx,
@@ -190,7 +197,11 @@ func filterImageName(opts *saveOptions) error {
 		if err != nil {
 			return errors.Wrapf(err, "filter image name failed when finding image name %q", imageName)
 		}
-		if _, ok := opts.finalImageSet[img.ID]; !ok {
+
+		finalImage, ok := opts.finalImageSet[img.ID]
+		if !ok {
+			finalImage = &savedImage{exist: true}
+			finalImage.tags = []reference.NamedTagged{}
 			opts.finalImageOrdered = append(opts.finalImageOrdered, img.ID)
 		}
 
@@ -199,10 +210,10 @@ func filterImageName(opts *saveOptions) error {
 			return errors.Wrapf(err, "filter image name failed when parsing name %q", imageName)
 		}
 		tagged, withTag := ref.(reference.NamedTagged)
-		if !withTag {
-			continue
+		if withTag {
+			finalImage.tags = append(finalImage.tags, tagged)
 		}
-		opts.finalImageSet[img.ID] = append(opts.finalImageSet[img.ID], tagged)
+		opts.finalImageSet[img.ID] = finalImage
 	}
 
 	return nil
diff --git a/tests/lib/common.sh b/tests/lib/common.sh
index 6a207da..4dd34aa 100755
--- a/tests/lib/common.sh
+++ b/tests/lib/common.sh
@@ -222,9 +222,23 @@ function show_and_run_command() {
 }
 
 function run_with_debug() {
-    if [ "${DEBUG:-0}" -eq 1 ]; then
-        $1
-    else
-        $1 > /dev/null 2>&1
+    function fail_and_exit(){
+        echo "FAIL"
+        echo "Run \"journalctl -xefu isula-build\" to get the log."
+        systemctl stop isula-build
+        exit 1
+    }
+
+    if [ "${DEBUG:-0}" -eq 0 ]; then
+        if ! $1 > /dev/null 2>&1; then
+            fail_and_exit
+        fi
+        return
+    fi
+    echo "$1"
+    if ! $1; then
+        fail_and_exit
     fi
+    echo "------------command-delimiter-----------"
+    echo "                                        "
 }
\ No newline at end of file
diff --git a/tests/src/integration_test_save_single_image_multiple_tags.sh b/tests/src/integration_test_save_single_image_multiple_tags.sh
index a25786a..1eaeb8d 100644
--- a/tests/src/integration_test_save_single_image_multiple_tags.sh
+++ b/tests/src/integration_test_save_single_image_multiple_tags.sh
@@ -22,6 +22,7 @@ context_dir="$top_dir"/tests/data/add-chown-basic
 
 function clean()
 {
+    isula-build ctr-img rm -p > /dev/null 2>&1
     systemctl stop isula-build
     rm -rf "$temp_tar"
 }
@@ -34,21 +35,42 @@ function pre_test()
 
 function do_test()
 {
-    if ! run_with_debug "isula-build ctr-img build -t $image_name:latest $context_dir"; then
+    # get image id
+    if ! image_id1=$(isula-build ctr-img build -t $image_name:latest "$context_dir"|grep "Build success with image id: "|cut -d ":" -f 2); then
         echo "FAIL"
     fi
-
-    if ! run_with_debug "isula-build ctr-img tag $image_name:latest $image_name:latest-child"; then
+    if ! image_id2=$(isula-build ctr-img build -t $image_name:latest2 "$context_dir"|grep "Build success with image id: "|cut -d ":" -f 2); then
         echo "FAIL"
     fi
 
-    if ! run_with_debug "isula-build ctr-img save -f docker $image_name:latest $image_name:latest-child -o $temp_tar"; then
-        echo "FAIL"
-    fi
+    ! run_with_debug "isula-build ctr-img tag $image_name:latest $image_name:latest-child"
 
-    if ! run_with_debug "isula-build ctr-img rm $image_name:latest $image_name:latest-child"; then
-        echo "FAIL"
-    fi
+    # save with id + name
+    ! run_with_debug "isula-build ctr-img save -f docker $image_id1 $image_name:latest-child -o $temp_tar"
+    rm -rf "$temp_tar"
+
+    # save with name + id
+    ! run_with_debug "isula-build ctr-img save -f docker $image_name:latest-child $image_id1 -o $temp_tar"
+    rm -rf "$temp_tar"
+
+    # save with name + name
+    ! run_with_debug "isula-build ctr-img save -f docker $image_name:latest $image_name:latest-child -o $temp_tar"
+    rm -rf "$temp_tar"
+
+    # save with different images id1 + id2
+    ! run_with_debug "isula-build ctr-img save -f docker $image_id1 $image_id2 -o $temp_tar"
+    rm -rf "$temp_tar"
+
+    # save with different images "without latest tag" + id2
+    ! run_with_debug "isula-build ctr-img save -f docker $image_name $image_id2 -o $temp_tar"
+    rm -rf "$temp_tar"
+
+    # save with id1 + id2 + name
+    ! run_with_debug "isula-build ctr-img save -f docker $image_id1 $image_id2 $image_name:latest2 -o $temp_tar"
+    rm -rf "$temp_tar"
+
+    ! run_with_debug "isula-build ctr-img rm $image_name:latest $image_name:latest-child"
+    ! run_with_debug "isula-build ctr-img rm $image_name:latest2"
 
     echo "PASS" 
 }
diff --git a/tests/src/integration_test_set_new_root.sh b/tests/src/integration_test_set_new_root.sh
index 7238240..bb11a08 100644
--- a/tests/src/integration_test_set_new_root.sh
+++ b/tests/src/integration_test_set_new_root.sh
@@ -26,6 +26,8 @@ function clean()
 {
     rm -f $config_file
     mv "$config_file".bak $config_file
+
+    isula-build ctr-img rm -p > /dev/null 2>&1
     systemctl stop isula-build
     rm -rf $run_root $data_root
 }
-- 
2.27.0

