Skip to content

Commit

Permalink
feat: support custom writer and storage for apply and preview
Browse files Browse the repository at this point in the history
  • Loading branch information
elliotxx committed Jun 9, 2022
1 parent d88c533 commit e743ad8
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 26 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ require (
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
github.com/mitchellh/hashstructure v1.0.0
github.com/pkg/errors v0.9.1
github.com/pterm/pterm v0.12.41
github.com/pterm/pterm v0.12.42-0.20220427210824-6bb8c6e6cc77
github.com/pulumi/pulumi/sdk/v3 v3.24.0
github.com/sergi/go-diff v1.2.0
github.com/spf13/cobra v1.1.1
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -769,8 +769,8 @@ github.com/pterm/pterm v0.12.31/go.mod h1:32ZAWZVXD7ZfG0s8qqHXePte42kdz8ECtRyEej
github.com/pterm/pterm v0.12.33/go.mod h1:x+h2uL+n7CP/rel9+bImHD5lF3nM9vJj80k9ybiiTTE=
github.com/pterm/pterm v0.12.36/go.mod h1:NjiL09hFhT/vWjQHSj1athJpx6H8cjpHXNAK5bUw8T8=
github.com/pterm/pterm v0.12.40/go.mod h1:ffwPLwlbXxP+rxT0GsgDTzS3y3rmpAO1NMjUkGTYf8s=
github.com/pterm/pterm v0.12.41 h1:e2BRfFo1H9nL8GY0S3ImbZqfZ/YimOk9XtkhoobKJVs=
github.com/pterm/pterm v0.12.41/go.mod h1:LW/G4J2A42XlTaPTAGRPvbBfF4UXvHWhC6SN7ueU4jU=
github.com/pterm/pterm v0.12.42-0.20220427210824-6bb8c6e6cc77 h1:bfxFB3HuoLruylqH12k4pfx0L6ZmvCSbGRYkBRSdUZI=
github.com/pterm/pterm v0.12.42-0.20220427210824-6bb8c6e6cc77/go.mod h1:LW/G4J2A42XlTaPTAGRPvbBfF4UXvHWhC6SN7ueU4jU=
github.com/pulumi/pulumi/sdk/v3 v3.24.0 h1:jXJQqSd4fJeB/XGGBMb9Rt6CrsT5T3/XMk67fH04v+s=
github.com/pulumi/pulumi/sdk/v3 v3.24.0/go.mod h1:WHOQB00iuHZyXhwrymxpKXhpOahSguJIpRjVokmM11w=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
Expand Down
2 changes: 2 additions & 0 deletions pkg/engine/states/db_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ func init() {
AddToBackends("db", NewDBState)
}

var _ StateStorage = &DBState{}

func NewDBState() StateStorage {
result := &DBState{}
return result
Expand Down
2 changes: 2 additions & 0 deletions pkg/engine/states/filesystem_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ func init() {
AddToBackends("local", NewFileSystemState)
}

var _ StateStorage = &FileSystemState{}

type FileSystemState struct {
// state Path is in the same dir where command line is invoked
Path string
Expand Down
15 changes: 15 additions & 0 deletions pkg/engine/states/oss_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@ import (

"github.com/aliyun/aliyun-oss-go-sdk/oss"
"github.com/google/uuid"
"github.com/zclconf/go-cty/cty"
)

var ErrOSSNoExist = errors.New("oss: key not exist")

var _ StateStorage = &OssState{}

type OssState struct {
bucket *oss.Bucket
}
Expand All @@ -36,6 +39,18 @@ func NewOSSState(endPoint, accessKeyID, accessKeySecret, bucketName string) (*Os
return ossState, nil
}

// ConfigSchema returns a description of the expected configuration
// structure for the receiving backend.
func (s *OssState) ConfigSchema() cty.Type {
return cty.Type{}
}

// Configure uses the provided configuration to set configuration fields
// within the OssState backend.
func (s *OssState) Configure(obj cty.Value) error {
return nil
}

func (s *OssState) Apply(state *State) error {
u, err := uuid.NewUUID()
if err != nil {
Expand Down
15 changes: 15 additions & 0 deletions pkg/engine/states/s3_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,13 @@ import (
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3"
"github.com/google/uuid"
"github.com/zclconf/go-cty/cty"
)

var ErrS3NoExist = errors.New("s3: key not exist")

var _ StateStorage = &S3State{}

type S3State struct {
sess *session.Session
bucketName string
Expand All @@ -38,6 +41,18 @@ func NewS3State(endPoint, accessKeyID, accessKeySecret, bucketName string, regio
return s3State, nil
}

// ConfigSchema returns a description of the expected configuration
// structure for the receiving backend.
func (s *S3State) ConfigSchema() cty.Type {
return cty.Type{}
}

// Configure uses the provided configuration to set configuration fields
// within the S3State backend.
func (s *S3State) Configure(obj cty.Value) error {
return nil
}

func (s *S3State) Apply(state *State) error {
u, err := uuid.NewUUID()
if err != nil {
Expand Down
54 changes: 35 additions & 19 deletions pkg/kusionctl/cmd/apply/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package apply

import (
"fmt"
"io"
"os"
"path/filepath"
"strings"
"sync"
Expand Down Expand Up @@ -72,7 +74,8 @@ func (o *ApplyOptions) Run() error {
pterm.Println()

// Compute changes for preview
changes, err := preview(o, planResources, project, stack)
stateStorage := &states.FileSystemState{Path: filepath.Join(o.WorkDir, states.KusionState)}
changes, err := Preview(o, stateStorage, planResources, project, stack, os.Stdout)
if err != nil {
return err
}
Expand Down Expand Up @@ -114,13 +117,12 @@ func (o *ApplyOptions) Run() error {
}

if !o.OnlyPreview {
// Apply
fmt.Println("Start applying diffs ...")
if err := apply(o, planResources, changes); err != nil {
if err := Apply(o, stateStorage, planResources, changes, os.Stdout); err != nil {
return err
}

// Dry run hint
// If dry run, print the hint
if o.DryRun {
fmt.Printf("\nNOTE: Currently running in the --dry-run mode, the above configuration does not really take effect\n")
}
Expand All @@ -129,8 +131,14 @@ func (o *ApplyOptions) Run() error {
return nil
}

func preview(o *ApplyOptions, planResources *models.Spec,
project *projectstack.Project, stack *projectstack.Stack,
// The preview function will preview for all resources changes
func Preview(
o *ApplyOptions,
storage states.StateStorage,
planResources *models.Spec,
project *projectstack.Project,
stack *projectstack.Stack,
out io.Writer,
) (*operation.Changes, error) {
log.Info("Start compute preview changes ...")

Expand All @@ -142,7 +150,7 @@ func preview(o *ApplyOptions, planResources *models.Spec,
pc := &operation.PreviewOperation{
Operation: operation.Operation{
Runtime: kubernetesRuntime,
StateStorage: &states.FileSystemState{Path: filepath.Join(o.WorkDir, states.KusionState)},
StateStorage: storage,
Order: &operation.ChangeOrder{StepKeys: []string{}, ChangeSteps: map[string]*operation.ChangeStep{}},
},
}
Expand All @@ -165,7 +173,15 @@ func preview(o *ApplyOptions, planResources *models.Spec,
return operation.NewChanges(project, stack, rsp.Order), nil
}

func apply(o *ApplyOptions, planResources *models.Spec, changes *operation.Changes) error {
// The apply function will apply the resources changes,
// and will save the state to specified storage.
func Apply(
o *ApplyOptions,
storage states.StateStorage,
planResources *models.Spec,
changes *operation.Changes,
out io.Writer,
) error {
// Build apply operation
kubernetesRuntime, err := runtime.NewKubernetesRuntime()
if err != nil {
Expand All @@ -175,22 +191,22 @@ func apply(o *ApplyOptions, planResources *models.Spec, changes *operation.Chang
ac := &operation.ApplyOperation{
Operation: operation.Operation{
Runtime: kubernetesRuntime,
StateStorage: &states.FileSystemState{Path: filepath.Join(o.WorkDir, states.KusionState)},
StateStorage: storage,
MsgCh: make(chan operation.Message),
},
}

// line summary
// Line summary
var ls lineSummary

// progress bar, print dag walk detail
progressbar, err := pterm.DefaultProgressbar.WithTotal(len(changes.StepKeys)).Start()
// Progress bar, print dag walk detail
progressbar, err := pterm.DefaultProgressbar.WithTotal(len(changes.StepKeys)).WithWriter(out).Start()
if err != nil {
return err
}
// wait msgCh close
// Wait msgCh close
var wg sync.WaitGroup
// receive msg and print detail
// Receive msg and print detail
go func() {
defer func() {
if p := recover(); p != nil {
Expand Down Expand Up @@ -224,7 +240,7 @@ func apply(o *ApplyOptions, planResources *models.Spec, changes *operation.Chang
strings.ToLower(string(msg.OpResult)),
)
}
pterm.Success.Println(title)
pterm.Success.WithWriter(out).Println(title)
progressbar.UpdateTitle(title)
progressbar.Increment()
ls.Count(changeStep.Action)
Expand All @@ -234,7 +250,7 @@ func apply(o *ApplyOptions, planResources *models.Spec, changes *operation.Chang
pterm.Bold.Sprint(changeStep.ID),
strings.ToLower(string(msg.OpResult)),
)
pterm.Error.Printf("%s, %v\n", title, msg.OpErr)
pterm.Error.WithWriter(out).Printf("%s, %v\n", title, msg.OpErr)
default:
title := fmt.Sprintf("%s %s %s",
changeStep.Action.Ing(),
Expand Down Expand Up @@ -271,11 +287,11 @@ func apply(o *ApplyOptions, planResources *models.Spec, changes *operation.Chang
}
}

// wait for msgCh closed
// Wait for msgCh closed
wg.Wait()
// Print summary
pterm.Println()
pterm.Printf("Apply complete! Resources: %d created, %d updated, %d deleted.\n", ls.created, ls.updated, ls.deleted)
pterm.Fprintln(out)
pterm.Fprintln(out, fmt.Sprintf("Apply complete! Resources: %d created, %d updated, %d deleted.", ls.created, ls.updated, ls.deleted))
return nil
}

Expand Down
13 changes: 9 additions & 4 deletions pkg/kusionctl/cmd/apply/options_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"context"
"errors"
"fmt"
"os"
"path/filepath"
"reflect"
"testing"
"time"
Expand All @@ -21,6 +23,7 @@ import (
"kusionstack.io/kusion/pkg/engine/models"
"kusionstack.io/kusion/pkg/engine/operation"
"kusionstack.io/kusion/pkg/engine/runtime"
"kusionstack.io/kusion/pkg/engine/states"
"kusionstack.io/kusion/pkg/projectstack"
"kusionstack.io/kusion/pkg/status"
)
Expand Down Expand Up @@ -112,13 +115,14 @@ func mockCompileWithSpinner() {
}

func Test_preview(t *testing.T) {
stateStorage := &states.FileSystemState{Path: filepath.Join("", states.KusionState)}
t.Run("preview success", func(t *testing.T) {
defer monkey.UnpatchAll()
mockNewKubernetesRuntime()
mockOperationPreview()

o := NewApplyOptions()
_, err := preview(o, &models.Spec{Resources: []models.Resource{sa1, sa2, sa3}}, project, stack)
_, err := Preview(o, stateStorage, &models.Spec{Resources: []models.Resource{sa1, sa2, sa3}}, project, stack, os.Stdout)
assert.Nil(t, err)
})
}
Expand Down Expand Up @@ -209,6 +213,7 @@ func newSA(name string) models.Resource {
}

func Test_apply(t *testing.T) {
stateStorage := &states.FileSystemState{Path: filepath.Join("", states.KusionState)}
t.Run("dry run", func(t *testing.T) {
defer monkey.UnpatchAll()
mockNewKubernetesRuntime()
Expand All @@ -228,7 +233,7 @@ func Test_apply(t *testing.T) {
changes := operation.NewChanges(project, stack, order)
o := NewApplyOptions()
o.DryRun = true
err := apply(o, planResources, changes)
err := Apply(o, stateStorage, planResources, changes, os.Stdout)
assert.Nil(t, err)
})
t.Run("apply success", func(t *testing.T) {
Expand Down Expand Up @@ -257,7 +262,7 @@ func Test_apply(t *testing.T) {
}
changes := operation.NewChanges(project, stack, order)

err := apply(o, planResources, changes)
err := Apply(o, stateStorage, planResources, changes, os.Stdout)
assert.Nil(t, err)
})
t.Run("apply failed", func(t *testing.T) {
Expand All @@ -280,7 +285,7 @@ func Test_apply(t *testing.T) {
}
changes := operation.NewChanges(project, stack, order)

err := apply(o, planResources, changes)
err := Apply(o, stateStorage, planResources, changes, os.Stdout)
assert.NotNil(t, err)
})
}
Expand Down

0 comments on commit e743ad8

Please sign in to comment.