Skip to content

Commit

Permalink
refactor: backend validations
Browse files Browse the repository at this point in the history
Signed-off-by: Bird <aflybird0@gmail.com>
  • Loading branch information
aFlyBird0 committed Aug 19, 2022
1 parent 0e9f896 commit ce4ce17
Show file tree
Hide file tree
Showing 15 changed files with 190 additions and 139 deletions.
33 changes: 11 additions & 22 deletions internal/pkg/backend/backend.go
Original file line number Diff line number Diff line change
@@ -1,21 +1,13 @@
package backend

import (
"fmt"
"strings"

"github.com/devstream-io/devstream/internal/pkg/backend/k8s"
"github.com/devstream-io/devstream/internal/pkg/backend/local"
"github.com/devstream-io/devstream/internal/pkg/backend/s3"
"github.com/devstream-io/devstream/internal/pkg/backend/types"
"github.com/devstream-io/devstream/internal/pkg/configmanager"
"github.com/devstream-io/devstream/pkg/util/log"
)

type Type string

const (
Local Type = "local"
S3 Type = "s3"
K8s Type = "k8s"
)

// Backend is used to persist data, it can be local file/etcd/s3/k8s...
Expand All @@ -28,24 +20,21 @@ type Backend interface {

// GetBackend will return a Backend by the given name.
func GetBackend(state configmanager.State) (Backend, error) {
typeName := Type(state.Backend)
switch typeName {
case Local:
log.Infof("Using local backend. State file: %s.", state.Options.StateFile)
return local.NewLocal(state.Options.StateFile), nil
case S3:
log.Infof("Using s3 backend. Bucket: %s, region: %s, key: %s.", state.Options.Bucket, state.Options.Region, state.Options.Key)
typeName := types.Type(state.Backend)
switch {
case types.Local == typeName:
return local.NewLocal(state.Options.StateFile)
case types.S3 == typeName:
return s3.NewS3Backend(
state.Options.Bucket,
state.Options.Region,
state.Options.Key,
), nil
case K8s:
log.Infof("Using configmap backend. Namespace: %s, ConfigMap name: %s.", state.Options.Namespace, state.Options.ConfigMap)
state.Options.Key)
case strings.ToLower(state.Backend) == types.K8s.String() ||
strings.ToLower(state.Backend) == types.K8sAlis.String():
return k8s.NewBackend(
state.Options.Namespace,
state.Options.ConfigMap)
default:
return nil, fmt.Errorf("the backend type < %s > is illegal", typeName)
return nil, types.NewInvalidBackendErr(state.Backend)
}
}
20 changes: 19 additions & 1 deletion internal/pkg/backend/backend_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package backend_test

import (
"os"

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

"github.com/devstream-io/devstream/internal/pkg/backend"
"github.com/devstream-io/devstream/internal/pkg/backend/local"
"github.com/devstream-io/devstream/internal/pkg/backend/types"
"github.com/devstream-io/devstream/internal/pkg/configmanager"
)

Expand All @@ -15,6 +19,11 @@ var _ = Describe("GetBackend", func() {
_, err := backend.GetBackend(state)
Expect(err).Error().ShouldNot(HaveOccurred())
})

AfterEach(func() {
err := os.RemoveAll(local.DefaultStateFile)
Expect(err).NotTo(HaveOccurred())
})
})

// TODO: add mock s3 test
Expand All @@ -23,7 +32,16 @@ var _ = Describe("GetBackend", func() {
state := configmanager.State{Backend: "not_exist_plug"}
_, err := backend.GetBackend(state)
Expect(err).Error().Should(HaveOccurred())
Expect(err.Error()).Should(Equal("the backend type < not_exist_plug > is illegal"))
Expect(types.IsInvalidBackendErr(err)).To(BeTrue())
})
})

When("s3 config is empty", func() {
It("should return err of backendOptionErr", func() {
state := configmanager.State{Backend: "s3"}
_, err := backend.GetBackend(state)
Expect(err).Error().Should(HaveOccurred())
Expect(types.IsBackendOptionErr(err)).To(BeTrue())
})
})
})
16 changes: 15 additions & 1 deletion internal/pkg/backend/k8s/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@ import (
"sync"

"github.com/devstream-io/devstream/pkg/util/k8s"
"github.com/devstream-io/devstream/pkg/util/log"
)

const (
stateKey = "state"
defaultNamespace = "devstream"
defaultConfigMapName = "devstream-state"
stateKey = "state"
)

