add InfoMap command (#2665)

Add an extended version of Info() to parse the results from a call to redis.Info so that it’s simpler to operate on any given item in the result.

Signed-off-by: Nic Gibson <nic.gibson@redis.com>
This commit is contained in:
Nic Gibson 2023-10-30 16:07:42 +00:00 committed by GitHub
parent 4408f8cfb2
commit 343016bf72
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 108 additions and 0 deletions

View File

@ -1,9 +1,11 @@
package redis
import (
"bufio"
"context"
"fmt"
"net"
"regexp"
"strconv"
"strings"
"time"
@ -5298,3 +5300,84 @@ type LibraryInfo struct {
LibName *string
LibVer *string
}
// -------------------------------------------
type InfoCmd struct {
baseCmd
val map[string]map[string]string
}
var _ Cmder = (*InfoCmd)(nil)
func NewInfoCmd(ctx context.Context, args ...interface{}) *InfoCmd {
return &InfoCmd{
baseCmd: baseCmd{
ctx: ctx,
args: args,
},
}
}
func (cmd *InfoCmd) SetVal(val map[string]map[string]string) {
cmd.val = val
}
func (cmd *InfoCmd) Val() map[string]map[string]string {
return cmd.val
}
func (cmd *InfoCmd) Result() (map[string]map[string]string, error) {
return cmd.Val(), cmd.Err()
}
func (cmd *InfoCmd) String() string {
return cmdString(cmd, cmd.val)
}
func (cmd *InfoCmd) readReply(rd *proto.Reader) error {
val, err := rd.ReadString()
if err != nil {
return err
}
section := ""
scanner := bufio.NewScanner(strings.NewReader(val))
moduleRe := regexp.MustCompile(`module:name=(.+?),(.+)$`)
for scanner.Scan() {
line := scanner.Text()
if strings.HasPrefix(line, "#") {
if cmd.val == nil {
cmd.val = make(map[string]map[string]string)
}
section = strings.TrimPrefix(line, "# ")
cmd.val[section] = make(map[string]string)
} else if line != "" {
if section == "Modules" {
kv := moduleRe.FindStringSubmatch(line)
if len(kv) == 3 {
cmd.val[section][kv[1]] = kv[2]
}
} else {
kv := strings.SplitN(line, ":", 2)
if len(kv) == 2 {
cmd.val[section][kv[0]] = kv[1]
}
}
}
}
return nil
}
func (cmd *InfoCmd) Item(section, key string) string {
if cmd.val == nil {
return ""
} else if cmd.val[section] == nil {
return ""
} else {
return cmd.val[section][key]
}
}

View File

@ -571,6 +571,17 @@ func (c cmdable) Info(ctx context.Context, sections ...string) *StringCmd {
return cmd
}
func (c cmdable) InfoMap(ctx context.Context, sections ...string) *InfoCmd {
args := make([]interface{}, 1+len(sections))
args[0] = "info"
for i, section := range sections {
args[i+1] = section
}
cmd := NewInfoCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) LastSave(ctx context.Context) *IntCmd {
cmd := NewIntCmd(ctx, "lastsave")
_ = c(ctx, cmd)

View File

@ -335,6 +335,20 @@ var _ = Describe("Commands", func() {
Expect(info.Val()).NotTo(Equal(""))
})
It("should InfoMap", Label("redis.info"), func() {
info := client.InfoMap(ctx)
Expect(info.Err()).NotTo(HaveOccurred())
Expect(info.Val()).NotTo(BeNil())
info = client.InfoMap(ctx, "dummy")
Expect(info.Err()).NotTo(HaveOccurred())
Expect(info.Val()).To(BeNil())
info = client.InfoMap(ctx, "server")
Expect(info.Err()).NotTo(HaveOccurred())
Expect(info.Val()).To(HaveLen(1))
})
It("should Info cpu", func() {
info := client.Info(ctx, "cpu")
Expect(info.Err()).NotTo(HaveOccurred())