cd87afd15f
The e2e test code is absolutely hideous and leaks processes and files on disk. NomadAgent seems useful, but the clientstate e2e tests are very messy and slow. The last test "Corrupt" is probably the most useful as it explicitly corrupts the state file whereas the other tests attempt to reproduce steps thought to cause corruption in earlier releases of Nomad.
231 lines
5.8 KiB
Go
231 lines
5.8 KiB
Go
//+build linux
|
|
|
|
package nomad09upgrade
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
getter "github.com/hashicorp/go-getter"
|
|
"github.com/hashicorp/nomad/e2e/e2eutil"
|
|
"github.com/hashicorp/nomad/e2e/execagent"
|
|
"github.com/hashicorp/nomad/e2e/framework"
|
|
"github.com/hashicorp/nomad/helper/discover"
|
|
"github.com/hashicorp/nomad/helper/testlog"
|
|
"github.com/hashicorp/nomad/helper/uuid"
|
|
"github.com/hashicorp/nomad/testutil"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func init() {
|
|
framework.AddSuites(&framework.TestSuite{
|
|
Component: "nomad09upgrade",
|
|
CanRunLocal: true,
|
|
Cases: []framework.TestCase{
|
|
&UpgradePathTC{},
|
|
},
|
|
})
|
|
}
|
|
|
|
var (
|
|
nomadVersions = [...]string{
|
|
"0.8.7",
|
|
"0.8.6",
|
|
"0.8.5",
|
|
"0.8.4",
|
|
"0.8.3",
|
|
"0.8.2",
|
|
"0.8.1",
|
|
"0.8.0",
|
|
}
|
|
)
|
|
|
|
type UpgradePathTC struct {
|
|
framework.TC
|
|
|
|
binDir string
|
|
bin string
|
|
}
|
|
|
|
type upgradeAgents struct {
|
|
origAgent *execagent.NomadAgent
|
|
targetAgent *execagent.NomadAgent
|
|
}
|
|
|
|
func (tc *UpgradePathTC) newNomadServer(t *testing.T, ver string) (*upgradeAgents, error) {
|
|
binPath := filepath.Join(tc.binDir, ver, "nomad")
|
|
srv, err := execagent.NewMixedAgent(binPath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
w := testlog.NewWriter(t)
|
|
srv.Cmd.Stdout = w
|
|
srv.Cmd.Stderr = w
|
|
|
|
// Target should copy everything but the binary to target
|
|
target, err := execagent.NewMixedAgent(tc.bin)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
target.Cmd.Stdout = w
|
|
target.Cmd.Stderr = w
|
|
|
|
agents := &upgradeAgents{
|
|
origAgent: srv,
|
|
targetAgent: target,
|
|
}
|
|
return agents, nil
|
|
}
|
|
|
|
// BeforeAll downloads all of the desired nomad versions to test against
|
|
func (tc *UpgradePathTC) BeforeAll(f *framework.F) {
|
|
// Upgrade tests currently fail because the nomad binary isn't found by
|
|
// discover.NomadExecutable(). Ensure that nomad binary is available
|
|
// and discoverable and enable this test
|
|
f.T().Skip("upgrade tests are expected to fail. TODO: Fix")
|
|
|
|
bin, err := discover.NomadExecutable()
|
|
f.NoError(err)
|
|
tc.bin = bin
|
|
dir, err := ioutil.TempDir("", "")
|
|
f.NoError(err)
|
|
|
|
tc.binDir = dir
|
|
for _, ver := range nomadVersions {
|
|
verBin := filepath.Join(tc.binDir, ver)
|
|
f.NoError(os.Mkdir(verBin, 0755))
|
|
f.NoError(
|
|
getter.Get(verBin, fmt.Sprintf(
|
|
"https://releases.hashicorp.com/nomad/%s/nomad_%s_linux_amd64.zip",
|
|
ver, ver,
|
|
)))
|
|
f.T().Logf("downloaded nomad version %s to %s", ver, verBin)
|
|
}
|
|
}
|
|
|
|
// AfterAll cleans up the downloaded nomad binaries
|
|
func (tc *UpgradePathTC) AfterAll(f *framework.F) {
|
|
os.RemoveAll(tc.binDir)
|
|
}
|
|
|
|
func (tc *UpgradePathTC) TestRawExecTaskUpgrade(f *framework.F) {
|
|
for _, ver := range nomadVersions {
|
|
ver := ver
|
|
f.T().Run(ver, func(t *testing.T) {
|
|
t.Parallel()
|
|
tc.testUpgradeForJob(t, ver, "nomad09upgrade/rawexec.nomad")
|
|
})
|
|
}
|
|
}
|
|
|
|
func (tc *UpgradePathTC) TestExecTaskUpgrade(f *framework.F) {
|
|
for _, ver := range nomadVersions {
|
|
ver := ver
|
|
f.T().Run(ver, func(t *testing.T) {
|
|
t.Parallel()
|
|
tc.testUpgradeForJob(t, ver, "nomad09upgrade/exec.nomad")
|
|
})
|
|
}
|
|
}
|
|
|
|
func (tc *UpgradePathTC) TestDockerTaskUpgrade(f *framework.F) {
|
|
for _, ver := range nomadVersions {
|
|
ver := ver
|
|
f.T().Run(ver, func(t *testing.T) {
|
|
t.Parallel()
|
|
tc.testUpgradeForJob(t, ver, "nomad09upgrade/docker.nomad")
|
|
})
|
|
}
|
|
}
|
|
|
|
func (tc *UpgradePathTC) testUpgradeForJob(t *testing.T, ver string, jobfile string) {
|
|
require := require.New(t)
|
|
// Start a nomad agent for the given version
|
|
agents, err := tc.newNomadServer(t, ver)
|
|
require.NoError(err)
|
|
t.Logf("launching v%s nomad agent", ver)
|
|
require.NoError(agents.origAgent.Start())
|
|
|
|
// Wait for the agent to be ready
|
|
client, err := agents.origAgent.Client()
|
|
require.NoError(err)
|
|
e2eutil.WaitForNodesReady(t, client, 1)
|
|
|
|
// Register a sleep job
|
|
jobID := "sleep-" + uuid.Generate()[:8]
|
|
t.Logf("registering exec job with id %s", jobID)
|
|
e2eutil.RegisterAndWaitForAllocs(t, client, jobfile, jobID)
|
|
allocs, _, err := client.Jobs().Allocations(jobID, false, nil)
|
|
require.NoError(err)
|
|
require.Len(allocs, 1)
|
|
|
|
// Wait for sleep job to transition to running
|
|
id := allocs[0].ID
|
|
e2eutil.WaitForAllocRunning(t, client, id)
|
|
|
|
// Stop the agent, leaving the sleep job running
|
|
require.NoError(agents.origAgent.Stop())
|
|
|
|
// Start a nomad agent with the to be tested nomad binary
|
|
t.Logf("launching test nomad agent")
|
|
require.NoError(agents.targetAgent.Start())
|
|
|
|
// Wait for the agent to be ready
|
|
e2eutil.WaitForNodesReady(t, client, 1)
|
|
|
|
// Make sure the same allocation still exists
|
|
alloc, _, err := client.Allocations().Info(id, nil)
|
|
require.NoError(err)
|
|
// Pull stats from the allocation, testing that new code can interface with
|
|
// the old stats driver apis
|
|
testutil.WaitForResult(func() (bool, error) {
|
|
stats, err := client.Allocations().Stats(alloc, nil)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
return stats.ResourceUsage.MemoryStats.RSS > 0, fmt.Errorf("RSS for task should be greater than 0")
|
|
}, func(err error) {
|
|
require.NoError(err)
|
|
})
|
|
|
|
// Deregister the job. This tests that the new code can properly tear down
|
|
// upgraded allocs
|
|
_, _, err = client.Jobs().Deregister(alloc.JobID, true, nil)
|
|
require.NoError(err)
|
|
testutil.WaitForResult(func() (bool, error) {
|
|
j, _, _ := client.Jobs().Info(jobID, nil)
|
|
if j == nil {
|
|
return true, nil
|
|
}
|
|
time.Sleep(time.Millisecond * 100)
|
|
return false, fmt.Errorf("job with id %q should be purged", jobID)
|
|
}, func(err error) {
|
|
require.NoError(err)
|
|
})
|
|
|
|
// Check that the task dir mounts have been removed
|
|
testutil.WaitForResult(func() (bool, error) {
|
|
defer client.System().GarbageCollect()
|
|
time.Sleep(time.Millisecond * 100)
|
|
data, err := ioutil.ReadFile("/proc/mounts")
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
return !strings.Contains(string(data), id), fmt.Errorf("taskdir mounts should be cleaned up, but found mount for id %q:\n%s", id, string(data))
|
|
}, func(err error) {
|
|
require.NoError(err)
|
|
})
|
|
|
|
// Cleanup
|
|
agents.targetAgent.Stop()
|
|
agents.targetAgent.Destroy()
|
|
}
|