func setKey(value db.Entity) { path, err := value.Path() if err != nil { panic(err) } content, err := jsonio.Write(value) if err != nil { panic(err) } switch Driver { case "etcd": client, err := getEtcdClient() if err != nil { panic(err) } if _, err := client.Set(context.Background(), fmt.Sprintf("/volplugin/%v", path), string(content), nil); err != nil { panic(err) } case "consul": client, err := getConsulClient() if err != nil { panic(err) } if _, err := client.KV().Put(&api.KVPair{Key: fmt.Sprintf("volplugin/%v", path), Value: content}, nil); err != nil { panic(err) } } }
// WatchStop stops a watch. func (c *Client) WatchStop(obj db.Entity) error { path, err := obj.Path() if err != nil { return err } return helpers.WatchStop(c, path, c.watchers, &c.watcherMutex) }
// WatchStop stops a watch for a given object. func (c *Client) WatchStop(obj db.Entity) error { path, err := obj.Path() if err != nil { return err } return c.watchStopPath(path) }
// ListPrefix is used to list a subtree of an entity, such as listing volume by policy. func (c *Client) ListPrefix(prefix string, obj db.Entity) ([]db.Entity, error) { resp, err := c.client.Get(context.Background(), c.qualified(path.Join(obj.Prefix(), prefix)), &client.GetOptions{Recursive: true}) if err != nil { return nil, err } return c.traverse(resp.Node, obj), nil }
// Watch watches a given object for changes. func (c *Client) Watch(obj db.Entity) (chan db.Entity, chan error) { path, err := obj.Path() if err != nil { errChan := make(chan error, 1) errChan <- err return make(chan db.Entity), errChan } return c.watchPath(obj, path, false) }
// Watch watches a given object for changes. func (c *Client) Watch(obj db.Entity) (chan db.Entity, chan error) { path, err := obj.Path() if err != nil { errChan := make(chan error, 1) errChan <- err return nil, errChan } return helpers.WrapWatch(c, obj, path, false, c.watchers, &c.watcherMutex, c.startWatch) }
// Watch watches stuff. func (c *Client) Watch(obj db.Entity) (chan db.Entity, chan error) { path, err := obj.Path() if err != nil { errChan := make(chan error, 1) errChan <- err return nil, errChan } // these paths are qualified in watchInternal return helpers.WrapWatch(c, obj, path, false, c.watchers, &c.watcherMutex, c.watchInternal) }
// ListPrefix lists all the entities under prefix instead of listing the whole keyspace. func (c *Client) ListPrefix(prefix string, obj db.Entity) ([]db.Entity, error) { pairs, _, err := c.client.KV().List(c.qualified(path.Join(obj.Prefix(), prefix)), nil) if err != nil { return nil, err } entities := []db.Entity{} for _, pair := range pairs { copy, err := helpers.ReadAndSet(c, obj, pair.Key, pair.Value) if err != nil { return nil, err } entities = append(entities, copy) } return entities, nil }
func setKey(value db.Entity) { client, err := getEtcdClient() if err != nil { panic(err) } path, err := value.Path() if err != nil { panic(err) } content, err := jsonio.Write(value) if err != nil { panic(err) } if _, err := client.Set(context.Background(), fmt.Sprintf("/volplugin/%v", path), string(content), nil); err != nil { panic(err) } }
// 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 }
// Delete removes the object from the store. func (c *Client) Delete(obj db.Entity) error { if obj.Hooks().PreDelete != nil { if err := obj.Hooks().PreDelete(c, obj); err != nil { return errors.EtcdToErrored(err) } } path, err := obj.Path() if err != nil { return err } if _, err := c.client.Delete(context.Background(), c.qualified(path), nil); err != nil { return errors.EtcdToErrored(err) } if obj.Hooks().PostDelete != nil { if err := obj.Hooks().PostDelete(c, obj); err != nil { return errors.EtcdToErrored(err) } } return nil }
// WatchPrefixStop stops a watch. func (c *Client) WatchPrefixStop(obj db.Entity) error { return helpers.WatchStop(c, obj.Prefix(), c.watchers, &c.watcherMutex) }
// WatchPrefix watches all items under the given entity's prefix func (c *Client) WatchPrefix(obj db.Entity) (chan db.Entity, chan error) { return helpers.WrapWatch(c, obj, obj.Prefix(), true, c.watchers, &c.watcherMutex, c.startWatch) }
// WatchPrefix watches all items under the given entity's prefix func (c *Client) WatchPrefix(obj db.Entity) (chan db.Entity, chan error) { return c.watchPath(obj, obj.Prefix(), true) }
// WatchPrefixStop stops func (c *Client) WatchPrefixStop(obj db.Entity) error { return c.watchStopPath(obj.Prefix()) }
// WatchPrefix watches a directory prefix for changes. func (c *Client) WatchPrefix(obj db.Entity) (chan db.Entity, chan error) { // these paths are qualified in watchInternal return helpers.WrapWatch(c, obj, obj.Prefix(), true, c.watchers, &c.watcherMutex, c.watchInternal) }
// 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() }
// Set takes the object and commits it to the database. func (c *Client) Set(obj db.Entity) error { if err := obj.Validate(); err != nil { return err } if obj.Hooks().PreSet != nil { if err := obj.Hooks().PreSet(c, obj); err != nil { return errors.EtcdToErrored(err) } } content, err := jsonio.Write(obj) if err != nil { return err } path, err := obj.Path() if err != nil { return err } if _, err := c.client.Set(context.Background(), c.qualified(path), string(content), nil); err != nil { return errors.EtcdToErrored(err) } if obj.Hooks().PostSet != nil { if err := obj.Hooks().PostSet(c, obj); err != nil { return errors.EtcdToErrored(err) } } return nil }