Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Implement the modulectl create command #49

Merged
merged 57 commits into from
Sep 25, 2024
Merged
Show file tree
Hide file tree
Changes from 46 commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
f7a3e86
Add parsing and validations logic and unit tests for the module confi…
nesmabadr Sep 5, 2024
edfaf2b
Parse Manifest and Default CR
nesmabadr Sep 9, 2024
facfcb3
Remove Security Scanners Config option from create command (It alread…
nesmabadr Sep 10, 2024
334b96b
Add componentdescriptor package
nesmabadr Sep 10, 2024
ff3fa58
Add unit tests
nesmabadr Sep 10, 2024
2f7415b
Add component descriptor components
nesmabadr Sep 11, 2024
03eba2e
Add component descriptor metadata
nesmabadr Sep 11, 2024
e0b3a87
Add security config
nesmabadr Sep 16, 2024
fbc2e95
Add steps to create command
nesmabadr Sep 17, 2024
07983c4
Start implementing ComponentArchive
nesmabadr Sep 17, 2024
dce9ce6
add module layers and resources to component descriptor
amritanshusikdar Sep 18, 2024
daa20b2
Add Component Archive with Resources
nesmabadr Sep 18, 2024
b5a896c
Add the rest of the create module command
nesmabadr Sep 19, 2024
c2cea93
Fix linting issues
nesmabadr Sep 20, 2024
033cb1a
Fix crdParser and componentversion alreadyexisting error
nesmabadr Sep 20, 2024
740a0d7
Adding some output messages
nesmabadr Sep 20, 2024
35d7bc6
Fixes for private registry
nesmabadr Sep 23, 2024
9dab405
Fixes for reading from URL
nesmabadr Sep 23, 2024
5b22691
Add moduleconfig_reader_test unit tests
nesmabadr Sep 23, 2024
39ca904
Add componentdescriptor_test.go
nesmabadr Sep 23, 2024
2b1a270
Add gitsources_test.go
nesmabadr Sep 23, 2024
b69c118
Add moduleresources_test.go
nesmabadr Sep 23, 2024
09632f0
Add securityconfig_test.go
nesmabadr Sep 23, 2024
3986a54
rebase
lindnerby Sep 23, 2024
2a10554
rebase
lindnerby Sep 23, 2024
b53afc9
linting
lindnerby Sep 23, 2024
16a7c33
push coverage
lindnerby Sep 23, 2024
f4e7323
Add crdparser_test.go
nesmabadr Sep 23, 2024
05bb855
add description to test func
lindnerby Sep 23, 2024
13ae10e
deactivate some linters for tests. fmt.
lindnerby Sep 24, 2024
025b9ea
more linting and settings
lindnerby Sep 24, 2024
9658077
Add test coverage
nesmabadr Sep 24, 2024
295f672
Add test coverage
nesmabadr Sep 24, 2024
686a99c
use interface for AddModuleResourcesToArchive archive param
lindnerby Sep 24, 2024
2b66d59
bump coverage
lindnerby Sep 24, 2024
7cb7760
rename validation pkg
lindnerby Sep 24, 2024
32e3b53
rename validation pkg
lindnerby Sep 24, 2024
eb306d1
coverage
lindnerby Sep 24, 2024
788799e
adapt docs
lindnerby Sep 24, 2024
cc260ec
adapt flag tests
lindnerby Sep 24, 2024
dbccec9
linting
lindnerby Sep 24, 2024
684992f
Add registry_test.go
nesmabadr Sep 24, 2024
e94ea8d
Add registry_test.go
nesmabadr Sep 24, 2024
77d65be
Adjust unit test coverage
nesmabadr Sep 24, 2024
a3f562e
Add registryUrl != "" check
nesmabadr Sep 24, 2024
1294b8b
Add if gitremote != "" for git sources
nesmabadr Sep 24, 2024
2664dfa
refactor CreateModule
lindnerby Sep 24, 2024
565afaa
Fix coverage
nesmabadr Sep 24, 2024
a93d4ff
handle emtpy default cr
nesmabadr Sep 24, 2024
a541a62
fix annotations
nesmabadr Sep 24, 2024
73ee794
fix
lindnerby Sep 24, 2024
e64be70
adapt some review issues
lindnerby Sep 25, 2024
c57dc1f
v prefixed version is not valid
lindnerby Sep 25, 2024
91d2f29
apply some review comments
lindnerby Sep 25, 2024
53f2c67
add one guardclause
lindnerby Sep 25, 2024
f95bb23
fix param used for tests
lindnerby Sep 25, 2024
2b19112
fix coverage file
lindnerby Sep 25, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ linters-settings:
disabled: true
arguments: [ 120 ]
funlen:
statements: 50
lines: 80
ignore-comments: true
cyclop:
max-complexity: 20
nestif:
Expand Down Expand Up @@ -58,12 +60,27 @@ linters-settings:
alias: scaffoldcmd
- pkg: github.com/kyma-project/modulectl/cmd/modulectl/create
alias: createcmd
- pkg: github.com/kyma-project/modulectl/internal/service/moduleconfig/generator
alias: moduleconfiggenerator
- pkg: github.com/kyma-project/modulectl/internal/service/moduleconfig/reader
alias: moduleconfigreader
- pkg: ocm.software/ocm/api/ocm/compdesc/meta/v1
alias: ocmv1
- pkg: ocm.software/ocm/cmds/ocm/commands/ocmcmds/common/inputs/types/ociartifact
alias: ociartifacttypes
- pkg: k8s.io/apimachinery/pkg/apis/meta/v1
alias: metav1
ireturn:
allow:
- anon
- error
- empty
- stdlib
- vfs.FileSystem
- internal.BlobAccess
- internal.ComponentVersionAccess
- internal.Credentials
- internal.Repository
varnamelen:
ignore-names:
- ok
Expand All @@ -75,6 +92,9 @@ issues:
exclude-rules:
- path: "_test\\.go"
linters:
- dupl # Table driven unit and integration tests are expected to have duplicate code
- goconst # To be descriptive in tests we sometimes don't extract constants
- varnamelen # Table driven unit and integration tests are expected to have short variable names
- wrapcheck # Errors do not need to be wrapped in unit and integration tests
- err113 # Dynamic error creation in unit and integration tests is ok
- gochecknoglobals # Does not apply to unit and integration tests
Expand Down
58 changes: 48 additions & 10 deletions cmd/modulectl/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,27 @@ package modulectl
import (
"fmt"

"github.com/mandelsoft/vfs/pkg/memoryfs"
"github.com/mandelsoft/vfs/pkg/osfs"
"github.com/spf13/cobra"

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/componentarchive"
"github.com/kyma-project/modulectl/internal/service/componentdescriptor"
"github.com/kyma-project/modulectl/internal/service/contentprovider"
"github.com/kyma-project/modulectl/internal/service/crdparser"
"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/git"
moduleconfiggenerator "github.com/kyma-project/modulectl/internal/service/moduleconfig/generator"
moduleconfigreader "github.com/kyma-project/modulectl/internal/service/moduleconfig/reader"
"github.com/kyma-project/modulectl/internal/service/registry"
"github.com/kyma-project/modulectl/internal/service/scaffold"
"github.com/kyma-project/modulectl/internal/service/templategenerator"
"github.com/kyma-project/modulectl/tools/filesystem"
"github.com/kyma-project/modulectl/tools/ocirepo"
"github.com/kyma-project/modulectl/tools/yaml"

_ "embed"
Expand Down Expand Up @@ -69,7 +79,29 @@ func NewCmd() (*cobra.Command, error) {
}

func buildModuleService() (*create.Service, error) {
moduleService, err := create.NewService(&create.Service{})
fileSystemUtil := &filesystem.Util{}
tmpFileSystem := filesystem.NewTempFileSystem()

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

gitService := git.NewService()
gitSourcesService := componentdescriptor.NewGitSourcesService(gitService)
securityConfigService := componentdescriptor.NewSecurityConfigService(gitService)

memoryFileSystem := memoryfs.New()
osFileSystem := osfs.New()
archiveFileSystemService := filesystem.NewArchiveFileSystem(memoryFileSystem, osFileSystem)
componentArchiveService := componentarchive.NewService(archiveFileSystemService)
ociRepo := &ocirepo.OCIRepo{}
registryService := registry.NewService(ociRepo, nil)
moduleTemplateService := templategenerator.NewService(fileSystemUtil)
crdParserService := crdparser.NewService(fileSystemUtil)

moduleService, err := create.NewService(moduleConfigService, gitSourcesService,
securityConfigService, componentArchiveService, registryService, moduleTemplateService, crdParserService)
if err != nil {
return nil, fmt.Errorf("failed to create module service: %w", err)
}
Expand All @@ -80,17 +112,18 @@ func buildScaffoldService() (*scaffold.Service, error) {
fileSystemUtil := &filesystem.Util{}
yamlConverter := &yaml.ObjectToYAMLConverter{}

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

moduleConfigFileGenerator, err := filegenerator.NewService(moduleConfigKind, fileSystemUtil, moduleConfigContentProvider)
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)
moduleConfigService, err := moduleconfiggenerator.NewService(fileSystemUtil, moduleConfigFileGenerator)
if err != nil {
return nil, fmt.Errorf("failed to create module config service: %w", err)
}
Expand All @@ -100,17 +133,20 @@ func buildScaffoldService() (*scaffold.Service, error) {
return nil, fmt.Errorf("failed to create manifest file generator: %w", err)
}

manifestReuseFileGenerator, err := reusefilegenerator.NewService(manifestKind, fileSystemUtil, manifestFileGenerator)
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())
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)
defaultCRReuseFileGenerator, err := reusefilegenerator.NewService(defaultCRKind, fileSystemUtil,
defaultCRFileGenerator)
if err != nil {
return nil, fmt.Errorf("failed to create default CR reuse file generator: %w", err)
}
Expand All @@ -120,12 +156,14 @@ func buildScaffoldService() (*scaffold.Service, error) {
return nil, fmt.Errorf("failed to create security config content provider: %w", err)
}

securityConfigFileGenerator, err := filegenerator.NewService(securityConfigKind, fileSystemUtil, securityConfigContentProvider)
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)
securityConfigReuseFileGenerator, err := reusefilegenerator.NewService(securityConfigKind, fileSystemUtil,
securityConfigFileGenerator)
if err != nil {
return nil, fmt.Errorf("failed to create security config reuse file generator: %w", err)
}
Expand Down
12 changes: 4 additions & 8 deletions cmd/modulectl/create/cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,19 +52,17 @@ func Test_Execute_ParsesAllModuleOptions(t *testing.T) {
insecure := "true"
templateOutput := testutils.RandomName(10)
registryURL := testutils.RandomName(10)
registryCredSelector := testutils.RandomName(10)
secScannerConfig := testutils.RandomName(10)
credSelector := testutils.RandomName(10)

os.Args = []string{
"create",
"--module-config-file", moduleConfigFile,
"--credentials", credentials,
"--git-remote", gitRemote,
"--insecure", insecure,
"--output", templateOutput,
"--registry", registryURL,
"--registry-cred-selector", registryCredSelector,
"--sec-scanners-config", secScannerConfig,
"--registry-credentials", credentials,
"--registry-cred-selector", credSelector,
}

svc := &moduleServiceStub{}
Expand All @@ -82,8 +80,7 @@ func Test_Execute_ParsesAllModuleOptions(t *testing.T) {
assert.Equal(t, insecureFlagSet, svc.opts.Insecure)
assert.Equal(t, templateOutput, svc.opts.TemplateOutput)
assert.Equal(t, registryURL, svc.opts.RegistryURL)
assert.Equal(t, registryCredSelector, svc.opts.RegistryCredSelector)
assert.Equal(t, secScannerConfig, svc.opts.SecScannerConfig)
assert.Equal(t, credSelector, svc.opts.RegistryCredSelector)
}

func Test_Execute_ParsesModuleShortOptions(t *testing.T) {
Expand Down Expand Up @@ -124,7 +121,6 @@ func Test_Execute_ModuleParsesDefaults(t *testing.T) {
assert.Equal(t, createcmd.TemplateOutputFlagDefault, svc.opts.TemplateOutput)
assert.Equal(t, createcmd.RegistryURLFlagDefault, svc.opts.RegistryURL)
assert.Equal(t, createcmd.RegistryCredSelectorFlagDefault, svc.opts.RegistryCredSelector)
assert.Equal(t, createcmd.SecScannersConfigFlagDefault, svc.opts.SecScannerConfig)
}

// Test Stubs
Expand Down
1 change: 0 additions & 1 deletion cmd/modulectl/create/example.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
Examples:
Build a simple module and push it to a remote registry
modulectl create --module-config-file=/path/to/module-config-file --registry http://localhost:5001/unsigned --insecure
30 changes: 15 additions & 15 deletions cmd/modulectl/create/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,16 @@ import (
const (
ModuleConfigFileFlagName = "module-config-file"
ModuleConfigFileFlagDefault = "module-config.yaml"
moduleConfigFileFlagUsage = "Specifies the module configuration file."
moduleConfigFileFlagUsage = "Specifies the path to the module configuration file."

CredentialsFlagName = "credentials"
CredentialsFlagName = "registry-credentials" //nolint:gosec // Not hardcoded credentials, rather just flag name
credentialsFlagShort = "c"
CredentialsFlagDefault = ""
credentialsFlagUsage = "Basic authentication credentials for the given repository in the <user:password> format."

GitRemoteFlagName = "git-remote"
GitRemoteFlagDefault = "origin"
gitRemoteFlagUsage = `Specifies the remote name of the wanted GitHub repository. For example "origin" or "upstream" (default "origin").`
GitRemoteFlagDefault = ""
gitRemoteFlagUsage = "Specifies the URL of the module's GitHub repository. "

InsecureFlagName = "insecure"
InsecureFlagDefault = false
Expand All @@ -27,9 +27,10 @@ const (
TemplateOutputFlagName = "output"
templateOutputFlagShort = "o"
TemplateOutputFlagDefault = "template.yaml"
templateOutputFlagUsage = `File to write the module template if the module is uploaded to a registry (default "template.yaml").`
templateOutputFlagUsage = `Path to write the ModuleTemplate file to, if the module is uploaded to a registry (default "template.yaml").`

RegistryURLFlagName = "registry"
registryFlagShort = "r"
RegistryURLFlagDefault = ""
registryURLFlagUsage = "Context URL of the repository. The repository URL will be automatically added to the repository contexts in the module descriptor."

Expand All @@ -38,19 +39,18 @@ const (
RegistryCredSelectorFlagDefault = ""
//nolint:gosec // Not hardcoded credentials, rather just flag name
registryCredSelectorFlagUsage = `Label selector to identify an externally created Secret of type "kubernetes.io/dockerconfigjson". It allows the image to be accessed in private image registries. It can be used when you push your module to a registry with authenticated access. For example, "label1=value1,label2=value2".`

SecScannersConfigFlagName = "sec-scanners-config"
SecScannersConfigFlagDefault = "sec-scanners-config.yaml"
secScannersConfigFlagUsage = `Path to the file holding the security scan configuration (default "sec-scanners-config.yaml").`
)

func parseFlags(flags *pflag.FlagSet, opts *create.Options) {
flags.StringVar(&opts.ModuleConfigFile, ModuleConfigFileFlagName, ModuleConfigFileFlagDefault, moduleConfigFileFlagUsage)
flags.StringVarP(&opts.Credentials, CredentialsFlagName, credentialsFlagShort, CredentialsFlagDefault, credentialsFlagUsage)
flags.StringVar(&opts.ModuleConfigFile, ModuleConfigFileFlagName, ModuleConfigFileFlagDefault,
moduleConfigFileFlagUsage)
flags.StringVarP(&opts.Credentials, CredentialsFlagName, credentialsFlagShort, CredentialsFlagDefault,
credentialsFlagUsage)
flags.StringVar(&opts.GitRemote, GitRemoteFlagName, GitRemoteFlagDefault, gitRemoteFlagUsage)
flags.BoolVar(&opts.Insecure, InsecureFlagName, InsecureFlagDefault, insecureFlagUsage)
flags.StringVarP(&opts.TemplateOutput, TemplateOutputFlagName, templateOutputFlagShort, TemplateOutputFlagDefault, templateOutputFlagUsage)
flags.StringVar(&opts.RegistryURL, RegistryURLFlagName, RegistryURLFlagDefault, registryURLFlagUsage)
flags.StringVar(&opts.RegistryCredSelector, RegistryCredSelectorFlagName, RegistryCredSelectorFlagDefault, registryCredSelectorFlagUsage)
flags.StringVar(&opts.SecScannerConfig, SecScannersConfigFlagName, SecScannersConfigFlagDefault, secScannersConfigFlagUsage)
flags.StringVarP(&opts.TemplateOutput, TemplateOutputFlagName, templateOutputFlagShort, TemplateOutputFlagDefault,
templateOutputFlagUsage)
flags.StringVarP(&opts.RegistryURL, RegistryURLFlagName, registryFlagShort, RegistryURLFlagDefault, registryURLFlagUsage)
flags.StringVar(&opts.RegistryCredSelector, RegistryCredSelectorFlagName, RegistryCredSelectorFlagDefault,
registryCredSelectorFlagUsage)
}
9 changes: 6 additions & 3 deletions cmd/modulectl/create/flags_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,17 @@ func Test_ScaffoldFlagsDefaults(t *testing.T) {
value string
expected string
}{
{name: createcmd.ModuleConfigFileFlagName, value: createcmd.ModuleConfigFileFlagDefault, expected: "module-config.yaml"},
{
name: createcmd.ModuleConfigFileFlagName,
value: createcmd.ModuleConfigFileFlagDefault,
expected: "module-config.yaml",
},
{name: createcmd.CredentialsFlagName, value: createcmd.CredentialsFlagDefault, expected: ""},
{name: createcmd.GitRemoteFlagName, value: createcmd.GitRemoteFlagDefault, expected: "origin"},
{name: createcmd.GitRemoteFlagName, value: createcmd.GitRemoteFlagDefault, expected: ""},
{name: createcmd.InsecureFlagName, value: strconv.FormatBool(createcmd.InsecureFlagDefault), expected: "false"},
{name: createcmd.TemplateOutputFlagName, value: createcmd.TemplateOutputFlagDefault, expected: "template.yaml"},
{name: createcmd.RegistryURLFlagName, value: createcmd.RegistryURLFlagDefault, expected: ""},
{name: createcmd.RegistryCredSelectorFlagName, value: createcmd.RegistryCredSelectorFlagDefault, expected: ""},
{name: createcmd.SecScannersConfigFlagName, value: createcmd.SecScannersConfigFlagDefault, expected: "sec-scanners-config.yaml"},
}

for _, testcase := range tests {
Expand Down
Loading
Loading