packer-cn/builder/yandex/driver_yc.go

266 lines
6.6 KiB
Go
Raw Normal View History

2019-03-26 08:29:15 -04:00
package yandex
import (
"context"
"fmt"
2019-03-26 08:29:15 -04:00
"log"
"strings"
"time"
2019-03-26 08:29:15 -04:00
grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
2020-12-17 16:29:25 -05:00
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
"github.com/hashicorp/packer-plugin-sdk/useragent"
2019-03-26 08:29:15 -04:00
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
2019-03-26 08:29:15 -04:00
"github.com/hashicorp/packer/builder/yandex/version"
2019-03-26 08:29:15 -04:00
"github.com/yandex-cloud/go-genproto/yandex/cloud/compute/v1"
"github.com/yandex-cloud/go-genproto/yandex/cloud/endpoint"
"github.com/yandex-cloud/go-genproto/yandex/cloud/vpc/v1"
2019-03-26 08:29:15 -04:00
ycsdk "github.com/yandex-cloud/go-sdk"
"github.com/yandex-cloud/go-sdk/iamkey"
"github.com/yandex-cloud/go-sdk/pkg/requestid"
"github.com/yandex-cloud/go-sdk/pkg/retry"
"github.com/yandex-cloud/go-sdk/sdkresolvers"
2019-03-26 08:29:15 -04:00
)
const (
defaultExponentialBackoffBase = 50 * time.Millisecond
defaultExponentialBackoffCap = 1 * time.Minute
)
2019-03-26 08:29:15 -04:00
type driverYC struct {
sdk *ycsdk.SDK
ui packersdk.Ui
2019-03-26 08:29:15 -04:00
}
func NewDriverYC(ui packersdk.Ui, ac *AccessConfig) (Driver, error) {
log.Printf("[INFO] Initialize Yandex.Cloud client...")
sdkConfig := ycsdk.Config{}
if ac.Endpoint != "" {
sdkConfig.Endpoint = ac.Endpoint
}
switch {
case ac.Token == "" && ac.ServiceAccountKeyFile == "":
2020-06-17 05:41:11 -04:00
log.Printf("[INFO] Use Instance Service Account for authentication")
sdkConfig.Credentials = ycsdk.InstanceServiceAccount()
case ac.Token != "":
if strings.HasPrefix(ac.Token, "t1.") && strings.Count(ac.Token, ".") == 2 {
log.Printf("[INFO] Use IAM token for authentication")
sdkConfig.Credentials = ycsdk.NewIAMTokenCredentials(ac.Token)
} else {
log.Printf("[INFO] Use OAuth token for authentication")
sdkConfig.Credentials = ycsdk.OAuthToken(ac.Token)
}
case ac.ServiceAccountKeyFile != "":
log.Printf("[INFO] Use Service Account key file %q for authentication", ac.ServiceAccountKeyFile)
key, err := iamkey.ReadFromJSONFile(ac.ServiceAccountKeyFile)
if err != nil {
return nil, err
}
credentials, err := ycsdk.ServiceAccountKey(key)
if err != nil {
return nil, err
}
sdkConfig.Credentials = credentials
}
requestIDInterceptor := requestid.Interceptor()
retryInterceptor := retry.Interceptor(
retry.WithMax(ac.MaxRetries),
retry.WithCodes(codes.Unavailable),
retry.WithAttemptHeader(true),
retry.WithBackoff(retry.BackoffExponentialWithJitter(defaultExponentialBackoffBase, defaultExponentialBackoffCap)))
// Make sure retry interceptor is above id interceptor.
// Now we will have new request id for every retry attempt.
interceptorChain := grpc_middleware.ChainUnaryClient(retryInterceptor, requestIDInterceptor)
sdk, err := ycsdk.Build(context.Background(), sdkConfig,
2020-12-09 08:48:35 -05:00
grpc.WithUserAgent(useragent.String(version.YandexPluginVersion.FormattedVersion())),
grpc.WithUnaryInterceptor(interceptorChain),
)
if err != nil {
return nil, err
}
if _, err = sdk.ApiEndpoint().ApiEndpoint().List(context.Background(), &endpoint.ListApiEndpointsRequest{}); err != nil {
return nil, err
}
return &driverYC{
sdk: sdk,
ui: ui,
}, nil
}
2019-03-26 08:29:15 -04:00
func (d *driverYC) GetImage(imageID string) (*Image, error) {
image, err := d.sdk.Compute().Image().Get(context.Background(), &compute.GetImageRequest{
ImageId: imageID,
})
if err != nil {
return nil, err
}
return &Image{
ID: image.Id,
Labels: image.Labels,
Licenses: image.ProductIds,
Name: image.Name,
Description: image.Description,
2019-03-26 08:29:15 -04:00
FolderID: image.FolderId,
MinDiskSizeGb: toGigabytes(image.MinDiskSize),
SizeGb: toGigabytes(image.StorageSize),
}, nil
}
func (d *driverYC) GetImageFromFolder(ctx context.Context, folderID string, family string) (*Image, error) {
image, err := d.sdk.Compute().Image().GetLatestByFamily(ctx, &compute.GetImageLatestByFamilyRequest{
2019-03-26 08:29:15 -04:00
FolderId: folderID,
Family: family,
})
if err != nil {
return nil, err
}
return &Image{
ID: image.Id,
Labels: image.Labels,
Licenses: image.ProductIds,
Name: image.Name,
Description: image.Description,
2019-03-26 08:29:15 -04:00
FolderID: image.FolderId,
Family: image.Family,
2019-03-26 08:29:15 -04:00
MinDiskSizeGb: toGigabytes(image.MinDiskSize),
SizeGb: toGigabytes(image.StorageSize),
}, nil
}
func (d *driverYC) GetImageFromFolderByName(ctx context.Context, folderID string, imageName string) (*Image, error) {
imageResolver := sdkresolvers.ImageResolver(imageName, sdkresolvers.FolderID(folderID))
if err := d.sdk.Resolve(ctx, imageResolver); err != nil {
return nil, fmt.Errorf("failed to resolve image name: %s", err)
}
return d.GetImage(imageResolver.ID())
}
func (d *driverYC) DeleteImage(ID string) error {
ctx := context.TODO()
op, err := d.sdk.WrapOperation(d.sdk.Compute().Image().Delete(ctx, &compute.DeleteImageRequest{
ImageId: ID,
}))
if err != nil {
return err
}
2019-03-26 08:29:15 -04:00
err = op.Wait(ctx)
if err != nil {
return err
2019-03-26 08:29:15 -04:00
}
_, err = op.Response()
return err
}
2019-03-26 08:29:15 -04:00
func (d *driverYC) SDK() *ycsdk.SDK {
return d.sdk
}
2019-03-26 08:29:15 -04:00
func (d *driverYC) DeleteInstance(ctx context.Context, instanceID string) error {
op, err := d.sdk.WrapOperation(d.sdk.Compute().Instance().Delete(ctx, &compute.DeleteInstanceRequest{
InstanceId: instanceID,
}))
if err != nil {
return err
}
2019-03-26 08:29:15 -04:00
err = op.Wait(ctx)
if err != nil {
return err
2019-03-26 08:29:15 -04:00
}
_, err = op.Response()
return err
}
2019-03-26 08:29:15 -04:00
func (d *driverYC) DeleteSubnet(ctx context.Context, subnetID string) error {
op, err := d.sdk.WrapOperation(d.sdk.VPC().Subnet().Delete(ctx, &vpc.DeleteSubnetRequest{
SubnetId: subnetID,
}))
if err != nil {
return err
}
2019-03-26 08:29:15 -04:00
err = op.Wait(ctx)
2019-03-26 08:29:15 -04:00
if err != nil {
return err
2019-03-26 08:29:15 -04:00
}
_, err = op.Response()
return err
}
func (d *driverYC) DeleteNetwork(ctx context.Context, networkID string) error {
op, err := d.sdk.WrapOperation(d.sdk.VPC().Network().Delete(ctx, &vpc.DeleteNetworkRequest{
NetworkId: networkID,
}))
if err != nil {
return err
2019-03-26 08:29:15 -04:00
}
err = op.Wait(ctx)
if err != nil {
return err
}
2019-03-26 08:29:15 -04:00
_, err = op.Response()
return err
2019-03-26 08:29:15 -04:00
}
func (d *driverYC) DeleteDisk(ctx context.Context, diskID string) error {
op, err := d.sdk.WrapOperation(d.sdk.Compute().Disk().Delete(ctx, &compute.DeleteDiskRequest{
DiskId: diskID,
}))
if err != nil {
return err
}
err = op.Wait(ctx)
if err != nil {
return err
}
_, err = op.Response()
return err
}
2020-04-26 19:37:10 -04:00
func (d *driverYC) GetInstanceMetadata(ctx context.Context, instanceID string, key string) (string, error) {
instance, err := d.sdk.Compute().Instance().Get(ctx, &compute.GetInstanceRequest{
2020-04-26 19:37:10 -04:00
InstanceId: instanceID,
View: compute.InstanceView_FULL,
})
if err != nil {
return "", err
}
for k, v := range instance.GetMetadata() {
if k == key {
return v, nil
}
}
return "", fmt.Errorf("Instance metadata key, %s, not found.", key)
2019-03-26 08:29:15 -04:00
}