github.com/rohankumardubey/nomad@v0.11.8/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  }