Skip to content

Commit 86eb626

Browse files
committed
refactor: backend validations
Signed-off-by: Bird <aflybird0@gmail.com>
1 parent 0e9f896 commit 86eb626

15 files changed

Lines changed: 183 additions & 135 deletions

File tree

internal/pkg/backend/backend.go

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,16 @@
11
package backend
22

33
import (
4-
"fmt"
4+
"strings"
55

66
"github.com/devstream-io/devstream/internal/pkg/backend/k8s"
77
"github.com/devstream-io/devstream/internal/pkg/backend/local"
88
"github.com/devstream-io/devstream/internal/pkg/backend/s3"
9+
"github.com/devstream-io/devstream/internal/pkg/backend/types"
910
"github.com/devstream-io/devstream/internal/pkg/configmanager"
1011
"github.com/devstream-io/devstream/pkg/util/log"
1112
)
1213

13-
type Type string
14-
15-
const (
16-
Local Type = "local"
17-
S3 Type = "s3"
18-
K8s Type = "k8s"
19-
)
20-
2114
// Backend is used to persist data, it can be local file/etcd/s3/k8s...
2215
type Backend interface {
2316
// Read is used to read data from persistent storage.
@@ -28,24 +21,24 @@ type Backend interface {
2821

2922
// GetBackend will return a Backend by the given name.
3023
func GetBackend(state configmanager.State) (Backend, error) {
31-
typeName := Type(state.Backend)
32-
switch typeName {
33-
case Local:
24+
typeName := types.Type(state.Backend)
25+
switch {
26+
case types.Local == typeName:
3427
log.Infof("Using local backend. State file: %s.", state.Options.StateFile)
35-
return local.NewLocal(state.Options.StateFile), nil
36-
case S3:
28+
return local.NewLocal(state.Options.StateFile)
29+
case types.S3 == typeName:
3730
log.Infof("Using s3 backend. Bucket: %s, region: %s, key: %s.", state.Options.Bucket, state.Options.Region, state.Options.Key)
3831
return s3.NewS3Backend(
3932
state.Options.Bucket,
4033
state.Options.Region,
41-
state.Options.Key,
42-
), nil
43-
case K8s:
34+
state.Options.Key)
35+
case strings.ToLower(state.Backend) == types.K8s.String() ||
36+
strings.ToLower(state.Backend) == types.K8sAlis.String():
4437
log.Infof("Using configmap backend. Namespace: %s, ConfigMap name: %s.", state.Options.Namespace, state.Options.ConfigMap)
4538
return k8s.NewBackend(
4639
state.Options.Namespace,
4740
state.Options.ConfigMap)
4841
default:
49-
return nil, fmt.Errorf("the backend type < %s > is illegal", typeName)
42+
return nil, types.NewInvalidBackendErr(state.Backend)
5043
}
5144
}

internal/pkg/backend/backend_test.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
package backend_test
22

33
import (
4+
"os"
5+
46
. "github.com/onsi/ginkgo/v2"
57
. "github.com/onsi/gomega"
68

79
"github.com/devstream-io/devstream/internal/pkg/backend"
10+
"github.com/devstream-io/devstream/internal/pkg/backend/local"
11+
"github.com/devstream-io/devstream/internal/pkg/backend/types"
812
"github.com/devstream-io/devstream/internal/pkg/configmanager"
913
)
1014

@@ -15,6 +19,11 @@ var _ = Describe("GetBackend", func() {
1519
_, err := backend.GetBackend(state)
1620
Expect(err).Error().ShouldNot(HaveOccurred())
1721
})
22+
23+
AfterEach(func() {
24+
err := os.RemoveAll(local.DefaultStateFile)
25+
Expect(err).NotTo(HaveOccurred())
26+
})
1827
})
1928

2029
// TODO: add mock s3 test
@@ -23,7 +32,16 @@ var _ = Describe("GetBackend", func() {
2332
state := configmanager.State{Backend: "not_exist_plug"}
2433
_, err := backend.GetBackend(state)
2534
Expect(err).Error().Should(HaveOccurred())
26-
Expect(err.Error()).Should(Equal("the backend type < not_exist_plug > is illegal"))
35+
Expect(types.IsInvalidBackendErr(err)).To(BeTrue())
36+
})
37+
})
38+
39+
When("s3 config is empty", func() {
40+
It("should return err of backendOptionErr", func() {
41+
state := configmanager.State{Backend: "s3"}
42+
_, err := backend.GetBackend(state)
43+
Expect(err).Error().Should(HaveOccurred())
44+
Expect(types.IsBackendOptionErr(err)).To(BeTrue())
2745
})
2846
})
2947
})

internal/pkg/backend/k8s/backend.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ import (
77
)
88

99
const (
10-
stateKey = "state"
10+
defaultNamespace = "devstream"
11+
defaultConfigMapName = "devstream-state"
12+
stateKey = "state"
1113
)
1214

