forked from TrueCloudLab/frostfs-node
[#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>
This commit is contained in:
parent
cbfaceb956
commit
db703a5117
4 changed files with 245 additions and 0 deletions
|
@ -0,0 +1,85 @@
|
|||
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
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue