Skip to content

Commit

Permalink
Added support for Block Storage Encryption (#572)
Browse files Browse the repository at this point in the history
* Added support for Block Storage Encryption

* Added instance test

* Addressed PR comments

* Added LA note
  • Loading branch information
ezilber-akamai authored Oct 15, 2024
1 parent 7ea8057 commit 9bbcf49
Show file tree
Hide file tree
Showing 10 changed files with 1,978 additions and 5 deletions.
3 changes: 2 additions & 1 deletion instances.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ type Instance struct {
// NOTE: Disk encryption may not currently be available to all users.
DiskEncryption InstanceDiskEncryption `json:"disk_encryption"`

LKEClusterID int `json:"lke_cluster_id"`
LKEClusterID int `json:"lke_cluster_id"`
Capabilities []string `json:"capabilities"`
}

// InstanceSpec represents a linode spec
Expand Down
1 change: 1 addition & 0 deletions regions.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const (
CapabilityBackups string = "Backups"
CapabilityPlacementGroup string = "Placement Group"
CapabilityDiskEncryption string = "Disk Encryption"
CapabilityBlockStorageEncryption string = "Block Storage Encryption"
)

// Region-related endpoints have a custom expiry time as the
Expand Down
468 changes: 468 additions & 0 deletions test/integration/fixtures/TestInstance_withBlockStorageEncryption.yaml

Large diffs are not rendered by default.

336 changes: 336 additions & 0 deletions test/integration/fixtures/TestRegions_blockStorageEncryption.yaml

Large diffs are not rendered by default.

462 changes: 462 additions & 0 deletions test/integration/fixtures/TestVolume_Create_withEncryption.yaml

Large diffs are not rendered by default.

594 changes: 594 additions & 0 deletions test/integration/fixtures/TestVolume_Get_withEncryption.yaml

Large diffs are not rendered by default.

25 changes: 21 additions & 4 deletions test/integration/instances_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@ package integration
import (
"context"
"encoding/base64"
"github.com/linode/linodego"
"github.com/stretchr/testify/require"
"slices"
"strconv"
"testing"

"github.com/stretchr/testify/require"

"github.com/linode/linodego"
)

type instanceModifier func(*linodego.Client, *linodego.InstanceCreateOptions)
Expand Down Expand Up @@ -561,6 +560,24 @@ func TestInstance_DiskEncryption(t *testing.T) {
}
}

func TestInstance_withBlockStorageEncryption(t *testing.T) {
client, clientTeardown := createTestClient(t, "fixtures/TestInstance_withBlockStorageEncryption")

inst, err := createInstance(t, client, true, func(client *linodego.Client, options *linodego.InstanceCreateOptions) {
options.Region = getRegionsWithCaps(t, client, []string{"Linodes", "Block Storage Encryption"})[0]
options.Label = "go-inst-test-create-bde"
})
require.NoError(t, err)

defer func() {
client.DeleteInstance(context.Background(), inst.ID)
clientTeardown()
}()

// Filtering is not currently supported on capabilities
require.True(t, slices.Contains(inst.Capabilities, "Block Storage Encryption"))
}

func TestInstance_withPG(t *testing.T) {
client, clientTeardown := createTestClient(t, "fixtures/TestInstance_withPG")

Expand Down
14 changes: 14 additions & 0 deletions test/integration/regions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,17 @@ func TestRegions_pgLimits(t *testing.T) {
require.NotZero(t, region.PlacementGroupLimits.MaximumLinodesPerPG)
require.NotZero(t, region.PlacementGroupLimits.MaximumPGsPerCustomer)
}

func TestRegions_blockStorageEncryption(t *testing.T) {
client, teardown := createTestClient(t, "fixtures/TestRegions_blockStorageEncryption")
defer teardown()

regions, err := client.ListRegions(context.Background(), nil)
require.NoError(t, err)

// Filtering is not currently supported on capabilities
regionIdx := slices.IndexFunc(regions, func(region linodego.Region) bool {
return slices.Contains(region.Capabilities, "Block Storage Encryption")
})
require.NotZero(t, regionIdx)
}
76 changes: 76 additions & 0 deletions test/integration/volumes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,33 @@ func TestVolume_Create_smoke(t *testing.T) {
}
}

