Files
nomad/command/agent/task_group_host_volume_claim_endpoint_test.go
Piotr Kazmierczak 58c6387323 stateful deployments: task group host volume claims API (#25114)
This PR introduces API endpoints /v1/volumes/claims/ and /v1/volumes/claim/:id
for listing and deleting task group host volume claims, respectively.
2025-02-25 15:51:59 +01:00

127 lines
3.8 KiB
Go

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package agent
import (
"fmt"
"net/http"
"net/http/httptest"
"testing"
"github.com/hashicorp/nomad/helper/uuid"
"github.com/hashicorp/nomad/nomad/mock"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/shoenig/test/must"
)
func TestTaskGroupHostVolumeClaimEndpoint(t *testing.T) {
hostVolCapsReadWrite := []*structs.HostVolumeCapability{
{
AttachmentMode: structs.HostVolumeAttachmentModeFilesystem,
AccessMode: structs.HostVolumeAccessModeSingleNodeReader,
},
{
AttachmentMode: structs.HostVolumeAttachmentModeFilesystem,
AccessMode: structs.HostVolumeAccessModeSingleNodeWriter,
},
}
dhv1 := &structs.HostVolume{
Namespace: structs.DefaultNamespace,
ID: uuid.Generate(),
Name: "foo",
NodeID: uuid.Generate(),
RequestedCapabilities: hostVolCapsReadWrite,
State: structs.HostVolumeStateReady,
}
stickyRequests := map[string]*structs.VolumeRequest{
"foo": {
Type: "host",
Source: "foo",
Sticky: true,
AccessMode: structs.CSIVolumeAccessModeSingleNodeWriter,
AttachmentMode: structs.CSIVolumeAttachmentModeFilesystem,
},
}
stickyJob := mock.Job()
stickyJob.TaskGroups[0].Volumes = stickyRequests
existingClaims := []*structs.TaskGroupHostVolumeClaim{
{
ID: uuid.Generate(),
Namespace: structs.DefaultNamespace,
JobID: stickyJob.ID,
TaskGroupName: stickyJob.TaskGroups[0].Name,
VolumeID: dhv1.ID,
VolumeName: dhv1.Name,
},
{
ID: uuid.Generate(),
Namespace: "foo",
JobID: stickyJob.ID,
TaskGroupName: stickyJob.TaskGroups[0].Name,
VolumeID: dhv1.ID,
VolumeName: dhv1.Name,
},
{
ID: uuid.Generate(),
Namespace: structs.DefaultNamespace,
JobID: "fooooo",
TaskGroupName: stickyJob.TaskGroups[0].Name,
VolumeID: dhv1.ID,
VolumeName: dhv1.Name,
},
}
httpTest(t, nil, func(s *TestAgent) {
// Create a volume claim on the test node
for _, claim := range existingClaims {
must.NoError(t, s.Agent.Server().State().UpsertTaskGroupHostVolumeClaim(structs.MsgTypeTestSetup, 1000, claim))
}
respW := httptest.NewRecorder()
// List claims
req, err := http.NewRequest(http.MethodGet, "/v1/volumes/claims", nil)
must.NoError(t, err)
claims, err := s.Server.TaskGroupHostVolumeClaimListRequest(respW, req)
must.NoError(t, err)
must.NotNil(t, claims)
respClaims := claims.([]*structs.TaskGroupHostVolumeClaim)
must.NotNil(t, respClaims)
// must contain all the claims except for the one in other ns
must.SliceLen(t, len(existingClaims)-1, respClaims)
// list by fooooo
req, err = http.NewRequest(http.MethodGet, "/v1/volumes/claims?job_id=fooooo", nil)
must.NoError(t, err)
claims, err = s.Server.TaskGroupHostVolumeClaimListRequest(respW, req)
must.NoError(t, err)
must.NotNil(t, claims)
respClaims = claims.([]*structs.TaskGroupHostVolumeClaim)
must.NotNil(t, respClaims)
must.Eq(t, existingClaims[2].ID, respClaims[0].ID)
// Delete claim number 1
req, err = http.NewRequest(http.MethodDelete, fmt.Sprintf("/v1/volumes/claim/%s", existingClaims[0].ID), nil)
must.NoError(t, err)
_, err = s.Server.taskGroupHostVolumeClaimDelete(existingClaims[0].ID, respW, req)
must.NoError(t, err)
// Verify claim was deleted
req, err = http.NewRequest(http.MethodGet, "/v1/volumes/claims", nil)
must.NoError(t, err)
claims, err = s.Server.TaskGroupHostVolumeClaimListRequest(respW, req)
must.NoError(t, err)
must.NotNil(t, claims)
respClaims = claims.([]*structs.TaskGroupHostVolumeClaim)
must.NotNil(t, respClaims)
must.SliceNotContains(t, respClaims, existingClaims[0])
})
}