// traverse walks the keyspace and converts anything that looks like an entity // into an entity and returns it as part of the array. // // traverse will log & skip errors to ensure bad data will not break this routine. func (c *Client) traverse(node *client.Node, obj db.Entity) []db.Entity { entities := []db.Entity{} if node.Dir { for _, inner := range node.Nodes { entities = append(entities, c.traverse(inner, obj)...) } } else { copy := obj.Copy() doAppend := true if err := jsonio.Read(copy, []byte(node.Value)); err != nil { // This is kept this way so a buggy policy won't break listing all of them logrus.Errorf("Received error retrieving value at path %q during list: %v", node.Key, err) doAppend = false } if err := copy.SetKey(c.trimPath(node.Key)); err != nil { logrus.Error(err) doAppend = false } // same here. fire hooks to retrieve the full entity. only log but don't append on error. if copy.Hooks().PostGet != nil { if err := copy.Hooks().PostGet(c, copy); err != nil { logrus.Errorf("Error received trying to run fetch hooks during %q list: %v", node.Key, err) doAppend = false } } if doAppend { entities = append(entities, copy) } } return entities }