Add timeoutSeconds to secretArgs

This commit is contained in:
Ivan Shvedunov
2018-08-14 22:50:33 +03:00
parent f9577ab540
commit f9a0e671b7
5 changed files with 77 additions and 8 deletions

View File

@@ -83,6 +83,9 @@ secretGenerator:
tls.key: "cat secret/tls.key" tls.key: "cat secret/tls.key"
type: "kubernetes.io/tls" type: "kubernetes.io/tls"
- name: downloaded_secret - name: downloaded_secret
# timeoutSeconds specifies the number of seconds to
# wait for the commands below. It defaults to 5 seconds.
timeoutSeconds: 30
commands: commands:
username: "curl -s https://path/to/secrets/username.yaml" username: "curl -s https://path/to/secrets/username.yaml"
password: "curl -s https://path/to/secrets/password.yaml" password: "curl -s https://path/to/secrets/password.yaml"

View File

@@ -19,6 +19,7 @@ package app
import ( import (
"encoding/base64" "encoding/base64"
"reflect" "reflect"
"strings"
"testing" "testing"
"github.com/kubernetes-sigs/kustomize/pkg/constants" "github.com/kubernetes-sigs/kustomize/pkg/constants"
@@ -53,6 +54,14 @@ secretGenerator:
DB_USERNAME: "printf admin" DB_USERNAME: "printf admin"
DB_PASSWORD: "printf somepw" DB_PASSWORD: "printf somepw"
type: Opaque type: Opaque
`
kustomizationContent2 = `
secretGenerator:
- name: secret
timeoutSeconds: 1
commands:
USER: "sleep 2"
type: Opaque
` `
deploymentContent = `apiVersion: apps/v1 deploymentContent = `apiVersion: apps/v1
metadata: metadata:
@@ -340,3 +349,24 @@ func TestRawResources2(t *testing.T) {
t.Fatalf("unexpected inequality: %v", err) t.Fatalf("unexpected inequality: %v", err)
} }
} }
func TestSecretTimeout(t *testing.T) {
l := loadertest.NewFakeLoader("/testpath")
err := l.AddFile("/testpath/"+constants.KustomizationFileName, []byte(kustomizationContent2))
if err != nil {
t.Fatalf("Failed to setup fake ldr.")
}
fakeFs := fs.MakeFakeFS()
fakeFs.Mkdir("/")
app, err := NewApplication(l, fakeFs)
if err != nil {
t.Fatalf("Unexpected construction error %v", err)
}
_, err = app.MakeCustomizedResMap()
if err == nil {
t.Fatalf("Didn't get the expected error for an unknown resource")
}
if !strings.Contains(err.Error(), "killed") {
t.Fatalf("Unpexpected error message %q", err)
}
}

View File

