github.com/kyma-project/kyma/components/asset-store-controller-manager@v0.0.0-20191203152857-3792b5df17c5/internal/store/store_test.go (about)

     1  package store_test
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"path/filepath"
     7  	"testing"
     8  
     9  	"github.com/kyma-project/kyma/components/asset-store-controller-manager/internal/store"
    10  	"github.com/kyma-project/kyma/components/asset-store-controller-manager/internal/store/automock"
    11  	"github.com/kyma-project/kyma/components/asset-store-controller-manager/pkg/apis/assetstore/v1alpha2"
    12  	"github.com/minio/minio-go"
    13  	"github.com/onsi/gomega"
    14  	"github.com/pkg/errors"
    15  	"github.com/stretchr/testify/mock"
    16  )
    17  
    18  func TestStore_BucketExists(t *testing.T) {
    19  	t.Run("Exists", func(t *testing.T) {
    20  		// Given
    21  		g := gomega.NewGomegaWithT(t)
    22  		name := "test-bucket"
    23  
    24  		minio := new(automock.MinioClient)
    25  		minio.On("BucketExists", name).Return(true, nil).Once()
    26  		defer minio.AssertExpectations(t)
    27  
    28  		store := store.New(minio, 1)
    29  
    30  		// When
    31  		exists, err := store.BucketExists(name)
    32  
    33  		// Then
    34  		g.Expect(err).NotTo(gomega.HaveOccurred())
    35  		g.Expect(exists).To(gomega.Equal(true))
    36  	})
    37  
    38  	t.Run("NotExists", func(t *testing.T) {
    39  		// Given
    40  		g := gomega.NewGomegaWithT(t)
    41  		name := "test-bucket"
    42  
    43  		minio := new(automock.MinioClient)
    44  		minio.On("BucketExists", name).Return(false, nil).Once()
    45  		defer minio.AssertExpectations(t)
    46  
    47  		store := store.New(minio, 1)
    48  
    49  		// When
    50  		exists, err := store.BucketExists(name)
    51  
    52  		// Then
    53  		g.Expect(err).NotTo(gomega.HaveOccurred())
    54  		g.Expect(exists).To(gomega.Equal(false))
    55  	})
    56  
    57  	t.Run("Error", func(t *testing.T) {
    58  		// Given
    59  		g := gomega.NewGomegaWithT(t)
    60  		name := "test-bucket"
    61  
    62  		minio := new(automock.MinioClient)
    63  		minio.On("BucketExists", name).Return(false, fmt.Errorf("test error")).Once()
    64  		defer minio.AssertExpectations(t)
    65  
    66  		store := store.New(minio, 1)
    67  
    68  		// When
    69  		exists, err := store.BucketExists(name)
    70  
    71  		// Then
    72  		g.Expect(err).To(gomega.HaveOccurred())
    73  		g.Expect(exists).To(gomega.Equal(false))
    74  	})
    75  }
    76  
    77  func TestStore_CompareBucketPolicy(t *testing.T) {
    78  	t.Run("SuccessNone", func(t *testing.T) {
    79  		// Given
    80  		g := gomega.NewGomegaWithT(t)
    81  		bucketName := "test-bucket"
    82  		expectedPolicy := v1alpha2.BucketPolicyNone
    83  		remotePolicy := "{\"Version\":\"2012-10-17\",\"Statement\":[]}"
    84  
    85  		minio := new(automock.MinioClient)
    86  		minio.On("GetBucketPolicy", bucketName).Return(remotePolicy, nil).Once()
    87  		defer minio.AssertExpectations(t)
    88  
    89  		store := store.New(minio, 1)
    90  
    91  		// When
    92  		equal, err := store.CompareBucketPolicy(bucketName, expectedPolicy)
    93  
    94  		// Then
    95  		g.Expect(err).NotTo(gomega.HaveOccurred())
    96  		g.Expect(equal).To(gomega.Equal(true))
    97  	})
    98  
    99  	t.Run("SuccessReadOnly", func(t *testing.T) {
   100  		// Given
   101  		g := gomega.NewGomegaWithT(t)
   102  		bucketName := "test-bucket"
   103  		expectedPolicy := v1alpha2.BucketPolicyReadOnly
   104  		remotePolicy := "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Action\":[\"s3:GetBucketLocation\",\"s3:ListBucket\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Resource\":[\"arn:aws:s3:::test-bucket\"],\"Sid\":\"\"},{\"Action\":[\"s3:GetObject\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Resource\":[\"arn:aws:s3:::test-bucket/*\"],\"Sid\":\"\"}]}"
   105  
   106  		minio := new(automock.MinioClient)
   107  		minio.On("GetBucketPolicy", bucketName).Return(remotePolicy, nil).Once()
   108  		defer minio.AssertExpectations(t)
   109  
   110  		store := store.New(minio, 1)
   111  
   112  		// When
   113  		equal, err := store.CompareBucketPolicy(bucketName, expectedPolicy)
   114  
   115  		// Then
   116  		g.Expect(err).NotTo(gomega.HaveOccurred())
   117  		g.Expect(equal).To(gomega.Equal(true))
   118  	})
   119  
   120  	t.Run("SuccessWriteOnly", func(t *testing.T) {
   121  		// Given
   122  		g := gomega.NewGomegaWithT(t)
   123  		bucketName := "test-bucket"
   124  		expectedPolicy := v1alpha2.BucketPolicyWriteOnly
   125  		remotePolicy := "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Action\":[\"s3:GetBucketLocation\",\"s3:ListBucketMultipartUploads\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Resource\":[\"arn:aws:s3:::test-bucket\"],\"Sid\":\"\"},{\"Action\":[\"s3:AbortMultipartUpload\",\"s3:DeleteObject\",\"s3:ListMultipartUploadParts\",\"s3:PutObject\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Resource\":[\"arn:aws:s3:::test-bucket/*\"],\"Sid\":\"\"}]}"
   126  
   127  		minio := new(automock.MinioClient)
   128  		minio.On("GetBucketPolicy", bucketName).Return(remotePolicy, nil).Once()
   129  		defer minio.AssertExpectations(t)
   130  
   131  		store := store.New(minio, 1)
   132  
   133  		// When
   134  		equal, err := store.CompareBucketPolicy(bucketName, expectedPolicy)
   135  
   136  		// Then
   137  		g.Expect(err).NotTo(gomega.HaveOccurred())
   138  		g.Expect(equal).To(gomega.Equal(true))
   139  	})
   140  
   141  	t.Run("SuccessReadWrite", func(t *testing.T) {
   142  		// Given
   143  		g := gomega.NewGomegaWithT(t)
   144  		bucketName := "test-bucket"
   145  		expectedPolicy := v1alpha2.BucketPolicyReadWrite
   146  		remotePolicy := "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Action\":[\"s3:GetBucketLocation\",\"s3:ListBucket\",\"s3:ListBucketMultipartUploads\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Resource\":[\"arn:aws:s3:::test-bucket\"],\"Sid\":\"\"},{\"Action\":[\"s3:AbortMultipartUpload\",\"s3:DeleteObject\",\"s3:GetObject\",\"s3:ListMultipartUploadParts\",\"s3:PutObject\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Resource\":[\"arn:aws:s3:::test-bucket/*\"],\"Sid\":\"\"}]}"
   147  
   148  		minio := new(automock.MinioClient)
   149  		minio.On("GetBucketPolicy", bucketName).Return(remotePolicy, nil).Once()
   150  		defer minio.AssertExpectations(t)
   151  
   152  		store := store.New(minio, 1)
   153  
   154  		// When
   155  		equal, err := store.CompareBucketPolicy(bucketName, expectedPolicy)
   156  
   157  		// Then
   158  		g.Expect(err).NotTo(gomega.HaveOccurred())
   159  		g.Expect(equal).To(gomega.Equal(true))
   160  	})
   161  
   162  	t.Run("SuccessMerged", func(t *testing.T) {
   163  		// Given
   164  		g := gomega.NewGomegaWithT(t)
   165  		bucketName := "test-bucket"
   166  		expectedPolicy := v1alpha2.BucketPolicyReadOnly
   167  		remotePolicy := "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Action\":[\"s3:GetBucketLocation\",\"s3:ListBucket\",\"s3:GetObject\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Resource\":[\"arn:aws:s3:::test-bucket\",\"arn:aws:s3:::test-bucket/*\"],\"Sid\":\"\"}]}"
   168  
   169  		minio := new(automock.MinioClient)
   170  		minio.On("GetBucketPolicy", bucketName).Return(remotePolicy, nil).Once()
   171  		defer minio.AssertExpectations(t)
   172  
   173  		store := store.New(minio, 1)
   174  
   175  		// When
   176  		equal, err := store.CompareBucketPolicy(bucketName, expectedPolicy)
   177  
   178  		// Then
   179  		g.Expect(err).NotTo(gomega.HaveOccurred())
   180  		g.Expect(equal).To(gomega.Equal(true))
   181  	})
   182  
   183  	t.Run("EmptyRemotePolicy", func(t *testing.T) {
   184  		// Given
   185  		g := gomega.NewGomegaWithT(t)
   186  		bucketName := "test-bucket"
   187  		expectedPolicy := v1alpha2.BucketPolicyNone
   188  
   189  		minio := new(automock.MinioClient)
   190  		minio.On("GetBucketPolicy", bucketName).Return("", nil).Once()
   191  		defer minio.AssertExpectations(t)
   192  
   193  		store := store.New(minio, 1)
   194  
   195  		// When
   196  		equal, err := store.CompareBucketPolicy(bucketName, expectedPolicy)
   197  
   198  		// Then
   199  		g.Expect(err).NotTo(gomega.HaveOccurred())
   200  		g.Expect(equal).To(gomega.Equal(false))
   201  	})
   202  
   203  	t.Run("Error", func(t *testing.T) {
   204  		// Given
   205  		g := gomega.NewGomegaWithT(t)
   206  		bucketName := "test-bucket"
   207  		expectedPolicy := v1alpha2.BucketPolicyNone
   208  
   209  		minio := new(automock.MinioClient)
   210  		minio.On("GetBucketPolicy", bucketName).Return("", errors.New("test-error")).Once()
   211  		defer minio.AssertExpectations(t)
   212  
   213  		store := store.New(minio, 1)
   214  
   215  		// When
   216  		_, err := store.CompareBucketPolicy(bucketName, expectedPolicy)
   217  
   218  		// Then
   219  		g.Expect(err).To(gomega.HaveOccurred())
   220  	})
   221  }
   222  
   223  func TestStore_ContainsAllObjects(t *testing.T) {
   224  	t.Run("Success", func(t *testing.T) {
   225  		// Given
   226  		g := gomega.NewGomegaWithT(t)
   227  		bucketName := "test-bucket"
   228  		assetName := "test-asset"
   229  		files := []string{"test/a.txt", "test/b/c/d.txt"}
   230  		objCh := fixObjectsChannel(minio.ObjectInfo{Key: "test-asset/test/a.txt"}, minio.ObjectInfo{Key: "test-asset/test/b/c/d.txt"})
   231  		ctx := context.TODO()
   232  
   233  		minio := new(automock.MinioClient)
   234  		minio.On("ListObjects", bucketName, assetName, true, ctx.Done()).Return(objCh).Once()
   235  		defer minio.AssertExpectations(t)
   236  
   237  		store := store.New(minio, 1)
   238  
   239  		// When
   240  		contains, err := store.ContainsAllObjects(ctx, bucketName, assetName, files)
   241  
   242  		// Then
   243  		g.Expect(err).NotTo(gomega.HaveOccurred())
   244  		g.Expect(contains).To(gomega.Equal(true))
   245  	})
   246  
   247  	t.Run("MissingFiles", func(t *testing.T) {
   248  		// Given
   249  		g := gomega.NewGomegaWithT(t)
   250  		bucketName := "test-bucket"
   251  		assetName := "test-asset"
   252  		files := []string{"test/a.txt", "test/b/c/d.txt"}
   253  		objCh := fixObjectsChannel(minio.ObjectInfo{Key: "test-asset/test/a.txt"})
   254  		ctx := context.TODO()
   255  
   256  		minio := new(automock.MinioClient)
   257  		minio.On("ListObjects", bucketName, assetName, true, ctx.Done()).Return(objCh).Once()
   258  		defer minio.AssertExpectations(t)
   259  
   260  		store := store.New(minio, 1)
   261  
   262  		// When
   263  		contains, err := store.ContainsAllObjects(ctx, bucketName, assetName, files)
   264  
   265  		// Then
   266  		g.Expect(err).NotTo(gomega.HaveOccurred())
   267  		g.Expect(contains).To(gomega.Equal(false))
   268  	})
   269  
   270  	t.Run("EmptyBucket", func(t *testing.T) {
   271  		// Given
   272  		g := gomega.NewGomegaWithT(t)
   273  		bucketName := "test-bucket"
   274  		assetName := "test-asset"
   275  		files := []string{"test/a.txt", "test/b/c/d.txt"}
   276  		objCh := fixObjectsChannel()
   277  		ctx := context.TODO()
   278  
   279  		minio := new(automock.MinioClient)
   280  		minio.On("ListObjects", bucketName, assetName, true, ctx.Done()).Return(objCh).Once()
   281  		defer minio.AssertExpectations(t)
   282  
   283  		store := store.New(minio, 1)
   284  
   285  		// When
   286  		contains, err := store.ContainsAllObjects(ctx, bucketName, assetName, files)
   287  
   288  		// Then
   289  		g.Expect(err).NotTo(gomega.HaveOccurred())
   290  		g.Expect(contains).To(gomega.Equal(false))
   291  	})
   292  
   293  	t.Run("EmptyAsset", func(t *testing.T) {
   294  		// Given
   295  		g := gomega.NewGomegaWithT(t)
   296  		bucketName := "test-bucket"
   297  		assetName := "test-asset"
   298  		files := make([]string, 0)
   299  		objCh := fixObjectsChannel(minio.ObjectInfo{Key: "test-asset/test/a.txt"})
   300  		ctx := context.TODO()
   301  
   302  		minio := new(automock.MinioClient)
   303  		minio.On("ListObjects", bucketName, assetName, true, ctx.Done()).Return(objCh).Once()
   304  		defer minio.AssertExpectations(t)
   305  
   306  		store := store.New(minio, 1)
   307  
   308  		// When
   309  		contains, err := store.ContainsAllObjects(ctx, bucketName, assetName, files)
   310  
   311  		// Then
   312  		g.Expect(err).NotTo(gomega.HaveOccurred())
   313  		g.Expect(contains).To(gomega.Equal(true))
   314  	})
   315  
   316  	t.Run("ListObjectsError", func(t *testing.T) {
   317  		// Given
   318  		g := gomega.NewGomegaWithT(t)
   319  		bucketName := "test-bucket"
   320  		assetName := "test-asset"
   321  		files := make([]string, 0)
   322  		objCh := fixObjectsChannel(minio.ObjectInfo{Key: "test-asset/test/a.txt", Err: errors.New("test-err")})
   323  		ctx := context.TODO()
   324  
   325  		minio := new(automock.MinioClient)
   326  		minio.On("ListObjects", bucketName, assetName, true, ctx.Done()).Return(objCh).Once()
   327  		defer minio.AssertExpectations(t)
   328  
   329  		store := store.New(minio, 1)
   330  
   331  		// When
   332  		_, err := store.ContainsAllObjects(ctx, bucketName, assetName, files)
   333  
   334  		// Then
   335  		g.Expect(err).To(gomega.HaveOccurred())
   336  	})
   337  }
   338  
   339  func TestStore_CreateBucket(t *testing.T) {
   340  	t.Run("SuccessNamespaced", func(t *testing.T) {
   341  		// Given
   342  		g := gomega.NewGomegaWithT(t)
   343  		namespace := "space"
   344  		crName := "test-bucket"
   345  		region := "asia"
   346  
   347  		minio := new(automock.MinioClient)
   348  		minio.On("BucketExists", mock.AnythingOfType("string")).Return(false, nil).Once()
   349  		minio.On("MakeBucket", mock.AnythingOfType("string"), region).Return(nil).Once()
   350  		defer minio.AssertExpectations(t)
   351  
   352  		store := store.New(minio, 1)
   353  
   354  		// When
   355  		name, err := store.CreateBucket(namespace, crName, region)
   356  
   357  		// Then
   358  		g.Expect(err).NotTo(gomega.HaveOccurred())
   359  		g.Expect(name).To(gomega.HavePrefix(crName))
   360  		g.Expect(name).ToNot(gomega.HaveSuffix(crName))
   361  	})
   362  
   363  	t.Run("SuccessClusterWide", func(t *testing.T) {
   364  		// Given
   365  		g := gomega.NewGomegaWithT(t)
   366  		crName := "test-bucket"
   367  		region := "asia"
   368  
   369  		minio := new(automock.MinioClient)
   370  		minio.On("BucketExists", mock.AnythingOfType("string")).Return(false, nil).Once()
   371  		minio.On("MakeBucket", mock.AnythingOfType("string"), region).Return(nil).Once()
   372  		defer minio.AssertExpectations(t)
   373  
   374  		store := store.New(minio, 1)
   375  
   376  		// When
   377  		name, err := store.CreateBucket("", crName, region)
   378  
   379  		// Then
   380  		g.Expect(err).NotTo(gomega.HaveOccurred())
   381  		g.Expect(name).To(gomega.HavePrefix(crName))
   382  		g.Expect(name).ToNot(gomega.HaveSuffix(crName))
   383  	})
   384  
   385  	t.Run("BucketExists", func(t *testing.T) {
   386  		// Given
   387  		g := gomega.NewGomegaWithT(t)
   388  		namespace := "space"
   389  		crName := "test-bucket"
   390  		region := "asia"
   391  
   392  		minio := new(automock.MinioClient)
   393  		minio.On("BucketExists", mock.AnythingOfType("string")).Return(true, nil).Once()
   394  		minio.On("BucketExists", mock.AnythingOfType("string")).Return(false, nil).Once()
   395  		minio.On("MakeBucket", mock.AnythingOfType("string"), region).Return(nil).Once()
   396  		defer minio.AssertExpectations(t)
   397  
   398  		store := store.New(minio, 1)
   399  
   400  		// When
   401  		name, err := store.CreateBucket(namespace, crName, region)
   402  
   403  		// Then
   404  		g.Expect(err).NotTo(gomega.HaveOccurred())
   405  		g.Expect(name).To(gomega.HavePrefix(crName))
   406  		g.Expect(name).ToNot(gomega.HaveSuffix(crName))
   407  	})
   408  
   409  	t.Run("CannotFindBucketName", func(t *testing.T) {
   410  		// Given
   411  		g := gomega.NewGomegaWithT(t)
   412  		namespace := "space"
   413  		crName := "test-bucket"
   414  		region := "asia"
   415  
   416  		minio := new(automock.MinioClient)
   417  		minio.On("BucketExists", mock.AnythingOfType("string")).Return(true, nil).Times(10)
   418  		defer minio.AssertExpectations(t)
   419  
   420  		store := store.New(minio, 1)
   421  
   422  		// When
   423  		_, err := store.CreateBucket(namespace, crName, region)
   424  
   425  		// Then
   426  		g.Expect(err).To(gomega.HaveOccurred())
   427  	})
   428  
   429  	t.Run("BucketExistsError", func(t *testing.T) {
   430  		// Given
   431  		g := gomega.NewGomegaWithT(t)
   432  		namespace := "space"
   433  		crName := "test-bucket"
   434  		region := "asia"
   435  
   436  		minio := new(automock.MinioClient)
   437  		minio.On("BucketExists", mock.AnythingOfType("string")).Return(false, errors.New("test-err")).Once()
   438  		defer minio.AssertExpectations(t)
   439  
   440  		store := store.New(minio, 1)
   441  
   442  		// When
   443  		_, err := store.CreateBucket(namespace, crName, region)
   444  
   445  		// Then
   446  		g.Expect(err).To(gomega.HaveOccurred())
   447  	})
   448  
   449  	t.Run("MakeBucketError", func(t *testing.T) {
   450  		// Given
   451  		g := gomega.NewGomegaWithT(t)
   452  		namespace := "space"
   453  		crName := "test-bucket"
   454  		region := "asia"
   455  
   456  		minio := new(automock.MinioClient)
   457  		minio.On("BucketExists", mock.AnythingOfType("string")).Return(false, nil).Once()
   458  		minio.On("MakeBucket", mock.AnythingOfType("string"), region).Return(errors.New("test-error")).Once()
   459  
   460  		defer minio.AssertExpectations(t)
   461  
   462  		store := store.New(minio, 1)
   463  
   464  		// When
   465  		_, err := store.CreateBucket(namespace, crName, region)
   466  
   467  		// Then
   468  		g.Expect(err).To(gomega.HaveOccurred())
   469  	})
   470  }
   471  
   472  func TestStore_DeleteBucket(t *testing.T) {
   473  	t.Run("Success", func(t *testing.T) {
   474  		// Given
   475  		g := gomega.NewGomegaWithT(t)
   476  		name := "test-bucket"
   477  		ctx := context.TODO()
   478  		objCh := fixObjectsChannel(minio.ObjectInfo{Key: "obj1"}, minio.ObjectInfo{Key: "obj2"}, minio.ObjectInfo{Key: "obj3"})
   479  		errCh := fixRemoveObjectErrorChannel()
   480  
   481  		minio := new(automock.MinioClient)
   482  		minio.On("BucketExists", name).Return(true, nil).Once()
   483  		minio.On("ListObjects", name, "", true, ctx.Done()).Return(objCh).Once()
   484  		minio.On("RemoveObjectsWithContext", ctx, name, mock.Anything).Return(errCh).Once()
   485  		minio.On("RemoveBucket", name).Return(nil).Once()
   486  		defer minio.AssertExpectations(t)
   487  
   488  		store := store.New(minio, 1)
   489  
   490  		// When
   491  		err := store.DeleteBucket(ctx, name)
   492  
   493  		// Then
   494  		g.Expect(err).NotTo(gomega.HaveOccurred())
   495  	})
   496  
   497  	t.Run("EmptyBucket", func(t *testing.T) {
   498  		// Given
   499  		g := gomega.NewGomegaWithT(t)
   500  		name := "test-bucket"
   501  		ctx := context.TODO()
   502  		objCh := fixObjectsChannel()
   503  
   504  		minio := new(automock.MinioClient)
   505  		minio.On("BucketExists", name).Return(true, nil).Once()
   506  		minio.On("ListObjects", name, "", true, ctx.Done()).Return(objCh).Once()
   507  		minio.On("RemoveBucket", name).Return(nil).Once()
   508  		defer minio.AssertExpectations(t)
   509  
   510  		store := store.New(minio, 1)
   511  
   512  		// When
   513  		err := store.DeleteBucket(ctx, name)
   514  
   515  		// Then
   516  		g.Expect(err).NotTo(gomega.HaveOccurred())
   517  	})
   518  
   519  	t.Run("BucketNotExists", func(t *testing.T) {
   520  		// Given
   521  		g := gomega.NewGomegaWithT(t)
   522  		name := "test-bucket"
   523  		ctx := context.TODO()
   524  
   525  		minio := new(automock.MinioClient)
   526  		minio.On("BucketExists", name).Return(false, nil).Once()
   527  		defer minio.AssertExpectations(t)
   528  
   529  		store := store.New(minio, 1)
   530  
   531  		// When
   532  		err := store.DeleteBucket(ctx, name)
   533  
   534  		// Then
   535  		g.Expect(err).NotTo(gomega.HaveOccurred())
   536  	})
   537  
   538  	t.Run("BucketExistsError", func(t *testing.T) {
   539  		// Given
   540  		g := gomega.NewGomegaWithT(t)
   541  		name := "test-bucket"
   542  		ctx := context.TODO()
   543  
   544  		minio := new(automock.MinioClient)
   545  		minio.On("BucketExists", name).Return(false, fmt.Errorf("test error")).Once()
   546  		defer minio.AssertExpectations(t)
   547  
   548  		store := store.New(minio, 1)
   549  
   550  		// When
   551  		err := store.DeleteBucket(ctx, name)
   552  
   553  		// Then
   554  		g.Expect(err).To(gomega.HaveOccurred())
   555  	})
   556  
   557  	t.Run("ListObjectsError", func(t *testing.T) {
   558  		// Given
   559  		g := gomega.NewGomegaWithT(t)
   560  		name := "test-bucket"
   561  		ctx := context.TODO()
   562  		objCh := fixObjectsChannel(minio.ObjectInfo{Key: "obj1"}, minio.ObjectInfo{Key: "obj2", Err: fmt.Errorf("test error")})
   563  
   564  		minio := new(automock.MinioClient)
   565  		minio.On("BucketExists", name).Return(true, nil).Once()
   566  		minio.On("ListObjects", name, "", true, ctx.Done()).Return(objCh).Once()
   567  		defer minio.AssertExpectations(t)
   568  
   569  		store := store.New(minio, 1)
   570  
   571  		// When
   572  		err := store.DeleteBucket(ctx, name)
   573  
   574  		// Then
   575  		g.Expect(err).To(gomega.HaveOccurred())
   576  	})
   577  
   578  	t.Run("RemoveBucketError", func(t *testing.T) {
   579  		// Given
   580  		g := gomega.NewGomegaWithT(t)
   581  		name := "test-bucket"
   582  		ctx := context.TODO()
   583  		objCh := fixObjectsChannel(minio.ObjectInfo{Key: "obj1"}, minio.ObjectInfo{Key: "obj2"}, minio.ObjectInfo{Key: "obj3"})
   584  		errCh := fixRemoveObjectErrorChannel()
   585  
   586  		minio := new(automock.MinioClient)
   587  		minio.On("BucketExists", name).Return(true, nil).Once()
   588  		minio.On("ListObjects", name, "", true, ctx.Done()).Return(objCh).Once()
   589  		minio.On("RemoveObjectsWithContext", ctx, name, mock.Anything).Return(errCh).Once()
   590  		minio.On("RemoveBucket", name).Return(errors.New("test-error")).Once()
   591  		defer minio.AssertExpectations(t)
   592  
   593  		store := store.New(minio, 1)
   594  
   595  		// When
   596  		err := store.DeleteBucket(ctx, name)
   597  
   598  		// Then
   599  		g.Expect(err).To(gomega.HaveOccurred())
   600  	})
   601  }
   602  
   603  func TestStore_DeleteObjects(t *testing.T) {
   604  	t.Run("Success", func(t *testing.T) {
   605  		// Given
   606  		g := gomega.NewGomegaWithT(t)
   607  		name := "test-bucket"
   608  		ctx := context.TODO()
   609  		objCh := fixObjectsChannel(minio.ObjectInfo{Key: "obj1"}, minio.ObjectInfo{Key: "obj2"}, minio.ObjectInfo{Key: "obj3"})
   610  		errCh := fixRemoveObjectErrorChannel()
   611  
   612  		minio := new(automock.MinioClient)
   613  		minio.On("ListObjects", name, "", true, ctx.Done()).Return(objCh).Once()
   614  		minio.On("RemoveObjectsWithContext", ctx, name, mock.Anything).Return(errCh).Once()
   615  		defer minio.AssertExpectations(t)
   616  
   617  		store := store.New(minio, 1)
   618  
   619  		// When
   620  		err := store.DeleteObjects(ctx, name, "")
   621  
   622  		// Then
   623  		g.Expect(err).NotTo(gomega.HaveOccurred())
   624  	})
   625  
   626  	t.Run("SuccessWithPrefix", func(t *testing.T) {
   627  		// Given
   628  		g := gomega.NewGomegaWithT(t)
   629  		name := "test-bucket"
   630  		prefix := "test"
   631  		ctx := context.TODO()
   632  		objCh := fixObjectsChannel(minio.ObjectInfo{Key: "test/obj1"}, minio.ObjectInfo{Key: "test/obj2"}, minio.ObjectInfo{Key: "test/obj3"})
   633  		errCh := fixRemoveObjectErrorChannel()
   634  
   635  		minio := new(automock.MinioClient)
   636  		minio.On("ListObjects", name, prefix, true, ctx.Done()).Return(objCh).Once()
   637  		minio.On("RemoveObjectsWithContext", ctx, name, mock.Anything).Return(errCh).Once()
   638  		defer minio.AssertExpectations(t)
   639  
   640  		store := store.New(minio, 1)
   641  
   642  		// When
   643  		err := store.DeleteObjects(ctx, name, prefix)
   644  
   645  		// Then
   646  		g.Expect(err).NotTo(gomega.HaveOccurred())
   647  	})
   648  
   649  	t.Run("NoObjects", func(t *testing.T) {
   650  		// Given
   651  		g := gomega.NewGomegaWithT(t)
   652  		name := "test-bucket"
   653  		ctx := context.TODO()
   654  		objCh := fixObjectsChannel()
   655  
   656  		minio := new(automock.MinioClient)
   657  		minio.On("ListObjects", name, "", true, ctx.Done()).Return(objCh).Once()
   658  		defer minio.AssertExpectations(t)
   659  
   660  		store := store.New(minio, 1)
   661  
   662  		// When
   663  		err := store.DeleteObjects(ctx, name, "")
   664  
   665  		// Then
   666  		g.Expect(err).NotTo(gomega.HaveOccurred())
   667  	})
   668  
   669  	t.Run("ListObjectsError", func(t *testing.T) {
   670  		// Given
   671  		g := gomega.NewGomegaWithT(t)
   672  		name := "test-bucket"
   673  		ctx := context.TODO()
   674  		objCh := fixObjectsChannel(minio.ObjectInfo{Key: "obj1"}, minio.ObjectInfo{Key: "obj2", Err: fmt.Errorf("test error")})
   675  
   676  		minio := new(automock.MinioClient)
   677  		minio.On("ListObjects", name, "", true, ctx.Done()).Return(objCh).Once()
   678  		defer minio.AssertExpectations(t)
   679  
   680  		store := store.New(minio, 1)
   681  
   682  		// When
   683  		err := store.DeleteObjects(ctx, name, "")
   684  
   685  		// Then
   686  		g.Expect(err).To(gomega.HaveOccurred())
   687  	})
   688  
   689  	t.Run("RemoveObjectsError", func(t *testing.T) {
   690  		// Given
   691  		g := gomega.NewGomegaWithT(t)
   692  		name := "test-bucket"
   693  		ctx := context.TODO()
   694  		objCh := fixObjectsChannel(minio.ObjectInfo{Key: "obj1"}, minio.ObjectInfo{Key: "obj2"}, minio.ObjectInfo{Key: "obj3"})
   695  		errCh := fixRemoveObjectErrorChannel(errors.New("test-error"))
   696  
   697  		minio := new(automock.MinioClient)
   698  		minio.On("ListObjects", name, "", true, ctx.Done()).Return(objCh).Once()
   699  		minio.On("RemoveObjectsWithContext", ctx, name, mock.Anything).Return(errCh).Once()
   700  		defer minio.AssertExpectations(t)
   701  
   702  		store := store.New(minio, 1)
   703  
   704  		// When
   705  		err := store.DeleteObjects(ctx, name, "")
   706  
   707  		// Then
   708  		g.Expect(err).To(gomega.HaveOccurred())
   709  	})
   710  }
   711  
   712  func TestStore_PutObjects(t *testing.T) {
   713  	t.Run("Success", func(t *testing.T) {
   714  		// Given
   715  		g := gomega.NewGomegaWithT(t)
   716  		bucketName := "test-bucket"
   717  		assetName := "test-asset"
   718  		sourceBasePath := "/tmp"
   719  		files := []string{"test/a.txt", "test/b.txt"}
   720  		ctx := context.TODO()
   721  
   722  		minio := new(automock.MinioClient)
   723  		minio.On("FPutObjectWithContext", ctx, bucketName, filepath.Join(assetName, files[0]), filepath.Join(sourceBasePath, files[0]), mock.Anything).Return(int64(1), nil).Once()
   724  		minio.On("FPutObjectWithContext", ctx, bucketName, filepath.Join(assetName, files[1]), filepath.Join(sourceBasePath, files[1]), mock.Anything).Return(int64(1), nil).Once()
   725  		defer minio.AssertExpectations(t)
   726  
   727  		store := store.New(minio, 2)
   728  
   729  		// When
   730  		err := store.PutObjects(ctx, bucketName, assetName, sourceBasePath, files)
   731  
   732  		// Then
   733  		g.Expect(err).NotTo(gomega.HaveOccurred())
   734  	})
   735  
   736  	t.Run("Error", func(t *testing.T) {
   737  		// Given
   738  		g := gomega.NewGomegaWithT(t)
   739  		bucketName := "test-bucket"
   740  		assetName := "test-asset"
   741  		sourceBasePath := "/tmp"
   742  		files := []string{"test/a.txt", "test/b.txt"}
   743  		ctx := context.TODO()
   744  
   745  		minio := new(automock.MinioClient)
   746  		minio.On("FPutObjectWithContext", ctx, bucketName, filepath.Join(assetName, files[0]), filepath.Join(sourceBasePath, files[0]), mock.Anything).Return(int64(1), nil).Once()
   747  		minio.On("FPutObjectWithContext", ctx, bucketName, filepath.Join(assetName, files[1]), filepath.Join(sourceBasePath, files[1]), mock.Anything).Return(int64(1), errors.New("test-error")).Once()
   748  		defer minio.AssertExpectations(t)
   749  
   750  		store := store.New(minio, 1)
   751  
   752  		// When
   753  		err := store.PutObjects(ctx, bucketName, assetName, sourceBasePath, files)
   754  
   755  		// Then
   756  		g.Expect(err).To(gomega.HaveOccurred())
   757  	})
   758  
   759  	t.Run("NoFiles", func(t *testing.T) {
   760  		// Given
   761  		g := gomega.NewGomegaWithT(t)
   762  		bucketName := "test-bucket"
   763  		assetName := "test-asset"
   764  		sourceBasePath := "/tmp"
   765  		files := make([]string, 0)
   766  		ctx := context.TODO()
   767  
   768  		minio := new(automock.MinioClient)
   769  		defer minio.AssertExpectations(t)
   770  
   771  		store := store.New(minio, 1)
   772  
   773  		// When
   774  		err := store.PutObjects(ctx, bucketName, assetName, sourceBasePath, files)
   775  
   776  		// Then
   777  		g.Expect(err).ToNot(gomega.HaveOccurred())
   778  	})
   779  }
   780  
   781  func TestStore_SetBucketPolicy(t *testing.T) {
   782  	t.Run("SuccessNone", func(t *testing.T) {
   783  		// Given
   784  		g := gomega.NewGomegaWithT(t)
   785  		bucketName := "test-bucket"
   786  		policy := v1alpha2.BucketPolicyNone
   787  		marshaledPolicy := "{\"Version\":\"2012-10-17\",\"Statement\":[]}"
   788  
   789  		minio := new(automock.MinioClient)
   790  		minio.On("SetBucketPolicy", bucketName, marshaledPolicy).Return(nil).Once()
   791  		defer minio.AssertExpectations(t)
   792  
   793  		store := store.New(minio, 1)
   794  
   795  		// When
   796  		err := store.SetBucketPolicy(bucketName, policy)
   797  
   798  		// Then
   799  		g.Expect(err).NotTo(gomega.HaveOccurred())
   800  	})
   801  
   802  	t.Run("SuccessReadOnly", func(t *testing.T) {
   803  		// Given
   804  		g := gomega.NewGomegaWithT(t)
   805  		bucketName := "test-bucket"
   806  		expectedPolicy := v1alpha2.BucketPolicyReadOnly
   807  		marshaledPolicy := "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Action\":[\"s3:GetBucketLocation\",\"s3:ListBucket\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Resource\":[\"arn:aws:s3:::test-bucket\"],\"Sid\":\"\"},{\"Action\":[\"s3:GetObject\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Resource\":[\"arn:aws:s3:::test-bucket/*\"],\"Sid\":\"\"}]}"
   808  
   809  		minio := new(automock.MinioClient)
   810  		minio.On("SetBucketPolicy", bucketName, marshaledPolicy).Return(nil).Once()
   811  		defer minio.AssertExpectations(t)
   812  
   813  		store := store.New(minio, 1)
   814  
   815  		// When
   816  		err := store.SetBucketPolicy(bucketName, expectedPolicy)
   817  
   818  		// Then
   819  		g.Expect(err).NotTo(gomega.HaveOccurred())
   820  	})
   821  
   822  	t.Run("SuccessWriteOnly", func(t *testing.T) {
   823  		// Given
   824  		g := gomega.NewGomegaWithT(t)
   825  		bucketName := "test-bucket"
   826  		expectedPolicy := v1alpha2.BucketPolicyWriteOnly
   827  		marshaledPolicy := "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Action\":[\"s3:GetBucketLocation\",\"s3:ListBucketMultipartUploads\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Resource\":[\"arn:aws:s3:::test-bucket\"],\"Sid\":\"\"},{\"Action\":[\"s3:AbortMultipartUpload\",\"s3:DeleteObject\",\"s3:ListMultipartUploadParts\",\"s3:PutObject\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Resource\":[\"arn:aws:s3:::test-bucket/*\"],\"Sid\":\"\"}]}"
   828  
   829  		minio := new(automock.MinioClient)
   830  		minio.On("SetBucketPolicy", bucketName, marshaledPolicy).Return(nil).Once()
   831  		defer minio.AssertExpectations(t)
   832  
   833  		store := store.New(minio, 1)
   834  
   835  		// When
   836  		err := store.SetBucketPolicy(bucketName, expectedPolicy)
   837  
   838  		// Then
   839  		g.Expect(err).NotTo(gomega.HaveOccurred())
   840  	})
   841  
   842  	t.Run("SuccessReadWrite", func(t *testing.T) {
   843  		// Given
   844  		g := gomega.NewGomegaWithT(t)
   845  		bucketName := "test-bucket"
   846  		expectedPolicy := v1alpha2.BucketPolicyReadWrite
   847  		marshaledPolicy := "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Action\":[\"s3:GetBucketLocation\",\"s3:ListBucket\",\"s3:ListBucketMultipartUploads\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Resource\":[\"arn:aws:s3:::test-bucket\"],\"Sid\":\"\"},{\"Action\":[\"s3:AbortMultipartUpload\",\"s3:DeleteObject\",\"s3:GetObject\",\"s3:ListMultipartUploadParts\",\"s3:PutObject\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Resource\":[\"arn:aws:s3:::test-bucket/*\"],\"Sid\":\"\"}]}"
   848  
   849  		minio := new(automock.MinioClient)
   850  		minio.On("SetBucketPolicy", bucketName, marshaledPolicy).Return(nil).Once()
   851  		defer minio.AssertExpectations(t)
   852  
   853  		store := store.New(minio, 1)
   854  
   855  		// When
   856  		err := store.SetBucketPolicy(bucketName, expectedPolicy)
   857  
   858  		// Then
   859  		g.Expect(err).NotTo(gomega.HaveOccurred())
   860  	})
   861  
   862  	t.Run("Error", func(t *testing.T) {
   863  		// Given
   864  		g := gomega.NewGomegaWithT(t)
   865  		bucketName := "test-bucket"
   866  		expectedPolicy := v1alpha2.BucketPolicyNone
   867  		marshaledPolicy := "{\"Version\":\"2012-10-17\",\"Statement\":[]}"
   868  
   869  		minio := new(automock.MinioClient)
   870  		minio.On("SetBucketPolicy", bucketName, marshaledPolicy).Return(errors.New("test-error")).Once()
   871  		defer minio.AssertExpectations(t)
   872  
   873  		store := store.New(minio, 1)
   874  
   875  		// When
   876  		err := store.SetBucketPolicy(bucketName, expectedPolicy)
   877  
   878  		// Then
   879  		g.Expect(err).To(gomega.HaveOccurred())
   880  	})
   881  }
   882  
   883  func fixObjectsChannel(objects ...minio.ObjectInfo) <-chan minio.ObjectInfo {
   884  	objCh := make(chan minio.ObjectInfo, len(objects)+1)
   885  	defer close(objCh)
   886  	for _, object := range objects {
   887  		objCh <- object
   888  	}
   889  
   890  	return objCh
   891  }
   892  
   893  func fixRemoveObjectErrorChannel(errs ...error) <-chan minio.RemoveObjectError {
   894  	objCh := make(chan minio.RemoveObjectError, len(errs)+1)
   895  	defer close(objCh)
   896  	for _, err := range errs {
   897  		info := minio.RemoveObjectError{
   898  			Err: err,
   899  		}
   900  
   901  		objCh <- info
   902  	}
   903  
   904  	return objCh
   905  }