From 11ce06bb8509d95d2402971391719ebcbffd4a4c Mon Sep 17 00:00:00 2001 From: Lukas Steiner Date: Mon, 10 Oct 2022 14:33:26 +0200 Subject: [PATCH 1/3] add storage backend tests --- .gitignore | 1 + docker-compose.yml | 8 ++++++++ pkg/storage/filesystem/filesystem.go | 2 +- pkg/storage/filesystem/filesystem_test.go | 16 ++++++++++++++++ pkg/storage/s3/s3_test.go | 19 +++++++++++++++++++ 5 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 pkg/storage/filesystem/filesystem_test.go create mode 100644 pkg/storage/s3/s3_test.go diff --git a/.gitignore b/.gitignore index f6c8fac..c9b19e5 100644 --- a/.gitignore +++ b/.gitignore @@ -31,5 +31,6 @@ go.work # End of https://www.toptal.com/developers/gitignore/api/go +.vscode .env terraform-backend diff --git a/docker-compose.yml b/docker-compose.yml index a73e393..7309a5a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -26,6 +26,14 @@ services: POSTGRES_PASSWORD: postgres ports: - "5432:5432" + minio: + image: minio/minio + environment: + MINIO_ROOT_USER: root + MINIO_ROOT_PASSWORD: password + command: server /storage + ports: + - "9000:9000" volumes: states: diff --git a/pkg/storage/filesystem/filesystem.go b/pkg/storage/filesystem/filesystem.go index c0776f0..8200e3c 100644 --- a/pkg/storage/filesystem/filesystem.go +++ b/pkg/storage/filesystem/filesystem.go @@ -30,7 +30,7 @@ func (f *FileSystemStorage) GetName() string { } func (f *FileSystemStorage) SaveState(s *terraform.State) error { - return os.WriteFile(fmt.Sprintf("%s/%s.tfstate", f.directory, s.ID), s.Data, 0600) + return os.WriteFile(f.getFileName(s.ID), s.Data, 0600) } func (f *FileSystemStorage) GetState(id string) (*terraform.State, error) { diff --git a/pkg/storage/filesystem/filesystem_test.go b/pkg/storage/filesystem/filesystem_test.go new file mode 100644 index 0000000..90a5c5c --- /dev/null +++ b/pkg/storage/filesystem/filesystem_test.go @@ -0,0 +1,16 @@ +package filesystem + +import ( + "testing" + + "github.com/nimbolus/terraform-backend/pkg/storage/util" +) + +func TestStorage(t *testing.T) { + s, err := NewFileSystemStorage("./storage") + if err != nil { + t.Error(err) + } + + util.StorageTest(t, s) +} diff --git a/pkg/storage/s3/s3_test.go b/pkg/storage/s3/s3_test.go new file mode 100644 index 0000000..ebb2e4e --- /dev/null +++ b/pkg/storage/s3/s3_test.go @@ -0,0 +1,19 @@ +//go:build integration || s3 +// +build integration s3 + +package s3 + +import ( + "testing" + + "github.com/nimbolus/terraform-backend/pkg/storage/util" +) + +func TestStorage(t *testing.T) { + s, err := NewS3Storage("localhost:9000", "terraform-backend", "root", "password", false) + if err != nil { + t.Error(err) + } + + util.StorageTest(t, s) +} From 1f58241212874255799dadd679ef9910b09c8d70 Mon Sep 17 00:00:00 2001 From: Lukas Steiner Date: Mon, 10 Oct 2022 22:32:47 +0200 Subject: [PATCH 2/3] add delete storage endpoint --- pkg/server/handler.go | 10 +++++++++- pkg/storage/filesystem/filesystem.go | 4 ++++ pkg/storage/postgres/postgres.go | 4 ++++ pkg/storage/s3/s3.go | 4 ++++ pkg/storage/storage.go | 1 + pkg/storage/util/storagetest.go | 5 +++++ 6 files changed, 27 insertions(+), 1 deletion(-) diff --git a/pkg/server/handler.go b/pkg/server/handler.go index dce28b1..4b5a25f 100644 --- a/pkg/server/handler.go +++ b/pkg/server/handler.go @@ -152,5 +152,13 @@ func Post(w http.ResponseWriter, state *terraform.State, body []byte, store stor func Delete(w http.ResponseWriter, state *terraform.State, store storage.Storage) { log.Debugf("delete state with id %s", state.ID) - HTTPResponse(w, http.StatusNotImplemented, "Delete state is not implemented") + + err := store.DeleteState(state.ID) + if err != nil { + log.Warnf("failed to delete state with id %s: %v", state.ID, err) + HTTPResponse(w, http.StatusInternalServerError, err.Error()) + return + } + + HTTPResponse(w, http.StatusOK, "") } diff --git a/pkg/storage/filesystem/filesystem.go b/pkg/storage/filesystem/filesystem.go index 8200e3c..365b96c 100644 --- a/pkg/storage/filesystem/filesystem.go +++ b/pkg/storage/filesystem/filesystem.go @@ -54,6 +54,10 @@ func (f *FileSystemStorage) GetState(id string) (*terraform.State, error) { }, nil } +func (f *FileSystemStorage) DeleteState(id string) error { + return os.Remove(f.getFileName(id)) +} + func (f *FileSystemStorage) getFileName(id string) string { return fmt.Sprintf("%s/%s.tfstate", f.directory, id) } diff --git a/pkg/storage/postgres/postgres.go b/pkg/storage/postgres/postgres.go index 719d394..d2d4bdf 100644 --- a/pkg/storage/postgres/postgres.go +++ b/pkg/storage/postgres/postgres.go @@ -76,3 +76,7 @@ func (p *PostgresStorage) GetState(id string) (*terraform.State, error) { return s, nil } + +func (p *PostgresStorage) DeleteState(id string) error { + return p.db.QueryRow(`DELETE FROM `+p.table+` WHERE state_id = $1`, id).Err() +} diff --git a/pkg/storage/s3/s3.go b/pkg/storage/s3/s3.go index 5b2535c..b7d2522 100644 --- a/pkg/storage/s3/s3.go +++ b/pkg/storage/s3/s3.go @@ -74,6 +74,10 @@ func (s *S3Storage) GetState(id string) (*terraform.State, error) { return state, nil } +func (s *S3Storage) DeleteState(id string) error { + return s.client.RemoveObject(context.Background(), s.bucket, getObjectName(id), minio.RemoveObjectOptions{}) +} + func getObjectName(id string) string { return fmt.Sprintf("%s.tfstate", id) } diff --git a/pkg/storage/storage.go b/pkg/storage/storage.go index 1afabc4..e055173 100644 --- a/pkg/storage/storage.go +++ b/pkg/storage/storage.go @@ -8,4 +8,5 @@ type Storage interface { GetName() string SaveState(s *terraform.State) error GetState(id string) (*terraform.State, error) + DeleteState(id string) error } diff --git a/pkg/storage/util/storagetest.go b/pkg/storage/util/storagetest.go index af5e043..f5f11e4 100644 --- a/pkg/storage/util/storagetest.go +++ b/pkg/storage/util/storagetest.go @@ -48,4 +48,9 @@ func StorageTest(t *testing.T, s storage.Storage) { if string(state.Data) != string(savedState.Data) { t.Errorf("state data does not match") } + + err = s.DeleteState(state.ID) + if err != nil { + t.Error(err) + } } From 23a7bbe6715d1e115727230dab9f4e80f8ed3ca6 Mon Sep 17 00:00:00 2001 From: Lukas Steiner Date: Tue, 11 Oct 2022 15:42:45 +0200 Subject: [PATCH 3/3] fix create s3 bucket if it does not exist --- pkg/storage/s3/s3.go | 8 +++++--- pkg/storage/s3/s3_test.go | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/pkg/storage/s3/s3.go b/pkg/storage/s3/s3.go index b7d2522..38766e6 100644 --- a/pkg/storage/s3/s3.go +++ b/pkg/storage/s3/s3.go @@ -24,13 +24,15 @@ func NewS3Storage(endpoint, bucket, accessKey, secretKey string, useSSL bool) (* Secure: useSSL, }) if err != nil { - return nil, fmt.Errorf("failed to initialize minio client: %v", err) + return nil, fmt.Errorf("failed to initialize minio client: %w", err) } if exists, err := client.BucketExists(context.Background(), bucket); err != nil { - return nil, fmt.Errorf("failed to check for bucket: %v", err) + return nil, fmt.Errorf("failed to check for bucket: %w", err) } else if !exists { - return nil, fmt.Errorf("bucket does not exist") + if err = client.MakeBucket(context.Background(), bucket, minio.MakeBucketOptions{}); err != nil { + return nil, fmt.Errorf("bucket does not exist and creation failed: %w", err) + } } return &S3Storage{ diff --git a/pkg/storage/s3/s3_test.go b/pkg/storage/s3/s3_test.go index ebb2e4e..75240dc 100644 --- a/pkg/storage/s3/s3_test.go +++ b/pkg/storage/s3/s3_test.go @@ -10,9 +10,9 @@ import ( ) func TestStorage(t *testing.T) { - s, err := NewS3Storage("localhost:9000", "terraform-backend", "root", "password", false) + s, err := NewS3Storage("localhost:9000", "tf-backend-integration-test", "root", "password", false) if err != nil { - t.Error(err) + t.Fatal(err) } util.StorageTest(t, s)