Skip to content

Commit

Permalink
Merge branch 'master' into f-bolt-db
Browse files Browse the repository at this point in the history
  • Loading branch information
dadgar committed May 9, 2017
2 parents 3f1ccf7 + 5804fbe commit e47be9f
Show file tree
Hide file tree
Showing 81 changed files with 4,505 additions and 759 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ services:
language: go

go:
- 1.8
- 1.8.x

branches:
only:
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@ IMPROVEMENTS:
* core: Back-pressure when evaluations are nacked and ensure scheduling
progress on evaluation failures [GH-2555]
* core: Track multiple job versions and add a stopped state for jobs [GH-2566]
* api: Add `verify_https_client` to require certificates from HTTP clients
[GH-2587]
* api/job: Ability to revert job to older versions [GH-2575]
* client: Fingerprint all routable addresses on an interface including IPv6
addresses [GH-2536]
* client: Hash host ID so its stable and well distributed [GH-2541]
* client: Environment variables for client DC and Region [GH-2507]
* config: Support Unix socket addresses for Consul [GH-2622]
* driver/docker: Allow specifying extra hosts [GH-2547]
* driver/docker: Allow setting container IP with user defined networks
[GH-2535]
Expand All @@ -22,6 +26,7 @@ BUG FIXES:
* client/artifact: Handle tars where file in directory is listed before
directory [GH-2524]
* driver/exec: Properly set file/dir ownership in chroots [GH-2552]
* driver/docker: Fix panic in Docker driver on Windows [GH-2614]
* server: Reject non-TLS clients when TLS enabled [GH-2525]
* server: Fix a panic in plan evaluation with partial failures and all_at_once
set [GH-2544]
Expand Down
3 changes: 2 additions & 1 deletion Vagrantfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ sudo DEBIAN_FRONTEND=noninteractive apt-get install -y build-essential curl git-
liblxc1 lxc-dev lxc-templates \
gcc-5-aarch64-linux-gnu binutils-aarch64-linux-gnu \
libc6-dev-i386 linux-libc-dev:i386 \
gcc-5-arm-linux-gnueabihf gcc-5-multilib-arm-linux-gnueabihf binutils-arm-linux-gnueabihf
gcc-5-arm-linux-gnueabihf gcc-5-multilib-arm-linux-gnueabihf binutils-arm-linux-gnueabihf \
gcc-mingw-w64 binutils-mingw-w64
# Setup go, for development of Nomad
SRCROOT="/opt/go"
Expand Down
9 changes: 7 additions & 2 deletions client/alloc_runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -276,8 +276,8 @@ func (r *AllocRunner) RestoreState() error {
continue
}

if err := tr.RestoreState(); err != nil {
r.logger.Printf("[ERR] client: failed to restore state for alloc %s task '%s': %v", r.alloc.ID, name, err)
if restartReason, err := tr.RestoreState(); err != nil {
r.logger.Printf("[ERR] client: failed to restore state for alloc %s task %q: %v", r.alloc.ID, name, err)
mErr.Errors = append(mErr.Errors, err)
} else if !r.alloc.TerminalStatus() {
// Only start if the alloc isn't in a terminal status.
Expand All @@ -288,6 +288,11 @@ func (r *AllocRunner) RestoreState() error {
r.logger.Printf("[WARN] client: initial save state for alloc %s task %s failed: %v", r.alloc.ID, name, err)
}
}

// Restart task runner if RestoreState gave a reason
if restartReason != "" {
tr.Restart("upgrade", restartReason)
}
}
}

Expand Down
79 changes: 79 additions & 0 deletions client/alloc_runner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ func (m *MockAllocStateUpdater) Update(alloc *structs.Allocation) {
func testAllocRunnerFromAlloc(alloc *structs.Allocation, restarts bool) (*MockAllocStateUpdater, *AllocRunner) {
logger := testLogger()
conf := config.DefaultConfig()
conf.Node = mock.Node()
conf.StateDir = os.TempDir()
conf.AllocDir = os.TempDir()
tmp, _ := ioutil.TempFile("", "state-db")
Expand Down Expand Up @@ -502,6 +503,84 @@ func TestAllocRunner_SaveRestoreState_TerminalAlloc(t *testing.T) {
})
}

