1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
11 "git.curoverse.com/arvados.git/lib/cloud"
12 "git.curoverse.com/arvados.git/lib/cloud/azure"
13 "git.curoverse.com/arvados.git/lib/cloud/ec2"
14 "git.curoverse.com/arvados.git/sdk/go/arvados"
15 "github.com/sirupsen/logrus"
16 "golang.org/x/crypto/ssh"
19 var drivers = map[string]cloud.Driver{
20 "azure": azure.Driver,
24 func newInstanceSet(cluster *arvados.Cluster, setID cloud.InstanceSetID, logger logrus.FieldLogger) (cloud.InstanceSet, error) {
25 driver, ok := drivers[cluster.Containers.CloudVMs.Driver]
27 return nil, fmt.Errorf("unsupported cloud driver %q", cluster.Containers.CloudVMs.Driver)
29 sharedResourceTags := cloud.SharedResourceTags(cluster.Containers.CloudVMs.ResourceTags)
30 is, err := driver.InstanceSet(cluster.Containers.CloudVMs.DriverParameters, setID, sharedResourceTags, logger)
31 if maxops := cluster.Containers.CloudVMs.MaxCloudOpsPerSecond; maxops > 0 {
32 is = rateLimitedInstanceSet{
34 ticker: time.NewTicker(time.Second / time.Duration(maxops)),
37 is = defaultTaggingInstanceSet{
39 defaultTags: cloud.InstanceTags(cluster.Containers.CloudVMs.ResourceTags),
41 is = filteringInstanceSet{
48 type rateLimitedInstanceSet struct {
53 func (is rateLimitedInstanceSet) Create(it arvados.InstanceType, image cloud.ImageID, tags cloud.InstanceTags, init cloud.InitCommand, pk ssh.PublicKey) (cloud.Instance, error) {
55 inst, err := is.InstanceSet.Create(it, image, tags, init, pk)
56 return &rateLimitedInstance{inst, is.ticker}, err
59 type rateLimitedInstance struct {
64 func (inst *rateLimitedInstance) Destroy() error {
66 return inst.Instance.Destroy()
69 // Adds the specified defaultTags to every Create() call.
70 type defaultTaggingInstanceSet struct {
72 defaultTags cloud.InstanceTags
75 func (is defaultTaggingInstanceSet) Create(it arvados.InstanceType, image cloud.ImageID, tags cloud.InstanceTags, init cloud.InitCommand, pk ssh.PublicKey) (cloud.Instance, error) {
76 allTags := cloud.InstanceTags{}
77 for k, v := range is.defaultTags {
80 for k, v := range tags {
83 return is.InstanceSet.Create(it, image, allTags, init, pk)
86 // Filters the instances returned by the wrapped InstanceSet's
87 // Instances() method (in case the wrapped InstanceSet didn't do this
89 type filteringInstanceSet struct {
91 logger logrus.FieldLogger
94 func (is filteringInstanceSet) Instances(tags cloud.InstanceTags) ([]cloud.Instance, error) {
95 instances, err := is.InstanceSet.Instances(tags)
98 var returning []cloud.Instance
100 for _, inst := range instances {
101 instTags := inst.Tags()
102 for k, v := range tags {
103 if instTags[k] != v {
105 continue nextInstance
108 returning = append(returning, inst)
110 is.logger.WithFields(logrus.Fields{
111 "returning": len(returning),
113 }).WithError(err).Debugf("filteringInstanceSet returning instances")
114 return returning, err