Skip to content

Commit

Permalink
Add secrets API
Browse files Browse the repository at this point in the history
The secrets API allows for re-creation of existing secrets in
the cluster when reinstalling apps. This also refactors to a
pattern that can be reused in other apps.

Signed-off-by: Alex Ellis (OpenFaaS Ltd) <alexellis2@gmail.com>
  • Loading branch information
alexellis committed Dec 5, 2020
1 parent 55e27c5 commit e9186bf
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 32 deletions.
121 changes: 92 additions & 29 deletions cmd/apps/inletsoperator_app.go
Expand Up @@ -4,7 +4,9 @@
package apps

import (
"bytes"
"fmt"
"io"
"io/ioutil"
"log"
"os"
Expand Down Expand Up @@ -46,6 +48,29 @@ func MakeInstallInletsOperator() *cobra.Command {
inletsOperator.Flags().String("pro-client-image", "", "Docker image for inlets-pro's client")
inletsOperator.Flags().StringArray("set", []string{}, "Use custom flags or override existing flags \n(example --set image=org/repo:tag)")

inletsOperator.PreRunE = func(command *cobra.Command, args []string) error {
tokenFileName, _ := command.Flags().GetString("token-file")
tokenString, _ := command.Flags().GetString("token")

if len(tokenFileName) > 0 && len(tokenString) > 0 {
return fmt.Errorf(`--token-file or --access-key is a required field for your cloud API token or service account JSON`)
}
if len(tokenFileName) > 0 {
if _, err := os.Stat(tokenFileName); err != nil {
return err
}
}

secretKeyFile, _ := command.Flags().GetString("secret-key-file")
if len(secretKeyFile) > 0 {
if _, err := os.Stat(secretKeyFile); err != nil {
return err
}
}

return nil
}

inletsOperator.RunE = func(command *cobra.Command, args []string) error {
kubeConfigPath, _ := command.Flags().GetString("kubeconfig")
if err := config.SetKubeconfig(kubeConfigPath); err != nil {
Expand All @@ -65,11 +90,8 @@ func MakeInstallInletsOperator() *cobra.Command {
}

clientArch, clientOS := env.GetClientArch()

fmt.Printf("Client: %q, %q\n", clientArch, clientOS)

log.Printf("User dir established as: %s\n", userPath)

os.Setenv("HELM_HOME", path.Join(userPath, ".helm"))

_, err = helm.TryDownloadHelm(userPath, clientArch, clientOS)
Expand Down Expand Up @@ -101,42 +123,40 @@ func MakeInstallInletsOperator() *cobra.Command {
tokenFileName, _ := command.Flags().GetString("token-file")
tokenString, _ := command.Flags().GetString("token")

var accessKeyFrom, accessKeyValue string
s := Secret{
Namespace: namespace,
Name: "inlets-access-key",
}
if len(tokenFileName) > 0 {
accessKeyFrom = "--from-file"
accessKeyValue = tokenFileName
} else if len(tokenString) > 0 {
accessKeyFrom = "--from-literal"
accessKeyValue = tokenString
s.Literals = append(s.Literals, SecretLiteral{
Name: "inlets-access-key",
FromFile: tokenFileName,
})
} else {
return fmt.Errorf(`--token-file or --access-key is a required field for your cloud API token or service account JSON`)
s.Literals = append(s.Literals, SecretLiteral{
Name: "inlets-access-key",
FromValue: tokenString,
})
}

res, err := k8s.KubectlTask("create", "secret", "generic",
"inlets-access-key",
"--namespace="+namespace,
accessKeyFrom, "inlets-access-key="+accessKeyValue)

err = applySecret(s)
if err != nil {
return err
} else if len(res.Stderr) > 0 && strings.Contains(res.Stderr, "AlreadyExists") {
fmt.Println("[Warning] secret inlets-access-key already exists and will be used.")
} else if len(res.Stderr) > 0 {
return fmt.Errorf("error from kubectl\n%q", res.Stderr)
}

secretKeyFile, _ := command.Flags().GetString("secret-key-file")

if len(secretKeyFile) > 0 {
res, err := k8s.KubectlTask("create", "secret", "generic",
"inlets-secret-key",
"--namespace="+namespace,
"--from-file", "inlets-secret-key="+secretKeyFile)
if len(res.Stderr) > 0 && strings.Contains(res.Stderr, "AlreadyExists") {
fmt.Println("[Warning] secret inlets-access-key already exists and will be used.")
} else if len(res.Stderr) > 0 {
return fmt.Errorf("error from kubectl\n%q", res.Stderr)
} else if err != nil {
s := Secret{
Namespace: namespace,
Name: "inlets-secret-key",
}
s.Literals = append(s.Literals, SecretLiteral{
Name: "inlets-access-key",
FromFile: secretKeyFile,
})

err = applySecret(s)
if err != nil {
return err
}
}
Expand Down Expand Up @@ -305,3 +325,46 @@ const inletsOperatorPostInstallMsg = `==========================================
= inlets-operator has been installed. =
=======================================================================` +
"\n\n" + InletsOperatorInfoMsg + "\n\n" + pkg.ThanksForUsing

type Secret struct {
Namespace string
Name string
Stdin io.Reader
Literals []SecretLiteral
}

type SecretLiteral struct {
Name string
FromFile string
FromValue string
}

func applySecret(s Secret) error {
parts := []string{"create", "secret", "generic", s.Name, "--dry-run=client", "-o=yaml"}

for _, l := range s.Literals {
if len(l.FromFile) > 0 {
parts = append(parts, "--from-file", s.Name+"="+l.FromFile)
} else {
parts = append(parts, "--from-literal", s.Name+"="+l.FromValue)
}
}

res, err := k8s.KubectlTask(parts...)

if err != nil {
return err
} else if len(res.Stderr) > 0 && strings.Contains(res.Stderr, "Warning") == false {
return fmt.Errorf("error from kubectl\n%q", res.Stderr)
}

manifest := bytes.NewReader([]byte(res.Stdout))
res, err = k8s.KubectlTaskStdin(manifest, "apply", "-f", "-")

if err != nil {
return err
} else if len(res.Stderr) > 0 && strings.Contains(res.Stderr, "Warning") == false {
return fmt.Errorf("error from kubectl\n%q", res.Stderr)
}
return nil
}
2 changes: 1 addition & 1 deletion go.mod
Expand Up @@ -3,7 +3,7 @@ module github.com/alexellis/arkade
go 1.13

require (
github.com/alexellis/go-execute v0.0.0-20191207085904-961405ea7544
github.com/alexellis/go-execute v0.0.0-20201205082949-69a2cde04f4f
github.com/cheggaaa/pb/v3 v3.0.5
github.com/fatih/color v1.9.0 // indirect
github.com/morikuni/aec v1.0.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Expand Up @@ -18,8 +18,8 @@ github.com/VividCortex/ewma v1.1.1 h1:MnEK4VOv6n0RSY4vtRe3h11qjxL3+t0B8yOL8iMXdc
github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alexellis/go-execute v0.0.0-20191207085904-961405ea7544 h1:KjtKgzxk/0wfp7vZxWUYPMiEJKep7FJ7C7o/vtHyc/Q=
github.com/alexellis/go-execute v0.0.0-20191207085904-961405ea7544/go.mod h1:zfRbgnPVxXCSpiKrg1CE72hNUWInqxExiaz2D9ppTts=
github.com/alexellis/go-execute v0.0.0-20201205082949-69a2cde04f4f h1:5auqirFmPvQPu2Cq8gSKPyT6l7KYr9UniEbmvOBiWXM=
github.com/alexellis/go-execute v0.0.0-20201205082949-69a2cde04f4f/go.mod h1:zfRbgnPVxXCSpiKrg1CE72hNUWInqxExiaz2D9ppTts=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
Expand Down
12 changes: 12 additions & 0 deletions pkg/k8s/kubernetes_exec.go
Expand Up @@ -5,6 +5,7 @@ package k8s

import (
"fmt"
"io"
"strings"

"github.com/alexellis/arkade/pkg/types"
Expand All @@ -19,7 +20,18 @@ func GetNodeArchitecture() string {

return arch
}
func KubectlTaskStdin(reader io.Reader, parts ...string) (execute.ExecResult, error) {
task := execute.ExecTask{
Command: "kubectl",
Args: parts,
StreamStdio: false,
Stdin: reader,
}

res, err := task.Execute()

return res, err
}
func KubectlTask(parts ...string) (execute.ExecResult, error) {
task := execute.ExecTask{
Command: "kubectl",
Expand Down

0 comments on commit e9186bf

Please sign in to comment.