From 4d8866824f15bc0db603ceef57a511925675af48 Mon Sep 17 00:00:00 2001 From: liranp Date: Tue, 4 Aug 2020 23:39:02 +0300 Subject: [PATCH] fix(spot): change `ScaleDown.MaxPercentage` from int to float64 --- go.mod | 2 +- go.sum | 4 +- pkg/model/spotinstmodel/instance_group.go | 4 +- .../fi/cloudup/spotinsttasks/elastigroup.go | 6 +- .../service/elastigroup/providers/aws/aws.go | 52 +-- .../ocean/providers/aws/launch_spec.go | 304 +++++++++++++++++- .../service/ocean/providers/aws/ocean.go | 293 ++++++++++++++++- .../service/ocean/providers/aws/ocean_ecs.go | 52 ++- .../service/ocean/providers/aws/service.go | 19 +- .../spotinst-sdk-go/spotinst/config.go | 4 +- .../spotinst/credentials/BUILD.bazel | 5 +- .../spotinst/credentials/credentials.go | 7 + .../spotinst/credentials/provider.go | 22 +- .../spotinst/credentials/provider_chain.go | 45 ++- .../spotinst/credentials/provider_env.go | 26 +- .../spotinst/credentials/provider_file.go | 47 ++- .../spotinst/credentials/provider_static.go | 23 +- .../spotinst/featureflag/BUILD.bazel | 12 + .../spotinst/featureflag/featureflag.go | 119 +++++++ .../spotinst/featureflag/features.go | 24 ++ .../spotinst-sdk-go/spotinst/version.go | 2 +- vendor/modules.txt | 3 +- 22 files changed, 949 insertions(+), 126 deletions(-) create mode 100644 vendor/github.com/spotinst/spotinst-sdk-go/spotinst/featureflag/BUILD.bazel create mode 100644 vendor/github.com/spotinst/spotinst-sdk-go/spotinst/featureflag/featureflag.go create mode 100644 vendor/github.com/spotinst/spotinst-sdk-go/spotinst/featureflag/features.go diff --git a/go.mod b/go.mod index 219bca4c11dca..4a24ae98c53ac 100644 --- a/go.mod +++ b/go.mod @@ -91,7 +91,7 @@ require ( github.com/spf13/cobra v0.0.5 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.4.0 - github.com/spotinst/spotinst-sdk-go v1.49.0 + github.com/spotinst/spotinst-sdk-go v1.56.0 github.com/stretchr/testify v1.5.1 github.com/urfave/cli v1.20.0 github.com/weaveworks/mesh v0.0.0-20170419100114-1f158d31de55 diff --git a/go.sum b/go.sum index e40a1fc1c1e56..eaf858e12b734 100644 --- a/go.sum +++ b/go.sum @@ -778,8 +778,8 @@ github.com/spf13/viper v1.3.2 h1:VUFqw5KcqRf7i70GOzW7N+Q7+gxVBkSSqiXB12+JQ4M= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= -github.com/spotinst/spotinst-sdk-go v1.49.0 h1:JmsLlsgd/cCKpcn04HrParo5r34owDzIC12IW1SpSEs= -github.com/spotinst/spotinst-sdk-go v1.49.0/go.mod h1:nWi2DyjUi1WUZclpsqZFXvImsU0T39ppqqHwC4/T5mw= +github.com/spotinst/spotinst-sdk-go v1.56.0 h1:w7OnAWXWPxvOvqjYv4i0kN70KWGTNcyoNB72suIA30g= +github.com/spotinst/spotinst-sdk-go v1.56.0/go.mod h1:nWi2DyjUi1WUZclpsqZFXvImsU0T39ppqqHwC4/T5mw= github.com/storageos/go-api v0.0.0-20180912212459-343b3eff91fc/go.mod h1:ZrLn+e0ZuF3Y65PNF6dIwbJPZqfmtCXxFm9ckv0agOY= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= diff --git a/pkg/model/spotinstmodel/instance_group.go b/pkg/model/spotinstmodel/instance_group.go index 8a95cf8f760ed..75f9481bc9444 100644 --- a/pkg/model/spotinstmodel/instance_group.go +++ b/pkg/model/spotinstmodel/instance_group.go @@ -815,14 +815,14 @@ func (b *InstanceGroupModelBuilder) buildAutoScalerOpts(clusterID string, ig *ko case InstanceGroupLabelAutoScalerScaleDownMaxPercentage: { - v, err := parseInt(v) + v, err := parseFloat(v) if err != nil { return nil, err } if opts.Down == nil { opts.Down = new(spotinsttasks.AutoScalerDownOpts) } - opts.Down.MaxPercentage = fi.Int(int(fi.Int64Value(v))) + opts.Down.MaxPercentage = v } case InstanceGroupLabelAutoScalerScaleDownEvaluationPeriods: diff --git a/upup/pkg/fi/cloudup/spotinsttasks/elastigroup.go b/upup/pkg/fi/cloudup/spotinsttasks/elastigroup.go index 26a0c7e251396..cdba6cb1e005c 100644 --- a/upup/pkg/fi/cloudup/spotinsttasks/elastigroup.go +++ b/upup/pkg/fi/cloudup/spotinsttasks/elastigroup.go @@ -96,7 +96,7 @@ type AutoScalerHeadroomOpts struct { } type AutoScalerDownOpts struct { - MaxPercentage *int + MaxPercentage *float64 EvaluationPeriods *int } @@ -1349,8 +1349,8 @@ type terraformAutoScalerHeadroom struct { } type terraformAutoScalerDown struct { - MaxPercentage *int `json:"max_scale_down_percentage,omitempty" cty:"max_scale_down_percentage"` - EvaluationPeriods *int `json:"evaluation_periods,omitempty" cty:"evaluation_periods"` + MaxPercentage *float64 `json:"max_scale_down_percentage,omitempty" cty:"max_scale_down_percentage"` + EvaluationPeriods *int `json:"evaluation_periods,omitempty" cty:"evaluation_periods"` } type terraformKV struct { diff --git a/vendor/github.com/spotinst/spotinst-sdk-go/service/elastigroup/providers/aws/aws.go b/vendor/github.com/spotinst/spotinst-sdk-go/service/elastigroup/providers/aws/aws.go index 2acae3bf6cbcc..0936da6d605f3 100644 --- a/vendor/github.com/spotinst/spotinst-sdk-go/service/elastigroup/providers/aws/aws.go +++ b/vendor/github.com/spotinst/spotinst-sdk-go/service/elastigroup/providers/aws/aws.go @@ -174,8 +174,8 @@ type AutoScaleHeadroom struct { } type AutoScaleDown struct { - EvaluationPeriods *int `json:"evaluationPeriods,omitempty"` - MaxScaleDownPercentage *int `json:"maxScaleDownPercentage,omitempty"` + EvaluationPeriods *int `json:"evaluationPeriods,omitempty"` + MaxScaleDownPercentage *float64 `json:"maxScaleDownPercentage,omitempty"` forceSendFields []string nullFields []string @@ -422,25 +422,26 @@ type Scaling struct { } type ScalingPolicy struct { - PolicyName *string `json:"policyName,omitempty"` - MetricName *string `json:"metricName,omitempty"` - Namespace *string `json:"namespace,omitempty"` - Source *string `json:"source,omitempty"` - Statistic *string `json:"statistic,omitempty"` - Unit *string `json:"unit,omitempty"` - Threshold *float64 `json:"threshold,omitempty"` - Adjustment *int `json:"adjustment,omitempty"` - MinTargetCapacity *int `json:"minTargetCapacity,omitempty"` - MaxTargetCapacity *int `json:"maxTargetCapacity,omitempty"` - EvaluationPeriods *int `json:"evaluationPeriods,omitempty"` - Period *int `json:"period,omitempty"` - Cooldown *int `json:"cooldown,omitempty"` - Operator *string `json:"operator,omitempty"` - Dimensions []*Dimension `json:"dimensions,omitempty"` - Action *Action `json:"action,omitempty"` - Target *float64 `json:"target,omitempty"` - IsEnabled *bool `json:"isEnabled,omitempty"` - Predictive *Predictive `json:"predictive,omitempty"` + PolicyName *string `json:"policyName,omitempty"` + MetricName *string `json:"metricName,omitempty"` + Namespace *string `json:"namespace,omitempty"` + Source *string `json:"source,omitempty"` + Statistic *string `json:"statistic,omitempty"` + Unit *string `json:"unit,omitempty"` + Threshold *float64 `json:"threshold,omitempty"` + Adjustment *int `json:"adjustment,omitempty"` + MinTargetCapacity *int `json:"minTargetCapacity,omitempty"` + MaxTargetCapacity *int `json:"maxTargetCapacity,omitempty"` + EvaluationPeriods *int `json:"evaluationPeriods,omitempty"` + Period *int `json:"period,omitempty"` + Cooldown *int `json:"cooldown,omitempty"` + Operator *string `json:"operator,omitempty"` + Dimensions []*Dimension `json:"dimensions,omitempty"` + Action *Action `json:"action,omitempty"` + Target *float64 `json:"target,omitempty"` + IsEnabled *bool `json:"isEnabled,omitempty"` + MaxCapacityPerScale *string `json:"maxCapacityPerScale,omitempty"` + Predictive *Predictive `json:"predictive,omitempty"` forceSendFields []string nullFields []string @@ -2213,7 +2214,7 @@ func (o *AutoScaleDown) SetEvaluationPeriods(v *int) *AutoScaleDown { return o } -func (o *AutoScaleDown) SetMaxScaleDownPercentage(v *int) *AutoScaleDown { +func (o *AutoScaleDown) SetMaxScaleDownPercentage(v *float64) *AutoScaleDown { if o.MaxScaleDownPercentage = v; o.MaxScaleDownPercentage == nil { o.nullFields = append(o.nullFields, "MaxScaleDownPercentage") } @@ -2792,6 +2793,13 @@ func (o *ScalingPolicy) SetIsEnabled(v *bool) *ScalingPolicy { return o } +func (o *ScalingPolicy) SetMaxCapacityPerScale(v *string) *ScalingPolicy { + if o.MaxCapacityPerScale = v; o.MaxCapacityPerScale == nil { + o.nullFields = append(o.nullFields, "MaxCapacityPerScale") + } + return o +} + // endregion // region Action diff --git a/vendor/github.com/spotinst/spotinst-sdk-go/service/ocean/providers/aws/launch_spec.go b/vendor/github.com/spotinst/spotinst-sdk-go/service/ocean/providers/aws/launch_spec.go index 3c3c78657a641..773a128d9bd5a 100644 --- a/vendor/github.com/spotinst/spotinst-sdk-go/service/ocean/providers/aws/launch_spec.go +++ b/vendor/github.com/spotinst/spotinst-sdk-go/service/ocean/providers/aws/launch_spec.go @@ -14,19 +14,22 @@ import ( ) type LaunchSpec struct { - ID *string `json:"id,omitempty"` - Name *string `json:"name,omitempty"` - OceanID *string `json:"oceanId,omitempty"` - ImageID *string `json:"imageId,omitempty"` - UserData *string `json:"userData,omitempty"` - RootVolumeSize *int `json:"rootVolumeSize,omitempty"` - SecurityGroupIDs []string `json:"securityGroupIds,omitempty"` - SubnetIDs []string `json:"subnetIds,omitempty"` - IAMInstanceProfile *IAMInstanceProfile `json:"iamInstanceProfile,omitempty"` - Labels []*Label `json:"labels,omitempty"` - Taints []*Taint `json:"taints,omitempty"` - AutoScale *AutoScale `json:"autoScale,omitempty"` - Tags []*Tag `json:"tags,omitempty"` + ID *string `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + OceanID *string `json:"oceanId,omitempty"` + ImageID *string `json:"imageId,omitempty"` + UserData *string `json:"userData,omitempty"` + RootVolumeSize *int `json:"rootVolumeSize,omitempty"` + SecurityGroupIDs []string `json:"securityGroupIds,omitempty"` + SubnetIDs []string `json:"subnetIds,omitempty"` + ResourceLimits *ResourceLimits `json:"resourceLimits,omitempty"` + IAMInstanceProfile *IAMInstanceProfile `json:"iamInstanceProfile,omitempty"` + AutoScale *AutoScale `json:"autoScale,omitempty"` + ElasticIPPool *ElasticIPPool `json:"elasticIpPool,omitempty"` + BlockDeviceMappings []*BlockDeviceMapping `json:"blockDeviceMappings,omitempty"` + Labels []*Label `json:"labels,omitempty"` + Taints []*Taint `json:"taints,omitempty"` + Tags []*Tag `json:"tags,omitempty"` // Read-only fields. CreatedAt *time.Time `json:"createdAt,omitempty"` @@ -49,6 +52,46 @@ type LaunchSpec struct { nullFields []string } +type ResourceLimits struct { + MaxInstanceCount *int `json:"maxInstanceCount,omitempty"` + + forceSendFields []string + nullFields []string +} + +type BlockDeviceMapping struct { + DeviceName *string `json:"deviceName,omitempty"` + NoDevice *string `json:"noDevice,omitempty"` + VirtualName *string `json:"virtualName,omitempty"` + EBS *EBS `json:"ebs,omitempty"` + + forceSendFields []string + nullFields []string +} + +type EBS struct { + DeleteOnTermination *bool `json:"deleteOnTermination,omitempty"` + Encrypted *bool `json:"encrypted,omitempty"` + KMSKeyID *string `json:"kmsKeyId,omitempty"` + SnapshotID *string `json:"snapshotId,omitempty"` + VolumeType *string `json:"volumeType,omitempty"` + IOPS *int `json:"iops,omitempty"` + VolumeSize *int `json:"volumeSize,omitempty"` + DynamicVolumeSize *DynamicVolumeSize `json:"dynamicVolumeSize,omitempty"` + + forceSendFields []string + nullFields []string +} + +type DynamicVolumeSize struct { + BaseSize *int `json:"baseSize,omitempty"` + SizePerResourceUnit *int `json:"sizePerResourceUnit,omitempty"` + Resource *string `json:"resource,omitempty"` + + forceSendFields []string + nullFields []string +} + type Label struct { Key *string `json:"key,omitempty"` Value *string `json:"value,omitempty"` @@ -83,6 +126,21 @@ type AutoScaleHeadroom struct { nullFields []string } +type ElasticIPPool struct { + TagSelector *TagSelector `json:"tagSelector,omitempty"` + + forceSendFields []string + nullFields []string +} + +type TagSelector struct { + Key *string `json:"tagKey,omitempty"` + Value *string `json:"tagValue,omitempty"` + + forceSendFields []string + nullFields []string +} + type ListLaunchSpecsInput struct { OceanID *string `json:"oceanId,omitempty"` } @@ -374,6 +432,186 @@ func (o *LaunchSpec) SetAutoScale(v *AutoScale) *LaunchSpec { return o } +func (o *LaunchSpec) SetElasticIPPool(v *ElasticIPPool) *LaunchSpec { + if o.ElasticIPPool = v; o.ElasticIPPool == nil { + o.nullFields = append(o.nullFields, "ElasticIPPool") + } + return o +} + +func (o *LaunchSpec) SetBlockDeviceMappings(v []*BlockDeviceMapping) *LaunchSpec { + if o.BlockDeviceMappings = v; o.BlockDeviceMappings == nil { + o.nullFields = append(o.nullFields, "BlockDeviceMappings") + } + return o +} + +func (o *LaunchSpec) SetTags(v []*Tag) *LaunchSpec { + if o.Tags = v; o.Tags == nil { + o.nullFields = append(o.nullFields, "Tags") + } + return o +} + +func (o *LaunchSpec) SetResourceLimits(v *ResourceLimits) *LaunchSpec { + if o.ResourceLimits = v; o.ResourceLimits == nil { + o.nullFields = append(o.nullFields, "ResourceLimits") + } + return o +} + +// endregion + +// region BlockDeviceMappings + +func (o BlockDeviceMapping) MarshalJSON() ([]byte, error) { + type noMethod BlockDeviceMapping + raw := noMethod(o) + return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields) +} + +func (o *BlockDeviceMapping) SetDeviceName(v *string) *BlockDeviceMapping { + if o.DeviceName = v; o.DeviceName == nil { + o.nullFields = append(o.nullFields, "DeviceName") + } + return o +} + +func (o *BlockDeviceMapping) SetNoDevice(v *string) *BlockDeviceMapping { + if o.NoDevice = v; o.NoDevice == nil { + o.nullFields = append(o.nullFields, "NoDevice") + } + return o +} + +func (o *BlockDeviceMapping) SetVirtualName(v *string) *BlockDeviceMapping { + if o.VirtualName = v; o.VirtualName == nil { + o.nullFields = append(o.nullFields, "VirtualName") + } + return o +} + +func (o *BlockDeviceMapping) SetEBS(v *EBS) *BlockDeviceMapping { + if o.EBS = v; o.EBS == nil { + o.nullFields = append(o.nullFields, "EBS") + } + return o +} + +// endregion + +// region EBS + +func (o EBS) MarshalJSON() ([]byte, error) { + type noMethod EBS + raw := noMethod(o) + return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields) +} + +func (o *EBS) SetEncrypted(v *bool) *EBS { + if o.Encrypted = v; o.Encrypted == nil { + o.nullFields = append(o.nullFields, "Encrypted") + } + return o +} + +func (o *EBS) SetIOPS(v *int) *EBS { + if o.IOPS = v; o.IOPS == nil { + o.nullFields = append(o.nullFields, "IOPS") + } + return o +} + +func (o *EBS) SetKMSKeyId(v *string) *EBS { + if o.KMSKeyID = v; o.KMSKeyID == nil { + o.nullFields = append(o.nullFields, "KMSKeyID") + } + return o +} + +func (o *EBS) SetSnapshotId(v *string) *EBS { + if o.SnapshotID = v; o.SnapshotID == nil { + o.nullFields = append(o.nullFields, "SnapshotID") + } + return o +} + +func (o *EBS) SetVolumeType(v *string) *EBS { + if o.VolumeType = v; o.VolumeType == nil { + o.nullFields = append(o.nullFields, "VolumeType") + } + return o +} + +func (o *EBS) SetDeleteOnTermination(v *bool) *EBS { + if o.DeleteOnTermination = v; o.DeleteOnTermination == nil { + o.nullFields = append(o.nullFields, "DeleteOnTermination") + } + return o +} + +func (o *EBS) SetVolumeSize(v *int) *EBS { + if o.VolumeSize = v; o.VolumeSize == nil { + o.nullFields = append(o.nullFields, "VolumeSize") + } + return o +} + +func (o *EBS) SetDynamicVolumeSize(v *DynamicVolumeSize) *EBS { + if o.DynamicVolumeSize = v; o.DynamicVolumeSize == nil { + o.nullFields = append(o.nullFields, "DynamicVolumeSize") + } + return o +} + +// end region + +// region Dynamic Volume Size + +func (o DynamicVolumeSize) MarshalJSON() ([]byte, error) { + type noMethod DynamicVolumeSize + raw := noMethod(o) + return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields) +} + +func (o *DynamicVolumeSize) SetBaseSize(v *int) *DynamicVolumeSize { + if o.BaseSize = v; o.BaseSize == nil { + o.nullFields = append(o.nullFields, "BaseSize") + } + return o +} + +func (o *DynamicVolumeSize) SetResource(v *string) *DynamicVolumeSize { + if o.Resource = v; o.Resource == nil { + o.nullFields = append(o.nullFields, "Resource") + } + return o +} + +func (o *DynamicVolumeSize) SetSizePerResourceUnit(v *int) *DynamicVolumeSize { + if o.SizePerResourceUnit = v; o.SizePerResourceUnit == nil { + o.nullFields = append(o.nullFields, "SizePerResourceUnit") + } + return o +} + +// end region + +// region ResourceLimits + +func (o ResourceLimits) MarshalJSON() ([]byte, error) { + type noMethod ResourceLimits + raw := noMethod(o) + return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields) +} + +func (o *ResourceLimits) SetMaxInstanceCount(v *int) *ResourceLimits { + if o.MaxInstanceCount = v; o.MaxInstanceCount == nil { + o.nullFields = append(o.nullFields, "MaxInstanceCount") + } + return o +} + // endregion // region Label @@ -484,9 +722,43 @@ func (o *AutoScaleHeadroom) SetNumOfUnits(v *int) *AutoScaleHeadroom { return o } -func (o *LaunchSpec) SetTags(v []*Tag) *LaunchSpec { - if o.Tags = v; o.Tags == nil { - o.nullFields = append(o.nullFields, "Tags") +// endregion + +// region ElasticIPPool + +func (o ElasticIPPool) MarshalJSON() ([]byte, error) { + type noMethod ElasticIPPool + raw := noMethod(o) + return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields) +} + +func (o *ElasticIPPool) SetTagSelector(v *TagSelector) *ElasticIPPool { + if o.TagSelector = v; o.TagSelector == nil { + o.nullFields = append(o.nullFields, "TagSelector") + } + return o +} + +// endregion + +// region TagSelector + +func (o TagSelector) MarshalJSON() ([]byte, error) { + type noMethod TagSelector + raw := noMethod(o) + return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields) +} + +func (o *TagSelector) SetTagKey(v *string) *TagSelector { + if o.Key = v; o.Key == nil { + o.nullFields = append(o.nullFields, "Key") + } + return o +} + +func (o *TagSelector) SetTagValue(v *string) *TagSelector { + if o.Value = v; o.Value == nil { + o.nullFields = append(o.nullFields, "Value") } return o } diff --git a/vendor/github.com/spotinst/spotinst-sdk-go/service/ocean/providers/aws/ocean.go b/vendor/github.com/spotinst/spotinst-sdk-go/service/ocean/providers/aws/ocean.go index bf8db27370a2b..3117fd447aedb 100644 --- a/vendor/github.com/spotinst/spotinst-sdk-go/service/ocean/providers/aws/ocean.go +++ b/vendor/github.com/spotinst/spotinst-sdk-go/service/ocean/providers/aws/ocean.go @@ -173,8 +173,8 @@ type AutoScalerResourceLimits struct { } type AutoScalerDown struct { - EvaluationPeriods *int `json:"evaluationPeriods,omitempty"` - MaxScaleDownPercentage *int `json:"maxScaleDownPercentage,omitempty"` + EvaluationPeriods *int `json:"evaluationPeriods,omitempty"` + MaxScaleDownPercentage *float64 `json:"maxScaleDownPercentage,omitempty"` forceSendFields []string nullFields []string @@ -216,19 +216,30 @@ type DeleteClusterInput struct { type DeleteClusterOutput struct{} +// Deprecated: Use CreateRollInput instead. type RollClusterInput struct { Roll *Roll `json:"roll,omitempty"` } +// Deprecated: Use CreateRollOutput instead. type RollClusterOutput struct { RollClusterStatus *RollClusterStatus `json:"clusterDeploymentStatus,omitempty"` } +// Deprecated: Use RollSpec instead. type Roll struct { - ClusterID *string `json:"clusterId,omitempty"` - BatchSizePercentage *int `json:"batchSizePercentage,omitempty"` + ClusterID *string `json:"clusterId,omitempty"` + Comment *string `json:"comment,omitempty"` + BatchSizePercentage *int `json:"batchSizePercentage,omitempty"` + DisableLaunchSpecAutoscaling *bool `json:"disableLaunchSpecAutoscaling,omitempty"` + LaunchSpecIDs []string `json:"launchSpecIds,omitempty"` + InstanceIDs []string `json:"instanceIds,omitempty"` + + forceSendFields []string + nullFields []string } +// Deprecated: Use RollStatus instead. type RollClusterStatus struct { OceanID *string `json:"oceanId,omitempty"` RollID *string `json:"id,omitempty"` @@ -240,11 +251,71 @@ type RollClusterStatus struct { UpdatedAt *string `json:"updatedAt,omitempty"` } +type RollSpec struct { + ID *string `json:"id,omitempty"` + ClusterID *string `json:"clusterId,omitempty"` + Comment *string `json:"comment,omitempty"` + BatchSizePercentage *int `json:"batchSizePercentage,omitempty"` + DisableLaunchSpecAutoScaling *bool `json:"disableLaunchSpecAutoScaling,omitempty"` + LaunchSpecIDs []string `json:"launchSpecIds,omitempty"` + InstanceIDs []string `json:"instanceIds,omitempty"` + + forceSendFields []string + nullFields []string +} + +type RollStatus struct { + ID *string `json:"id,omitempty"` + ClusterID *string `json:"oceanId,omitempty"` + Comment *string `json:"comment,omitempty"` + Status *string `json:"status,omitempty"` + Progress *Progress `json:"progress,omitempty"` + CurrentBatch *int `json:"currentBatch,omitempty"` + NumOfBatches *int `json:"numOfBatches,omitempty"` + LaunchSpecIDs []string `json:"launchSpecIds,omitempty"` + InstanceIDs []string `json:"instanceIds,omitempty"` + CreatedAt *string `json:"createdAt,omitempty"` + UpdatedAt *string `json:"updatedAt,omitempty"` +} + type Progress struct { Unit *string `json:"unit,omitempty"` Value *int `json:"value,omitempty"` } +type ListRollsInput struct { + ClusterID *string `json:"clusterId,omitempty"` +} + +type ListRollsOutput struct { + Rolls []*RollStatus `json:"rolls,omitempty"` +} + +type CreateRollInput struct { + Roll *RollSpec `json:"roll,omitempty"` +} + +type CreateRollOutput struct { + Roll *RollStatus `json:"roll,omitempty"` +} + +type ReadRollInput struct { + RollID *string `json:"rollId,omitempty"` + ClusterID *string `json:"clusterId,omitempty"` +} + +type ReadRollOutput struct { + Roll *RollStatus `json:"roll,omitempty"` +} + +type UpdateRollInput struct { + Roll *RollSpec `json:"roll,omitempty"` +} + +type UpdateRollOutput struct { + Roll *RollStatus `json:"roll,omitempty"` +} + func clusterFromJSON(in []byte) (*Cluster, error) { b := new(Cluster) if err := json.Unmarshal(in, b); err != nil { @@ -280,7 +351,7 @@ func clustersFromHttpResponse(resp *http.Response) ([]*Cluster, error) { return clustersFromJSON(body) } -func rollStatusFromJSON(in []byte) (*RollClusterStatus, error) { +func rollClusterStatusFromJSON(in []byte) (*RollClusterStatus, error) { b := new(RollClusterStatus) if err := json.Unmarshal(in, b); err != nil { return nil, err @@ -288,7 +359,7 @@ func rollStatusFromJSON(in []byte) (*RollClusterStatus, error) { return b, nil } -func rollStatusesFromJSON(in []byte) ([]*RollClusterStatus, error) { +func rollClusterStatusesFromJSON(in []byte) ([]*RollClusterStatus, error) { var rw client.Response if err := json.Unmarshal(in, &rw); err != nil { return nil, err @@ -297,6 +368,41 @@ func rollStatusesFromJSON(in []byte) ([]*RollClusterStatus, error) { if len(out) == 0 { return out, nil } + for i, rb := range rw.Response.Items { + b, err := rollClusterStatusFromJSON(rb) + if err != nil { + return nil, err + } + out[i] = b + } + return out, nil +} + +func rollClusterStatusesFromHttpResponse(resp *http.Response) ([]*RollClusterStatus, error) { + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, err + } + return rollClusterStatusesFromJSON(body) +} + +func rollStatusFromJSON(in []byte) (*RollStatus, error) { + b := new(RollStatus) + if err := json.Unmarshal(in, b); err != nil { + return nil, err + } + return b, nil +} + +func rollStatusesFromJSON(in []byte) ([]*RollStatus, error) { + var rw client.Response + if err := json.Unmarshal(in, &rw); err != nil { + return nil, err + } + out := make([]*RollStatus, len(rw.Response.Items)) + if len(out) == 0 { + return out, nil + } for i, rb := range rw.Response.Items { b, err := rollStatusFromJSON(rb) if err != nil { @@ -307,7 +413,7 @@ func rollStatusesFromJSON(in []byte) ([]*RollClusterStatus, error) { return out, nil } -func rollStatusesFromHttpResponse(resp *http.Response) ([]*RollClusterStatus, error) { +func rollStatusesFromHttpResponse(resp *http.Response) ([]*RollStatus, error) { body, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, err @@ -434,6 +540,130 @@ func (s *ServiceOp) DeleteCluster(ctx context.Context, input *DeleteClusterInput return &DeleteClusterOutput{}, nil } +func (s *ServiceOp) ListRolls(ctx context.Context, input *ListRollsInput) (*ListRollsOutput, error) { + path, err := uritemplates.Expand("/ocean/aws/k8s/cluster/{clusterId}/roll", uritemplates.Values{ + "clusterId": spotinst.StringValue(input.ClusterID), + }) + if err != nil { + return nil, err + } + + r := client.NewRequest(http.MethodGet, path) + resp, err := client.RequireOK(s.Client.Do(ctx, r)) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + v, err := rollStatusesFromHttpResponse(resp) + if err != nil { + return nil, err + } + + output := new(ListRollsOutput) + if len(v) > 0 { + output.Rolls = v + } + + return output, nil +} + +func (s *ServiceOp) CreateRoll(ctx context.Context, input *CreateRollInput) (*CreateRollOutput, error) { + path, err := uritemplates.Expand("/ocean/aws/k8s/cluster/{clusterId}/roll", uritemplates.Values{ + "clusterId": spotinst.StringValue(input.Roll.ClusterID), + }) + if err != nil { + return nil, err + } + + // We do not need the ID anymore so let's drop it. + input.Roll.ClusterID = nil + + r := client.NewRequest(http.MethodPost, path) + r.Obj = input + + resp, err := client.RequireOK(s.Client.Do(ctx, r)) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + v, err := rollStatusesFromHttpResponse(resp) + if err != nil { + return nil, err + } + + output := new(CreateRollOutput) + if len(v) > 0 { + output.Roll = v[0] + } + + return output, nil +} + +func (s *ServiceOp) ReadRoll(ctx context.Context, input *ReadRollInput) (*ReadRollOutput, error) { + path, err := uritemplates.Expand("/ocean/aws/k8s/cluster/{clusterId}/roll/{rollId}", uritemplates.Values{ + "clusterId": spotinst.StringValue(input.ClusterID), + "rollId": spotinst.StringValue(input.RollID), + }) + if err != nil { + return nil, err + } + + r := client.NewRequest(http.MethodGet, path) + resp, err := client.RequireOK(s.Client.Do(ctx, r)) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + v, err := rollStatusesFromHttpResponse(resp) + if err != nil { + return nil, err + } + + output := new(ReadRollOutput) + if len(v) > 0 { + output.Roll = v[0] + } + + return output, nil +} + +func (s *ServiceOp) UpdateRoll(ctx context.Context, input *UpdateRollInput) (*UpdateRollOutput, error) { + path, err := uritemplates.Expand("/ocean/aws/k8s/cluster/{clusterId}/roll/{rollId}", uritemplates.Values{ + "clusterId": spotinst.StringValue(input.Roll.ClusterID), + }) + if err != nil { + return nil, err + } + + // We do not need the ID anymore so let's drop it. + input.Roll.ClusterID = nil + + r := client.NewRequest(http.MethodPut, path) + r.Obj = input + + resp, err := client.RequireOK(s.Client.Do(ctx, r)) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + v, err := rollStatusesFromHttpResponse(resp) + if err != nil { + return nil, err + } + + output := new(UpdateRollOutput) + if len(v) > 0 { + output.Roll = v[0] + } + + return output, nil +} + +// Deprecated: Use CreateRoll instead. func (s *ServiceOp) Roll(ctx context.Context, input *RollClusterInput) (*RollClusterOutput, error) { path, err := uritemplates.Expand("/ocean/aws/k8s/cluster/{clusterId}/roll", uritemplates.Values{ "clusterId": spotinst.StringValue(input.Roll.ClusterID), @@ -454,7 +684,7 @@ func (s *ServiceOp) Roll(ctx context.Context, input *RollClusterInput) (*RollClu } defer resp.Body.Close() - rs, err := rollStatusesFromHttpResponse(resp) + rs, err := rollClusterStatusesFromHttpResponse(resp) if err != nil { return nil, err } @@ -1022,7 +1252,7 @@ func (o *AutoScalerDown) SetEvaluationPeriods(v *int) *AutoScalerDown { return o } -func (o *AutoScalerDown) SetMaxScaleDownPercentage(v *int) *AutoScalerDown { +func (o *AutoScalerDown) SetMaxScaleDownPercentage(v *float64) *AutoScalerDown { if o.MaxScaleDownPercentage = v; o.MaxScaleDownPercentage == nil { o.nullFields = append(o.nullFields, "MaxScaleDownPercentage") } @@ -1030,3 +1260,48 @@ func (o *AutoScalerDown) SetMaxScaleDownPercentage(v *int) *AutoScalerDown { } // endregion + +// region Roll + +func (o Roll) MarshalJSON() ([]byte, error) { + type noMethod Roll + raw := noMethod(o) + return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields) +} + +func (o *Roll) SetComment(v *string) *Roll { + if o.Comment = v; o.Comment == nil { + o.nullFields = append(o.nullFields, "Comment") + } + return o +} + +func (o *Roll) SetBatchSizePercentage(v *int) *Roll { + if o.BatchSizePercentage = v; o.BatchSizePercentage == nil { + o.nullFields = append(o.nullFields, "BatchSizePercentage") + } + return o +} + +func (o *Roll) SetDisableLaunchSpecAutoscaling(v *bool) *Roll { + if o.DisableLaunchSpecAutoscaling = v; o.DisableLaunchSpecAutoscaling == nil { + o.nullFields = append(o.nullFields, "DisableLaunchSpecAutoscaling") + } + return o +} + +func (o *Roll) SetLaunchSpecIDs(v []string) *Roll { + if o.LaunchSpecIDs = v; o.LaunchSpecIDs == nil { + o.nullFields = append(o.nullFields, "LaunchSpecIDs") + } + return o +} + +func (o *Roll) SetInstanceIDs(v []string) *Roll { + if o.InstanceIDs = v; o.InstanceIDs == nil { + o.nullFields = append(o.nullFields, "InstanceIDs") + } + return o +} + +// endregion diff --git a/vendor/github.com/spotinst/spotinst-sdk-go/service/ocean/providers/aws/ocean_ecs.go b/vendor/github.com/spotinst/spotinst-sdk-go/service/ocean/providers/aws/ocean_ecs.go index 766d002a47b95..787bbfd371de2 100644 --- a/vendor/github.com/spotinst/spotinst-sdk-go/service/ocean/providers/aws/ocean_ecs.go +++ b/vendor/github.com/spotinst/spotinst-sdk-go/service/ocean/providers/aws/ocean_ecs.go @@ -156,7 +156,7 @@ type ECSAutoScalerResourceLimits struct { } type ECSAutoScalerDown struct { - MaxScaleDownPercentage *int `json:"maxScaleDownPercentage,omitempty"` + MaxScaleDownPercentage *float64 `json:"maxScaleDownPercentage,omitempty"` forceSendFields []string nullFields []string @@ -207,8 +207,14 @@ type ECSRollClusterOutput struct { } type ECSRoll struct { - ClusterID *string `json:"clusterId,omitempty"` - BatchSizePercentage *int `json:"batchSizePercentage,omitempty"` + ClusterID *string `json:"clusterId,omitempty"` + Comment *string `json:"comment,omitempty"` + BatchSizePercentage *int `json:"batchSizePercentage,omitempty"` + LaunchSpecIDs []string `json:"launchSpecIds,omitempty"` + InstanceIDs []string `json:"instanceIds,omitempty"` + + forceSendFields []string + nullFields []string } type ECSRollClusterStatus struct { @@ -912,7 +918,7 @@ func (o ECSAutoScalerDown) MarshalJSON() ([]byte, error) { return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields) } -func (o *ECSAutoScalerDown) SetMaxScaleDownPercentage(v *int) *ECSAutoScalerDown { +func (o *ECSAutoScalerDown) SetMaxScaleDownPercentage(v *float64) *ECSAutoScalerDown { if o.MaxScaleDownPercentage = v; o.MaxScaleDownPercentage == nil { o.nullFields = append(o.nullFields, "MaxScaleDownPercentage") } @@ -920,3 +926,41 @@ func (o *ECSAutoScalerDown) SetMaxScaleDownPercentage(v *int) *ECSAutoScalerDown } // endregion + +// region ECSRoll + +func (o ECSRoll) MarshalJSON() ([]byte, error) { + type noMethod ECSRoll + raw := noMethod(o) + return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields) +} + +func (o *ECSRoll) SetComment(v *string) *ECSRoll { + if o.Comment = v; o.Comment == nil { + o.nullFields = append(o.nullFields, "Comment") + } + return o +} + +func (o *ECSRoll) SetBatchSizePercentage(v *int) *ECSRoll { + if o.BatchSizePercentage = v; o.BatchSizePercentage == nil { + o.nullFields = append(o.nullFields, "BatchSizePercentage") + } + return o +} + +func (o *ECSRoll) SetLaunchSpecIDs(v []string) *ECSRoll { + if o.LaunchSpecIDs = v; o.LaunchSpecIDs == nil { + o.nullFields = append(o.nullFields, "LaunchSpecIDs") + } + return o +} + +func (o *ECSRoll) SetInstanceIDs(v []string) *ECSRoll { + if o.InstanceIDs = v; o.InstanceIDs == nil { + o.nullFields = append(o.nullFields, "InstanceIDs") + } + return o +} + +// endregion diff --git a/vendor/github.com/spotinst/spotinst-sdk-go/service/ocean/providers/aws/service.go b/vendor/github.com/spotinst/spotinst-sdk-go/service/ocean/providers/aws/service.go index a42d4cbd152e8..79c675fda0a88 100644 --- a/vendor/github.com/spotinst/spotinst-sdk-go/service/ocean/providers/aws/service.go +++ b/vendor/github.com/spotinst/spotinst-sdk-go/service/ocean/providers/aws/service.go @@ -12,6 +12,13 @@ import ( // of the Spotinst API. See this package's package overview docs for details on // the service. type Service interface { + serviceKubernetes + serviceECS + + ListResourceSuggestions(context.Context, *ListResourceSuggestionsInput) (*ListResourceSuggestionsOutput, error) +} + +type serviceKubernetes interface { ListClusters(context.Context, *ListClustersInput) (*ListClustersOutput, error) CreateCluster(context.Context, *CreateClusterInput) (*CreateClusterOutput, error) ReadCluster(context.Context, *ReadClusterInput) (*ReadClusterOutput, error) @@ -27,7 +34,17 @@ type Service interface { ListClusterInstances(context.Context, *ListClusterInstancesInput) (*ListClusterInstancesOutput, error) DetachClusterInstances(context.Context, *DetachClusterInstancesInput) (*DetachClusterInstancesOutput, error) + ListRolls(context.Context, *ListRollsInput) (*ListRollsOutput, error) + CreateRoll(context.Context, *CreateRollInput) (*CreateRollOutput, error) + ReadRoll(context.Context, *ReadRollInput) (*ReadRollOutput, error) + UpdateRoll(context.Context, *UpdateRollInput) (*UpdateRollOutput, error) + + // Deprecated: Roll is obsolete, exists for backward compatibility only, + // and should not be used. Please use CreateRoll instead. Roll(context.Context, *RollClusterInput) (*RollClusterOutput, error) +} + +type serviceECS interface { ListECSClusters(context.Context, *ListECSClustersInput) (*ListECSClustersOutput, error) CreateECSCluster(context.Context, *CreateECSClusterInput) (*CreateECSClusterOutput, error) ReadECSCluster(context.Context, *ReadECSClusterInput) (*ReadECSClusterOutput, error) @@ -41,8 +58,6 @@ type Service interface { DeleteECSLaunchSpec(context.Context, *DeleteECSLaunchSpecInput) (*DeleteECSLaunchSpecOutput, error) RollECS(context.Context, *ECSRollClusterInput) (*ECSRollClusterOutput, error) - - ListResourceSuggestions(context.Context, *ListResourceSuggestionsInput) (*ListResourceSuggestionsOutput, error) } type ServiceOp struct { diff --git a/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/config.go b/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/config.go index 99a4f1cce9a0b..7639fe3c3a072 100644 --- a/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/config.go +++ b/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/config.go @@ -154,11 +154,11 @@ func (c *Config) WithLogger(logger log.Logger) *Config { // Merge merges the passed in configs into the existing config object. func (c *Config) Merge(cfgs ...*Config) { for _, cfg := range cfgs { - mergeConfig(c, cfg) + mergeConfigs(c, cfg) } } -func mergeConfig(c1, c2 *Config) { +func mergeConfigs(c1, c2 *Config) { if c2 == nil { return } diff --git a/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/credentials/BUILD.bazel b/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/credentials/BUILD.bazel index 322d66876017d..c39ec79d1bbf6 100644 --- a/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/credentials/BUILD.bazel +++ b/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/credentials/BUILD.bazel @@ -13,5 +13,8 @@ go_library( importmap = "k8s.io/kops/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/credentials", importpath = "github.com/spotinst/spotinst-sdk-go/spotinst/credentials", visibility = ["//visibility:public"], - deps = ["//vendor/github.com/go-ini/ini:go_default_library"], + deps = [ + "//vendor/github.com/go-ini/ini:go_default_library", + "//vendor/github.com/spotinst/spotinst-sdk-go/spotinst/featureflag:go_default_library", + ], ) diff --git a/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/credentials/credentials.go b/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/credentials/credentials.go index 52063806e6a15..fcea42bd9e4b0 100644 --- a/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/credentials/credentials.go +++ b/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/credentials/credentials.go @@ -1,9 +1,13 @@ package credentials import ( + "errors" "sync" ) +// ErrNoValidTokenFound is returned when there is no valid token. +var ErrNoValidTokenFound = errors.New("spotinst: no valid token found") + // A Credentials provides synchronous safe retrieval of Spotinst credentials. // Credentials will cache the credentials value. // @@ -43,6 +47,9 @@ func (c *Credentials) Get() (Value, error) { if err != nil { return Value{}, err } + if creds.Token == "" { + return Value{ProviderName: creds.ProviderName}, ErrNoValidTokenFound + } c.creds = creds c.forceRefresh = false } diff --git a/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/credentials/provider.go b/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/credentials/provider.go index e47bd939c0d2e..1468ff3fd85c3 100644 --- a/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/credentials/provider.go +++ b/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/credentials/provider.go @@ -5,13 +5,13 @@ import "fmt" // A Value is the Spotinst credentials value for individual credential fields. type Value struct { // Spotinst API token. - Token string `json:"token"` + Token string `ini:"token" json:"token"` // Spotinst account ID. - Account string `json:"account"` + Account string `ini:"account" json:"account"` // Provider used to get credentials. - ProviderName string `json:"-"` + ProviderName string `ini:"-" json:"-"` } // A Provider is the interface for any component which will provide credentials @@ -26,3 +26,19 @@ type Provider interface { // returned if the value were not obtainable, or empty. Retrieve() (Value, error) } + +// IsEmpty if all fields of a Value are empty. +func (v *Value) IsEmpty() bool { return v.Token == "" && v.Account == "" } + +// IsComplete if all fields of a Value are set. +func (v *Value) IsComplete() bool { return v.Token != "" && v.Account != "" } + +// Merge merges the passed in Value into the existing Value object. +func (v *Value) Merge(v2 Value) { + if v.Token == "" { + v.Token = v2.Token + } + if v.Account == "" { + v.Account = v2.Account + } +} diff --git a/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/credentials/provider_chain.go b/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/credentials/provider_chain.go index 682a83b2b25fe..32b568048838c 100644 --- a/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/credentials/provider_chain.go +++ b/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/credentials/provider_chain.go @@ -3,14 +3,16 @@ package credentials import ( "errors" "fmt" + + "github.com/spotinst/spotinst-sdk-go/spotinst/featureflag" ) -// ErrNoValidProvidersFoundInChain Is returned when there are no valid credentials +// ErrNoValidProvidersFoundInChain is returned when there are no valid credentials // providers in the ChainProvider. -var ErrNoValidProvidersFoundInChain = errors.New("spotinst: no valid credentials providers in chain") +var ErrNoValidProvidersFoundInChain = errors.New("spotinst: no valid " + + "credentials providers in chain") -// A ChainProvider will search for a provider which returns credentials and cache -// that provider until Retrieve is called again. +// A ChainProvider will search for a provider which returns credentials. // // The ChainProvider provides a way of chaining multiple providers together which // will pick the first available using priority order of the Providers in the list. @@ -34,7 +36,6 @@ var ErrNoValidProvidersFoundInChain = errors.New("spotinst: no valid credentials // ) type ChainProvider struct { Providers []Provider - active Provider } // NewChainCredentials returns a pointer to a new Credentials object @@ -46,27 +47,41 @@ func NewChainCredentials(providers ...Provider) *Credentials { } // Retrieve returns the credentials value or error if no provider returned -// without error. If a provider is found it will be cached. +// without error. func (c *ChainProvider) Retrieve() (Value, error) { + var value Value var errs errorList + for _, p := range c.Providers { - value, err := p.Retrieve() + v, err := p.Retrieve() if err == nil { - c.active = p - return value, nil + if featureflag.MergeCredentialsChain.Enabled() { + value.Merge(v) + if value.IsComplete() { + return value, nil + } + } else { + value = v + break + } + } else { + errs = append(errs, err) } - errs = append(errs, err) } - c.active = nil - err := ErrNoValidProvidersFoundInChain - if len(errs) > 0 { - err = errs + if value.Token == "" { + err := ErrNoValidProvidersFoundInChain + if len(errs) > 0 { + err = errs + } + + return Value{ProviderName: c.String()}, err } - return Value{}, err + return value, nil } +// String returns the string representation of the provider. func (c *ChainProvider) String() string { var out string for i, provider := range c.Providers { diff --git a/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/credentials/provider_env.go b/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/credentials/provider_env.go index 0067efd17b644..92b1088ee0528 100644 --- a/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/credentials/provider_env.go +++ b/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/credentials/provider_env.go @@ -6,7 +6,7 @@ import ( ) const ( - // EnvCredentialsProviderName provides a name of Env provider. + // EnvCredentialsProviderName specifies the name of the Env provider. EnvCredentialsProviderName = "EnvCredentialsProvider" // EnvCredentialsVarToken specifies the name of the environment variable @@ -18,9 +18,10 @@ const ( EnvCredentialsVarAccount = "SPOTINST_ACCOUNT" ) -// ErrEnvCredentialsTokenNotFound is returned when the Spotinst Token can't be -// found in the process's environment. -var ErrEnvCredentialsTokenNotFound = fmt.Errorf("spotinst: %s not found in environment", EnvCredentialsVarToken) +// ErrEnvCredentialsNotFound is returned when no credentials can be found in the +// process's environment. +var ErrEnvCredentialsNotFound = fmt.Errorf("spotinst: %s and %s not found "+ + "in environment", EnvCredentialsVarToken, EnvCredentialsVarAccount) // A EnvProvider retrieves credentials from the environment variables of the // running process. @@ -38,21 +39,18 @@ func NewEnvCredentials() *Credentials { // Retrieve retrieves the keys from the environment. func (e *EnvProvider) Retrieve() (Value, error) { - token := os.Getenv(EnvCredentialsVarToken) - if token == "" { - return Value{ProviderName: EnvCredentialsProviderName}, - ErrEnvCredentialsTokenNotFound - } - value := Value{ - Token: token, + Token: os.Getenv(EnvCredentialsVarToken), Account: os.Getenv(EnvCredentialsVarAccount), ProviderName: EnvCredentialsProviderName, } + if value.IsEmpty() { + return value, ErrEnvCredentialsNotFound + } + return value, nil } -func (e *EnvProvider) String() string { - return EnvCredentialsProviderName -} +// String returns the string representation of the provider. +func (e *EnvProvider) String() string { return EnvCredentialsProviderName } diff --git a/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/credentials/provider_file.go b/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/credentials/provider_file.go index b98bc019343d4..f6f8066b5a8de 100644 --- a/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/credentials/provider_file.go +++ b/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/credentials/provider_file.go @@ -12,7 +12,7 @@ import ( ) const ( - // FileCredentialsProviderName provides a name of File provider. + // FileCredentialsProviderName specifies the name of the File provider. FileCredentialsProviderName = "FileCredentialsProvider" // FileCredentialsEnvVarFile specifies the name of the environment variable @@ -25,13 +25,13 @@ const ( ) var ( - // ErrFileCredentialsLoadFailed is emitted when the provider is unable to load + // ErrFileCredentialsLoadFailed is returned when the provider is unable to load // credentials from the credentials file. ErrFileCredentialsLoadFailed = errors.New("spotinst: failed to load credentials file") - // ErrFileCredentialsTokenNotFound is emitted when the loaded credentials - // do not contain a valid token. - ErrFileCredentialsTokenNotFound = errors.New("spotinst: credentials do not contain token") + // ErrFileCredentialsNotFound is returned when the loaded credentials + // are empty. + ErrFileCredentialsNotFound = errors.New("spotinst: credentials file or profile is empty") ) // DefaultProfile returns the SDK's default profile name to use when loading @@ -93,11 +93,10 @@ func (p *FileProvider) Retrieve() (Value, error) { return value, nil } -func (p *FileProvider) String() string { - return FileCredentialsProviderName -} +// String returns the string representation of the provider. +func (p *FileProvider) String() string { return FileCredentialsProviderName } -// profile returns the profile to use to read Spotinst credentials. +// profile returns the profile to use to read the user credentials. func (p *FileProvider) profile() string { if p.Profile == "" { if p.Profile = os.Getenv(FileCredentialsEnvVarProfile); p.Profile != "" { @@ -110,7 +109,7 @@ func (p *FileProvider) profile() string { return p.Profile } -// filename returns the filename to use to read Spotinst credentials. +// filename returns the filename to use to read the user credentials. func (p *FileProvider) filename() string { if p.Filename == "" { if p.Filename = os.Getenv(FileCredentialsEnvVarFile); p.Filename != "" { @@ -136,8 +135,8 @@ func (p *FileProvider) loadCredentials(profile, filename string) (Value, error) } } - if len(value.Token) == 0 { - return value, ErrFileCredentialsTokenNotFound + if value.IsEmpty() { + return value, ErrFileCredentialsNotFound } return value, nil @@ -151,13 +150,33 @@ func (p *FileProvider) loadCredentialsINI(profile, filename string) (Value, erro return value, err } + value, err = getCredentialsFromINIProfile(profile, config) + if err != nil { + return value, err + } + + // Try to complete missing fields with default profile. + if profile != DefaultProfile() && !value.IsComplete() { + defaultValue, err := getCredentialsFromINIProfile(DefaultProfile(), config) + if err == nil { + value.Merge(defaultValue) + } + } + + return value, nil +} + +func getCredentialsFromINIProfile(profile string, config *ini.File) (Value, error) { + var value Value + section, err := config.GetSection(profile) if err != nil { return value, err } - value.Token = section.Key("token").String() - value.Account = section.Key("account").String() + if err := section.StrictMapTo(&value); err != nil { + return value, err + } return value, nil } diff --git a/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/credentials/provider_static.go b/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/credentials/provider_static.go index 17ad05d18f0d6..2ed6b3db85725 100644 --- a/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/credentials/provider_static.go +++ b/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/credentials/provider_static.go @@ -4,10 +4,10 @@ import ( "errors" ) -// StaticCredentialsProviderName provides a name of Static provider. +// StaticCredentialsProviderName specifies the name of the Static provider. const StaticCredentialsProviderName = "StaticCredentialsProvider" -// ErrStaticCredentialsEmpty is emitted when static credentials are empty. +// ErrStaticCredentialsEmpty is returned when static credentials are empty. var ErrStaticCredentialsEmpty = errors.New("spotinst: static credentials are empty") // A StaticProvider is a set of credentials which are set programmatically. @@ -19,25 +19,20 @@ type StaticProvider struct { // a static credentials value provider. func NewStaticCredentials(token, account string) *Credentials { return NewCredentials(&StaticProvider{Value: Value{ - Token: token, - Account: account, + ProviderName: StaticCredentialsProviderName, + Token: token, + Account: account, }}) } // Retrieve returns the credentials or error if the credentials are invalid. func (s *StaticProvider) Retrieve() (Value, error) { - if s.Token == "" { - return Value{ProviderName: StaticCredentialsProviderName}, - ErrStaticCredentialsEmpty - } - - if len(s.Value.ProviderName) == 0 { - s.Value.ProviderName = StaticCredentialsProviderName + if s.IsEmpty() { + return s.Value, ErrStaticCredentialsEmpty } return s.Value, nil } -func (s *StaticProvider) String() string { - return StaticCredentialsProviderName -} +// String returns the string representation of the provider. +func (s *StaticProvider) String() string { return StaticCredentialsProviderName } diff --git a/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/featureflag/BUILD.bazel b/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/featureflag/BUILD.bazel new file mode 100644 index 0000000000000..eb281cc529ffc --- /dev/null +++ b/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/featureflag/BUILD.bazel @@ -0,0 +1,12 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "featureflag.go", + "features.go", + ], + importmap = "k8s.io/kops/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/featureflag", + importpath = "github.com/spotinst/spotinst-sdk-go/spotinst/featureflag", + visibility = ["//visibility:public"], +) diff --git a/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/featureflag/featureflag.go b/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/featureflag/featureflag.go new file mode 100644 index 0000000000000..c065c35fd6704 --- /dev/null +++ b/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/featureflag/featureflag.go @@ -0,0 +1,119 @@ +package featureflag + +import ( + "fmt" + "strconv" + "strings" + "sync" +) + +// All registered feature flags. +var ( + flagsMutex sync.Mutex + flags = make(map[string]FeatureFlag) +) + +// FeatureFlag indicates whether a given feature is enabled or not. +type FeatureFlag interface { + fmt.Stringer + + // Name returns the name of the feature flag. + Name() string + + // Enabled returns true if the feature is enabled. + Enabled() bool +} + +// featureFlag represents a feature being gated. +type featureFlag struct { + name string + enabled bool +} + +// New returns a new feature flag. +func New(name string, enabled bool) FeatureFlag { + flagsMutex.Lock() + defer flagsMutex.Unlock() + + ff, ok := flags[name] + if !ok { + ff = &featureFlag{name: name} + flags[name] = ff + } + + ff.(*featureFlag).enabled = enabled + return ff +} + +// Name returns the name of the feature flag. +func (f *featureFlag) Name() string { return f.name } + +// Enabled returns true if the feature is enabled. +func (f *featureFlag) Enabled() bool { return f.enabled } + +// String returns the string representation of the feature flag. +func (f *featureFlag) String() string { return fmt.Sprintf("%s=%t", f.name, f.enabled) } + +// Set parses and stores features from a string like "feature1=true,feature2=false". +func Set(features string) { + for _, s := range strings.Split(strings.TrimSpace(features), ",") { + if len(s) == 0 { + continue + } + + segments := strings.SplitN(s, "=", 2) + name := strings.TrimSpace(segments[0]) + + enabled := true + if len(segments) > 1 { + value := strings.TrimSpace(segments[1]) + enabled, _ = strconv.ParseBool(value) // ignore errors and fallback to `false` + } + + New(name, enabled) + } +} + +// Get returns a specific feature flag by name. +func Get(name string) FeatureFlag { + flagsMutex.Lock() + defer flagsMutex.Unlock() + + f, ok := flags[name] + if !ok { + f = new(featureFlag) + } + + return &featureFlag{ + name: name, + enabled: f.Enabled(), + } +} + +// All returns a list of all known feature flags. +func All() FeatureFlags { + flagsMutex.Lock() + defer flagsMutex.Unlock() + + features := make(FeatureFlags, 0, len(flags)) + for name, flag := range flags { + features = append(features, &featureFlag{ + name: name, + enabled: flag.Enabled(), + }) + } + + return features +} + +// FeatureFlags defines a list of feature flags. +type FeatureFlags []FeatureFlag + +// String returns the string representation of a list of feature flags. +func (f FeatureFlags) String() string { + features := make([]string, len(f)) + for i, ff := range f { + features[i] = ff.String() + } + return strings.Join(features, ",") +} diff --git a/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/featureflag/features.go b/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/featureflag/features.go new file mode 100644 index 0000000000000..04a5e132ff67e --- /dev/null +++ b/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/featureflag/features.go @@ -0,0 +1,24 @@ +package featureflag + +import "os" + +// Default features. +var ( + // Toggle the usage of merging credentials in chain provider. + // + // This feature allows users to configure their credentials using multiple + // providers. For example, a token can be statically configured using a file, + // while the account can be dynamically configured via environment variables. + MergeCredentialsChain = New("MergeCredentialsChain", false) +) + +// EnvVar is the name of the environment variable to read feature flags from. +// The value should be a comma-separated list of K=V flags, while V is optional. +const EnvVar = "SPOTINST_FEATURE_FLAGS" + +// setFromEnv reads an environment variable and sets features from its value. +func setFromEnv() { Set(os.Getenv(EnvVar)) } + +func init() { + setFromEnv() +} diff --git a/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/version.go b/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/version.go index b18475d81004a..9e49e67712909 100644 --- a/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/version.go +++ b/vendor/github.com/spotinst/spotinst-sdk-go/spotinst/version.go @@ -1,7 +1,7 @@ package spotinst // SDKVersion is the current version of the SDK. -const SDKVersion = "1.49.0" +const SDKVersion = "1.56.0" // SDKName is the name of the SDK. const SDKName = "spotinst-sdk-go" diff --git a/vendor/modules.txt b/vendor/modules.txt index 1c03bc331abd9..a07fab70b71d8 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -505,7 +505,7 @@ github.com/spf13/pflag # github.com/spf13/viper v1.4.0 ## explicit github.com/spf13/viper -# github.com/spotinst/spotinst-sdk-go v1.49.0 +# github.com/spotinst/spotinst-sdk-go v1.56.0 ## explicit github.com/spotinst/spotinst-sdk-go/service/elastigroup github.com/spotinst/spotinst-sdk-go/service/elastigroup/providers/aws @@ -517,6 +517,7 @@ github.com/spotinst/spotinst-sdk-go/service/ocean/providers/gcp github.com/spotinst/spotinst-sdk-go/spotinst github.com/spotinst/spotinst-sdk-go/spotinst/client github.com/spotinst/spotinst-sdk-go/spotinst/credentials +github.com/spotinst/spotinst-sdk-go/spotinst/featureflag github.com/spotinst/spotinst-sdk-go/spotinst/log github.com/spotinst/spotinst-sdk-go/spotinst/session github.com/spotinst/spotinst-sdk-go/spotinst/util/jsonutil