1315
type Backend struct {
@@ -21,6 +23,15 @@ type Backend struct {
2123

2224
// NewBackend returns a backend which uses ConfigMap to store data
2325
func NewBackend(namespace, configMapName string) (*Backend, error) {
26+
// default value
27+
if namespace == "" {
28+
namespace = defaultNamespace
29+
}
30+
if configMapName == "" {
31+
configMapName = defaultConfigMapName
32+
}
33+
34+
// create client and return
2435
c, err := k8s.NewClient()
2536
if err != nil {
2637
return nil, err

internal/pkg/backend/local/local.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@ type Local struct {
1818
}
1919

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

@@ -35,7 +36,7 @@ func NewLocal(filename string) *Local {
3536

3637
return &Local{
3738
filename: lFile,
38-
}
39+
}, nil
3940
}
4041

4142
// Read is used to retrieve the data from local file.

internal/pkg/backend/local/local_test.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@ var _ = Describe("NewLocal func", func() {
2121

2222
When("input filename", func() {
2323
It("should create state file", func() {
24-
local.NewLocal(tFileLoc)
25-
_, err := os.Stat(tFileLoc)
24+
_, err := local.NewLocal(tFileLoc)
25+
Expect(err).Should(Succeed())
26+
_, err = os.Stat(tFileLoc)
2627
Expect(err).Error().ShouldNot(HaveOccurred())
2728
})
2829
})
@@ -32,13 +33,15 @@ var _ = Describe("Local struct", func() {
3233
var (
3334
tFile, tFileLoc, tempDir string
3435
tLocal *local.Local
36+
err error
3537
)
3638

3739
BeforeEach(func() {
3840
tempDir = GinkgoT().TempDir()
3941
tFile = "test_state_file"
4042
tFileLoc = filepath.Join(tempDir, tFile)
41-
tLocal = local.NewLocal(tFileLoc)
43+
tLocal, err = local.NewLocal(tFileLoc)
44+
Expect(err).ShouldNot(HaveOccurred())
4245
})
4346

4447
Describe("Read method", func() {

internal/pkg/backend/s3/s3.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@ type S3Backend struct {
1111
file *s3.S3File
1212
}
1313

14-
func NewS3Backend(bucket, region, key string) *S3Backend {
14+
func NewS3Backend(bucket, region, key string) (*S3Backend, error) {
15+
if err := validate(bucket, region, key); err != nil {
16+
return nil, err
17+
}
18+
1519
ctx := context.Background()
1620
client, err := s3.NewClient(ctx, region)
1721
if err != nil {
@@ -25,7 +29,7 @@ func NewS3Backend(bucket, region, key string) *S3Backend {
2529

2630
return &S3Backend{
2731
file: file,
28-
}
32+
}, nil
2933
}
3034

3135
func (b *S3Backend) Read() ([]byte, error) {
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package s3_test
2+
3+
import (
4+
"testing"
5+
6+
. "github.com/onsi/ginkgo/v2"
7+
. "github.com/onsi/gomega"
8+
)
9+
10+
func TestS3(t *testing.T) {
11+
RegisterFailHandler(Fail)
12+
RunSpecs(t, "S3 Suite")
13+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package s3
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/devstream-io/devstream/internal/pkg/backend/types"
7+
"github.com/devstream-io/devstream/pkg/util/log"
8+
)
9+
10+
func validate(bucket, region, key string) error {
11+
var errs []error
12+
if bucket == "" {
13+
errs = append(errs, fmt.Errorf("state s3 Bucket is empty"))
14+
}
15+
if region == "" {
16+
errs = append(errs, fmt.Errorf("state s3 Region is empty"))
17+
}
18+
if key == "" {
19+
errs = append(errs, fmt.Errorf("state s3 Key is empty"))
20+
}
21+
22+
if len(errs) > 0 {
23+
for _, err := range errs {
24+
log.Error(err)
25+
}
26+
return types.NewBackendOptionErr(types.S3)
27+
}
28+
29+
return nil
30+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package s3
2+
3+
import (
4+
. "github.com/onsi/ginkgo/v2"
5+
. "github.com/onsi/gomega"
6+
)
7+
8+
var _ = Describe("Validate", func() {
9+
It("should return error s3 option not config", func() {
10+
err := validate("", "", "")
11+
Expect(err).Error().Should(HaveOccurred())
12+
Expect(err.Error()).Should(
13+
ContainSubstring("invaid s3 sate config"),
14+
)
15+
})
16+
17+
It("should return true if config s3 valid", func() {
18+
bucket := "test_bucket"
19+
region := "test_region"
20+
key := "test_key"
21+
22+
err := validate(bucket, region, key)
23+
Expect(err).Error().ShouldNot(HaveOccurred())
24+
})
25+
})
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package types
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
)
7+
8+
type backendOptionErr struct {
9+
backendType Type
10+
}
11+
12+
func NewBackendOptionErr(typ Type) error {
13+
return backendOptionErr{backendType: typ}
14+
}
15+
16+
func (err backendOptionErr) Error() string {
17+
return fmt.Sprintf("invaid %s sate config", err.backendType)
18+
}
19+
20+
func IsBackendOptionErr(err error) bool {
21+
return errors.As(err, &backendOptionErr{})
22+
}
23+
24+
type invalidBackendErr struct {
25+
backendType string
26+
}
27+
28+
func NewInvalidBackendErr(typ string) error {
29+
return invalidBackendErr{backendType: typ}
30+
}
31+
32+
func (err invalidBackendErr) Error() string {
33+
return fmt.Sprintf("the backend type < %s > is illegal", err.backendType)
34+
}
35+
36+
func IsInvalidBackendErr(err error) bool {
37+
return errors.As(err, &invalidBackendErr{})
38+
}

0 commit comments

Comments
 (0)