2020-07-08 14:58:56 -04:00
|
|
|
package yandeximport
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2020-07-16 17:59:39 -04:00
|
|
|
"net/url"
|
|
|
|
"strings"
|
|
|
|
"time"
|
2020-07-08 14:58:56 -04:00
|
|
|
|
|
|
|
"github.com/aws/aws-sdk-go/aws"
|
|
|
|
"github.com/aws/aws-sdk-go/aws/credentials"
|
|
|
|
"github.com/aws/aws-sdk-go/aws/session"
|
|
|
|
"github.com/aws/aws-sdk-go/service/s3"
|
2020-07-16 17:59:39 -04:00
|
|
|
"github.com/hashicorp/packer/packer"
|
2020-07-08 14:58:56 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
const defaultS3Region = "ru-central1"
|
|
|
|
const defaultStorageEndpoint = "storage.yandexcloud.net"
|
|
|
|
|
|
|
|
func newYCStorageClient(storageEndpoint, accessKey, secretKey string) (*s3.S3, error) {
|
|
|
|
var creds *credentials.Credentials
|
|
|
|
|
|
|
|
if storageEndpoint == "" {
|
|
|
|
storageEndpoint = defaultStorageEndpoint
|
|
|
|
}
|
|
|
|
|
|
|
|
s3Config := &aws.Config{
|
|
|
|
Endpoint: aws.String(storageEndpoint),
|
|
|
|
Region: aws.String(defaultS3Region),
|
|
|
|
}
|
|
|
|
|
|
|
|
switch {
|
|
|
|
case accessKey != "" && secretKey != "":
|
|
|
|
creds = credentials.NewStaticCredentials(accessKey, secretKey, "")
|
|
|
|
default:
|
|
|
|
return nil, fmt.Errorf("either access or secret key not provided")
|
|
|
|
}
|
|
|
|
|
|
|
|
s3Config.Credentials = creds
|
|
|
|
newSession, err := session.NewSession(s3Config)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return s3.New(newSession), nil
|
|
|
|
}
|
2020-07-16 17:59:39 -04:00
|
|
|
|
|
|
|
// Get path-style S3 URL and return presigned URL
|
2020-07-21 18:01:30 -04:00
|
|
|
func presignUrl(s3conn *s3.S3, ui packer.Ui, fullUrl string) (cloudImageSource, error) {
|
2020-07-16 17:59:39 -04:00
|
|
|
bucket, key, err := s3URLToBucketKey(fullUrl)
|
|
|
|
if err != nil {
|
2020-07-21 18:01:30 -04:00
|
|
|
return nil, err
|
2020-07-16 17:59:39 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
req, _ := s3conn.GetObjectRequest(&s3.GetObjectInput{
|
|
|
|
Bucket: aws.String(bucket),
|
|
|
|
Key: aws.String(key),
|
|
|
|
})
|
|
|
|
|
|
|
|
// Compute service allow only `https://storage.yandexcloud.net/...` URLs for Image create process
|
|
|
|
req.Config.S3ForcePathStyle = aws.Bool(true)
|
|
|
|
|
2020-07-16 18:09:49 -04:00
|
|
|
urlStr, _, err := req.PresignRequest(30 * time.Minute)
|
2020-07-16 17:59:39 -04:00
|
|
|
if err != nil {
|
|
|
|
ui.Say(fmt.Sprintf("Failed to presign url: %s", err))
|
2020-07-21 18:01:30 -04:00
|
|
|
return nil, err
|
2020-07-16 17:59:39 -04:00
|
|
|
}
|
|
|
|
|
2020-07-21 18:01:30 -04:00
|
|
|
return &objectSource{
|
|
|
|
urlStr,
|
|
|
|
}, nil
|
2020-07-16 17:59:39 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
func s3URLToBucketKey(storageURL string) (bucket string, key string, err error) {
|
|
|
|
u, err := url.Parse(storageURL)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if u.Scheme == "s3" {
|
|
|
|
// s3://bucket/key
|
|
|
|
bucket = u.Host
|
|
|
|
key = strings.TrimLeft(u.Path, "/")
|
|
|
|
} else if u.Scheme == "https" {
|
|
|
|
// https://***.storage.yandexcloud.net/...
|
|
|
|
if u.Host == defaultStorageEndpoint {
|
|
|
|
// No bucket name in the host part
|
|
|
|
path := strings.SplitN(u.Path, "/", 3)
|
|
|
|
bucket = path[1]
|
|
|
|
key = path[2]
|
|
|
|
} else {
|
|
|
|
// Bucket name in host
|
|
|
|
bucket = strings.TrimSuffix(u.Host, "."+defaultStorageEndpoint)
|
|
|
|
key = strings.TrimLeft(u.Path, "/")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|