-
Notifications
You must be signed in to change notification settings - Fork 457
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for SRV records for memcache clients
This allows MEMCAHE_SRV to be specified as an SRV record from which multiple memcache hosts can be resolved. For example: MEMCACHE_SRV=_memcache._tcp.mylovelydomain.com This can be used instead of MEMCACHE_HOST_PORT. This will then be resolved and whatever set of servers it represents will be used as the set of memcache servers to connect to. At this stage neither priority or weight is supported, though weight could be fairly straightforwardly in future. The SRV can be polled periodically for new servers by setting the following env var (with 0 meaning "never check"): MEMCACHE_SRV_REFRESH=600s # supports standard go durations Signed-off-by: Peter Marsh <[email protected]>
- Loading branch information
1 parent
60c8eb0
commit 6cdcee2
Showing
7 changed files
with
221 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package srv | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"net" | ||
"regexp" | ||
|
||
logger "github.com/sirupsen/logrus" | ||
) | ||
|
||
var srvRegex = regexp.MustCompile(`^_(.+?)\._(.+?)\.(.+)$`) | ||
|
||
func ParseSrv(srv string) (string, string, string, error) { | ||
matches := srvRegex.FindStringSubmatch(srv) | ||
if matches == nil { | ||
errorText := fmt.Sprintf("could not parse %s to SRV parts", srv) | ||
logger.Errorf(errorText) | ||
return "", "", "", errors.New(errorText) | ||
} | ||
return matches[1], matches[2], matches[3], nil | ||
} | ||
|
||
func ServerStringsFromSrv(srv string) ([]string, error) { | ||
service, proto, name, err := ParseSrv(srv) | ||
|
||
if err != nil { | ||
logger.Errorf("failed to parse SRV: %s", err) | ||
return nil, err | ||
} | ||
|
||
_, srvs, err := net.LookupSRV(service, proto, name) | ||
|
||
if err != nil { | ||
logger.Errorf("failed to lookup SRV: %s", err) | ||
return nil, err | ||
} | ||
|
||
logger.Debugf("found %v servers(s) from SRV", len(srvs)) | ||
|
||
serversFromSrv := make([]string, len(srvs)) | ||
for i, srv := range srvs { | ||
server := fmt.Sprintf("%s:%v", srv.Target, srv.Port) | ||
logger.Debugf("server from srv[%v]: %s", i, server) | ||
serversFromSrv[i] = fmt.Sprintf("%s:%v", srv.Target, srv.Port) | ||
} | ||
|
||
return serversFromSrv, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package srv | ||
|
||
import ( | ||
"errors" | ||
"net" | ||
"testing" | ||
|
||
"github.com/envoyproxy/ratelimit/src/srv" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestParseSrv(t *testing.T) { | ||
service, proto, name, err := srv.ParseSrv("_something._tcp.example.org.") | ||
assert.Equal(t, service, "something") | ||
assert.Equal(t, proto, "tcp") | ||
assert.Equal(t, name, "example.org.") | ||
assert.Nil(t, err) | ||
|
||
service, proto, name, err = srv.ParseSrv("_something-else._udp.example.org") | ||
assert.Equal(t, service, "something-else") | ||
assert.Equal(t, proto, "udp") | ||
assert.Equal(t, name, "example.org") | ||
assert.Nil(t, err) | ||
|
||
_, _, _, err = srv.ParseSrv("example.org") | ||
assert.Equal(t, err, errors.New("could not parse example.org to SRV parts")) | ||
} | ||
|
||
func TestServerStringsFromSrvWhenSrvIsNotWellFormed(t *testing.T) { | ||
_, err := srv.ServerStringsFromSrv("example.org") | ||
assert.Equal(t, err, errors.New("could not parse example.org to SRV parts")) | ||
} | ||
|
||
func TestServerStringsFromSevWhenSrvIsWellFormedButNotLookupable(t *testing.T) { | ||
_, err := srv.ServerStringsFromSrv("_something._tcp.example.invalid") | ||
var e *net.DNSError | ||
if errors.As(err, &e) { | ||
assert.Equal(t, e.Err, "no such host") | ||
assert.Equal(t, e.Name, "_something._tcp.example.invalid") | ||
assert.False(t, e.IsTimeout) | ||
assert.False(t, e.IsTemporary) | ||
assert.True(t, e.IsNotFound) | ||
} else { | ||
t.Fail() | ||
} | ||
} | ||
|
||
func TestServerStrings(t *testing.T) { | ||
// it seems reasonable to think _xmpp-server._tcp.gmail.com will be available for a long time! | ||
servers, err := srv.ServerStringsFromSrv("_xmpp-server._tcp.gmail.com.") | ||
assert.True(t, len(servers) > 0) | ||
for _, s := range servers { | ||
assert.Regexp(t, `^.*xmpp-server.*google.com.:\d+$`, s) | ||
} | ||
assert.Nil(t, err) | ||
} |