diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e2c66da..2dc560a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ ## Changelog +### [13.20.2](https://kaos.sh/ek/13.20.2) + +- **`[knf/validators/time]`** Added timezone validator +- **`[timeutil]`** Added method `DurationAs` +- **`[timeutil]`** Method `Period.DurationIn` renamed to `Period.DurationAs` +- **`[knf/validators]`** Code refactoring +- **`[timeutil]`** Code refactoring + ### [13.20.1](https://kaos.sh/ek/13.20.1) - **`[timeutil]`** Added method `Period.Stringf` diff --git a/knf/validators/cron/validators.go b/knf/validators/cron/validators.go index 54aaa20a..18a65f3c 100644 --- a/knf/validators/cron/validators.go +++ b/knf/validators/cron/validators.go @@ -18,20 +18,21 @@ import ( // ////////////////////////////////////////////////////////////////////////////////// // var ( - // Expression returns an error if config property contains invalid cron expression + // Expression returns an error if configuration property contains invalid cron + // expression Expression = validateCronExpression ) // ////////////////////////////////////////////////////////////////////////////////// // func validateCronExpression(config knf.IConfig, prop string, value any) error { - confVal := config.GetS(prop) + v := config.GetS(prop) - if confVal == "" { + if v == "" { return nil } - _, err := cron.Parse(confVal) + _, err := cron.Parse(v) if err != nil { return fmt.Errorf("Property %s contains invalid cron expression: %w", prop, err) diff --git a/knf/validators/cron/validators_test.go b/knf/validators/cron/validators_test.go index 5c31e5e4..15aa8bb0 100644 --- a/knf/validators/cron/validators_test.go +++ b/knf/validators/cron/validators_test.go @@ -51,7 +51,7 @@ func (s *ValidatorSuite) TestCronValidator(c *check.C) { err = knf.Global(configFile) c.Assert(err, check.IsNil) - errs := knf.Validate([]*knf.Validator{ + errs := knf.Validate(knf.Validators{ {"cron:test1", Expression, nil}, {"cron:test2", Expression, nil}, {"cron:test3", Expression, nil}, @@ -60,7 +60,7 @@ func (s *ValidatorSuite) TestCronValidator(c *check.C) { c.Assert(errs, check.HasLen, 0) - errs = knf.Validate([]*knf.Validator{ + errs = knf.Validate(knf.Validators{ {"cron:test5", Expression, nil}, }) diff --git a/knf/validators/fs/validators.go b/knf/validators/fs/validators.go index b4a1e26f..25f17db4 100644 --- a/knf/validators/fs/validators.go +++ b/knf/validators/fs/validators.go @@ -21,33 +21,33 @@ import ( // ////////////////////////////////////////////////////////////////////////////////// // var ( - // Perms returns error if config property contains path to object with given + // Perms returns error if configuration property contains path to object with given // permissions Perms = validatePerms - // Owner returns error if config property contains path to object with other + // Owner returns error if configuration property contains path to object with other // owner Owner = validateOwner - // OwnerGroup returns error if config property contains path to object with other - // owner group + // OwnerGroup returns error if configuration property contains path to object with + // other owner group OwnerGroup = validateOwnerGroup - // FileMode returns error if config property contains path to object with other - // file mode + // FileMode returns error if configuration property contains path to object with + // other file mode FileMode = validateFileMode - // MatchPattern returns error if config property contains path which doesn't match - // given shell pattern + // MatchPattern returns error if configuration property contains path which doesn't + // match given shell pattern MatchPattern = validateMatchPattern ) // ////////////////////////////////////////////////////////////////////////////////// // func validatePerms(config knf.IConfig, prop string, value any) error { - target := config.GetS(prop) + v := config.GetS(prop) - if target == "" { + if v == "" { return nil } @@ -65,7 +65,7 @@ func validatePerms(config knf.IConfig, prop string, value any) error { return getValidatorInputError("Perms", prop, value) } - if !fsutil.CheckPerms(perms, target) { + if !fsutil.CheckPerms(perms, v) { switch perms { case "F": return fmt.Errorf("Property %s must be path to file", prop) @@ -94,9 +94,9 @@ func validatePerms(config knf.IConfig, prop string, value any) error { } func validateOwner(config knf.IConfig, prop string, value any) error { - target := config.GetS(prop) + v := config.GetS(prop) - if target == "" { + if v == "" { return nil } @@ -120,23 +120,23 @@ func validateOwner(config knf.IConfig, prop string, value any) error { return fmt.Errorf("Can't find user %q on system", owner) } - uid, _, err := fsutil.GetOwner(target) + uid, _, err := fsutil.GetOwner(v) if err != nil { - return fmt.Errorf("Can't get owner for %q", target) + return fmt.Errorf("Can't get owner for %q", v) } if user.UID != uid { - return fmt.Errorf("User %s must be owner of %s", owner, target) + return fmt.Errorf("User %s must be owner of %s", owner, v) } return nil } func validateOwnerGroup(config knf.IConfig, prop string, value any) error { - target := config.GetS(prop) + v := config.GetS(prop) - if target == "" { + if v == "" { return nil } @@ -160,23 +160,23 @@ func validateOwnerGroup(config knf.IConfig, prop string, value any) error { return fmt.Errorf("Can't find group %q on system", ownerGroup) } - _, gid, err := fsutil.GetOwner(target) + _, gid, err := fsutil.GetOwner(v) if err != nil { - return fmt.Errorf("Can't get owner group for %q", target) + return fmt.Errorf("Can't get owner group for %q", v) } if group.GID != gid { - return fmt.Errorf("Group %s must be owner of %s", ownerGroup, target) + return fmt.Errorf("Group %s must be owner of %s", ownerGroup, v) } return nil } func validateFileMode(config knf.IConfig, prop string, value any) error { - target := config.GetS(prop) + v := config.GetS(prop) - if target == "" { + if v == "" { return nil } @@ -194,24 +194,24 @@ func validateFileMode(config knf.IConfig, prop string, value any) error { return getValidatorInputError("FileMode", prop, value) } - targetPerms := fsutil.GetMode(target) + targetPerms := fsutil.GetMode(v) if targetPerms == 0 { - return fmt.Errorf("Can't get mode for %q", target) + return fmt.Errorf("Can't get mode for %q", v) } if mode != targetPerms { return fmt.Errorf( - "%s has different mode (%o != %o)", target, targetPerms, mode) + "%s has different mode (%o != %o)", v, targetPerms, mode) } return nil } func validateMatchPattern(config knf.IConfig, prop string, value any) error { - target := config.GetS(prop) + v := config.GetS(prop) - if target == "" { + if v == "" { return nil } @@ -229,7 +229,7 @@ func validateMatchPattern(config knf.IConfig, prop string, value any) error { return getValidatorInputError("MatchPattern", prop, value) } - isMatch, err := path.Match(pattern, target) + isMatch, err := path.Match(pattern, v) if err != nil { return fmt.Errorf("Can't parse shell pattern: %v", err) diff --git a/knf/validators/fs/validators_test.go b/knf/validators/fs/validators_test.go index fda9e02e..a70498d4 100644 --- a/knf/validators/fs/validators_test.go +++ b/knf/validators/fs/validators_test.go @@ -48,7 +48,7 @@ func (s *ValidatorSuite) TestPermsValidator(c *C) { err := knf.Global(configFile) c.Assert(err, IsNil) - errs := knf.Validate([]*knf.Validator{ + errs := knf.Validate(knf.Validators{ {"test:test0", Perms, "FR"}, {"test:test1", Perms, "FR"}, }) @@ -60,7 +60,7 @@ func (s *ValidatorSuite) TestPermsValidator(c *C) { err = knf.Global(configFile) c.Assert(err, IsNil) - errs = knf.Validate([]*knf.Validator{ + errs = knf.Validate(knf.Validators{ {"test:test1", Perms, "F"}, {"test:test1", Perms, "FR"}, {"test:test1", Perms, "FW"}, @@ -99,14 +99,14 @@ func (s *ValidatorSuite) TestOwnerValidator(c *C) { err := knf.Global(configFile) c.Assert(err, IsNil) - errs := knf.Validate([]*knf.Validator{ + errs := knf.Validate(knf.Validators{ {"test:test0", Owner, "root"}, {"test:test1", Owner, "root"}, }) c.Assert(errs, HasLen, 0) - errs = knf.Validate([]*knf.Validator{ + errs = knf.Validate(knf.Validators{ {"test:test1", Owner, "nobody"}, {"test:test1", Owner, "somerandomuser"}, {"test:test1", Owner, ""}, @@ -125,7 +125,7 @@ func (s *ValidatorSuite) TestOwnerValidator(c *C) { err = knf.Global(configFile) c.Assert(err, IsNil) - errs = knf.Validate([]*knf.Validator{ + errs = knf.Validate(knf.Validators{ {"test:test1", Owner, "root"}, }) @@ -142,12 +142,12 @@ func (s *ValidatorSuite) TestOwnerGroupValidator(c *C) { var errs []error if runtime.GOOS == "darwin" { - errs = knf.Validate([]*knf.Validator{ + errs = knf.Validate(knf.Validators{ {"test:test0", OwnerGroup, "wheel"}, {"test:test1", OwnerGroup, "wheel"}, }) } else { - errs = knf.Validate([]*knf.Validator{ + errs = knf.Validate(knf.Validators{ {"test:test0", OwnerGroup, "root"}, {"test:test1", OwnerGroup, "root"}, }) @@ -155,7 +155,7 @@ func (s *ValidatorSuite) TestOwnerGroupValidator(c *C) { c.Assert(errs, HasLen, 0) - errs = knf.Validate([]*knf.Validator{ + errs = knf.Validate(knf.Validators{ {"test:test1", OwnerGroup, "daemon"}, {"test:test1", OwnerGroup, "somerandomgroup"}, {"test:test1", OwnerGroup, ""}, @@ -174,7 +174,7 @@ func (s *ValidatorSuite) TestOwnerGroupValidator(c *C) { err = knf.Global(configFile) c.Assert(err, IsNil) - errs = knf.Validate([]*knf.Validator{ + errs = knf.Validate(knf.Validators{ {"test:test1", OwnerGroup, "daemon"}, }) @@ -188,14 +188,14 @@ func (s *ValidatorSuite) TestFileModeValidator(c *C) { err := knf.Global(configFile) c.Assert(err, IsNil) - errs := knf.Validate([]*knf.Validator{ + errs := knf.Validate(knf.Validators{ {"test:test0", FileMode, os.FileMode(0644)}, {"test:test1", FileMode, os.FileMode(0644)}, }) c.Assert(errs, HasLen, 0) - errs = knf.Validate([]*knf.Validator{ + errs = knf.Validate(knf.Validators{ {"test:test1", FileMode, os.FileMode(0777)}, }) @@ -207,7 +207,7 @@ func (s *ValidatorSuite) TestFileModeValidator(c *C) { err = knf.Global(configFile) c.Assert(err, IsNil) - errs = knf.Validate([]*knf.Validator{ + errs = knf.Validate(knf.Validators{ {"test:test1", FileMode, os.FileMode(0644)}, {"test:test1", FileMode, os.FileMode(0)}, {"test:test1", FileMode, 100}, @@ -226,14 +226,14 @@ func (s *ValidatorSuite) TestMatchPattern(c *C) { err := knf.Global(configFile) c.Assert(err, IsNil) - errs := knf.Validate([]*knf.Validator{ + errs := knf.Validate(knf.Validators{ {"test:test0", MatchPattern, "/etc/*"}, {"test:test1", MatchPattern, "/etc/*"}, }) c.Assert(errs, HasLen, 0) - errs = knf.Validate([]*knf.Validator{ + errs = knf.Validate(knf.Validators{ {"test:test1", MatchPattern, "/var/*"}, {"test:test1", MatchPattern, "[]a"}, {"test:test1", MatchPattern, ""}, diff --git a/knf/validators/network/validators.go b/knf/validators/network/validators.go index a95d14a0..3d0af8d3 100644 --- a/knf/validators/network/validators.go +++ b/knf/validators/network/validators.go @@ -20,128 +20,129 @@ import ( // ////////////////////////////////////////////////////////////////////////////////// // var ( - // IP returns error if config property isn't a valid IP address + // IP returns error if configuration property isn't a valid IP address IP = validateIP - // Port returns error if config property isn't a valid port number + // Port returns error if configuration property isn't a valid port number Port = validatePort - // MAC returns error if config property isn't a valid MAC address + // MAC returns error if configuration property isn't a valid MAC address MAC = validateMAC - // CIDR returns error if config property isn't a valid CIDR address + // CIDR returns error if configuration property isn't a valid CIDR address CIDR = validateCIDR - // URL returns error if config property isn't a valid URL + // URL returns error if configuration property isn't a valid URL URL = validateURL - // Mail returns error if config property isn't a valid email address + // Mail returns error if configuration property isn't a valid email address Mail = validateMail - // HasIP returns error if system doesn't have interface with IP from config property + // HasIP returns error if system doesn't have interface with IP from configuration + // property HasIP = validateHasIP ) // ////////////////////////////////////////////////////////////////////////////////// // func validateIP(config knf.IConfig, prop string, value any) error { - ipStr := config.GetS(prop) + v := config.GetS(prop) - if ipStr == "" { + if v == "" { return nil } - ip := net.ParseIP(ipStr) + ip := net.ParseIP(v) if ip == nil { - return fmt.Errorf("%q is not a valid IP address", ipStr) + return fmt.Errorf("%q is not a valid IP address", v) } return nil } func validatePort(config knf.IConfig, prop string, value any) error { - portStr := config.GetS(prop) + v := config.GetS(prop) - if portStr == "" { + if v == "" { return nil } portInt := config.GetI(prop) if portInt == 0 || portInt > 65535 { - return fmt.Errorf("%q is not a valid port number", portStr) + return fmt.Errorf("%q is not a valid port number", v) } return nil } func validateMAC(config knf.IConfig, prop string, value any) error { - macStr := config.GetS(prop) + v := config.GetS(prop) - if macStr == "" { + if v == "" { return nil } - _, err := net.ParseMAC(macStr) + _, err := net.ParseMAC(v) if err != nil { - return fmt.Errorf("%q is not a valid MAC address: %v", macStr, err) + return fmt.Errorf("%q is not a valid MAC address: %v", v, err) } return nil } func validateCIDR(config knf.IConfig, prop string, value any) error { - cidrStr := config.GetS(prop) + v := config.GetS(prop) - if cidrStr == "" { + if v == "" { return nil } - _, _, err := net.ParseCIDR(cidrStr) + _, _, err := net.ParseCIDR(v) if err != nil { - return fmt.Errorf("%q is not a valid CIDR address: %v", cidrStr, err) + return fmt.Errorf("%q is not a valid CIDR address: %v", v, err) } return nil } func validateURL(config knf.IConfig, prop string, value any) error { - urlStr := config.GetS(prop) + v := config.GetS(prop) - if urlStr == "" { + if v == "" { return nil } - _, err := url.ParseRequestURI(urlStr) + _, err := url.ParseRequestURI(v) if err != nil { - return fmt.Errorf("%q is not a valid URL address: %v", urlStr, err) + return fmt.Errorf("%q is not a valid URL address: %v", v, err) } return nil } func validateMail(config knf.IConfig, prop string, value any) error { - mailStr := config.GetS(prop) + v := config.GetS(prop) - if mailStr == "" { + if v == "" { return nil } - if !strings.ContainsRune(mailStr, '@') || !strings.ContainsRune(mailStr, '.') { - return fmt.Errorf("%q is not a valid email address", mailStr) + if !strings.ContainsRune(v, '@') || !strings.ContainsRune(v, '.') { + return fmt.Errorf("%q is not a valid email address", v) } return nil } func validateHasIP(config knf.IConfig, prop string, value any) error { - ipStr := config.GetS(prop) + v := config.GetS(prop) - if ipStr == "" { + if v == "" { return nil } @@ -159,11 +160,11 @@ func validateHasIP(config knf.IConfig, prop string, value any) error { } for _, a := range addr { - if ipStr == a.(*net.IPNet).IP.String() { + if v == a.(*net.IPNet).IP.String() { return nil } } } - return fmt.Errorf("The system does not have an interface with the address %q", ipStr) + return fmt.Errorf("The system does not have an interface with the address %q", v) } diff --git a/knf/validators/network/validators_test.go b/knf/validators/network/validators_test.go index bcd1dc3a..922a3147 100644 --- a/knf/validators/network/validators_test.go +++ b/knf/validators/network/validators_test.go @@ -75,14 +75,14 @@ func (s *ValidatorSuite) TestIPValidator(c *C) { err := knf.Global(configFile) c.Assert(err, IsNil) - errs := knf.Validate([]*knf.Validator{ + errs := knf.Validate(knf.Validators{ {"ip:test0", IP, nil}, {"ip:test1", IP, nil}, }) c.Assert(errs, HasLen, 0) - errs = knf.Validate([]*knf.Validator{ + errs = knf.Validate(knf.Validators{ {"ip:test2", IP, nil}, }) @@ -96,14 +96,14 @@ func (s *ValidatorSuite) TestHasIPValidator(c *C) { err := knf.Global(configFile) c.Assert(err, IsNil) - errs := knf.Validate([]*knf.Validator{ + errs := knf.Validate(knf.Validators{ {"ip:test0", HasIP, nil}, {"ip:test1", HasIP, nil}, }) c.Assert(errs, HasLen, 0) - errs = knf.Validate([]*knf.Validator{ + errs = knf.Validate(knf.Validators{ {"ip:test3", HasIP, nil}, }) @@ -117,14 +117,14 @@ func (s *ValidatorSuite) TestPortValidator(c *C) { err := knf.Global(configFile) c.Assert(err, IsNil) - errs := knf.Validate([]*knf.Validator{ + errs := knf.Validate(knf.Validators{ {"port:test0", Port, nil}, {"port:test1", Port, nil}, }) c.Assert(errs, HasLen, 0) - errs = knf.Validate([]*knf.Validator{ + errs = knf.Validate(knf.Validators{ {"port:test2", Port, nil}, {"port:test3", Port, nil}, }) @@ -140,14 +140,14 @@ func (s *ValidatorSuite) TestMACValidator(c *C) { err := knf.Global(configFile) c.Assert(err, IsNil) - errs := knf.Validate([]*knf.Validator{ + errs := knf.Validate(knf.Validators{ {"mac:test0", MAC, nil}, {"mac:test1", MAC, nil}, }) c.Assert(errs, HasLen, 0) - errs = knf.Validate([]*knf.Validator{ + errs = knf.Validate(knf.Validators{ {"mac:test2", MAC, nil}, }) @@ -161,14 +161,14 @@ func (s *ValidatorSuite) TestCIDRValidator(c *C) { err := knf.Global(configFile) c.Assert(err, IsNil) - errs := knf.Validate([]*knf.Validator{ + errs := knf.Validate(knf.Validators{ {"cidr:test0", CIDR, nil}, {"cidr:test1", CIDR, nil}, }) c.Assert(errs, HasLen, 0) - errs = knf.Validate([]*knf.Validator{ + errs = knf.Validate(knf.Validators{ {"cidr:test2", CIDR, nil}, }) @@ -182,14 +182,14 @@ func (s *ValidatorSuite) TestURLValidator(c *C) { err := knf.Global(configFile) c.Assert(err, IsNil) - errs := knf.Validate([]*knf.Validator{ + errs := knf.Validate(knf.Validators{ {"url:test0", URL, nil}, {"url:test1", URL, nil}, }) c.Assert(errs, HasLen, 0) - errs = knf.Validate([]*knf.Validator{ + errs = knf.Validate(knf.Validators{ {"url:test2", URL, nil}, }) @@ -203,7 +203,7 @@ func (s *ValidatorSuite) TestMailValidator(c *C) { err := knf.Global(configFile) c.Assert(err, IsNil) - errs := knf.Validate([]*knf.Validator{ + errs := knf.Validate(knf.Validators{ {"mail:test0", Mail, nil}, {"mail:test1", Mail, nil}, {"mail:test2", Mail, nil}, diff --git a/knf/validators/regexp/validators.go b/knf/validators/regexp/validators.go index f9b4f0fa..03b476d7 100644 --- a/knf/validators/regexp/validators.go +++ b/knf/validators/regexp/validators.go @@ -18,16 +18,16 @@ import ( // ////////////////////////////////////////////////////////////////////////////////// // var ( - // Regexp returns an error if config property does not match given regexp + // Regexp returns an error if configuration property does not match given regexp Regexp = validateRegexp ) // ////////////////////////////////////////////////////////////////////////////////// // func validateRegexp(config knf.IConfig, prop string, value any) error { - confVal := config.GetS(prop) + v := config.GetS(prop) - if confVal == "" { + if v == "" { return nil } @@ -43,7 +43,7 @@ func validateRegexp(config knf.IConfig, prop string, value any) error { return fmt.Errorf("Invalid input for regexp.Regexp validator: %w", err) } - if !re.MatchString(confVal) { + if !re.MatchString(v) { return fmt.Errorf("Property %s must match regexp pattern %q", prop, t) } diff --git a/knf/validators/regexp/validators_test.go b/knf/validators/regexp/validators_test.go index 7e3a25c9..55d12fda 100644 --- a/knf/validators/regexp/validators_test.go +++ b/knf/validators/regexp/validators_test.go @@ -49,14 +49,14 @@ func (s *ValidatorSuite) TestRegexpValidator(c *check.C) { err = knf.Global(configFile) c.Assert(err, check.IsNil) - errs := knf.Validate([]*knf.Validator{ + errs := knf.Validate(knf.Validators{ {"regexp:test1", Regexp, `^[A-Z0-9]{4,5}$`}, {"regexp:test3", Regexp, `^[A-Z0-9]{4,5}$`}, }) c.Assert(errs, check.HasLen, 0) - errs = knf.Validate([]*knf.Validator{ + errs = knf.Validate(knf.Validators{ {"regexp:test2", Regexp, `^[A-Z0-9]{4}$`}, {"regexp:test2", Regexp, `\`}, {"regexp:test2", Regexp, ""}, diff --git a/knf/validators/system/validators.go b/knf/validators/system/validators.go index b91f6d6b..92c7de01 100644 --- a/knf/validators/system/validators.go +++ b/knf/validators/system/validators.go @@ -19,32 +19,32 @@ import ( // ////////////////////////////////////////////////////////////////////////////////// // var ( - // User returns error if config property contains name of user or UID which not + // User returns error if configuration property contains name of user or UID which not // present on the system User = validateUser - // Group returns error if config property contains name of group or GID which not - // present on the system + // Group returns error if configuration property contains name of group or GID which + // not present on the system Group = validateGroup ) // ////////////////////////////////////////////////////////////////////////////////// // func validateUser(config knf.IConfig, prop string, value any) error { - userNameOrID := config.GetS(prop) + v := config.GetS(prop) - if userNameOrID != "" && !system.IsUserExist(userNameOrID) { - return fmt.Errorf("User %q is not present on the system", userNameOrID) + if v != "" && !system.IsUserExist(v) { + return fmt.Errorf("User %q is not present on the system", v) } return nil } func validateGroup(config knf.IConfig, prop string, value any) error { - groupNameOrID := config.GetS(prop) + v := config.GetS(prop) - if groupNameOrID != "" && !system.IsGroupExist(groupNameOrID) { - return fmt.Errorf("Group %q is not present on the system", groupNameOrID) + if v != "" && !system.IsGroupExist(v) { + return fmt.Errorf("Group %q is not present on the system", v) } return nil diff --git a/knf/validators/system/validators_linux.go b/knf/validators/system/validators_linux.go index 0c9ab46c..21f3621f 100644 --- a/knf/validators/system/validators_linux.go +++ b/knf/validators/system/validators_linux.go @@ -19,17 +19,17 @@ import ( // ////////////////////////////////////////////////////////////////////////////////// // var ( - // Interface returns error if config property contains name of network interface - // which not present on the system + // Interface returns error if configuration property contains name of network + // interface which not present on the system Interface = validateInterface ) // ////////////////////////////////////////////////////////////////////////////////// // func validateInterface(config knf.IConfig, prop string, value any) error { - interfaceName := config.GetS(prop) + v := config.GetS(prop) - if interfaceName == "" { + if v == "" { return nil } @@ -39,10 +39,10 @@ func validateInterface(config knf.IConfig, prop string, value any) error { return fmt.Errorf("Can't get interfaces info: %v", err) } - _, isPresent := stats[interfaceName] + _, isPresent := stats[v] if !isPresent { - return fmt.Errorf("Interface %q is not present on the system", interfaceName) + return fmt.Errorf("Interface %q is not present on the system", v) } return nil diff --git a/knf/validators/system/validators_linux_test.go b/knf/validators/system/validators_linux_test.go index 2b4719b5..2034d01e 100644 --- a/knf/validators/system/validators_linux_test.go +++ b/knf/validators/system/validators_linux_test.go @@ -21,14 +21,14 @@ func (s *ValidatorSuite) TestInterfaceValidator(c *C) { err := knf.Global(configFile) c.Assert(err, IsNil) - errs := knf.Validate([]*knf.Validator{ + errs := knf.Validate(knf.Validators{ {"interface:test0", Interface, nil}, {"interface:test1", Interface, nil}, }) c.Assert(errs, HasLen, 0) - errs = knf.Validate([]*knf.Validator{ + errs = knf.Validate(knf.Validators{ {"interface:test2", Interface, nil}, }) diff --git a/knf/validators/system/validators_test.go b/knf/validators/system/validators_test.go index 55fd4277..748daef6 100644 --- a/knf/validators/system/validators_test.go +++ b/knf/validators/system/validators_test.go @@ -57,14 +57,14 @@ func (s *ValidatorSuite) TestUserValidator(c *C) { err := knf.Global(configFile) c.Assert(err, IsNil) - errs := knf.Validate([]*knf.Validator{ + errs := knf.Validate(knf.Validators{ {"user:test0", User, nil}, {"user:test1", User, nil}, }) c.Assert(errs, HasLen, 0) - errs = knf.Validate([]*knf.Validator{ + errs = knf.Validate(knf.Validators{ {"user:test2", User, nil}, }) @@ -77,14 +77,14 @@ func (s *ValidatorSuite) TestGroupValidator(c *C) { err := knf.Global(configFile) c.Assert(err, IsNil) - errs := knf.Validate([]*knf.Validator{ + errs := knf.Validate(knf.Validators{ {"group:test0", Group, nil}, {"group:test1", Group, nil}, }) c.Assert(errs, HasLen, 0) - errs = knf.Validate([]*knf.Validator{ + errs = knf.Validate(knf.Validators{ {"group:test2", Group, nil}, }) diff --git a/knf/validators/time/validators.go b/knf/validators/time/validators.go index d154d684..feceee98 100644 --- a/knf/validators/time/validators.go +++ b/knf/validators/time/validators.go @@ -21,21 +21,25 @@ import ( // ////////////////////////////////////////////////////////////////////////////////// // var ( - // Format returns an error if the config property contains an invalid time conversion - // format + // Format returns an error if the configuration property contains an invalid time + // conversion format Format = validateFormat + + // Timezone returns an error if the configuration property contains an invalid time + // zone name + Timezone = validateTimezone ) // ////////////////////////////////////////////////////////////////////////////////// // func validateFormat(config knf.IConfig, prop string, value any) error { - confVal := config.GetS(prop) + v := config.GetS(prop) - if confVal == "" { + if v == "" { return nil } - str := timeutil.Format(time.Now(), confVal) + str := timeutil.Format(time.Now(), v) if !strings.ContainsRune(str, '%') { return nil @@ -48,3 +52,19 @@ func validateFormat(config knf.IConfig, prop string, value any) error { prop, seq, ) } + +func validateTimezone(config knf.IConfig, prop string, value any) error { + v := config.GetS(prop) + + if v == "" { + return nil + } + + _, err := time.LoadLocation(v) + + if err == nil { + return nil + } + + return fmt.Errorf("Property %s contains invalid time zone name: %v", prop, err) +} diff --git a/knf/validators/time/validators_test.go b/knf/validators/time/validators_test.go index c6f4ae67..bda59a01 100644 --- a/knf/validators/time/validators_test.go +++ b/knf/validators/time/validators_test.go @@ -19,11 +19,20 @@ import ( // ////////////////////////////////////////////////////////////////////////////////// // const _CONFIG_DATA = ` -[time] +[format] test1: test2: %D test3: %Y/%m/%d %H:%M:%S %Z test4: %H:%M:%i + +[timezone] + test1: + test2: Local + test3: UTC + test4: Etc/GMT+12 + test5: Europe/Dublin + test6: Europe/Guernsey + test7: Europe/Hogwarts ` // ////////////////////////////////////////////////////////////////////////////////// // @@ -50,21 +59,49 @@ func (s *ValidatorSuite) TestFormatValidator(c *check.C) { err = knf.Global(configFile) c.Assert(err, check.IsNil) - errs := knf.Validate([]*knf.Validator{ - {"time:test1", Format, nil}, - {"time:test2", Format, nil}, - {"time:test3", Format, nil}, + errs := knf.Validate(knf.Validators{ + {"format:test1", Format, nil}, + {"format:test2", Format, nil}, + {"format:test3", Format, nil}, + }) + + c.Assert(errs, check.HasLen, 0) + + errs = knf.Validate(knf.Validators{ + {"format:test4", Format, nil}, + }) + + c.Assert(errs, check.HasLen, 1) + + c.Assert(errs[0].Error(), check.Equals, `Property format:test4 contains invalid time format: Invalid control sequence "%i"`) +} + +func (s *ValidatorSuite) TestTimezoneValidator(c *check.C) { + var err error + + configFile := createConfig(c, _CONFIG_DATA) + + err = knf.Global(configFile) + c.Assert(err, check.IsNil) + + errs := knf.Validate(knf.Validators{ + {"timezone:test1", Timezone, nil}, + {"timezone:test2", Timezone, nil}, + {"timezone:test3", Timezone, nil}, + {"timezone:test4", Timezone, nil}, + {"timezone:test5", Timezone, nil}, + {"timezone:test6", Timezone, nil}, }) c.Assert(errs, check.HasLen, 0) - errs = knf.Validate([]*knf.Validator{ - {"time:test4", Format, nil}, + errs = knf.Validate(knf.Validators{ + {"timezone:test7", Timezone, nil}, }) c.Assert(errs, check.HasLen, 1) - c.Assert(errs[0].Error(), check.Equals, `Property time:test4 contains invalid time format: Invalid control sequence "%i"`) + c.Assert(errs[0].Error(), check.Equals, `Property timezone:test7 contains invalid time zone name: unknown time zone Europe/Hogwarts`) } // ////////////////////////////////////////////////////////////////////////////////// // diff --git a/knf/validators/validators.go b/knf/validators/validators.go index 4d922f1d..8a724e0c 100644 --- a/knf/validators/validators.go +++ b/knf/validators/validators.go @@ -98,32 +98,32 @@ func validatorSet(config knf.IConfig, prop string, value any) error { } func validatorTypeBool(config knf.IConfig, prop string, value any) error { - propValue := config.GetS(prop) + v := config.GetS(prop) - switch strings.ToLower(propValue) { + switch strings.ToLower(v) { case "", "0", "1", "true", "false", "yes", "no": return nil default: return fmt.Errorf( "Property %s contains unsupported boolean value (%s)", - prop, propValue, + prop, v, ) } } func validatorTypeNum(config knf.IConfig, prop string, value any) error { - propValue := config.GetS(prop) + v := config.GetS(prop) - if propValue == "" { + if v == "" { return nil } - _, err := strconv.Atoi(propValue) + _, err := strconv.Atoi(v) if err != nil { return fmt.Errorf( "Property %s contains unsupported numeric value (%s)", - prop, propValue, + prop, v, ) } @@ -131,18 +131,18 @@ func validatorTypeNum(config knf.IConfig, prop string, value any) error { } func validatorTypeFloat(config knf.IConfig, prop string, value any) error { - propValue := config.GetS(prop) + v := config.GetS(prop) - if propValue == "" { + if v == "" { return nil } - _, err := strconv.ParseFloat(propValue, 64) + _, err := strconv.ParseFloat(v, 64) if err != nil { return fmt.Errorf( "Property %s contains unsupported float value (%s)", - prop, propValue, + prop, v, ) } @@ -150,20 +150,20 @@ func validatorTypeFloat(config knf.IConfig, prop string, value any) error { } func validatorTypeSize(config knf.IConfig, prop string, value any) error { - propValue := config.GetS(prop) + v := config.GetS(prop) - if propValue == "" { + if v == "" { return nil } size := config.GetSZ(prop) - propValueNorm := strings.TrimRight(propValue, " bB") + propValueNorm := strings.TrimRight(v, " bB") _, err := strconv.ParseFloat(propValueNorm, 64) if size == 0 && err != nil { return fmt.Errorf( "Property %s contains unsupported size value (%s)", - prop, propValue, + prop, v, ) } diff --git a/timeutil/example_test.go b/timeutil/example_test.go index e8645f98..c2411fa8 100644 --- a/timeutil/example_test.go +++ b/timeutil/example_test.go @@ -336,6 +336,17 @@ func ExampleSince() { fmt.Println(Since(d, DAY)) } +func ExampleDurationAs() { + d1 := time.Date(2021, 1, 1, 12, 30, 15, 0, time.Local) + d2 := time.Date(2024, 6, 15, 14, 15, 45, 0, time.Local) + + d := d2.Sub(d1) + + fmt.Printf("Days: %d\n", DurationAs(d, DAY)) + // Output: + // Days: 1261 +} + func ExampleFromISOWeek() { t := FromISOWeek(25, 2021, time.UTC) @@ -397,15 +408,15 @@ func ExamplePeriod_Duration() { // Period duration: 1h45m30s } -func ExamplePeriod_DurationIn() { +func ExamplePeriod_DurationAs() { p := Period{ time.Date(2021, 1, 1, 12, 30, 15, 0, time.Local), time.Date(2021, 6, 15, 14, 15, 45, 0, time.Local), } - fmt.Printf("Period duration (hours): %d\n", p.DurationIn(HOUR)) - fmt.Printf("Period duration (days): %d\n", p.DurationIn(DAY)) - fmt.Printf("Period duration (weeks): %d\n", p.DurationIn(WEEK)) + fmt.Printf("Period duration (hours): %d\n", p.DurationAs(HOUR)) + fmt.Printf("Period duration (days): %d\n", p.DurationAs(DAY)) + fmt.Printf("Period duration (weeks): %d\n", p.DurationAs(WEEK)) // Output: // Period duration (hours): 3961 diff --git a/timeutil/period.go b/timeutil/period.go index 48810913..e47446d9 100644 --- a/timeutil/period.go +++ b/timeutil/period.go @@ -32,39 +32,39 @@ func (p Period) Duration() time.Duration { return p.End.Sub(p.Start) } -// DurationIn returns duration of period in given units -func (p Period) DurationIn(mod time.Duration) int { - return int(p.Duration() / mod) +// DurationAs returns duration of period in given units +func (p Period) DurationAs(unit time.Duration) int { + return DurationAs(p.Duration(), unit) } // Seconds returns duration in seconds func (p Period) Seconds() int { - return p.DurationIn(SECOND) + return p.DurationAs(SECOND) } // Minutes returns duration in minutes func (p Period) Minutes() int { - return p.DurationIn(MINUTE) + return p.DurationAs(MINUTE) } // Hours returns duration in hours func (p Period) Hours() int { - return p.DurationIn(HOUR) + return p.DurationAs(HOUR) } // Days returns duration in days func (p Period) Days() int { - return p.DurationIn(DAY) + return p.DurationAs(DAY) } // Weeks returns duration in weeks func (p Period) Weeks() int { - return p.DurationIn(WEEK) + return p.DurationAs(WEEK) } // Years returns duration in years func (p Period) Years() int { - return p.DurationIn(YEAR) + return p.DurationAs(YEAR) } // String returns string representation of period diff --git a/timeutil/timeutil.go b/timeutil/timeutil.go index 8cdb790e..bd29e3ab 100644 --- a/timeutil/timeutil.go +++ b/timeutil/timeutil.go @@ -54,7 +54,7 @@ func PrettyDuration(d any) string { return "" } - if dur != 0 && dur < time.Second { + if dur != 0 && dur < SECOND { return getPrettyShortDuration(dur, " ") } @@ -264,7 +264,7 @@ func ParseDuration(dur string, defMod ...rune) (time.Duration, error) { } } - return time.Second * time.Duration(result), nil + return SECOND * time.Duration(result), nil } // StartOfHour returns start of the hour @@ -475,15 +475,20 @@ func IsWeekend(t time.Time) bool { } // Until returns time until given moment in given units -func Until(t time.Time, mod time.Duration) int { +func Until(t time.Time, unit time.Duration) int { now := time.Now().In(t.Location()) - return int(t.Sub(now) / mod) + return int(t.Sub(now) / unit) } // Since returns time since given moment in given units -func Since(t time.Time, mod time.Duration) int { +func Since(t time.Time, unit time.Duration) int { now := time.Now().In(t.Location()) - return int(now.Sub(t) / mod) + return int(now.Sub(t) / unit) +} + +// DurationAs returns duration in given units +func DurationAs(t, unit time.Duration) int { + return int(t / unit) } // FromISOWeek returns date for given week number in given year @@ -504,25 +509,25 @@ func convertDuration(d any) (time.Duration, bool) { case time.Duration: return u, true case int: - return time.Duration(u) * time.Second, true + return time.Duration(u) * SECOND, true case int16: - return time.Duration(u) * time.Second, true + return time.Duration(u) * SECOND, true case int32: - return time.Duration(u) * time.Second, true + return time.Duration(u) * SECOND, true case uint: - return time.Duration(u) * time.Second, true + return time.Duration(u) * SECOND, true case uint16: - return time.Duration(u) * time.Second, true + return time.Duration(u) * SECOND, true case uint32: - return time.Duration(u) * time.Second, true + return time.Duration(u) * SECOND, true case uint64: - return time.Duration(u) * time.Second, true + return time.Duration(u) * SECOND, true case float32: - return time.Duration(u) * time.Second, true + return time.Duration(u) * SECOND, true case float64: - return time.Duration(u) * time.Second, true + return time.Duration(u) * SECOND, true case int64: - return time.Duration(u) * time.Second, true + return time.Duration(u) * SECOND, true } return 0, false diff --git a/timeutil/timeutil_test.go b/timeutil/timeutil_test.go index f3c158f1..aea75b8f 100644 --- a/timeutil/timeutil_test.go +++ b/timeutil/timeutil_test.go @@ -377,6 +377,9 @@ func (s *TimeUtilSuite) TestHelpers(c *C) { d = time.Date(2012, 1, 1, 12, 0, 0, 0, time.Local) c.Assert(Since(d, DAY), Not(Equals), 0) + + d = time.Date(2023, 8, 1, 12, 30, 15, 0, time.Local) + c.Assert(DurationAs(time.Since(d), DAY), Equals, 585) } // ////////////////////////////////////////////////////////////////////////////////// // diff --git a/version.go b/version.go index fed02596..5d0c1342 100644 --- a/version.go +++ b/version.go @@ -8,4 +8,4 @@ package ek // ////////////////////////////////////////////////////////////////////////////////// // // VERSION is current ek package version -const VERSION = "13.20.1" +const VERSION = "13.20.2"