Skip to content

Commit

Permalink
Merge branch 'main' into feat/kyma-project#54-suppport-spec-associate…
Browse files Browse the repository at this point in the history
…dresources
  • Loading branch information
LeelaChacha authored Oct 23, 2024
2 parents 37c72ed + cc4d01d commit f2383fe
Show file tree
Hide file tree
Showing 28 changed files with 979 additions and 377 deletions.
3 changes: 0 additions & 3 deletions .golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@ linters:
- paralleltest # should be enabled consciously for long running tests
- wsl # too strict and mostly code is not more readable
linters-settings:
gomoddirectives:
replace-allow-list:
- ocm.software/ocm
revive:
severity: error
rules:
Expand Down
16 changes: 14 additions & 2 deletions cmd/modulectl/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"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/fileresolver"
"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"
Expand Down Expand Up @@ -89,7 +90,17 @@ func buildModuleService() (*create.Service, error) {
fileSystemUtil := &filesystem.Util{}
tmpFileSystem := filesystem.NewTempFileSystem()

moduleConfigService, err := moduleconfigreader.NewService(fileSystemUtil, tmpFileSystem)
manifestFileResolver, err := fileresolver.NewFileResolver("kyma-module-manifest-*.yaml", tmpFileSystem)
if err != nil {
return nil, fmt.Errorf("failed to create manifest file resolver: %w", err)
}

defaultCRFileResolver, err := fileresolver.NewFileResolver("kyma-module-default-cr-*.yaml", tmpFileSystem)
if err != nil {
return nil, fmt.Errorf("failed to create default CR file resolver: %w", err)
}

moduleConfigService, err := moduleconfigreader.NewService(fileSystemUtil)
if err != nil {
return nil, fmt.Errorf("failed to create module config service: %w", err)
}
Expand Down Expand Up @@ -127,7 +138,8 @@ func buildModuleService() (*create.Service, error) {
return nil, fmt.Errorf("failed to create crd parser service: %w", err)
}
moduleService, err := create.NewService(moduleConfigService, gitSourcesService,
securityConfigService, componentArchiveService, registryService, moduleTemplateService, crdParserService)
securityConfigService, componentArchiveService, registryService, moduleTemplateService,
crdParserService, manifestFileResolver, defaultCRFileResolver, fileSystemUtil)
if err != nil {
return nil, fmt.Errorf("failed to create module service: %w", err)
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/modulectl/create/example.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
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
modulectl create --config-file=/path/to/module-config-file --registry http://localhost:5001/unsigned --insecure
2 changes: 1 addition & 1 deletion docs/gen-docs/modulectl_create.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ modulectl create [--config-file MODULE_CONFIG_FILE] [--registry MODULE_REGISTRY]

```bash
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
modulectl create --config-file=/path/to/module-config-file --registry http://localhost:5001/unsigned --insecure
```

## Flags
Expand Down
7 changes: 2 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@ module github.com/kyma-project/modulectl

go 1.23.2

// This replace is because the new ocm package version doesn't allow pushing to insecure registries. https://github.com/open-component-model/ocm/issues/971
replace ocm.software/ocm => ocm.software/ocm v0.15.0

require (
github.com/Masterminds/semver/v3 v3.3.0
github.com/go-git/go-git/v5 v5.12.0
Expand All @@ -18,7 +15,7 @@ require (
gopkg.in/yaml.v3 v3.0.1
k8s.io/apiextensions-apiserver v0.31.1
k8s.io/apimachinery v0.31.1
ocm.software/ocm v0.16.0
ocm.software/ocm v0.16.2
sigs.k8s.io/yaml v1.4.0
)

Expand Down Expand Up @@ -230,7 +227,6 @@ require (
github.com/opencontainers/runtime-spec v1.2.0 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/pborman/uuid v1.2.1 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
github.com/pjbgf/sha1cd v0.3.0 // indirect
Expand Down Expand Up @@ -335,6 +331,7 @@ require (
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect
oras.land/oras-go v1.2.5 // indirect
oras.land/oras-go/v2 v2.5.0 // indirect
sigs.k8s.io/controller-runtime v0.19.0 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/kustomize/api v0.17.3 // indirect
Expand Down
21 changes: 11 additions & 10 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -379,8 +379,8 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/fluxcd/cli-utils v0.36.0-flux.9 h1:RITKdwIAqT3EFKXl7B91mj6usVjxcy7W8PJZlxqUa84=
github.com/fluxcd/cli-utils v0.36.0-flux.9/go.mod h1:q6lXQpbAlrZmTB4Qe5oAENkv0y2kwMWcqTMDHrRo2Is=
github.com/fluxcd/pkg/ssa v0.41.0 h1:UFrnHJ/cT2+6Qoh98o7INipSoj8GjwMEtb9hLus15xQ=
github.com/fluxcd/pkg/ssa v0.41.0/go.mod h1:Lfu6g8AGbJ/MHSq5zSOBWMTJu9pPC5dG1ykmYC1NTPs=
github.com/fluxcd/pkg/ssa v0.41.1 h1:VW87zsLYAKUvCxJhuEH7VzxVh3SxaU+PyApCT6gKjTk=
github.com/fluxcd/pkg/ssa v0.41.1/go.mod h1:7cbyLHqFd5FpcKvhxbHG3DkMm3cZteW45Mi78B0hg8g=
github.com/foxcpp/go-mockdns v1.1.0 h1:jI0rD8M0wuYAxL7r/ynTrCQQq0BVqfB99Vgk7DlmewI=
github.com/foxcpp/go-mockdns v1.1.0/go.mod h1:IhLeSFGed3mJIAXPH2aiRQB+kqz7oqu8ld2qVbOu7Wk=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
Expand Down Expand Up @@ -512,8 +512,8 @@ github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/gomodule/redigo v1.8.9 h1:Sl3u+2BI/kk+VEatbj0scLdrFhjPmbxOc1myhDP41ws=
github.com/gomodule/redigo v1.8.9/go.mod h1:7ArFNvsTjH8GMMzB4uy1snslv2BwmginuMs06a1uzZE=
github.com/gomodule/redigo v1.8.2 h1:H5XSIre1MB5NbPYFp+i1NBbb5qN1W8Y8YAQoAYbkm8k=
github.com/gomodule/redigo v1.8.2/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
github.com/google/certificate-transparency-go v1.0.10-0.20180222191210-5ab67e519c93/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg=
Expand Down Expand Up @@ -627,9 +627,8 @@ github.com/jellydator/ttlcache/v3 v3.2.0 h1:6lqVJ8X3ZaUwvzENqPAobDsXNExfUJd61u++
github.com/jellydator/ttlcache/v3 v3.2.0/go.mod h1:hi7MGFdMAwZna5n2tuvh63DvFLzVKySzCVW6+0gA2n4=
github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8=
github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
github.com/jinzhu/gorm v0.0.0-20170222002820-5409931a1bb8 h1:CZkYfurY6KGhVtlalI4QwQ6T0Cu6iuY3e0x5RLu96WE=
github.com/jinzhu/gorm v0.0.0-20170222002820-5409931a1bb8/go.mod h1:Vla75njaFJ8clLU1W44h34PjIkijhjHIYnZxMqCdxqo=
github.com/jinzhu/gorm v1.9.16 h1:+IyIjPEABKRpsu/F8OvDPy9fyQlgsg2luMV2ZIH5i5o=
github.com/jinzhu/gorm v1.9.16/go.mod h1:G3LB3wezTOWM2ITLzPxEXgSkOXAntiLHS7UdBefADcs=
github.com/jinzhu/inflection v0.0.0-20170102125226-1c35d901db3d h1:jRQLvyVGL+iVtDElaEIDdKwpPqUIZJfzkNLV34htpEc=
github.com/jinzhu/inflection v0.0.0-20170102125226-1c35d901db3d/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
Expand Down Expand Up @@ -1329,14 +1328,16 @@ k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag=
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98=
k8s.io/kubectl v0.31.0 h1:kANwAAPVY02r4U4jARP/C+Q1sssCcN/1p9Nk+7BQKVg=
k8s.io/kubectl v0.31.0/go.mod h1:pB47hhFypGsaHAPjlwrNbvhXgmuAr01ZBvAIIUaI8d4=
k8s.io/kubectl v0.31.1 h1:ih4JQJHxsEggFqDJEHSOdJ69ZxZftgeZvYo7M/cpp24=
k8s.io/kubectl v0.31.1/go.mod h1:aNuQoR43W6MLAtXQ/Bu4GDmoHlbhHKuyD49lmTC8eJM=
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A=
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
ocm.software/ocm v0.15.0 h1:9DUaVXSh0T2Q0ty7abyoOPhSRqHmM8xw/5/uPf4m1h0=
ocm.software/ocm v0.15.0/go.mod h1:uNul0D9Z/7BrEB1LBnRYXlixjbEqtLMSaOMs/qGg1rk=
ocm.software/ocm v0.16.2 h1:XonVlRRtBUVmDClFxThh0MPwP/70dJAJ44DAxYU+8eU=
ocm.software/ocm v0.16.2/go.mod h1:0AnDbAG3qv6xj0gxOzEiB7n9lNXdni3j31PsjROaZNs=
oras.land/oras-go v1.2.5 h1:XpYuAwAb0DfQsunIyMfeET92emK8km3W4yEzZvUbsTo=
oras.land/oras-go v1.2.5/go.mod h1:PuAwRShRZCsZb7g8Ar3jKKQR/2A/qN+pkYxIOd/FAoo=
oras.land/oras-go/v2 v2.5.0 h1:o8Me9kLY74Vp5uw07QXPiitjsw7qNXi8Twd+19Zf02c=
oras.land/oras-go/v2 v2.5.0/go.mod h1:z4eisnLP530vwIOUOJeBIj0aGI0L1C3d53atvCBqZHg=
sigs.k8s.io/controller-runtime v0.19.0 h1:nWVM7aq+Il2ABxwiCizrVDSlmDcshi9llbaFbC0ji/Q=
sigs.k8s.io/controller-runtime v0.19.0/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
Expand Down
33 changes: 33 additions & 0 deletions internal/common/validation/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ package validation

import (
"fmt"
"net/url"
"regexp"
"strings"

"github.com/Masterminds/semver/v3"

commonerrors "github.com/kyma-project/modulectl/internal/common/errors"
"github.com/kyma-project/modulectl/internal/service/contentprovider"
)

const (
Expand Down Expand Up @@ -107,6 +109,37 @@ func ValidateNamespace(namespace string) error {
return nil
}

func ValidateResources(resources contentprovider.ResourcesMap) error {
for name, link := range resources {
if name == "" {
return fmt.Errorf("%w: name must not be empty", commonerrors.ErrInvalidOption)
}

if link == "" {
return fmt.Errorf("%w: link must not be empty", commonerrors.ErrInvalidOption)
}

if err := ValidateIsValidHTTPSURL(link); err != nil {
return err
}
}

return nil
}

func ValidateIsValidHTTPSURL(input string) error {
_url, err := url.Parse(input)
if err != nil {
return fmt.Errorf("%w: link %s is not a valid URL", commonerrors.ErrInvalidOption, input)
}

if _url.Scheme != "https" {
return fmt.Errorf("%w: link %s is not using https scheme", commonerrors.ErrInvalidOption, input)
}

return nil
}

func validateSemanticVersion(version string) error {
_, err := semver.StrictNewVersion(strings.TrimSpace(version))
if err != nil {
Expand Down
95 changes: 95 additions & 0 deletions internal/common/validation/validation_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package validation_test

import (
"fmt"
"testing"

"github.com/kyma-project/modulectl/internal/common/validation"
"github.com/kyma-project/modulectl/internal/service/contentprovider"
)

func TestValidateModuleName(t *testing.T) {
Expand Down Expand Up @@ -266,3 +268,96 @@ func TestValidateGvk(t *testing.T) {
})
}
}

func TestValidateResources(t *testing.T) {
tests := []struct {
name string
resources contentprovider.ResourcesMap
wantErr bool
}{
{
name: "valid resources",
resources: contentprovider.ResourcesMap{
"first": "https://github.com/kyma-project/template-operator/releases/download/1.0.1/template-operator.yaml",
"second": "https://github.com/kyma-project/template-operator/releases/download/1.0.1/template-operator.yaml",
},
wantErr: false,
},
{
name: "empty name",
resources: contentprovider.ResourcesMap{
"": "https://github.com/kyma-project/template-operator/releases/download/1.0.1/template-operator.yaml",
},
wantErr: true,
},
{
name: "empty link",
resources: contentprovider.ResourcesMap{
"first": "",
},
wantErr: true,
},
{
name: "non-https schema",
resources: contentprovider.ResourcesMap{
"first": "http://github.com/kyma-project/template-operator/releases/download/1.0.1/template-operator.yaml",
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := validation.ValidateResources(tt.resources); (err != nil) != tt.wantErr {
fmt.Println(err.Error())
t.Errorf("ValidateResources() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}

func TestValidateIsValidHttpsUrl(t *testing.T) {
tests := []struct {
name string
url string
wantErr bool
}{
{
name: "valid url",
url: "https://github.com/kyma-project/template-operator/releases/download/1.0.1/template-operator.yaml",
wantErr: false,
},
{
name: "invalid url - not using https",
url: "http://github.com/kyma-project/template-operator/releases/download/1.0.1/template-operator.yaml",
wantErr: true,
},
{
name: "invalid url - usig file scheme",
url: "file:///Users/User/template-operator/releases/download/1.0.1/template-operator.yaml",
wantErr: true,
},
{
name: "invalid url - local path",
url: "./1.0.1/template-operator.yaml",
wantErr: true,
},
{
name: "invalid url",
url: "%% not a valid url",
wantErr: true,
},
{
name: "empty url",
url: "",
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := validation.ValidateIsValidHTTPSURL(tt.url); (err != nil) != tt.wantErr {
fmt.Println(err.Error())
t.Errorf("ValidateIsValidUrl() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
49 changes: 43 additions & 6 deletions internal/service/contentprovider/moduleconfig.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package contentprovider

import (
"errors"
"fmt"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand All @@ -9,6 +10,8 @@ import (
"github.com/kyma-project/modulectl/internal/common/types"
)

var ErrDuplicateResourceNames = errors.New("resources contain duplicate entries")

type ModuleConfigProvider struct {
yamlConverter ObjectToYAMLConverter
}
Expand All @@ -35,12 +38,12 @@ func (s *ModuleConfigProvider) GetDefaultContent(args types.KeyValueArgs) (strin

func (s *ModuleConfigProvider) getModuleConfig(args types.KeyValueArgs) ModuleConfig {
return ModuleConfig{
Name: args[ArgModuleName],
Version: args[ArgModuleVersion],
Channel: args[ArgModuleChannel],
ManifestPath: args[ArgManifestFile],
Security: args[ArgSecurityConfigFile],
DefaultCRPath: args[ArgDefaultCRFile],
Name: args[ArgModuleName],
Version: args[ArgModuleVersion],
Channel: args[ArgModuleChannel],
Manifest: args[ArgManifestFile],
Security: args[ArgSecurityConfigFile],
DefaultCR: args[ArgDefaultCRFile],
}
}

Expand Down Expand Up @@ -92,4 +95,38 @@ type ModuleConfig struct {
Annotations map[string]string `yaml:"annotations" comment:"optional, additional annotations for the ModuleTemplate"`
AssociatedResources []*metav1.GroupVersionKind `yaml:"associatedResources" comment:"optional, GVK of the resources which are associated to the ModuleTemplate"`
Manager *Manager `yaml:"manager" comment:"optional, the module resource that can be used to indicate the installation readiness of the module. This is typically the manager deployment of the module"`
Resources ResourcesMap `yaml:"resources,omitempty" comment:"optional, additional resources of the ModuleTemplate that may be fetched"`
}

type resource struct {
Name string `yaml:"name"`
Link string `yaml:"link"`
}

type ResourcesMap map[string]string

func (rm *ResourcesMap) UnmarshalYAML(unmarshal func(interface{}) error) error {
resources := []resource{}
if err := unmarshal(&resources); err != nil {
return err
}

*rm = make(map[string]string)
for _, resource := range resources {
(*rm)[resource.Name] = resource.Link
}

if len(resources) > len(*rm) {
return ErrDuplicateResourceNames
}

return nil
}

func (rm ResourcesMap) MarshalYAML() (interface{}, error) {
resources := []resource{}
for name, link := range rm {
resources = append(resources, resource{Name: name, Link: link})
}
return resources, nil
}
Loading

0 comments on commit f2383fe

Please sign in to comment.