// TestAllocRunner_SaveRestoreState_Upgrade asserts that pre-0.6 exec tasks are
// restarted on upgrade.
func TestAllocRunner_SaveRestoreState_Upgrade(t *testing.T) {
alloc := mock.Alloc()
task := alloc.Job.TaskGroups[0].Tasks[0]
task.Driver = "mock_driver"
task.Config = map[string]interface{}{
"exit_code": "0",
"run_for": "10s",
}

upd, ar := testAllocRunnerFromAlloc(alloc, false)
// Hack in old version to cause an upgrade on RestoreState
origConfig := ar.config.Copy()
ar.config.Version = "0.5.6"
go ar.Run()

// Snapshot state
testutil.WaitForResult(func() (bool, error) {
return len(ar.tasks) == 1, nil
}, func(err error) {
t.Fatalf("task never started: %v", err)
})

err := ar.SaveState()
if err != nil {
t.Fatalf("err: %v", err)
}

// Create a new alloc runner
l2 := prefixedTestLogger("----- ar2: ")
ar2 := NewAllocRunner(l2, origConfig, upd.Update,
&structs.Allocation{ID: ar.alloc.ID}, ar.vaultClient,
ar.consulClient)
err = ar2.RestoreState()
if err != nil {
t.Fatalf("err: %v", err)
}
go ar2.Run()

testutil.WaitForResult(func() (bool, error) {
if len(ar2.tasks) != 1 {
return false, fmt.Errorf("Incorrect number of tasks")
}

if upd.Count < 3 {
return false, nil
}

for _, ev := range ar2.alloc.TaskStates["web"].Events {
if strings.HasSuffix(ev.RestartReason, pre06ScriptCheckReason) {
return true, nil
}
}
return false, fmt.Errorf("no restart with proper reason found")
}, func(err error) {
t.Fatalf("err: %v\nAllocs: %#v\nWeb State: %#v", err, upd.Allocs, ar2.alloc.TaskStates["web"])
})

// Destroy and wait
ar2.Destroy()
start := time.Now()

testutil.WaitForResult(func() (bool, error) {
alloc := ar2.Alloc()
if alloc.ClientStatus != structs.AllocClientStatusComplete {
return false, fmt.Errorf("Bad client status; got %v; want %v", alloc.ClientStatus, structs.AllocClientStatusComplete)
}
return true, nil
}, func(err error) {
t.Fatalf("err: %v %#v %#v", err, upd.Allocs[0], ar.alloc.TaskStates)
})

if time.Since(start) > time.Duration(testutil.TestMultiplier()*5)*time.Second {
t.Fatalf("took too long to terminate")
}
}

