1
0
mirror of https://github.com/rancher/steve.git synced 2025-05-30 10:36:31 +00:00
steve/pkg/resources/formatters/formatter.go
Diogo Souza b0e3b528a8
2.8 helm data formatter (#307)
* changing secret and configmap formatters to return decoded helm data if includeHelmData query parameter is present

* update gomod
2024-10-28 15:55:44 -05:00

142 lines
3.7 KiB
Go

package formatters
import (
"bytes"
"compress/gzip"
"encoding/base64"
"encoding/json"
"io"
"github.com/golang/protobuf/proto"
"github.com/pkg/errors"
"github.com/rancher/apiserver/pkg/types"
"github.com/rancher/norman/types/convert"
"github.com/rancher/wrangler/v2/pkg/data"
"github.com/sirupsen/logrus"
"helm.sh/helm/v3/pkg/release"
rspb "k8s.io/helm/pkg/proto/hapi/release"
)
var (
ErrNotHelmRelease = errors.New("not helm release") // error for when it's not a helm release
magicGzip = []byte{0x1f, 0x8b, 0x08} // gzip magic header
)
func HandleHelmData(request *types.APIRequest, resource *types.RawResource) {
objData := resource.APIObject.Data()
if q := request.Query.Get("includeHelmData"); q == "true" {
var helmReleaseData string
if resource.Type == "secret" {
b, err := base64.StdEncoding.DecodeString(objData.String("data", "release"))
if err != nil {
return
}
helmReleaseData = string(b)
} else {
helmReleaseData = objData.String("data", "release")
}
if objData.String("metadata", "labels", "owner") == "helm" {
rl, err := decodeHelm3(helmReleaseData)
if err != nil {
logrus.Errorf("Failed to decode helm3 release data: %v", err)
return
}
objData.SetNested(rl, "data", "release")
}
if objData.String("metadata", "labels", "OWNER") == "TILLER" {
rl, err := decodeHelm2(helmReleaseData)
if err != nil {
logrus.Errorf("Failed to decode helm2 release data: %v", err)
return
}
objData.SetNested(rl, "data", "release")
}
} else {
DropHelmData(objData)
}
}
func Pod(request *types.APIRequest, resource *types.RawResource) {
data := resource.APIObject.Data()
fields := data.StringSlice("metadata", "fields")
if len(fields) > 2 {
data.SetNested(convert.LowerTitle(fields[2]), "metadata", "state", "name")
}
}
// decodeHelm3 receives a helm3 release data string, decodes the string data using the standard base64 library
// and unmarshals the data into release.Release struct to return it.
func decodeHelm3(data string) (*release.Release, error) {
b, err := base64.StdEncoding.DecodeString(data)
if err != nil {
return nil, err
}
// Data is too small to be helm 3 release object
if len(b) <= 3 {
return nil, ErrNotHelmRelease
}
// 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 := io.ReadAll(r)
if err != nil {
return nil, err
}
b = b2
}
var rls release.Release
// unmarshal release object bytes
if err := json.Unmarshal(b, &rls); err != nil {
return nil, err
}
return &rls, nil
}
// decodeHelm2 receives a helm2 release data and returns the corresponding helm2 release proto struct
func decodeHelm2(data string) (*rspb.Release, error) {
b, err := base64.StdEncoding.DecodeString(data)
if err != nil {
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 := io.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 {
return nil, err
}
return &rls, nil
}
func DropHelmData(data data.Object) {
if data.String("metadata", "labels", "owner") == "helm" ||
data.String("metadata", "labels", "OWNER") == "TILLER" {
if data.String("data", "release") != "" {
delete(data.Map("data"), "release")
}
}
}