37baabe134
* EE-384: add endpoint to set auto backup (#224) * EE-383: add endpoint to fetch backup settings (#231) * add get backup settings handler * add api docs desc * EE-382: restore from s3 (#233) * EE-381: add GET backup status handler (#234) * EE-385: Add S3 backup execute handler (#237) * add s3 backup execute handler * refactories inside `./api/backup/backup_scheduler.go` and `./api/backup/backup_scheduler.go` * fix tests * EE-375: added backup to S3 form * EE-376: added restore from S3 form * EE-377: Update Home screen to display last backup run status * update backup service with back end endpoints. * restart admin monitor during s3 restores * use go 1.13 * go 1.13 compatibility * EE-375: added cron-validator lib * EE-375: using enum to compare form types * EE-375: validate cron rule field * try fix windows build * EE-375 EE-376 backup and restore forms validation changes * fix(autobackup): update autobackup settings validation rules (#260) * fix(autobackup): automate backup to s3 fe update (#261) * EE-292: fixed typo in property. * EE-292: updated auto backup front end validation. * EE-292: updated lib to validate cron rule in front end * fix dependencies * bumped libcompose version Co-authored-by: Hui <arris_li@hotmail.com> Co-authored-by: Felix Han <felix.han@portainer.io> Co-authored-by: fhanportainer <79428273+fhanportainer@users.noreply.github.com>
119 lines
3.5 KiB
Go
119 lines
3.5 KiB
Go
package s3
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
"os/exec"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/aws/aws-sdk-go/aws"
|
|
"github.com/aws/aws-sdk-go/aws/credentials"
|
|
"github.com/aws/aws-sdk-go/aws/session"
|
|
"github.com/aws/aws-sdk-go/service/s3"
|
|
"github.com/pkg/errors"
|
|
portainer "github.com/portainer/portainer/api"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
var s3session *session.Session
|
|
|
|
const (
|
|
existingBucket = "testbucket"
|
|
key = "testfile"
|
|
)
|
|
|
|
func TestMain(m *testing.M) {
|
|
sess, stopMinio := startMinio()
|
|
s3session = sess
|
|
|
|
if _, err := s3.New(s3session).CreateBucket(&s3.CreateBucketInput{Bucket: aws.String(existingBucket)}); err != nil {
|
|
log.Fatal(errors.Wrap(err, "failed to create bucket"))
|
|
}
|
|
|
|
m.Run()
|
|
|
|
s3.New(s3session).DeleteObject(&s3.DeleteObjectInput{Bucket: aws.String(existingBucket), Key: aws.String(key)})
|
|
s3.New(s3session).DeleteBucket(&s3.DeleteBucketInput{Bucket: aws.String(existingBucket)})
|
|
stopMinio()
|
|
}
|
|
|
|
func Test_upload_shouldFail_whenBucketIsMissing(t *testing.T) {
|
|
if err := Upload(s3session, strings.NewReader("test"), "unknown-bucket", key); err != nil {
|
|
assert.Error(t, err, "should fail uploading to non existing bucket")
|
|
}
|
|
}
|
|
|
|
func Test_upload_shouldFail_whenBucketExists(t *testing.T) {
|
|
|
|
if err := Upload(s3session, strings.NewReader("test"), existingBucket, key); err != nil {
|
|
assert.Nil(t, err, "should succeed uploading to existing bucket")
|
|
}
|
|
}
|
|
|
|
func Test_download_shouldFail_whenBucketIsMissing(t *testing.T) {
|
|
buf := aws.NewWriteAtBuffer([]byte{})
|
|
err := Download(s3session, buf, portainer.S3Location{BucketName: "missing", Filename: key})
|
|
assert.Error(t, err, "should fail downloading from a missing bucket")
|
|
}
|
|
|
|
func Test_download_shouldFail_whenFileIsMissing(t *testing.T) {
|
|
buf := aws.NewWriteAtBuffer([]byte{})
|
|
err := Download(s3session, buf, portainer.S3Location{BucketName: existingBucket, Filename: "missing-file"})
|
|
assert.Error(t, err, "should fail downloading because file is missing")
|
|
}
|
|
|
|
func Test_download_shouldSucceed_whenFileExists(t *testing.T) {
|
|
Upload(s3session, strings.NewReader("test"), existingBucket, key)
|
|
|
|
buf := aws.NewWriteAtBuffer([]byte{})
|
|
err := Download(s3session, buf, portainer.S3Location{BucketName: existingBucket, Filename: key})
|
|
assert.Nil(t, err, "should succeed when file exists")
|
|
}
|
|
|
|
func startMinio() (*session.Session, func()) {
|
|
up := exec.Command("docker-compose", "-f", "docker-compose.test.yml", "up", "-d")
|
|
up.Stderr = os.Stderr
|
|
if err := up.Run(); err != nil {
|
|
log.Fatal(errors.Wrap(err, "failed to run docker-compose up"))
|
|
}
|
|
|
|
minioHost := "http://localhost:9090"
|
|
|
|
// wait for minio to get up and running
|
|
client := http.Client{
|
|
Timeout: 50 * time.Millisecond,
|
|
}
|
|
for i := 0; i < 10; i++ {
|
|
resp, _ := client.Get(fmt.Sprintf("%s/minio/health/live", minioHost))
|
|
if resp != nil && resp.StatusCode == http.StatusOK {
|
|
log.Println("[DEBUG] Minio is up and running")
|
|
break
|
|
}
|
|
<-time.After(500 * time.Millisecond)
|
|
}
|
|
|
|
// create session
|
|
sess, err := session.NewSessionWithOptions(session.Options{
|
|
Config: aws.Config{
|
|
Credentials: credentials.NewStaticCredentials("minioadmin", "minioadmin", ""),
|
|
Endpoint: aws.String(minioHost),
|
|
Region: aws.String("us-east-1"),
|
|
DisableSSL: aws.Bool(true),
|
|
S3ForcePathStyle: aws.Bool(true),
|
|
}})
|
|
if err != nil {
|
|
log.Fatal(errors.Wrap(err, "failed to create minio session"))
|
|
}
|
|
|
|
return sess, func() {
|
|
down := exec.Command("docker-compose", "-f", "docker-compose.test.yml", "rm", "-sfv")
|
|
if err := down.Run(); err != nil {
|
|
log.Fatal(errors.Wrap(err, "failed to run docker-compose rm"))
|
|
}
|
|
}
|
|
}
|