package config import ( `errors` `fmt` `reflect` `strings` ) var err error // TODO: Match block validation // Have I mentioned how dumb golang is yet? The following methods share 90% of the same code, // but ironically delegating that to a separate function is going to be even more of a PITA for now // than just maintaining two separate methods. // How dumb. // Validate validates the actual struct of an SshdConf itself, ensuring that certain list fields contain // valid item(s). It collects all found issues in allErr. func (c *SshdConf) Validate() (validConf bool, allErr []error) { // Set the default as true. // We set it on false on first failed validation and keep going. validConf = true fields := reflect.TypeOf(c) values := reflect.ValueOf(c) for i := 0; i < fields.NumField(); i++ { field := fields.Field(i) value := values.Field(i) var validField bool n := field.Name single, isSingle := validSshdSingleVals[n] multi, isMulti := validSshdMultiVals[n] if isSingle { v := value.String() for _, x := range single { if v == x { validField = true break } } if !validField { validConf = false e := fmt.Sprintf( "field %v: value %v is not allowed; must be ONE of: %v", n, v, single, ) allErr = append(allErr, errors.New(e)) } } else if isMulti { // These are all []strings if the field name is in validSshdMultiVals. // But golang is still dumb and has no way of serializing directly, so here comes the hackery. v, ok := value.Interface().([]string) if !ok { validConf = false e := fmt.Sprintf( "field %v: value %v was not able to be parsed as a []string", n, v, ) allErr = append(allErr, errors.New(e)) } var invalidSlice []string for _, vStr := range v { validItem := false for _, strip := range sshdStripPre { if n == strip { for _, c := range []string{"+", "-", "^"} { vStr = strings.TrimPrefix(vStr, c) } } } for _, x := range multi { if vStr == x { validItem = true } } if !validItem { invalidSlice = append(invalidSlice, vStr) } } for _, x := range invalidSlice { e := fmt.Sprintf( "field %v: value item %v is not valid; it must be one or more of %v", n, x, multi, ) allErr = append(allErr, errors.New(e)) } } } return validConf, allErr } // Validate validates the actual struct of an SshConf itself, ensuring that certain list fields contain // valid item(s). It collects all found issues in allErr. func (c *SshConf) Validate() (validConf bool, allErr []error) { // Set the default as true. // We set it on false on first failed validation and keep going. validConf = true fields := reflect.TypeOf(c) values := reflect.ValueOf(c) for i := 0; i < fields.NumField(); i++ { field := fields.Field(i) value := values.Field(i) var validField bool n := field.Name single, isSingle := validSshSingleVals[n] multi, isMulti := validSshMultiVals[n] if isSingle { v := value.String() for _, x := range single { if v == x { validField = true break } } if !validField { validConf = false e := fmt.Sprintf( "field %v: value %v is not allowed; must be ONE of: %v", n, v, single, ) allErr = append(allErr, errors.New(e)) } } else if isMulti { // These are all []strings if the field name is in validSshMultiVals. // But golang is still dumb and has no way of serializing directly, so here comes the hackery. v, ok := value.Interface().([]string) if !ok { validConf = false e := fmt.Sprintf( "field %v: value %v was not able to be parsed as a []string", n, v, ) allErr = append(allErr, errors.New(e)) } var invalidSlice []string for _, vStr := range v { validItem := false for _, strip := range sshStripPre { if n == strip { for _, c := range []string{"+", "-", "^"} { vStr = strings.TrimPrefix(vStr, c) } } } for _, x := range multi { if vStr == x { validItem = true } } if !validItem { invalidSlice = append(invalidSlice, vStr) } } for _, x := range invalidSlice { e := fmt.Sprintf( "field %v: value item %v is not valid; it must be one or more of %v", n, x, multi, ) allErr = append(allErr, errors.New(e)) } } } return validConf, allErr }