/
utils.go
154 lines (125 loc) · 4.31 KB
/
utils.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
package yandeximport
import (
"context"
"fmt"
"os"
"strings"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/s3"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
"github.com/hashicorp/packer/builder/yandex"
"github.com/yandex-cloud/go-genproto/yandex/cloud/compute/v1"
)
func uploadToBucket(s3conn *s3.S3, ui packersdk.Ui, artifact packersdk.Artifact, bucket string, objectName string) (cloudImageSource, error) {
ui.Say("Looking for qcow2 file in list of artifacts...")
source := ""
for _, path := range artifact.Files() {
ui.Say(fmt.Sprintf("Found artifact %v...", path))
if strings.HasSuffix(path, ".qcow2") {
source = path
break
}
}
if source == "" {
return nil, fmt.Errorf("no qcow2 file found in list of artifacts")
}
artifactFile, err := os.Open(source)
if err != nil {
err := fmt.Errorf("error opening %v", source)
return nil, err
}
ui.Say(fmt.Sprintf("Uploading file %v to bucket %v/%v...", source, bucket, objectName))
_, err = s3conn.PutObject(&s3.PutObjectInput{
Bucket: aws.String(bucket),
Key: aws.String(objectName),
Body: artifactFile,
})
if err != nil {
ui.Say(fmt.Sprintf("Failed to upload: %v", objectName))
return nil, err
}
req, _ := s3conn.GetObjectRequest(&s3.GetObjectInput{
Bucket: aws.String(bucket),
Key: aws.String(objectName),
})
// Compute service allow only `https://storage.yandexcloud.net/...` URLs for Image create process
req.Config.S3ForcePathStyle = aws.Bool(true)
err = req.Build()
if err != nil {
ui.Say(fmt.Sprintf("Failed to build S3 request: %v", err))
return nil, err
}
return &objectSource{
url: req.HTTPRequest.URL.String(),
}, nil
}
func createYCImage(ctx context.Context, driver yandex.Driver, ui packersdk.Ui, imageSrc cloudImageSource, c *Config) (*compute.Image, error) {
req := &compute.CreateImageRequest{
FolderId: c.CloudConfig.FolderID,
Name: c.ImageConfig.ImageName,
Description: c.ImageConfig.ImageDescription,
Labels: c.ImageConfig.ImageLabels,
Family: c.ImageConfig.ImageFamily,
MinDiskSize: int64(c.ImageMinDiskSizeGb),
ProductIds: c.ImageProductIDs,
}
// switch on cloudImageSource type: cloud image id or storage URL
switch v := imageSrc.(type) {
case *imageSource:
req.Source = &compute.CreateImageRequest_ImageId{ImageId: v.imageID}
case *objectSource:
req.Source = &compute.CreateImageRequest_Uri{Uri: v.url}
}
op, err := driver.SDK().WrapOperation(driver.SDK().Compute().Image().Create(ctx, req))
if err != nil {
ui.Say("Error creating Yandex Compute Image")
return nil, err
}
ui.Say(fmt.Sprintf("Source of Image creation: %s", imageSrc.Description()))
ui.Say(fmt.Sprintf("Creating Yandex Compute Image %v within operation %#v", c.ImageName, op.Id()))
ui.Say("Waiting for Yandex Compute Image creation operation to complete...")
err = op.Wait(ctx)
// fail if image creation operation has an error
if err != nil {
return nil, fmt.Errorf("failed to create Yandex Compute Image: %s", err)
}
protoMetadata, err := op.Metadata()
if err != nil {
return nil, fmt.Errorf("error while get image create operation metadata: %s", err)
}
md, ok := protoMetadata.(*compute.CreateImageMetadata)
if !ok {
return nil, fmt.Errorf("could not get Image ID from create operation metadata")
}
image, err := driver.SDK().Compute().Image().Get(ctx, &compute.GetImageRequest{
ImageId: md.ImageId,
})
if err != nil {
return nil, fmt.Errorf("error while image get request: %s", err)
}
return image, nil
}
func deleteFromBucket(s3conn *s3.S3, ui packersdk.Ui, imageSrc cloudImageSource) error {
var url string
// switch on cloudImageSource type: cloud image id or storage URL
switch v := imageSrc.(type) {
case *objectSource:
url = v.GetSourceID()
case *imageSource:
return fmt.Errorf("invalid argument for `deleteFromBucket` method: %v", v)
}
bucket, objectName, err := s3URLToBucketKey(url)
if err != nil {
return err
}
ui.Say(fmt.Sprintf("Deleting import source from Object Storage %s/%s...", bucket, objectName))
_, err = s3conn.DeleteObject(&s3.DeleteObjectInput{
Bucket: aws.String(bucket),
Key: aws.String(objectName),
})
if err != nil {
ui.Say(fmt.Sprintf("Failed to delete: %v/%v", bucket, objectName))
return fmt.Errorf("error deleting storage object %q in bucket %q: %s ", objectName, bucket, err)
}
return nil
}