Skip to content

Commit

Permalink
feat: merge branch 0.12.0 (#1109)
Browse files Browse the repository at this point in the history
* feat: add configs in the workspace mod definition (#1066)
* feat: add the 'mod list' command (#1070)
  • Loading branch information
SparkYuan authored May 9, 2024
1 parent 6da5948 commit f9c000c
Show file tree
Hide file tree
Showing 20 changed files with 508 additions and 256 deletions.
17 changes: 13 additions & 4 deletions pkg/apis/api.kusion.io/v1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ type Workspace struct {
}

// ModuleConfigs is a set of multiple ModuleConfig, whose key is the module name.
// The module name format is "source@version".
type ModuleConfigs map[string]*ModuleConfig

// GenericConfig is a generic model to describe config which shields the difference among multiple concrete
Expand All @@ -113,9 +112,11 @@ type GenericConfig map[string]any
// in multiple patchers is not allowed. For a project, if not specified in the patcher block's
// "projectSelector" field, the default config will be used.
//
// Take the ModuleConfig of "database" for an example, which is shown as below:
// Take the ModuleConfig of "mysql" for an example, which is shown as below:
//
// config := ModuleConfig {
// config := ModuleConfig {
// "path": "ghcr.io/kusionstack/mysql"
// "version": "0.1.0"
// "default": {
// "type": "aws",
// "version": "5.7",
Expand All @@ -127,9 +128,17 @@ type GenericConfig map[string]any
// },
// }
type ModuleConfig struct {
// Path is the path of the module. It can be a local path or a remote URL
Path string `yaml:"path" json:"path"`
// Version is the version of the module.
Version string `yaml:"version" json:"version"`
// Configs contains all levels of module configs
Configs Configs `yaml:"configs" json:"configs"`
}

type Configs struct {
// Default is default block of the module config.
Default GenericConfig `yaml:"default" json:"default"`

// ModulePatcherConfigs are the patcher blocks of the module config.
ModulePatcherConfigs `yaml:",inline,omitempty" json:",inline,omitempty"`
}
Expand Down
32 changes: 25 additions & 7 deletions pkg/cmd/meta/meta.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,16 +97,23 @@ func (f *MetaFlags) ToOptions() (*MetaOptions, error) {
opts.RefProject = refProject
opts.RefStack = refStack

var storageBackend backend.Backend
if f.Backend != nil {
storageBackend, err = backend.NewBackend(*f.Backend)
opts.StorageBackend = storageBackend
}
storageBackend, err := f.ParseBackend()
if err != nil {
return nil, err
}
opts.StorageBackend = storageBackend

// Get current workspace from backend
workspace, err := f.ParseWorkspace(storageBackend)
if err != nil {
return nil, err
}
opts.RefWorkspace = workspace

return opts, nil
}

func (f *MetaFlags) ParseWorkspace(storageBackend backend.Backend) (*v1.Workspace, error) {
if f.Workspace != nil && storageBackend != nil {
workspaceStorage, err := storageBackend.WorkspaceStorage()
if err != nil {
Expand All @@ -116,8 +123,19 @@ func (f *MetaFlags) ToOptions() (*MetaOptions, error) {
if err != nil {
return nil, err
}
opts.RefWorkspace = refWorkspace
return refWorkspace, nil
}
return nil, nil
}

return opts, nil
func (f *MetaFlags) ParseBackend() (backend.Backend, error) {
var storageBackend backend.Backend
var err error
if f.Backend != nil {
storageBackend, err = backend.NewBackend(*f.Backend)
if err != nil {
return nil, err
}
}
return storageBackend, nil
}
8 changes: 4 additions & 4 deletions pkg/cmd/mod/mod_init.go → pkg/cmd/mod/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@ type InitOptions struct {
TemplateURL string
}

var example = i18n.T(`# Create a kusion module template in the current directory
var initExample = i18n.T(`# Create a kusion module template in the current directory
kusion mod init my-module
# Init a kusion module at the specified Path
kusion mod init my-module ./modules
# Init a module from a remote git template repository
kusion mod init my-module --template https://github.com/<user>/<repo>`)
var short = i18n.T("Create a kusion module along with common files and directories in the current directory")
var initShort = i18n.T("Create a kusion module along with common files and directories in the current directory")

const (
defaultTemplateURL = "https://github.com/KusionStack/kusion-module-scaffolding.git"
Expand All @@ -41,8 +41,8 @@ func NewCmdInit() *cobra.Command {

cmd := &cobra.Command{
Use: "init [MODULE NAME] [PATH]",
Short: short,
Example: templates.Examples(example),
Short: initShort,
Example: templates.Examples(initExample),
RunE: func(cmd *cobra.Command, args []string) (err error) {
defer util.RecoverErr(&err)
util.CheckErr(o.Validate(args))
Expand Down
File renamed without changes.
102 changes: 102 additions & 0 deletions pkg/cmd/mod/list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package mod

import (
"fmt"

"github.com/pterm/pterm"
"github.com/spf13/cobra"
"k8s.io/cli-runtime/pkg/genericiooptions"
"k8s.io/kubectl/pkg/util/templates"

v1 "kusionstack.io/kusion/pkg/apis/api.kusion.io/v1"
"kusionstack.io/kusion/pkg/backend"
"kusionstack.io/kusion/pkg/cmd/meta"
"kusionstack.io/kusion/pkg/cmd/util"
"kusionstack.io/kusion/pkg/util/i18n"
)

var listExample = i18n.T(`# List kusion modules in the current workspace
kusion mod list
# List modules in a specified workspace
kusion mod list --workspace=dev
`)
var listShort = i18n.T("List kusion modules in a workspace ")

type Flag struct {
meta.MetaFlags
}

func (f *Flag) toOption(io genericiooptions.IOStreams) (*Options, error) {
storageBackend, err := f.ParseBackend()
if err != nil {
return nil, err
}

// Get current workspace from backend
workspace, err := f.ParseWorkspace(storageBackend)
if err != nil {
return nil, err
}

return &Options{
Workspace: workspace,
StorageBackend: storageBackend,
IO: io,
}, nil
}

type Options struct {
// Workspace referenced the workspace for this CLI invocation.
Workspace *v1.Workspace
// StorageBackend referenced the target storage backend for this CLI invocation.
StorageBackend backend.Backend
IO genericiooptions.IOStreams
}

func (o *Options) Run() error {
tableHeader := []string{"Name", "URL", "Version"}
tableData := pterm.TableData{tableHeader}
workspace := o.Workspace
if workspace == nil {
return fmt.Errorf("cannot find workspace with nil")
}
modules := workspace.Modules
for k, module := range modules {
tableData = append(tableData, []string{k, module.Path, module.Version})
}
_ = pterm.DefaultTable.WithHasHeader().
WithHeaderStyle(&pterm.ThemeDefault.TableHeaderStyle).
WithLeftAlignment(true).
WithSeparator(" ").
WithData(tableData).
WithWriter(o.IO.Out).
Render()
pterm.Println()

return nil
}

func NewCmdList(io genericiooptions.IOStreams) *cobra.Command {
f := &Flag{
MetaFlags: *meta.NewMetaFlags(),
}

cmd := &cobra.Command{
Use: "list [WORKSPACE]",
Short: listShort,
Example: templates.Examples(listExample),
Args: cobra.ExactArgs(0),
RunE: func(cmd *cobra.Command, args []string) (err error) {
defer util.RecoverErr(&err)

o, err := f.toOption(io)
util.CheckErr(err)
util.CheckErr(o.Run())
return
},
}
f.MetaFlags.AddFlags(cmd)

return cmd
}
56 changes: 56 additions & 0 deletions pkg/cmd/mod/list_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package mod

import (
"testing"

"github.com/stretchr/testify/assert"
"k8s.io/cli-runtime/pkg/genericiooptions"

v1 "kusionstack.io/kusion/pkg/apis/api.kusion.io/v1"
"kusionstack.io/kusion/pkg/backend/storages"
"kusionstack.io/kusion/pkg/cmd/meta"
)

func TestFlag_ToOption(t *testing.T) {
f := &Flag{
MetaFlags: *meta.NewMetaFlags(),
}

t.Run("Successful Option Creation", func(t *testing.T) {
_, err := f.toOption(genericiooptions.IOStreams{})
assert.NoError(t, err)
})

t.Run("Failed Option Creation Due to Invalid Backend", func(t *testing.T) {
s := "invalid-backend"
f.MetaFlags.Backend = &s
_, err := f.toOption(genericiooptions.IOStreams{})
assert.Error(t, err)
})
}

func TestOptions_Run(t *testing.T) {
o := &Options{
Workspace: &v1.Workspace{
Modules: map[string]*v1.ModuleConfig{
"module1": {
Path: "path1",
Version: "v1.0.0",
},
},
},
StorageBackend: &storages.LocalStorage{},
IO: genericiooptions.IOStreams{},
}

t.Run("Successful Run", func(t *testing.T) {
err := o.Run()
assert.NoError(t, err)
})

t.Run("Failed Run Due to Nil Workspace", func(t *testing.T) {
o.Workspace = nil
err := o.Run()
assert.Error(t, err)
})
}
5 changes: 3 additions & 2 deletions pkg/cmd/mod/mod.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package mod

import (
"github.com/spf13/cobra"
"k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/cli-runtime/pkg/genericiooptions"
"k8s.io/kubectl/pkg/util/templates"

cmdutil "kusionstack.io/kusion/pkg/cmd/util"
Expand All @@ -15,7 +15,7 @@ var modLong = i18n.T(`
These commands help you manage the lifecycle of Kusion modules.`)

// NewCmdMod returns an initialized Command instance for 'mod' sub command
func NewCmdMod(streams genericclioptions.IOStreams) *cobra.Command {
func NewCmdMod(streams genericiooptions.IOStreams) *cobra.Command {
cmd := &cobra.Command{
Use: "mod",
DisableFlagsInUseLine: true,
Expand All @@ -27,6 +27,7 @@ func NewCmdMod(streams genericclioptions.IOStreams) *cobra.Command {
// add subcommands
cmd.AddCommand(NewCmdInit())
cmd.AddCommand(NewCmdPush(streams))
cmd.AddCommand(NewCmdList(streams))

return cmd
}
File renamed without changes.
34 changes: 18 additions & 16 deletions pkg/cmd/workspace/util/testdata/valid_ws.yaml
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
modules:
database:
default:
instanceType: db.t3.micro
type: aws
version: "5.7"
smallClass:
projectSelector:
- foo
- bar
instanceType: db.t3.small
port:
default:
type: aws
mysql:
path: ghcr.io/kusionstack/mysql
version: 0.1.0
configs:
default:
instanceType: db.t3.micro
type: aws
version: '5.7'
smallClass:
projectSelector:
- foo
- bar
instanceType: db.t3.small
network:
configs:
default:
type: aws
runtimes:
kubernetes:
kubeConfig: /etc/kubeconfig.yaml
terraform:
aws:
source: hashicorp/aws
version: 1.0.4
region: us-east-1
backends:
local: {}
region: us-east-1
3 changes: 3 additions & 0 deletions pkg/modules/generators/app_configurations_generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ func (g *appConfigurationGenerator) callModules(
}

// parse module result
// todo extract to a method
for _, res := range response.Resources {
temp := &v1.Resource{}
err = yaml.Unmarshal(res, temp)
Expand All @@ -324,7 +325,9 @@ func (g *appConfigurationGenerator) callModules(
}
resources = append(resources, *temp)
}

// parse patcher
// todo extract to a method
for _, patcher := range response.Patchers {
temp := &internalv1.Patcher{}
err = yaml.Unmarshal(patcher, temp)
Expand Down
Loading

0 comments on commit f9c000c

Please sign in to comment.