mirror of
https://github.com/helm/helm.git
synced 2026-04-15 21:59:50 -04:00
Add compression to configmap storage driver
This commit changes the configmap storage driver to compress the serialized release before storing it as a base64 encoded string. This change is backward compatible as it handles existing releases gracefully by skipping the decompression step when the gzip magic header is not present.
This commit is contained in:
parent
05c04bccae
commit
eb4b78bbbe
2 changed files with 67 additions and 2 deletions
|
|
@ -17,8 +17,11 @@ limitations under the License.
|
|||
package driver // import "k8s.io/helm/pkg/storage/driver"
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"strconv"
|
||||
"time"
|
||||
|
|
@ -40,6 +43,8 @@ const ConfigMapsDriverName = "ConfigMap"
|
|||
|
||||
var b64 = base64.StdEncoding
|
||||
|
||||
var magicGzip = []byte{0x1f, 0x8b, 0x08}
|
||||
|
||||
// ConfigMaps is a wrapper around an implementation of a kubernetes
|
||||
// ConfigMapsInterface.
|
||||
type ConfigMaps struct {
|
||||
|
|
@ -254,13 +259,23 @@ func newConfigMapsObject(key string, rls *rspb.Release, lbs labels) (*api.Config
|
|||
}
|
||||
|
||||
// encodeRelease encodes a release returning a base64 encoded
|
||||
// binary protobuf encoding representation, or error.
|
||||
// gzipped binary protobuf encoding representation, or error.
|
||||
func encodeRelease(rls *rspb.Release) (string, error) {
|
||||
b, err := proto.Marshal(rls)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return b64.EncodeToString(b), nil
|
||||
var buf bytes.Buffer
|
||||
w, err := gzip.NewWriterLevel(&buf, gzip.BestCompression)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if _, err = w.Write(b); err != nil {
|
||||
return "", err
|
||||
}
|
||||
w.Close()
|
||||
|
||||
return b64.EncodeToString(buf.Bytes()), nil
|
||||
}
|
||||
|
||||
// decodeRelease decodes the bytes in data into a release
|
||||
|
|
@ -274,6 +289,21 @@ func decodeRelease(data string) (*rspb.Release, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// For backwards compatibility with releases that were stored before
|
||||
// compression was introduced we skip decompression if the
|
||||
// gzip magic header is not found
|
||||
if bytes.Equal(b[0:3], magicGzip) {
|
||||
r, err := gzip.NewReader(bytes.NewReader(b))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b2, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b = b2
|
||||
}
|
||||
|
||||
var rls rspb.Release
|
||||
// unmarshal protobuf bytes
|
||||
if err := proto.Unmarshal(b, &rls); err != nil {
|
||||
|
|
|
|||
|
|
@ -14,10 +14,14 @@ limitations under the License.
|
|||
package driver
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
|
||||
rspb "k8s.io/helm/pkg/proto/hapi/release"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
)
|
||||
|
||||
func TestConfigMapName(t *testing.T) {
|
||||
|
|
@ -46,6 +50,37 @@ func TestConfigMapGet(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestUNcompressedConfigMapGet(t *testing.T) {
|
||||
vers := int32(1)
|
||||
name := "smug-pigeon"
|
||||
key := testKey(name, vers)
|
||||
rel := releaseStub(name, vers, rspb.Status_DEPLOYED)
|
||||
|
||||
// Create a test fixture which contains an uncompressed release
|
||||
cfgmap, err := newConfigMapsObject(key, rel, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create configmap: %s", err)
|
||||
}
|
||||
b, err := proto.Marshal(rel)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to marshal release: %s", err)
|
||||
}
|
||||
cfgmap.Data["release"] = base64.StdEncoding.EncodeToString(b)
|
||||
var mock MockConfigMapsInterface
|
||||
mock.objects = map[string]*api.ConfigMap{key: cfgmap}
|
||||
cfgmaps := NewConfigMaps(&mock)
|
||||
|
||||
// get release with key
|
||||
got, err := cfgmaps.Get(key)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to get release: %s", err)
|
||||
}
|
||||
// compare fetched release with original
|
||||
if !reflect.DeepEqual(rel, got) {
|
||||
t.Errorf("Expected {%q}, got {%q}", rel, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigMapList(t *testing.T) {
|
||||
cfgmaps := newTestFixtureCfgMaps(t, []*rspb.Release{
|
||||
releaseStub("key-1", 1, rspb.Status_DELETED),
|
||||
|
|
|
|||
Loading…
Reference in a new issue