Skip to content

Commit

Permalink
feat: realize release storage of local, oss and s3
Browse files Browse the repository at this point in the history
  • Loading branch information
healthjyk committed May 11, 2024
1 parent f9c000c commit 0308028
Show file tree
Hide file tree
Showing 14 changed files with 1,680 additions and 9 deletions.
18 changes: 9 additions & 9 deletions pkg/engine/release/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,20 @@ import (
v1 "kusionstack.io/kusion/pkg/apis/api.kusion.io/v1"
)

// Storage is used to provide storage service for multiple releases.
// Storage is used to provide storage service for multiple Releases of a specified Project
// and Workspace.
type Storage interface {
// Get returns a specified Release which is determined by the group of Project, Workspace
// and Revision.
Get(project, workspace string, revision uint64) (*v1.Release, error)
// Get returns a specified Release by Revision.
Get(revision uint64) (*v1.Release, error)

// GetRevisions returns the Revisions of a specified Project and Workspace.
GetRevisions(project, workspace string) ([]uint64, error)
// GetRevisions returns all the Revisions.
GetRevisions() []uint64

// GetStackBoundRevisions returns the Revisions of a specified Project, Stack and Workspace.
GetStackBoundRevisions(project, stack, workspace string) ([]uint64, error)
// GetStackBoundRevisions returns the Revisions of a specified Stack.
GetStackBoundRevisions(stack string) []uint64

// GetLatestRevision returns the latest State which corresponds to the current infra Resources.
GetLatestRevision(project, workspace string) (uint64, error)
GetLatestRevision() uint64

// Create creates a new Release in the Storage.
Create(release *v1.Release) error
Expand Down
126 changes: 126 additions & 0 deletions pkg/engine/release/storages/local.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package storages

import (
"fmt"
"os"
"path/filepath"

"gopkg.in/yaml.v3"

v1 "kusionstack.io/kusion/pkg/apis/api.kusion.io/v1"
)

// LocalStorage is an implementation of release.Storage which uses local filesystem as storage.
type LocalStorage struct {
// The directory path to store the release files.
path string

meta *releasesMetaData
}

// NewLocalStorage news local release storage, and derives metadata.
func NewLocalStorage(path string) (*LocalStorage, error) {
s := &LocalStorage{path: path}

// create the releases directory
if err := os.MkdirAll(s.path, os.ModePerm); err != nil {
return nil, fmt.Errorf("create releases directory failed, %w", err)
}
// read releases metadata
if err := s.readMeta(); err != nil {
return nil, err
}

return s, nil
}

func (s *LocalStorage) Get(revision uint64) (*v1.Release, error) {
if !checkRevisionExistence(s.meta, revision) {
return nil, ErrReleaseNotExist
}

content, err := os.ReadFile(filepath.Join(s.path, fmt.Sprintf("%d%s", revision, yamlSuffix)))
if err != nil {
return nil, fmt.Errorf("read release file failed: %w", err)
}

r := &v1.Release{}
if err = yaml.Unmarshal(content, r); err != nil {
return nil, fmt.Errorf("yaml unmarshal release failed: %w", err)
}
return r, nil
}

func (s *LocalStorage) GetRevisions() []uint64 {
return getRevisions(s.meta)
}

func (s *LocalStorage) GetStackBoundRevisions(stack string) []uint64 {
return getStackBoundRevisions(s.meta, stack)
}

func (s *LocalStorage) GetLatestRevision() uint64 {
return s.meta.LatestRevision
}

func (s *LocalStorage) Create(r *v1.Release) error {
if checkRevisionExistence(s.meta, r.Revision) {
return ErrReleaseAlreadyExist
}

if err := s.writeRelease(r); err != nil {
return err
}

addLatestReleaseMetaData(s.meta, r.Revision, r.Stack, r.Phase)
return s.writeMeta()
}

func (s *LocalStorage) Update(r *v1.Release) error {
if !checkRevisionExistence(s.meta, r.Revision) {
return ErrReleaseNotExist
}

return s.writeRelease(r)
}

func (s *LocalStorage) readMeta() error {
content, err := os.ReadFile(filepath.Join(s.path, metadataFile))
if os.IsNotExist(err) {
s.meta = &releasesMetaData{}
return nil
} else if err != nil {
return fmt.Errorf("read releases metadata file failed: %w", err)
}

meta := &releasesMetaData{}
if err = yaml.Unmarshal(content, meta); err != nil {
return fmt.Errorf("yaml unmarshal releases metadata failed: %w", err)
}
s.meta = meta
return nil
}

func (s *LocalStorage) writeMeta() error {
content, err := yaml.Marshal(s.meta)
if err != nil {
return fmt.Errorf("yaml marshal releases metadata failed: %w", err)
}

if err = os.WriteFile(filepath.Join(s.path, metadataFile), content, os.ModePerm); err != nil {
return fmt.Errorf("write releases metadata file failed: %w", err)
}
return nil
}

func (s *LocalStorage) writeRelease(r *v1.Release) error {
content, err := yaml.Marshal(r)
if err != nil {
return fmt.Errorf("yaml marshal release failed: %w", err)
}

if err = os.WriteFile(filepath.Join(s.path, fmt.Sprintf("%d%s", r.Revision, yamlSuffix)), content, os.ModePerm); err != nil {
return fmt.Errorf("write release file failed: %w", err)
}
return nil
}
Loading

0 comments on commit 0308028

Please sign in to comment.