Skip to content

Commit

Permalink
Open sourcing V1 types.
Browse files Browse the repository at this point in the history
  • Loading branch information
andream16 committed Dec 19, 2024
1 parent 03e68e6 commit 6b00099
Show file tree
Hide file tree
Showing 6 changed files with 524 additions and 0 deletions.
38 changes: 38 additions & 0 deletions smithyctl/types/v1/component.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package v1

type (
// ComponentType represents all the types of components that Smithy supports.
// ENUM(unknown, target, scanner, enricher, filter, reporter)
ComponentType string

// Component is a binary or a script that can be used in the context of a
// workflow to generate some useful result.
Component struct {
// Description describes what the component will do.
Description string
// Name is the component name.
Name string
// Parameters is the list of parameters to be supplied to the component.
Parameters []Parameter
// Steps is the list of steps to be supplied to the component.
Steps []Step
// Type represents the component type.
Type ComponentType
}

// Step represents an executing step inside a Component.
Step struct {
// Args is the list of arguments supplied to a component.
Args []string
// EnvVars is the set of environment variables key:val supplied to a component.
EnvVars map[string]string
// Name is the step name.
Name string
// Executable is the path to the entrypoint to run the component.
Executable string
// Images is the docker image to be run for this component.
Image string
// Script will be deprecated after rewriting all components.
Script string
}
)
95 changes: 95 additions & 0 deletions smithyctl/types/v1/component_enum.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

142 changes: 142 additions & 0 deletions smithyctl/types/v1/parameter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
package v1

import (
"encoding/json"
"errors"
"fmt"
)

var (
// ErrMismatchedExpectedType is returned when the type field of a parameter
// is not the same as the actual type of the value of a parameter.
ErrMismatchedExpectedType = errors.New("stated parameter type different than actual value type")
// ErrUnknownParameterType is returned when the type of field parameter
// is not one of the expected values.
ErrUnknownParameterType = errors.New("unknown parameter type")
)

type (
// ParameterType represents the type of parameter that can be parsed by the
// system.
// ENUM(string, const:string, list:string)
ParameterType string

// Parameter is a struct whose value must be of the type as it's defined in the
// Type field. Due to the fact that this value is expected to be communicated
// to external clients via JSON, which doesn't support rich types, we need to
// communicate the expected value type via an enum string. Given the Golang
// type system, there is no way to enforce the type restrictions via an
// interface, so do all the type checks when marshaling/unmarshalling the JSON
// bytes, since this type will constantly be subject to such transformations.
Parameter struct {
// Name is the name of the parameter.
Name string
// Type is the parameter type.
Type ParameterType
// Value is the JSON encoded/decoded value of the parameter which is decoded based its Type.
Value any
}
)

// UnmarshalJSON unmarshal JSON bytes into a Parameter object.
func (p *Parameter) UnmarshalJSON(b []byte) error {
partialParameter := &struct {
Name string
Type ParameterType
}{}

var err error
if err = json.Unmarshal(b, partialParameter); err != nil {
return err
}

p.Name = partialParameter.Name
p.Type = partialParameter.Type

switch partialParameter.Type {
case ParameterTypeString, ParameterTypeConststring:
parameterValueStrPtr := &struct{ Value *string }{}
if err = json.Unmarshal(b, parameterValueStrPtr); err == nil {
p.Value = parameterValueStrPtr.Value
break
}
parameterValueStr := &struct{ Value string }{}
err = json.Unmarshal(b, parameterValueStr)
p.Value = parameterValueStr.Value
case ParameterTypeListstring:
parameterValue := &struct{ Value []string }{}
err = json.Unmarshal(b, parameterValue)
p.Value = parameterValue.Value
default:
err = ErrUnknownParameterType
}
if err != nil {
return fmt.Errorf("parameter.Name: %s, parameter.Type: %s: %w", partialParameter.Name, partialParameter.Type, err)
}

return nil
}

// MarshalJSON marshals the Parameter into JSON bytes.
func (p *Parameter) MarshalJSON() ([]byte, error) {
if err := p.Validate(); err != nil {
return nil, err
}

b, err := json.Marshal(struct {
Name string
Type ParameterType
Value any
}{
Name: p.Name,
Type: p.Type,
Value: p.Value,
})
if err != nil {
return nil, fmt.Errorf("could not json marshal value: %w", err)
}

return b, nil
}

// Validate checks all the fields of the parameter to make sure that the type
// specified matches the actual type of the value
func (p *Parameter) Validate() error {
_, err := ParseParameterType(string(p.Type))
if err != nil {
return fmt.Errorf("could not parse parameter '%s' with type: '%s': %w", p.Name, p.Type, err)
}

if p.Value == nil {
return nil
}

var correctType bool
switch p.Type {
case ParameterTypeString, ParameterTypeConststring:
_, correctType = p.Value.(*string)
if !correctType {
_, correctType = p.Value.(string)
}
case ParameterTypeListstring:
_, correctType = p.Value.([]string)
default:
err = ErrUnknownParameterType
}

if !correctType {
err = ErrMismatchedExpectedType
}

if err != nil {
return fmt.Errorf(
"invalid parameter '%s' with type '%s' and value '%v': %w",
p.Name,
p.Type,
p.Value,
err,
)
}

return nil
}
49 changes: 49 additions & 0 deletions smithyctl/types/v1/parameter_enum.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 6b00099

Please sign in to comment.