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) } } }
func (s *testSuite) TestDump(c *C) { copy := testPolicies["basic"].Copy() for i := 0; i < 10; i++ { copy.(*db.Policy).Name = fmt.Sprintf("test%d", i) c.Assert(s.client.Set(copy), IsNil) } tarballPath, err := s.client.Dump("") c.Assert(err, IsNil) defer os.Remove(tarballPath) // check that the tarball was created in the expected spot _, err = os.Stat(tarballPath) c.Assert(os.IsNotExist(err), Equals, false) tarballFilename := filepath.Base(tarballPath) // can't use filepath.Ext() here because it thinks ".gz" is the extension dirName := tarballFilename[:strings.LastIndex(tarballFilename, ".tar.gz")] for i := 0; i < 10; i++ { testFilename := path.Join(dirName, "volplugin/policies", fmt.Sprintf("test%d", i)) data, err := ioutil.ReadFile(tarballPath) c.Assert(err, IsNil) // check that our test key is present and has the expected value reader := bytes.NewReader(data) gzReader, err := gzip.NewReader(reader) c.Assert(err, IsNil) tarReader := tar.NewReader(gzReader) found := false for { header, err := tarReader.Next() if err == io.EOF { break } c.Assert(err, IsNil) if header.Name == testFilename { var b bytes.Buffer _, err = io.Copy(&b, tarReader) c.Assert(err, IsNil) copy := testPolicies["basic"].Copy() copy.(*db.Policy).Name = fmt.Sprintf("test%d", i) c.Assert(s.client.Get(copy), IsNil) content, err := jsonio.Write(copy) c.Assert(err, IsNil) c.Assert(b.String(), Equals, string(content)) found = true break } } c.Assert(found, Equals, true, Commentf(testFilename)) } }
// 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 }
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) } }
// Free a lock. Pass force=true to force it dead. func (c *Client) Free(lock db.Lock, force bool) error { content, err := jsonio.Write(lock) if err != nil { return errors.LockFailed.Combine(err) } path, err := lock.Path() if err != nil { return errors.LockFailed.Combine(err) } opts := &client.DeleteOptions{PrevValue: string(content)} if force { opts = &client.DeleteOptions{} } _, err = c.client.Delete(context.Background(), c.qualified(path), opts) return err }
func (c *Client) doAcquire(lock db.Lock, ttl time.Duration) error { content, err := jsonio.Write(lock) if err != nil { return errors.LockFailed.Combine(err) } path, err := lock.Path() if err != nil { return errors.LockFailed.Combine(err) } _, err = c.client.Set(context.Background(), c.qualified(path), string(content), &client.SetOptions{PrevValue: string(content), TTL: ttl}) if er, ok := err.(client.Error); ok && er.Code == client.ErrorCodeKeyNotFound { _, err := c.client.Set(context.Background(), c.qualified(path), string(content), &client.SetOptions{PrevExist: client.PrevNoExist, TTL: ttl}) if err != nil { return errors.LockFailed.Combine(err) } return nil } return err }
// acquires and yields a *lock{} populated with all the values needed to // persist and reap this lock. Returns true if it is already running and we // have re-requested a running lock. func (c *Client) lock(obj db.Lock, ttl time.Duration, refresh bool) (*lock, bool, error) { // consul has a minimum ttl of 10s. Adjust. if ttl < 10*time.Second { ttl = 10 * time.Second } path, err := obj.Path() if err != nil { return nil, false, errors.LockFailed.Combine(err) } tmplock, ok := c.getLock(path) if ok { if reflect.DeepEqual(tmplock.obj, obj) { return tmplock, true, nil } return nil, false, errors.LockFailed.Combine(errored.Errorf("Invalid lock attempted at %q -- already exists", path)) } sessionID, err := c.getSession(obj, ttl, refresh) if err != nil { return nil, false, err } content, err := jsonio.Write(obj) if err != nil { return nil, false, err } mylock, err := c.client.LockOpts(&api.LockOptions{ LockTryOnce: true, Key: c.qualified(path), Value: content, SessionTTL: ttl.String(), MonitorRetryTime: ttl, MonitorRetries: -1, }) if err != nil { return nil, false, err } stopChan := make(chan struct{}) go func() { time.Sleep(100 * time.Millisecond) close(stopChan) }() monitor, err := mylock.Lock(stopChan) if err != nil { return nil, false, err } done := make(chan struct{}) lockObj := &lock{ lock: mylock, sessionID: sessionID, doneChan: done, monitorChan: monitor, obj: obj, ttl: ttl, path: path, refresh: refresh, } return lockObj, false, nil }