Skip to content

Commit

Permalink
feat(core): add keystore
Browse files Browse the repository at this point in the history
  • Loading branch information
gelleson committed Aug 11, 2021
1 parent 90c5dc1 commit f6bc7e0
Show file tree
Hide file tree
Showing 9 changed files with 323 additions and 12 deletions.
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ require (
github.com/go-playground/validator/v10 v10.9.0
github.com/mattn/go-sqlite3 v1.14.7 // indirect
github.com/pkg/errors v0.9.1
github.com/robfig/cron v1.2.0 // indirect
github.com/stretchr/testify v1.7.0
github.com/teambition/rrule-go v1.7.1 // indirect
gorm.io/driver/sqlite v1.1.4
gorm.io/gorm v1.21.11
)
8 changes: 8 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ github.com/jinzhu/now v1.1.2 h1:eVKgfIdy9b6zbWBMgFpfDPoAMifwSZagU9HmEU6zgiI=
github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
Expand All @@ -31,12 +33,17 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ=
github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/teambition/rrule-go v1.7.1 h1:k5uDf0NdE7+Xw3bPxakpMKf0bEYkhrfXdPLbJP5mW5I=
github.com/teambition/rrule-go v1.7.1/go.mod h1:mBJ1Ht5uboJ6jexKdNUJg2NcwP8uUMNvStWXlJD3MvU=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
Expand All @@ -51,6 +58,7 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Expand Down
78 changes: 76 additions & 2 deletions internal/backup/backup.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,81 @@
package backup

import "github.com/gelleson/packup/pkg/database"
import (
"github.com/gelleson/packup/internal/keystore"
"github.com/gelleson/packup/pkg/database"
)

type keystoreService interface {
Get(key string) (keystore.Credential, error)
}

type BackupService struct {
database *database.Database
db *database.Database
keystoreService keystoreService
}

func NewBackupService(db *database.Database, keystoreService keystoreService) *BackupService {
return &BackupService{db: db, keystoreService: keystoreService}
}

func (s BackupService) Create(b Backup) (Backup, error) {

if err := b.Validate(); err != nil {
return Backup{}, err
}

b.SetDefaults()

if b.Keystore != "" {
if _, err := s.keystoreService.Get(b.Keystore); err != nil {
return Backup{}, err
}
}

if tx := s.db.Conn().Create(&b); tx.Error != nil {
return Backup{}, tx.Error
}

return b, nil
}

func (s BackupService) Update(b Backup) (Backup, error) {

if err := b.Validate(); err != nil {
return Backup{}, err
}

b.SetDefaults()

if b.Keystore != "" {
if _, err := s.keystoreService.Get(b.Keystore); err != nil {
return Backup{}, err
}
}

if tx := s.db.Conn().Model(&b).Updates(b); tx.Error != nil {
return Backup{}, tx.Error
}

return b, nil
}

func (s BackupService) Find(skip uint, limit uint) ([]Backup, error) {

backups := make([]Backup, 0)

if tx := s.db.Conn().Limit(int(limit)).Offset(int(skip)).Find(&backups); tx.Error != nil {
return nil, tx.Error
}

return backups, nil
}

func (s BackupService) Delete(id uint) error {

if tx := s.db.Conn().Delete(&Backup{}, "id = ?", int(id)); tx.Error != nil {
return tx.Error
}

return nil
}
55 changes: 47 additions & 8 deletions internal/backup/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package backup

import (
"github.com/gelleson/packup/pkg/compress"
"github.com/gelleson/packup/pkg/validators"
"github.com/pkg/errors"
"gorm.io/gorm"
"time"
Expand All @@ -21,16 +22,17 @@ type ExecutionType string

func (et ExecutionType) Validate() error {

if et != OnceExecution && et != CronExecution {
return errors.New("execution type should be equal to cron or once")
if et != OnceExecution && et != CronExecution && et != RruleExecution {
return errors.New("execution type should be equal to cron or once or rrule")
}

return nil
}

const (
OnceExecution ExecutionType = "once"
CronExecution ExecutionType = "cron"
OnceExecution ExecutionType = "once"
CronExecution ExecutionType = "cron"
RruleExecution ExecutionType = "rrule"
)

type Template string
Expand All @@ -41,15 +43,52 @@ type Backup struct {
gorm.Model
Name string `validate:"required"`
Compress compress.Type `validate:"required"`
ExecutionType ExecutionType `validate:"required"`
ExecutionTime string `validate:"required"`
Tag string `validate:"required"`
Keystore string
Bucket string `validate:"required"`
Keystore string `validate:"required"`
Bucket string `validate:"required"`
BackupNameTemplate Template
Namespace string
Timezone string
LastExecutionTime time.Time

ExecutionType ExecutionType `validate:"required,oneof=once cron rrule"`
Cron string `validate:"required_if=ExecutionType cron"`
Rrule string `validate:"required_if=ExecutionType rrule"`
ExecutionTime time.Time `validate:"required_if=ExecutionType once"`
}

func (b Backup) Validate() error {

if err := validators.Struct(b); err != nil {
return err
}

if err := isValidExecutionValue(b); err != nil {
return err
}

if err := isValidTimezone(b.Timezone); err != nil {
return err
}

return nil
}

func (b *Backup) SetDefaults() {

if b.BackupNameTemplate == "" {
b.BackupNameTemplate = DefaultBackupTemplate
}

if b.Timezone == "" {
zone, _ := time.Now().Local().Zone()

b.Timezone = zone
}

if b.Namespace == "" {
b.Namespace = b.Name
}
}

type Status string
Expand Down
25 changes: 25 additions & 0 deletions internal/backup/model_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package backup

import (
"github.com/gelleson/packup/pkg/compress"
"github.com/gelleson/packup/pkg/validators"
"github.com/stretchr/testify/assert"
"testing"
)

func TestBackup_Validate(t *testing.T) {

tssc := Backup{
Name: "postgres",
Compress: compress.GzipType,
Tag: "alfa",
Keystore: "store",
Bucket: "domain",
ExecutionType: RruleExecution,
Rrule: "hello",
}

if err := validators.Struct(tssc); err != nil {
assert.Fail(t, err.Error())
}
}
52 changes: 52 additions & 0 deletions internal/backup/validator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package backup

import (
"github.com/pkg/errors"
"github.com/robfig/cron"
"github.com/teambition/rrule-go"
"time"
)

func isValidExecutionValue(b Backup) error {

switch b.ExecutionType {
case OnceExecution:

now := time.Now()

if !now.Before(b.ExecutionTime) {
return errors.New("execution_time should be future time")
}

return nil

case RruleExecution:

if _, err := rrule.StrToRRule(b.Rrule); err != nil {
return err
}

return nil

case CronExecution:

parser := cron.NewParser(cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow)

if _, err := parser.Parse(b.Cron); err != nil {
return err
}

return nil

default:

return nil
}
}

func isValidTimezone(timezone string) error {

_, err := time.LoadLocation(timezone)

return err
}
Loading

0 comments on commit f6bc7e0

Please sign in to comment.