Skip to content

Commit

Permalink
feat: Implement Create Module Command Layer (#40)
Browse files Browse the repository at this point in the history
* add create module command basic layer

* add tests for create module flags

* restructure and add more test cases

* add more tests and improve old tests

* add more test cases

* fix lint errors and refactor duplicate code

* address review comments

* add godox support in linting
remove TODOs

* address review comments

* heavy refactor into new command structure

* update docs

* fix scaffold e2e tests

* fix pipeline for unit tests

* fix all refactor mishaps

* remove NOTE from golangci yaml

* update .golangci.yaml
fix refactor mishaps
minor refactoring

* add unit tests for modulectl create validate()
fix regular expression for options validation

* fix linting

* fix documentation

* make gendocs happy

* gendocs: add custom function for printing flag usage

* make linter happy
  • Loading branch information
amritanshusikdar authored Sep 4, 2024
1 parent b3636b1 commit 9dcc28d
Show file tree
Hide file tree
Showing 42 changed files with 940 additions and 265 deletions.
6 changes: 4 additions & 2 deletions .golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ linters:
- exportloopref # deprecated (since v1.60.2), replaced by copyloopvar
- forbidigo # temparily disabled
- godot # not needed
- godox # disabled for this project
- gomnd # deprecated (since v1.58.0), renamed to mnd
- lll
- nlreturn # too strict and mostly code is not more readable
Expand Down Expand Up @@ -55,8 +54,10 @@ linters-settings:
alias: iotools
- pkg: github.com/kyma-project/modulectl/internal/common/errors
alias: commonerrors
- pkg: github.com/kyma-project/modulectl/cmd/modulectl/create/scaffold
- pkg: github.com/kyma-project/modulectl/cmd/modulectl/scaffold
alias: scaffoldcmd
- pkg: github.com/kyma-project/modulectl/cmd/modulectl/create
alias: createcmd
ireturn:
allow:
- anon
Expand All @@ -69,6 +70,7 @@ linters-settings:
ignore-type-assert-ok: true
ignore-map-index-ok: true
ignore-chan-recv-ok: true
godox: # `TODO`, `BUG`, `FIXME` are the default, no need to mention again
issues:
exclude-rules:
- path: "_test\\.go"
Expand Down
116 changes: 110 additions & 6 deletions cmd/modulectl/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,27 @@ import (

"github.com/spf13/cobra"

"github.com/kyma-project/modulectl/cmd/modulectl/create"
createcmd "github.com/kyma-project/modulectl/cmd/modulectl/create"
scaffoldcmd "github.com/kyma-project/modulectl/cmd/modulectl/scaffold"
"github.com/kyma-project/modulectl/internal/service/contentprovider"
"github.com/kyma-project/modulectl/internal/service/create"
"github.com/kyma-project/modulectl/internal/service/filegenerator"
"github.com/kyma-project/modulectl/internal/service/filegenerator/reusefilegenerator"
"github.com/kyma-project/modulectl/internal/service/moduleconfig"
"github.com/kyma-project/modulectl/internal/service/scaffold"
"github.com/kyma-project/modulectl/tools/filesystem"
"github.com/kyma-project/modulectl/tools/yaml"

_ "embed"
)

const (
moduleConfigKind = "module-config"
manifestKind = "manifest"
defaultCRKind = "defaultcr"
securityConfigKind = "security-config"
)

//go:embed use.txt
var use string

Expand All @@ -24,17 +40,105 @@ func NewCmd() (*cobra.Command, error) {
Use: use,
Short: short,
Long: long,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("This is the Kyma ModuleCtl command executed")
},
}

cmd, err := create.NewCmd()
scaffoldService, err := buildScaffoldService()
if err != nil {
return nil, fmt.Errorf("failed to build scaffold service: %w", err)
}

scaffoldCmd, err := scaffoldcmd.NewCmd(scaffoldService)
if err != nil {
return nil, fmt.Errorf("failed to build scaffold command: %w", err)
}

moduleService, err := buildModuleService()
if err != nil {
return nil, fmt.Errorf("failed to build module service: %w", err)
}

createCmd, err := createcmd.NewCmd(moduleService)
if err != nil {
return nil, fmt.Errorf("failed to build create command: %w", err)
}

