// Get retrieves the item from etcd's key/value store and then populates obj with its data. func (c *Client) Get(obj db.Entity) error { if obj.Hooks().PreGet != nil { if err := obj.Hooks().PreGet(c, obj); err != nil { return errors.EtcdToErrored(err) } } path, err := obj.Path() if err != nil { return err } resp, err := c.client.Get(context.Background(), c.qualified(path), nil) if err != nil { return errors.EtcdToErrored(err) } if err := jsonio.Read(obj, []byte(resp.Node.Value)); err != nil { return err } if err := obj.SetKey(c.trimPath(resp.Node.Key)); err != nil { return err } if obj.Hooks().PostGet != nil { if err := obj.Hooks().PostGet(c, obj); err != nil { return errors.EtcdToErrored(err) } } return obj.Validate() }
// 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 }