// Get is used to fetch an entry func (c *ZookeeperBackend) Get(key string) (*Entry, error) { defer metrics.MeasureSince([]string{"zookeeper", "get"}, time.Now()) // Attempt to read the full path fullPath := c.nodePath(key) value, _, err := c.client.Get(fullPath) // Ignore if the node does not exist if err == zk.ErrNoNode { err = nil } if err != nil { return nil, err } // Handle a non-existing value if value == nil { return nil, nil } ent := &Entry{ Key: key, Value: value, } return ent, nil }
// Put is used to insert or update an entry func (c *ZookeeperBackend) Put(entry *Entry) error { defer metrics.MeasureSince([]string{"zookeeper", "put"}, time.Now()) // Attempt to set the full path fullPath := c.nodePath(entry.Key) _, err := c.client.Set(fullPath, entry.Value, -1) // If we get ErrNoNode, we need to construct the path hierarchy if err == zk.ErrNoNode { return c.ensurePath(fullPath, entry.Value) } return err }
// Delete is used to permanently delete an entry func (c *ZookeeperBackend) Delete(key string) error { defer metrics.MeasureSince([]string{"zookeeper", "delete"}, time.Now()) if key == "" { return nil } // Delete the full path fullPath := c.nodePath(key) err := c.client.Delete(fullPath, -1) // Mask if the node does not exist if err != nil && err != zk.ErrNoNode { return fmt.Errorf("Failed to remove %q: %v", fullPath, err) } err = c.cleanupLogicalPath(key) return err }
// List is used ot list all the keys under a given // prefix, up to the next prefix. func (c *ZookeeperBackend) List(prefix string) ([]string, error) { defer metrics.MeasureSince([]string{"zookeeper", "list"}, time.Now()) // Query the children at the full path fullPath := strings.TrimSuffix(c.path+prefix, "/") result, _, err := c.client.Children(fullPath) // If the path nodes are missing, no children! if err == zk.ErrNoNode { return []string{}, nil } else if err != nil { return []string{}, err } children := []string{} for _, key := range result { childPath := fullPath + "/" + key _, stat, err := c.client.Exists(childPath) if err != nil { // Node is ought to exists, so it must be something different return []string{}, err } // Check if this entry is a leaf of a node, // and append the slash which is what Vault depends on // for iteration if stat.DataLength > 0 && stat.NumChildren > 0 { msgFmt := "Node %q is both of data and leaf type ??" panic(fmt.Sprintf(msgFmt, childPath)) } else if stat.DataLength == 0 { // No, we cannot differentiate here on number of children as node // can have all it leafs remoed, and it still is a node. children = append(children, key+"/") } else { children = append(children, key[1:]) } } sort.Strings(children) return children, nil }