rootCmd.AddCommand(cmd)
rootCmd.AddCommand(scaffoldCmd)
rootCmd.AddCommand(createCmd)

return rootCmd, nil
}

func buildModuleService() (*create.Service, error) {
moduleService, err := create.NewService(&create.Service{})
if err != nil {
return nil, fmt.Errorf("failed to create module service: %w", err)
}
return moduleService, nil
}

func buildScaffoldService() (*scaffold.Service, error) {
fileSystemUtil := &filesystem.Util{}
yamlConverter := &yaml.ObjectToYAMLConverter{}

moduleConfigContentProvider, err := contentprovider.NewModuleConfig(yamlConverter)
if err != nil {
return nil, fmt.Errorf("failed to create module config content provider: %w", err)
}

moduleConfigFileGenerator, err := filegenerator.NewService(moduleConfigKind, fileSystemUtil, moduleConfigContentProvider)
if err != nil {
return nil, fmt.Errorf("failed to create module config file generator: %w", err)
}

moduleConfigService, err := moduleconfig.NewService(fileSystemUtil, moduleConfigFileGenerator)
if err != nil {
return nil, fmt.Errorf("failed to create module config service: %w", err)
}

manifestFileGenerator, err := filegenerator.NewService(manifestKind, fileSystemUtil, contentprovider.NewManifest())
if err != nil {
return nil, fmt.Errorf("failed to create manifest file generator: %w", err)
}

manifestReuseFileGenerator, err := reusefilegenerator.NewService(manifestKind, fileSystemUtil, manifestFileGenerator)
if err != nil {
return nil, fmt.Errorf("failed to create manifest reuse file generator: %w", err)
}

defaultCRFileGenerator, err := filegenerator.NewService(defaultCRKind, fileSystemUtil, contentprovider.NewDefaultCR())
if err != nil {
return nil, fmt.Errorf("failed to create default CR file generator: %w", err)
}

defaultCRReuseFileGenerator, err := reusefilegenerator.NewService(defaultCRKind, fileSystemUtil, defaultCRFileGenerator)
if err != nil {
return nil, fmt.Errorf("failed to create default CR reuse file generator: %w", err)
}

securityConfigContentProvider, err := contentprovider.NewSecurityConfig(yamlConverter)
if err != nil {
return nil, fmt.Errorf("failed to create security config content provider: %w", err)
}

securityConfigFileGenerator, err := filegenerator.NewService(securityConfigKind, fileSystemUtil, securityConfigContentProvider)
if err != nil {
return nil, fmt.Errorf("failed to create security config file generator: %w", err)
}

securityConfigReuseFileGenerator, err := reusefilegenerator.NewService(securityConfigKind, fileSystemUtil, securityConfigFileGenerator)
if err != nil {
return nil, fmt.Errorf("failed to create security config reuse file generator: %w", err)
}

scaffoldService, err := scaffold.NewService(
moduleConfigService,
manifestReuseFileGenerator,
defaultCRReuseFileGenerator,
securityConfigReuseFileGenerator,
)
if err != nil {
return nil, fmt.Errorf("failed to create scaffold service: %w", err)
}

return scaffoldService, nil
}
114 changes: 22 additions & 92 deletions cmd/modulectl/create/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,13 @@ import (

"github.com/spf13/cobra"

scaffoldcmd "github.com/kyma-project/modulectl/cmd/modulectl/create/scaffold"
"github.com/kyma-project/modulectl/internal/service/contentprovider"
"github.com/kyma-project/modulectl/internal/service/filegenerator"
"github.com/kyma-project/modulectl/internal/service/filegenerator/reusefilegenerator"
"github.com/kyma-project/modulectl/internal/service/moduleconfig"
"github.com/kyma-project/modulectl/internal/service/scaffold"
"github.com/kyma-project/modulectl/tools/filesystem"
"github.com/kyma-project/modulectl/tools/yaml"
commonerrors "github.com/kyma-project/modulectl/internal/common/errors"
"github.com/kyma-project/modulectl/internal/service/create"
iotools "github.com/kyma-project/modulectl/tools/io"

_ "embed"
)

const (
moduleConfigKind = "module-config"
manifestKind = "manifest"
defaultCRKind = "defaultcr"
securityConfigKind = "security-config"
)