// Ensure pre-#2132 state files containing the Context struct are properly
// migrated to the new format.
//
Expand Down
29 changes: 16 additions & 13 deletions client/consul_template_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,10 @@ func newTestHarness(t *testing.T, templates []*structs.Template, consul, vault b
harness.taskDir = d

if consul {
harness.consul = ctestutil.NewTestServer(t)
harness.consul, err = ctestutil.NewTestServer()
if err != nil {
t.Fatalf("error starting test Consul server: %v", err)
}
harness.config.ConsulConfig = &sconfig.ConsulConfig{
Addr: harness.consul.HTTPAddr,
}
Expand Down Expand Up @@ -445,7 +448,7 @@ func TestTaskTemplateManager_Unblock_Consul(t *testing.T) {
}

// Write the key to Consul
harness.consul.SetKV(key, []byte(content))
harness.consul.SetKV(t, key, []byte(content))

// Wait for the unblock
select {
Expand Down Expand Up @@ -563,7 +566,7 @@ func TestTaskTemplateManager_Unblock_Multi_Template(t *testing.T) {
}

// Write the key to Consul
harness.consul.SetKV(consulKey, []byte(consulContent))
harness.consul.SetKV(t, consulKey, []byte(consulContent))

// Wait for the unblock
select {
Expand Down Expand Up @@ -612,7 +615,7 @@ func TestTaskTemplateManager_Rerender_Noop(t *testing.T) {
}

// Write the key to Consul
harness.consul.SetKV(key, []byte(content1))
harness.consul.SetKV(t, key, []byte(content1))

// Wait for the unblock
select {
Expand All @@ -633,7 +636,7 @@ func TestTaskTemplateManager_Rerender_Noop(t *testing.T) {
}

// Update the key in Consul
harness.consul.SetKV(key, []byte(content2))
harness.consul.SetKV(t, key, []byte(content2))

select {
case <-harness.mockHooks.RestartCh:
Expand Down Expand Up @@ -697,8 +700,8 @@ func TestTaskTemplateManager_Rerender_Signal(t *testing.T) {
}

// Write the key to Consul
harness.consul.SetKV(key1, []byte(content1_1))
harness.consul.SetKV(key2, []byte(content2_1))
harness.consul.SetKV(t, key1, []byte(content1_1))
harness.consul.SetKV(t, key2, []byte(content2_1))

// Wait for the unblock
select {
Expand All @@ -712,8 +715,8 @@ func TestTaskTemplateManager_Rerender_Signal(t *testing.T) {
}

// Update the keys in Consul
harness.consul.SetKV(key1, []byte(content1_2))
harness.consul.SetKV(key2, []byte(content2_2))
harness.consul.SetKV(t, key1, []byte(content1_2))
harness.consul.SetKV(t, key2, []byte(content2_2))

// Wait for signals
timeout := time.After(time.Duration(1*testutil.TestMultiplier()) * time.Second)
Expand Down Expand Up @@ -782,7 +785,7 @@ func TestTaskTemplateManager_Rerender_Restart(t *testing.T) {
}

// Write the key to Consul
harness.consul.SetKV(key1, []byte(content1_1))
harness.consul.SetKV(t, key1, []byte(content1_1))

// Wait for the unblock
select {
Expand All @@ -792,7 +795,7 @@ func TestTaskTemplateManager_Rerender_Restart(t *testing.T) {
}

// Update the keys in Consul
harness.consul.SetKV(key1, []byte(content1_2))
harness.consul.SetKV(t, key1, []byte(content1_2))

// Wait for restart
timeout := time.After(time.Duration(1*testutil.TestMultiplier()) * time.Second)
Expand Down Expand Up @@ -878,7 +881,7 @@ func TestTaskTemplateManager_Signal_Error(t *testing.T) {
harness.mockHooks.SignalError = fmt.Errorf("test error")

// Write the key to Consul
harness.consul.SetKV(key1, []byte(content1))
harness.consul.SetKV(t, key1, []byte(content1))

// Wait a little
select {
Expand All @@ -888,7 +891,7 @@ func TestTaskTemplateManager_Signal_Error(t *testing.T) {
}

// Write the key to Consul
harness.consul.SetKV(key1, []byte(content2))
harness.consul.SetKV(t, key1, []byte(content2))

// Wait for kill channel
select {
Expand Down
2 changes: 2 additions & 0 deletions client/driver/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,8 @@ func GetTaskEnv(taskDir *allocdir.TaskDir, node *structs.Node,
env := env.NewTaskEnvironment(node).
SetTaskMeta(alloc.Job.CombinedTaskMeta(alloc.TaskGroup, task.Name)).
SetJobName(alloc.Job.Name).
SetDatacenterName(node.Datacenter).
SetRegionName(conf.Region).
SetEnvvars(task.Env).
SetTaskName(task.Name)

Expand Down
7 changes: 6 additions & 1 deletion client/driver/driver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ func testConfig() *config.Config {
conf.StateDir = os.TempDir()
conf.AllocDir = os.TempDir()
conf.MaxKillTimeout = 10 * time.Second
conf.Region = "global"
conf.Node = mock.Node()
return conf
}

Expand All @@ -88,6 +90,7 @@ type testContext struct {
// It is up to the caller to call AllocDir.Destroy to cleanup.
func testDriverContexts(t *testing.T, task *structs.Task) *testContext {
cfg := testConfig()
cfg.Node = mock.Node()
allocDir := allocdir.NewAllocDir(testLogger(), filepath.Join(cfg.AllocDir, structs.GenerateUUID()))
if err := allocDir.Build(); err != nil {
t.Fatalf("AllocDir.Build() failed: %v", err)
Expand Down Expand Up @@ -162,7 +165,7 @@ func setupTaskEnv(t *testing.T, driver string) (*allocdir.TaskDir, map[string]st
conf := testConfig()
allocDir := allocdir.NewAllocDir(testLogger(), filepath.Join(conf.AllocDir, alloc.ID))
taskDir := allocDir.NewTaskDir(task.Name)
env, err := GetTaskEnv(taskDir, nil, task, alloc, conf, "")
env, err := GetTaskEnv(taskDir, conf.Node, task, alloc, conf, "")
if err != nil {
t.Fatalf("GetTaskEnv() failed: %v", err)
}
Expand Down Expand Up @@ -209,6 +212,8 @@ func setupTaskEnv(t *testing.T, driver string) (*allocdir.TaskDir, map[string]st
"NOMAD_ALLOC_NAME": alloc.Name,
"NOMAD_TASK_NAME": task.Name,
"NOMAD_JOB_NAME": alloc.Job.Name,
"NOMAD_DC": "dc1",
"NOMAD_REGION": "global",
}

act := env.EnvMap()
Expand Down
Loading

0 comments on commit e47be9f

Please sign in to comment.