From 70d0048d3530fcb3d00b12d5e895b9ec3977b538 Mon Sep 17 00:00:00 2001 From: Jingfang Liu Date: Fri, 23 Feb 2018 11:34:23 -0800 Subject: [PATCH] Add secret resource --- pkg/kinflate/resource/secret.go | 71 ++++++++++++++++++++++++++++ pkg/kinflate/resource/secret_test.go | 62 ++++++++++++++++++++++++ 2 files changed, 133 insertions(+) create mode 100644 pkg/kinflate/resource/secret.go create mode 100644 pkg/kinflate/resource/secret_test.go diff --git a/pkg/kinflate/resource/secret.go b/pkg/kinflate/resource/secret.go new file mode 100644 index 000000000..a8d4c3037 --- /dev/null +++ b/pkg/kinflate/resource/secret.go @@ -0,0 +1,71 @@ +/* +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 resource + +import ( + "context" + "os" + "os/exec" + "path/filepath" + "time" + + corev1 "k8s.io/api/core/v1" + manifest "k8s.io/kubectl/pkg/apis/manifest/v1alpha1" +) + +// NewFromSecretGenerator takes a SecretGenerator and executes its command in directory p +// then writes the output to a Resource object and returns a pointer to it. +func NewFromSecretGenerator(s manifest.SecretGenerator, p string) (*Resource, error) { + corev1secret := &corev1.Secret{} + corev1secret.APIVersion = "v1" + corev1secret.Kind = "Secret" + corev1secret.Name = s.Name + corev1secret.Type = corev1.SecretType(s.Type) + if corev1secret.Type == "" { + corev1secret.Type = corev1.SecretTypeOpaque + } + corev1secret.Data = map[string][]byte{} + + for k, v := range s.Commands { + out, err := createSecretKey(p, v) + if err != nil { + return nil, err + } + corev1secret.Data[k] = out + } + + obj, err := objectToUnstructured(corev1secret) + + if err != nil { + return nil, err + } + + return &Resource{Data: obj}, nil +} + +func createSecretKey(wd string, command string) ([]byte, error) { + fi, err := os.Stat(wd) + if err != nil || !fi.IsDir() { + wd = filepath.Dir(wd) + } + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + cmd := exec.CommandContext(ctx, "sh", "-c", command) + cmd.Dir = wd + + return cmd.Output() +} diff --git a/pkg/kinflate/resource/secret_test.go b/pkg/kinflate/resource/secret_test.go new file mode 100644 index 000000000..2e5bf7567 --- /dev/null +++ b/pkg/kinflate/resource/secret_test.go @@ -0,0 +1,62 @@ +/* +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 resource + +import ( + "encoding/base64" + "reflect" + "testing" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + manifest "k8s.io/kubectl/pkg/apis/manifest/v1alpha1" +) + +func TestNewFromSecretGenerator(t *testing.T) { + secret := manifest.SecretGenerator{ + Name: "secret", + Commands: map[string]string{ + "DB_USERNAME": "printf admin", + "DB_PASSWORD": "printf somepw", + }, + Type: "Opaque", + } + re, err := NewFromSecretGenerator(secret, ".") + + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + expected := &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": "v1", + "kind": "Secret", + "metadata": map[string]interface{}{ + "name": "secret", + "creationTimestamp": nil, + }, + "type": string(corev1.SecretTypeOpaque), + "data": map[string]interface{}{ + "DB_USERNAME": base64.StdEncoding.EncodeToString([]byte("admin")), + "DB_PASSWORD": base64.StdEncoding.EncodeToString([]byte("somepw")), + }, + }, + } + + if !reflect.DeepEqual(*re.Data, *expected) { + t.Fatalf("%#v\ndoesn't match expected:\n%#v", *re.Data, *expected) + } +}