Merge pull request #13234 from spotinst/feat-ocean-template

Spotinst: Ocean as a template for VNGs
This commit is contained in:
Kubernetes Prow Robot 2022-03-19 00:45:08 -07:00 committed by GitHub
commit 65694b20b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
39 changed files with 2935 additions and 601 deletions

View File

@ -14,6 +14,7 @@ The following experimental features are currently available:
* `+GoogleCloudBucketAcl` - Enables setting the ACL on the state store bucket when using GCS
* `+Spotinst` - Enables the use of the Spot integration
* `+SpotinstOcean` - Enables the use of the Spot Ocean integration
* `+SpotinstOceanTemplate` - Enables the use of Spot Ocean object as a template for Virtual Node Groups
* `+SpotinstHybrid` - Toggles between hybrid and full instance group implementations
* `-SpotinstController` - Toggles the installation of the Spot controller addon off
* `+SkipEtcdVersionCheck` - Bypasses the check that etcd-manager is using a supported etcd version

View File

@ -70,6 +70,7 @@ Make sure to set up [a dedicated IAM user](./aws.md#setup-iam-user), [DNS record
|---|---|
| `+Spotinst` | Enables the use of the Spot integration. |
| `+SpotinstOcean` | Enables the use of the Spot Ocean integration. |
| `+SpotinstOceanTemplate` - Enables the use of Spot Ocean object as a template for Virtual Node Groups. |
| `+SpotinstHybrid` | Toggles between hybrid and full instance group implementations. Allows you to gradually integrate with Spot Ocean by continuing to use instance groups through AWS Auto Scaling groups, except for specific instance groups labeled with a predefined [metadata label](#metadata-labels). |
| `-SpotinstController` | Toggles the installation of the Spot controller addon off. Please note that the feature flag must be prefixed with a minus (`-`) sign to set its value to `false`, which results in disabling the controller. |
@ -79,7 +80,7 @@ You can add an Ocean instance group to new or existing clusters. To create a new
```bash
# configure the feature flags
export KOPS_FEATURE_FLAGS="Spotinst,SpotinstOcean"
export KOPS_FEATURE_FLAGS="Spotinst,SpotinstOcean,SpotinstOceanTemplate"
# create the cluster
kops create cluster --zones=us-west-2a example
@ -124,7 +125,7 @@ To create a new instance group, run:
```bash
# configure the feature flags
export KOPS_FEATURE_FLAGS="Spotinst,SpotinstOcean"
export KOPS_FEATURE_FLAGS="Spotinst,SpotinstOcean,SpotinstOceanTemplate"
# create the instance group
kops create instancegroup --role=node --name=example

6
go.mod
View File

@ -70,7 +70,7 @@ require (
github.com/spf13/cobra v1.2.1
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.8.1
github.com/spotinst/spotinst-sdk-go v1.85.0
github.com/spotinst/spotinst-sdk-go v1.110.0
github.com/stretchr/testify v1.7.0
github.com/weaveworks/mesh v0.0.0-20191105120815-58dbcc3e8e63
github.com/zclconf/go-cty v1.8.2
@ -91,6 +91,7 @@ require (
k8s.io/client-go v0.23.1
k8s.io/component-base v0.23.1
k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c
k8s.io/klog v1.0.0
k8s.io/klog/v2 v2.30.0
k8s.io/kubectl v0.23.1
k8s.io/kubelet v0.23.1
@ -227,13 +228,12 @@ require (
google.golang.org/genproto v0.0.0-20211111162719-482062a4217b // indirect
google.golang.org/grpc v1.42.0 // indirect
google.golang.org/protobuf v1.27.1 // indirect
gopkg.in/ini.v1 v1.62.0 // indirect
gopkg.in/ini.v1 v1.66.3 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
k8s.io/apiextensions-apiserver v0.23.1 // indirect
k8s.io/cloud-provider v0.23.1 // indirect
k8s.io/csi-translation-lib v0.23.1 // indirect
k8s.io/klog v1.0.0 // indirect
k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65 // indirect
oras.land/oras-go v0.4.0 // indirect
sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 // indirect

7
go.sum
View File

@ -1224,8 +1224,8 @@ github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/y
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/spf13/viper v1.8.1 h1:Kq1fyeebqsBfbjZj4EL7gj2IO0mMaiyjYUWcUsl2O44=
github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns=
github.com/spotinst/spotinst-sdk-go v1.85.0 h1:tMXKhxfmU7BnqTnUpR2s/hEyTASfrxkgPb/3Tqn6tmM=
github.com/spotinst/spotinst-sdk-go v1.85.0/go.mod h1:RuKksd1/RyQogMCxKFI5B75NeFRcgl3W+26DVX6S4m0=
github.com/spotinst/spotinst-sdk-go v1.110.0 h1:5dcaXu4rbqljRIckTiqo5tngUrLSHEZ/VYF4fNLtz54=
github.com/spotinst/spotinst-sdk-go v1.110.0/go.mod h1:qIh4nc5hbkVEAdCG9QTf3EaFHX5cmkj8U37iZn2KpCE=
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8=
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
github.com/storageos/go-api v2.2.0+incompatible/go.mod h1:ZrLn+e0ZuF3Y65PNF6dIwbJPZqfmtCXxFm9ckv0agOY=
@ -1976,8 +1976,9 @@ gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.57.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.66.3 h1:jRskFVxYaMGAMUbN0UZ7niA9gzL9B49DOqE78vg0k3w=
gopkg.in/ini.v1 v1.66.3/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=

View File

@ -62,6 +62,8 @@ var (
Spotinst = new("Spotinst", Bool(false))
// SpotinstOcean toggles the use of Spotinst Ocean instance group implementation.
SpotinstOcean = new("SpotinstOcean", Bool(false))
// SpotinstOceanTemplate toggles the use of Spotinst Ocean object as a template for Virtual Node Groups.
SpotinstOceanTemplate = new("SpotinstOceanTemplate", Bool(false))
// SpotinstHybrid toggles between hybrid and full instance group implementations.
SpotinstHybrid = new("SpotinstHybrid", Bool(false))
// SpotinstController toggles the installation of the Spotinst controller addon.

View File

@ -292,7 +292,7 @@ func (b *SpotInstanceGroupModelBuilder) buildElastigroup(c *fi.ModelBuilderConte
}
// Public IP.
group.AssociatePublicIP, err = b.buildPublicIpOpts(ig)
group.AssociatePublicIPAddress, err = b.buildPublicIPOpts(ig)
if err != nil {
return fmt.Errorf("error building public ip options: %v", err)
}
@ -337,42 +337,30 @@ func (b *SpotInstanceGroupModelBuilder) buildOcean(c *fi.ModelBuilderContext, ig
Name: fi.String("nodes." + b.ClusterName()),
}
// Attempt to find the default LaunchSpec.
var ig *kops.InstanceGroup
{
// Single instance group.
if len(igs) == 1 {
ig = igs[0].DeepCopy()
}
if featureflag.SpotinstOceanTemplate.Enabled() {
ocean.UseAsTemplateOnly = fi.Bool(true)
}
// Multiple instance groups.
if len(igs) > 1 {
for _, g := range igs {
for k, v := range g.ObjectMeta.Labels {
if k == SpotInstanceGroupLabelOceanDefaultLaunchSpec {
defaultLaunchSpec, err := parseBool(v)
if err != nil {
continue
}
if fi.BoolValue(defaultLaunchSpec) {
if ig != nil {
return fmt.Errorf("unable to detect default launch spec: "+
"multiple instance groups labeled with `%s: \"true\"`",
SpotInstanceGroupLabelOceanDefaultLaunchSpec)
}
ig = g.DeepCopy()
break
ig := igs[0].DeepCopy()
if len(igs) > 1 {
for _, g := range igs {
for k, v := range g.ObjectMeta.Labels {
if k == SpotInstanceGroupLabelOceanDefaultLaunchSpec {
defaultLaunchSpec, err := parseBool(v)
if err != nil {
continue
}
if fi.BoolValue(defaultLaunchSpec) {
if ig != nil {
return fmt.Errorf("unable to detect default launch spec: "+
"multiple instance groups labeled with `%s: \"true\"`",
SpotInstanceGroupLabelOceanDefaultLaunchSpec)
}
ig = g.DeepCopy()
break
}
}
}
// No default instance group. Use the first one.
if ig == nil {
ig = igs[0].DeepCopy()
}
}
klog.V(4).Infof("Detected default launch spec: %q", b.AutoscalingGroupName(ig))
@ -428,35 +416,9 @@ func (b *SpotInstanceGroupModelBuilder) buildOcean(c *fi.ModelBuilderContext, ig
}
}
// Capacity.
ocean.MinSize = fi.Int64(0)
ocean.MaxSize = fi.Int64(0)
// Monitoring.
ocean.Monitoring = ig.Spec.DetailedInstanceMonitoring
// User data.
ocean.UserData, err = b.BootstrapScriptBuilder.ResourceNodeUp(c, ig)
if err != nil {
return fmt.Errorf("error building user data: %v", err)
}
// Instance profile.
ocean.IAMInstanceProfile, err = b.LinkToIAMInstanceProfile(ig)
if err != nil {
return fmt.Errorf("error building iam instance profile: %v", err)
}
// Root volume.
rootVolumeOpts, err := b.buildRootVolumeOpts(ig)
if err != nil {
return fmt.Errorf("error building root volume options: %v", err)
}
if rootVolumeOpts != nil {
ocean.RootVolumeOpts = rootVolumeOpts
ocean.RootVolumeOpts.Type = nil // not supported in Ocean
}
// Security groups.
ocean.SecurityGroups, err = b.buildSecurityGroups(c, ig)
if err != nil {
@ -469,24 +431,12 @@ func (b *SpotInstanceGroupModelBuilder) buildOcean(c *fi.ModelBuilderContext, ig
return fmt.Errorf("error building ssh key: %v", err)
}
// Public IP.
ocean.AssociatePublicIP, err = b.buildPublicIpOpts(ig)
if err != nil {
return fmt.Errorf("error building public ip options: %v", err)
}
// Subnets.
ocean.Subnets, err = b.buildSubnets(ig)
if err != nil {
return fmt.Errorf("error building subnets: %v", err)
}
// Tags.
ocean.Tags, err = b.buildTags(ig)
if err != nil {
return fmt.Errorf("error building cloud tags: %v", err)
}
// Auto Scaler.
ocean.AutoScalerOpts, err = b.buildAutoScalerOpts(b.ClusterName(), ig)
if err != nil {
@ -498,6 +448,46 @@ func (b *SpotInstanceGroupModelBuilder) buildOcean(c *fi.ModelBuilderContext, ig
ocean.AutoScalerOpts.Headroom = nil
}
if !fi.BoolValue(ocean.UseAsTemplateOnly) {
// Capacity.
ocean.MinSize = fi.Int64(0)
ocean.MaxSize = fi.Int64(0)
// User data.
ocean.UserData, err = b.BootstrapScriptBuilder.ResourceNodeUp(c, ig)
if err != nil {
return fmt.Errorf("error building user data: %v", err)
}
// Instance profile.
ocean.IAMInstanceProfile, err = b.LinkToIAMInstanceProfile(ig)
if err != nil {
return fmt.Errorf("error building iam instance profile: %v", err)
}
// Root volume.
rootVolumeOpts, err := b.buildRootVolumeOpts(ig)
if err != nil {
return fmt.Errorf("error building root volume options: %v", err)
}
if rootVolumeOpts != nil {
ocean.RootVolumeOpts = rootVolumeOpts
ocean.RootVolumeOpts.Type = nil // not supported in Ocean
}
// Public IP.
ocean.AssociatePublicIPAddress, err = b.buildPublicIPOpts(ig)
if err != nil {
return fmt.Errorf("error building public ip options: %v", err)
}
// Tags.
ocean.Tags, err = b.buildTags(ig)
if err != nil {
return fmt.Errorf("error building cloud tags: %v", err)
}
}
// Create a Launch Spec for each instance group.
for _, g := range igs {
if err := b.buildLaunchSpec(c, g, ig, ocean); err != nil {
@ -551,11 +541,16 @@ func (b *SpotInstanceGroupModelBuilder) buildLaunchSpec(c *fi.ModelBuilderContex
// Capacity.
minSize, maxSize := b.buildCapacity(ig)
ocean.MinSize = fi.Int64(fi.Int64Value(ocean.MinSize) + fi.Int64Value(minSize))
ocean.MaxSize = fi.Int64(fi.Int64Value(ocean.MaxSize) + fi.Int64Value(maxSize))
if fi.BoolValue(ocean.UseAsTemplateOnly) {
launchSpec.MinSize = minSize
launchSpec.MaxSize = maxSize
} else {
ocean.MinSize = fi.Int64(fi.Int64Value(ocean.MinSize) + fi.Int64Value(minSize))
ocean.MaxSize = fi.Int64(fi.Int64Value(ocean.MaxSize) + fi.Int64Value(maxSize))
}
// User data.
if ig.Name == igOcean.Name {
if ig.Name == igOcean.Name && !featureflag.SpotinstOceanTemplate.Enabled() {
launchSpec.UserData = ocean.UserData
} else {
launchSpec.UserData, err = b.BootstrapScriptBuilder.ResourceNodeUp(c, ig)
@ -580,6 +575,12 @@ func (b *SpotInstanceGroupModelBuilder) buildLaunchSpec(c *fi.ModelBuilderContex
launchSpec.RootVolumeOpts.Optimization = nil
}
// Public IP.
launchSpec.AssociatePublicIPAddress, err = b.buildPublicIPOpts(ig)
if err != nil {
return fmt.Errorf("error building public ip options: %v", err)
}
// Security groups.
launchSpec.SecurityGroups, err = b.buildSecurityGroups(c, ig)
if err != nil {
@ -661,7 +662,7 @@ func (b *SpotInstanceGroupModelBuilder) buildSubnets(ig *kops.InstanceGroup) ([]
return out, nil
}
func (b *SpotInstanceGroupModelBuilder) buildPublicIpOpts(ig *kops.InstanceGroup) (*bool, error) {
func (b *SpotInstanceGroupModelBuilder) buildPublicIPOpts(ig *kops.InstanceGroup) (*bool, error) {
subnetMap := make(map[string]*kops.ClusterSubnetSpec)
for i := range b.Cluster.Spec.Subnets {
subnet := &b.Cluster.Spec.Subnets[i]
@ -691,7 +692,7 @@ func (b *SpotInstanceGroupModelBuilder) buildPublicIpOpts(ig *kops.InstanceGroup
associatePublicIP = false
if ig.Spec.AssociatePublicIP != nil {
if *ig.Spec.AssociatePublicIP {
klog.Warningf("Ignoring AssociatePublicIP=true for private SpotInstanceGroup %q", ig.ObjectMeta.Name)
klog.Warningf("Ignoring AssociatePublicIPAddress=true for private SpotInstanceGroup %q", ig.ObjectMeta.Name)
}
}
default:

View File

@ -1541,7 +1541,7 @@ github.com/spf13/viper v1.6.2/go.mod h1:t3iDnF5Jlj76alVNuyFBk5oUMCvsrkbvZK0WQdfD
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns=
github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy5AsM=
github.com/spotinst/spotinst-sdk-go v1.85.0/go.mod h1:RuKksd1/RyQogMCxKFI5B75NeFRcgl3W+26DVX6S4m0=
github.com/spotinst/spotinst-sdk-go v1.110.0/go.mod h1:qIh4nc5hbkVEAdCG9QTf3EaFHX5cmkj8U37iZn2KpCE=
github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI=
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8=
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
@ -2435,8 +2435,9 @@ gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.52.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.57.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.66.2 h1:XfR1dOYubytKy4Shzc2LHrrGhU0lDCfDGG1yLPmpgsI=
gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.66.3 h1:jRskFVxYaMGAMUbN0UZ7niA9gzL9B49DOqE78vg0k3w=
gopkg.in/ini.v1 v1.66.3/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo=
gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eRhxkJMWSIz9Q=
gopkg.in/jcmturner/gokrb5.v7 v7.2.3/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM=

View File

@ -26,6 +26,7 @@ go_library(
"//vendor/github.com/spotinst/spotinst-sdk-go/spotinst/client:go_default_library",
"//vendor/github.com/spotinst/spotinst-sdk-go/spotinst/util/stringutil:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/klog:go_default_library",
"//vendor/k8s.io/klog/v2:go_default_library",
],
)

View File

@ -44,7 +44,6 @@ type Elastigroup struct {
Name *string
Lifecycle fi.Lifecycle
ID *string
Region *string
MinSize *int64
MaxSize *int64
@ -68,7 +67,7 @@ type Elastigroup struct {
Subnets []*awstasks.Subnet
SecurityGroups []*awstasks.SecurityGroup
Monitoring *bool
AssociatePublicIP *bool
AssociatePublicIPAddress *bool
Tenancy *string
RootVolumeOpts *RootVolumeOpts
AutoScalerOpts *AutoScalerOpts
@ -164,26 +163,26 @@ func (e *Elastigroup) GetDependencies(tasks map[string]fi.Task) []fi.Task {
return deps
}
func (e *Elastigroup) find(svc spotinst.InstanceGroupService, name string) (*aws.Group, error) {
klog.V(4).Infof("Attempting to find Elastigroup: %q", name)
func (e *Elastigroup) find(svc spotinst.InstanceGroupService) (*aws.Group, error) {
klog.V(4).Infof("Attempting to find Elastigroup: %q", fi.StringValue(e.Name))
groups, err := svc.List(context.Background())
if err != nil {
return nil, fmt.Errorf("spotinst: failed to find elastigroup %s: %v", name, err)
return nil, fmt.Errorf("spotinst: failed to find elastigroup %s: %v", fi.StringValue(e.Name), err)
}
var out *aws.Group
for _, group := range groups {
if group.Name() == name {
if group.Name() == fi.StringValue(e.Name) {
out = group.Obj().(*aws.Group)
break
}
}
if out == nil {
return nil, fmt.Errorf("spotinst: failed to find elastigroup %q", name)
return nil, fmt.Errorf("spotinst: failed to find elastigroup %q", fi.StringValue(e.Name))
}
klog.V(4).Infof("Elastigroup/%s: %s", name, stringutil.Stringify(out))
klog.V(4).Infof("Elastigroup/%s: %s", fi.StringValue(e.Name), stringutil.Stringify(out))
return out, nil
}
@ -192,13 +191,12 @@ var _ fi.HasCheckExisting = &Elastigroup{}
func (e *Elastigroup) Find(c *fi.Context) (*Elastigroup, error) {
cloud := c.Cloud.(awsup.AWSCloud)
group, err := e.find(cloud.Spotinst().Elastigroup(), *e.Name)
group, err := e.find(cloud.Spotinst().Elastigroup())
if err != nil {
return nil, err
}
actual := &Elastigroup{}
actual.ID = group.ID
actual.Name = group.Name
actual.Region = group.Region
@ -351,7 +349,7 @@ func (e *Elastigroup) Find(c *fi.Context) (*Elastigroup, error) {
}
}
actual.AssociatePublicIP = fi.Bool(associatePublicIP)
actual.AssociatePublicIPAddress = fi.Bool(associatePublicIP)
}
// Load balancers.
@ -479,7 +477,7 @@ func (e *Elastigroup) Find(c *fi.Context) (*Elastigroup, error) {
func (e *Elastigroup) CheckExisting(c *fi.Context) bool {
cloud := c.Cloud.(awsup.AWSCloud)
group, err := e.find(cloud.Spotinst().Elastigroup(), *e.Name)
group, err := e.find(cloud.Spotinst().Elastigroup())
return err == nil && group != nil
}
@ -643,12 +641,12 @@ func (_ *Elastigroup) create(cloud awsup.AWSCloud, a, e, changes *Elastigroup) e
// Public IP.
{
if e.AssociatePublicIP != nil {
if e.AssociatePublicIPAddress != nil {
iface := &aws.NetworkInterface{
Description: fi.String("eth0"),
DeviceIndex: fi.Int(0),
DeleteOnTermination: fi.Bool(true),
AssociatePublicIPAddress: e.AssociatePublicIP,
AssociatePublicIPAddress: e.AssociatePublicIPAddress,
}
group.Compute.LaunchSpecification.SetNetworkInterfaces([]*aws.NetworkInterface{iface})
@ -766,9 +764,8 @@ readyLoop:
}
// Create the Elastigroup.
id, err := cloud.Spotinst().Elastigroup().Create(context.Background(), eg)
_, err = cloud.Spotinst().Elastigroup().Create(context.Background(), eg)
if err == nil {
e.ID = fi.String(id)
break
}
@ -795,7 +792,7 @@ readyLoop:
func (_ *Elastigroup) update(cloud awsup.AWSCloud, a, e, changes *Elastigroup) error {
klog.V(2).Infof("Updating Elastigroup %q", *e.Name)
actual, err := e.find(cloud.Spotinst().Elastigroup(), *e.Name)
actual, err := e.find(cloud.Spotinst().Elastigroup())
if err != nil {
klog.Errorf("Unable to resolve Elastigroup %q, error: %v", *e.Name, err)
return err
@ -997,7 +994,7 @@ func (_ *Elastigroup) update(cloud awsup.AWSCloud, a, e, changes *Elastigroup) e
// Network interfaces.
{
if changes.AssociatePublicIP != nil {
if changes.AssociatePublicIPAddress != nil {
if group.Compute == nil {
group.Compute = new(aws.Compute)
}
@ -1009,11 +1006,11 @@ func (_ *Elastigroup) update(cloud awsup.AWSCloud, a, e, changes *Elastigroup) e
Description: fi.String("eth0"),
DeviceIndex: fi.Int(0),
DeleteOnTermination: fi.Bool(true),
AssociatePublicIPAddress: changes.AssociatePublicIP,
AssociatePublicIPAddress: changes.AssociatePublicIPAddress,
}
group.Compute.LaunchSpecification.SetNetworkInterfaces([]*aws.NetworkInterface{iface})
changes.AssociatePublicIP = nil
changes.AssociatePublicIPAddress = nil
changed = true
}
}
@ -1327,15 +1324,15 @@ func (_ *Elastigroup) update(cloud awsup.AWSCloud, a, e, changes *Elastigroup) e
empty := &Elastigroup{}
if !reflect.DeepEqual(empty, changes) {
klog.Warningf("Not all changes applied to Elastigroup %q: %v", *group.ID, changes)
klog.Warningf("Not all changes applied to Elastigroup %q: %v", *e.Name, changes)
}
if !changed {
klog.V(2).Infof("No changes detected in Elastigroup %q", *group.ID)
klog.V(2).Infof("No changes detected in Elastigroup %q", *e.Name)
return nil
}
klog.V(2).Infof("Updating Elastigroup %q (config: %s)", *group.ID, stringutil.Stringify(group))
klog.V(2).Infof("Updating Elastigroup %q (config: %s)", *e.Name, stringutil.Stringify(group))
// Wrap the raw object as an Elastigroup.
eg, err := spotinst.NewElastigroup(cloud.ProviderID(), group)
@ -1572,12 +1569,12 @@ func (_ *Elastigroup) RenderTerraform(t *terraform.TerraformTarget, a, e, change
}
// Public IP.
if e.AssociatePublicIP != nil {
if e.AssociatePublicIPAddress != nil {
tf.NetworkInterfaces = append(tf.NetworkInterfaces, &terraformElastigroupNetworkInterface{
Description: fi.String("eth0"),
DeviceIndex: fi.Int(0),
DeleteOnTermination: fi.Bool(true),
AssociatePublicIPAddress: e.AssociatePublicIP,
AssociatePublicIPAddress: e.AssociatePublicIPAddress,
})
}

View File

@ -40,18 +40,20 @@ type LaunchSpec struct {
Name *string
Lifecycle fi.Lifecycle
ID *string
SpotPercentage *int64
UserData fi.Resource
SecurityGroups []*awstasks.SecurityGroup
Subnets []*awstasks.Subnet
IAMInstanceProfile *awstasks.IAMInstanceProfile
ImageID *string
InstanceTypes []string
Tags map[string]string
RootVolumeOpts *RootVolumeOpts
AutoScalerOpts *AutoScalerOpts
RestrictScaleDown *bool
SpotPercentage *int64
UserData fi.Resource
SecurityGroups []*awstasks.SecurityGroup
Subnets []*awstasks.Subnet
IAMInstanceProfile *awstasks.IAMInstanceProfile
ImageID *string
InstanceTypes []string
Tags map[string]string
RootVolumeOpts *RootVolumeOpts
AutoScalerOpts *AutoScalerOpts
RestrictScaleDown *bool
AssociatePublicIPAddress *bool
MinSize *int64
MaxSize *int64
Ocean *Ocean
}
@ -127,7 +129,7 @@ var _ fi.HasCheckExisting = &LaunchSpec{}
func (o *LaunchSpec) Find(c *fi.Context) (*LaunchSpec, error) {
cloud := c.Cloud.(awsup.AWSCloud)
ocean, err := o.Ocean.find(cloud.Spotinst().Ocean(), *o.Ocean.Name)
ocean, err := o.Ocean.find(cloud.Spotinst().Ocean())
if err != nil {
return nil, err
}
@ -138,14 +140,20 @@ func (o *LaunchSpec) Find(c *fi.Context) (*LaunchSpec, error) {
}
actual := &LaunchSpec{}
actual.ID = spec.ID
actual.Name = spec.Name
actual.Ocean = &Ocean{
ID: ocean.ID,
Name: ocean.Name,
}
actual.RestrictScaleDown = spec.RestrictScaleDown
// Capacity.
{
if spec.ResourceLimits != nil {
actual.MinSize = fi.Int64(int64(fi.IntValue(spec.ResourceLimits.MinInstanceCount)))
actual.MaxSize = fi.Int64(int64(fi.IntValue(spec.ResourceLimits.MaxInstanceCount)))
}
}
// Image.
{
actual.ImageID = spec.ImageID
@ -164,16 +172,13 @@ func (o *LaunchSpec) Find(c *fi.Context) (*LaunchSpec, error) {
// User data.
{
var userData []byte
if spec.UserData != nil {
userData, err = base64.StdEncoding.DecodeString(fi.StringValue(spec.UserData))
userData, err := base64.StdEncoding.DecodeString(fi.StringValue(spec.UserData))
if err != nil {
return nil, err
}
actual.UserData = fi.NewStringResource(string(userData))
}
actual.UserData = fi.NewStringResource(string(userData))
}
// IAM instance profile.
@ -243,6 +248,11 @@ func (o *LaunchSpec) Find(c *fi.Context) (*LaunchSpec, error) {
}
}
// Public IP.
if spec.AssociatePublicIPAddress != nil {
actual.AssociatePublicIPAddress = spec.AssociatePublicIPAddress
}
// Instance types.
{
if itypes := spec.InstanceTypes; itypes != nil {
@ -308,7 +318,9 @@ func (o *LaunchSpec) Find(c *fi.Context) (*LaunchSpec, error) {
// Strategy.
{
if strategy := spec.Strategy; strategy != nil {
actual.SpotPercentage = fi.Int64(int64(fi.IntValue(strategy.SpotPercentage)))
if strategy.SpotPercentage != nil {
actual.SpotPercentage = fi.Int64(int64(fi.IntValue(strategy.SpotPercentage)))
}
}
}
@ -347,7 +359,7 @@ func (o *LaunchSpec) createOrUpdate(cloud awsup.AWSCloud, a, e, changes *LaunchS
}
func (_ *LaunchSpec) create(cloud awsup.AWSCloud, a, e, changes *LaunchSpec) error {
ocean, err := e.Ocean.find(cloud.Spotinst().Ocean(), *e.Ocean.Name)
ocean, err := e.Ocean.find(cloud.Spotinst().Ocean())
if err != nil {
return err
}
@ -361,6 +373,15 @@ func (_ *LaunchSpec) create(cloud awsup.AWSCloud, a, e, changes *LaunchSpec) err
spec.SetName(e.Name)
spec.SetOceanId(ocean.ID)
// Capacity.
{
if e.MinSize != nil || e.MaxSize != nil {
spec.ResourceLimits = new(aws.ResourceLimits)
spec.ResourceLimits.SetMinInstanceCount(fi.Int(int(*e.MinSize)))
spec.ResourceLimits.SetMaxInstanceCount(fi.Int(int(*e.MaxSize)))
}
}
// Image.
{
if e.ImageID != nil {
@ -432,6 +453,13 @@ func (_ *LaunchSpec) create(cloud awsup.AWSCloud, a, e, changes *LaunchSpec) err
}
}
// Public IP.
{
if e.AssociatePublicIPAddress != nil {
spec.SetAssociatePublicIPAddress(e.AssociatePublicIPAddress)
}
}
// Instance types.
{
if e.InstanceTypes != nil {
@ -511,19 +539,24 @@ func (_ *LaunchSpec) create(cloud awsup.AWSCloud, a, e, changes *LaunchSpec) err
}
// Create a new LaunchSpec.
id, err := cloud.Spotinst().LaunchSpec().Create(context.Background(), sp)
_, err = cloud.Spotinst().LaunchSpec().Create(context.Background(), sp)
if err != nil {
return fmt.Errorf("spotinst: failed to create launch spec: %v", err)
}
e.ID = fi.String(id)
return nil
}
func (_ *LaunchSpec) update(cloud awsup.AWSCloud, a, e, changes *LaunchSpec) error {
klog.V(2).Infof("Updating Launch Spec for Ocean %q", *a.Ocean.ID)
klog.V(2).Infof("Updating Launch Spec for Ocean %q", *a.Ocean.Name)
actual, err := e.find(cloud.Spotinst().LaunchSpec(), *a.Ocean.ID)
ocean, err := a.Ocean.find(cloud.Spotinst().Ocean())
if err != nil {
klog.Errorf("Unable to resolve Ocean %q, error: %v", *a.Ocean.Name, err)
return err
}
actual, err := e.find(cloud.Spotinst().LaunchSpec(), *ocean.ID)
if err != nil {
klog.Errorf("Unable to resolve Launch Spec %q, error: %v", *e.Name, err)
return err
@ -531,7 +564,29 @@ func (_ *LaunchSpec) update(cloud awsup.AWSCloud, a, e, changes *LaunchSpec) err
var changed bool
spec := new(aws.LaunchSpec)
spec.SetId(a.ID)
spec.SetId(actual.ID)
// Capacity.
{
if changes.MinSize != nil {
if spec.ResourceLimits == nil {
spec.ResourceLimits = new(aws.ResourceLimits)
}
spec.ResourceLimits.SetMinInstanceCount(fi.Int(int(*e.MinSize)))
changes.MinSize = nil
changed = true
}
if changes.MaxSize != nil {
if spec.ResourceLimits == nil {
spec.ResourceLimits = new(aws.ResourceLimits)
}
spec.ResourceLimits.SetMaxInstanceCount(fi.Int(int(*e.MaxSize)))
changes.MaxSize = nil
changed = true
}
}
// Image.
{
@ -625,6 +680,15 @@ func (_ *LaunchSpec) update(cloud awsup.AWSCloud, a, e, changes *LaunchSpec) err
}
}
// Public IP.
{
if changes.AssociatePublicIPAddress != nil {
spec.SetAssociatePublicIPAddress(e.AssociatePublicIPAddress)
changes.AssociatePublicIPAddress = nil
changed = true
}
}
// Instance types.
{
if changes.InstanceTypes != nil {
@ -723,22 +787,17 @@ func (_ *LaunchSpec) update(cloud awsup.AWSCloud, a, e, changes *LaunchSpec) err
empty := &LaunchSpec{}
if !reflect.DeepEqual(empty, changes) {
klog.Warningf("Not all changes applied to Launch Spec %q: %v", *spec.ID, changes)
klog.Warningf("Not all changes applied to Launch Spec %q: %v", *e.Name, changes)
}
if !changed {
klog.V(2).Infof("No changes detected in Launch Spec %q", *spec.ID)
klog.V(2).Infof("No changes detected in Launch Spec %q", *e.Name)
return nil
}
klog.V(2).Infof("Updating Launch Spec %q (config: %s)", *spec.ID, stringutil.Stringify(spec))
klog.V(2).Infof("Updating Launch Spec %q (config: %s)", *e.Name, stringutil.Stringify(spec))
ctx := context.Background()
ocean, err := e.Ocean.find(cloud.Spotinst().Ocean(), *e.Ocean.Name)
if err != nil {
return err
}
// Reset the Spot percentage on the Cluster level.
if spec.Strategy != nil && spec.Strategy.SpotPercentage != nil &&
ocean.Strategy != nil && ocean.Strategy.SpotPercentage != nil {
@ -776,30 +835,36 @@ type terraformLaunchSpec struct {
Name *string `cty:"name"`
OceanID *terraformWriter.Literal `cty:"ocean_id"`
Monitoring *bool `cty:"monitoring"`
EBSOptimized *bool `cty:"ebs_optimized"`
ImageID *string `cty:"image_id"`
AssociatePublicIPAddress *bool `cty:"associate_public_ip_address"`
RestrictScaleDown *bool `cty:"restrict_scale_down"`
RootVolumeSize *int64 `cty:"root_volume_size"`
UserData *terraformWriter.Literal `cty:"user_data"`
IAMInstanceProfile *terraformWriter.Literal `cty:"iam_instance_profile"`
KeyName *terraformWriter.Literal `cty:"key_name"`
InstanceTypes []string `cty:"instance_types"`
SubnetIDs []*terraformWriter.Literal `cty:"subnet_ids"`
SecurityGroups []*terraformWriter.Literal `cty:"security_groups"`
Taints []*terraformTaint `cty:"taints"`
Labels []*terraformKV `cty:"labels"`
Tags []*terraformKV `cty:"tags"`
Headrooms []*terraformAutoScalerHeadroom `cty:"autoscale_headrooms"`
BlockDeviceMappings []*terraformBlockDeviceMapping `cty:"block_device_mappings"`
Strategy *terraformLaunchSpecStrategy `cty:"strategy"`
Monitoring *bool `cty:"monitoring"`
EBSOptimized *bool `cty:"ebs_optimized"`
ImageID *string `cty:"image_id"`
AssociatePublicIPAddress *bool `cty:"associate_public_ip_address"`
RestrictScaleDown *bool `cty:"restrict_scale_down"`
RootVolumeSize *int64 `cty:"root_volume_size"`
UserData *terraformWriter.Literal `cty:"user_data"`
IAMInstanceProfile *terraformWriter.Literal `cty:"iam_instance_profile"`
KeyName *terraformWriter.Literal `cty:"key_name"`
InstanceTypes []string `cty:"instance_types"`
SubnetIDs []*terraformWriter.Literal `cty:"subnet_ids"`
SecurityGroups []*terraformWriter.Literal `cty:"security_groups"`
Taints []*terraformTaint `cty:"taints"`
Labels []*terraformKV `cty:"labels"`
Tags []*terraformKV `cty:"tags"`
Headrooms []*terraformAutoScalerHeadroom `cty:"autoscale_headrooms"`
BlockDeviceMappings []*terraformBlockDeviceMapping `cty:"block_device_mappings"`
Strategy *terraformLaunchSpecStrategy `cty:"strategy"`
ResourceLimits *terraformLaunchSpecResourceLimits `cty:"resource_limits"`
}
type terraformLaunchSpecStrategy struct {
SpotPercentage *int64 `cty:"spot_percentage"`
}
type terraformLaunchSpecResourceLimits struct {
MinInstanceCount *int64 `cty:"min_instance_count"`
MaxInstanceCount *int64 `cty:"max_instance_count"`
}
type terraformBlockDeviceMapping struct {
DeviceName *string `cty:"device_name"`
EBS *terraformBlockDeviceMappingEBS `cty:"ebs"`
@ -818,9 +883,20 @@ func (_ *LaunchSpec) RenderTerraform(t *terraform.TerraformTarget, a, e, changes
cloud := t.Cloud.(awsup.AWSCloud)
tf := &terraformLaunchSpec{
Name: e.Name,
OceanID: e.Ocean.TerraformLink(),
InstanceTypes: e.InstanceTypes,
Name: e.Name,
OceanID: e.Ocean.TerraformLink(),
InstanceTypes: e.InstanceTypes,
AssociatePublicIPAddress: e.AssociatePublicIPAddress,
}
// Capacity.
{
if e.MinSize != nil || e.MaxSize != nil {
tf.ResourceLimits = &terraformLaunchSpecResourceLimits{
MinInstanceCount: e.MinSize,
MaxInstanceCount: e.MaxSize,
}
}
}
// Image.

View File

@ -24,10 +24,11 @@ import (
"strings"
"time"
"k8s.io/klog"
"github.com/spotinst/spotinst-sdk-go/service/ocean/providers/aws"
"github.com/spotinst/spotinst-sdk-go/spotinst/client"
"github.com/spotinst/spotinst-sdk-go/spotinst/util/stringutil"
"k8s.io/klog/v2"
"k8s.io/kops/pkg/resources/spotinst"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/upup/pkg/fi/cloudup/awstasks"
@ -41,7 +42,6 @@ type Ocean struct {
Name *string
Lifecycle fi.Lifecycle
ID *string
MinSize *int64
MaxSize *int64
UtilizeReservedInstances *bool
@ -59,7 +59,8 @@ type Ocean struct {
Subnets []*awstasks.Subnet
SecurityGroups []*awstasks.SecurityGroup
Monitoring *bool
AssociatePublicIP *bool
AssociatePublicIPAddress *bool
UseAsTemplateOnly *bool
RootVolumeOpts *RootVolumeOpts
AutoScalerOpts *AutoScalerOpts
}
@ -104,26 +105,26 @@ func (o *Ocean) GetDependencies(tasks map[string]fi.Task) []fi.Task {
return deps
}
func (o *Ocean) find(svc spotinst.InstanceGroupService, name string) (*aws.Cluster, error) {
klog.V(4).Infof("Attempting to find Ocean: %q", name)
func (o *Ocean) find(svc spotinst.InstanceGroupService) (*aws.Cluster, error) {
klog.V(4).Infof("Attempting to find Ocean: %q", fi.StringValue(o.Name))
oceans, err := svc.List(context.Background())
if err != nil {
return nil, fmt.Errorf("spotinst: failed to find ocean %q: %v", name, err)
return nil, fmt.Errorf("spotinst: failed to find ocean %q: %v", fi.StringValue(o.Name), err)
}
var out *aws.Cluster
for _, ocean := range oceans {
if ocean.Name() == name {
if ocean.Name() == fi.StringValue(o.Name) {
out = ocean.Obj().(*aws.Cluster)
break
}
}
if out == nil {
return nil, fmt.Errorf("spotinst: failed to find ocean %q", name)
return nil, fmt.Errorf("spotinst: failed to find ocean %q", fi.StringValue(o.Name))
}
klog.V(4).Infof("Ocean/%s: %s", name, stringutil.Stringify(out))
klog.V(4).Infof("Ocean/%s: %s", fi.StringValue(o.Name), stringutil.Stringify(out))
return out, nil
}
@ -132,19 +133,20 @@ var _ fi.HasCheckExisting = &Ocean{}
func (o *Ocean) Find(c *fi.Context) (*Ocean, error) {
cloud := c.Cloud.(awsup.AWSCloud)
ocean, err := o.find(cloud.Spotinst().Ocean(), *o.Name)
ocean, err := o.find(cloud.Spotinst().Ocean())
if err != nil {
return nil, err
}
actual := &Ocean{}
actual.ID = ocean.ID
actual.Name = ocean.Name
// Capacity.
{
actual.MinSize = fi.Int64(int64(fi.IntValue(ocean.Capacity.Minimum)))
actual.MaxSize = fi.Int64(int64(fi.IntValue(ocean.Capacity.Maximum)))
if !fi.BoolValue(ocean.Compute.LaunchSpecification.UseAsTemplateOnly) {
actual.MinSize = fi.Int64(int64(fi.IntValue(ocean.Capacity.Minimum)))
actual.MaxSize = fi.Int64(int64(fi.IntValue(ocean.Capacity.Maximum)))
}
}
// Strategy.
@ -239,16 +241,13 @@ func (o *Ocean) Find(c *fi.Context) (*Ocean, error) {
// User data.
{
var userData []byte
if lc.UserData != nil {
userData, err = base64.StdEncoding.DecodeString(fi.StringValue(lc.UserData))
userData, err := base64.StdEncoding.DecodeString(fi.StringValue(lc.UserData))
if err != nil {
return nil, err
}
actual.UserData = fi.NewStringResource(string(userData))
}
actual.UserData = fi.NewStringResource(string(userData))
}
// EBS optimization.
@ -257,7 +256,6 @@ func (o *Ocean) Find(c *fi.Context) (*Ocean, error) {
if actual.RootVolumeOpts == nil {
actual.RootVolumeOpts = new(RootVolumeOpts)
}
actual.RootVolumeOpts.Optimization = lc.EBSOptimized
}
}
@ -274,7 +272,7 @@ func (o *Ocean) Find(c *fi.Context) (*Ocean, error) {
// Public IP.
if lc.AssociatePublicIPAddress != nil {
actual.AssociatePublicIP = lc.AssociatePublicIPAddress
actual.AssociatePublicIPAddress = lc.AssociatePublicIPAddress
}
// Root volume options.
@ -287,6 +285,11 @@ func (o *Ocean) Find(c *fi.Context) (*Ocean, error) {
if lc.Monitoring != nil {
actual.Monitoring = lc.Monitoring
}
// Template.
if lc.UseAsTemplateOnly != nil {
actual.UseAsTemplateOnly = lc.UseAsTemplateOnly
}
}
// Auto Scaler.
@ -325,7 +328,7 @@ func (o *Ocean) Find(c *fi.Context) (*Ocean, error) {
func (o *Ocean) CheckExisting(c *fi.Context) bool {
cloud := c.Cloud.(awsup.AWSCloud)
ocean, err := o.find(cloud.Spotinst().Ocean(), *o.Name)
ocean, err := o.find(cloud.Spotinst().Ocean())
return err == nil && ocean != nil
}
@ -354,7 +357,6 @@ func (o *Ocean) createOrUpdate(cloud awsup.AWSCloud, a, e, changes *Ocean) error
func (_ *Ocean) create(cloud awsup.AWSCloud, a, e, changes *Ocean) error {
klog.V(2).Infof("Creating Ocean %q", *e.Name)
e.applyDefaults()
ocean := &aws.Cluster{
Capacity: new(aws.Capacity),
@ -372,9 +374,11 @@ func (_ *Ocean) create(cloud awsup.AWSCloud, a, e, changes *Ocean) error {
// Capacity.
{
ocean.Capacity.SetTarget(fi.Int(int(*e.MinSize)))
ocean.Capacity.SetMinimum(fi.Int(int(*e.MinSize)))
ocean.Capacity.SetMaximum(fi.Int(int(*e.MaxSize)))
if !fi.BoolValue(e.UseAsTemplateOnly) {
ocean.Capacity.SetTarget(fi.Int(int(*e.MinSize)))
ocean.Capacity.SetMinimum(fi.Int(int(*e.MinSize)))
ocean.Capacity.SetMaximum(fi.Int(int(*e.MaxSize)))
}
}
// Strategy.
@ -426,6 +430,7 @@ func (_ *Ocean) create(cloud awsup.AWSCloud, a, e, changes *Ocean) error {
// Launch specification.
{
ocean.Compute.LaunchSpecification.SetUseAsTemplateOnly(e.UseAsTemplateOnly)
ocean.Compute.LaunchSpecification.SetMonitoring(e.Monitoring)
ocean.Compute.LaunchSpecification.SetKeyPair(e.SSHKey.Name)
@ -440,30 +445,6 @@ func (_ *Ocean) create(cloud awsup.AWSCloud, a, e, changes *Ocean) error {
}
}
// User data.
{
if e.UserData != nil {
userData, err := fi.ResourceAsString(e.UserData)
if err != nil {
return err
}
if len(userData) > 0 {
encoded := base64.StdEncoding.EncodeToString([]byte(userData))
ocean.Compute.LaunchSpecification.SetUserData(fi.String(encoded))
}
}
}
// IAM instance profile.
{
if e.IAMInstanceProfile != nil {
iprof := new(aws.IAMInstanceProfile)
iprof.SetName(e.IAMInstanceProfile.GetName())
ocean.Compute.LaunchSpecification.SetIAMInstanceProfile(iprof)
}
}
// Security groups.
{
if e.SecurityGroups != nil {
@ -475,35 +456,62 @@ func (_ *Ocean) create(cloud awsup.AWSCloud, a, e, changes *Ocean) error {
}
}
// Public IP.
{
if e.AssociatePublicIP != nil {
ocean.Compute.LaunchSpecification.SetAssociatePublicIPAddress(e.AssociatePublicIP)
}
}
if !fi.BoolValue(e.UseAsTemplateOnly) {
// User data.
{
if e.UserData != nil {
userData, err := fi.ResourceAsString(e.UserData)
if err != nil {
return err
}
// Root volume options.
{
if opts := e.RootVolumeOpts; opts != nil {
// Volume size.
if opts.Size != nil {
ocean.Compute.LaunchSpecification.SetRootVolumeSize(fi.Int(int(*opts.Size)))
if len(userData) > 0 {
encoded := base64.StdEncoding.EncodeToString([]byte(userData))
ocean.Compute.LaunchSpecification.SetUserData(fi.String(encoded))
}
}
}
// EBS optimization.
if opts.Optimization != nil {
ocean.Compute.LaunchSpecification.SetEBSOptimized(opts.Optimization)
// IAM instance profile.
{
if e.IAMInstanceProfile != nil {
iprof := new(aws.IAMInstanceProfile)
iprof.SetName(e.IAMInstanceProfile.GetName())
ocean.Compute.LaunchSpecification.SetIAMInstanceProfile(iprof)
}
}
// Root volume options.
{
if opts := e.RootVolumeOpts; opts != nil {
// Volume size.
if opts.Size != nil {
ocean.Compute.LaunchSpecification.SetRootVolumeSize(fi.Int(int(*opts.Size)))
}
// EBS optimization.
if opts.Optimization != nil {
ocean.Compute.LaunchSpecification.SetEBSOptimized(opts.Optimization)
}
}
}
// Public IP.
{
if e.AssociatePublicIPAddress != nil {
ocean.Compute.LaunchSpecification.SetAssociatePublicIPAddress(e.AssociatePublicIPAddress)
}
}
// Tags.
{
if e.Tags != nil {
ocean.Compute.LaunchSpecification.SetTags(e.buildTags())
}
}
}
// Tags.
{
if e.Tags != nil {
ocean.Compute.LaunchSpecification.SetTags(e.buildTags())
}
}
}
}
@ -559,9 +567,8 @@ readyLoop:
}
// Create a new Ocean.
id, err := cloud.Spotinst().Ocean().Create(context.Background(), oc)
_, err = cloud.Spotinst().Ocean().Create(context.Background(), oc)
if err == nil {
e.ID = fi.String(id)
break
}
@ -588,7 +595,7 @@ readyLoop:
func (_ *Ocean) update(cloud awsup.AWSCloud, a, e, changes *Ocean) error {
klog.V(2).Infof("Updating Ocean %q", *e.Name)
actual, err := e.find(cloud.Spotinst().Ocean(), *e.Name)
actual, err := e.find(cloud.Spotinst().Ocean())
if err != nil {
klog.Errorf("Unable to resolve Ocean %q, error: %s", *e.Name, err)
return err
@ -734,31 +741,6 @@ func (_ *Ocean) update(cloud awsup.AWSCloud, a, e, changes *Ocean) error {
}
}
// User data.
{
if changes.UserData != nil {
userData, err := fi.ResourceAsString(e.UserData)
if err != nil {
return err
}
if len(userData) > 0 {
if ocean.Compute == nil {
ocean.Compute = new(aws.Compute)
}
if ocean.Compute.LaunchSpecification == nil {
ocean.Compute.LaunchSpecification = new(aws.LaunchSpecification)
}
encoded := base64.StdEncoding.EncodeToString([]byte(userData))
ocean.Compute.LaunchSpecification.SetUserData(fi.String(encoded))
changed = true
}
changes.UserData = nil
}
}
// Image.
{
if changes.ImageID != nil {
@ -783,41 +765,6 @@ func (_ *Ocean) update(cloud awsup.AWSCloud, a, e, changes *Ocean) error {
}
}
// Tags.
{
if changes.Tags != nil {
if ocean.Compute == nil {
ocean.Compute = new(aws.Compute)
}
if ocean.Compute.LaunchSpecification == nil {
ocean.Compute.LaunchSpecification = new(aws.LaunchSpecification)
}
ocean.Compute.LaunchSpecification.SetTags(e.buildTags())
changes.Tags = nil
changed = true
}
}
// IAM instance profile.
{
if changes.IAMInstanceProfile != nil {
if ocean.Compute == nil {
ocean.Compute = new(aws.Compute)
}
if ocean.Compute.LaunchSpecification == nil {
ocean.Compute.LaunchSpecification = new(aws.LaunchSpecification)
}
iprof := new(aws.IAMInstanceProfile)
iprof.SetName(e.IAMInstanceProfile.GetName())
ocean.Compute.LaunchSpecification.SetIAMInstanceProfile(iprof)
changes.IAMInstanceProfile = nil
changed = true
}
}
// Monitoring.
{
if changes.Monitoring != nil {
@ -834,6 +781,22 @@ func (_ *Ocean) update(cloud awsup.AWSCloud, a, e, changes *Ocean) error {
}
}
// Template.
{
if changes.UseAsTemplateOnly != nil {
if ocean.Compute == nil {
ocean.Compute = new(aws.Compute)
}
if ocean.Compute.LaunchSpecification == nil {
ocean.Compute.LaunchSpecification = new(aws.LaunchSpecification)
}
ocean.Compute.LaunchSpecification.SetUseAsTemplateOnly(e.UseAsTemplateOnly)
changes.UseAsTemplateOnly = nil
changed = true
}
}
// SSH key.
{
if changes.SSHKey != nil {
@ -850,28 +813,35 @@ func (_ *Ocean) update(cloud awsup.AWSCloud, a, e, changes *Ocean) error {
}
}
// Public IP.
{
if changes.AssociatePublicIP != nil {
if ocean.Compute == nil {
ocean.Compute = new(aws.Compute)
}
if ocean.Compute.LaunchSpecification == nil {
ocean.Compute.LaunchSpecification = new(aws.LaunchSpecification)
}
if !fi.BoolValue(e.UseAsTemplateOnly) {
// User data.
{
if changes.UserData != nil {
userData, err := fi.ResourceAsString(e.UserData)
if err != nil {
return err
}
ocean.Compute.LaunchSpecification.SetAssociatePublicIPAddress(e.AssociatePublicIP)
changes.AssociatePublicIP = nil
changed = true
if len(userData) > 0 {
if ocean.Compute == nil {
ocean.Compute = new(aws.Compute)
}
if ocean.Compute.LaunchSpecification == nil {
ocean.Compute.LaunchSpecification = new(aws.LaunchSpecification)
}
encoded := base64.StdEncoding.EncodeToString([]byte(userData))
ocean.Compute.LaunchSpecification.SetUserData(fi.String(encoded))
changed = true
}
changes.UserData = nil
}
}
}
// Root volume options.
{
if opts := changes.RootVolumeOpts; opts != nil {
// Volume size.
if opts.Size != nil {
// Tags.
{
if changes.Tags != nil {
if ocean.Compute == nil {
ocean.Compute = new(aws.Compute)
}
@ -879,12 +849,15 @@ func (_ *Ocean) update(cloud awsup.AWSCloud, a, e, changes *Ocean) error {
ocean.Compute.LaunchSpecification = new(aws.LaunchSpecification)
}
ocean.Compute.LaunchSpecification.SetRootVolumeSize(fi.Int(int(*opts.Size)))
ocean.Compute.LaunchSpecification.SetTags(e.buildTags())
changes.Tags = nil
changed = true
}
}
// EBS optimization.
if opts.Optimization != nil {
// IAM instance profile.
{
if changes.IAMInstanceProfile != nil {
if ocean.Compute == nil {
ocean.Compute = new(aws.Compute)
}
@ -892,11 +865,63 @@ func (_ *Ocean) update(cloud awsup.AWSCloud, a, e, changes *Ocean) error {
ocean.Compute.LaunchSpecification = new(aws.LaunchSpecification)
}
ocean.Compute.LaunchSpecification.SetEBSOptimized(e.RootVolumeOpts.Optimization)
iprof := new(aws.IAMInstanceProfile)
iprof.SetName(e.IAMInstanceProfile.GetName())
ocean.Compute.LaunchSpecification.SetIAMInstanceProfile(iprof)
changes.IAMInstanceProfile = nil
changed = true
}
}
changes.RootVolumeOpts = nil
// Public IP.
{
if changes.AssociatePublicIPAddress != nil {
if ocean.Compute == nil {
ocean.Compute = new(aws.Compute)
}
if ocean.Compute.LaunchSpecification == nil {
ocean.Compute.LaunchSpecification = new(aws.LaunchSpecification)
}
ocean.Compute.LaunchSpecification.SetAssociatePublicIPAddress(e.AssociatePublicIPAddress)
changes.AssociatePublicIPAddress = nil
changed = true
}
}
// Root volume options.
{
if opts := changes.RootVolumeOpts; opts != nil {
// Volume size.
if opts.Size != nil {
if ocean.Compute == nil {
ocean.Compute = new(aws.Compute)
}
if ocean.Compute.LaunchSpecification == nil {
ocean.Compute.LaunchSpecification = new(aws.LaunchSpecification)
}
ocean.Compute.LaunchSpecification.SetRootVolumeSize(fi.Int(int(*opts.Size)))
changed = true
}
// EBS optimization.
if opts.Optimization != nil {
if ocean.Compute == nil {
ocean.Compute = new(aws.Compute)
}
if ocean.Compute.LaunchSpecification == nil {
ocean.Compute.LaunchSpecification = new(aws.LaunchSpecification)
}
ocean.Compute.LaunchSpecification.SetEBSOptimized(e.RootVolumeOpts.Optimization)
changed = true
}
changes.RootVolumeOpts = nil
}
}
}
}
@ -904,28 +929,30 @@ func (_ *Ocean) update(cloud awsup.AWSCloud, a, e, changes *Ocean) error {
// Capacity.
{
if changes.MinSize != nil {
if ocean.Capacity == nil {
ocean.Capacity = new(aws.Capacity)
}
if !fi.BoolValue(e.UseAsTemplateOnly) {
if changes.MinSize != nil {
if ocean.Capacity == nil {
ocean.Capacity = new(aws.Capacity)
}
ocean.Capacity.SetMinimum(fi.Int(int(*e.MinSize)))
changes.MinSize = nil
changed = true
ocean.Capacity.SetMinimum(fi.Int(int(*e.MinSize)))
changes.MinSize = nil
changed = true
// Scale up the target capacity, if needed.
if int64(*actual.Capacity.Target) < *e.MinSize {
ocean.Capacity.SetTarget(fi.Int(int(*e.MinSize)))
}
}
if changes.MaxSize != nil {
if ocean.Capacity == nil {
ocean.Capacity = new(aws.Capacity)
// Scale up the target capacity, if needed.
if int64(*actual.Capacity.Target) < *e.MinSize {
ocean.Capacity.SetTarget(fi.Int(int(*e.MinSize)))
}
}
if changes.MaxSize != nil {
if ocean.Capacity == nil {
ocean.Capacity = new(aws.Capacity)
}
ocean.Capacity.SetMaximum(fi.Int(int(*e.MaxSize)))
changes.MaxSize = nil
changed = true
ocean.Capacity.SetMaximum(fi.Int(int(*e.MaxSize)))
changes.MaxSize = nil
changed = true
}
}
}
@ -969,15 +996,15 @@ func (_ *Ocean) update(cloud awsup.AWSCloud, a, e, changes *Ocean) error {
empty := &Ocean{}
if !reflect.DeepEqual(empty, changes) {
klog.Warningf("Not all changes applied to Ocean %q: %v", *ocean.ID, changes)
klog.Warningf("Not all changes applied to Ocean %q: %v", *e.Name, changes)
}
if !changed {
klog.V(2).Infof("No changes detected in Ocean %q", *ocean.ID)
klog.V(2).Infof("No changes detected in Ocean %q", *e.Name)
return nil
}
klog.V(2).Infof("Updating Ocean %q (config: %s)", *ocean.ID, stringutil.Stringify(ocean))
klog.V(2).Infof("Updating Ocean %q (config: %s)", *e.Name, stringutil.Stringify(ocean))
// Wrap the raw object as an Ocean.
oc, err := spotinst.NewOcean(cloud.ProviderID(), ocean)
@ -1013,6 +1040,7 @@ type terraformOcean struct {
DrainingTimeout *int64 `cty:"draining_timeout"`
GracePeriod *int64 `cty:"grace_period"`
UseAsTemplateOnly *bool `cty:"use_as_template_only"`
Monitoring *bool `cty:"monitoring"`
EBSOptimized *bool `cty:"ebs_optimized"`
ImageID *string `cty:"image_id"`
@ -1026,16 +1054,11 @@ type terraformOcean struct {
func (_ *Ocean) RenderTerraform(t *terraform.TerraformTarget, a, e, changes *Ocean) error {
cloud := t.Cloud.(awsup.AWSCloud)
e.applyDefaults()
tf := &terraformOcean{
Name: e.Name,
Region: fi.String(cloud.Region()),
DesiredCapacity: e.MinSize,
MinSize: e.MinSize,
MaxSize: e.MaxSize,
Name: e.Name,
Region: fi.String(cloud.Region()),
UseAsTemplateOnly: e.UseAsTemplateOnly,
FallbackToOnDemand: e.FallbackToOnDemand,
UtilizeReservedInstances: e.UtilizeReservedInstances,
UtilizeCommitments: e.UtilizeCommitments,
@ -1075,39 +1098,6 @@ func (_ *Ocean) RenderTerraform(t *terraform.TerraformTarget, a, e, changes *Oce
}
}
// User data.
if e.UserData != nil {
var err error
tf.UserData, err = t.AddFileResource("spotinst_ocean_aws", *e.Name, "user_data", e.UserData, false)
if err != nil {
return err
}
}
// Public IP.
if e.AssociatePublicIP != nil {
tf.AssociatePublicIPAddress = e.AssociatePublicIP
}
// Root volume options.
if opts := e.RootVolumeOpts; opts != nil {
// Volume size.
if opts.Size != nil {
tf.RootVolumeSize = opts.Size
}
// EBS optimization.
if opts.Optimization != nil {
tf.EBSOptimized = opts.Optimization
}
}
// IAM instance profile.
if e.IAMInstanceProfile != nil {
tf.IAMInstanceProfile = e.IAMInstanceProfile.TerraformLink()
}
// Monitoring.
if e.Monitoring != nil {
tf.Monitoring = e.Monitoring
@ -1175,8 +1165,46 @@ func (_ *Ocean) RenderTerraform(t *terraform.TerraformTarget, a, e, changes *Oce
}
}
// Tags.
{
if !fi.BoolValue(tf.UseAsTemplateOnly) {
// Capacity.
tf.DesiredCapacity = e.MinSize
tf.MinSize = e.MinSize
tf.MaxSize = e.MaxSize
// Root volume options.
if opts := e.RootVolumeOpts; opts != nil {
// Volume size.
if opts.Size != nil {
tf.RootVolumeSize = opts.Size
}
// EBS optimization.
if opts.Optimization != nil {
tf.EBSOptimized = opts.Optimization
}
}
// IAM instance profile.
if e.IAMInstanceProfile != nil {
tf.IAMInstanceProfile = e.IAMInstanceProfile.TerraformLink()
}
// User data.
if e.UserData != nil {
var err error
tf.UserData, err = t.AddFileResource("spotinst_ocean_aws", *e.Name, "user_data", e.UserData, false)
if err != nil {
return err
}
}
// Public IP.
if e.AssociatePublicIPAddress != nil {
tf.AssociatePublicIPAddress = e.AssociatePublicIPAddress
}
// Tags.
if e.Tags != nil {
for _, tag := range e.buildTags() {
tf.Tags = append(tf.Tags, &terraformKV{
@ -1206,17 +1234,3 @@ func (o *Ocean) buildTags() []*aws.Tag {
return tags
}
func (o *Ocean) applyDefaults() {
if o.FallbackToOnDemand == nil {
o.FallbackToOnDemand = fi.Bool(true)
}
if o.UtilizeReservedInstances == nil {
o.UtilizeReservedInstances = fi.Bool(true)
}
if o.Monitoring == nil {
o.Monitoring = fi.Bool(false)
}
}

View File

@ -423,35 +423,66 @@ type Task struct {
}
type Scaling struct {
Up []*ScalingPolicy `json:"up,omitempty"`
Down []*ScalingPolicy `json:"down,omitempty"`
Target []*ScalingPolicy `json:"target,omitempty"`
Up []*ScalingPolicy `json:"up,omitempty"`
Down []*ScalingPolicy `json:"down,omitempty"`
Target []*ScalingPolicy `json:"target,omitempty"`
MultipleMetrics *MultipleMetrics `json:"multipleMetrics,omitempty"`
forceSendFields []string
nullFields []string
}
type MultipleMetrics struct {
Metrics []*Metrics `json:"metrics,omitempty"`
Expressions []*Expressions `json:"expressions,omitempty"`
forceSendFields []string
nullFields []string
}
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"`
MaxCapacityPerScale *string `json:"maxCapacityPerScale,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"`
StepAdjustments []*StepAdjustment `json:"stepAdjustments,omitempty"`
forceSendFields []string
nullFields []string
}
type Metrics struct {
Name *string `json:"name,omitempty"`
MetricName *string `json:"metricName,omitempty"`
Namespace *string `json:"namespace,omitempty"`
Dimensions []*Dimension `json:"dimensions,omitempty"`
ExtendedStatistic *string `json:"extendedStatistic,omitempty"`
Statistic *string `json:"statistic,omitempty"`
Unit *string `json:"unit,omitempty"`
forceSendFields []string
nullFields []string
}
type Expressions struct {
Expression *string `json:"expression,omitempty"`
Name *string `json:"name,omitempty"`
forceSendFields []string
nullFields []string
@ -485,6 +516,14 @@ type Predictive struct {
nullFields []string
}
type StepAdjustment struct {
Action *Action `json:"action,omitempty"`
Threshold *int `json:"threshold,omitempty"`
forceSendFields []string
nullFields []string
}
type Strategy struct {
Risk *float64 `json:"risk,omitempty"`
OnDemandCount *int `json:"onDemandCount,omitempty"`
@ -600,26 +639,91 @@ type AvailabilityZone struct {
}
type LaunchSpecification struct {
LoadBalancerNames []string `json:"loadBalancerNames,omitempty"`
LoadBalancersConfig *LoadBalancersConfig `json:"loadBalancersConfig,omitempty"`
SecurityGroupIDs []string `json:"securityGroupIds,omitempty"`
HealthCheckType *string `json:"healthCheckType,omitempty"`
HealthCheckGracePeriod *int `json:"healthCheckGracePeriod,omitempty"`
HealthCheckUnhealthyDurationBeforeReplacement *int `json:"healthCheckUnhealthyDurationBeforeReplacement,omitempty"`
ImageID *string `json:"imageId,omitempty"`
KeyPair *string `json:"keyPair,omitempty"`
UserData *string `json:"userData,omitempty"`
ShutdownScript *string `json:"shutdownScript,omitempty"`
Tenancy *string `json:"tenancy,omitempty"`
Monitoring *bool `json:"monitoring,omitempty"`
EBSOptimized *bool `json:"ebsOptimized,omitempty"`
IAMInstanceProfile *IAMInstanceProfile `json:"iamRole,omitempty"`
CreditSpecification *CreditSpecification `json:"creditSpecification,omitempty"`
BlockDeviceMappings []*BlockDeviceMapping `json:"blockDeviceMappings,omitempty"`
NetworkInterfaces []*NetworkInterface `json:"networkInterfaces,omitempty"`
Tags []*Tag `json:"tags,omitempty"`
MetadataOptions *MetadataOptions `json:"metadataOptions,omitempty"`
CPUOptions *CPUOptions `json:"cpuOptions,omitempty"`
LoadBalancerNames []string `json:"loadBalancerNames,omitempty"`
LoadBalancersConfig *LoadBalancersConfig `json:"loadBalancersConfig,omitempty"`
SecurityGroupIDs []string `json:"securityGroupIds,omitempty"`
HealthCheckType *string `json:"healthCheckType,omitempty"`
HealthCheckGracePeriod *int `json:"healthCheckGracePeriod,omitempty"`
HealthCheckUnhealthyDurationBeforeReplacement *int `json:"healthCheckUnhealthyDurationBeforeReplacement,omitempty"`
ImageID *string `json:"imageId,omitempty"`
KeyPair *string `json:"keyPair,omitempty"`
UserData *string `json:"userData,omitempty"`
ShutdownScript *string `json:"shutdownScript,omitempty"`
Tenancy *string `json:"tenancy,omitempty"`
Monitoring *bool `json:"monitoring,omitempty"`
EBSOptimized *bool `json:"ebsOptimized,omitempty"`
IAMInstanceProfile *IAMInstanceProfile `json:"iamRole,omitempty"`
CreditSpecification *CreditSpecification `json:"creditSpecification,omitempty"`
BlockDeviceMappings []*BlockDeviceMapping `json:"blockDeviceMappings,omitempty"`
NetworkInterfaces []*NetworkInterface `json:"networkInterfaces,omitempty"`
Tags []*Tag `json:"tags,omitempty"`
MetadataOptions *MetadataOptions `json:"metadataOptions,omitempty"`
CPUOptions *CPUOptions `json:"cpuOptions,omitempty"`
ResourceTagSpecification *ResourceTagSpecification `json:"resourceTagSpecification,omitempty"`
ITF *ITF `json:"itf,omitempty"`
forceSendFields []string
nullFields []string
}
type ITF struct {
LoadBalancers []*ITFLoadBalancer `json:"loadBalancers,omitempty"`
MigrationHealthinessThreshold *int `json:"migrationHealthinessThreshold,omitempty"`
FixedTargetGroups *bool `json:"fixedTargetGroups,omitempty"`
WeightStrategy *string `json:"weightStrategy,omitempty"`
TargetGroupConfig *TargetGroupConfig `json:"targetGroupConfig,omitempty"`
DefaultStaticTargetGroups []*StaticTargetGroup `json:"defaultStaticTargetGroups,omitempty"`
forceSendFields []string
nullFields []string
}
type ITFLoadBalancer struct {
ListenerRules []*ListenerRule `json:"listenerRules,omitempty"`
LoadBalancerARN *string `json:"loadBalancerArn,omitempty"`
forceSendFields []string
nullFields []string
}
type ListenerRule struct {
RuleARN *string `json:"ruleArn,omitempty"`
StaticTargetGroups []*StaticTargetGroup `json:"staticTargetGroups,omitempty"`
forceSendFields []string
nullFields []string
}
type StaticTargetGroup struct {
StaticTargetGroupARN *string `json:"arn,omitempty"`
Percentage *float64 `json:"percentage,omitempty"`
forceSendFields []string
nullFields []string
}
type TargetGroupConfig struct {
VPCID *string `json:"vpcId,omitempty"`
HealthCheckIntervalSeconds *int `json:"healthCheckIntervalSeconds,omitempty"`
HealthCheckPath *string `json:"healthCheckPath,omitempty"`
HealthCheckPort *string `json:"healthCheckPort,omitempty"`
HealthCheckProtocol *string `json:"healthCheckProtocol,omitempty"`
HealthCheckTimeoutSeconds *int `json:"healthCheckTimeoutSeconds,omitempty"`
HealthyThresholdCount *int `json:"healthyThresholdCount,omitempty"`
UnhealthyThresholdCount *int `json:"unhealthyThresholdCount,omitempty"`
Port *int `json:"port,omitempty"`
Protocol *string `json:"protocol,omitempty"`
ProtocolVersion *string `json:"protocolVersion,omitempty"`
Matcher *Matcher `json:"matcher,omitempty"`
Tags []*Tag `json:"tags,omitempty"`
forceSendFields []string
nullFields []string
}
type Matcher struct {
HTTPCode *string `json:"httpCode,omitempty"`
GRPCCode *string `json:"grpcCode,omitempty"`
forceSendFields []string
nullFields []string
@ -640,6 +744,44 @@ type CPUOptions struct {
nullFields []string
}
type ResourceTagSpecification struct {
Volumes *Volumes `json:"volumes,omitempty"`
Snapshots *Snapshots `json:"snapshots,omitempty"`
ENIs *ENIs `json:"enis,omitempty"`
AMIs *AMIs `json:"amis,omitempty"`
forceSendFields []string
nullFields []string
}
type Volumes struct {
ShouldTag *bool `json:"shouldTag,omitempty"`
forceSendFields []string
nullFields []string
}
type Snapshots struct {
ShouldTag *bool `json:"shouldTag,omitempty"`
forceSendFields []string
nullFields []string
}
type ENIs struct {
ShouldTag *bool `json:"shouldTag,omitempty"`
forceSendFields []string
nullFields []string
}
type AMIs struct {
ShouldTag *bool `json:"shouldTag,omitempty"`
forceSendFields []string
nullFields []string
}
type LoadBalancersConfig struct {
LoadBalancers []*LoadBalancer `json:"loadBalancers,omitempty"`
@ -2918,6 +3060,13 @@ func (o *Scaling) SetTarget(v []*ScalingPolicy) *Scaling {
return o
}
func (o *Scaling) SetMultipleMetrics(v *MultipleMetrics) *Scaling {
if o.MultipleMetrics = v; o.MultipleMetrics == nil {
o.nullFields = append(o.nullFields, "MultipleMetrics")
}
return o
}
// endregion
// region ScalingPolicy
@ -3068,6 +3217,120 @@ func (o *ScalingPolicy) SetMaxCapacityPerScale(v *string) *ScalingPolicy {
return o
}
func (o *ScalingPolicy) SetStepAdjustments(v []*StepAdjustment) *ScalingPolicy {
if o.StepAdjustments = v; o.StepAdjustments == nil {
o.nullFields = append(o.nullFields, "StepAdjustments")
}
return o
}
// endregion
// region MultipleMetrics
func (o MultipleMetrics) MarshalJSON() ([]byte, error) {
type noMethod MultipleMetrics
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *MultipleMetrics) SetExpressions(v []*Expressions) *MultipleMetrics {
if o.Expressions = v; o.Expressions == nil {
o.nullFields = append(o.nullFields, "Expressions")
}
return o
}
func (o *MultipleMetrics) SetMetrics(v []*Metrics) *MultipleMetrics {
if o.Metrics = v; o.Metrics == nil {
o.nullFields = append(o.nullFields, "Metrics")
}
return o
}
// endregion
// region Metrics
func (o Metrics) MarshalJSON() ([]byte, error) {
type noMethod Metrics
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *Metrics) SetMetricName(v *string) *Metrics {
if o.MetricName = v; o.MetricName == nil {
o.nullFields = append(o.nullFields, "MetricName")
}
return o
}
func (o *Metrics) SetNamespace(v *string) *Metrics {
if o.Namespace = v; o.Namespace == nil {
o.nullFields = append(o.nullFields, "Namespace")
}
return o
}
func (o *Metrics) SetDimensions(v []*Dimension) *Metrics {
if o.Dimensions = v; o.Dimensions == nil {
o.nullFields = append(o.nullFields, "Dimensions")
}
return o
}
func (o *Metrics) SetName(v *string) *Metrics {
if o.Name = v; o.Name == nil {
o.nullFields = append(o.nullFields, "Name")
}
return o
}
func (o *Metrics) SetExtendedStatistic(v *string) *Metrics {
if o.ExtendedStatistic = v; o.ExtendedStatistic == nil {
o.nullFields = append(o.nullFields, "ExtendedStatistic")
}
return o
}
func (o *Metrics) SetStatistic(v *string) *Metrics {
if o.Statistic = v; o.Statistic == nil {
o.nullFields = append(o.nullFields, "Statistic")
}
return o
}
func (o *Metrics) SetUnit(v *string) *Metrics {
if o.Unit = v; o.Unit == nil {
o.nullFields = append(o.nullFields, "Unit")
}
return o
}
// endregion
// region Expression
func (o Expressions) MarshalJSON() ([]byte, error) {
type noMethod Expressions
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *Expressions) SetExpression(v *string) *Expressions {
if o.Expression = v; o.Expression == nil {
o.nullFields = append(o.nullFields, "Expression")
}
return o
}
func (o *Expressions) SetName(v *string) *Expressions {
if o.Name = v; o.Name == nil {
o.nullFields = append(o.nullFields, "Name")
}
return o
}
// endregion
// region Action
@ -3170,6 +3433,30 @@ func (o *Predictive) SetMode(v *string) *Predictive {
// endregion
// region StepAdjustments
func (o StepAdjustment) MarshalJSON() ([]byte, error) {
type noMethod StepAdjustment
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *StepAdjustment) SetAction(v *Action) *StepAdjustment {
if o.Action = v; o.Action == nil {
o.nullFields = append(o.nullFields, "Action")
}
return o
}
func (o *StepAdjustment) SetThreshold(v *int) *StepAdjustment {
if o.Threshold = v; o.Threshold == nil {
o.nullFields = append(o.nullFields, "Threshold")
}
return o
}
// endregion
// region Strategy
func (o Strategy) MarshalJSON() ([]byte, error) {
@ -3766,6 +4053,267 @@ func (o *LaunchSpecification) SetCPUOptions(v *CPUOptions) *LaunchSpecification
return o
}
func (o *LaunchSpecification) SetResourceTagSpecification(v *ResourceTagSpecification) *LaunchSpecification {
if o.ResourceTagSpecification = v; o.ResourceTagSpecification == nil {
o.nullFields = append(o.nullFields, "ResourceTagSpecification")
}
return o
}
func (o *LaunchSpecification) SetITF(v *ITF) *LaunchSpecification {
if o.ITF = v; o.ITF == nil {
o.nullFields = append(o.nullFields, "ITF")
}
return o
}
// endregion
// region Matcher
func (o Matcher) MarshalJSON() ([]byte, error) {
type noMethod Matcher
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *Matcher) SetHTTPCode(v *string) *Matcher {
if o.HTTPCode = v; o.HTTPCode == nil {
o.nullFields = append(o.nullFields, "HTTPCode")
}
return o
}
func (o *Matcher) SetGRPCCode(v *string) *Matcher {
if o.GRPCCode = v; o.GRPCCode == nil {
o.nullFields = append(o.nullFields, "GRPCCode")
}
return o
}
// endregion
// region ITF
func (o ITF) MarshalJSON() ([]byte, error) {
type noMethod ITF
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *ITF) SetLoadBalancers(v []*ITFLoadBalancer) *ITF {
if o.LoadBalancers = v; o.LoadBalancers == nil {
o.nullFields = append(o.nullFields, "LoadBalancers")
}
return o
}
func (o *ITF) SetMigrationHealthinessThreshold(v *int) *ITF {
if o.MigrationHealthinessThreshold = v; o.MigrationHealthinessThreshold == nil {
o.nullFields = append(o.nullFields, "MigrationHealthinessThreshold")
}
return o
}
func (o *ITF) SetFixedTargetGroups(v *bool) *ITF {
if o.FixedTargetGroups = v; o.FixedTargetGroups == nil {
o.nullFields = append(o.nullFields, "FixedTargetGroups")
}
return o
}
func (o *ITF) SetWeightStrategy(v *string) *ITF {
if o.WeightStrategy = v; o.WeightStrategy == nil {
o.nullFields = append(o.nullFields, "WeightStrategy")
}
return o
}
func (o *ITF) SetTargetGroupConfig(v *TargetGroupConfig) *ITF {
if o.TargetGroupConfig = v; o.TargetGroupConfig == nil {
o.nullFields = append(o.nullFields, "TargetGroupConfig")
}
return o
}
func (o *ITF) SetDefaultStaticTargetGroups(v []*StaticTargetGroup) *ITF {
if o.DefaultStaticTargetGroups = v; o.DefaultStaticTargetGroups == nil {
o.nullFields = append(o.nullFields, "DefaultStaticTargetGroups")
}
return o
}
// endregion
// region ITFLoadBalancer
func (o ITFLoadBalancer) MarshalJSON() ([]byte, error) {
type noMethod ITFLoadBalancer
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *ITFLoadBalancer) SetListenerRules(v []*ListenerRule) *ITFLoadBalancer {
if o.ListenerRules = v; o.ListenerRules == nil {
o.nullFields = append(o.nullFields, "ListenerRules")
}
return o
}
func (o *ITFLoadBalancer) SetLoadBalancerARN(v *string) *ITFLoadBalancer {
if o.LoadBalancerARN = v; o.LoadBalancerARN == nil {
o.nullFields = append(o.nullFields, "LoadBalancerARN")
}
return o
}
// endregion
// region ListenerRule
func (o ListenerRule) MarshalJSON() ([]byte, error) {
type noMethod ListenerRule
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *ListenerRule) SetRuleARN(v *string) *ListenerRule {
if o.RuleARN = v; o.RuleARN == nil {
o.nullFields = append(o.nullFields, "RuleARN")
}
return o
}
func (o *ListenerRule) SetStaticTargetGroups(v []*StaticTargetGroup) *ListenerRule {
if o.StaticTargetGroups = v; o.StaticTargetGroups == nil {
o.nullFields = append(o.nullFields, "StaticTargetGroups")
}
return o
}
// endregion
// region StaticTargetGroup
func (o StaticTargetGroup) MarshalJSON() ([]byte, error) {
type noMethod StaticTargetGroup
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *StaticTargetGroup) SetStaticTargetGroupARN(v *string) *StaticTargetGroup {
if o.StaticTargetGroupARN = v; o.StaticTargetGroupARN == nil {
o.nullFields = append(o.nullFields, "StaticTargetGroupARN")
}
return o
}
func (o *StaticTargetGroup) SetPercentage(v *float64) *StaticTargetGroup {
if o.Percentage = v; o.Percentage == nil {
o.nullFields = append(o.nullFields, "Percentage")
}
return o
}
// region TargetGroupConfig
func (o TargetGroupConfig) MarshalJSON() ([]byte, error) {
type noMethod TargetGroupConfig
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *TargetGroupConfig) SetVPCId(v *string) *TargetGroupConfig {
if o.VPCID = v; o.VPCID == nil {
o.nullFields = append(o.nullFields, "VPCID")
}
return o
}
func (o *TargetGroupConfig) SetHealthCheckIntervalSeconds(v *int) *TargetGroupConfig {
if o.HealthCheckIntervalSeconds = v; o.HealthCheckIntervalSeconds == nil {
o.nullFields = append(o.nullFields, "HealthCheckIntervalSeconds")
}
return o
}
func (o *TargetGroupConfig) SetHealthCheckPath(v *string) *TargetGroupConfig {
if o.HealthCheckPath = v; o.HealthCheckPath == nil {
o.nullFields = append(o.nullFields, "HealthCheckPath")
}
return o
}
func (o *TargetGroupConfig) SetHealthCheckPort(v *string) *TargetGroupConfig {
if o.HealthCheckPort = v; o.HealthCheckPort == nil {
o.nullFields = append(o.nullFields, "HealthCheckPort")
}
return o
}
func (o *TargetGroupConfig) SetHealthCheckProtocol(v *string) *TargetGroupConfig {
if o.HealthCheckProtocol = v; o.HealthCheckProtocol == nil {
o.nullFields = append(o.nullFields, "HealthCheckProtocol")
}
return o
}
func (o *TargetGroupConfig) SetHealthyThresholdCount(v *int) *TargetGroupConfig {
if o.HealthyThresholdCount = v; o.HealthyThresholdCount == nil {
o.nullFields = append(o.nullFields, "HealthyThresholdCount")
}
return o
}
func (o *TargetGroupConfig) SetUnhealthyThresholdCount(v *int) *TargetGroupConfig {
if o.UnhealthyThresholdCount = v; o.UnhealthyThresholdCount == nil {
o.nullFields = append(o.nullFields, "UnhealthyThresholdCount")
}
return o
}
func (o *TargetGroupConfig) SetHealthCheckTimeoutSeconds(v *int) *TargetGroupConfig {
if o.HealthCheckTimeoutSeconds = v; o.HealthCheckTimeoutSeconds == nil {
o.nullFields = append(o.nullFields, "HealthCheckTimeoutSeconds")
}
return o
}
func (o *TargetGroupConfig) SetPort(v *int) *TargetGroupConfig {
if o.Port = v; o.Port == nil {
o.nullFields = append(o.nullFields, "Port")
}
return o
}
func (o *TargetGroupConfig) SetProtocol(v *string) *TargetGroupConfig {
if o.Protocol = v; o.Protocol == nil {
o.nullFields = append(o.nullFields, "Protocol")
}
return o
}
func (o *TargetGroupConfig) SetProtocolVersion(v *string) *TargetGroupConfig {
if o.ProtocolVersion = v; o.ProtocolVersion == nil {
o.nullFields = append(o.nullFields, "ProtocolVersion")
}
return o
}
func (o *TargetGroupConfig) SetMatcher(v *Matcher) *TargetGroupConfig {
if o.Matcher = v; o.Matcher == nil {
o.nullFields = append(o.nullFields, "Matcher")
}
return o
}
func (o *TargetGroupConfig) SetTags(v []*Tag) *TargetGroupConfig {
if o.Tags = v; o.Tags == nil {
o.nullFields = append(o.nullFields, "Tags")
}
return o
}
// endregion
// region LoadBalancersConfig
@ -4631,3 +5179,109 @@ func (o *Device) SetSnapshotID(v *string) *Device {
}
// endregion
// region ResourceTagSpecification
func (o ResourceTagSpecification) MarshalJSON() ([]byte, error) {
type noMethod ResourceTagSpecification
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *ResourceTagSpecification) SetVolumes(v *Volumes) *ResourceTagSpecification {
if o.Volumes = v; o.Volumes == nil {
o.nullFields = append(o.nullFields, "Volumes")
}
return o
}
func (o *ResourceTagSpecification) SetSnapshots(v *Snapshots) *ResourceTagSpecification {
if o.Snapshots = v; o.Snapshots == nil {
o.nullFields = append(o.nullFields, "Snapshots")
}
return o
}
func (o *ResourceTagSpecification) SetENIs(v *ENIs) *ResourceTagSpecification {
if o.ENIs = v; o.ENIs == nil {
o.nullFields = append(o.nullFields, "ENIs")
}
return o
}
func (o *ResourceTagSpecification) SetAMIs(v *AMIs) *ResourceTagSpecification {
if o.AMIs = v; o.AMIs == nil {
o.nullFields = append(o.nullFields, "AMIs")
}
return o
}
// endregion
// region Volumes
func (o Volumes) MarshalJSON() ([]byte, error) {
type noMethod Volumes
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *Volumes) SetShouldTag(v *bool) *Volumes {
if o.ShouldTag = v; o.ShouldTag == nil {
o.nullFields = append(o.nullFields, "ShouldTag")
}
return o
}
// endregion
// region Snapshots
func (o Snapshots) MarshalJSON() ([]byte, error) {
type noMethod Snapshots
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *Snapshots) SetShouldTag(v *bool) *Snapshots {
if o.ShouldTag = v; o.ShouldTag == nil {
o.nullFields = append(o.nullFields, "ShouldTag")
}
return o
}
// endregion
// region ENIs
func (o ENIs) MarshalJSON() ([]byte, error) {
type noMethod ENIs
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *ENIs) SetShouldTag(v *bool) *ENIs {
if o.ShouldTag = v; o.ShouldTag == nil {
o.nullFields = append(o.nullFields, "ShouldTag")
}
return o
}
// endregion
// region AMIs
func (o AMIs) MarshalJSON() ([]byte, error) {
type noMethod AMIs
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *AMIs) SetShouldTag(v *bool) *AMIs {
if o.ShouldTag = v; o.ShouldTag == nil {
o.nullFields = append(o.nullFields, "ShouldTag")
}
return o
}
// endregion

View File

@ -80,9 +80,31 @@ type VMSizes struct {
}
type LaunchSpecification struct {
Image *Image `json:"image,omitempty"`
Network *Network `json:"network,omitempty"`
Login *Login `json:"login,omitempty"`
Image *Image `json:"image,omitempty"`
Network *Network `json:"network,omitempty"`
Login *Login `json:"login,omitempty"`
CustomData *string `json:"customData,omitempty"`
ManagedServiceIdentities []*ManagedServiceIdentity `json:"managedServiceIdentities,omitempty"`
LoadBalancersConfig *LoadBalancersConfig `json:"loadBalancersConfig,omitempty"`
ShutdownScript *string `json:"shutdownScript,omitempty"`
forceSendFields []string
nullFields []string
}
type LoadBalancersConfig struct {
LoadBalancers []*LoadBalancer `json:"loadBalancers,omitempty"`
forceSendFields []string
nullFields []string
}
type LoadBalancer struct {
Type *string `json:"type,omitempty"`
ResourceGroupName *string `json:"resourceGroupName,omitempty"`
Name *string `json:"name,omitempty"`
SKU *string `json:"sku,omitempty"`
BackendPoolNames []string `json:"backendPoolNames,omitempty"`
forceSendFields []string
nullFields []string
@ -124,10 +146,11 @@ type Network struct {
}
type NetworkInterface struct {
SubnetName *string `json:"subnetName,omitempty"`
AssignPublicIP *bool `json:"assignPublicIp,omitempty"`
IsPrimary *bool `json:"isPrimary,omitempty"`
AdditionalIPConfigs []*AdditionalIPConfig `json:"additionalIpConfigurations,omitempty"`
SubnetName *string `json:"subnetName,omitempty"`
AssignPublicIP *bool `json:"assignPublicIp,omitempty"`
IsPrimary *bool `json:"isPrimary,omitempty"`
AdditionalIPConfigs []*AdditionalIPConfig `json:"additionalIpConfigurations,omitempty"`
ApplicationSecurityGroups []*ApplicationSecurityGroup `json:"applicationSecurityGroups,omitempty"`
forceSendFields []string
nullFields []string
@ -150,6 +173,22 @@ type Login struct {
nullFields []string
}
type ApplicationSecurityGroup struct {
Name *string `json:"name,omitempty"`
ResourceGroupName *string `json:"resourceGroupName,omitempty"`
forceSendFields []string
nullFields []string
}
type ManagedServiceIdentity struct {
ResourceGroupName *string `json:"resourceGroupName,omitempty"`
Name *string `json:"name,omitempty"`
forceSendFields []string
nullFields []string
}
type CreateGroupInput struct {
Group *Group `json:"group,omitempty"`
}
@ -559,6 +598,35 @@ func (o *LaunchSpecification) SetLogin(v *Login) *LaunchSpecification {
return o
}
func (o *LaunchSpecification) SetCustomData(v *string) *LaunchSpecification {
if o.CustomData = v; o.CustomData == nil {
o.nullFields = append(o.nullFields, "CustomData")
}
return o
}
func (o *LaunchSpecification) SetManagedServiceIdentities(v []*ManagedServiceIdentity) *LaunchSpecification {
if o.ManagedServiceIdentities = v; o.ManagedServiceIdentities == nil {
o.nullFields = append(o.nullFields, "ManagedServiceIdentities")
}
return o
}
func (o *LaunchSpecification) SetLoadBalancersConfig(v *LoadBalancersConfig) *LaunchSpecification {
if o.LoadBalancersConfig = v; o.LoadBalancersConfig == nil {
o.nullFields = append(o.nullFields, "LoadBalancersConfig")
}
return o
}
// SetShutdownScript sets the shutdown script used when draining instances
func (o *LaunchSpecification) SetShutdownScript(v *string) *LaunchSpecification {
if o.ShutdownScript = v; o.ShutdownScript == nil {
o.nullFields = append(o.nullFields, "ShutdownScript")
}
return o
}
// endregion
// region Image
@ -714,6 +782,13 @@ func (o *NetworkInterface) SetIsPrimary(v *bool) *NetworkInterface {
return o
}
func (o *NetworkInterface) SetApplicationSecurityGroups(v []*ApplicationSecurityGroup) *NetworkInterface {
if o.ApplicationSecurityGroups = v; o.ApplicationSecurityGroups == nil {
o.nullFields = append(o.nullFields, "ApplicationSecurityGroups")
}
return o
}
// endregion
// region AdditionalIPConfig
@ -724,7 +799,6 @@ func (o AdditionalIPConfig) MarshalJSON() ([]byte, error) {
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
// SetName sets the name
func (o *AdditionalIPConfig) SetName(v *string) *AdditionalIPConfig {
if o.Name = v; o.Name == nil {
o.nullFields = append(o.nullFields, "Name")
@ -732,7 +806,6 @@ func (o *AdditionalIPConfig) SetName(v *string) *AdditionalIPConfig {
return o
}
// SetPrivateIPAddressVersion sets the ip address version
func (o *AdditionalIPConfig) SetPrivateIPAddressVersion(v *string) *AdditionalIPConfig {
if o.PrivateIPAddressVersion = v; o.PrivateIPAddressVersion == nil {
o.nullFields = append(o.nullFields, "PrivateIPAddressVersion")
@ -772,3 +845,113 @@ func (o *Login) SetPassword(v *string) *Login {
}
// endregion
// region ApplicationSecurityGroup
func (o ApplicationSecurityGroup) MarshalJSON() ([]byte, error) {
type noMethod ApplicationSecurityGroup
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *ApplicationSecurityGroup) SetName(v *string) *ApplicationSecurityGroup {
if o.Name = v; o.Name == nil {
o.nullFields = append(o.nullFields, "Name")
}
return o
}
func (o *ApplicationSecurityGroup) SetResourceGroupName(v *string) *ApplicationSecurityGroup {
if o.ResourceGroupName = v; o.ResourceGroupName == nil {
o.nullFields = append(o.nullFields, "ResourceGroupName")
}
return o
}
// endregion
// region ManagedServiceIdentity
func (o ManagedServiceIdentity) MarshalJSON() ([]byte, error) {
type noMethod ManagedServiceIdentity
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *ManagedServiceIdentity) SetResourceGroupName(v *string) *ManagedServiceIdentity {
if o.ResourceGroupName = v; o.ResourceGroupName == nil {
o.nullFields = append(o.nullFields, "ResourceGroupName")
}
return o
}
func (o *ManagedServiceIdentity) SetName(v *string) *ManagedServiceIdentity {
if o.Name = v; o.Name == nil {
o.nullFields = append(o.nullFields, "Name")
}
return o
}
// endregion
// region LoadBalancersConfig
func (o LoadBalancersConfig) MarshalJSON() ([]byte, error) {
type noMethod LoadBalancersConfig
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *LoadBalancersConfig) SetLoadBalancers(v []*LoadBalancer) *LoadBalancersConfig {
if o.LoadBalancers = v; o.LoadBalancers == nil {
o.nullFields = append(o.nullFields, "LoadBalancers")
}
return o
}
// endregion
// region LoadBalancer
func (o LoadBalancer) MarshalJSON() ([]byte, error) {
type noMethod LoadBalancer
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *LoadBalancer) SetType(v *string) *LoadBalancer {
if o.Type = v; o.Type == nil {
o.nullFields = append(o.nullFields, "Type")
}
return o
}
func (o *LoadBalancer) SetResourceGroupName(v *string) *LoadBalancer {
if o.ResourceGroupName = v; o.ResourceGroupName == nil {
o.nullFields = append(o.nullFields, "ResourceGroupName")
}
return o
}
func (o *LoadBalancer) SetName(v *string) *LoadBalancer {
if o.Name = v; o.Name == nil {
o.nullFields = append(o.nullFields, "Name")
}
return o
}
func (o *LoadBalancer) SetSKU(v *string) *LoadBalancer {
if o.SKU = v; o.SKU == nil {
o.nullFields = append(o.nullFields, "SKU")
}
return o
}
func (o *LoadBalancer) SeBackendPoolNames(v []string) *LoadBalancer {
if o.BackendPoolNames = v; o.BackendPoolNames == nil {
o.nullFields = append(o.nullFields, "BackendPoolNames")
}
return o
}
// endregion

View File

@ -370,10 +370,11 @@ type ScalingPolicy struct {
// Strategy defines the strategy attributes of a Group.
type Strategy struct {
DrainingTimeout *int `json:"drainingTimeout,omitempty"`
FallbackToOnDemand *bool `json:"fallbackToOd,omitempty"`
PreemptiblePercentage *int `json:"preemptiblePercentage,omitempty"`
OnDemandCount *int `json:"onDemandCount,omitempty"`
DrainingTimeout *int `json:"drainingTimeout,omitempty"`
FallbackToOnDemand *bool `json:"fallbackToOd,omitempty"`
PreemptiblePercentage *int `json:"preemptiblePercentage,omitempty"`
OnDemandCount *int `json:"onDemandCount,omitempty"`
ProvisioningModel *string `json:"provisioningModel,omitempty"`
forceSendFields []string
nullFields []string
@ -2164,4 +2165,11 @@ func (o *Strategy) SetOnDemandCount(v *int) *Strategy {
return o
}
func (o *Strategy) SetProvisioningModel(v *string) *Strategy {
if o.ProvisioningModel = v; o.ProvisioningModel == nil {
o.nullFields = append(o.nullFields, "ProvisioningModel")
}
return o
}
// endregion

View File

@ -24,6 +24,7 @@ type Cluster struct {
Compute *Compute `json:"compute,omitempty"`
Scheduling *Scheduling `json:"scheduling,omitempty"`
AutoScaler *AutoScaler `json:"autoScaler,omitempty"`
Logging *Logging `json:"logging,omitempty"`
// Read-only fields.
CreatedAt *time.Time `json:"createdAt,omitempty"`
@ -110,18 +111,19 @@ type InstanceTypes struct {
}
type LaunchSpecification struct {
AssociatePublicIPAddress *bool `json:"associatePublicIpAddress,omitempty"`
SecurityGroupIDs []string `json:"securityGroupIds,omitempty"`
ImageID *string `json:"imageId,omitempty"`
KeyPair *string `json:"keyPair,omitempty"`
UserData *string `json:"userData,omitempty"`
IAMInstanceProfile *IAMInstanceProfile `json:"iamInstanceProfile,omitempty"`
Tags []*Tag `json:"tags,omitempty"`
LoadBalancers []*LoadBalancer `json:"loadBalancers,omitempty"`
RootVolumeSize *int `json:"rootVolumeSize,omitempty"`
Monitoring *bool `json:"monitoring,omitempty"`
EBSOptimized *bool `json:"ebsOptimized,omitempty"`
UseAsTemplateOnly *bool `json:"useAsTemplateOnly,omitempty"`
AssociatePublicIPAddress *bool `json:"associatePublicIpAddress,omitempty"`
SecurityGroupIDs []string `json:"securityGroupIds,omitempty"`
ImageID *string `json:"imageId,omitempty"`
KeyPair *string `json:"keyPair,omitempty"`
UserData *string `json:"userData,omitempty"`
IAMInstanceProfile *IAMInstanceProfile `json:"iamInstanceProfile,omitempty"`
Tags []*Tag `json:"tags,omitempty"`
LoadBalancers []*LoadBalancer `json:"loadBalancers,omitempty"`
RootVolumeSize *int `json:"rootVolumeSize,omitempty"`
Monitoring *bool `json:"monitoring,omitempty"`
EBSOptimized *bool `json:"ebsOptimized,omitempty"`
UseAsTemplateOnly *bool `json:"useAsTemplateOnly,omitempty"`
InstanceMetadataOptions *InstanceMetadataOptions `json:"instanceMetadataOptions,omitempty"`
forceSendFields []string
nullFields []string
@ -145,13 +147,15 @@ type LoadBalancer struct {
}
type AutoScaler struct {
IsEnabled *bool `json:"isEnabled,omitempty"`
IsAutoConfig *bool `json:"isAutoConfig,omitempty"`
Cooldown *int `json:"cooldown,omitempty"`
AutoHeadroomPercentage *int `json:"autoHeadroomPercentage,omitempty"`
Headroom *AutoScalerHeadroom `json:"headroom,omitempty"`
ResourceLimits *AutoScalerResourceLimits `json:"resourceLimits,omitempty"`
Down *AutoScalerDown `json:"down,omitempty"`
IsEnabled *bool `json:"isEnabled,omitempty"`
IsAutoConfig *bool `json:"isAutoConfig,omitempty"`
Cooldown *int `json:"cooldown,omitempty"`
AutoHeadroomPercentage *int `json:"autoHeadroomPercentage,omitempty"`
Headroom *AutoScalerHeadroom `json:"headroom,omitempty"`
ResourceLimits *AutoScalerResourceLimits `json:"resourceLimits,omitempty"`
Down *AutoScalerDown `json:"down,omitempty"`
EnableAutomaticAndManualHeadroom *bool `json:"enableAutomaticAndManualHeadroom,omitempty"`
ExtendedResourceDefinitions []string `json:"extendedResourceDefinitions,omitempty"`
forceSendFields []string
nullFields []string
@ -183,6 +187,35 @@ type AutoScalerDown struct {
nullFields []string
}
type InstanceMetadataOptions struct {
HTTPTokens *string `json:"httpTokens,omitempty"`
HTTPPutResponseHopLimit *int `json:"httpPutResponseHopLimit,omitempty"`
forceSendFields []string
nullFields []string
}
type Logging struct {
Export *Export `json:"export,omitempty"`
forceSendFields []string
nullFields []string
}
type Export struct {
S3 *S3 `json:"s3,omitempty"`
forceSendFields []string
nullFields []string
}
type S3 struct {
ID *string `json:"id,omitempty"`
forceSendFields []string
nullFields []string
}
type ListClustersInput struct{}
type ListClustersOutput struct {
@ -872,6 +905,13 @@ func (o *Cluster) SetAutoScaler(v *AutoScaler) *Cluster {
return o
}
func (o *Cluster) SetLogging(v *Logging) *Cluster {
if o.Logging = v; o.Logging == nil {
o.nullFields = append(o.nullFields, "Logging")
}
return o
}
// endregion
// region Strategy
@ -1183,6 +1223,13 @@ func (o *LaunchSpecification) SetUseAsTemplateOnly(v *bool) *LaunchSpecification
return o
}
func (o *LaunchSpecification) SetInstanceMetadataOptions(v *InstanceMetadataOptions) *LaunchSpecification {
if o.InstanceMetadataOptions = v; o.InstanceMetadataOptions == nil {
o.nullFields = append(o.nullFields, "InstanceMetadataOptions")
}
return o
}
// endregion
// region LoadBalancer
@ -1291,6 +1338,20 @@ func (o *AutoScaler) SetDown(v *AutoScalerDown) *AutoScaler {
return o
}
func (o *AutoScaler) SetEnableAutomaticAndManualHeadroom(v *bool) *AutoScaler {
if o.EnableAutomaticAndManualHeadroom = v; o.EnableAutomaticAndManualHeadroom == nil {
o.nullFields = append(o.nullFields, "EnableAutomaticAndManualHeadroom")
}
return o
}
func (o *AutoScaler) SetExtendedResourceDefinitions(v []string) *AutoScaler {
if o.ExtendedResourceDefinitions = v; o.ExtendedResourceDefinitions == nil {
o.nullFields = append(o.nullFields, "ExtendedResourceDefinitions")
}
return o
}
// endregion
// region AutoScalerHeadroom
@ -1475,3 +1536,78 @@ func (o *RollSpec) SetInstanceIDs(v []string) *RollSpec {
}
// endregion
// region InstanceMetadataOptions
func (o InstanceMetadataOptions) MarshalJSON() ([]byte, error) {
type noMethod InstanceMetadataOptions
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *InstanceMetadataOptions) SetHTTPTokens(v *string) *InstanceMetadataOptions {
if o.HTTPTokens = v; o.HTTPTokens == nil {
o.nullFields = append(o.nullFields, "HTTPTokens")
}
return o
}
func (o *InstanceMetadataOptions) SetHTTPPutResponseHopLimit(v *int) *InstanceMetadataOptions {
if o.HTTPPutResponseHopLimit = v; o.HTTPPutResponseHopLimit == nil {
o.nullFields = append(o.nullFields, "HTTPPutResponseHopLimit")
}
return o
}
// endregion
// region Logging
func (o Logging) MarshalJSON() ([]byte, error) {
type noMethod Logging
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *Logging) SetExport(v *Export) *Logging {
if o.Export = v; o.Export == nil {
o.nullFields = append(o.nullFields, "Export")
}
return o
}
// endregion
// region Export
func (o Export) MarshalJSON() ([]byte, error) {
type noMethod Export
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *Export) SetS3(v *S3) *Export {
if o.S3 = v; o.S3 == nil {
o.nullFields = append(o.nullFields, "S3")
}
return o
}
// endregion
// region S3
func (o S3) MarshalJSON() ([]byte, error) {
type noMethod S3
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *S3) SetId(v *string) *S3 {
if o.ID = v; o.ID == nil {
o.nullFields = append(o.nullFields, "ID")
}
return o
}
// endregion

View File

@ -49,6 +49,7 @@ type ECSStrategy struct {
DrainingTimeout *int `json:"drainingTimeout,omitempty"`
UtilizeReservedInstances *bool `json:"utilizeReservedInstances,omitempty"`
UtilizeCommitments *bool `json:"utilizeCommitments,omitempty"`
SpotPercentage *int `json:"spotPercentage,omitempty"`
forceSendFields []string
nullFields []string
@ -106,16 +107,17 @@ type ECSInstanceTypes struct {
}
type ECSLaunchSpecification struct {
AssociatePublicIPAddress *bool `json:"associatePublicIpAddress,omitempty"`
SecurityGroupIDs []string `json:"securityGroupIds,omitempty"`
ImageID *string `json:"imageId,omitempty"`
KeyPair *string `json:"keyPair,omitempty"`
UserData *string `json:"userData,omitempty"`
IAMInstanceProfile *ECSIAMInstanceProfile `json:"iamInstanceProfile,omitempty"`
Tags []*Tag `json:"tags,omitempty"`
Monitoring *bool `json:"monitoring,omitempty"`
EBSOptimized *bool `json:"ebsOptimized,omitempty"`
BlockDeviceMappings []*ECSBlockDeviceMapping `json:"blockDeviceMappings,omitempty"`
AssociatePublicIPAddress *bool `json:"associatePublicIpAddress,omitempty"`
SecurityGroupIDs []string `json:"securityGroupIds,omitempty"`
ImageID *string `json:"imageId,omitempty"`
KeyPair *string `json:"keyPair,omitempty"`
UserData *string `json:"userData,omitempty"`
IAMInstanceProfile *ECSIAMInstanceProfile `json:"iamInstanceProfile,omitempty"`
Tags []*Tag `json:"tags,omitempty"`
Monitoring *bool `json:"monitoring,omitempty"`
EBSOptimized *bool `json:"ebsOptimized,omitempty"`
BlockDeviceMappings []*ECSBlockDeviceMapping `json:"blockDeviceMappings,omitempty"`
InstanceMetadataOptions *ECSInstanceMetadataOptions `json:"instanceMetadataOptions,omitempty"`
forceSendFields []string
nullFields []string
@ -139,12 +141,13 @@ type ECSIAMInstanceProfile struct {
}
type ECSAutoScaler struct {
IsEnabled *bool `json:"isEnabled,omitempty"`
IsAutoConfig *bool `json:"isAutoConfig,omitempty"`
Cooldown *int `json:"cooldown,omitempty"`
Headroom *ECSAutoScalerHeadroom `json:"headroom,omitempty"`
ResourceLimits *ECSAutoScalerResourceLimits `json:"resourceLimits,omitempty"`
Down *ECSAutoScalerDown `json:"down,omitempty"`
IsEnabled *bool `json:"isEnabled,omitempty"`
IsAutoConfig *bool `json:"isAutoConfig,omitempty"`
Cooldown *int `json:"cooldown,omitempty"`
Headroom *ECSAutoScalerHeadroom `json:"headroom,omitempty"`
ResourceLimits *ECSAutoScalerResourceLimits `json:"resourceLimits,omitempty"`
Down *ECSAutoScalerDown `json:"down,omitempty"`
AutoHeadroomPercentage *int `json:"autoHeadroomPercentage,omitempty"`
forceSendFields []string
nullFields []string
@ -245,6 +248,14 @@ type ECSProgress struct {
Value *int `json:"value,omitempty"`
}
type ECSInstanceMetadataOptions struct {
HTTPTokens *string `json:"httpTokens,omitempty"`
HTTPPutResponseHopLimit *int `json:"httpPutResponseHopLimit,omitempty"`
forceSendFields []string
nullFields []string
}
func ecsClusterFromJSON(in []byte) (*ECSCluster, error) {
b := new(ECSCluster)
if err := json.Unmarshal(in, b); err != nil {
@ -713,6 +724,13 @@ func (o *ECSStrategy) SetUtilizeCommitments(v *bool) *ECSStrategy {
return o
}
func (o *ECSStrategy) SetSpotPercentage(v *int) *ECSStrategy {
if o.SpotPercentage = v; o.SpotPercentage == nil {
o.nullFields = append(o.nullFields, "SpotPercentage")
}
return o
}
// endregion
// region InstanceTypes
@ -810,6 +828,13 @@ func (o *ECSLaunchSpecification) SetBlockDeviceMappings(v []*ECSBlockDeviceMappi
return o
}
func (o *ECSLaunchSpecification) SetInstanceMetadataOptions(v *ECSInstanceMetadataOptions) *ECSLaunchSpecification {
if o.InstanceMetadataOptions = v; o.InstanceMetadataOptions == nil {
o.nullFields = append(o.nullFields, "InstanceMetadataOptions")
}
return o
}
// endregion
// region ECSOptimizeImages
@ -917,6 +942,13 @@ func (o *ECSAutoScaler) SetDown(v *ECSAutoScalerDown) *ECSAutoScaler {
return o
}
func (o *ECSAutoScaler) SetAutoHeadroomPercentage(v *int) *ECSAutoScaler {
if o.AutoHeadroomPercentage = v; o.AutoHeadroomPercentage == nil {
o.nullFields = append(o.nullFields, "AutoHeadroomPercentage")
}
return o
}
// endregion
// region AutoScalerHeadroom
@ -1028,3 +1060,27 @@ func (o *ECSRoll) SetInstanceIDs(v []string) *ECSRoll {
}
// endregion
// region InstanceMetadataOptions
func (o ECSInstanceMetadataOptions) MarshalJSON() ([]byte, error) {
type noMethod ECSInstanceMetadataOptions
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *ECSInstanceMetadataOptions) SetHTTPTokens(v *string) *ECSInstanceMetadataOptions {
if o.HTTPTokens = v; o.HTTPTokens == nil {
o.nullFields = append(o.nullFields, "HTTPTokens")
}
return o
}
func (o *ECSInstanceMetadataOptions) SetHTTPPutResponseHopLimit(v *int) *ECSInstanceMetadataOptions {
if o.HTTPPutResponseHopLimit = v; o.HTTPPutResponseHopLimit == nil {
o.nullFields = append(o.nullFields, "HTTPPutResponseHopLimit")
}
return o
}
// endregion

View File

@ -5,6 +5,7 @@ import (
"encoding/json"
"io/ioutil"
"net/http"
"strconv"
"time"
"github.com/spotinst/spotinst-sdk-go/spotinst"
@ -23,6 +24,7 @@ type LaunchSpec struct {
SecurityGroupIDs []string `json:"securityGroupIds,omitempty"`
SubnetIDs []string `json:"subnetIds,omitempty"`
InstanceTypes []string `json:"instanceTypes,omitempty"`
PreferredSpotTypes []string `json:"preferredSpotTypes,omitempty"`
Strategy *LaunchSpecStrategy `json:"strategy,omitempty"`
ResourceLimits *ResourceLimits `json:"resourceLimits,omitempty"`
IAMInstanceProfile *IAMInstanceProfile `json:"iamInstanceProfile,omitempty"`
@ -34,6 +36,7 @@ type LaunchSpec struct {
Tags []*Tag `json:"tags,omitempty"`
AssociatePublicIPAddress *bool `json:"associatePublicIpAddress,omitempty"`
RestrictScaleDown *bool `json:"restrictScaleDown,omitempty"`
LaunchSpecScheduling *LaunchSpecScheduling `json:"scheduling,omitempty"`
// Read-only fields.
CreatedAt *time.Time `json:"createdAt,omitempty"`
@ -58,6 +61,7 @@ type LaunchSpec struct {
type ResourceLimits struct {
MaxInstanceCount *int `json:"maxInstanceCount,omitempty"`
MinInstanceCount *int `json:"minInstanceCount,omitempty"`
forceSendFields []string
nullFields []string
@ -153,6 +157,49 @@ type LaunchSpecStrategy struct {
nullFields []string
}
type LaunchSpecScheduling struct {
Tasks []*LaunchSpecTask `json:"tasks,omitempty"`
ShutdownHours *LaunchSpecShutdownHours `json:"shutdownHours,omitempty"`
forceSendFields []string
nullFields []string
}
type LaunchSpecTask struct {
IsEnabled *bool `json:"isEnabled,omitempty"`
CronExpression *string `json:"cronExpression,omitempty"`
TaskType *string `json:"taskType,omitempty"`
Config *TaskConfig `json:"config,omitempty"`
forceSendFields []string
nullFields []string
}
type LaunchSpecShutdownHours struct {
IsEnabled *bool `json:"isEnabled,omitempty"`
TimeWindows []string `json:"timeWindows,omitempty"`
forceSendFields []string
nullFields []string
}
type TaskConfig struct {
TaskHeadrooms []*LaunchSpecTaskHeadroom `json:"headrooms,omitempty"`
forceSendFields []string
nullFields []string
}
type LaunchSpecTaskHeadroom struct {
CPUPerUnit *int `json:"cpuPerUnit,omitempty"`
GPUPerUnit *int `json:"gpuPerUnit,omitempty"`
MemoryPerUnit *int `json:"memoryPerUnit,omitempty"`
NumOfUnits *int `json:"numOfUnits,omitempty"`
forceSendFields []string
nullFields []string
}
type ListLaunchSpecsInput struct {
OceanID *string `json:"oceanId,omitempty"`
}
@ -162,7 +209,8 @@ type ListLaunchSpecsOutput struct {
}
type CreateLaunchSpecInput struct {
LaunchSpec *LaunchSpec `json:"launchSpec,omitempty"`
LaunchSpec *LaunchSpec `json:"launchSpec,omitempty"`
InitialNodes *int `json:"-"`
}
type CreateLaunchSpecOutput struct {
@ -187,6 +235,7 @@ type UpdateLaunchSpecOutput struct {
type DeleteLaunchSpecInput struct {
LaunchSpecID *string `json:"launchSpecId,omitempty"`
ForceDelete *bool `json:"-"`
}
type DeleteLaunchSpecOutput struct{}
@ -251,6 +300,10 @@ func (s *ServiceOp) CreateLaunchSpec(ctx context.Context, input *CreateLaunchSpe
r := client.NewRequest(http.MethodPost, "/ocean/aws/k8s/launchSpec")
r.Obj = input
if input.InitialNodes != nil {
r.Params.Set("initialNodes", strconv.Itoa(spotinst.IntValue(input.InitialNodes)))
}
resp, err := client.RequireOK(s.Client.Do(ctx, r))
if err != nil {
return nil, err
@ -341,6 +394,10 @@ func (s *ServiceOp) DeleteLaunchSpec(ctx context.Context, input *DeleteLaunchSpe
r := client.NewRequest(http.MethodDelete, path)
if input.ForceDelete != nil {
r.Params.Set("forceDelete", strconv.FormatBool(spotinst.BoolValue(input.ForceDelete)))
}
resp, err := client.RequireOK(s.Client.Do(ctx, r))
if err != nil {
return nil, err
@ -416,6 +473,13 @@ func (o *LaunchSpec) SetInstanceTypes(v []string) *LaunchSpec {
return o
}
func (o *LaunchSpec) SetPreferredSpotTypes(v []string) *LaunchSpec {
if o.PreferredSpotTypes = v; o.PreferredSpotTypes == nil {
o.nullFields = append(o.nullFields, "PreferredSpotTypes")
}
return o
}
func (o *LaunchSpec) SetRootVolumeSize(v *int) *LaunchSpec {
if o.RootVolumeSize = v; o.RootVolumeSize == nil {
o.nullFields = append(o.nullFields, "RootVolumeSize")
@ -500,6 +564,13 @@ func (o *LaunchSpec) SetRestrictScaleDown(v *bool) *LaunchSpec {
return o
}
func (o *LaunchSpec) SetScheduling(v *LaunchSpecScheduling) *LaunchSpec {
if o.LaunchSpecScheduling = v; o.LaunchSpecScheduling == nil {
o.nullFields = append(o.nullFields, "LaunchSpecScheduling")
}
return o
}
// endregion
// region BlockDeviceMapping
@ -659,6 +730,13 @@ func (o *ResourceLimits) SetMaxInstanceCount(v *int) *ResourceLimits {
return o
}
func (o *ResourceLimits) SetMinInstanceCount(v *int) *ResourceLimits {
if o.MinInstanceCount = v; o.MinInstanceCount == nil {
o.nullFields = append(o.nullFields, "MinInstanceCount")
}
return o
}
// endregion
// region Label
@ -828,3 +906,142 @@ func (o *LaunchSpecStrategy) SetSpotPercentage(v *int) *LaunchSpecStrategy {
}
// endregion
//region Scheduling
func (o LaunchSpecScheduling) MarshalJSON() ([]byte, error) {
type noMethod LaunchSpecScheduling
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *LaunchSpecScheduling) SetTasks(v []*LaunchSpecTask) *LaunchSpecScheduling {
if o.Tasks = v; o.Tasks == nil {
o.nullFields = append(o.nullFields, "Tasks")
}
return o
}
func (o *LaunchSpecScheduling) SetShutdownHours(v *LaunchSpecShutdownHours) *LaunchSpecScheduling {
if o.ShutdownHours = v; o.ShutdownHours == nil {
o.nullFields = append(o.nullFields, "ShutdownHours")
}
return o
}
// endregion
//region LaunchSpecTask
func (o LaunchSpecTask) MarshalJSON() ([]byte, error) {
type noMethod LaunchSpecTask
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *LaunchSpecTask) SetIsEnabled(v *bool) *LaunchSpecTask {
if o.IsEnabled = v; o.IsEnabled == nil {
o.nullFields = append(o.nullFields, "IsEnabled")
}
return o
}
func (o *LaunchSpecTask) SetCronExpression(v *string) *LaunchSpecTask {
if o.CronExpression = v; o.CronExpression == nil {
o.nullFields = append(o.nullFields, "CronExpression")
}
return o
}
func (o *LaunchSpecTask) SetTaskType(v *string) *LaunchSpecTask {
if o.TaskType = v; o.TaskType == nil {
o.nullFields = append(o.nullFields, "TaskType")
}
return o
}
func (o *LaunchSpecTask) SetTaskConfig(v *TaskConfig) *LaunchSpecTask {
if o.Config = v; o.Config == nil {
o.nullFields = append(o.nullFields, "Config")
}
return o
}
// endregion
//region LaunchSpecShutdownHours
func (o LaunchSpecShutdownHours) MarshalJSON() ([]byte, error) {
type noMethod LaunchSpecShutdownHours
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *LaunchSpecShutdownHours) SetIsEnabled(v *bool) *LaunchSpecShutdownHours {
if o.IsEnabled = v; o.IsEnabled == nil {
o.nullFields = append(o.nullFields, "IsEnabled")
}
return o
}
func (o *LaunchSpecShutdownHours) SetTimeWindows(v []string) *LaunchSpecShutdownHours {
if o.TimeWindows = v; o.TimeWindows == nil {
o.nullFields = append(o.nullFields, "TimeWindows")
}
return o
}
//region TaskConfig
func (o TaskConfig) MarshalJSON() ([]byte, error) {
type noMethod TaskConfig
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *TaskConfig) SetHeadrooms(v []*LaunchSpecTaskHeadroom) *TaskConfig {
if o.TaskHeadrooms = v; o.TaskHeadrooms == nil {
o.nullFields = append(o.nullFields, "TaskHeadrooms")
}
return o
}
// endregion
// region LaunchSpecTaskHeadroom
func (o LaunchSpecTaskHeadroom) MarshalJSON() ([]byte, error) {
type noMethod LaunchSpecTaskHeadroom
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *LaunchSpecTaskHeadroom) SetCPUPerUnit(v *int) *LaunchSpecTaskHeadroom {
if o.CPUPerUnit = v; o.CPUPerUnit == nil {
o.nullFields = append(o.nullFields, "CPUPerUnit")
}
return o
}
func (o *LaunchSpecTaskHeadroom) SetGPUPerUnit(v *int) *LaunchSpecTaskHeadroom {
if o.GPUPerUnit = v; o.GPUPerUnit == nil {
o.nullFields = append(o.nullFields, "GPUPerUnit")
}
return o
}
func (o *LaunchSpecTaskHeadroom) SetMemoryPerUnit(v *int) *LaunchSpecTaskHeadroom {
if o.MemoryPerUnit = v; o.MemoryPerUnit == nil {
o.nullFields = append(o.nullFields, "MemoryPerUnit")
}
return o
}
func (o *LaunchSpecTaskHeadroom) SetNumOfUnits(v *int) *LaunchSpecTaskHeadroom {
if o.NumOfUnits = v; o.NumOfUnits == nil {
o.nullFields = append(o.nullFields, "NumOfUnits")
}
return o
}
// endregion

View File

@ -14,19 +14,21 @@ import (
)
type ECSLaunchSpec 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"`
SecurityGroupIDs []string `json:"securityGroupIds,omitempty"`
AutoScale *ECSAutoScale `json:"autoScale,omitempty"`
IAMInstanceProfile *ECSIAMInstanceProfile `json:"iamInstanceProfile,omitempty"`
Attributes []*ECSAttribute `json:"attributes,omitempty"`
BlockDeviceMappings []*ECSBlockDeviceMapping `json:"blockDeviceMappings,omitempty"`
Tags []*Tag `json:"tags,omitempty"`
InstanceTypes []string `json:"instanceTypes,omitempty"`
RestrictScaleDown *bool `json:"restrictScaleDown,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"`
SecurityGroupIDs []string `json:"securityGroupIds,omitempty"`
AutoScale *ECSAutoScale `json:"autoScale,omitempty"`
IAMInstanceProfile *ECSIAMInstanceProfile `json:"iamInstanceProfile,omitempty"`
Attributes []*ECSAttribute `json:"attributes,omitempty"`
BlockDeviceMappings []*ECSBlockDeviceMapping `json:"blockDeviceMappings,omitempty"`
Tags []*Tag `json:"tags,omitempty"`
InstanceTypes []string `json:"instanceTypes,omitempty"`
RestrictScaleDown *bool `json:"restrictScaleDown,omitempty"`
SubnetIDs []string `json:"subnetIds,omitempty"`
LaunchSpecScheduling *ECSLaunchSpecScheduling `json:"scheduling,omitempty"`
// Read-only fields.
CreatedAt *time.Time `json:"createdAt,omitempty"`
@ -107,6 +109,39 @@ type ECSDynamicVolumeSize struct {
nullFields []string
}
type ECSLaunchSpecScheduling struct {
Tasks []*ECSLaunchSpecTask `json:"tasks,omitempty"`
forceSendFields []string
nullFields []string
}
type ECSLaunchSpecTask struct {
IsEnabled *bool `json:"isEnabled,omitempty"`
CronExpression *string `json:"cronExpression,omitempty"`
TaskType *string `json:"taskType,omitempty"`
Config *ECSTaskConfig `json:"config,omitempty"`
forceSendFields []string
nullFields []string
}
type ECSTaskConfig struct {
TaskHeadrooms []*ECSLaunchSpecTaskHeadroom `json:"headrooms,omitempty"`
forceSendFields []string
nullFields []string
}
type ECSLaunchSpecTaskHeadroom struct {
CPUPerUnit *int `json:"cpuPerUnit,omitempty"`
MemoryPerUnit *int `json:"memoryPerUnit,omitempty"`
NumOfUnits *int `json:"numOfUnits,omitempty"`
forceSendFields []string
nullFields []string
}
type ListECSLaunchSpecsInput struct {
OceanID *string `json:"oceanId,omitempty"`
}
@ -405,6 +440,20 @@ func (o *ECSLaunchSpec) SetRestrictScaleDown(v *bool) *ECSLaunchSpec {
return o
}
func (o *ECSLaunchSpec) SetSubnetIDs(v []string) *ECSLaunchSpec {
if o.SubnetIDs = v; o.SubnetIDs == nil {
o.nullFields = append(o.nullFields, "SubnetIDs")
}
return o
}
func (o *ECSLaunchSpec) SetScheduling(v *ECSLaunchSpecScheduling) *ECSLaunchSpec {
if o.LaunchSpecScheduling = v; o.LaunchSpecScheduling == nil {
o.nullFields = append(o.nullFields, "ECSLaunchSpecScheduling")
}
return o
}
// endregion
// region Attributes
@ -620,3 +669,106 @@ func (o *ECSDynamicVolumeSize) SetSizePerResourceUnit(v *int) *ECSDynamicVolumeS
}
// endregion
//region Scheduling
func (o ECSLaunchSpecScheduling) MarshalJSON() ([]byte, error) {
type noMethod ECSLaunchSpecScheduling
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *ECSLaunchSpecScheduling) SetTasks(v []*ECSLaunchSpecTask) *ECSLaunchSpecScheduling {
if o.Tasks = v; o.Tasks == nil {
o.nullFields = append(o.nullFields, "Tasks")
}
return o
}
// endregion
//region LaunchSpecTask
func (o ECSLaunchSpecTask) MarshalJSON() ([]byte, error) {
type noMethod ECSLaunchSpecTask
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *ECSLaunchSpecTask) SetIsEnabled(v *bool) *ECSLaunchSpecTask {
if o.IsEnabled = v; o.IsEnabled == nil {
o.nullFields = append(o.nullFields, "IsEnabled")
}
return o
}
func (o *ECSLaunchSpecTask) SetCronExpression(v *string) *ECSLaunchSpecTask {
if o.CronExpression = v; o.CronExpression == nil {
o.nullFields = append(o.nullFields, "CronExpression")
}
return o
}
func (o *ECSLaunchSpecTask) SetTaskType(v *string) *ECSLaunchSpecTask {
if o.TaskType = v; o.TaskType == nil {
o.nullFields = append(o.nullFields, "TaskType")
}
return o
}
func (o *ECSLaunchSpecTask) SetTaskConfig(v *ECSTaskConfig) *ECSLaunchSpecTask {
if o.Config = v; o.Config == nil {
o.nullFields = append(o.nullFields, "Config")
}
return o
}
// endregion
//region TaskConfig
func (o ECSTaskConfig) MarshalJSON() ([]byte, error) {
type noMethod ECSTaskConfig
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *ECSTaskConfig) SetHeadrooms(v []*ECSLaunchSpecTaskHeadroom) *ECSTaskConfig {
if o.TaskHeadrooms = v; o.TaskHeadrooms == nil {
o.nullFields = append(o.nullFields, "TaskHeadrooms")
}
return o
}
// endregion
// region LaunchSpecTaskHeadroom
func (o ECSLaunchSpecTaskHeadroom) MarshalJSON() ([]byte, error) {
type noMethod ECSLaunchSpecTaskHeadroom
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *ECSLaunchSpecTaskHeadroom) SetCPUPerUnit(v *int) *ECSLaunchSpecTaskHeadroom {
if o.CPUPerUnit = v; o.CPUPerUnit == nil {
o.nullFields = append(o.nullFields, "CPUPerUnit")
}
return o
}
func (o *ECSLaunchSpecTaskHeadroom) SetMemoryPerUnit(v *int) *ECSLaunchSpecTaskHeadroom {
if o.MemoryPerUnit = v; o.MemoryPerUnit == nil {
o.nullFields = append(o.nullFields, "MemoryPerUnit")
}
return o
}
func (o *ECSLaunchSpecTaskHeadroom) SetNumOfUnits(v *int) *ECSLaunchSpecTaskHeadroom {
if o.NumOfUnits = v; o.NumOfUnits == nil {
o.nullFields = append(o.nullFields, "NumOfUnits")
}
return o
}
// endregion

View File

@ -34,17 +34,46 @@ type ContainerResourceSuggestion struct {
RequestedMemory *float64 `json:"requestedMemory,omitempty"`
}
// ListResourceSuggestionsInput represents the input of `ListResourceSuggestions` function.
type Filter struct {
Attribute *Attribute `json:"attribute,omitempty"`
Namespaces []string `json:"namespaces,omitempty"`
forceSendFields []string
nullFields []string
}
type Attribute struct {
Key *string `json:"key,omitempty"`
Operator *string `json:"operator,omitempty"`
Type *string `json:"type,omitempty"`
Value *string `json:"value,omitempty"`
forceSendFields []string
nullFields []string
}
// Deprecated: Use ListOceanResourceSuggestionsInput instead.
type ListResourceSuggestionsInput struct {
OceanID *string `json:"oceanId,omitempty"`
Namespace *string `json:"namespace,omitempty"`
}
// ListResourceSuggestionsOutput represents the output of `ListResourceSuggestions` function.
// Deprecated: Use ListOceanResourceSuggestionsOutput instead.
type ListResourceSuggestionsOutput struct {
Suggestions []*ResourceSuggestion `json:"suggestions,omitempty"`
}
// ListOceanResourceSuggestionsInput represents the input of `ListOceanResourceSuggestions` function.
type ListOceanResourceSuggestionsInput struct {
OceanID *string `json:"oceanId,omitempty"`
Filter *Filter `json:"filter,omitempty"`
}
// ListOceanResourceSuggestionsOutput represents the output of `ListOceanResourceSuggestions` function.
type ListOceanResourceSuggestionsOutput struct {
Suggestions []*ResourceSuggestion `json:"suggestions,omitempty"`
}
func resourceSuggestionFromJSON(in []byte) (*ResourceSuggestion, error) {
b := new(ResourceSuggestion)
if err := json.Unmarshal(in, b); err != nil {
@ -77,8 +106,37 @@ func resourceSuggestionsFromHTTPResponse(resp *http.Response) ([]*ResourceSugges
return resourceSuggestionsFromJSON(body)
}
// ListResourceSuggestions returns a list of right-sizing resource suggestions
// ListOceanResourceSuggestions returns a list of right-sizing resource suggestions
// for an Ocean cluster.
func (s *ServiceOp) ListOceanResourceSuggestions(ctx context.Context, input *ListOceanResourceSuggestionsInput) (*ListOceanResourceSuggestionsOutput, error) {
path, err := uritemplates.Expand("/ocean/aws/k8s/cluster/{oceanId}/rightSizing/suggestion", uritemplates.Values{
"oceanId": spotinst.StringValue(input.OceanID),
})
if err != nil {
return nil, err
}
r := client.NewRequest(http.MethodPost, path)
// We do NOT need the ID anymore, so let's drop it.
input.OceanID = nil
r.Obj = input
resp, err := client.RequireOK(s.Client.Do(ctx, r))
if err != nil {
return nil, err
}
defer resp.Body.Close()
rs, err := resourceSuggestionsFromHTTPResponse(resp)
if err != nil {
return nil, err
}
return &ListOceanResourceSuggestionsOutput{Suggestions: rs}, nil
}
// Deprecated: Use ListOceanResourceSuggestions instead.
func (s *ServiceOp) ListResourceSuggestions(ctx context.Context, input *ListResourceSuggestionsInput) (*ListResourceSuggestionsOutput, error) {
path, err := uritemplates.Expand("/ocean/aws/k8s/cluster/{oceanId}/rightSizing/resourceSuggestion", uritemplates.Values{
"oceanId": spotinst.StringValue(input.OceanID),

View File

@ -62,6 +62,10 @@ type serviceECS interface {
}
type serviceCommon interface {
ListOceanResourceSuggestions(context.Context, *ListOceanResourceSuggestionsInput) (*ListOceanResourceSuggestionsOutput, error)
// Deprecated: ListResourceSuggestions is obsolete, exists for backward compatibility only,
// and should not be used. Please use ListOceanResourceSuggestions instead.
ListResourceSuggestions(context.Context, *ListResourceSuggestionsInput) (*ListResourceSuggestionsOutput, error)
}

View File

@ -6,6 +6,7 @@ go_library(
"cluster.go",
"common.go",
"nodegroup.go",
"rightsizing.go",
"service.go",
],
importmap = "k8s.io/kops/vendor/github.com/spotinst/spotinst-sdk-go/service/ocean/providers/azure",

View File

@ -73,7 +73,7 @@ type VirtualNodeGroupTemplate struct {
}
type ResourceLimits struct {
MaxVCPU *int `json:"maxVcpu,omitempty"`
MaxVCPU *int `json:"maxVCpu,omitempty"`
MaxMemoryGib *int `json:"maxMemoryGib,omitempty"`
forceSendFields []string
@ -104,33 +104,36 @@ type Automatic struct {
}
type VMSizes struct {
Whitelist []*string `json:"whitelist,omitempty"`
Whitelist []string `json:"whitelist,omitempty"`
forceSendFields []string
nullFields []string
}
type LaunchSpecification struct {
ResourceGroupName *string `json:"resourceGroupName,omitempty"`
CustomData *string `json:"customData,omitempty"`
Image *Image `json:"image,omitempty"`
Network *Network `json:"network,omitempty"`
OSDisk *OSDisk `json:"osDisk,omitempty"`
Login *Login `json:"login,omitempty"`
LoadBalancersConfig *LoadBalancersConfig `json:"loadBalancersConfig,omitempty"`
Extensions []*Extension `json:"extensions,omitempty"`
Tags []*Tag `json:"tags,omitempty"`
ResourceGroupName *string `json:"resourceGroupName,omitempty"`
CustomData *string `json:"customData,omitempty"`
Image *Image `json:"image,omitempty"`
Network *Network `json:"network,omitempty"`
OSDisk *OSDisk `json:"osDisk,omitempty"`
Login *Login `json:"login,omitempty"`
LoadBalancersConfig *LoadBalancersConfig `json:"loadBalancersConfig,omitempty"`
ManagedServiceIdentities []*ManagedServiceIdentity `json:"managedServiceIdentities,omitempty"`
Extensions []*Extension `json:"extensions,omitempty"`
Tags []*Tag `json:"tags,omitempty"`
forceSendFields []string
nullFields []string
}
type Extension struct {
APIVersion *string `json:"apiVersion,omitempty"`
MinorVersionAutoUpgrade *bool `json:"minorVersionAutoUpgrade,omitempty"`
Name *string `json:"name,omitempty"`
Publisher *string `json:"publisher,omitempty"`
Type *string `json:"type,omitempty"`
APIVersion *string `json:"apiVersion,omitempty"`
MinorVersionAutoUpgrade *bool `json:"minorVersionAutoUpgrade,omitempty"`
Name *string `json:"name,omitempty"`
Publisher *string `json:"publisher,omitempty"`
Type *string `json:"type,omitempty"`
ProtectedSettings interface{} `json:"protectedSettings,omitempty"`
PublicSettings interface{} `json:"publicSettings,omitempty"`
forceSendFields []string
nullFields []string
@ -178,11 +181,11 @@ type MarketplaceImage struct {
}
type LoadBalancer struct {
BackendPoolNames []*string `json:"backendPoolNames,omitempty"`
LoadBalancerSKU *string `json:"loadBalancerSku,omitempty"`
Name *string `json:"name,omitempty"`
ResourceGroupName *string `json:"resourceGroupName,omitempty"`
Type *string `json:"type,omitempty"`
BackendPoolNames []string `json:"backendPoolNames,omitempty"`
LoadBalancerSKU *string `json:"loadBalancerSku,omitempty"`
Name *string `json:"name,omitempty"`
ResourceGroupName *string `json:"resourceGroupName,omitempty"`
Type *string `json:"type,omitempty"`
forceSendFields []string
nullFields []string
@ -194,6 +197,7 @@ type NetworkInterface struct {
IsPrimary *bool `json:"isPrimary,omitempty"`
EnableIPForwarding *bool `json:"enableIPForwarding,omitempty"`
PublicIPSKU *string `json:"publicIpSku,omitempty"`
SecurityGroup *SecurityGroup `json:"securityGroup,omitempty"`
AdditionalIPConfigs []*AdditionalIPConfig `json:"additionalIpConfigurations,omitempty"`
forceSendFields []string
@ -216,6 +220,14 @@ type SecurityGroup struct {
nullFields []string
}
type ManagedServiceIdentity struct {
ResourceGroupName *string `json:"resourceGroupName,omitempty"`
Name *string `json:"name,omitempty"`
forceSendFields []string
nullFields []string
}
type ListClustersInput struct{}
type ListClustersOutput struct {
@ -793,7 +805,7 @@ func (o VMSizes) MarshalJSON() ([]byte, error) {
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *VMSizes) SetWhitelist(v []*string) *VMSizes {
func (o *VMSizes) SetWhitelist(v []string) *VMSizes {
if o.Whitelist = v; o.Whitelist == nil {
o.nullFields = append(o.nullFields, "Whitelist")
}
@ -845,6 +857,41 @@ func (o *LaunchSpecification) SetLogin(v *Login) *LaunchSpecification {
return o
}
func (o *LaunchSpecification) SetManagedServiceIdentities(v []*ManagedServiceIdentity) *LaunchSpecification {
if o.ManagedServiceIdentities = v; o.ManagedServiceIdentities == nil {
o.nullFields = append(o.nullFields, "ManagedServiceIdentities")
}
return o
}
func (o *LaunchSpecification) SetExtensions(v []*Extension) *LaunchSpecification {
if o.Extensions = v; o.Extensions == nil {
o.nullFields = append(o.nullFields, "Extensions")
}
return o
}
func (o *LaunchSpecification) SetLoadBalancersConfig(v *LoadBalancersConfig) *LaunchSpecification {
if o.LoadBalancersConfig = v; o.LoadBalancersConfig == nil {
o.nullFields = append(o.nullFields, "LoadBalancersConfig")
}
return o
}
func (o *LaunchSpecification) SetOSDisk(v *OSDisk) *LaunchSpecification {
if o.OSDisk = v; o.OSDisk == nil {
o.nullFields = append(o.nullFields, "OSDisk")
}
return o
}
func (o *LaunchSpecification) SetTags(v []*Tag) *LaunchSpecification {
if o.Tags = v; o.Tags == nil {
o.nullFields = append(o.nullFields, "Tags")
}
return o
}
// endregion
// region Image
@ -983,6 +1030,13 @@ func (o *NetworkInterface) SetPublicIPSKU(v *string) *NetworkInterface {
return o
}
func (o *NetworkInterface) SetSecurityGroup(v *SecurityGroup) *NetworkInterface {
if o.SecurityGroup = v; o.SecurityGroup == nil {
o.nullFields = append(o.nullFields, "SecurityGroup")
}
return o
}
// endregion
// region AdditionalIPConfig
@ -1078,6 +1132,20 @@ func (o *Extension) SetMinorVersionAutoUpgrade(v *bool) *Extension {
return o
}
func (o *Extension) SetProtectedSettings(v interface{}) *Extension {
if o.ProtectedSettings = v; o.ProtectedSettings == nil {
o.nullFields = append(o.nullFields, "ProtectedSettings")
}
return o
}
func (o *Extension) SetPublicSettings(v interface{}) *Extension {
if o.PublicSettings = v; o.PublicSettings == nil {
o.nullFields = append(o.nullFields, "PublicSettings")
}
return o
}
// endregion
// region LoadBalancersConfig
@ -1088,7 +1156,7 @@ func (o LoadBalancersConfig) MarshalJSON() ([]byte, error) {
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *LoadBalancersConfig) SetUserName(v []*LoadBalancer) *LoadBalancersConfig {
func (o *LoadBalancersConfig) SetLoadBalancers(v []*LoadBalancer) *LoadBalancersConfig {
if o.LoadBalancers = v; o.LoadBalancers == nil {
o.nullFields = append(o.nullFields, "LoadBalancers")
}
@ -1133,7 +1201,7 @@ func (o *LoadBalancer) SetType(v *string) *LoadBalancer {
return o
}
func (o *LoadBalancer) SeBackendPoolNames(v []*string) *LoadBalancer {
func (o *LoadBalancer) SeBackendPoolNames(v []string) *LoadBalancer {
if o.BackendPoolNames = v; o.BackendPoolNames == nil {
o.nullFields = append(o.nullFields, "BackendPoolNames")
}
@ -1165,3 +1233,27 @@ func (o *SecurityGroup) SetName(v *string) *SecurityGroup {
}
// endregion
// region ManagedServiceIdentity
func (o ManagedServiceIdentity) MarshalJSON() ([]byte, error) {
type noMethod ManagedServiceIdentity
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *ManagedServiceIdentity) SetResourceGroupName(v *string) *ManagedServiceIdentity {
if o.ResourceGroupName = v; o.ResourceGroupName == nil {
o.nullFields = append(o.nullFields, "ResourceGroupName")
}
return o
}
func (o *ManagedServiceIdentity) SetName(v *string) *ManagedServiceIdentity {
if o.Name = v; o.Name == nil {
o.nullFields = append(o.nullFields, "Name")
}
return o
}
// endregion

View File

@ -0,0 +1,134 @@
package azure
import (
"context"
"encoding/json"
"io/ioutil"
"net/http"
"github.com/spotinst/spotinst-sdk-go/spotinst"
"github.com/spotinst/spotinst-sdk-go/spotinst/client"
"github.com/spotinst/spotinst-sdk-go/spotinst/util/uritemplates"
)
type Filter struct {
Attribute *Attribute `json:"attribute,omitempty"`
Namespaces []string `json:"namespaces,omitempty"`
forceSendFields []string
nullFields []string
}
type Attribute struct {
Key *string `json:"key,omitempty"`
Operator *string `json:"operator,omitempty"`
Type *string `json:"type,omitempty"`
Value *string `json:"value,omitempty"`
forceSendFields []string
nullFields []string
}
// ResourceSuggestion represents a single resource suggestion.
type ResourceSuggestion struct {
ResourceName *string `json:"resourceName,omitempty"`
ResourceType *string `json:"resourceType,omitempty"`
Namespace *string `json:"namespace,omitempty"`
SuggestedCPU *float64 `json:"suggestedCPU,omitempty"`
RequestedCPU *float64 `json:"requestedCPU,omitempty"`
SuggestedMemory *float64 `json:"suggestedMemory,omitempty"`
RequestedMemory *float64 `json:"requestedMemory,omitempty"`
Containers []*ContainerResourceSuggestion `json:"containers,omitempty"`
}
// ContainerResourceSuggestion represents a resource suggestion for a
// single container.
type ContainerResourceSuggestion struct {
Name *string `json:"name,omitempty"`
SuggestedCPU *float64 `json:"suggestedCpu,omitempty"`
RequestedCPU *float64 `json:"requestedCpu,omitempty"`
SuggestedMemory *float64 `json:"suggestedMemory,omitempty"`
RequestedMemory *float64 `json:"requestedMemory,omitempty"`
}
// ListResourceSuggestionsInput represents the input of `ListResourceSuggestions` function.
type ListResourceSuggestionsInput struct {
OceanID *string `json:"oceanId,omitempty"`
Namespace *string `json:"namespace,omitempty"`
Filter *Filter `json:"filter,omitempty"`
}
// ListResourceSuggestionsOutput represents the output of `ListResourceSuggestions` function.
type ListResourceSuggestionsOutput struct {
Suggestions []*ResourceSuggestion `json:"suggestions,omitempty"`
}
// region Unmarshallers
func resourceSuggestionFromJSON(in []byte) (*ResourceSuggestion, error) {
b := new(ResourceSuggestion)
if err := json.Unmarshal(in, b); err != nil {
return nil, err
}
return b, nil
}
func resourceSuggestionsFromJSON(in []byte) ([]*ResourceSuggestion, error) {
var rw client.Response
if err := json.Unmarshal(in, &rw); err != nil {
return nil, err
}
out := make([]*ResourceSuggestion, len(rw.Response.Items))
for i, rb := range rw.Response.Items {
b, err := resourceSuggestionFromJSON(rb)
if err != nil {
return nil, err
}
out[i] = b
}
return out, nil
}
func resourceSuggestionsFromHTTPResponse(resp *http.Response) ([]*ResourceSuggestion, error) {
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return resourceSuggestionsFromJSON(body)
}
// endregion
// region API request
// ListResourceSuggestions returns a list of right-sizing resource suggestions
// for an Ocean cluster.
func (s *ServiceOp) ListResourceSuggestions(ctx context.Context, input *ListResourceSuggestionsInput) (*ListResourceSuggestionsOutput, error) {
path, err := uritemplates.Expand("/ocean/azure/k8s/cluster/{oceanId}/rightSizing/suggestion", uritemplates.Values{
"oceanId": spotinst.StringValue(input.OceanID),
})
if err != nil {
return nil, err
}
r := client.NewRequest(http.MethodPost, path)
// We do NOT need the ID anymore, so let's drop it.
input.OceanID = nil
r.Obj = input
resp, err := client.RequireOK(s.Client.Do(ctx, r))
if err != nil {
return nil, err
}
defer resp.Body.Close()
rs, err := resourceSuggestionsFromHTTPResponse(resp)
if err != nil {
return nil, err
}
return &ListResourceSuggestionsOutput{Suggestions: rs}, nil
}
//endregion

View File

@ -24,6 +24,7 @@ type Service interface {
ReadVirtualNodeGroup(context.Context, *ReadVirtualNodeGroupInput) (*ReadVirtualNodeGroupOutput, error)
UpdateVirtualNodeGroup(context.Context, *UpdateVirtualNodeGroupInput) (*UpdateVirtualNodeGroupOutput, error)
DeleteVirtualNodeGroup(context.Context, *DeleteVirtualNodeGroupInput) (*DeleteVirtualNodeGroupOutput, error)
ListResourceSuggestions(context.Context, *ListResourceSuggestionsInput) (*ListResourceSuggestionsOutput, error)
}
type ServiceOp struct {

View File

@ -53,13 +53,14 @@ type Strategy struct {
}
type AutoScaler struct {
IsEnabled *bool `json:"isEnabled,omitempty"`
IsAutoConfig *bool `json:"isAutoConfig,omitempty"`
Cooldown *int `json:"cooldown,omitempty"`
AutoHeadroomPercentage *int `json:"autoHeadroomPercentage,omitempty"`
Headroom *AutoScalerHeadroom `json:"headroom,omitempty"`
ResourceLimits *AutoScalerResourceLimits `json:"resourceLimits,omitempty"`
Down *AutoScalerDown `json:"down,omitempty"`
IsEnabled *bool `json:"isEnabled,omitempty"`
IsAutoConfig *bool `json:"isAutoConfig,omitempty"`
Cooldown *int `json:"cooldown,omitempty"`
AutoHeadroomPercentage *int `json:"autoHeadroomPercentage,omitempty"`
Headroom *AutoScalerHeadroom `json:"headroom,omitempty"`
ResourceLimits *AutoScalerResourceLimits `json:"resourceLimits,omitempty"`
Down *AutoScalerDown `json:"down,omitempty"`
EnableAutomaticAndManualHeadroom *bool `json:"enableAutomaticAndManualHeadroom,omitempty"`
forceSendFields []string
nullFields []string
@ -171,6 +172,7 @@ type LaunchSpecification struct {
ServiceAccount *string `json:"serviceAccount,omitempty"`
SourceImage *string `json:"sourceImage,omitempty"`
Tags []string `json:"tags,omitempty"`
RootVolumeType *string `json:"rootVolumeType,omitempty"`
forceSendFields []string
nullFields []string
@ -254,6 +256,44 @@ type DeleteClusterInput struct {
type DeleteClusterOutput struct{}
type RollSpec struct {
ClusterID *string `json:"clusterId,omitempty"`
Comment *string `json:"comment,omitempty"`
BatchSizePercentage *int `json:"batchSizePercentage,omitempty"`
LaunchSpecIDs []string `json:"launchSpecIds,omitempty"`
InstanceNames []string `json:"instanceNames,omitempty"`
forceSendFields []string
nullFields []string
}
type RollStatus struct {
RollID *string `json:"rollId,omitempty"`
ClusterID *string `json:"oceanId,omitempty"`
Comment *string `json:"comment,omitempty"`
Status *string `json:"status,omitempty"`
Progress *Progress `json:"progress,omitempty"`
BatchNumber *int `json:"batchNumber,omitempty"`
NumOfBatches *int `json:"numOfBatches,omitempty"`
LaunchSpecIDs []string `json:"launchSpecIds,omitempty"`
InstanceNames []string `json:"instanceNames,omitempty"`
CreatedAt *time.Time `json:"createdAt,omitempty"`
UpdatedAt *time.Time `json:"updatedAt,omitempty"`
}
type Progress struct {
Unit *string `json:"unit,omitempty"`
Value *float64 `json:"value,omitempty"`
}
type CreateRollInput struct {
Roll *RollSpec `json:"roll,omitempty"`
}
type CreateRollOutput struct {
Roll *RollStatus `json:"roll,omitempty"`
}
func clusterFromJSON(in []byte) (*Cluster, error) {
b := new(Cluster)
if err := json.Unmarshal(in, b); err != nil {
@ -472,6 +512,73 @@ func (s *ServiceOp) ImportOceanGKECluster(ctx context.Context, input *ImportOcea
return output, nil
}
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 {
return nil, err
}
out[i] = b
}
return out, nil
}
func rollStatusesFromHttpResponse(resp *http.Response) ([]*RollStatus, error) {
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return rollStatusesFromJSON(body)
}
func (s *ServiceOp) CreateRoll(ctx context.Context, input *CreateRollInput) (*CreateRollOutput, error) {
path, err := uritemplates.Expand("/ocean/gcp/k8s/cluster/{clusterId}/roll", uritemplates.Values{
"clusterId": spotinst.StringValue(input.Roll.ClusterID),
})
if err != nil {
return nil, err
}
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
}
// region Cluster
func (o Cluster) MarshalJSON() ([]byte, error) {
@ -853,6 +960,13 @@ func (o *LaunchSpecification) SetTags(v []string) *LaunchSpecification {
return o
}
func (o *LaunchSpecification) SetRootVolumeType(v *string) *LaunchSpecification {
if o.RootVolumeType = v; o.RootVolumeType == nil {
o.nullFields = append(o.nullFields, "RootVolumeType")
}
return o
}
// endregion
// region BackendService
@ -1085,6 +1199,13 @@ func (o *AutoScaler) SetDown(v *AutoScalerDown) *AutoScaler {
return o
}
func (o *AutoScaler) SetEnableAutomaticAndManualHeadroom(v *bool) *AutoScaler {
if o.EnableAutomaticAndManualHeadroom = v; o.EnableAutomaticAndManualHeadroom == nil {
o.nullFields = append(o.nullFields, "EnableAutomaticAndManualHeadroom")
}
return o
}
// endregion
// region AutoScalerHeadroom
@ -1173,3 +1294,41 @@ func (o *AutoScalerDown) SetMaxScaleDownPercentage(v *float64) *AutoScalerDown {
}
// endregion
// region RollSpec
func (o RollSpec) MarshalJSON() ([]byte, error) {
type noMethod RollSpec
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *RollSpec) SetComment(v *string) *RollSpec {
if o.Comment = v; o.Comment == nil {
o.nullFields = append(o.nullFields, "Comment")
}
return o
}
func (o *RollSpec) SetBatchSizePercentage(v *int) *RollSpec {
if o.BatchSizePercentage = v; o.BatchSizePercentage == nil {
o.nullFields = append(o.nullFields, "BatchSizePercentage")
}
return o
}
func (o *RollSpec) SetLaunchSpecIDs(v []string) *RollSpec {
if o.LaunchSpecIDs = v; o.LaunchSpecIDs == nil {
o.nullFields = append(o.nullFields, "LaunchSpecIDs")
}
return o
}
func (o *RollSpec) SetInstanceNames(v []string) *RollSpec {
if o.InstanceNames = v; o.InstanceNames == nil {
o.nullFields = append(o.nullFields, "InstanceNames")
}
return o
}
// endregion

View File

@ -13,14 +13,25 @@ import (
)
type LaunchSpec struct {
ID *string `json:"id,omitempty"`
OceanID *string `json:"oceanId,omitempty"`
SourceImage *string `json:"sourceImage,omitempty"`
Metadata []*Metadata `json:"metadata,omitempty"`
Labels []*Label `json:"labels,omitempty"`
Taints []*Taint `json:"taints,omitempty"`
AutoScale *AutoScale `json:"autoScale,omitempty"`
RestrictScaleDown *bool `json:"restrictScaleDown,omitempty"`
ID *string `json:"id,omitempty"`
Name *string `json:"name,omitempty"`
OceanID *string `json:"oceanId,omitempty"`
SourceImage *string `json:"sourceImage,omitempty"`
Metadata []*Metadata `json:"metadata,omitempty"`
Labels []*Label `json:"labels,omitempty"`
Taints []*Taint `json:"taints,omitempty"`
AutoScale *AutoScale `json:"autoScale,omitempty"`
RestrictScaleDown *bool `json:"restrictScaleDown,omitempty"`
Tags []*Tag `json:"tags,omitempty"`
Strategy *LaunchSpecStrategy `json:"strategy,omitempty"`
RootVolumeSizeInGB *int `json:"rootVolumeSizeInGb,omitempty"`
RootVolumeType *string `json:"rootVolumeType,omitempty"`
ShieldedInstanceConfig *ShieldedInstanceConfig `json:"shieldedInstanceConfig,omitempty"`
ServiceAccount *string `json:"serviceAccount,omitempty"`
InstanceTypes []string `json:"instanceTypes,omitempty"`
Storage *Storage `json:"storage,omitempty"`
ResourceLimits *ResourceLimits `json:"resourceLimits,omitempty"`
LaunchSpecScheduling *GKELaunchSpecScheduling `json:"scheduling,omitempty"`
// forceSendFields is a list of field names (e.g. "Keys") to
// unconditionally include in API requests. By default, fields with
@ -73,6 +84,70 @@ type AutoScaleHeadroom struct {
nullFields []string
}
type LaunchSpecStrategy struct {
PreemptiblePercentage *int `json:"preemptiblePercentage,omitempty"`
forceSendFields []string
nullFields []string
}
type ShieldedInstanceConfig struct {
EnableSecureBoot *bool `json:"enableSecureBoot,omitempty"`
EnableIntegrityMonitoring *bool `json:"enableIntegrityMonitoring,omitempty"`
forceSendFields []string
nullFields []string
}
type Storage struct {
LocalSSDCount *int `json:"localSsdCount,omitempty"`
forceSendFields []string
nullFields []string
}
type ResourceLimits struct {
MaxInstanceCount *int `json:"maxInstanceCount,omitempty"`
MinInstanceCount *int `json:"minInstanceCount,omitempty"`
forceSendFields []string
nullFields []string
}
type GKELaunchSpecScheduling struct {
Tasks []*GKELaunchSpecTask `json:"tasks,omitempty"`
forceSendFields []string
nullFields []string
}
type GKELaunchSpecTask struct {
IsEnabled *bool `json:"isEnabled,omitempty"`
CronExpression *string `json:"cronExpression,omitempty"`
TaskType *string `json:"taskType,omitempty"`
Config *GKETaskConfig `json:"config,omitempty"`
forceSendFields []string
nullFields []string
}
type GKETaskConfig struct {
TaskHeadrooms []*GKELaunchSpecTaskHeadroom `json:"headrooms,omitempty"`
forceSendFields []string
nullFields []string
}
type GKELaunchSpecTaskHeadroom struct {
CPUPerUnit *int `json:"cpuPerUnit,omitempty"`
GPUPerUnit *int `json:"gpuPerUnit,omitempty"`
MemoryPerUnit *int `json:"memoryPerUnit,omitempty"`
NumOfUnits *int `json:"numOfUnits,omitempty"`
forceSendFields []string
nullFields []string
}
type ListLaunchSpecsInput struct {
OceanID *string `json:"oceanId,omitempty"`
}
@ -322,6 +397,13 @@ func (o *LaunchSpec) SetOceanId(v *string) *LaunchSpec {
return o
}
func (o *LaunchSpec) SetName(v *string) *LaunchSpec {
if o.Name = v; o.Name == nil {
o.nullFields = append(o.nullFields, "Name")
}
return o
}
func (o *LaunchSpec) SetSourceImage(v *string) *LaunchSpec {
if o.SourceImage = v; o.SourceImage == nil {
o.nullFields = append(o.nullFields, "SourceImage")
@ -364,6 +446,76 @@ func (o *LaunchSpec) SetRestrictScaleDown(v *bool) *LaunchSpec {
return o
}
func (o *LaunchSpec) SetStrategy(v *LaunchSpecStrategy) *LaunchSpec {
if o.Strategy = v; o.Strategy == nil {
o.nullFields = append(o.nullFields, "Strategy")
}
return o
}
func (o *LaunchSpec) SetRootVolumeSizeInGB(v *int) *LaunchSpec {
if o.RootVolumeSizeInGB = v; o.RootVolumeSizeInGB == nil {
o.nullFields = append(o.nullFields, "RootVolumeSizeInGB")
}
return o
}
func (o *LaunchSpec) SetRootVolumeType(v *string) *LaunchSpec {
if o.RootVolumeType = v; o.RootVolumeType == nil {
o.nullFields = append(o.nullFields, "RootVolumeType")
}
return o
}
func (o *LaunchSpec) SetServiceAccount(v *string) *LaunchSpec {
if o.ServiceAccount = v; o.ServiceAccount == nil {
o.nullFields = append(o.nullFields, "ServiceAccount")
}
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) SetShieldedInstanceConfig(v *ShieldedInstanceConfig) *LaunchSpec {
if o.ShieldedInstanceConfig = v; o.ShieldedInstanceConfig == nil {
o.nullFields = append(o.nullFields, "ShieldedInstanceConfig")
}
return o
}
func (o *LaunchSpec) SetInstanceTypes(v []string) *LaunchSpec {
if o.InstanceTypes = v; o.InstanceTypes == nil {
o.nullFields = append(o.nullFields, "InstanceTypes")
}
return o
}
func (o *LaunchSpec) SetStorage(v *Storage) *LaunchSpec {
if o.Storage = v; o.Storage == nil {
o.nullFields = append(o.nullFields, "Storage")
}
return o
}
func (o *LaunchSpec) SetResourceLimits(v *ResourceLimits) *LaunchSpec {
if o.ResourceLimits = v; o.ResourceLimits == nil {
o.nullFields = append(o.nullFields, "ResourceLimits")
}
return o
}
func (o *LaunchSpec) SetScheduling(v *GKELaunchSpecScheduling) *LaunchSpec {
if o.LaunchSpecScheduling = v; o.LaunchSpecScheduling == nil {
o.nullFields = append(o.nullFields, "GKELaunchSpecScheduling")
}
return o
}
// endregion
// region Label
@ -489,3 +641,195 @@ func (o *AutoScaleHeadroom) SetNumOfUnits(v *int) *AutoScaleHeadroom {
}
// endregion
// region Strategy
func (o LaunchSpecStrategy) MarshalJSON() ([]byte, error) {
type noMethod LaunchSpecStrategy
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *LaunchSpecStrategy) SetPreemptiblePercentage(v *int) *LaunchSpecStrategy {
if o.PreemptiblePercentage = v; o.PreemptiblePercentage == nil {
o.nullFields = append(o.nullFields, "PreemptiblePercentage")
}
return o
}
//endregion
// region ShieldedInstanceConfig
func (o ShieldedInstanceConfig) MarshalJSON() ([]byte, error) {
type noMethod ShieldedInstanceConfig
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *ShieldedInstanceConfig) SetEnableIntegrityMonitoring(v *bool) *ShieldedInstanceConfig {
if o.EnableIntegrityMonitoring = v; o.EnableIntegrityMonitoring == nil {
o.nullFields = append(o.nullFields, "EnableIntegrityMonitoring")
}
return o
}
func (o *ShieldedInstanceConfig) SetEnableSecureBoot(v *bool) *ShieldedInstanceConfig {
if o.EnableSecureBoot = v; o.EnableSecureBoot == nil {
o.nullFields = append(o.nullFields, "EnableSecureBoot")
}
return o
}
//endregion
// region Storage
func (o Storage) MarshalJSON() ([]byte, error) {
type noMethod Storage
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *Storage) SetLocalSSDCount(v *int) *Storage {
if o.LocalSSDCount = v; o.LocalSSDCount == nil {
o.nullFields = append(o.nullFields, "LocalSSDCount")
}
return o
}
//endregion
// 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
}
func (o *ResourceLimits) SetMinInstanceCount(v *int) *ResourceLimits {
if o.MinInstanceCount = v; o.MinInstanceCount == nil {
o.nullFields = append(o.nullFields, "MinInstanceCount")
}
return o
}
//endregion
//region Scheduling
func (o GKELaunchSpecScheduling) MarshalJSON() ([]byte, error) {
type noMethod GKELaunchSpecScheduling
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *GKELaunchSpecScheduling) SetTasks(v []*GKELaunchSpecTask) *GKELaunchSpecScheduling {
if o.Tasks = v; o.Tasks == nil {
o.nullFields = append(o.nullFields, "Tasks")
}
return o
}
// endregion
//region LaunchSpecTask
func (o GKELaunchSpecTask) MarshalJSON() ([]byte, error) {
type noMethod GKELaunchSpecTask
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *GKELaunchSpecTask) SetIsEnabled(v *bool) *GKELaunchSpecTask {
if o.IsEnabled = v; o.IsEnabled == nil {
o.nullFields = append(o.nullFields, "IsEnabled")
}
return o
}
func (o *GKELaunchSpecTask) SetCronExpression(v *string) *GKELaunchSpecTask {
if o.CronExpression = v; o.CronExpression == nil {
o.nullFields = append(o.nullFields, "CronExpression")
}
return o
}
func (o *GKELaunchSpecTask) SetTaskType(v *string) *GKELaunchSpecTask {
if o.TaskType = v; o.TaskType == nil {
o.nullFields = append(o.nullFields, "TaskType")
}
return o
}
func (o *GKELaunchSpecTask) SetTaskConfig(v *GKETaskConfig) *GKELaunchSpecTask {
if o.Config = v; o.Config == nil {
o.nullFields = append(o.nullFields, "Config")
}
return o
}
// endregion
//region TaskConfig
func (o GKETaskConfig) MarshalJSON() ([]byte, error) {
type noMethod GKETaskConfig
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *GKETaskConfig) SetHeadrooms(v []*GKELaunchSpecTaskHeadroom) *GKETaskConfig {
if o.TaskHeadrooms = v; o.TaskHeadrooms == nil {
o.nullFields = append(o.nullFields, "TaskHeadroom")
}
return o
}
// endregion
// region LaunchSpecTaskHeadroom
func (o GKELaunchSpecTaskHeadroom) MarshalJSON() ([]byte, error) {
type noMethod GKELaunchSpecTaskHeadroom
raw := noMethod(o)
return jsonutil.MarshalJSON(raw, o.forceSendFields, o.nullFields)
}
func (o *GKELaunchSpecTaskHeadroom) SetCPUPerUnit(v *int) *GKELaunchSpecTaskHeadroom {
if o.CPUPerUnit = v; o.CPUPerUnit == nil {
o.nullFields = append(o.nullFields, "CPUPerUnit")
}
return o
}
func (o *GKELaunchSpecTaskHeadroom) SetGPUPerUnit(v *int) *GKELaunchSpecTaskHeadroom {
if o.GPUPerUnit = v; o.GPUPerUnit == nil {
o.nullFields = append(o.nullFields, "GPUPerUnit")
}
return o
}
func (o *GKELaunchSpecTaskHeadroom) SetMemoryPerUnit(v *int) *GKELaunchSpecTaskHeadroom {
if o.MemoryPerUnit = v; o.MemoryPerUnit == nil {
o.nullFields = append(o.nullFields, "MemoryPerUnit")
}
return o
}
func (o *GKELaunchSpecTaskHeadroom) SetNumOfUnits(v *int) *GKELaunchSpecTaskHeadroom {
if o.NumOfUnits = v; o.NumOfUnits == nil {
o.nullFields = append(o.nullFields, "NumOfUnits")
}
return o
}
// endregion

View File

@ -26,6 +26,8 @@ type Service interface {
ImportOceanGKECluster(ctx context.Context, input *ImportOceanGKEClusterInput) (*ImportOceanGKEClusterOutput, error)
ImportOceanGKELaunchSpec(ctx context.Context, input *ImportOceanGKELaunchSpecInput) (*ImportOceanGKELaunchSpecOutput, error)
CreateRoll(context.Context, *CreateRollInput) (*CreateRollOutput, error)
}
type ServiceOp struct {

View File

@ -1,7 +1,7 @@
package spotinst
// SDKVersion is the current version of the SDK.
const SDKVersion = "1.85.0"
const SDKVersion = "1.110.0"
// SDKName is the name of the SDK.
const SDKName = "spotinst-sdk-go"

12
vendor/gopkg.in/ini.v1/.editorconfig generated vendored Normal file
View File

@ -0,0 +1,12 @@
# http://editorconfig.org
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*_test.go]
trim_trailing_whitespace = false

1
vendor/gopkg.in/ini.v1/.gitignore generated vendored
View File

@ -4,3 +4,4 @@ ini.sublime-workspace
testdata/conf_reflect.ini
.idea
/.vscode
.DS_Store

21
vendor/gopkg.in/ini.v1/.golangci.yml generated vendored Normal file
View File

@ -0,0 +1,21 @@
linters-settings:
nakedret:
max-func-lines: 0 # Disallow any unnamed return statement
linters:
enable:
- deadcode
- errcheck
- gosimple
- govet
- ineffassign
- staticcheck
- structcheck
- typecheck
- unused
- varcheck
- nakedret
- gofmt
- rowserrcheck
- unconvert
- goimports

2
vendor/gopkg.in/ini.v1/README.md generated vendored
View File

@ -24,7 +24,7 @@ Package ini provides INI file read and write functionality in Go.
## Installation
The minimum requirement of Go is **1.6**.
The minimum requirement of Go is **1.12**.
```sh
$ go get gopkg.in/ini.v1

2
vendor/gopkg.in/ini.v1/codecov.yml generated vendored
View File

@ -6,4 +6,4 @@ coverage:
threshold: 1%
comment:
layout: 'diff, files'
layout: 'diff'

34
vendor/gopkg.in/ini.v1/file.go generated vendored
View File

@ -142,6 +142,12 @@ func (f *File) GetSection(name string) (*Section, error) {
return secs[0], err
}
// HasSection returns true if the file contains a section with given name.
func (f *File) HasSection(name string) bool {
section, _ := f.GetSection(name)
return section != nil
}
// SectionsByName returns all sections with given name.
func (f *File) SectionsByName(name string) ([]*Section, error) {
if len(name) == 0 {
@ -168,8 +174,9 @@ func (f *File) SectionsByName(name string) ([]*Section, error) {
func (f *File) Section(name string) *Section {
sec, err := f.GetSection(name)
if err != nil {
// Note: It's OK here because the only possible error is empty section name,
// but if it's empty, this piece of code won't be executed.
if name == "" {
name = DefaultSection
}
sec, _ = f.NewSection(name)
return sec
}
@ -435,16 +442,16 @@ func (f *File) writeToBuffer(indent string) (*bytes.Buffer, error) {
kname = `"""` + kname + `"""`
}
for _, val := range key.ValueWithShadows() {
writeKeyValue := func(val string) (bool, error) {
if _, err := buf.WriteString(kname); err != nil {
return nil, err
return false, err
}
if key.isBooleanType {
if kname != sec.keyList[len(sec.keyList)-1] {
buf.WriteString(LineBreak)
}
continue KeyList
return true, nil
}
// Write out alignment spaces before "=" sign
@ -461,10 +468,27 @@ func (f *File) writeToBuffer(indent string) (*bytes.Buffer, error) {
val = `"` + val + `"`
}
if _, err := buf.WriteString(equalSign + val + LineBreak); err != nil {
return false, err
}
return false, nil
}
shadows := key.ValueWithShadows()
if len(shadows) == 0 {
if _, err := writeKeyValue(""); err != nil {
return nil, err
}
}
for _, val := range shadows {
exitLoop, err := writeKeyValue(val)
if err != nil {
return nil, err
} else if exitLoop {
continue KeyList
}
}
for _, val := range key.nestedValues {
if _, err := buf.WriteString(indent + " " + val + LineBreak); err != nil {
return nil, err

4
vendor/gopkg.in/ini.v1/ini.go generated vendored
View File

@ -1,5 +1,3 @@
// +build go1.6
// Copyright 2014 Unknwon
//
// Licensed under the Apache License, Version 2.0 (the "License"): you may
@ -125,6 +123,8 @@ type LoadOptions struct {
ReaderBufferSize int
// AllowNonUniqueSections indicates whether to allow sections with the same name multiple times.
AllowNonUniqueSections bool
// AllowDuplicateShadowValues indicates whether values for shadowed keys should be deduplicated.
AllowDuplicateShadowValues bool
}
// DebugFunc is the type of function called to log parse events.

20
vendor/gopkg.in/ini.v1/key.go generated vendored
View File

@ -54,14 +54,16 @@ func (k *Key) addShadow(val string) error {
return errors.New("cannot add shadow to auto-increment or boolean key")
}
// Deduplicate shadows based on their values.
if k.value == val {
return nil
}
for i := range k.shadows {
if k.shadows[i].value == val {
if !k.s.f.options.AllowDuplicateShadowValues {
// Deduplicate shadows based on their values.
if k.value == val {
return nil
}
for i := range k.shadows {
if k.shadows[i].value == val {
return nil
}
}
}
shadow := newKey(k.s, k.name, val)
@ -111,6 +113,9 @@ func (k *Key) Value() string {
// ValueWithShadows returns raw values of key and its shadows if any.
func (k *Key) ValueWithShadows() []string {
if len(k.shadows) == 0 {
if k.value == "" {
return []string{}
}
return []string{k.value}
}
vals := make([]string, len(k.shadows)+1)
@ -781,10 +786,8 @@ func (k *Key) parseUint64s(strs []string, addInvalid, returnOnInvalid bool) ([]u
return vals, err
}
type Parser func(str string) (interface{}, error)
// parseTimesFormat transforms strings to times in given format.
func (k *Key) parseTimesFormat(format string, strs []string, addInvalid, returnOnInvalid bool) ([]time.Time, error) {
vals := make([]time.Time, 0, len(strs))
@ -801,7 +804,6 @@ func (k *Key) parseTimesFormat(format string, strs []string, addInvalid, returnO
return vals, err
}
// doParse transforms strings to different types
func (k *Key) doParse(strs []string, addInvalid, returnOnInvalid bool, parser Parser) ([]interface{}, error) {
vals := make([]interface{}, 0, len(strs))

38
vendor/gopkg.in/ini.v1/parser.go generated vendored
View File

@ -131,7 +131,7 @@ func readKeyName(delimiters string, in []byte) (string, int, error) {
// Check if key name surrounded by quotes.
var keyQuote string
if line[0] == '"' {
if len(line) > 6 && string(line[0:3]) == `"""` {
if len(line) > 6 && line[0:3] == `"""` {
keyQuote = `"""`
} else {
keyQuote = `"`
@ -232,7 +232,7 @@ func (p *parser) readValue(in []byte, bufferSize int) (string, error) {
}
var valQuote string
if len(line) > 3 && string(line[0:3]) == `"""` {
if len(line) > 3 && line[0:3] == `"""` {
valQuote = `"""`
} else if line[0] == '`' {
valQuote = "`"
@ -289,12 +289,8 @@ func (p *parser) readValue(in []byte, bufferSize int) (string, error) {
hasSurroundedQuote(line, '"')) && !p.options.PreserveSurroundedQuote {
line = line[1 : len(line)-1]
} else if len(valQuote) == 0 && p.options.UnescapeValueCommentSymbols {
if strings.Contains(line, `\;`) {
line = strings.Replace(line, `\;`, ";", -1)
}
if strings.Contains(line, `\#`) {
line = strings.Replace(line, `\#`, "#", -1)
}
line = strings.ReplaceAll(line, `\;`, ";")
line = strings.ReplaceAll(line, `\#`, "#")
} else if p.options.AllowPythonMultilineValues && lastChar == '\n' {
return p.readPythonMultilines(line, bufferSize)
}
@ -306,15 +302,9 @@ func (p *parser) readPythonMultilines(line string, bufferSize int) (string, erro
parserBufferPeekResult, _ := p.buf.Peek(bufferSize)
peekBuffer := bytes.NewBuffer(parserBufferPeekResult)
indentSize := 0
for {
peekData, peekErr := peekBuffer.ReadBytes('\n')
if peekErr != nil {
if peekErr == io.EOF {
p.debug("readPythonMultilines: io.EOF, peekData: %q, line: %q", string(peekData), line)
return line, nil
}
if peekErr != nil && peekErr != io.EOF {
p.debug("readPythonMultilines: failed to peek with error: %v", peekErr)
return "", peekErr
}
@ -333,19 +323,6 @@ func (p *parser) readPythonMultilines(line string, bufferSize int) (string, erro
return line, nil
}
// Determine indent size and line prefix.
currentIndentSize := len(peekMatches[1])
if indentSize < 1 {
indentSize = currentIndentSize
p.debug("readPythonMultilines: indent size is %d", indentSize)
}
// Make sure each line is indented at least as far as first line.
if currentIndentSize < indentSize {
p.debug("readPythonMultilines: end of value, current indent: %d, expected indent: %d, line: %q", currentIndentSize, indentSize, line)
return line, nil
}
// Advance the parser reader (buffer) in-sync with the peek buffer.
_, err := p.buf.Discard(len(peekData))
if err != nil {
@ -353,8 +330,7 @@ func (p *parser) readPythonMultilines(line string, bufferSize int) (string, erro
return "", err
}
// Handle indented empty line.
line += "\n" + peekMatches[1][indentSize:] + peekMatches[2]
line += "\n" + peekMatches[0]
}
}
@ -465,6 +441,8 @@ func (f *File) parse(reader io.Reader) (err error) {
// Reset auto-counter and comments
p.comment.Reset()
p.count = 1
// Nested values can't span sections
isLastValueEmpty = false
inUnparseableSection = false
for i := range f.options.UnparseableSections {

2
vendor/gopkg.in/ini.v1/section.go generated vendored
View File

@ -217,7 +217,7 @@ func (s *Section) KeysHash() map[string]string {
defer s.f.lock.RUnlock()
}
hash := map[string]string{}
hash := make(map[string]string, len(s.keysHash))
for key, value := range s.keysHash {
hash[key] = value
}

4
vendor/modules.txt generated vendored
View File

@ -709,7 +709,7 @@ github.com/spf13/pflag
# github.com/spf13/viper v1.8.1
## explicit; go 1.12
github.com/spf13/viper
# github.com/spotinst/spotinst-sdk-go v1.85.0
# github.com/spotinst/spotinst-sdk-go v1.110.0
## explicit; go 1.16
github.com/spotinst/spotinst-sdk-go/service/elastigroup
github.com/spotinst/spotinst-sdk-go/service/elastigroup/providers/aws
@ -1012,7 +1012,7 @@ gopkg.in/gcfg.v1/types
# gopkg.in/inf.v0 v0.9.1
## explicit
gopkg.in/inf.v0
# gopkg.in/ini.v1 v1.62.0
# gopkg.in/ini.v1 v1.66.3
## explicit
gopkg.in/ini.v1
# gopkg.in/square/go-jose.v2 v2.5.1