github.com/iqoqo/nomad@v0.11.3-0.20200911112621-d7021c74d101/e2e/nomad09upgrade/upgrade.go (about) 1 //+build linux 2 3 package nomad09upgrade 4 5 import ( 6 "fmt" 7 "io/ioutil" 8 "os" 9 "path/filepath" 10 "strings" 11 "testing" 12 "time" 13 14 getter "github.com/hashicorp/go-getter" 15 "github.com/hashicorp/nomad/e2e/e2eutil" 16 "github.com/hashicorp/nomad/e2e/execagent" 17 "github.com/hashicorp/nomad/e2e/framework" 18 "github.com/hashicorp/nomad/helper/discover" 19 "github.com/hashicorp/nomad/helper/testlog" 20 "github.com/hashicorp/nomad/helper/uuid" 21 "github.com/hashicorp/nomad/testutil" 22 "github.com/stretchr/testify/require" 23 ) 24 25 func init() { 26 framework.AddSuites(&framework.TestSuite{ 27 Component: "nomad09upgrade", 28 CanRunLocal: true, 29 Cases: []framework.TestCase{ 30 &UpgradePathTC{}, 31 }, 32 }) 33 } 34 35 var ( 36 nomadVersions = [...]string{ 37 "0.8.7", 38 "0.8.6", 39 "0.8.5", 40 "0.8.4", 41 "0.8.3", 42 "0.8.2", 43 "0.8.1", 44 "0.8.0", 45 } 46 ) 47 48 type UpgradePathTC struct { 49 framework.TC 50 51 binDir string 52 bin string 53 } 54 55 type upgradeAgents struct { 56 origAgent *execagent.NomadAgent 57 targetAgent *execagent.NomadAgent 58 } 59 60 func (tc *UpgradePathTC) newNomadServer(t *testing.T, ver string) (*upgradeAgents, error) { 61 binPath := filepath.Join(tc.binDir, ver, "nomad") 62 srv, err := execagent.NewMixedAgent(binPath) 63 if err != nil { 64 return nil, err 65 } 66 67 w := testlog.NewWriter(t) 68 srv.Cmd.Stdout = w 69 srv.Cmd.Stderr = w 70 71 // Target should copy everything but the binary to target 72 target, err := execagent.NewMixedAgent(tc.bin) 73 if err != nil { 74 return nil, err 75 } 76 target.Cmd.Stdout = w 77 target.Cmd.Stderr = w 78 79 agents := &upgradeAgents{ 80 origAgent: srv, 81 targetAgent: target, 82 } 83 return agents, nil 84 } 85 86 // BeforeAll downloads all of the desired nomad versions to test against 87 func (tc *UpgradePathTC) BeforeAll(f *framework.F) { 88 // Upgrade tests currently fail because the nomad binary isn't found by 89 // discover.NomadExecutable(). Ensure that nomad binary is available 90 // and discoverable and enable this test 91 f.T().Skip("upgrade tests are expected to fail. TODO: Fix") 92 93 bin, err := discover.NomadExecutable() 94 f.NoError(err) 95 tc.bin = bin 96 dir, err := ioutil.TempDir("", "") 97 f.NoError(err) 98 99 tc.binDir = dir 100 for _, ver := range nomadVersions { 101 verBin := filepath.Join(tc.binDir, ver) 102 f.NoError(os.Mkdir(verBin, 0755)) 103 f.NoError( 104 getter.Get(verBin, fmt.Sprintf( 105 "https://releases.hashicorp.com/nomad/%s/nomad_%s_linux_amd64.zip", 106 ver, ver, 107 ))) 108 f.T().Logf("downloaded nomad version %s to %s", ver, verBin) 109 } 110 } 111 112 // AfterAll cleans up the downloaded nomad binaries 113 func (tc *UpgradePathTC) AfterAll(f *framework.F) { 114 os.RemoveAll(tc.binDir) 115 } 116 117 func (tc *UpgradePathTC) TestRawExecTaskUpgrade(f *framework.F) { 118 for _, ver := range nomadVersions { 119 ver := ver 120 f.T().Run(ver, func(t *testing.T) { 121 t.Parallel() 122 tc.testUpgradeForJob(t, ver, "nomad09upgrade/rawexec.nomad") 123 }) 124 } 125 } 126 127 func (tc *UpgradePathTC) TestExecTaskUpgrade(f *framework.F) { 128 for _, ver := range nomadVersions { 129 ver := ver 130 f.T().Run(ver, func(t *testing.T) { 131 t.Parallel() 132 tc.testUpgradeForJob(t, ver, "nomad09upgrade/exec.nomad") 133 }) 134 } 135 } 136 137 func (tc *UpgradePathTC) TestDockerTaskUpgrade(f *framework.F) { 138 for _, ver := range nomadVersions { 139 ver := ver 140 f.T().Run(ver, func(t *testing.T) { 141 t.Parallel() 142 tc.testUpgradeForJob(t, ver, "nomad09upgrade/docker.nomad") 143 }) 144 } 145 } 146 147 func (tc *UpgradePathTC) testUpgradeForJob(t *testing.T, ver string, jobfile string) { 148 require := require.New(t) 149 // Start a nomad agent for the given version 150 agents, err := tc.newNomadServer(t, ver) 151 require.NoError(err) 152 t.Logf("launching v%s nomad agent", ver) 153 require.NoError(agents.origAgent.Start()) 154 155 // Wait for the agent to be ready 156 client, err := agents.origAgent.Client() 157 require.NoError(err) 158 e2eutil.WaitForNodesReady(t, client, 1) 159 160 // Register a sleep job 161 jobID := "sleep-" + uuid.Generate()[:8] 162 t.Logf("registering exec job with id %s", jobID) 163 e2eutil.RegisterAndWaitForAllocs(t, client, jobfile, jobID, "") 164 allocs, _, err := client.Jobs().Allocations(jobID, false, nil) 165 require.NoError(err) 166 require.Len(allocs, 1) 167 168 // Wait for sleep job to transition to running 169 id := allocs[0].ID 170 e2eutil.WaitForAllocRunning(t, client, id) 171 172 // Stop the agent, leaving the sleep job running 173 require.NoError(agents.origAgent.Stop()) 174 175 // Start a nomad agent with the to be tested nomad binary 176 t.Logf("launching test nomad agent") 177 require.NoError(agents.targetAgent.Start()) 178 179 // Wait for the agent to be ready 180 e2eutil.WaitForNodesReady(t, client, 1) 181 182 // Make sure the same allocation still exists 183 alloc, _, err := client.Allocations().Info(id, nil) 184 require.NoError(err) 185 // Pull stats from the allocation, testing that new code can interface with 186 // the old stats driver apis 187 testutil.WaitForResult(func() (bool, error) { 188 stats, err := client.Allocations().Stats(alloc, nil) 189 if err != nil { 190 return false, err 191 } 192 193 return stats.ResourceUsage.MemoryStats.RSS > 0, fmt.Errorf("RSS for task should be greater than 0") 194 }, func(err error) { 195 require.NoError(err) 196 }) 197 198 // Deregister the job. This tests that the new code can properly tear down 199 // upgraded allocs 200 _, _, err = client.Jobs().Deregister(alloc.JobID, true, nil) 201 require.NoError(err) 202 testutil.WaitForResult(func() (bool, error) { 203 j, _, _ := client.Jobs().Info(jobID, nil) 204 if j == nil { 205 return true, nil 206 } 207 time.Sleep(time.Millisecond * 100) 208 return false, fmt.Errorf("job with id %q should be purged", jobID) 209 }, func(err error) { 210 require.NoError(err) 211 }) 212 213 // Check that the task dir mounts have been removed 214 testutil.WaitForResult(func() (bool, error) { 215 defer client.System().GarbageCollect() 216 time.Sleep(time.Millisecond * 100) 217 data, err := ioutil.ReadFile("/proc/mounts") 218 if err != nil { 219 return false, err 220 } 221 222 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)) 223 }, func(err error) { 224 require.NoError(err) 225 }) 226 227 // Cleanup 228 agents.targetAgent.Stop() 229 agents.targetAgent.Destroy() 230 }