Merge pull request #8748 from christoe/christoe/8491-gzip-consul-remote-state

state/remote: Add gzip support to consul remote state (#8491)
This commit is contained in:
James Bardin 2017-03-14 15:27:46 -04:00 committed by GitHub
commit 1527eae6b7
4 changed files with 64 additions and 2 deletions

View File

@ -53,6 +53,13 @@ func New() backend.Backend {
Description: "HTTP Auth in the format of 'username:password'",
Default: "", // To prevent input
},
"gzip": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
Description: "Compress the state data using gzip",
Default: false,
},
},
}

View File

@ -85,11 +85,15 @@ func (b *Backend) State(name string) (state.State, error) {
// Determine the path of the data
path := b.path(name)
// Determine whether to gzip or not
gzip := b.configData.Get("gzip").(bool)
// Build the state client
stateMgr := &remote.State{
Client: &RemoteClient{
Client: client,
Path: path,
GZip: gzip,
},
}

View File

@ -1,6 +1,8 @@
package consul
import (
"bytes"
"compress/gzip"
"crypto/md5"
"encoding/json"
"errors"
@ -22,6 +24,7 @@ const (
type RemoteClient struct {
Client *consulapi.Client
Path string
GZip bool
consulLock *consulapi.Lock
lockCh <-chan struct{}
@ -36,18 +39,37 @@ func (c *RemoteClient) Get() (*remote.Payload, error) {
return nil, nil
}
payload := pair.Value
// If the payload starts with 0x1f, it's gzip, not json
if len(pair.Value) >= 1 && pair.Value[0] == '\x1f' {
if data, err := uncompressState(pair.Value); err == nil {
payload = data
} else {
return nil, err
}
}
md5 := md5.Sum(pair.Value)
return &remote.Payload{
Data: pair.Value,
Data: payload,
MD5: md5[:],
}, nil
}
func (c *RemoteClient) Put(data []byte) error {
payload := data
if c.GZip {
if compressedState, err := compressState(data); err == nil {
payload = compressedState
} else {
return err
}
}
kv := c.Client.KV()
_, err := kv.Put(&consulapi.KVPair{
Key: c.Path,
Value: data,
Value: payload,
}, nil)
return err
}
@ -177,3 +199,31 @@ func (c *RemoteClient) Unlock(id string) error {
return err
}
func compressState(data []byte) ([]byte, error) {
b := new(bytes.Buffer)
gz := gzip.NewWriter(b)
if _, err := gz.Write(data); err != nil {
return nil, err
}
if err := gz.Flush(); err != nil {
return nil, err
}
if err := gz.Close(); err != nil {
return nil, err
}
return b.Bytes(), nil
}
func uncompressState(data []byte) ([]byte, error) {
b := new(bytes.Buffer)
gz, err := gzip.NewReader(bytes.NewReader(data))
if err != nil {
return nil, err
}
b.ReadFrom(gz)
if err := gz.Close(); err != nil {
return nil, err
}
return b.Bytes(), nil
}

View File

@ -53,3 +53,4 @@ The following configuration options / environment variables are supported:
* `datacenter` - (Optional) The datacenter to use. Defaults to that of the agent.
* `http_auth` / `CONSUL_HTTP_AUTH` - (Optional) HTTP Basic Authentication credentials to be used when
communicating with Consul, in the format of either `user` or `user:pass`.
* `gzip` - (Optional) `true` to compress the state data using gzip, or `false` (the default) to leave it uncompressed.