readysite / pkg / platform / providers / aws / volume.go
2.5 KB
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
}
← Back