cloudapi: Share an ec2 snapshot/ami with an account
This commit is contained in:
parent
6388aaff4c
commit
22c9f6af61
10 changed files with 118 additions and 28 deletions
|
|
@ -97,7 +97,7 @@ func UploadImageToAWS(c *awsCredentials, imagePath string, imageName string) err
|
|||
if err != nil {
|
||||
return fmt.Errorf("cannot upload the image: %#v", err)
|
||||
}
|
||||
_, err = uploader.Register(imageName, c.Bucket, imageName)
|
||||
_, err = uploader.Register(imageName, c.Bucket, imageName, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot register the image: %#v", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,9 +26,10 @@ type AWSUploadRequestOptions struct {
|
|||
|
||||
// AWSUploadRequestOptionsEc2 defines model for AWSUploadRequestOptionsEc2.
|
||||
type AWSUploadRequestOptionsEc2 struct {
|
||||
AccessKeyId string `json:"access_key_id"`
|
||||
SecretAccessKey string `json:"secret_access_key"`
|
||||
SnapshotName *string `json:"snapshot_name,omitempty"`
|
||||
AccessKeyId string `json:"access_key_id"`
|
||||
SecretAccessKey string `json:"secret_access_key"`
|
||||
ShareWithAccounts *[]string `json:"share_with_accounts,omitempty"`
|
||||
SnapshotName *string `json:"snapshot_name,omitempty"`
|
||||
}
|
||||
|
||||
// AWSUploadRequestOptionsS3 defines model for AWSUploadRequestOptionsS3.
|
||||
|
|
|
|||
|
|
@ -210,6 +210,11 @@ components:
|
|||
snapshot_name:
|
||||
type: string
|
||||
example: 'my-snapshot'
|
||||
share_with_accounts:
|
||||
type: array
|
||||
example: ['123456789012']
|
||||
items:
|
||||
type: string
|
||||
Customizations:
|
||||
type: object
|
||||
properties:
|
||||
|
|
|
|||
|
|
@ -167,14 +167,19 @@ func (server *Server) Compose(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
var share []string
|
||||
if awsUploadOptions.Ec2.ShareWithAccounts != nil {
|
||||
share = *awsUploadOptions.Ec2.ShareWithAccounts
|
||||
}
|
||||
key := fmt.Sprintf("composer-api-%s", uuid.New().String())
|
||||
t := target.NewAWSTarget(&target.AWSTargetOptions{
|
||||
Filename: imageType.Filename(),
|
||||
Region: awsUploadOptions.Region,
|
||||
AccessKeyID: awsUploadOptions.S3.AccessKeyId,
|
||||
SecretAccessKey: awsUploadOptions.S3.SecretAccessKey,
|
||||
Bucket: awsUploadOptions.S3.Bucket,
|
||||
Key: key,
|
||||
Filename: imageType.Filename(),
|
||||
Region: awsUploadOptions.Region,
|
||||
AccessKeyID: awsUploadOptions.S3.AccessKeyId,
|
||||
SecretAccessKey: awsUploadOptions.S3.SecretAccessKey,
|
||||
Bucket: awsUploadOptions.S3.Bucket,
|
||||
Key: key,
|
||||
ShareWithAccounts: share,
|
||||
})
|
||||
if awsUploadOptions.Ec2.SnapshotName != nil {
|
||||
t.ImageName = *awsUploadOptions.Ec2.SnapshotName
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
package target
|
||||
|
||||
type AWSTargetOptions struct {
|
||||
Filename string `json:"filename"`
|
||||
Region string `json:"region"`
|
||||
AccessKeyID string `json:"accessKeyID"`
|
||||
SecretAccessKey string `json:"secretAccessKey"`
|
||||
Bucket string `json:"bucket"`
|
||||
Key string `json:"key"`
|
||||
Filename string `json:"filename"`
|
||||
Region string `json:"region"`
|
||||
AccessKeyID string `json:"accessKeyID"`
|
||||
SecretAccessKey string `json:"secretAccessKey"`
|
||||
Bucket string `json:"bucket"`
|
||||
Key string `json:"key"`
|
||||
ShareWithAccounts []string `json:"shareWithAccounts"`
|
||||
}
|
||||
|
||||
func (AWSTargetOptions) isTargetOptions() {}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import (
|
|||
|
||||
type AWS struct {
|
||||
uploader *s3manager.Uploader
|
||||
importer *ec2.EC2
|
||||
ec2 *ec2.EC2
|
||||
s3 *s3.S3
|
||||
}
|
||||
|
||||
|
|
@ -36,7 +36,7 @@ func New(region, accessKeyID, accessKey string) (*AWS, error) {
|
|||
|
||||
return &AWS{
|
||||
uploader: s3manager.NewUploader(sess),
|
||||
importer: ec2.New(sess),
|
||||
ec2: ec2.New(sess),
|
||||
s3: s3.New(sess),
|
||||
}, nil
|
||||
}
|
||||
|
|
@ -117,10 +117,10 @@ func WaitUntilImportSnapshotTaskCompletedWithContext(c *ec2.EC2, ctx aws.Context
|
|||
// Register is a function that imports a snapshot, waits for the snapshot to
|
||||
// fully import, tags the snapshot, cleans up the image in S3, and registers
|
||||
// an AMI in AWS.
|
||||
func (a *AWS) Register(name, bucket, key string) (*string, error) {
|
||||
func (a *AWS) Register(name, bucket, key string, shareWith []string) (*string, error) {
|
||||
log.Printf("[AWS] 📥 Importing snapshot from image: %s/%s", bucket, key)
|
||||
snapshotDescription := fmt.Sprintf("Image Builder AWS Import of %s", name)
|
||||
importTaskOutput, err := a.importer.ImportSnapshot(
|
||||
importTaskOutput, err := a.ec2.ImportSnapshot(
|
||||
&ec2.ImportSnapshotInput{
|
||||
Description: aws.String(snapshotDescription),
|
||||
DiskContainer: &ec2.SnapshotDiskContainer{
|
||||
|
|
@ -132,12 +132,13 @@ func (a *AWS) Register(name, bucket, key string) (*string, error) {
|
|||
},
|
||||
)
|
||||
if err != nil {
|
||||
log.Printf("[AWS] error importing snapshot: %s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log.Printf("[AWS] 🚚 Waiting for snapshot to finish importing: %s", *importTaskOutput.ImportTaskId)
|
||||
err = WaitUntilImportSnapshotTaskCompleted(
|
||||
a.importer,
|
||||
a.ec2,
|
||||
&ec2.DescribeImportSnapshotTasksInput{
|
||||
ImportTaskIds: []*string{
|
||||
importTaskOutput.ImportTaskId,
|
||||
|
|
@ -158,7 +159,7 @@ func (a *AWS) Register(name, bucket, key string) (*string, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
importOutput, err := a.importer.DescribeImportSnapshotTasks(
|
||||
importOutput, err := a.ec2.DescribeImportSnapshotTasks(
|
||||
&ec2.DescribeImportSnapshotTasksInput{
|
||||
ImportTaskIds: []*string{
|
||||
importTaskOutput.ImportTaskId,
|
||||
|
|
@ -171,8 +172,28 @@ func (a *AWS) Register(name, bucket, key string) (*string, error) {
|
|||
|
||||
snapshotID := importOutput.ImportSnapshotTasks[0].SnapshotTaskDetail.SnapshotId
|
||||
|
||||
if len(shareWith) > 0 {
|
||||
log.Printf("[AWS] 🎥 Sharing ec2 snapshot")
|
||||
var userIds []*string
|
||||
for _, v := range shareWith {
|
||||
userIds = append(userIds, &v)
|
||||
}
|
||||
_, err := a.ec2.ModifySnapshotAttribute(
|
||||
&ec2.ModifySnapshotAttributeInput{
|
||||
Attribute: aws.String("createVolumePermission"),
|
||||
OperationType: aws.String("add"),
|
||||
SnapshotId: snapshotID,
|
||||
UserIds: userIds,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Println("[AWS] 📨 Shared ec2 snapshot")
|
||||
}
|
||||
|
||||
// Tag the snapshot with the image name.
|
||||
req, _ := a.importer.CreateTagsRequest(
|
||||
req, _ := a.ec2.CreateTagsRequest(
|
||||
&ec2.CreateTagsInput{
|
||||
Resources: []*string{snapshotID},
|
||||
Tags: []*ec2.Tag{
|
||||
|
|
@ -189,7 +210,7 @@ func (a *AWS) Register(name, bucket, key string) (*string, error) {
|
|||
}
|
||||
|
||||
log.Printf("[AWS] 📋 Registering AMI from imported snapshot: %s", *snapshotID)
|
||||
registerOutput, err := a.importer.RegisterImage(
|
||||
registerOutput, err := a.ec2.RegisterImage(
|
||||
&ec2.RegisterImageInput{
|
||||
Architecture: aws.String("x86_64"),
|
||||
VirtualizationType: aws.String("hvm"),
|
||||
|
|
@ -211,5 +232,28 @@ func (a *AWS) Register(name, bucket, key string) (*string, error) {
|
|||
}
|
||||
|
||||
log.Printf("[AWS] 🎉 AMI registered: %s", *registerOutput.ImageId)
|
||||
|
||||
if len(shareWith) > 0 {
|
||||
log.Println("[AWS] 💿 Sharing ec2 AMI")
|
||||
var launchPerms []*ec2.LaunchPermission
|
||||
for _, id := range shareWith {
|
||||
launchPerms = append(launchPerms, &ec2.LaunchPermission{
|
||||
UserId: &id,
|
||||
})
|
||||
}
|
||||
_, err := a.ec2.ModifyImageAttribute(
|
||||
&ec2.ModifyImageAttributeInput{
|
||||
ImageId: registerOutput.ImageId,
|
||||
LaunchPermission: &ec2.LaunchPermissionModifications{
|
||||
Add: launchPerms,
|
||||
},
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Println("[AWS] 💿 Shared AMI")
|
||||
}
|
||||
|
||||
return registerOutput.ImageId, nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue