func (m *Manager) GroupKVReplace(name string, d []*pb.KVData) error {
	dg := &pb.Group{
		Name: &name,
		KV:   d,
	}
	_, err := m.RunGroupChain("KV-REPLACE", dg)
	return err
}
GroupKVReplace replaces an existing key on a group.  If the key
does not exist an error is returned.
package tree
import (
	"fmt"
	"strings"
	"github.com/netauth/netauth/internal/db"
	"github.com/netauth/netauth/internal/tree/util"
	pb "github.com/netauth/protocol"
)
func (m *Manager) CreateGroup(name, displayName, managedBy string, number int32) error {
	rg := &pb.Group{
		Name:        &name,
		DisplayName: &displayName,
		ManagedBy:   &managedBy,
		Number:      &number,
	}
	_, err := m.RunGroupChain("CREATE", rg)
	return err
}
func (m *Manager) FetchGroup(name string) (*pb.Group, error) {
	rg := &pb.Group{
		Name: &name,
	}
	return m.RunGroupChain("FETCH", rg)
}
func (m *Manager) DestroyGroup(name string) error {
	rg := &pb.Group{
		Name: &name,
	}
	_, err := m.RunGroupChain("DESTROY", rg)
	return err
}
func (m *Manager) UpdateGroupMeta(name string, update *pb.Group) error {
	update.Name = &name
	_, err := m.RunGroupChain("MERGE-METADATA", update)
	return err
}
func (m *Manager) ManageUntypedGroupMeta(name, mode, key, value string) ([]string, error) {
	rg := &pb.Group{
		Name:        &name,
		UntypedMeta: []string{fmt.Sprintf("%s:%s", key, value)},
	}
	chain := "FETCH"
	switch strings.ToUpper(mode) {
	case "UPSERT":
		chain = "UGM-UPSERT"
	case "CLEARFUZZY":
		chain = "UGM-CLEARFUZZY"
	case "CLEAREXACT":
		chain = "UGM-CLEAREXACT"
	default:
		mode = "READ"
	}
	g, err := m.RunGroupChain(chain, rg)
	if err != nil {
		return nil, err
	}
	if strings.ToUpper(mode) == "READ" {
		return util.PatchKeyValueSlice(g.UntypedMeta, "READ", key, ""), nil
	}
	return nil, nil
}
func (m *Manager) GroupKVGet(name string, keys []*pb.KVData) ([]*pb.KVData, error) {
	g, err := m.FetchGroup(name)
	if err != nil {
		return nil, err
	}
	if len(keys) == 1 && keys[0].GetKey() == "*" {
		return g.GetKV(), nil
	}
	out := []*pb.KVData{}
	for _, haystack := range g.GetKV() {
		for _, needle := range keys {
			if haystack.GetKey() != needle.GetKey() {
				continue
			}
			out = append(out, haystack)
		}
	}
	if len(out) == 0 {
		return nil, ErrNoSuchKey
	}
	return out, nil
}
func (m *Manager) GroupKVAdd(name string, d []*pb.KVData) error {
	dg := &pb.Group{
		Name: &name,
		KV:   d,
	}
	_, err := m.RunGroupChain("KV-ADD", dg)
	return err
}
func (m *Manager) GroupKVDel(name string, d []*pb.KVData) error {
	dg := &pb.Group{
		Name: &name,
		KV:   d,
	}
	_, err := m.RunGroupChain("KV-DEL", dg)
	return err
}