github.com/jenkins-x/jx/v2@v2.1.155/pkg/cloud/amazon/storage/bucket_provider_test.go (about) 1 // +build unit 2 3 package storage 4 5 import ( 6 "bufio" 7 "bytes" 8 "fmt" 9 "io" 10 "strings" 11 "testing" 12 13 "github.com/acarl005/stripansi" 14 "github.com/aws/aws-sdk-go/aws/awserr" 15 "github.com/aws/aws-sdk-go/service/s3" 16 "github.com/aws/aws-sdk-go/service/s3/s3iface" 17 "github.com/aws/aws-sdk-go/service/s3/s3manager" 18 "github.com/aws/aws-sdk-go/service/s3/s3manager/s3manageriface" 19 "github.com/jenkins-x/jx-logging/pkg/log" 20 "github.com/jenkins-x/jx/v2/pkg/config" 21 "github.com/stretchr/testify/assert" 22 ) 23 24 type mockedS3 struct { 25 s3iface.S3API 26 } 27 28 type mockedUploader struct { 29 s3manageriface.UploaderAPI 30 } 31 type mockedDownloader struct { 32 s3manager.Downloader 33 } 34 35 var ( 36 expectedBucketContents = `this is a test 37 string to download 38 from the bucket 39 ` 40 ) 41 42 type FakeRequestFailure struct { 43 awserr.RequestFailure 44 } 45 46 func (r FakeRequestFailure) HostID() string { 47 return "" 48 } 49 50 func (m mockedUploader) Upload(u *s3manager.UploadInput, f ...func(*s3manager.Uploader)) (*s3manager.UploadOutput, error) { 51 return &s3manager.UploadOutput{ 52 Location: fmt.Sprintf("%s%s", *u.Bucket, *u.Key), 53 }, nil 54 } 55 56 func (m mockedDownloader) Download(w io.WriterAt, i *s3.GetObjectInput, f ...func(*s3manager.Downloader)) (int64, error) { 57 written, err := w.WriteAt([]byte(expectedBucketContents), 0) 58 return int64(written), err 59 } 60 61 func (m mockedS3) HeadBucket(input *s3.HeadBucketInput) (*s3.HeadBucketOutput, error) { 62 if *input.Bucket == "bucket_that_exists" { 63 return &s3.HeadBucketOutput{}, nil 64 } 65 return nil, FakeRequestFailure{ 66 awserr.NewRequestFailure(awserr.New(s3.ErrCodeNoSuchBucket, "", nil), 404, ""), 67 } 68 } 69 70 func (m mockedS3) CreateBucket(input *s3.CreateBucketInput) (*s3.CreateBucketOutput, error) { 71 return nil, nil 72 } 73 74 func TestAmazonBucketProvider_EnsureBucketIsCreated(t *testing.T) { 75 p := AmazonBucketProvider{ 76 Requirements: &config.RequirementsConfig{ 77 Cluster: config.ClusterConfig{ 78 Region: "us-east-1", 79 }, 80 }, 81 api: &mockedS3{}, 82 } 83 84 tests := []struct { 85 bucket string 86 message string 87 }{ 88 { 89 bucket: "new_bucket", 90 message: "The bucket s3://new_bucket does not exist so lets create it\n", 91 }, 92 { 93 bucket: "bucket_that_exists", 94 message: "", 95 }, 96 } 97 for _, test := range tests { 98 t.Run(test.bucket, func(t *testing.T) { 99 message := log.CaptureOutput(func() { 100 err := p.EnsureBucketIsCreated("s3://" + test.bucket) 101 assert.NoError(t, err) 102 }) 103 104 assert.Equal(t, test.message, stripansi.Strip(message)) 105 }) 106 } 107 } 108 109 func TestAmazonBucketProvider_CreateNewBucketForCluster(t *testing.T) { 110 p := AmazonBucketProvider{ 111 Requirements: &config.RequirementsConfig{ 112 Cluster: config.ClusterConfig{ 113 Region: "us-east-1", 114 }, 115 }, 116 api: &mockedS3{}, 117 } 118 119 message := log.CaptureOutput(func() { 120 url, err := p.CreateNewBucketForCluster("test-cluster", "test-kind") 121 assert.NoError(t, err) 122 assert.True(t, strings.HasPrefix(url, "s3://test-cluster-test-kind-")) 123 }) 124 assert.NotEmpty(t, message) 125 126 // Test very long name and trimming of hyphens 127 message = log.CaptureOutput(func() { 128 longName := strings.Repeat("A", 62) 129 url, err := p.CreateNewBucketForCluster(longName+"-cluster", "test-kind") 130 assert.NoError(t, err) 131 assert.Equal(t, "s3://"+longName, url) 132 }) 133 assert.NotEmpty(t, message) 134 } 135 136 func TestAmazonBucketProvider_s3(t *testing.T) { 137 p := AmazonBucketProvider{ 138 Requirements: &config.RequirementsConfig{ 139 Cluster: config.ClusterConfig{ 140 Region: "us-east-1", 141 }, 142 }, 143 } 144 145 svc, err := p.s3() 146 assert.NoError(t, err) 147 assert.NotNil(t, svc) 148 } 149 150 func TestAmazonBucketProvider_s3WithNoRegion(t *testing.T) { 151 p := AmazonBucketProvider{ 152 Requirements: &config.RequirementsConfig{}, 153 } 154 155 svc, err := p.s3() 156 assert.Nil(t, svc) 157 assert.Error(t, err) 158 } 159 160 func TestAmazonBucketProvider_UploadFileToBucket(t *testing.T) { 161 p := AmazonBucketProvider{ 162 Requirements: &config.RequirementsConfig{ 163 Cluster: config.ClusterConfig{ 164 Region: "us-east-1", 165 }, 166 }, 167 uploader: mockedUploader{}, 168 } 169 b := []byte("This is uploaded") 170 location, err := p.UploadFileToBucket(bytes.NewReader(b), "output", "bucket") 171 assert.NoError(t, err) 172 173 assert.Equal(t, "s3://bucket/output", location, "the returned url should be valid") 174 } 175 176 func TestAmazonBucketProvider_DownloadFileFromBucket(t *testing.T) { 177 p := AmazonBucketProvider{ 178 Requirements: &config.RequirementsConfig{ 179 Cluster: config.ClusterConfig{ 180 Region: "us-east-1", 181 }, 182 }, 183 downloader: mockedDownloader{}, 184 } 185 reader, err := p.DownloadFileFromBucket("s3://bucket/key") 186 assert.NoError(t, err) 187 188 scanner := bufio.NewScanner(reader) 189 scanner.Split(bufio.ScanLines) 190 var bucketContent string 191 for scanner.Scan() { 192 bucketContent += fmt.Sprintln(scanner.Text()) 193 } 194 195 assert.Equal(t, expectedBucketContents, bucketContent, "the returned contents should be match") 196 err = reader.Close() 197 assert.NoError(t, err, "reader.Close()") 198 }