//go:embed use.txt
var use string

Expand All @@ -33,90 +21,32 @@ var short string
//go:embed long.txt
var long string

func NewCmd() (*cobra.Command, error) {
rootCmd := &cobra.Command{
Use: use,
Short: short,
Long: long,
}

svc, err := buildScaffoldService()
if err != nil {
return nil, fmt.Errorf("failed to build scaffold service: %w", err)
}

cmd, err := scaffoldcmd.NewCmd(svc)
if err != nil {
return nil, fmt.Errorf("failed to build scaffold command: %w", err)
}
//go:embed example.txt
var example string

rootCmd.AddCommand(cmd)
return rootCmd, nil
type ModuleService interface {
CreateModule(opts create.Options) error
}

func buildScaffoldService() (*scaffold.Service, error) {
fileSystemUtil := &filesystem.Util{}
yamlConverter := &yaml.ObjectToYAMLConverter{}

moduleConfigContentProvider, err := contentprovider.NewModuleConfig(yamlConverter)
if err != nil {
return nil, fmt.Errorf("failed to create module config content provider: %w", err)
}

moduleConfigFileGenerator, err := filegenerator.NewService(moduleConfigKind, fileSystemUtil, moduleConfigContentProvider)
if err != nil {
return nil, fmt.Errorf("failed to create module config file generator: %w", err)
}

moduleConfigService, err := moduleconfig.NewService(fileSystemUtil, moduleConfigFileGenerator)
if err != nil {
return nil, fmt.Errorf("failed to create module config service: %w", err)
func NewCmd(moduleService ModuleService) (*cobra.Command, error) {
if moduleService == nil {
return nil, fmt.Errorf("%w: createService must not be nil", commonerrors.ErrInvalidArg)
}

manifestFileGenerator, err := filegenerator.NewService(manifestKind, fileSystemUtil, contentprovider.NewManifest())
if err != nil {
return nil, fmt.Errorf("failed to create manifest file generator: %w", err)
}

manifestReuseFileGenerator, err := reusefilegenerator.NewService(manifestKind, fileSystemUtil, manifestFileGenerator)
if err != nil {
return nil, fmt.Errorf("failed to create manifest reuse file generator: %w", err)
}

defaultCRFileGenerator, err := filegenerator.NewService(defaultCRKind, fileSystemUtil, contentprovider.NewDefaultCR())
if err != nil {
return nil, fmt.Errorf("failed to create default CR file generator: %w", err)
}

defaultCRReuseFileGenerator, err := reusefilegenerator.NewService(defaultCRKind, fileSystemUtil, defaultCRFileGenerator)
if err != nil {
return nil, fmt.Errorf("failed to create default CR reuse file generator: %w", err)
}

securitConfigContentProvider, err := contentprovider.NewSecurityConfig(yamlConverter)
if err != nil {
return nil, fmt.Errorf("failed to create security config content provider: %w", err)
}
opts := create.Options{}

securityConfigFileGenerator, err := filegenerator.NewService(securityConfigKind, fileSystemUtil, securitConfigContentProvider)
if err != nil {
return nil, fmt.Errorf("failed to create security config file generator: %w", err)
cmd := &cobra.Command{
Use: use,
Short: short,
Long: long,
Example: example,
RunE: func(cmd *cobra.Command, _ []string) error {
return moduleService.CreateModule(opts)
},
}

securityConfigReuseFileGenerator, err := reusefilegenerator.NewService(securityConfigKind, fileSystemUtil, securityConfigFileGenerator)
if err != nil {
return nil, fmt.Errorf("failed to create security config reuse file generator: %w", err)
}

scaffoldService, err := scaffold.NewService(
moduleConfigService,
manifestReuseFileGenerator,
defaultCRReuseFileGenerator,
securityConfigReuseFileGenerator,
)
if err != nil {
return nil, fmt.Errorf("failed to create scaffold service: %w", err)
}
opts.Out = iotools.NewDefaultOut(cmd.OutOrStdout())
parseFlags(cmd.Flags(), &opts)

return scaffoldService, nil
return cmd, nil
}
Loading

0 comments on commit 9dcc28d

Please sign in to comment.