mirror of https://github.com/k3s-io/k3s
Merge pull request #60755 from glb/support-b64dec-in-templates
Automatic merge from submit-queue (batch tested with PRs 61354, 61366, 61386, 61394, 60755). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. pkg/printers: Support base64 decode in kubectl get go-template **What this PR does / why we need it**: Adds a `base64decode` function to templates in `kubectl` so that it's possible to extract secret data in plaintext instead of base64 without requiring a separate executable to do the decode. Sample usage: ```sh kubectl get secret SECRET -o go-template='{{ .data.KEY | base64decode }}' ``` **Which issue(s) this PR fixes**: Fixes kubernetes/kubernetes#45293. **Special notes for your reviewer**: **Release note**: ```release-note You can now use the `base64decode` function in kubectl go templates to decode base64-encoded data, for example `kubectl get secret SECRET -o go-template='{{ .data.KEY | base64decode }}'`. ```pull/8/head
commit
1365ce3419
|
@ -69,7 +69,10 @@ filegroup(
|
|||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["humanreadable_test.go"],
|
||||
srcs = [
|
||||
"humanreadable_test.go",
|
||||
"template_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
|
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||
package printers
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
|
@ -33,7 +34,10 @@ type TemplatePrinter struct {
|
|||
|
||||
func NewTemplatePrinter(tmpl []byte) (*TemplatePrinter, error) {
|
||||
t, err := template.New("output").
|
||||
Funcs(template.FuncMap{"exists": exists}).
|
||||
Funcs(template.FuncMap{
|
||||
"exists": exists,
|
||||
"base64decode": base64decode,
|
||||
}).
|
||||
Parse(string(tmpl))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -112,3 +116,11 @@ func (p *TemplatePrinter) safeExecute(w io.Writer, obj interface{}) error {
|
|||
}
|
||||
return retErr
|
||||
}
|
||||
|
||||
func base64decode(v string) (string, error) {
|
||||
data, err := base64.StdEncoding.DecodeString(v)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("base64 decode failed: %v", err)
|
||||
}
|
||||
return string(data), nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package printers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
)
|
||||
|
||||
func TestTemplate(t *testing.T) {
|
||||
testCase := map[string]struct {
|
||||
template string
|
||||
obj runtime.Object
|
||||
expectOut string
|
||||
expectErr func(error) (string, bool)
|
||||
}{
|
||||
"support base64 decoding of secret data": {
|
||||
template: "{{ .Data.username | base64decode }}",
|
||||
obj: &api.Secret{
|
||||
Data: map[string][]byte{
|
||||
"username": []byte("hunter"),
|
||||
},
|
||||
},
|
||||
expectOut: "hunter",
|
||||
},
|
||||
"test error path for base64 decoding": {
|
||||
template: "{{ .Data.username | base64decode }}",
|
||||
obj: &badlyMarshaledSecret{},
|
||||
expectErr: func(err error) (string, bool) {
|
||||
matched := strings.Contains(err.Error(), "base64 decode")
|
||||
return "a base64 decode error", matched
|
||||
},
|
||||
},
|
||||
}
|
||||
for name, test := range testCase {
|
||||
buffer := &bytes.Buffer{}
|
||||
|
||||
p, err := NewTemplatePrinter([]byte(test.template))
|
||||
if err != nil {
|
||||
if test.expectErr == nil {
|
||||
t.Errorf("[%s]expected success but got:\n %v\n", name, err)
|
||||
continue
|
||||
}
|
||||
if expected, ok := test.expectErr(err); !ok {
|
||||
t.Errorf("[%s]expect:\n %v\n but got:\n %v\n", name, expected, err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
err = p.PrintObj(test.obj, buffer)
|
||||
if err != nil {
|
||||
if test.expectErr == nil {
|
||||
t.Errorf("[%s]expected success but got:\n %v\n", name, err)
|
||||
continue
|
||||
}
|
||||
if expected, ok := test.expectErr(err); !ok {
|
||||
t.Errorf("[%s]expect:\n %v\n but got:\n %v\n", name, expected, err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if test.expectErr != nil {
|
||||
t.Errorf("[%s]expect:\n error\n but got:\n no error\n", name)
|
||||
continue
|
||||
}
|
||||
|
||||
if test.expectOut != buffer.String() {
|
||||
t.Errorf("[%s]expect:\n %v\n but got:\n %v\n", name, test.expectOut, buffer.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type badlyMarshaledSecret struct {
|
||||
api.Secret
|
||||
}
|
||||
|
||||
func (a badlyMarshaledSecret) MarshalJSON() ([]byte, error) {
|
||||
return []byte(`{"apiVersion":"v1","Data":{"username":"--THIS IS NOT BASE64--"},"kind":"Secret"}`), nil
|
||||
}
|
Loading…
Reference in New Issue