volume.go
package aws
import (
"fmt"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/ec2"
"github.com/aws/aws-sdk-go-v2/service/ec2/types"
"github.com/readysite/readysite/pkg/platform"
)
// CreateVolume creates an EBS volume
func (b *backend) CreateVolume(name string, sizeGB int, region platform.Region) (*platform.Volume, error) {
az, ok := regions[region]
if !ok {
return nil, fmt.Errorf("%w: %s", platform.ErrUnsupportedRegion, region)
}
// AWS needs availability zone, append 'a'
az = az + "a"
input := &ec2.CreateVolumeInput{
AvailabilityZone: aws.String(az),
Size: aws.Int32(int32(sizeGB)),
VolumeType: types.VolumeTypeGp3,
TagSpecifications: []types.TagSpecification{
{
ResourceType: types.ResourceTypeVolume,
Tags: []types.Tag{
{Key: aws.String("Name"), Value: aws.String(name)},
},
},
},
}
result, err := b.ec2.CreateVolume(b.ctx, input)
if err != nil {
return nil, fmt.Errorf("create volume: %w", err)
}
return &platform.Volume{
ID: *result.VolumeId,
Name: name,
Size: int(*result.Size),
Region: *result.AvailabilityZone,
}, nil
}
// GetVolume retrieves an EBS volume by name
func (b *backend) GetVolume(name string) (*platform.Volume, error) {
input := &ec2.DescribeVolumesInput{
Filters: []types.Filter{
{Name: aws.String("tag:Name"), Values: []string{name}},
},
}
result, err := b.ec2.DescribeVolumes(b.ctx, input)
if err != nil {
return nil, fmt.Errorf("describe volumes: %w", err)
}
for _, v := range result.Volumes {
serverID := ""
if len(v.Attachments) > 0 {
serverID = *v.Attachments[0].InstanceId
}
return &platform.Volume{
ID: *v.VolumeId,
Name: name,
Size: int(*v.Size),
Region: *v.AvailabilityZone,
ServerID: serverID,
}, nil
}
return nil, platform.ErrNotFound
}
// AttachVolume attaches an EBS volume to an EC2 instance
func (b *backend) AttachVolume(volumeID, serverID string) error {
input := &ec2.AttachVolumeInput{
Device: aws.String("/dev/sdf"),
InstanceId: aws.String(serverID),
VolumeId: aws.String(volumeID),
}
_, err := b.ec2.AttachVolume(b.ctx, input)
if err != nil {
return fmt.Errorf("attach volume: %w", err)
}
return nil
}
// DetachVolume detaches an EBS volume
func (b *backend) DetachVolume(volumeID string) error {
input := &ec2.DetachVolumeInput{
VolumeId: aws.String(volumeID),
}
_, err := b.ec2.DetachVolume(b.ctx, input)
if err != nil {
return fmt.Errorf("detach volume: %w", err)
}
return nil
}