github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/e2e/csi/efs.go (about)

     1  package csi
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  
     7  	e2e "github.com/hashicorp/nomad/e2e/e2eutil"
     8  	"github.com/hashicorp/nomad/e2e/framework"
     9  	"github.com/hashicorp/nomad/helper/uuid"
    10  	"github.com/stretchr/testify/require"
    11  )
    12  
    13  // CSINodeOnlyPluginEFSTest exercises the AWS EFS plugin, which is an
    14  // example of a plugin that can run in Node-only mode.
    15  type CSINodeOnlyPluginEFSTest struct {
    16  	framework.TC
    17  	uuid         string
    18  	testJobIDs   []string
    19  	volumeIDs    []string
    20  	pluginJobIDs []string
    21  }
    22  
    23  const efsPluginID = "aws-efs0"
    24  
    25  func (tc *CSINodeOnlyPluginEFSTest) BeforeAll(f *framework.F) {
    26  	t := f.T()
    27  
    28  	_, err := os.Stat("csi/input/volume-efs.hcl")
    29  	if err != nil {
    30  		t.Skip("skipping CSI test because EFS volume spec file missing:", err)
    31  	}
    32  
    33  	// Ensure cluster has leader and at least two client
    34  	// nodes in a ready state before running tests
    35  	e2e.WaitForLeader(t, tc.Nomad())
    36  	e2e.WaitForNodesReady(t, tc.Nomad(), 2)
    37  }
    38  
    39  // TestEFSVolumeClaim launches AWS EFS plugins and registers an EFS volume
    40  // as a Nomad CSI volume. We then deploy a job that writes to the volume,
    41  // and share the volume with another job which should be able to read the
    42  // data written by the first job.
    43  func (tc *CSINodeOnlyPluginEFSTest) TestEFSVolumeClaim(f *framework.F) {
    44  	t := f.T()
    45  	require := require.New(t)
    46  	nomadClient := tc.Nomad()
    47  	tc.uuid = uuid.Generate()[0:8]
    48  
    49  	// deploy the node plugins job (no need for a controller for EFS)
    50  	nodesJobID := "aws-efs-plugin-nodes-" + tc.uuid
    51  	f.NoError(e2e.Register(nodesJobID, "csi/input/plugin-aws-efs-nodes.nomad"))
    52  	tc.pluginJobIDs = append(tc.pluginJobIDs, nodesJobID)
    53  
    54  	f.NoError(e2e.WaitForAllocStatusComparison(
    55  		func() ([]string, error) { return e2e.AllocStatuses(nodesJobID, ns) },
    56  		func(got []string) bool {
    57  			for _, status := range got {
    58  				if status != "running" {
    59  					return false
    60  				}
    61  			}
    62  			return true
    63  		}, pluginAllocWait,
    64  	), "plugin job should be running")
    65  
    66  	f.NoError(waitForPluginStatusMinNodeCount(efsPluginID, 2, pluginWait),
    67  		"aws-efs0 node plugins did not become healthy")
    68  
    69  	// register a volume
    70  	volID := "efs-vol0"
    71  	err := volumeRegister(volID, "csi/input/volume-efs.hcl", "register")
    72  	require.NoError(err)
    73  	tc.volumeIDs = append(tc.volumeIDs, volID)
    74  
    75  	// deploy a job that writes to the volume
    76  	writeJobID := "write-efs-" + tc.uuid
    77  	tc.testJobIDs = append(tc.testJobIDs, writeJobID) // ensure failed tests clean up
    78  	f.NoError(e2e.Register(writeJobID, "csi/input/use-efs-volume-write.nomad"))
    79  	f.NoError(
    80  		e2e.WaitForAllocStatusExpected(writeJobID, ns, []string{"running"}),
    81  		"job should be running")
    82  
    83  	allocs, err := e2e.AllocsForJob(writeJobID, ns)
    84  	f.NoError(err, "could not get allocs for write job")
    85  	f.Len(allocs, 1, "could not get allocs for write job")
    86  	writeAllocID := allocs[0]["ID"]
    87  
    88  	// read data from volume and assert the writer wrote a file to it
    89  	expectedPath := "/task/test/" + writeAllocID
    90  	_, err = readFile(nomadClient, writeAllocID, expectedPath)
    91  	require.NoError(err)
    92  
    93  	// Shutdown the writer so we can run a reader.
    94  	// although EFS should support multiple readers, the plugin
    95  	// does not.
    96  	err = e2e.StopJob(writeJobID)
    97  	require.NoError(err)
    98  
    99  	// wait for the volume unpublish workflow to complete
   100  	require.NoError(waitForVolumeClaimRelease(volID, reapWait),
   101  		"write-efs alloc claim was not released")
   102  
   103  	// deploy a job that reads from the volume
   104  	readJobID := "read-efs-" + tc.uuid
   105  	tc.testJobIDs = append(tc.testJobIDs, readJobID) // ensure failed tests clean up
   106  	f.NoError(e2e.Register(readJobID, "csi/input/use-efs-volume-read.nomad"))
   107  	f.NoError(
   108  		e2e.WaitForAllocStatusExpected(readJobID, ns, []string{"running"}),
   109  		"job should be running")
   110  
   111  	allocs, err = e2e.AllocsForJob(readJobID, ns)
   112  	f.NoError(err, "could not get allocs for read job")
   113  	f.Len(allocs, 1, "could not get allocs for read job")
   114  	readAllocID := allocs[0]["ID"]
   115  
   116  	// read data from volume and assert the writer wrote a file to it
   117  	require.NoError(err)
   118  	_, err = readFile(nomadClient, readAllocID, expectedPath)
   119  	require.NoError(err)
   120  }
   121  
   122  func (tc *CSINodeOnlyPluginEFSTest) AfterEach(f *framework.F) {
   123  
   124  	// Stop all jobs in test
   125  	for _, id := range tc.testJobIDs {
   126  		err := e2e.StopJob(id, "-purge")
   127  		f.Assert().NoError(err)
   128  	}
   129  	tc.testJobIDs = []string{}
   130  
   131  	// Deregister all volumes in test
   132  	for _, id := range tc.volumeIDs {
   133  		// make sure all the test jobs have finished unpublishing claims
   134  		err := waitForVolumeClaimRelease(id, reapWait)
   135  		f.Assert().NoError(err, "volume claims were not released")
   136  
   137  		out, err := e2e.Command("nomad", "volume", "deregister", id)
   138  		assertNoErrorElseDump(f, err,
   139  			fmt.Sprintf("could not deregister volume:\n%v", out), tc.pluginJobIDs)
   140  	}
   141  	tc.volumeIDs = []string{}
   142  
   143  	// Deregister all plugin jobs in test
   144  	for _, id := range tc.pluginJobIDs {
   145  		err := e2e.StopJob(id, "-purge")
   146  		f.Assert().NoError(err)
   147  	}
   148  	tc.pluginJobIDs = []string{}
   149  
   150  	// Garbage collect
   151  	out, err := e2e.Command("nomad", "system", "gc")
   152  	f.Assert().NoError(err, out)
   153  }