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 }