Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions .github/workflows/s3-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,61 @@ jobs:
region_name: ${{ env.REGION_NAME }}
stack_name: ${{ env.STACK_NAME }}

# AWS European Sovereign Cloud Integration
aws-s3-esc-integration:
name: AWS S3 European Sovereign Cloud Integration
runs-on: ubuntu-latest
# Run on push/workflow_dispatch, skip forks and Dependabot on PRs
if: |
github.event_name == 'push' ||
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && github.actor != 'dependabot[bot]')
env:
REGION_NAME: eusc-de-east-1
STACK_NAME: s3cli-private-bucket
S3_ENDPOINT_HOST: https://s3.eusc-de-east-1.amazonaws.eu

steps:
- name: Checkout code
uses: actions/checkout@v6

- name: Set up Go
uses: actions/setup-go@v6
with:
go-version-file: go.mod

- name: Install Ginkgo
run: go install github.com/onsi/ginkgo/v2/ginkgo@latest

- name: Setup AWS infrastructure
uses: ./.github/actions/s3-integration-setup
with:
access_key_id: ${{ secrets.AWS_ESC_ACCESS_KEY_ID }}
secret_access_key: ${{ secrets.AWS_ESC_SECRET_ACCESS_KEY }}
region_name: ${{ env.REGION_NAME }}
stack_name: ${{ env.STACK_NAME }}

- name: Run AWS ESC region tests
uses: ./.github/actions/s3-integration-run
with:
access_key_id: ${{ secrets.AWS_ESC_ACCESS_KEY_ID }}
secret_access_key: ${{ secrets.AWS_ESC_SECRET_ACCESS_KEY }}
region_name: ${{ env.REGION_NAME }}
stack_name: ${{ env.STACK_NAME }}
s3_endpoint_host: ${{ env.S3_ENDPOINT_HOST }}
focus_regex: 'AWS ESC'
test_type: 'aws'

- name: Teardown AWS infrastructure
if: always()
uses: ./.github/actions/s3-integration-teardown
with:
access_key_id: ${{ secrets.AWS_ESC_ACCESS_KEY_ID }}
secret_access_key: ${{ secrets.AWS_ESC_SECRET_ACCESS_KEY }}
region_name: ${{ env.REGION_NAME }}
stack_name: ${{ env.STACK_NAME }}


s3-compatible-integration:
name: S3 Compatible Integration
runs-on: ubuntu-latest
Expand Down
128 changes: 128 additions & 0 deletions s3/integration/aws_esc_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package integration_test

import (
"os"

"github.com/cloudfoundry/storage-cli/s3/config"
"github.com/cloudfoundry/storage-cli/s3/integration"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

var _ = Describe("Testing for AWS European Sovereign Cloud region", func() {
Context("with AWS ESC (static creds) configurations", func() {
accessKeyID := os.Getenv("ACCESS_KEY_ID")
secretAccessKey := os.Getenv("SECRET_ACCESS_KEY")
bucketName := os.Getenv("BUCKET_NAME")
region := os.Getenv("REGION")
s3Host := os.Getenv("S3_HOST")

BeforeEach(func() {
Expect(accessKeyID).ToNot(BeEmpty(), "ACCESS_KEY_ID must be set")
Expect(secretAccessKey).ToNot(BeEmpty(), "SECRET_ACCESS_KEY must be set")
Expect(bucketName).ToNot(BeEmpty(), "BUCKET_NAME must be set")
Expect(region).ToNot(BeEmpty(), "REGION must be set")
Expect(s3Host).ToNot(BeEmpty(), "S3_HOST must be set")
})

configurations := []TableEntry{
Entry("with region and without host", &config.S3Cli{
AccessKeyID: accessKeyID,
SecretAccessKey: secretAccessKey,
BucketName: bucketName,
Region: region,
}),
Entry("with folder", &config.S3Cli{
AccessKeyID: accessKeyID,
SecretAccessKey: secretAccessKey,
BucketName: bucketName,
FolderName: "test-folder/a-folder",
Region: region,
}),
Entry("with host style enabled", &config.S3Cli{
AccessKeyID: accessKeyID,
SecretAccessKey: secretAccessKey,
BucketName: bucketName,
Region: region,
HostStyle: true,
}),
}
DescribeTable("Blobstore lifecycle works",
func(cfg *config.S3Cli) { integration.AssertLifecycleWorks(s3CLIPath, cfg) },
configurations,
)

DescribeTable("Invoking `ensure-storage-exists` works",
func(cfg *config.S3Cli) { integration.AssertOnStorageExists(s3CLIPath, cfg) },
configurations,
)
DescribeTable("Blobstore bulk operations work",
func(cfg *config.S3Cli) { integration.AssertOnBulkOperations(s3CLIPath, cfg) },
configurations,
)
DescribeTable("Invoking `s3cli get` on a non-existent-key fails",
func(cfg *config.S3Cli) { integration.AssertGetNonexistentFails(s3CLIPath, cfg) },
configurations,
)
DescribeTable("Invoking `s3cli delete` on a non-existent-key does not fail",
func(cfg *config.S3Cli) { integration.AssertDeleteNonexistentWorks(s3CLIPath, cfg) },
configurations,
)
DescribeTable("Invoking `s3cli sign` returns a signed URL",
func(cfg *config.S3Cli) { integration.AssertOnSignedURLs(s3CLIPath, cfg) },
configurations,
)
DescribeTable("Multipart copy works with low threshold",
func(cfg *config.S3Cli) { integration.AssertMultipartCopyWorks(s3CLIPath, cfg) },
configurations,
)

configurations = []TableEntry{
Entry("with encryption", &config.S3Cli{
AccessKeyID: accessKeyID,
SecretAccessKey: secretAccessKey,
BucketName: bucketName,
Region: region,
ServerSideEncryption: "AES256",
}),
Entry("without encryption", &config.S3Cli{
AccessKeyID: accessKeyID,
SecretAccessKey: secretAccessKey,
BucketName: bucketName,
Region: region,
}),
}
DescribeTable("Invoking `s3cli put` uploads with options",
func(cfg *config.S3Cli) { integration.AssertPutOptionsApplied(s3CLIPath, cfg) },
configurations,
)

Describe("Invoking `s3cli put` with arbitrary upload failures", func() {
It("returns the appropriate error message", func() {
cfg := &config.S3Cli{
AccessKeyID: accessKeyID,
SecretAccessKey: secretAccessKey,
BucketName: bucketName,
Host: "http://localhost",
}
msg := "upload failure"
integration.AssertOnPutFailures(cfg, largeContent, msg)
})
})

Describe("Invoking `s3cli put` with multipart upload failures", func() {
It("returns the appropriate error message", func() {
cfg := &config.S3Cli{
AccessKeyID: accessKeyID,
SecretAccessKey: secretAccessKey,
BucketName: bucketName,
Region: region,
MultipartUpload: true,
}
msg := "upload retry limit exceeded"
integration.AssertOnPutFailures(cfg, largeContent, msg)
})
})
})
})
Loading