github.com/SAP/jenkins-library@v1.362.0/cmd/imagePushToRegistry_test.go (about)

     1  package cmd
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/stretchr/testify/assert"
     7  
     8  	dockermock "github.com/SAP/jenkins-library/pkg/docker/mock"
     9  	"github.com/SAP/jenkins-library/pkg/mock"
    10  )
    11  
    12  const (
    13  	customDockerConfig = `{"auths":{"source.registry":{"auth":"c291cmNldXNlcjpzb3VyY2VwYXNzd29yZA=="},"target.registry":{"auth":"dGFyZ2V0dXNlcjp0YXJnZXRwYXNzd29yZA=="}}}`
    14  	dockerConfig       = `{
    15  	"auths": {
    16  		"source.registry": {
    17  			"auth": "c291cmNldXNlcjpzb3VyY2VwYXNzd29yZA=="
    18  		},
    19  		"target.registry": {
    20  			"auth": "dGFyZ2V0dXNlcjp0YXJnZXRwYXNzd29yZA=="
    21  		},
    22  		"test.registry": {
    23  			"auth": "dGVzdHVzZXI6dGVzdHBhc3N3b3Jk"
    24  		}
    25  	}
    26  }`
    27  )
    28  
    29  type imagePushToRegistryMockUtils struct {
    30  	*mock.ExecMockRunner
    31  	*mock.FilesMock
    32  	*dockermock.CraneMockUtils
    33  }
    34  
    35  func newImagePushToRegistryMockUtils(craneUtils *dockermock.CraneMockUtils) *imagePushToRegistryMockUtils {
    36  	utils := &imagePushToRegistryMockUtils{
    37  		ExecMockRunner: &mock.ExecMockRunner{},
    38  		FilesMock:      &mock.FilesMock{},
    39  		CraneMockUtils: craneUtils,
    40  	}
    41  
    42  	return utils
    43  }
    44  
    45  func TestRunImagePushToRegistry(t *testing.T) {
    46  	t.Parallel()
    47  
    48  	t.Run("good case", func(t *testing.T) {
    49  		t.Parallel()
    50  
    51  		config := imagePushToRegistryOptions{
    52  			SourceRegistryURL:      "https://source.registry",
    53  			SourceImages:           []string{"source-image"},
    54  			SourceImageTag:         "1.0.0-123+456",
    55  			SourceRegistryUser:     "sourceuser",
    56  			SourceRegistryPassword: "sourcepassword",
    57  			TargetRegistryURL:      "https://target.registry",
    58  			TargetImages:           map[string]any{"source-image": "target-image"},
    59  			TargetImageTag:         "1.0.0-123+456",
    60  			TargetRegistryUser:     "targetuser",
    61  			TargetRegistryPassword: "targetpassword",
    62  		}
    63  		craneMockUtils := &dockermock.CraneMockUtils{}
    64  		utils := newImagePushToRegistryMockUtils(craneMockUtils)
    65  		err := runImagePushToRegistry(&config, nil, utils)
    66  		assert.NoError(t, err)
    67  		createdConfig, err := utils.FileRead(targetDockerConfigPath)
    68  		assert.NoError(t, err)
    69  		assert.Equal(t, customDockerConfig, string(createdConfig))
    70  		assert.Equal(t, "1.0.0-123-456", config.SourceImageTag)
    71  		assert.Equal(t, "1.0.0-123-456", config.TargetImageTag)
    72  	})
    73  
    74  	t.Run("multiple imageNameTags", func(t *testing.T) {
    75  		t.Parallel()
    76  
    77  		config := imagePushToRegistryOptions{
    78  			SourceRegistryURL: "https://source.registry",
    79  			SourceImages:      []string{"source-image"},
    80  			SourceImageNameTags: []string{"com.sap.docker/ppiper:240104-20240227184612",
    81  				"com.sap.docker/ppiper:240104-20240227184612-amd64",
    82  				"com.sap.docker/ppiper:240104-20240227184612-aarch64",
    83  			},
    84  			SourceRegistryUser:     "sourceuser",
    85  			SourceRegistryPassword: "sourcepassword",
    86  			TargetRegistryURL:      "https://target.registry",
    87  			TargetImageTag:         "1.0.0-123+456",
    88  			TargetRegistryUser:     "targetuser",
    89  			TargetRegistryPassword: "targetpassword",
    90  			UseImageNameTags:       true,
    91  		}
    92  		craneMockUtils := &dockermock.CraneMockUtils{}
    93  		utils := newImagePushToRegistryMockUtils(craneMockUtils)
    94  		err := runImagePushToRegistry(&config, nil, utils)
    95  		assert.NoError(t, err)
    96  		createdConfig, err := utils.FileRead(targetDockerConfigPath)
    97  		assert.Equal(t, customDockerConfig, string(createdConfig))
    98  	})
    99  
   100  	t.Run("failed to copy image", func(t *testing.T) {
   101  		t.Parallel()
   102  
   103  		config := imagePushToRegistryOptions{
   104  			SourceRegistryURL:      "https://source.registry",
   105  			SourceRegistryUser:     "sourceuser",
   106  			SourceRegistryPassword: "sourcepassword",
   107  			SourceImages:           []string{"source-image"},
   108  			TargetRegistryURL:      "https://target.registry",
   109  			TargetRegistryUser:     "targetuser",
   110  			TargetRegistryPassword: "targetpassword",
   111  			TargetImageTag:         "0.0.1",
   112  		}
   113  		craneMockUtils := &dockermock.CraneMockUtils{
   114  			ErrCopyImage: dockermock.ErrCopyImage,
   115  		}
   116  		utils := newImagePushToRegistryMockUtils(craneMockUtils)
   117  		err := runImagePushToRegistry(&config, nil, utils)
   118  		assert.EqualError(t, err, "failed to copy images: copy image err")
   119  	})
   120  
   121  	t.Run("failed to push local image", func(t *testing.T) {
   122  		t.Parallel()
   123  
   124  		config := imagePushToRegistryOptions{
   125  			TargetImages:           map[string]any{"img": "source-image"},
   126  			TargetImageTag:         "0.0.1",
   127  			TargetRegistryURL:      "https://target.registry",
   128  			TargetRegistryUser:     "targetuser",
   129  			TargetRegistryPassword: "targetpassword",
   130  			LocalDockerImagePath:   "/local/path",
   131  			PushLocalDockerImage:   true,
   132  		}
   133  		craneMockUtils := &dockermock.CraneMockUtils{
   134  			ErrLoadImage: dockermock.ErrLoadImage,
   135  		}
   136  		utils := newImagePushToRegistryMockUtils(craneMockUtils)
   137  		err := runImagePushToRegistry(&config, nil, utils)
   138  		assert.EqualError(t, err, "failed to push local image to \"target.registry\": load image err")
   139  	})
   140  }
   141  
   142  func TestHandleCredentialsForPrivateRegistry(t *testing.T) {
   143  	t.Parallel()
   144  
   145  	craneMockUtils := &dockermock.CraneMockUtils{}
   146  	t.Run("no custom docker config provided", func(t *testing.T) {
   147  		t.Parallel()
   148  
   149  		utils := newImagePushToRegistryMockUtils(craneMockUtils)
   150  		utils.AddFile("targetDockerConfigPath", []byte("abc"))
   151  		err := handleCredentialsForPrivateRegistry("", "target.registry", "targetuser", "targetpassword", utils)
   152  		assert.NoError(t, err)
   153  		createdConfigFile, err := utils.FileRead(targetDockerConfigPath)
   154  		assert.NoError(t, err)
   155  		assert.Equal(t, `{"auths":{"target.registry":{"auth":"dGFyZ2V0dXNlcjp0YXJnZXRwYXNzd29yZA=="}}}`, string(createdConfigFile))
   156  	})
   157  
   158  	t.Run("custom docker config provided", func(t *testing.T) {
   159  		t.Parallel()
   160  
   161  		utils := newImagePushToRegistryMockUtils(craneMockUtils)
   162  		utils.AddFile(targetDockerConfigPath, []byte(customDockerConfig))
   163  		err := handleCredentialsForPrivateRegistry(targetDockerConfigPath, "test.registry", "testuser", "testpassword", utils)
   164  		assert.NoError(t, err)
   165  		createdConfigFile, err := utils.FileRead(targetDockerConfigPath)
   166  		assert.NoError(t, err)
   167  		assert.Equal(t, dockerConfig, string(createdConfigFile))
   168  	})
   169  
   170  	t.Run("wrong format of docker config", func(t *testing.T) {
   171  		t.Parallel()
   172  
   173  		utils := newImagePushToRegistryMockUtils(craneMockUtils)
   174  		utils.AddFile(targetDockerConfigPath, []byte(`{auths:}`))
   175  		err := handleCredentialsForPrivateRegistry("", "test.registry", "testuser", "testpassword", utils)
   176  		assert.EqualError(t, err, "failed to create new docker config: failed to unmarshal json file '/root/.docker/config.json': invalid character 'a' looking for beginning of object key string")
   177  	})
   178  }
   179  
   180  func TestPushLocalImageToTargetRegistry(t *testing.T) {
   181  	t.Parallel()
   182  	t.Run("good case", func(t *testing.T) {
   183  		t.Parallel()
   184  
   185  		craneMockUtils := &dockermock.CraneMockUtils{}
   186  		config := &imagePushToRegistryOptions{
   187  			PushLocalDockerImage: true,
   188  			LocalDockerImagePath: "/image/path",
   189  			TargetRegistryURL:    "https://target.registry",
   190  			TagLatest:            false,
   191  		}
   192  		utils := newImagePushToRegistryMockUtils(craneMockUtils)
   193  		err := pushLocalImageToTargetRegistry(config, utils)
   194  		assert.NoError(t, err)
   195  	})
   196  
   197  	t.Run("bad case - failed to load image", func(t *testing.T) {
   198  		t.Parallel()
   199  
   200  		craneMockUtils := &dockermock.CraneMockUtils{
   201  			ErrLoadImage: dockermock.ErrLoadImage,
   202  		}
   203  		config := &imagePushToRegistryOptions{
   204  			PushLocalDockerImage: true,
   205  			LocalDockerImagePath: "/image/path",
   206  			TargetRegistryURL:    "https://target.registry",
   207  			TagLatest:            false,
   208  		}
   209  		utils := newImagePushToRegistryMockUtils(craneMockUtils)
   210  		err := pushLocalImageToTargetRegistry(config, utils)
   211  		assert.EqualError(t, err, "load image err")
   212  	})
   213  
   214  	t.Run("bad case - failed to push image", func(t *testing.T) {
   215  		t.Parallel()
   216  
   217  		craneMockUtils := &dockermock.CraneMockUtils{
   218  			ErrPushImage: dockermock.ErrPushImage,
   219  		}
   220  		config := &imagePushToRegistryOptions{
   221  			PushLocalDockerImage: true,
   222  			LocalDockerImagePath: "/image/path",
   223  			TargetRegistryURL:    "https://target.registry",
   224  			TargetImages:         map[string]any{"image1": "my-image"},
   225  			TagLatest:            true,
   226  		}
   227  		utils := newImagePushToRegistryMockUtils(craneMockUtils)
   228  		err := pushLocalImageToTargetRegistry(config, utils)
   229  		assert.EqualError(t, err, "push image err")
   230  	})
   231  }
   232  
   233  func TestMapSourceTargetImages(t *testing.T) {
   234  	expected := map[string]any{
   235  		"img1": "img1", "img2": "img2",
   236  	}
   237  	sourceImages := []string{"img1", "img2"}
   238  	got := mapSourceTargetImages(sourceImages)
   239  	assert.Equal(t, got, expected)
   240  }