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  }