func TestVolume_Create_withEncryption(t *testing.T) {
client, teardown := createTestClient(t, "fixtures/TestVolume_Create_withEncryption")
defer teardown()

createOpts := linodego.VolumeCreateOptions{
Label: "go-vol-test-create-encryption",
Region: getRegionsWithCaps(t, client, []string{"Linodes", "Block Storage Encryption"})[0],
Encryption: "enabled",
}
volume, err := client.CreateVolume(context.Background(), createOpts)
if err != nil {
t.Errorf("Error listing volumes, expected struct, got error %v", err)
}
if volume.ID == 0 {
t.Errorf("Expected a volumes id, but got 0")
}

assertDateSet(t, volume.Created)
assertDateSet(t, volume.Updated)

// volumes deleted too fast tend to stick, adding a few seconds to catch up
time.Sleep(time.Second * 5)
if err := client.DeleteVolume(context.Background(), volume.ID); err != nil {
t.Errorf("Expected to delete a volume, but got %v", err)
}
}

func TestVolume_Resize(t *testing.T) {
client, volume, teardown, err := setupVolume(t, "fixtures/TestVolume_Resize")
defer teardown()
Expand Down Expand Up @@ -88,6 +115,55 @@ func TestVolume_Get(t *testing.T) {
assertDateSet(t, volume.Updated)
}

func TestVolume_Get_withEncryption(t *testing.T) {
client, teardown := createTestClient(t, "fixtures/TestVolume_Get_withEncryption")
defer teardown()

createOpts := linodego.VolumeCreateOptions{
Label: "go-vol-test-get-encryption",
Region: getRegionsWithCaps(t, client, []string{"Linodes", "Block Storage Encryption"})[0],
Encryption: "enabled",
}
volume, err := client.CreateVolume(context.Background(), createOpts)
if err != nil {
t.Errorf("Error listing volumes, expected struct, got error %v", err)
}
if volume.ID == 0 {
t.Errorf("Expected a volumes id, but got 0")
}

returnedVolume, err := client.GetVolume(context.Background(), volume.ID)
if err != nil {
t.Errorf("Error getting volume %d, expected *LinodeVolume, got error %v", volume.ID, err)
}
if returnedVolume.Encryption != "enabled" {
t.Errorf("Expected volume encryption to be enabled, but got %v", returnedVolume.Encryption)
}

volumes, err := client.ListVolumes(context.Background(), nil)
if err != nil {
t.Errorf("Error listing volumes, expected struct, got error %v", err)
}
found := false
for _, v := range volumes {
if v.ID == volume.ID {
found = true
if v.Encryption != "enabled" {
t.Errorf("Expected volume encryption to be enabled, but got %v", v.Encryption)
}
}
}
if !found {
t.Errorf("%d volume not found in list", volume.ID)
}

// volumes deleted too fast tend to stick, adding a few seconds to catch up
time.Sleep(time.Second * 5)
if err := client.DeleteVolume(context.Background(), volume.ID); err != nil {
t.Errorf("Expected to delete a volume, but got %v", err)
}
}

func TestVolume_WaitForLinodeID_nil(t *testing.T) {
client, volume, teardown, err := setupVolume(t, "fixtures/TestVolume_WaitForLinodeID_nil")
defer teardown()
Expand Down
4 changes: 4 additions & 0 deletions volumes.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ type Volume struct {
Tags []string `json:"tags"`
Created *time.Time `json:"-"`
Updated *time.Time `json:"-"`

// Note: Block Storage Disk Encryption is not currently available to all users.
Encryption string `json:"encryption"`
}

// VolumeCreateOptions fields are those accepted by CreateVolume
Expand All @@ -50,6 +53,7 @@ type VolumeCreateOptions struct {
// An array of tags applied to this object. Tags are for organizational purposes only.
Tags []string `json:"tags"`
PersistAcrossBoots *bool `json:"persist_across_boots,omitempty"`
Encryption string `json:"encryption,omitempty"`
}

// VolumeUpdateOptions fields are those accepted by UpdateVolume
Expand Down

0 comments on commit 9bbcf49

Please sign in to comment.