frostfs-node/pkg/innerring/processors/netmap/nodevalidation/locode/calls.go
Leonard Lyubich db703a5117 [#316] ir/netmap: Validate LOCODE attributes of network map candidates
Define a structure for dealing with the geographic location of nodes.
Implement VerifyAndUpdate (with the same purpose as NodeValidator interface)
that checks LOCODE attribute and fills other attributes of the location.
Technically the entity is a wrapper over the NeoFS location database: it
maps the node LOCODE to the database record from which the new attributes
are generated.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2021-02-10 14:05:03 +03:00

85 lines
2 KiB
Go

package locode
import (
"github.com/nspcc-dev/neofs-api-go/pkg/netmap"
"github.com/nspcc-dev/neofs-node/pkg/util/locode"
"github.com/pkg/errors"
)
var errMissingLocode = errors.New("missing locode attribute")
var errMissingRequiredAttr = errors.New("missing required attribute in DB record")
// VerifyAndUpdate validates LOCODE attribute of n
// and adds a group of related attributes.
//
// If n does not contain LOCODE attribute or its value does not
// match the UN/LOCODE format, an error returns.
//
// New attributes are formed from the record of DB instance (Prm).
// If DB entry R was found w/o errors, then new attributes are:
// * CountryCode: R.CountryCode().String();
// * Country: R.CountryName();
// * CityCode: R.LocationCode().String();
// * City: Record.LocationName();
// * SubDivCode: R.SubDivCode();
// * SubDiv: R.SubDivName();
// * Continent: R.Continent().String().
//
// LOCODE attribute remains untouched.
func (v *Validator) VerifyAndUpdate(n *netmap.NodeInfo) error {
mAttr := uniqueAttributes(n.Attributes())
attrLocode, ok := mAttr[attrKeyLocode]
if !ok {
return errMissingLocode
}
lc, err := locode.FromString(attrLocode.Value())
if err != nil {
return errors.Wrap(err, "invalid locode value")
}
record, err := v.db.Get(lc)
if err != nil {
return errors.Wrap(err, "could not get locode record from DB")
}
for attrKey, attrDesc := range v.mAttr {
attrVal := attrDesc.converter(record)
if attrVal == "" {
if !attrDesc.optional {
return errMissingRequiredAttr
}
continue
}
a := netmap.NewNodeAttribute()
a.SetKey(attrKey)
a.SetValue(attrVal)
mAttr[attrKey] = a
}
as := n.Attributes()
as = as[:0]
for _, attr := range mAttr {
as = append(as, attr)
}
n.SetAttributes(as...)
return nil
}
func uniqueAttributes(as []*netmap.NodeAttribute) map[string]*netmap.NodeAttribute {
mAttr := make(map[string]*netmap.NodeAttribute, len(as))
for _, attr := range as {
mAttr[attr.Key()] = attr
}
return mAttr
}