Skip to content

Commit

Permalink
Merge pull request IBM-Cloud#1 from compose/clicompat
Browse files Browse the repository at this point in the history
Redis CLI Compatibility on the command line
  • Loading branch information
codepope committed Aug 7, 2018
2 parents ade917e + 022575c commit f9e0447
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 13 deletions.
36 changes: 26 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,41 @@

## About

Redli is a Go-based alternative to the official Redis-cli application. It's major feature is that it understands redis: and rediss: URLs and, unlike Redis-cli currently, can connect to TLS/SSL secured Redis without the need for tunnels. It also has a number of flags and environment variables for passing server certificates over as files or base64 strings.
Redli is a Go-based alternative to the official Redis-cli application. It's major feature is that it mimics the redis-cli command line argurments while also understanding rediss: protocols and supporting a `--tls` flag allowing it to connect to TLS/SSL secured Redis without the need for tunnels. It also has a number of flags and environment variables for passing server certificates over as files or base64 strings. Note, passing a certificate turns TLS on by default.

## Usage

```text
redli [<flags>] <url>
```
redli [<flags>] [<commands>...]
```

### Flags

* `--help` Show context-sensitive help (also try --help-long and --help-man).
* `--debug` Enable debug mode.
* `--long` Enable long prompt with host/port
* `--certfile=CERTFILE` Self-signed certificate file for validation
* `--certb64=CERTB64` Self-signed certificate string as base64 for validation
```text
--help Show context-sensitive help (also try --help-long and --help-man).
--debug Enable debug mode.
--long Enable long prompt with host/port
-u, --uri=URI URI to connect to
-h, --host="127.0.0.1" Host to connect to
-p, --port=6379 Port to connect to
-a, --auth=AUTH Password to use when connecting
-n, --ndb=0 Redis database to access
--tls Enable TLS/SSL
--certfile=CERTFILE Self-signed certificate file for validation
--certb64=CERTB64 Self-signed certificate string as base64 for validation
```

* `URI` URI to connect To. It follow the format of [the provisional IANA spec for Redis URLs](https://www.iana.org/assignments/uri-schemes/prov/redis), but with the option to denote a TLS secured connection with the protocol rediss:.

### Args

```text
[<commands>] Redis commands and values
```

#### Args
e.g. `INFO KEYSPACE`

* `<url>` URL to connect To. The URL is, at this point in development, mandatory. It follow the format of [the provisional IANA spec for Redis URLs](https://www.iana.org/assignments/uri-schemes/prov/redis), but with the option to denote a TLS secured connection with the protocol rediss:.
Be aware of interactions with wild cards and special characters in the shell; quote and escape as appropriate.

## License

Expand Down
67 changes: 64 additions & 3 deletions main.go → redli.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import (
"fmt"
"io/ioutil"
"log"
"os"
"sort"
"strconv"
"strings"

// "github.com/chzyer/readline"
Expand All @@ -21,9 +23,15 @@ import (
var (
debug = kingpin.Flag("debug", "Enable debug mode.").Bool()
longprompt = kingpin.Flag("long", "Enable long prompt with host/port").Bool()
redisurl = kingpin.Arg("url", "URL to connect To.").Required().URL()
redisurl = kingpin.Flag("uri", "URI to connect to").Short('u').URL()
redishost = kingpin.Flag("host", "Host to connect to").Short('h').Default("127.0.0.1").String()
redisport = kingpin.Flag("port", "Port to connect to").Short('p').Default("6379").Int()
redisauth = kingpin.Flag("auth", "Password to use when connecting").Short('a').String()
redisdb = kingpin.Flag("ndb", "Redis database to access").Short('n').Default("0").Int()
redistls = kingpin.Flag("tls", "Enable TLS/SSL").Default("false").Bool()
rediscertfile = kingpin.Flag("certfile", "Self-signed certificate file for validation").Envar("REDIS_CERTFILE").File()
rediscertb64 = kingpin.Flag("certb64", "Self-signed certificate string as base64 for validation").Envar("REDIS_CERTB64").String()
commandargs = kingpin.Arg("commands", "Redis commands and values").Strings()
)

var (
Expand All @@ -50,6 +58,26 @@ func main() {
cert = mycert
}

connectionurl := ""

if *redisurl == nil {
// With no URI, build a URI from other flags
if *redistls {
connectionurl = "rediss:https://"
} else {
connectionurl = "redis:https://"
}

if redisauth != nil {
connectionurl = connectionurl + "x:" + *redisauth + "@"
}

connectionurl = connectionurl + *redishost + ":" + strconv.Itoa(*redisport) + "/" + strconv.Itoa(*redisdb)
} else {
connectionurl = (*redisurl).String()
}

// If we have a certificate, then assume TLS
if len(cert) > 0 {

config := &tls.Config{RootCAs: x509.NewCertPool(),
Expand All @@ -61,20 +89,53 @@ func main() {
}

var err error
conn, err = redis.DialURL((*redisurl).String(), redis.DialTLSConfig(config))
conn, err = redis.DialURL(connectionurl, redis.DialTLSConfig(config))
if err != nil {
log.Fatal("Dial", err)
}
defer conn.Close()
} else {
var err error
conn, err = redis.DialURL((*redisurl).String())
conn, err = redis.DialURL(connectionurl)
if err != nil {
log.Fatal("Dial", err)
}
defer conn.Close()
}

// We may not need to carry on setting up the interactive front end so...
if *commandargs != nil {
command := *commandargs
var args = make([]interface{}, len(command[1:]))
for i, d := range command[1:] {
args[i] = d
}
result, err := conn.Do(command[0], args...)

if err != nil {
log.Fatal(err)
}

switch v := result.(type) {
case redis.Error:
fmt.Printf("%s\n", v.Error())
case int64:
fmt.Printf("%d\n", v)
case string:
fmt.Printf("%s\n", v)
case []byte:
fmt.Printf("%s\n", string(v))
case nil:
fmt.Printf("nil\n")
case []interface{}:
for i, j := range v {
fmt.Printf("%d) %s\n", i+1, j)
}
}

os.Exit(0)
}

json.Unmarshal([]byte(redisCommandsJSON), &rawrediscommands)

rediscommands := make(map[string]Command, len(rawrediscommands))
Expand Down

0 comments on commit f9e0447

Please sign in to comment.