From 4cccaa0e0eb71c1755880ea4d71f440e1973aa29 Mon Sep 17 00:00:00 2001 From: Adnan Issadeen Date: Tue, 4 Sep 2018 17:55:07 +0530 Subject: [PATCH] Initial commit --- Gopkg.lock | 33 +++++++++++++++++++ Gopkg.toml | 34 ++++++++++++++++++++ cmd/get.go | 82 +++++++++++++++++++++++++++++++++++++++++++++++ cmd/root.go | 20 ++++++++++++ core/getsecret.go | 71 ++++++++++++++++++++++++++++++++++++++++ main.go | 9 ++++++ 6 files changed, 249 insertions(+) create mode 100644 Gopkg.lock create mode 100644 Gopkg.toml create mode 100644 cmd/get.go create mode 100644 cmd/root.go create mode 100644 core/getsecret.go create mode 100644 main.go diff --git a/Gopkg.lock b/Gopkg.lock new file mode 100644 index 0000000..8d43ca1 --- /dev/null +++ b/Gopkg.lock @@ -0,0 +1,33 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + digest = "1:870d441fe217b8e689d7949fef6e43efbc787e50f200cb1e70dbca9204a1d6be" + name = "github.com/inconshreveable/mousetrap" + packages = ["."] + pruneopts = "UT" + revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75" + version = "v1.0" + +[[projects]] + digest = "1:645cabccbb4fa8aab25a956cbcbdf6a6845ca736b2c64e197ca7cbb9d210b939" + name = "github.com/spf13/cobra" + packages = ["."] + pruneopts = "UT" + revision = "ef82de70bb3f60c65fb8eebacbb2d122ef517385" + version = "v0.0.3" + +[[projects]] + digest = "1:dab83a1bbc7ad3d7a6ba1a1cc1760f25ac38cdf7d96a5cdd55cd915a4f5ceaf9" + name = "github.com/spf13/pflag" + packages = ["."] + pruneopts = "UT" + revision = "9a97c102cda95a86cec2345a6f09f55a939babf5" + version = "v1.0.2" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + input-imports = ["github.com/spf13/cobra"] + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml new file mode 100644 index 0000000..cd6fa38 --- /dev/null +++ b/Gopkg.toml @@ -0,0 +1,34 @@ +# Gopkg.toml example +# +# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html +# for detailed Gopkg.toml documentation. +# +# required = ["github.com/user/thing/cmd/thing"] +# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] +# +# [[constraint]] +# name = "github.com/user/project" +# version = "1.0.0" +# +# [[constraint]] +# name = "github.com/user/project2" +# branch = "dev" +# source = "github.com/myfork/project2" +# +# [[override]] +# name = "github.com/x/y" +# version = "2.4.0" +# +# [prune] +# non-go = false +# go-tests = true +# unused-packages = true + + +[prune] + go-tests = true + unused-packages = true + +[[constraint]] + name = "github.com/spf13/cobra" + version = "0.0.3" diff --git a/cmd/get.go b/cmd/get.go new file mode 100644 index 0000000..f03bd46 --- /dev/null +++ b/cmd/get.go @@ -0,0 +1,82 @@ +package cmd + +import ( + "fmt" + "log" + "sort" + + "encoding/base64" + + "github.com/bufferapp/kubesecret/core" + "github.com/spf13/cobra" +) + +var namespace string +var secretKey string +var allKeys bool + +var getCmd = &cobra.Command{ + Use: "get", + Short: "Gets the keys and their values for a given secret", + Run: func(cmd *cobra.Command, args []string) { + s, err := core.GetSecretsByNamespaceAndName(namespace, args[0]) + if err == nil { + keys := make([]string, 0, len(s.Data)) + for k := range s.Data { + keys = append(keys, k) + } + sort.Strings(keys) + + if secretKey == "" { + if allKeys { + fmt.Printf("List of keys with associated values\n\n") + for _, k := range keys { + value, err := base64.StdEncoding.DecodeString(s.Data[k]) + if err != nil { + log.Fatalln(err) + } else { + fmt.Printf("%s: %s\n ------------ \n", k, value) + } + } + fmt.Printf("\n\n") + } + fmt.Printf("List of all keys for %s\n\n", args[0]) + for _, k := range keys { + fmt.Printf("%s\n", k) + } + fmt.Printf("\n\nUse kubesecret get %s -k key --namespace %s to print the value for a specific key\n", args[0], namespace) + } else { + found := false + for k, v := range s.Data { + if found { + break + } else { + if k == secretKey { + found = true + decodedValue, err := base64.StdEncoding.DecodeString(v) + if err != nil { + log.Fatalln(err) + } else { + fmt.Printf("%s: %s\n", k, decodedValue) + } + } + } + } + if !found { + fmt.Println("Could not find the key specified") + } + } + } else { + fmt.Println(err) + } + }, + Args: cobra.ExactArgs(1), +} + +func init() { + rootCmd.AddCommand(getCmd) + getCmd.Flags().StringVarP(&namespace, "namespace", "n", "", "Namespace to search for secret in. (Required)") + getCmd.Flags().StringVarP(&secretKey, "key", "k", "", "Specific key value to get") + getCmd.Flags().BoolVar(&allKeys, "all-keys", false, "List the values of all the keys") + getCmd.MarkFlagRequired("namespace") +} diff --git a/cmd/root.go b/cmd/root.go new file mode 100644 index 0000000..ec4d002 --- /dev/null +++ b/cmd/root.go @@ -0,0 +1,20 @@ +package cmd + +import ( + "fmt" + "os" + + "github.com/spf13/cobra" +) + +var rootCmd = &cobra.Command{ + Use: "kubesecret", + Short: "Gets a specified secret for a given namespace", +} + +func Execute() { + if err := rootCmd.Execute(); err != nil { + fmt.Println(err) + os.Exit(1) + } +} diff --git a/core/getsecret.go b/core/getsecret.go new file mode 100644 index 0000000..238a059 --- /dev/null +++ b/core/getsecret.go @@ -0,0 +1,71 @@ +package core + +import ( + "encoding/json" + "errors" + "log" + "os/exec" + "strings" +) + +type metadata struct { + Name string `json:"Name"` + Namespace string `json:"namespace"` +} +type Secret struct { + APIVersion string `json:"apiVersion"` + Type string `json:"type"` + Kind string `json:"kind"` + Metadata metadata `json:"metadata"` + Data map[string]string `json:"data"` +} + +type secrets struct { + APIVersion string `json:"apiVersion"` + Items []Secret `json:"Items"` +} + +// GetSecrets Executes the kubectl command line +func GetSecrets(namespace string) { + log.Println("Executing kubectl") + out, _ := exec.Command("kubectl", "get", "secrets", "--namespace", "buffer", "-o", "json").CombinedOutput() + + var dataRetrived map[string]interface{} + if err := json.Unmarshal(out, &dataRetrived); err != nil { + log.Fatal(err) + } + for k := range dataRetrived { + log.Println(k) + } + + var secretsRetrieved secrets + if err := json.Unmarshal(out, &secretsRetrieved); err != nil { + log.Fatal(err) + } + log.Printf("Length of items: %d\n", len(secretsRetrieved.Items)) + log.Println(secretsRetrieved.Items[0].APIVersion) + log.Println(len(secretsRetrieved.Items[0].Data)) + log.Println(secretsRetrieved.Items[0].Metadata.Name) + for _, secretRetrieved := range secretsRetrieved.Items { + log.Println(secretRetrieved.Metadata.Name) + for k, v := range secretRetrieved.Data { + log.Printf("%s: %s\n", k, v) + } + } +} + +// GetSecretsByNamespaceAndName returns a secret for a given namespace and secret name +func GetSecretsByNamespaceAndName(namespace, secretName string) (Secret, error) { + if namespace == "" || secretName == "" { + return Secret{}, errors.New("Namespace or secretName cannot be empty") + } + out, _ := exec.Command("kubectl", "get", "secret", "--namespace", namespace, secretName, "-o", "json").CombinedOutput() + var secretRetrieved Secret + if strings.Contains(string(out), "Error from server (NotFound)") { + return Secret{}, errors.New(string(out)) + } + if err := json.Unmarshal(out, &secretRetrieved); err != nil { + return Secret{}, err + } + return secretRetrieved, nil +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..a1fd5a9 --- /dev/null +++ b/main.go @@ -0,0 +1,9 @@ +package main + +import ( + "github.com/bufferapp/kubesecret/cmd" +) + +func main() { + cmd.Execute() +}