Skip to content

Commit

Permalink
feat(decl/loader): replace go-yaml/yaml with goccy/go-yaml
Browse files Browse the repository at this point in the history
Replace go-yaml/yaml as it is practically not maintained anymore
and requires additional code to be written for marshalling
structures specifying 'inline' on any on their fields.

Signed-off-by: Leonardo Di Giovanna <[email protected]>
Co-authored-by: Aldo Lacuku <[email protected]>
  • Loading branch information
ekoops and alacuku committed Dec 8, 2024
1 parent 5161671 commit bd06558
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 117 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ require (
github.com/go-playground/universal-translator v0.18.1
github.com/go-playground/validator/v10 v10.22.1
github.com/go-viper/mapstructure/v2 v2.2.1
github.com/goccy/go-yaml v1.15.7
github.com/google/uuid v1.6.0
github.com/iancoleman/strcase v0.3.0
github.com/mitchellh/go-homedir v1.1.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1v
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/goccy/go-yaml v1.15.7 h1:L7XuKpd/A66X4w/dlk08lVfiIADdy79a1AzRoIefC98=
github.com/goccy/go-yaml v1.15.7/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
Expand Down
105 changes: 4 additions & 101 deletions pkg/test/loader/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import (
"regexp"

"github.com/go-viper/mapstructure/v2"
"gopkg.in/yaml.v3"
"github.com/goccy/go-yaml"

"github.com/falcosecurity/event-generator/pkg/test/loader/schema"
)
Expand All @@ -39,6 +39,7 @@ func New() *Loader {
func (l *Loader) Load(r io.Reader) (*Description, error) {
// Decode YAML description into generic map[string]any.
var rawDesc map[string]any

if err := yaml.NewDecoder(r).Decode(&rawDesc); err != nil {
return nil, fmt.Errorf("error decoding YAML description: %w", err)
}
Expand Down Expand Up @@ -441,103 +442,7 @@ type ProcessContext struct {
type TestResource struct {
Type TestResourceType `yaml:"type" mapstructure:"type"`
Name string `yaml:"name" mapstructure:"name"`
Spec any `yaml:"-" mapstructure:"-"`
}

// MarshalYAML returns an inner representation of the TestResource instance that is used, in place of the instance, to
// marshal the content.
// TODO: this method should be implemented with a pointer receiver but unfortunately, the yaml.v3 library is only able
// to call it if it is implemented with a value receiver. Uniform the receivers once the library is replaced.
func (r TestResource) MarshalYAML() (any, error) {
switch resourceType := r.Type; resourceType {
case TestResourceTypeClientServer:
return struct {
Type TestResourceType `yaml:"type"`
Name string `yaml:"name"`
Spec *TestResourceClientServerSpec `yaml:"spec,inline"`
}{Type: resourceType, Name: r.Name, Spec: r.Spec.(*TestResourceClientServerSpec)}, nil
case TestResourceTypeFD:
return r.marshalFD()
case TestResourceTypeProcess:
return struct {
Type TestResourceType `yaml:"type"`
Name string `yaml:"name"`
Spec *TestResourceProcessSpec `yaml:"spec,inline"`
}{Type: resourceType, Name: r.Name, Spec: r.Spec.(*TestResourceProcessSpec)}, nil
default:
return nil, fmt.Errorf("unknown test resource type %q", resourceType)
}
}

// marshalFD returns an inner representation of the fd test resource instance that is used, in place of the instance, to
// marshal the content.
// TODO: this function contains a lot of repetitions for TestResource common fields. However, it is not possible to
// provide an addition MarshalYAML method for TestResourceFDSpec, as it will not be called by the library if the Spec
// field specify "inline" (as it should be in our case). Take care of replace this with a more elegant solution once
// yaml.v3 is replaced.
func (r *TestResource) marshalFD() (any, error) {
spec := r.Spec.(*TestResourceFDSpec)
subSpec := spec.Spec
switch subtype := spec.Subtype; subtype {
case TestResourceFDSubtypeFile:
return struct {
Type TestResourceType `yaml:"type"`
Name string `yaml:"name"`
Subtype TestResourceFDSubtype `yaml:"subtype"`
Spec *TestResourceFDFileSpec `yaml:"subspec,inline"`
}{Type: r.Type, Name: r.Name, Subtype: subtype, Spec: subSpec.(*TestResourceFDFileSpec)}, nil
case TestResourceFDSubtypeDirectory:
return struct {
Type TestResourceType `yaml:"type"`
Name string `yaml:"name"`
Subtype TestResourceFDSubtype `yaml:"subtype"`
Spec *TestResourceFDDirectorySpec `yaml:"subspec,inline"`
}{Type: r.Type, Name: r.Name, Subtype: subtype, Spec: subSpec.(*TestResourceFDDirectorySpec)}, nil
case TestResourceFDSubtypePipe:
return struct {
Type TestResourceType `yaml:"type"`
Name string `yaml:"name"`
Subtype TestResourceFDSubtype `yaml:"subtype"`
Spec *TestResourceFDPipeSpec `yaml:"subspec,inline"`
}{Type: r.Type, Name: r.Name, Subtype: subtype, Spec: subSpec.(*TestResourceFDPipeSpec)}, nil
case TestResourceFDSubtypeEvent:
return struct {
Type TestResourceType `yaml:"type"`
Name string `yaml:"name"`
Subtype TestResourceFDSubtype `yaml:"subtype"`
Spec *TestResourceFDEventSpec `yaml:"subspec,inline"`
}{Type: r.Type, Name: r.Name, Subtype: subtype, Spec: subSpec.(*TestResourceFDEventSpec)}, nil
case TestResourceFDSubtypeSignal:
return struct {
Type TestResourceType `yaml:"type"`
Name string `yaml:"name"`
Subtype TestResourceFDSubtype `yaml:"subtype"`
Spec *TestResourceFDSignalSpec `yaml:"subspec,inline"`
}{Type: r.Type, Name: r.Name, Subtype: subtype, Spec: subSpec.(*TestResourceFDSignalSpec)}, nil
case TestResourceFDSubtypeEpoll:
return struct {
Type TestResourceType `yaml:"type"`
Name string `yaml:"name"`
Subtype TestResourceFDSubtype `yaml:"subtype"`
Spec *TestResourceFDEpollSpec `yaml:"subspec,inline"`
}{Type: r.Type, Name: r.Name, Subtype: subtype, Spec: subSpec.(*TestResourceFDEpollSpec)}, nil
case TestResourceFDSubtypeInotify:
return struct {
Type TestResourceType `yaml:"type"`
Name string `yaml:"name"`
Subtype TestResourceFDSubtype `yaml:"subtype"`
Spec *TestResourceFDInotifySpec `yaml:"subspec,inline"`
}{Type: r.Type, Name: r.Name, Subtype: subtype, Spec: subSpec.(*TestResourceFDInotifySpec)}, nil
case TestResourceFDSubtypeMem:
return struct {
Type TestResourceType `yaml:"type"`
Name string `yaml:"name"`
Subtype TestResourceFDSubtype `yaml:"subtype"`
Spec *TestResourceFDMemSpec `yaml:"subspec,inline"`
}{Type: r.Type, Name: r.Name, Subtype: subtype, Spec: subSpec.(*TestResourceFDMemSpec)}, nil
default:
return nil, fmt.Errorf("unknown fd test resource subtype %q", subtype)
}
Spec any `yaml:"spec,inline" mapstructure:"-"`
}

// TestResourceType is the type of test resource.
Expand Down Expand Up @@ -583,7 +488,7 @@ const (
// TestResourceFDSpec describes an fd test resource.
type TestResourceFDSpec struct {
Subtype TestResourceFDSubtype `yaml:"subtype" mapstructure:"subtype"`
Spec any `yaml:"-" mapstructure:"-"`
Spec any `yaml:"spec,inline" mapstructure:"-"`
}

// TestResourceFDSubtype is the subtype of fd test resource.
Expand Down Expand Up @@ -666,8 +571,6 @@ type TestStep struct {

// MarshalYAML returns an inner representation of the TestStep instance that is used, in place of the instance, to
// marshal the content.
// TODO: this method should be implemented with a pointer receiver but unfortunately, the yaml.v3 library is only able
// to call it if it is implemented with a value receiver. Uniform the receivers once the library is replaced.
func (s TestStep) MarshalYAML() (any, error) {
switch stepType := s.Type; stepType {
case TestStepTypeSyscall:
Expand Down
2 changes: 1 addition & 1 deletion pkg/test/step/syscall/base/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ func setArgFieldValues(argFieldContainer reflect.Value, rawArgs map[string]any)
for rawArg, rawArgValue := range rawArgs {
argField, err := field.ByName(rawArg, argFieldContainer)
if err != nil {
return nil, fmt.Errorf("error getting %q argument field: %w", rawArg, err)
return nil, fmt.Errorf("error setting %q argument field: %w", rawArg, err)
}

argFieldBoundArgs, err := setArgFieldValue(argField, rawArgValue)
Expand Down
32 changes: 17 additions & 15 deletions pkg/test/step/syscall/base/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,24 @@ import (
)

var (
errMustBePositive = fmt.Errorf("value must be positive")
errMustBeString = fmt.Errorf("value must be a string")
errCannotConvertToInt = fmt.Errorf("cannot convert to int")
errUnexpectedNullByte = fmt.Errorf("unexpected NULL byte")
errPortOutOfRange = fmt.Errorf("port number out of range (0, 65535]")
errMustBeStringOrInt = fmt.Errorf("value must be a string or an int")
errMustBeMap = fmt.Errorf("value must be a map")
errMustBePositive = fmt.Errorf("value must be positive")
errMustBeString = fmt.Errorf("value must be a string")
errCannotConvertToInt = fmt.Errorf("cannot convert to int")
errUnexpectedNullByte = fmt.Errorf("unexpected NULL byte")
errPortOutOfRange = fmt.Errorf("port number out of range (0, 65535]")
errMustBeStringOrUint64 = fmt.Errorf("value must be a string or an uint64")
errMustBeMap = fmt.Errorf("value must be a map")
)

func parseInt64(value any) (int64, error) {
v := reflect.ValueOf(value)
if !v.CanInt() {
var n int64
typ := reflect.TypeOf(n)
if !v.CanConvert(typ) {
return 0, errCannotConvertToInt
}

return v.Int(), nil
return v.Convert(typ).Int(), nil
}

func parseString(value any) (string, error) {
Expand Down Expand Up @@ -133,22 +135,22 @@ func parseSocketAddress(value any) (unix.Sockaddr, error) {

func parseSingleValue(value any, valuesMap map[string]int) (int, error) {
switch value := value.(type) {
case int:
return value, nil
case uint64:
return int(value), nil //nolint:gosec // Disable G115
case string:
if parsedValue, ok := valuesMap[value]; ok {
return parsedValue, nil
}
return strconv.Atoi(value)
default:
return 0, errMustBeStringOrInt
return 0, errMustBeStringOrUint64
}
}

func parseFlags(value any, flagsMap map[string]int) (int, error) {
switch value := value.(type) {
case int:
return value, nil
case uint64:
return int(value), nil //nolint:gosec // Disable G115
case string:
if flags, err := strconv.Atoi(value); err == nil {
return flags, nil
Expand All @@ -165,7 +167,7 @@ func parseFlags(value any, flagsMap map[string]int) (int, error) {

return flags, nil
default:
return 0, errMustBeStringOrInt
return 0, errMustBeStringOrUint64
}
}

Expand Down

0 comments on commit bd06558

Please sign in to comment.