Skip to content

Commit 956ce9a

Browse files
authored
Merge pull request #123 from streamx-dev/issue_122
feat add support for different s3 providers
2 parents 215d73b + ecb405d commit 956ce9a

File tree

7 files changed

+191
-84
lines changed

7 files changed

+191
-84
lines changed

config/crd/bases/gatling-operator.tech.zozo.com_gatlings.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ spec:
176176
type: array
177177
provider:
178178
description: '(Required) Provider specifies the cloud provider
179-
that will be used. Supported providers: `aws`, `gcp`, and `azure`'
179+
that will be used. Supported providers: `aws`, `s3`, `gcp`, and `azure`'
180180
type: string
181181
region:
182182
description: (Optional) Region Name.

docs/user-guide.md

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
- [Parallel Number of Gatling Load Testing](#parallel-number-of-gatling-load-testing)
2323
- [Configure Cloud Storage Provider](#configure-cloud-storage-provider)
2424
- [Set Amazon S3 as Cloud Storage](#set-amazon-s3-as-cloud-storage)
25+
- [Set S3 as Cloud Storage](#set-s3-as-cloud-storage)
2526
- [Set Google Cloud Storage as Cloud Storage](#set-google-cloud-storage-as-cloud-storage)
2627
- [Set Azure Blob Storage as Cloud Storage](#set-azure-blob-storage-as-cloud-storage)
2728
- [Configure Notification Service Provider](#configure-notification-service-provider)
@@ -657,6 +658,60 @@ Here is an IAM policy to attach for Gatling Pod to interact with Amazon S3 bucke
657658
- Replace `BUCKET_NAME` above with your bucket name
658659
- To know more about the ways to supply rclone with a set of AWS credentials, please check [this](https://rclone.org/s3/#configuration).
659660

661+
#### Set S3 as Cloud Storage
662+
663+
This section provides guidance on setting up any cloud storage provider that supports the S3 API.
664+
In this example suppose you want to store Gatling reports to a bucket named `gatling-operator-reports` in OVH's S3 provider, specifically in the `de` region.
665+
You configure each fields in `.spec.cloudStorageSpec` and set `RCLONE_S3_ENDPOINT` env like this:
666+
667+
```yaml
668+
apiVersion: gatling-operator.tech.zozo.com/v1alpha1
669+
kind: Gatling
670+
metadata:
671+
name: gatling-sample
672+
spec:
673+
cloudStorageSpec:
674+
provider: "s3"
675+
bucket: "gatling-operator-reports"
676+
region: "de"
677+
env:
678+
- name: RCLONE_S3_ENDPOINT
679+
value: https://s3.de.io.cloud.ovh.net
680+
...omit...
681+
```
682+
683+
However, this is not enough. You must supply Gatling Pod (both Gatling Runner Pod and Gatling Reporter Pod) with credentials to access S3 bucket. Strictly speaking, [rclone](https://rclone.org/) container in Gatling Pod interacts with S3 bucket, thus you need to supply rclone with credentials.
684+
685+
Below is shown how to set S3 credentials via environment variables:
686+
687+
```yaml
688+
...omit...
689+
cloudStorageSpec:
690+
provider: "s3"
691+
bucket: "gatling-operator-reports"
692+
region: "de"
693+
env:
694+
- name: RCLONE_S3_PROVIDER
695+
value: Other
696+
- name: RCLONE_S3_ACCESS_KEY_ID
697+
valueFrom:
698+
secretKeyRef:
699+
name: s3-keys
700+
key: S3_ACCESS_KEY
701+
- name: RCLONE_S3_SECRET_ACCESS_KEY
702+
valueFrom:
703+
secretKeyRef:
704+
name: s3-keys
705+
key: S3_SECRET_ACCESS
706+
- name: RCLONE_S3_ENDPOINT
707+
value: https://s3.de.io.cloud.ovh.net
708+
- name: RCLONE_S3_REGION
709+
value: de
710+
...omit...
711+
```
712+
713+
There are multiple ways to authenticate for more please check [this](https://rclone.org/s3/#configuration).
714+
660715
#### Set Google Cloud Storage as Cloud Storage
661716

662717
Suppose that you want to store Gatling reports to a bucket named `gatling-operator-reports` of Google Cloud Storage, you configure each fields in `.spec.cloudStorageSpec` like this:

pkg/cloudstorages/aws.go

Lines changed: 0 additions & 65 deletions
This file was deleted.

pkg/cloudstorages/cloudstorage.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ func GetProvider(provider string, args ...EnvVars) *CloudStorageProvider {
2727
var csp CloudStorageProvider
2828
switch provider {
2929
case "aws":
30-
csp = &AWSCloudStorageProvider{providerName: provider}
30+
csp = &S3CloudStorageProvider{providerName: provider}
31+
case "s3":
32+
csp = &S3CloudStorageProvider{providerName: provider}
3133
case "gcp":
3234
csp = &GCPCloudStorageProvider{providerName: provider}
3335
case "azure":

pkg/cloudstorages/cloudstorage_test.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ var _ = Describe("GetProvider", func() {
1515
provider = "aws"
1616
expectedValue = "aws"
1717
})
18-
It("should get a pointer of AWSCloudStorageProvider that has ProviderName field value = aws", func() {
18+
It("should get a pointer of S3CloudStorageProvider that has ProviderName field value = aws", func() {
1919
cspp := GetProvider(provider)
2020
Expect(cspp).NotTo(BeNil())
2121
Expect((*cspp).GetName()).To(Equal(expectedValue))
@@ -34,6 +34,18 @@ var _ = Describe("GetProvider", func() {
3434
})
3535
})
3636

37+
Context("Provider is s3", func() {
38+
BeforeEach(func() {
39+
provider = "s3"
40+
expectedValue = "s3"
41+
})
42+
It("should get a pointer of S3CloudStorageProvider that has ProviderName field value = s3", func() {
43+
cspp := GetProvider(provider)
44+
Expect(cspp).NotTo(BeNil())
45+
Expect((*cspp).GetName()).To(Equal(expectedValue))
46+
})
47+
})
48+
3749
Context("Provider is non-supported one", func() {
3850
BeforeEach(func() {
3951
provider = "foo"

pkg/cloudstorages/s3.go

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package cloudstorages
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
)
7+
8+
type S3CloudStorageProvider struct {
9+
providerName string
10+
customS3ProviderHost string
11+
}
12+
13+
func (p *S3CloudStorageProvider) init(args []EnvVars) {
14+
if len(args) > 0 {
15+
var envs EnvVars = args[0]
16+
for _, env := range envs {
17+
if env.Name == "RCLONE_S3_ENDPOINT" {
18+
p.customS3ProviderHost = p.checkAndRemoveProtocol(env.Value)
19+
break
20+
}
21+
}
22+
}
23+
}
24+
25+
func (p *S3CloudStorageProvider) checkAndRemoveProtocol(url string) string {
26+
idx := strings.Index(url, "://")
27+
if idx == -1 {
28+
return url
29+
}
30+
return url[idx+3:]
31+
}
32+
33+
func (p *S3CloudStorageProvider) GetName() string {
34+
return p.providerName
35+
}
36+
37+
func (p *S3CloudStorageProvider) GetCloudStoragePath(bucket string, gatlingName string, subDir string) string {
38+
// Format s3:<bucket>/<gatling-name>/<sub-dir>
39+
return fmt.Sprintf("s3:%s/%s/%s", bucket, gatlingName, subDir)
40+
}
41+
42+
func (p *S3CloudStorageProvider) GetCloudStorageReportURL(bucket string, gatlingName string, subDir string) string {
43+
// Format https://<bucket>.<s3-provider-host>/<gatling-name>/<sub-dir>/index.html
44+
defaultS3ProviderHost := "s3.amazonaws.com"
45+
s3ProviderHost := defaultS3ProviderHost
46+
if p.customS3ProviderHost != "" {
47+
s3ProviderHost = p.customS3ProviderHost
48+
}
49+
50+
return fmt.Sprintf("https://%s.%s/%s/%s/index.html", bucket, s3ProviderHost, gatlingName, subDir)
51+
}
52+
53+
func (p *S3CloudStorageProvider) GetGatlingTransferResultCommand(resultsDirectoryPath string, region string, storagePath string) string {
54+
template := `
55+
RESULTS_DIR_PATH=%s
56+
rclone config create s3 s3 env_auth=true region %s
57+
while true; do
58+
if [ -f "${RESULTS_DIR_PATH}/FAILED" ]; then
59+
echo "Skip transfering gatling results"
60+
break
61+
fi
62+
if [ -f "${RESULTS_DIR_PATH}/COMPLETED" ]; then
63+
for source in $(find ${RESULTS_DIR_PATH} -type f -name *.log)
64+
do
65+
rclone copyto ${source} --s3-no-check-bucket --s3-env-auth %s/${HOSTNAME}.log
66+
done
67+
break
68+
fi
69+
sleep 1;
70+
done
71+
`
72+
return fmt.Sprintf(template, resultsDirectoryPath, region, storagePath)
73+
}
74+
75+
func (p *S3CloudStorageProvider) GetGatlingAggregateResultCommand(resultsDirectoryPath string, region string, storagePath string) string {
76+
template := `
77+
GATLING_AGGREGATE_DIR=%s
78+
rclone config create s3 s3 env_auth=true region %s
79+
rclone copy --s3-no-check-bucket --s3-env-auth %s ${GATLING_AGGREGATE_DIR}
80+
`
81+
return fmt.Sprintf(template, resultsDirectoryPath, region, storagePath)
82+
}
83+
84+
func (p *S3CloudStorageProvider) GetGatlingTransferReportCommand(resultsDirectoryPath string, region string, storagePath string) string {
85+
template := `
86+
GATLING_AGGREGATE_DIR=%s
87+
rclone config create s3 s3 env_auth=true region %s
88+
rclone copy ${GATLING_AGGREGATE_DIR} --exclude "*.log" --s3-no-check-bucket --s3-env-auth %s
89+
`
90+
return fmt.Sprintf(template, resultsDirectoryPath, region, storagePath)
91+
}

pkg/cloudstorages/aws_test.go renamed to pkg/cloudstorages/s3_test.go

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ var _ = Describe("GetName", func() {
1616
})
1717
Context("Provider is aws", func() {
1818
It("should get provider name = aws", func() {
19-
csp := &AWSCloudStorageProvider{providerName: provider}
19+
csp := &S3CloudStorageProvider{providerName: provider}
2020
Expect(csp.GetName()).To(Equal(expectedValue))
2121
})
2222
})
@@ -39,33 +39,45 @@ var _ = Describe("GetCloudStoragePath", func() {
3939
})
4040
Context("Provider is aws", func() {
4141
It("path is aws s3 bucket", func() {
42-
csp := &AWSCloudStorageProvider{providerName: provider}
42+
csp := &S3CloudStorageProvider{providerName: provider}
4343
Expect(csp.GetCloudStoragePath(bucket, gatlingName, subDir)).To(Equal(expectedValue))
4444
})
4545
})
4646
})
4747

4848
var _ = Describe("GetCloudStorageReportURL", func() {
4949
var (
50-
provider string
51-
bucket string
52-
gatlingName string
53-
subDir string
54-
expectedValue string
50+
provider string
51+
bucket string
52+
gatlingName string
53+
subDir string
5554
)
5655
BeforeEach(func() {
57-
provider = "aws"
56+
provider = "s3"
5857
bucket = "testBucket"
5958
gatlingName = "testGatling"
6059
subDir = "subDir"
61-
expectedValue = "https://testBucket.s3.amazonaws.com/testGatling/subDir/index.html"
6260
})
63-
Context("Provider is aws", func() {
64-
It("path is aws s3 bucket", func() {
65-
csp := &AWSCloudStorageProvider{providerName: provider}
66-
Expect(csp.GetCloudStorageReportURL(bucket, gatlingName, subDir)).To(Equal(expectedValue))
61+
Context("Provider is s3", func() {
62+
It("path is aws s3 bucket if RCLONE_S3_ENDPOINT not defined", func() {
63+
csp := &S3CloudStorageProvider{providerName: provider}
64+
Expect(csp.GetCloudStorageReportURL(bucket, gatlingName, subDir)).To(Equal("https://testBucket.s3.amazonaws.com/testGatling/subDir/index.html"))
65+
})
66+
67+
It("path is S3 bucket with custom provider endpoint", func() {
68+
csp := &S3CloudStorageProvider{providerName: provider}
69+
csp.init([]EnvVars{
70+
{
71+
{
72+
Name: "RCLONE_S3_ENDPOINT",
73+
Value: "https://s3.de.io.cloud.ovh.net",
74+
},
75+
},
76+
})
77+
Expect(csp.GetCloudStorageReportURL(bucket, gatlingName, subDir)).To(Equal("https://testBucket.s3.de.io.cloud.ovh.net/testGatling/subDir/index.html"))
6778
})
6879
})
80+
6981
})
7082

7183
var _ = Describe("GetGatlingTransferResultCommand", func() {
@@ -102,7 +114,7 @@ done
102114
})
103115
Context("Provider is aws", func() {
104116
It("returns commands with s3 rclone config", func() {
105-
csp := &AWSCloudStorageProvider{providerName: provider}
117+
csp := &S3CloudStorageProvider{providerName: provider}
106118
Expect(csp.GetGatlingTransferResultCommand(resultsDirectoryPath, region, storagePath)).To(Equal(expectedValue))
107119
})
108120
})
@@ -129,7 +141,7 @@ rclone copy --s3-no-check-bucket --s3-env-auth testStoragePath ${GATLING_AGGREGA
129141
})
130142
Context("Provider is aws", func() {
131143
It("returns commands with s3 rclone config", func() {
132-
csp := &AWSCloudStorageProvider{providerName: provider}
144+
csp := &S3CloudStorageProvider{providerName: provider}
133145
Expect(csp.GetGatlingAggregateResultCommand(resultsDirectoryPath, region, storagePath)).To(Equal(expectedValue))
134146
})
135147
})
@@ -156,7 +168,7 @@ rclone copy ${GATLING_AGGREGATE_DIR} --exclude "*.log" --s3-no-check-bucket --s3
156168
})
157169
Context("Provider is aws", func() {
158170
It("returns commands with s3 rclone config", func() {
159-
csp := &AWSCloudStorageProvider{providerName: provider}
171+
csp := &S3CloudStorageProvider{providerName: provider}
160172
Expect(csp.GetGatlingTransferReportCommand(resultsDirectoryPath, region, storagePath)).To(Equal(expectedValue))
161173
})
162174
})

0 commit comments

Comments
 (0)