Skip to content

Commit

Permalink
feat: validate module path and version in the workspace (#1131)
Browse files Browse the repository at this point in the history
  • Loading branch information
SparkYuan committed May 22, 2024
1 parent bd90c5a commit 519b8c3
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 32 deletions.
11 changes: 4 additions & 7 deletions pkg/cmd/workspace/util/testdata/valid_ws.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,11 @@ modules:
- bar
instanceType: db.t3.small
network:
path: ghcr.io/kusionstack/mysql
version: 0.1.0
configs:
default:
type: aws
runtimes:
context:
kubernetes:
kubeConfig: /etc/kubeconfig.yaml
terraform:
aws:
source: hashicorp/aws
version: 1.0.4
region: us-east-1
kubeConfig: /etc/kubeconfig.yaml
4 changes: 2 additions & 2 deletions pkg/engine/api/generate/generator/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import (
v1 "kusionstack.io/kusion/pkg/apis/api.kusion.io/v1"
"kusionstack.io/kusion/pkg/engine/api/builders"
"kusionstack.io/kusion/pkg/engine/api/generate/run"
"kusionstack.io/kusion/pkg/modules/generators"
"kusionstack.io/kusion/pkg/modules"
"kusionstack.io/kusion/pkg/util/io"
"kusionstack.io/kusion/pkg/util/kfile"
)
Expand Down Expand Up @@ -101,7 +101,7 @@ func CopyDependentModules(workDir string) error {
for _, dep := range modFile.Deps {
if dep.Source.Oci != nil {
// ignore workload modules
if generators.IgnoreModules[dep.Name] {
if modules.IgnoreModules[dep.Name] {
continue
}

Expand Down
29 changes: 17 additions & 12 deletions pkg/modules/generators/app_configurations_generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,6 @@ type appConfigurationGenerator struct {
dependencies *pkg.Dependencies
}

// IgnoreModules todo@dayuan delete this condition after workload is changed into a module
var IgnoreModules = map[string]bool{
"service": true,
"job": true,
}

func NewAppConfigurationGenerator(
project string,
stack string,
Expand Down Expand Up @@ -357,7 +351,7 @@ func (g *appConfigurationGenerator) callModules(projectModuleConfigs map[string]
// generate customized module resources
for t, config := range indexModuleConfig {
// ignore workload modules
if IgnoreModules[t] {
if modules.IgnoreModules[t] {
continue
}

Expand Down Expand Up @@ -419,7 +413,10 @@ func (g *appConfigurationGenerator) buildModuleConfigIndex(platformModuleConfigs
return nil, err
}
log.Info("build module index of accessory:%s module key: %s", accName, key)
moduleName := getModuleName(accessory)
moduleName, err := getModuleName(accessory)
if err != nil {
return nil, err
}
indexModuleConfig[key] = moduleConfig{
devConfig: accessory,
platformConfig: platformModuleConfigs[moduleName],
Expand All @@ -432,7 +429,11 @@ func (g *appConfigurationGenerator) buildModuleConfigIndex(platformModuleConfigs
// parseModuleKey returns the module key of the accessory in format of "org/module@version"
// example: "kusionstack/mysql@v0.1.0"
func parseModuleKey(accessory v1.Accessory, dependencies *pkg.Dependencies) (string, error) {
moduleName := getModuleName(accessory)
moduleName, err := getModuleName(accessory)
if err != nil {
return "", err
}

// find module namespace and version
d, ok := dependencies.Deps[moduleName]
if !ok {
Expand All @@ -452,9 +453,13 @@ func parseModuleKey(accessory v1.Accessory, dependencies *pkg.Dependencies) (str
return key, nil
}

func getModuleName(accessory v1.Accessory) string {
split := strings.Split(accessory["_type"].(string), ".")
return split[0]
func getModuleName(accessory v1.Accessory) (string, error) {
t, ok := accessory["_type"]
if !ok {
return "", errors.New("can not find '_type' in module config")
}
split := strings.Split(t.(string), ".")
return split[0], nil
}

func (g *appConfigurationGenerator) initModuleRequest(config moduleConfig) (*proto.GeneratorRequest, error) {
Expand Down
21 changes: 16 additions & 5 deletions pkg/modules/generators/app_configurations_generator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,9 @@ func TestAppConfigurationGenerator_Generate_CustomNamespace(t *testing.T) {
ws := buildMockWorkspace("fakeNs")
dep := &pkg.Dependencies{
Deps: map[string]pkg.Dependency{
"fake": {
Name: "fakeName",
"port": {
Name: "port",
Version: "1.0.0",
},
},
}
Expand Down Expand Up @@ -176,6 +177,12 @@ func buildMockApp() (string, *v1.AppConfiguration) {
},
},
},
Accessories: map[string]v1.Accessory{
"port": map[string]interface{}{
"port": "2333",
"_type": "port.Port",
},
},
}
}

Expand Down Expand Up @@ -203,13 +210,17 @@ func buildMockWorkspace(namespace string) *v1.Workspace {
},
},
"port": &v1.ModuleConfig{
Path: "kusionstack.io/port",
Version: "v1.0.0",
Configs: v1.Configs{
Default: v1.GenericConfig{
"type": "aws",
},
},
},
"namespace": &v1.ModuleConfig{
Path: "kusionstack.io/namespace",
Version: "v1.0.0",
Configs: v1.Configs{
Default: v1.GenericConfig{
"name": namespace,
Expand Down Expand Up @@ -344,8 +355,8 @@ func TestAppConfigurationGenerator_CallModules(t *testing.T) {
// Mock dependencies
dependencies := &pkg.Dependencies{
Deps: map[string]pkg.Dependency{
"module1": {
Version: "v1.0.0",
"port": {
Version: "1.0.0",
Source: pkg.Source{
Oci: &pkg.Oci{
Repo: "kusionstack/module1",
Expand All @@ -357,7 +368,7 @@ func TestAppConfigurationGenerator_CallModules(t *testing.T) {

// Mock project module configs
projectModuleConfigs := map[string]v1.GenericConfig{
"module1": {
"port": {
"config1": "value1",
},
}
Expand Down
6 changes: 6 additions & 0 deletions pkg/modules/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ import (
v1 "kusionstack.io/kusion/pkg/apis/api.kusion.io/v1"
)

// IgnoreModules todo@dayuan delete this condition after workload is changed into a module
var IgnoreModules = map[string]bool{
"service": true,
"job": true,
}

// CallGeneratorFuncs calls each NewGeneratorFunc in the given slice
// and returns a slice of Generator instances.
func CallGeneratorFuncs(newGenerators ...NewGeneratorFunc) ([]Generator, error) {
Expand Down
26 changes: 21 additions & 5 deletions pkg/workspace/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
utilerrors "k8s.io/apimachinery/pkg/util/errors"

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

var (
Expand Down Expand Up @@ -60,7 +61,7 @@ func ValidateModuleConfigs(configs v1.ModuleConfigs) error {
if cfg == nil {
return fmt.Errorf("%w, module name: %s", ErrEmptyModuleConfig, name)
}
if err := ValidateModuleConfig(cfg); err != nil {
if err := ValidateModuleConfig(name, cfg); err != nil {
return fmt.Errorf("%w, module name: %s", err, name)
}
}
Expand All @@ -69,7 +70,10 @@ func ValidateModuleConfigs(configs v1.ModuleConfigs) error {
}

// ValidateModuleConfig is used to validate the moduleConfig is valid or not.
func ValidateModuleConfig(config *v1.ModuleConfig) error {
func ValidateModuleConfig(name string, config *v1.ModuleConfig) error {
if err := ValidateModuleMetadata(name, config); err != nil {
return err
}
if err := ValidateModuleDefaultConfig(config.Configs.Default); err != nil {
return err
}
Expand All @@ -79,10 +83,22 @@ func ValidateModuleConfig(config *v1.ModuleConfig) error {
return nil
}

func ValidateModuleMetadata(name string, config *v1.ModuleConfig) error {
if modules.IgnoreModules[name] {
return nil
}
if config.Version == "" {
return fmt.Errorf("empty version of module:%s in the workspacek config", name)
}
if config.Path == "" {
return fmt.Errorf("empty path of module:%s in the workspacek config", name)
}
return nil
}

func ValidateModuleDefaultConfig(config v1.GenericConfig) error {
// todo@dayuan validate path and version in the config when we have turned workload into a module
if len(config) == 0 {
return fmt.Errorf("%w, block name: %s", ErrEmptyModuleConfigBlock, v1.DefaultBlock)
if config == nil {
return nil
}
if _, ok := config[v1.ProjectSelectorField]; ok {
return ErrNotEmptyModuleConfigProjectSelector
Expand Down
26 changes: 25 additions & 1 deletion pkg/workspace/validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ func mockValidModuleConfigs() map[string]*v1.ModuleConfig {
},
},
"network": {
Path: "ghcr.io/kusionstack/network",
Version: "0.1.0",
Configs: v1.Configs{
Default: v1.GenericConfig{
"type": "aws",
Expand Down Expand Up @@ -274,12 +276,34 @@ func TestValidateModuleConfig(t *testing.T) {

for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
err := ValidateModuleConfig(&tc.moduleConfig)
err := ValidateModuleConfig("mysql", &tc.moduleConfig)
assert.Equal(t, tc.success, err == nil)
})
}
}

func TestValidateModuleMetadata(t *testing.T) {
t.Run("ValidModuleMetadata", func(t *testing.T) {
err := ValidateModuleMetadata("testModule", &v1.ModuleConfig{Version: "1.0.0", Path: "/path/to/module"})
assert.NoError(t, err)
})

t.Run("IgnoreModule", func(t *testing.T) {
err := ValidateModuleMetadata("service", &v1.ModuleConfig{Version: "1.0.0", Path: "/path/to/module"})
assert.NoError(t, err)
})

t.Run("EmptyModuleVersion", func(t *testing.T) {
err := ValidateModuleMetadata("testModule", &v1.ModuleConfig{Version: "", Path: "/path/to/module"})
assert.Error(t, err)
})

t.Run("EmptyModulePath", func(t *testing.T) {
err := ValidateModuleMetadata("testModule", &v1.ModuleConfig{Version: "1.0.0", Path: ""})
assert.Error(t, err)
})
}

func TestValidateAWSSecretStore(t *testing.T) {
type args struct {
ss *v1.AWSProvider
Expand Down

0 comments on commit 519b8c3

Please sign in to comment.