@@ -31,6 +31,10 @@ import (
"k8s.io/apimachinery/pkg/util/validation" "k8s.io/apimachinery/pkg/util/validation"
) )
const (
defaultCommandTimeout = 5 * time.Second
)
// SecretFactory makes Secrets. // SecretFactory makes Secrets.
type SecretFactory struct { type SecretFactory struct {
fSys fs.FileSystem fSys fs.FileSystem
@@ -61,7 +65,12 @@ func (f *SecretFactory) MakeSecret(args *types.SecretArgs) (*corev1.Secret, erro
var err error var err error
s := f.makeFreshSecret(args) s := f.makeFreshSecret(args)
pairs, err := f.keyValuesFromEnvFileCommand(args.EnvCommand) timeout := defaultCommandTimeout
if args.TimeoutSeconds != nil {
timeout = time.Duration(*args.TimeoutSeconds) * time.Second
}
pairs, err := f.keyValuesFromEnvFileCommand(args.EnvCommand, timeout)
if err != nil { if err != nil {
return nil, errors.Wrap(err, fmt.Sprintf( return nil, errors.Wrap(err, fmt.Sprintf(
"env source file: %s", "env source file: %s",
@@ -69,7 +78,7 @@ func (f *SecretFactory) MakeSecret(args *types.SecretArgs) (*corev1.Secret, erro
} }
all = append(all, pairs...) all = append(all, pairs...)
pairs, err = f.keyValuesFromCommands(args.Commands) pairs, err = f.keyValuesFromCommands(args.Commands, timeout)
if err != nil { if err != nil {
return nil, errors.Wrap(err, fmt.Sprintf( return nil, errors.Wrap(err, fmt.Sprintf(
"commands %v", args.Commands)) "commands %v", args.Commands))
@@ -98,18 +107,18 @@ func addKvToSecret(secret *corev1.Secret, keyName, data string) error {
return nil return nil
} }
func (f *SecretFactory) keyValuesFromEnvFileCommand(cmd string) ([]kvPair, error) { func (f *SecretFactory) keyValuesFromEnvFileCommand(cmd string, timeout time.Duration) ([]kvPair, error) {
content, err := f.createSecretKey(cmd) content, err := f.createSecretKey(cmd, timeout)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return keyValuesFromLines(content) return keyValuesFromLines(content)
} }
func (f *SecretFactory) keyValuesFromCommands(sources map[string]string) ([]kvPair, error) { func (f *SecretFactory) keyValuesFromCommands(sources map[string]string, timeout time.Duration) ([]kvPair, error) {
var kvs []kvPair var kvs []kvPair
for k, cmd := range sources { for k, cmd := range sources {
content, err := f.createSecretKey(cmd) content, err := f.createSecretKey(cmd, timeout)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -119,14 +128,14 @@ func (f *SecretFactory) keyValuesFromCommands(sources map[string]string) ([]kvPa
} }
// Run a command, return its output as the secret. // Run a command, return its output as the secret.
func (f *SecretFactory) createSecretKey(command string) ([]byte, error) { func (f *SecretFactory) createSecretKey(command string, timeout time.Duration) ([]byte, error) {
if !f.fSys.IsDir(f.wd) { if !f.fSys.IsDir(f.wd) {
f.wd = filepath.Dir(f.wd) f.wd = filepath.Dir(f.wd)
if !f.fSys.IsDir(f.wd) { if !f.fSys.IsDir(f.wd) {
return nil, errors.New("not a directory: " + f.wd) return nil, errors.New("not a directory: " + f.wd)
} }
} }
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel() defer cancel()
cmd := exec.CommandContext(ctx, "sh", "-c", command) cmd := exec.CommandContext(ctx, "sh", "-c", command)
cmd.Dir = f.wd cmd.Dir = f.wd

View File

@@ -94,3 +94,27 @@ func TestNewResMapFromSecretArgs(t *testing.T) {
t.Fatalf("%#v\ndoesn't match expected:\n%#v", actual, expected) t.Fatalf("%#v\ndoesn't match expected:\n%#v", actual, expected)
} }
} }
func TestSecretTimeout(t *testing.T) {
timeout := int64(1)
secrets := []types.SecretArgs{
{
Name: "slow",
TimeoutSeconds: &timeout,
CommandSources: types.CommandSources{
Commands: map[string]string{
"USER": "sleep 2",
},
},
Type: "Opaque",
},
}
fakeFs := fs.MakeFakeFS()
fakeFs.Mkdir(".")
_, err := NewResMapFromSecretArgs(
configmapandsecret.NewSecretFactory(fakeFs, "."), secrets)
if err == nil {
t.Fatal("didn't get the expected timeout error", err)
}
}

View File

@@ -117,6 +117,9 @@ type SecretArgs struct {
// CommandSources for secret. // CommandSources for secret.
CommandSources `json:",inline,omitempty" yaml:",inline,omitempty"` CommandSources `json:",inline,omitempty" yaml:",inline,omitempty"`
// TimeoutSeconds specifies the timeout for commands.
TimeoutSeconds *int64 `json:"timeoutSeconds,omitempty" yaml:"timeoutSeconds,omitempty"`
} }
// CommandSources contains some generic sources for secrets. // CommandSources contains some generic sources for secrets.