type Backend struct {
Expand All @@ -21,6 +24,17 @@ type Backend struct {

// NewBackend returns a backend which uses ConfigMap to store data
func NewBackend(namespace, configMapName string) (*Backend, error) {
// default value
if namespace == "" {
namespace = defaultNamespace
}
if configMapName == "" {
configMapName = defaultConfigMapName
}

log.Infof("Using configmap backend. Namespace: %s, ConfigMap name: %s.", namespace, configMapName)

// create client and return
c, err := k8s.NewClient()
if err != nil {
return nil, err
Expand Down
7 changes: 5 additions & 2 deletions internal/pkg/backend/local/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,15 @@ type Local struct {
}

// NewLocal will use DefaultStateFile as statemanager file if filename is not given.
func NewLocal(filename string) *Local {
func NewLocal(filename string) (*Local, error) {
var lFile = filename
if filename == "" {
log.Debugf("The stateFile has not been set, default value %s will be used.", DefaultStateFile)
lFile = DefaultStateFile
}

log.Infof("Using local backend. State file: %s.", filename)

if _, err := os.Stat(lFile); errors.Is(err, os.ErrNotExist) {
file, err := os.Create(lFile)
if err != nil {
Expand All @@ -35,7 +38,7 @@ func NewLocal(filename string) *Local {

return &Local{
filename: lFile,
}
}, nil
}

// Read is used to retrieve the data from local file.
Expand Down
9 changes: 6 additions & 3 deletions internal/pkg/backend/local/local_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ var _ = Describe("NewLocal func", func() {

When("input filename", func() {
It("should create state file", func() {
local.NewLocal(tFileLoc)
_, err := os.Stat(tFileLoc)
_, err := local.NewLocal(tFileLoc)
Expect(err).Should(Succeed())
_, err = os.Stat(tFileLoc)
Expect(err).Error().ShouldNot(HaveOccurred())
})
})
Expand All @@ -32,13 +33,15 @@ var _ = Describe("Local struct", func() {
var (
tFile, tFileLoc, tempDir string
tLocal *local.Local
err error
)

BeforeEach(func() {
tempDir = GinkgoT().TempDir()
tFile = "test_state_file"
tFileLoc = filepath.Join(tempDir, tFile)
tLocal = local.NewLocal(tFileLoc)
tLocal, err = local.NewLocal(tFileLoc)
Expect(err).ShouldNot(HaveOccurred())
})

Describe("Read method", func() {
Expand Down
10 changes: 8 additions & 2 deletions internal/pkg/backend/s3/s3.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,13 @@ type S3Backend struct {
file *s3.S3File
}

func NewS3Backend(bucket, region, key string) *S3Backend {
func NewS3Backend(bucket, region, key string) (*S3Backend, error) {
if err := validate(bucket, region, key); err != nil {
return nil, err
}

log.Infof("Using s3 backend. Bucket: %s, region: %s, key: %s.", bucket, region, key)

ctx := context.Background()
client, err := s3.NewClient(ctx, region)
if err != nil {
Expand All @@ -25,7 +31,7 @@ func NewS3Backend(bucket, region, key string) *S3Backend {

return &S3Backend{
file: file,
}
}, nil
}

func (b *S3Backend) Read() ([]byte, error) {
Expand Down
13 changes: 13 additions & 0 deletions internal/pkg/backend/s3/s3_suite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package s3_test

import (
"testing"

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

func TestS3(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "S3 Suite")
}
30 changes: 30 additions & 0 deletions internal/pkg/backend/s3/validate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package s3

import (
"fmt"

"github.com/devstream-io/devstream/internal/pkg/backend/types"
"github.com/devstream-io/devstream/pkg/util/log"
)

func validate(bucket, region, key string) error {
var errs []error
if bucket == "" {
errs = append(errs, fmt.Errorf("state s3 Bucket is empty"))
}
if region == "" {
errs = append(errs, fmt.Errorf("state s3 Region is empty"))
}
if key == "" {
errs = append(errs, fmt.Errorf("state s3 Key is empty"))
}

if len(errs) > 0 {
for _, err := range errs {
log.Error(err)
}
return types.NewBackendOptionErr(types.S3)
}

return nil
}
25 changes: 25 additions & 0 deletions internal/pkg/backend/s3/validate_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package s3

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

var _ = Describe("Validate", func() {
It("should return error s3 option not config", func() {
err := validate("", "", "")
Expect(err).Error().Should(HaveOccurred())
Expect(err.Error()).Should(
ContainSubstring("invaid s3 sate config"),
)
})

It("should return true if config s3 valid", func() {
bucket := "test_bucket"
region := "test_region"
key := "test_key"

err := validate(bucket, region, key)
Expect(err).Error().ShouldNot(HaveOccurred())
})
})
38 changes: 38 additions & 0 deletions internal/pkg/backend/types/error.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package types

import (
"errors"
"fmt"
)

type backendOptionErr struct {
backendType Type
}

func NewBackendOptionErr(typ Type) error {
return backendOptionErr{backendType: typ}
}

func (err backendOptionErr) Error() string {
return fmt.Sprintf("invaid %s sate config", err.backendType)
}

func IsBackendOptionErr(err error) bool {
return errors.As(err, &backendOptionErr{})
}

type invalidBackendErr struct {
backendType string
}

func NewInvalidBackendErr(typ string) error {
return invalidBackendErr{backendType: typ}
}

func (err invalidBackendErr) Error() string {
return fmt.Sprintf("the backend type < %s > is illegal", err.backendType)
}

func IsInvalidBackendErr(err error) bool {
return errors.As(err, &invalidBackendErr{})
}
14 changes: 14 additions & 0 deletions internal/pkg/backend/types/vars.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package types

type Type string

func (t Type) String() string {
return string(t)
}

const (
Local Type = "local"
S3 Type = "s3"
K8s Type = "k8s"
K8sAlis Type = "kubernetes"
)
2 changes: 1 addition & 1 deletion internal/pkg/configmanager/configmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ func (m *Manager) renderConfigs(coreConfigBytes, variablesConfigBytes, toolsConf
log.Errorf("Please verify the format of your core config. Error: %s.", err)
return nil, err
}
if err := coreConfig.ValidateAndDefault(); err != nil {
if err := coreConfig.Validate(); err != nil {
return nil, err
}
state := coreConfig.State
Expand Down
Loading

0 comments on commit ce4ce17

Please sign in to comment.