Skip to content

Commit

Permalink
Enhance Scenario Validation and Error Handling
Browse files Browse the repository at this point in the history
This commit enhances scenario validation and error handling across the `localstorage.go` and `scenario.go` files. The key updates include:

- Introduced validation checks for `scenarioParams` within the `ReadCnappGoatConfig`, `updateScenariosFromFolder`, and `createScenario` methods in `localstorage.go`.
- Enhanced error messages in the `scenario.go` file for improved clarity.
- Refactored the panic error handling in the `Module` and `Platform` string representation functions to return an empty string instead.
- Improved the unmarshalling logic for runtime options.
- Added a comprehensive `IsValid` function for scenario parameters to ensure all necessary fields are present and correctly formatted.
  • Loading branch information
noamsdahan committed Aug 21, 2023
1 parent d277a70 commit 600b371
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 4 deletions.
9 changes: 9 additions & 0 deletions localstorage.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,9 @@ func (l *LocalStorage) ReadCnappGoatConfig(scenario *Scenario) (map[string]strin
if err = yaml.Unmarshal(data, &cnappGoatConfig); err != nil {
return nil, fmt.Errorf("failed to parse Pulumi.yaml: %w", err)
}
if err := cnappGoatConfig.ScenarioParams.IsValid(); err != nil {
return nil, fmt.Errorf("scenarioParams field is empty for scenario %v", scenario.Name)
}

return cnappGoatConfig.ScenarioParams.Config, nil
}
Expand Down Expand Up @@ -179,6 +182,9 @@ func (l *LocalStorage) updateScenariosFromFolder(scenariosFullPath string) (map[
return nil, fmt.Errorf("scenario folder does not exist, cannot perform UpdateScenarioFolder: %s", scenariosFullPath)
}
scenariosFromScenarioDir, err := l.loadScenarios(scenariosFullPath)
if err != nil {
return nil, fmt.Errorf("unable to load scenarios from scenario directory: %w", err)
}
var scenariosFromWorkDir map[string]*Scenario
if l.WorkingDirectoryExists() {
scenariosFromWorkDir, err = l.loadScenarios(l.WorkingDir)
Expand Down Expand Up @@ -288,6 +294,9 @@ func (l *LocalStorage) createScenario(path string) (*Scenario, error) {
if err = yaml.Unmarshal(data, &scenario); err != nil {
return nil, fmt.Errorf("failed to parse Pulumi.yaml: %w", err)
}
if err = scenario.ScenarioParams.IsValid(); err != nil {
return nil, fmt.Errorf("scenarioParams field is empty for scenario %v", scenario.Name)
}

scenario.SrcDir = filepath.Dir(path)

Expand Down
59 changes: 55 additions & 4 deletions scenario.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package cnappgoat

import (
"errors"
"fmt"
"strings"

"gopkg.in/yaml.v3"
Expand Down Expand Up @@ -83,7 +84,7 @@ func (m Module) String() string {
case IAC:
return "IAC"
default:
panic("CNAPPgoat module name not formatted")
return ""
}
}

Expand All @@ -110,7 +111,7 @@ func (p Platform) String() string {
case GCP:
return "GCP"
default:
panic("platform name not formatted")
return ""
}
}

Expand Down Expand Up @@ -143,7 +144,9 @@ func (r *runtime) UnmarshalYAML(unmarshal func(interface{}) error) error {
if name, ok := runtimeObj["name"].(string); ok {
r.Name = name
}
r.Options = runtimeObj
if options, ok := runtimeObj["options"].(map[string]interface{}); ok {
r.Options = options
}

return nil
}
Expand All @@ -169,7 +172,7 @@ func ModuleFromString(name string) (Module, error) {
case strings.ToLower(IAC.String()):
return IAC, nil
default:
return "", errors.New("unknown CNAPPgoat module name: " + name)
return "", errors.New("unknown module name: " + name)
}
}

Expand Down Expand Up @@ -200,3 +203,51 @@ func StateFromString(state string) (State, error) {
return State{}, errors.New("unknown state: " + state)
}
}

func (p scenarioParams) IsValid() error {
if p.Module == "" && p.Platform == "" && p.ID == "" && p.FriendlyName == "" && p.Description == "" && p.ScenarioType == "" {
return errors.New("scenarioParams is empty, yaml is missing value cnappgoat-params")
}
if p.Module == "" {
return errors.New("module is required")
}
if p.Platform == "" {
return errors.New("platform is required")
}
if p.ID == "" {
return errors.New("id is required")
}
if len(strings.Split(p.ID, "-")) < 3 {
return fmt.Errorf("id must be in the format of <module>-<platform>-<id>, id is: %s", p.ID)
}
// module must be valid
if _, err := ModuleFromString(string(p.Module)); err != nil {
return err
}
// platform must be valid
if _, err := PlatformFromString(string(p.Platform)); err != nil {
return err
}
if !p.Module.Equals(Module(strings.Split(p.ID, "-")[0])) {
return fmt.Errorf("id must start with matching module name: %s, id is: %v", p.Module, p.ID)
}
if !p.Platform.Equals(Platform(strings.Split(p.ID, "-")[1])) {
return fmt.Errorf("id must include matching platform name, id is: %v", p.ID)
}
if p.FriendlyName == "" {
return errors.New("friendlyName is required")
}
if p.Description == "" {
return errors.New("description is required")
}
if p.ScenarioType == "" {
return errors.New("scenarioType is required")
}
if _, err := ModuleFromString(string(p.Module)); err != nil {
return err
}
if _, err := PlatformFromString(string(p.Platform)); err != nil {
return err
}
return nil
}

0 comments on commit 600b371

Please sign in to comment.