Add retries to Yandex builder
Signed-off-by: Gennady Lipenkov <xgen@yandex-team.ru>
This commit is contained in:
parent
211f7bd9de
commit
fceaa9ccf9
|
@ -4,12 +4,14 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
"github.com/hashicorp/packer/common"
|
"github.com/hashicorp/packer/common"
|
||||||
"github.com/hashicorp/packer/helper/communicator"
|
"github.com/hashicorp/packer/helper/communicator"
|
||||||
"github.com/hashicorp/packer/helper/multistep"
|
"github.com/hashicorp/packer/helper/multistep"
|
||||||
"github.com/hashicorp/packer/packer"
|
"github.com/hashicorp/packer/packer"
|
||||||
|
|
||||||
"github.com/yandex-cloud/go-genproto/yandex/cloud/compute/v1"
|
"github.com/yandex-cloud/go-genproto/yandex/cloud/compute/v1"
|
||||||
|
"github.com/yandex-cloud/go-sdk/pkg/requestid"
|
||||||
)
|
)
|
||||||
|
|
||||||
// The unique ID for this builder.
|
// The unique ID for this builder.
|
||||||
|
@ -35,6 +37,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
|
||||||
// representing a Yandex.Cloud compute image.
|
// representing a Yandex.Cloud compute image.
|
||||||
func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) {
|
func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) {
|
||||||
driver, err := NewDriverYC(ui, b.config)
|
driver, err := NewDriverYC(ui, b.config)
|
||||||
|
ctx = requestid.ContextWithClientTraceID(ctx, uuid.New().String())
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
//go:generate struct-markdown
|
|
||||||
|
|
||||||
package yandex
|
package yandex
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -22,6 +20,7 @@ import (
|
||||||
const defaultEndpoint = "api.cloud.yandex.net:443"
|
const defaultEndpoint = "api.cloud.yandex.net:443"
|
||||||
const defaultGpuPlatformID = "gpu-standard-v1"
|
const defaultGpuPlatformID = "gpu-standard-v1"
|
||||||
const defaultPlatformID = "standard-v1"
|
const defaultPlatformID = "standard-v1"
|
||||||
|
const defaultMaxRetries = 3
|
||||||
const defaultZone = "ru-central1-a"
|
const defaultZone = "ru-central1-a"
|
||||||
|
|
||||||
var reImageFamily = regexp.MustCompile(`^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$`)
|
var reImageFamily = regexp.MustCompile(`^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$`)
|
||||||
|
@ -74,6 +73,8 @@ type Config struct {
|
||||||
Labels map[string]string `mapstructure:"labels" required:"false"`
|
Labels map[string]string `mapstructure:"labels" required:"false"`
|
||||||
// Identifier of the hardware platform configuration for the instance. This defaults to standard-v1.
|
// Identifier of the hardware platform configuration for the instance. This defaults to standard-v1.
|
||||||
PlatformID string `mapstructure:"platform_id" required:"false"`
|
PlatformID string `mapstructure:"platform_id" required:"false"`
|
||||||
|
// The maximum number of times an API request is being executed
|
||||||
|
MaxRetries int `mapstructure:"max_retries"`
|
||||||
// Metadata applied to the launched instance.
|
// Metadata applied to the launched instance.
|
||||||
Metadata map[string]string `mapstructure:"metadata" required:"false"`
|
Metadata map[string]string `mapstructure:"metadata" required:"false"`
|
||||||
// Metadata applied to the launched instance. Value are file paths.
|
// Metadata applied to the launched instance. Value are file paths.
|
||||||
|
@ -219,6 +220,10 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
|
||||||
c.Zone = defaultZone
|
c.Zone = defaultZone
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if c.MaxRetries == 0 {
|
||||||
|
c.MaxRetries = defaultMaxRetries
|
||||||
|
}
|
||||||
|
|
||||||
// provision config by OS environment variables
|
// provision config by OS environment variables
|
||||||
if c.Token == "" {
|
if c.Token == "" {
|
||||||
c.Token = os.Getenv("YC_TOKEN")
|
c.Token = os.Getenv("YC_TOKEN")
|
||||||
|
|
|
@ -4,10 +4,13 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
|
||||||
"github.com/hashicorp/packer/helper/useragent"
|
"github.com/hashicorp/packer/helper/useragent"
|
||||||
"github.com/hashicorp/packer/packer"
|
"github.com/hashicorp/packer/packer"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
"google.golang.org/grpc/metadata"
|
"google.golang.org/grpc/metadata"
|
||||||
|
|
||||||
"github.com/yandex-cloud/go-genproto/yandex/cloud/compute/v1"
|
"github.com/yandex-cloud/go-genproto/yandex/cloud/compute/v1"
|
||||||
|
@ -16,9 +19,15 @@ import (
|
||||||
ycsdk "github.com/yandex-cloud/go-sdk"
|
ycsdk "github.com/yandex-cloud/go-sdk"
|
||||||
"github.com/yandex-cloud/go-sdk/iamkey"
|
"github.com/yandex-cloud/go-sdk/iamkey"
|
||||||
"github.com/yandex-cloud/go-sdk/pkg/requestid"
|
"github.com/yandex-cloud/go-sdk/pkg/requestid"
|
||||||
|
"github.com/yandex-cloud/go-sdk/pkg/retry"
|
||||||
"github.com/yandex-cloud/go-sdk/sdkresolvers"
|
"github.com/yandex-cloud/go-sdk/sdkresolvers"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultExponentialBackoffBase = 50 * time.Millisecond
|
||||||
|
defaultExponentialBackoffCap = 1 * time.Minute
|
||||||
|
)
|
||||||
|
|
||||||
type driverYC struct {
|
type driverYC struct {
|
||||||
sdk *ycsdk.SDK
|
sdk *ycsdk.SDK
|
||||||
ui packer.Ui
|
ui packer.Ui
|
||||||
|
@ -51,11 +60,23 @@ func NewDriverYC(ui packer.Ui, config *Config) (Driver, error) {
|
||||||
sdkConfig.Credentials = credentials
|
sdkConfig.Credentials = credentials
|
||||||
}
|
}
|
||||||
|
|
||||||
|
requestIDInterceptor := requestid.Interceptor()
|
||||||
|
|
||||||
|
retryInterceptor := retry.Interceptor(
|
||||||
|
retry.WithMax(config.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)
|
||||||
|
|
||||||
userAgentMD := metadata.Pairs("user-agent", useragent.String())
|
userAgentMD := metadata.Pairs("user-agent", useragent.String())
|
||||||
|
|
||||||
sdk, err := ycsdk.Build(context.Background(), sdkConfig,
|
sdk, err := ycsdk.Build(context.Background(), sdkConfig,
|
||||||
grpc.WithDefaultCallOptions(grpc.Header(&userAgentMD)),
|
grpc.WithDefaultCallOptions(grpc.Header(&userAgentMD)),
|
||||||
grpc.WithUnaryInterceptor(requestid.Interceptor()))
|
grpc.WithUnaryInterceptor(interceptorChain))
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -106,6 +106,8 @@ can be configured for this builder.
|
||||||
|
|
||||||
- `platform_id` (string) - Identifier of the hardware platform configuration for the instance. This defaults to `standard-v1`.
|
- `platform_id` (string) - Identifier of the hardware platform configuration for the instance. This defaults to `standard-v1`.
|
||||||
|
|
||||||
|
- `max_retries` (number) - The maximum number of times an API request is being executed.
|
||||||
|
|
||||||
- `metadata` (object of key/value strings) - Metadata applied to the launched
|
- `metadata` (object of key/value strings) - Metadata applied to the launched
|
||||||
instance.
|
instance.
|
||||||
|
|
||||||
|
@ -135,10 +137,11 @@ can be configured for this builder.
|
||||||
|
|
||||||
- `source_image_folder_id` (string) - The ID of the folder containing the source image.
|
- `source_image_folder_id` (string) - The ID of the folder containing the source image.
|
||||||
|
|
||||||
- `source_image_id` (string) - The source image ID to use to create the new image from.
|
- `source_image_id` (string) - The source image ID to use to create the new image
|
||||||
|
from.
|
||||||
|
|
||||||
- `source_image_name` (string) - The source image name to use to create the new image from.
|
- `source_image_name` (string) - The source image name to use to create the new image
|
||||||
Name will be looked up in `source_image_folder_id`.
|
from. Name will be looked up in `source_image_folder_id`.
|
||||||
|
|
||||||
- `state_timeout` (string) - The time to wait for instance state changes.
|
- `state_timeout` (string) - The time to wait for instance state changes.
|
||||||
Defaults to `5m`.
|
Defaults to `5m`.
|
||||||
|
|
Loading…
Reference in New Issue