Skip to content

Commit

Permalink
feat: Error wrapping from newer to older in the error chain (#112)
Browse files Browse the repository at this point in the history
* Resolve conflict

* Added error wrapping changes ##105

* Fix unit testing and wrapped errors #105

* Fix e2e testing

* Fix e2e testing

* remove assertion duplication as require.errorAs is included in the require.errorIs

* resolve error messages

* changes for the PR comment

* changes for the PR comment

* patch the path error message

* patch the path error message

* e2e cleanup err msg

* reformat the error message

* reformat the error message

* reformat the error message

* reformat the error message
  • Loading branch information
medmes authored Nov 29, 2024
1 parent 4ceddc0 commit f7b9155
Show file tree
Hide file tree
Showing 29 changed files with 143 additions and 153 deletions.
2 changes: 1 addition & 1 deletion cmd/modulectl/create/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ type Service interface {

func NewCmd(service Service) (*cobra.Command, error) {
if service == nil {
return nil, fmt.Errorf("%w: service must not be nil", commonerrors.ErrInvalidArg)
return nil, fmt.Errorf("service must not be nil: %w", commonerrors.ErrInvalidArg)
}

opts := create.Options{}
Expand Down
2 changes: 1 addition & 1 deletion cmd/modulectl/scaffold/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ type Service interface {

func NewCmd(service Service) (*cobra.Command, error) {
if service == nil {
return nil, fmt.Errorf("%w: service must not be nil", commonerrors.ErrInvalidArg)
return nil, fmt.Errorf("service must not be nil: %w", commonerrors.ErrInvalidArg)
}

opts := scaffold.Options{}
Expand Down
35 changes: 17 additions & 18 deletions internal/common/validation/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,17 @@ const (

func ValidateModuleName(name string) error {
if name == "" {
return fmt.Errorf("%w: opts.ModuleName must not be empty", commonerrors.ErrInvalidOption)
return fmt.Errorf("opts.ModuleName must not be empty: %w", commonerrors.ErrInvalidOption)
}

if len(name) > moduleNameMaxLength {
return fmt.Errorf("%w: opts.ModuleName length must not exceed %q characters", commonerrors.ErrInvalidOption,
moduleNameMaxLength)
return fmt.Errorf("opts.ModuleName length must not exceed %q characters: %w", moduleNameMaxLength, commonerrors.ErrInvalidOption)
}

if matched, err := regexp.MatchString(moduleNamePattern, name); err != nil {
return fmt.Errorf("%w: failed to evaluate regex pattern for opts.ModuleName", commonerrors.ErrInvalidOption)
return fmt.Errorf("failed to evaluate regex pattern for opts.ModuleName: %w", commonerrors.ErrInvalidOption)
} else if !matched {
return fmt.Errorf("%w: opts.ModuleName must match the required pattern, e.g: 'github.com/path-to/your-repo'",
return fmt.Errorf("opts.ModuleName must match the required pattern, e.g: 'github.com/path-to/your-repo': %w",
commonerrors.ErrInvalidOption)
}

Expand All @@ -41,7 +40,7 @@ func ValidateModuleName(name string) error {

func ValidateModuleVersion(version string) error {
if version == "" {
return fmt.Errorf("%w: opts.ModuleVersion must not be empty", commonerrors.ErrInvalidOption)
return fmt.Errorf("opts.ModuleVersion must not be empty: %w", commonerrors.ErrInvalidOption)
}

if err := validateSemanticVersion(version); err != nil {
Expand All @@ -53,7 +52,7 @@ func ValidateModuleVersion(version string) error {

func ValidateModuleNamespace(namespace string) error {
if namespace == "" {
return fmt.Errorf("%w: opts.ModuleNamespace must not be empty", commonerrors.ErrInvalidOption)
return fmt.Errorf("opts.ModuleNamespace must not be empty: %w", commonerrors.ErrInvalidOption)
}

if err := ValidateNamespace(namespace); err != nil {
Expand All @@ -65,15 +64,15 @@ func ValidateModuleNamespace(namespace string) error {

func ValidateNamespace(namespace string) error {
if len(namespace) > namespaceMaxLength {
return fmt.Errorf("%w: opts.ModuleNamespace length must not exceed %q characters",
commonerrors.ErrInvalidOption,
namespaceMaxLength)
return fmt.Errorf("opts.ModuleNamespace length must not exceed %q characters: %w",
namespaceMaxLength,
commonerrors.ErrInvalidOption)
}

if matched, err := regexp.MatchString(namespacePattern, namespace); err != nil {
return fmt.Errorf("failed to evaluate regex pattern for module namespace: %w", err)
} else if !matched {
return fmt.Errorf("%w: namespace must match the required pattern, only small alphanumeric characters and hyphens",
return fmt.Errorf("namespace must match the required pattern, only small alphanumeric characters and hyphens: %w",
commonerrors.ErrInvalidOption)
}

Expand All @@ -83,11 +82,11 @@ func ValidateNamespace(namespace string) error {
func ValidateMapEntries(nameLinkMap map[string]string) error {
for name, link := range nameLinkMap {
if name == "" {
return fmt.Errorf("%w: name must not be empty", commonerrors.ErrInvalidOption)
return fmt.Errorf("name must not be empty: %w", commonerrors.ErrInvalidOption)
}

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

if err := ValidateIsValidHTTPSURL(link); err != nil {
Expand All @@ -100,16 +99,16 @@ func ValidateMapEntries(nameLinkMap map[string]string) error {

func ValidateIsValidHTTPSURL(input string) error {
if input == "" {
return fmt.Errorf("%w: must not be empty", commonerrors.ErrInvalidOption)
return fmt.Errorf("must not be empty: %w", commonerrors.ErrInvalidOption)
}

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

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

return nil
Expand All @@ -118,8 +117,8 @@ func ValidateIsValidHTTPSURL(input string) error {
func validateSemanticVersion(version string) error {
_, err := semver.StrictNewVersion(strings.TrimSpace(version))
if err != nil {
return fmt.Errorf("%w: opts.ModuleVersion failed to parse as semantic version: %w",
commonerrors.ErrInvalidOption, err)
return fmt.Errorf("opts.ModuleVersion failed to be parsed as semantic version: %w",
commonerrors.ErrInvalidOption)
}

return nil
Expand Down
2 changes: 1 addition & 1 deletion internal/service/componentarchive/componentarchive.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ type Service struct {

func NewService(fileSystem ArchiveFileSystem) (*Service, error) {
if fileSystem == nil {
return nil, fmt.Errorf("%w: fileSystem must not be nil", commonerrors.ErrInvalidArg)
return nil, fmt.Errorf("fileSystem must not be nil: %w", commonerrors.ErrInvalidArg)
}

return &Service{
Expand Down
2 changes: 1 addition & 1 deletion internal/service/componentdescriptor/gitsources.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ type GitSourcesService struct {

func NewGitSourcesService(gitService GitService) (*GitSourcesService, error) {
if gitService == nil {
return nil, fmt.Errorf("%w: gitService must not be nil", commonerrors.ErrInvalidArg)
return nil, fmt.Errorf("gitService must not be nil: %w", commonerrors.ErrInvalidArg)
}

return &GitSourcesService{
Expand Down
6 changes: 3 additions & 3 deletions internal/service/componentdescriptor/securityconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ type SecurityConfigService struct {

func NewSecurityConfigService(fileReader FileReader) (*SecurityConfigService, error) {
if fileReader == nil {
return nil, fmt.Errorf("%w: fileReader must not be nil", commonerrors.ErrInvalidArg)
return nil, fmt.Errorf("fileReader must not be nil: %w", commonerrors.ErrInvalidArg)
}

return &SecurityConfigService{
Expand Down Expand Up @@ -193,12 +193,12 @@ func appendLabelToAccessor(labeled compdesc.LabelsAccessor, key, value, baseKey
func GetImageNameAndTag(imageURL string) (string, string, error) {
imageTag := strings.Split(imageURL, ":")
if len(imageTag) != imageTagSlicesLength {
return "", "", fmt.Errorf("%w: , image URL: %s", errInvalidURL, imageURL)
return "", "", fmt.Errorf("image URL: %s: %w", imageURL, errInvalidURL)
}

imageName := strings.Split(imageTag[0], "/")
if len(imageName) == 0 {
return "", "", fmt.Errorf("%w: , image URL: %s", errInvalidURL, imageURL)
return "", "", fmt.Errorf("image URL: %s: %w", imageURL, errInvalidURL)
}

return imageName[len(imageName)-1], imageTag[len(imageTag)-1], nil
Expand Down
12 changes: 6 additions & 6 deletions internal/service/contentprovider/moduleconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ type ModuleConfigProvider struct {

func NewModuleConfigProvider(yamlConverter ObjectToYAMLConverter) (*ModuleConfigProvider, error) {
if yamlConverter == nil {
return nil, fmt.Errorf("%w: yamlConverter must not be nil", commonerrors.ErrInvalidArg)
return nil, fmt.Errorf("yamlConverter must not be nil: %w", commonerrors.ErrInvalidArg)
}

return &ModuleConfigProvider{
Expand Down Expand Up @@ -48,19 +48,19 @@ func (s *ModuleConfigProvider) getModuleConfig(args types.KeyValueArgs) ModuleCo

func (s *ModuleConfigProvider) validateArgs(args types.KeyValueArgs) error {
if args == nil {
return fmt.Errorf("%w: args must not be nil", ErrInvalidArg)
return fmt.Errorf("args must not be nil: %w", ErrInvalidArg)
}

if value, ok := args[ArgModuleName]; !ok {
return fmt.Errorf("%w: %s", ErrMissingArg, ArgModuleName)
return fmt.Errorf("%s: %w", ArgModuleName, ErrMissingArg)
} else if value == "" {
return fmt.Errorf("%w: %s must not be empty", ErrInvalidArg, ArgModuleName)
return fmt.Errorf("%s must not be empty: %w", ArgModuleName, ErrInvalidArg)
}

if value, ok := args[ArgModuleVersion]; !ok {
return fmt.Errorf("%w: %s", ErrMissingArg, ArgModuleVersion)
return fmt.Errorf("%s: %w", ArgModuleVersion, ErrMissingArg)
} else if value == "" {
return fmt.Errorf("%w: %s must not be empty", ErrInvalidArg, ArgModuleVersion)
return fmt.Errorf("%s must not be empty: %w", ArgModuleVersion, ErrInvalidArg)
}

return nil
Expand Down
8 changes: 4 additions & 4 deletions internal/service/contentprovider/securityconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ type SecurityConfig struct {

func NewSecurityConfig(yamlConverter ObjectToYAMLConverter) (*SecurityConfig, error) {
if yamlConverter == nil {
return nil, fmt.Errorf("%w: yamlConverter must not be nil", commonerrors.ErrInvalidArg)
return nil, fmt.Errorf("yamlConverter must not be nil: %w", commonerrors.ErrInvalidArg)
}

return &SecurityConfig{
Expand All @@ -31,16 +31,16 @@ func (s *SecurityConfig) GetDefaultContent(args types.KeyValueArgs) (string, err

func (s *SecurityConfig) validateArgs(args types.KeyValueArgs) error {
if args == nil {
return fmt.Errorf("%w: args must not be nil", ErrInvalidArg)
return fmt.Errorf("args must not be nil: %w", ErrInvalidArg)
}

value, ok := args[ArgModuleName]
if !ok {
return fmt.Errorf("%w: %s", ErrMissingArg, ArgModuleName)
return fmt.Errorf("%s: %w", ArgModuleName, ErrMissingArg)
}

if value == "" {
return fmt.Errorf("%w: %s must not be empty", ErrInvalidArg, ArgModuleName)
return fmt.Errorf("%s must not be empty: %w", ArgModuleName, ErrInvalidArg)
}

return nil
Expand Down
2 changes: 1 addition & 1 deletion internal/service/crdparser/crdparser.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ type Service struct {

func NewService(fileSystem FileSystem) (*Service, error) {
if fileSystem == nil {
return nil, fmt.Errorf("%w: fileSystem must not be nil", commonerrors.ErrInvalidArg)
return nil, fmt.Errorf("fileSystem must not be nil: %w", commonerrors.ErrInvalidArg)
}

return &Service{
Expand Down
30 changes: 15 additions & 15 deletions internal/service/create/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,43 +86,43 @@ func NewService(moduleConfigService ModuleConfigService,
fileSystem FileSystem,
) (*Service, error) {
if moduleConfigService == nil {
return nil, fmt.Errorf("%w: moduleConfigService must not be nil", commonerrors.ErrInvalidArg)
return nil, fmt.Errorf("moduleConfigService must not be nil: %w", commonerrors.ErrInvalidArg)
}

if gitSourcesService == nil {
return nil, fmt.Errorf("%w: gitSourcesService must not be nil", commonerrors.ErrInvalidArg)
return nil, fmt.Errorf("gitSourcesService must not be nil: %w", commonerrors.ErrInvalidArg)
}

if securityConfigService == nil {
return nil, fmt.Errorf("%w: securityConfigService must not be nil", commonerrors.ErrInvalidArg)
return nil, fmt.Errorf("securityConfigService must not be nil: %w", commonerrors.ErrInvalidArg)
}

if componentArchiveService == nil {
return nil, fmt.Errorf("%w: componentArchiveService must not be nil", commonerrors.ErrInvalidArg)
return nil, fmt.Errorf("componentArchiveService must not be nil: %w", commonerrors.ErrInvalidArg)
}

if registryService == nil {
return nil, fmt.Errorf("%w: registryService must not be nil", commonerrors.ErrInvalidArg)
return nil, fmt.Errorf("registryService must not be nil: %w", commonerrors.ErrInvalidArg)
}

if moduleTemplateService == nil {
return nil, fmt.Errorf("%w: moduleTemplateService must not be nil", commonerrors.ErrInvalidArg)
return nil, fmt.Errorf("moduleTemplateService must not be nil: %w", commonerrors.ErrInvalidArg)
}

if crdParserService == nil {
return nil, fmt.Errorf("%w: crdParserService must not be nil", commonerrors.ErrInvalidArg)
return nil, fmt.Errorf("crdParserService must not be nil: %w", commonerrors.ErrInvalidArg)
}

if manifestFileResolver == nil {
return nil, fmt.Errorf("%w: manifestFileResolver must not be nil", commonerrors.ErrInvalidArg)
return nil, fmt.Errorf("manifestFileResolver must not be nil: %w", commonerrors.ErrInvalidArg)
}

if defaultCRFileResolver == nil {
return nil, fmt.Errorf("%w: defaultCRFileResolver must not be nil", commonerrors.ErrInvalidArg)
return nil, fmt.Errorf("defaultCRFileResolver must not be nil: %w", commonerrors.ErrInvalidArg)
}

if fileSystem == nil {
return nil, fmt.Errorf("%w: fileSystem must not be nil", commonerrors.ErrInvalidArg)
return nil, fmt.Errorf("fileSystem must not be nil: %w", commonerrors.ErrInvalidArg)
}

return &Service{
Expand Down Expand Up @@ -219,27 +219,27 @@ func (s *Service) pushImgAndCreateTemplate(archive *comparch.ComponentArchive, m

if err := s.registryService.PushComponentVersion(archive, opts.Insecure, opts.Credentials,
opts.RegistryURL); err != nil {
return fmt.Errorf("%w: failed to push component archive", err)
return fmt.Errorf("failed to push component archive: %w", err)
}

componentVersionAccess, err := s.registryService.GetComponentVersion(archive, opts.Insecure, opts.Credentials, opts.RegistryURL)
if err != nil {
return fmt.Errorf("%w: failed to get component version", err)
return fmt.Errorf("failed to get component version: %w", err)
}

var crData []byte
if defaultCRFilePath != "" {
crData, err = s.fileSystem.ReadFile(defaultCRFilePath)
if err != nil {
return fmt.Errorf("%w: failed to get default CR data", err)
return fmt.Errorf("failed to get default CR data: %w", err)
}
}

opts.Out.Write("- Generating ModuleTemplate\n")
descriptor := componentVersionAccess.GetDescriptor()
if err = s.moduleTemplateService.GenerateModuleTemplate(moduleConfig, descriptor,
crData, isCRDClusterScoped, opts.TemplateOutput); err != nil {
return fmt.Errorf("%w: failed to generate module template", err)
return fmt.Errorf("failed to generate module template: %w", err)
}
return nil
}
Expand All @@ -252,7 +252,7 @@ func (s *Service) configureSecScannerConf(descriptor *compdesc.ComponentDescript
}

if err = s.securityConfigService.AppendSecurityScanConfig(descriptor, *securityConfig); err != nil {
return fmt.Errorf("%w: failed to append security scan config", err)
return fmt.Errorf("failed to append security scan config: %w", err)
}
return nil
}
12 changes: 6 additions & 6 deletions internal/service/create/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,28 +21,28 @@ type Options struct {

func (opts Options) Validate() error {
if opts.Out == nil {
return fmt.Errorf("%w: opts.Out must not be nil", commonerrors.ErrInvalidOption)
return fmt.Errorf("opts.Out must not be nil: %w", commonerrors.ErrInvalidOption)
}

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

if opts.Credentials != "" {
matched, err := regexp.MatchString("(.+):(.+)", opts.Credentials)
if err != nil {
return fmt.Errorf("%w: opts.Credentials could not be parsed: %w", commonerrors.ErrInvalidOption, err)
return fmt.Errorf("opts.Credentials could not be parsed: %w: %w", commonerrors.ErrInvalidOption, err)
} else if !matched {
return fmt.Errorf("%w: opts.Credentials is in invalid format", commonerrors.ErrInvalidOption)
return fmt.Errorf("opts.Credentials is in invalid format: %w", commonerrors.ErrInvalidOption)
}
}

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

if opts.RegistryURL != "" && !strings.HasPrefix(opts.RegistryURL, "http") {
return fmt.Errorf("%w: opts.RegistryURL does not start with http(s)", commonerrors.ErrInvalidOption)
return fmt.Errorf("opts.RegistryURL does not start with http(s): %w", commonerrors.ErrInvalidOption)
}

return nil
Expand Down
8 changes: 4 additions & 4 deletions internal/service/filegenerator/filegenerator.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ type Service struct {

func NewService(kind string, fileSystem FileWriter, defaultContentProvider DefaultContentProvider) (*Service, error) {
if kind == "" {
return nil, fmt.Errorf("%w: kind must not be empty", commonerrors.ErrInvalidArg)
return nil, fmt.Errorf("kind must not be empty: %w", commonerrors.ErrInvalidArg)
}

if fileSystem == nil {
return nil, fmt.Errorf("%w: fileSystem must not be nil", commonerrors.ErrInvalidArg)
return nil, fmt.Errorf("fileSystem must not be nil: %w", commonerrors.ErrInvalidArg)
}

if defaultContentProvider == nil {
return nil, fmt.Errorf("%w: defaultContentProvider must not be nil", commonerrors.ErrInvalidArg)
return nil, fmt.Errorf("defaultContentProvider must not be nil: %w", commonerrors.ErrInvalidArg)
}

return &Service{
Expand All @@ -60,7 +60,7 @@ func (s *Service) GenerateFile(out iotools.Out, path string, args types.KeyValue

func (s *Service) writeFile(content, path string) error {
if err := s.fileWriter.WriteFile(path, content); err != nil {
return fmt.Errorf("%w %s: %w", ErrWritingFile, path, err)
return fmt.Errorf("file path: %s, %w: %w", path, err, ErrWritingFile)
}

return nil
Expand Down
Loading

0 comments on commit f7b9155

Please sign in to comment.