From af036be754a81bcbfe0c58868802a7e0dcb8f4cd Mon Sep 17 00:00:00 2001 From: Alex Dadgar Date: Tue, 11 Oct 2016 15:25:49 -0700 Subject: [PATCH] Struct/api/parsing --- api/tasks.go | 6 ++++-- jobspec/parse.go | 6 ++++++ jobspec/parse_test.go | 26 ++++++++++++++++++-------- jobspec/test-fixtures/basic.hcl | 7 +++++++ nomad/structs/structs.go | 29 +++++++++++++++++++++++++++++ nomad/structs/structs_test.go | 18 ++++++++++++++++++ 6 files changed, 82 insertions(+), 10 deletions(-) diff --git a/api/tasks.go b/api/tasks.go index aab17ec4d..294d8cffb 100644 --- a/api/tasks.go +++ b/api/tasks.go @@ -177,8 +177,10 @@ type Template struct { } type Vault struct { - Policies []string - Env bool + Policies []string + Env bool + TokenChangeMode string + TokenChangeSignal string } // NewTask creates and initializes a new Task. diff --git a/jobspec/parse.go b/jobspec/parse.go index 964870603..3c19b4d52 100644 --- a/jobspec/parse.go +++ b/jobspec/parse.go @@ -1177,6 +1177,8 @@ func parseVault(result *structs.Vault, list *ast.ObjectList) error { valid := []string{ "policies", "env", + "change_mode", + "change_signal", } if err := checkHCLKeys(listVal, valid); err != nil { return multierror.Prefix(err, "vault ->") @@ -1192,6 +1194,10 @@ func parseVault(result *structs.Vault, list *ast.ObjectList) error { m["env"] = true } + if _, ok := m["change_mode"]; !ok { + m["change_mode"] = structs.VaultChangeModeRestart + } + if err := mapstructure.WeakDecode(m, result); err != nil { return err } diff --git a/jobspec/parse_test.go b/jobspec/parse_test.go index b2ade94f3..fde40251c 100644 --- a/jobspec/parse_test.go +++ b/jobspec/parse_test.go @@ -159,8 +159,9 @@ func TestParse(t *testing.T) { }, }, Vault: &structs.Vault{ - Policies: []string{"foo", "bar"}, - Env: true, + Policies: []string{"foo", "bar"}, + Env: true, + ChangeMode: structs.VaultChangeModeRestart, }, Templates: []*structs.Template{ { @@ -199,6 +200,12 @@ func TestParse(t *testing.T) { }, }, LogConfig: structs.DefaultLogConfig(), + Vault: &structs.Vault{ + Policies: []string{"foo", "bar"}, + Env: false, + ChangeMode: structs.VaultChangeModeSignal, + ChangeSignal: "SIGUSR1", + }, }, }, }, @@ -475,16 +482,18 @@ func TestParse(t *testing.T) { Name: "redis", LogConfig: structs.DefaultLogConfig(), Vault: &structs.Vault{ - Policies: []string{"group"}, - Env: true, + Policies: []string{"group"}, + Env: true, + ChangeMode: structs.VaultChangeModeRestart, }, }, &structs.Task{ Name: "redis2", LogConfig: structs.DefaultLogConfig(), Vault: &structs.Vault{ - Policies: []string{"task"}, - Env: false, + Policies: []string{"task"}, + Env: false, + ChangeMode: structs.VaultChangeModeRestart, }, }, }, @@ -498,8 +507,9 @@ func TestParse(t *testing.T) { Name: "redis", LogConfig: structs.DefaultLogConfig(), Vault: &structs.Vault{ - Policies: []string{"job"}, - Env: true, + Policies: []string{"job"}, + Env: true, + ChangeMode: structs.VaultChangeModeRestart, }, }, }, diff --git a/jobspec/test-fixtures/basic.hcl b/jobspec/test-fixtures/basic.hcl index 1250f9a45..f25d9a87b 100644 --- a/jobspec/test-fixtures/basic.hcl +++ b/jobspec/test-fixtures/basic.hcl @@ -165,6 +165,13 @@ job "binstore-storagelocker" { attribute = "kernel.arch" value = "amd64" } + + vault { + policies = ["foo", "bar"] + env = false + change_mode = "signal" + change_signal = "SIGUSR1" + } } constraint { diff --git a/nomad/structs/structs.go b/nomad/structs/structs.go index 2971f76e6..35f299e6c 100644 --- a/nomad/structs/structs.go +++ b/nomad/structs/structs.go @@ -2818,6 +2818,17 @@ func (d *EphemeralDisk) Copy() *EphemeralDisk { return ld } +const ( + // VaultChangeModeNoop takes no action when a new token is retrieved. + VaultChangeModeNoop = "noop" + + // VaultChangeModeSignal signals the task when a new token is retrieved. + VaultChangeModeSignal = "signal" + + // VaultChangeModeRestart restarts the task when a new token is retrieved. + VaultChangeModeRestart = "restart" +) + // Vault stores the set of premissions a task needs access to from Vault. type Vault struct { // Policies is the set of policies that the task needs access to @@ -2826,6 +2837,14 @@ type Vault struct { // Env marks whether the Vault Token should be exposed as an environment // variable Env bool + + // ChangeMode is used to configure the task's behavior when the Vault + // token changes because the original token could not be renewed in time. + ChangeMode string `mapstructure:"change_mode"` + + // ChangeSignal is the signal sent to the task when a new token is + // retrieved. This is only valid when using the signal change mode. + ChangeSignal string `mapstructure:"change_signal"` } // Copy returns a copy of this Vault block. @@ -2849,6 +2868,16 @@ func (v *Vault) Validate() error { return fmt.Errorf("Policy list can not be empty") } + switch v.ChangeMode { + case VaultChangeModeSignal: + if v.ChangeSignal == "" { + return fmt.Errorf("Signal must be specified when using change mode %q", VaultChangeModeSignal) + } + case VaultChangeModeNoop, VaultChangeModeRestart: + default: + return fmt.Errorf("Unknown change mode %q", v.ChangeMode) + } + return nil } diff --git a/nomad/structs/structs_test.go b/nomad/structs/structs_test.go index 62e40de2c..7ce4cfc86 100644 --- a/nomad/structs/structs_test.go +++ b/nomad/structs/structs_test.go @@ -1307,3 +1307,21 @@ func TestAllocation_Terminated(t *testing.T) { } } } + +func TestVault_Validate(t *testing.T) { + v := &Vault{ + Env: true, + ChangeMode: VaultChangeModeNoop, + } + + if err := v.Validate(); err == nil || !strings.Contains(err.Error(), "Policy list") { + t.Fatalf("Expected policy list empty error") + } + + v.Policies = []string{"foo"} + v.ChangeMode = VaultChangeModeSignal + + if err := v.Validate(); err == nil || !strings.Contains(err.Error(), "Signal must") { + t.Fatalf("Expected signal empty error") + } +}