Skip to content

Commit 0334d8b

Browse files
author
Darren Bathgate
committed
Added ssh connection rate limiting feature
- allows enabling ssh connection rate limiting - adds configurable amount of max connections per duration window - adds configurable duration window
1 parent 09c9679 commit 0334d8b

38 files changed

+380
-77
lines changed

bosh/build_client.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package bosh
22

33
import (
44
"github.com/cloudfoundry-incubator/bosh-backup-and-restore/instance"
5+
"github.com/cloudfoundry-incubator/bosh-backup-and-restore/ratelimiter"
56
"github.com/cloudfoundry-incubator/bosh-backup-and-restore/ssh"
67
"github.com/cloudfoundry/bosh-cli/v7/director"
78
"github.com/pkg/errors"
@@ -10,7 +11,7 @@ import (
1011
boshlog "github.com/cloudfoundry/bosh-utils/logger"
1112
)
1213

13-
func BuildClient(targetUrl, username, password, caCert, bbrVersion string, logger boshlog.Logger) (Client, error) {
14+
func BuildClient(targetUrl, username, password, caCert, bbrVersion string, rateLimiter ratelimiter.RateLimiter, logger boshlog.Logger) (Client, error) {
1415
var client Client
1516

1617
factoryConfig, err := director.NewConfigFromURL(targetUrl)
@@ -44,7 +45,7 @@ func BuildClient(targetUrl, username, password, caCert, bbrVersion string, logge
4445
return client, errors.Wrap(err, "error building bosh director client")
4546
}
4647

47-
return NewClient(boshDirector, director.NewSSHOpts, ssh.NewSshRemoteRunner, logger, instance.NewJobFinder(bbrVersion, logger), NewBoshManifestQuerier), nil
48+
return NewClient(boshDirector, director.NewSSHOpts, ssh.NewSshRemoteRunner, rateLimiter, logger, instance.NewJobFinder(bbrVersion, logger), NewBoshManifestQuerier), nil
4849
}
4950

5051
func getDirectorInfo(directorFactory director.Factory, factoryConfig director.FactoryConfig) (director.Info, error) {

bosh/build_client_test.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"github.com/cloudfoundry-incubator/bosh-backup-and-restore/internal/cf-webmock/mockbosh"
99
"github.com/cloudfoundry-incubator/bosh-backup-and-restore/internal/cf-webmock/mockhttp"
1010
"github.com/cloudfoundry-incubator/bosh-backup-and-restore/internal/cf-webmock/mockuaa"
11+
"github.com/cloudfoundry-incubator/bosh-backup-and-restore/ratelimiter"
1112
boshlog "github.com/cloudfoundry/bosh-utils/logger"
1213
. "github.com/onsi/ginkgo/v2"
1314
. "github.com/onsi/gomega"
@@ -50,7 +51,7 @@ var _ = Describe("BuildClient", func() {
5051
mockbosh.Manifest(deploymentName).RespondsWith([]byte("manifest contents")),
5152
)
5253

53-
client, err := BuildClient(director.URL, username, password, caCert, bbrVersion, logger)
54+
client, err := BuildClient(director.URL, username, password, caCert, bbrVersion, ratelimiter.NoOpRateLimiter{}, logger)
5455

5556
Expect(err).NotTo(HaveOccurred())
5657
manifest, err := client.GetManifest(deploymentName)
@@ -75,7 +76,7 @@ var _ = Describe("BuildClient", func() {
7576
mockbosh.Manifest(deploymentName).RespondsWith([]byte("manifest contents")),
7677
)
7778

78-
client, err := BuildClient(director.URL, username, password, caCert, bbrVersion, logger)
79+
client, err := BuildClient(director.URL, username, password, caCert, bbrVersion, ratelimiter.NoOpRateLimiter{}, logger)
7980

8081
Expect(err).NotTo(HaveOccurred())
8182
manifest, err := client.GetManifest(deploymentName)
@@ -90,7 +91,7 @@ var _ = Describe("BuildClient", func() {
9091
director.VerifyAndMock(
9192
mockbosh.Info().WithAuthTypeUAA(""),
9293
)
93-
_, err := BuildClient(director.URL, username, password, caCert, bbrVersion, logger)
94+
_, err := BuildClient(director.URL, username, password, caCert, bbrVersion, ratelimiter.NoOpRateLimiter{}, logger)
9495

9596
Expect(err).To(MatchError(ContainSubstring("invalid UAA URL")))
9697

@@ -103,7 +104,7 @@ var _ = Describe("BuildClient", func() {
103104
caCertPath := "-----BEGIN"
104105
basicAuthDirectorURL := director.URL
105106

106-
_, err := BuildClient(basicAuthDirectorURL, username, password, caCertPath, bbrVersion, logger)
107+
_, err := BuildClient(basicAuthDirectorURL, username, password, caCertPath, bbrVersion, ratelimiter.NoOpRateLimiter{}, logger)
107108
Expect(err).To(MatchError(ContainSubstring("Missing PEM block")))
108109
})
109110

@@ -113,7 +114,7 @@ var _ = Describe("BuildClient", func() {
113114
caCertPath := ""
114115
basicAuthDirectorURL := ""
115116

116-
_, err := BuildClient(basicAuthDirectorURL, username, password, caCertPath, bbrVersion, logger)
117+
_, err := BuildClient(basicAuthDirectorURL, username, password, caCertPath, bbrVersion, ratelimiter.NoOpRateLimiter{}, logger)
117118
Expect(err).To(MatchError(ContainSubstring("invalid bosh URL")))
118119
})
119120

@@ -125,7 +126,7 @@ var _ = Describe("BuildClient", func() {
125126
mockbosh.Info().Fails("fooo!"),
126127
)
127128

128-
_, err := BuildClient(director.URL, username, password, caCert, bbrVersion, logger)
129+
_, err := BuildClient(director.URL, username, password, caCert, bbrVersion, ratelimiter.NoOpRateLimiter{}, logger)
129130
Expect(err).To(MatchError(ContainSubstring("bosh director unreachable or unhealthy")))
130131
})
131132
})

bosh/client.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55

66
"github.com/cloudfoundry-incubator/bosh-backup-and-restore/instance"
77
"github.com/cloudfoundry-incubator/bosh-backup-and-restore/orchestrator"
8+
"github.com/cloudfoundry-incubator/bosh-backup-and-restore/ratelimiter"
89
"github.com/cloudfoundry-incubator/bosh-backup-and-restore/ssh"
910
"github.com/cloudfoundry/bosh-cli/v7/director"
1011
"github.com/cloudfoundry/bosh-utils/uuid"
@@ -25,13 +26,15 @@ type BoshClient interface {
2526
func NewClient(boshDirector director.Director,
2627
sshOptsGenerator ssh.SSHOptsGenerator,
2728
remoteRunnerFactory ssh.RemoteRunnerFactory,
29+
rateLimiter ratelimiter.RateLimiter,
2830
logger Logger,
2931
jobFinder instance.JobFinder,
3032
manifestQuerierCreator instance.ManifestQuerierCreator) Client {
3133
return Client{
3234
Director: boshDirector,
3335
SSHOptsGenerator: sshOptsGenerator,
3436
RemoteRunnerFactory: remoteRunnerFactory,
37+
RateLimiter: rateLimiter,
3538
Logger: logger,
3639
jobFinder: jobFinder,
3740
manifestQuerierCreator: manifestQuerierCreator,
@@ -42,6 +45,7 @@ type Client struct {
4245
director.Director
4346
ssh.SSHOptsGenerator
4447
ssh.RemoteRunnerFactory
48+
ratelimiter.RateLimiter
4549
Logger
4650
jobFinder instance.JobFinder
4751
manifestQuerierCreator instance.ManifestQuerierCreator
@@ -112,7 +116,7 @@ func (c Client) FindInstances(deploymentName string) ([]orchestrator.Instance, e
112116
return nil, errors.Wrap(err, "ssh.NewConnection.ParseAuthorizedKey failed")
113117
}
114118

115-
remoteRunner, err := c.RemoteRunnerFactory(host.Host, host.Username, privateKey, gossh.FixedHostKey(hostPublicKey), supportedEncryptionAlgorithms(hostPublicKey), c.Logger)
119+
remoteRunner, err := c.RemoteRunnerFactory(host.Host, host.Username, privateKey, gossh.FixedHostKey(hostPublicKey), supportedEncryptionAlgorithms(hostPublicKey), c.RateLimiter, c.Logger)
116120
if err != nil {
117121
cleanupAlreadyMadeConnections(deployment, slugs, sshOpts)
118122
return nil, errors.Wrap(err, "failed to connect using ssh")

bosh/client_test.go

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"github.com/cloudfoundry-incubator/bosh-backup-and-restore/instance"
1313
instancefakes "github.com/cloudfoundry-incubator/bosh-backup-and-restore/instance/fakes"
1414
"github.com/cloudfoundry-incubator/bosh-backup-and-restore/orchestrator"
15+
"github.com/cloudfoundry-incubator/bosh-backup-and-restore/ratelimiter"
1516
"github.com/cloudfoundry-incubator/bosh-backup-and-restore/ssh"
1617
sshfakes "github.com/cloudfoundry-incubator/bosh-backup-and-restore/ssh/fakes"
1718
"github.com/cloudfoundry/bosh-cli/v7/director"
@@ -43,7 +44,7 @@ var _ = Describe("Director", func() {
4344
var b bosh.BoshClient
4445

4546
JustBeforeEach(func() {
46-
b = bosh.NewClient(boshDirector, optsGenerator.Spy, remoteRunnerFactory.Spy, boshLogger, fakeJobFinder, manifestQuerierCreator.Spy)
47+
b = bosh.NewClient(boshDirector, optsGenerator.Spy, remoteRunnerFactory.Spy, ratelimiter.NoOpRateLimiter{}, boshLogger, fakeJobFinder, manifestQuerierCreator.Spy)
4748
})
4849

4950
BeforeEach(func() {
@@ -166,7 +167,7 @@ var _ = Describe("Director", func() {
166167

167168
It("creates a remote runner for each host", func() {
168169
Expect(remoteRunnerFactory.CallCount()).To(Equal(1))
169-
host, username, privateKey, _, hostPublicKeyAlgorithm, logger := remoteRunnerFactory.ArgsForCall(0)
170+
host, username, privateKey, _, hostPublicKeyAlgorithm, _, logger := remoteRunnerFactory.ArgsForCall(0)
170171
Expect(host).To(Equal("10.0.0.0"))
171172
Expect(username).To(Equal("username"))
172173
Expect(privateKey).To(Equal("private_key"))
@@ -195,7 +196,7 @@ var _ = Describe("Director", func() {
195196

196197
It("uses the specified port", func() {
197198
Expect(remoteRunnerFactory.CallCount()).To(Equal(1))
198-
host, username, privateKey, _, hostPublicKeyAlgorithm, logger := remoteRunnerFactory.ArgsForCall(0)
199+
host, username, privateKey, _, hostPublicKeyAlgorithm, _, logger := remoteRunnerFactory.ArgsForCall(0)
199200
Expect(host).To(Equal("10.0.0.0:3457"))
200201
Expect(username).To(Equal("username"))
201202
Expect(privateKey).To(Equal("private_key"))
@@ -328,14 +329,14 @@ var _ = Describe("Director", func() {
328329
It("creates a remote runner for each host", func() {
329330
Expect(remoteRunnerFactory.CallCount()).To(Equal(2))
330331

331-
host, username, privateKey, _, hostPublicKeyAlgorithm, logger := remoteRunnerFactory.ArgsForCall(0)
332+
host, username, privateKey, _, hostPublicKeyAlgorithm, _, logger := remoteRunnerFactory.ArgsForCall(0)
332333
Expect(host).To(Equal("10.0.0.1"))
333334
Expect(username).To(Equal("username"))
334335
Expect(privateKey).To(Equal("private_key"))
335336
Expect(hostPublicKeyAlgorithm).To(Equal(hostKeyAlgorithmRSA))
336337
Expect(logger).To(Equal(boshLogger))
337338

338-
host, username, privateKey, _, hostPublicKeyAlgorithm, logger = remoteRunnerFactory.ArgsForCall(1)
339+
host, username, privateKey, _, hostPublicKeyAlgorithm, _, logger = remoteRunnerFactory.ArgsForCall(1)
339340
Expect(host).To(Equal("10.0.0.2"))
340341
Expect(username).To(Equal("username"))
341342
Expect(privateKey).To(Equal("private_key"))
@@ -621,21 +622,21 @@ var _ = Describe("Director", func() {
621622
It("creates a remote runner for each host that has scripts, and the first instance of each group that doesn't", func() {
622623
Expect(remoteRunnerFactory.CallCount()).To(Equal(3))
623624

624-
host, username, privateKey, _, hostPublicKeyAlgorithm, logger := remoteRunnerFactory.ArgsForCall(0)
625+
host, username, privateKey, _, hostPublicKeyAlgorithm, _, logger := remoteRunnerFactory.ArgsForCall(0)
625626
Expect(host).To(Equal("10.0.0.1"))
626627
Expect(username).To(Equal("username"))
627628
Expect(privateKey).To(Equal("private_key"))
628629
Expect(hostPublicKeyAlgorithm).To(Equal(hostKeyAlgorithmRSA))
629630
Expect(logger).To(Equal(boshLogger))
630631

631-
host, username, privateKey, _, hostPublicKeyAlgorithm, logger = remoteRunnerFactory.ArgsForCall(1)
632+
host, username, privateKey, _, hostPublicKeyAlgorithm, _, logger = remoteRunnerFactory.ArgsForCall(1)
632633
Expect(host).To(Equal("10.0.0.3"))
633634
Expect(username).To(Equal("username"))
634635
Expect(privateKey).To(Equal("private_key"))
635636
Expect(hostPublicKeyAlgorithm).To(Equal(hostKeyAlgorithmRSA))
636637
Expect(logger).To(Equal(boshLogger))
637638

638-
host, username, privateKey, _, hostPublicKeyAlgorithm, logger = remoteRunnerFactory.ArgsForCall(2)
639+
host, username, privateKey, _, hostPublicKeyAlgorithm, _, logger = remoteRunnerFactory.ArgsForCall(2)
639640
Expect(host).To(Equal("10.0.0.4"))
640641
Expect(username).To(Equal("username"))
641642
Expect(privateKey).To(Equal("private_key"))
@@ -689,7 +690,7 @@ var _ = Describe("Director", func() {
689690

690691
It("uses the ECDSA algorithm to create its remote runners", func() {
691692
Expect(remoteRunnerFactory.CallCount()).To(Equal(1))
692-
_, _, _, _, hostPublicKeyAlgorithm, _ := remoteRunnerFactory.ArgsForCall(0)
693+
_, _, _, _, hostPublicKeyAlgorithm, _, _ := remoteRunnerFactory.ArgsForCall(0)
693694
Expect(hostPublicKeyAlgorithm).To(Equal(hostKeyAlgorithmECDSA))
694695
})
695696

@@ -995,7 +996,7 @@ var _ = Describe("Director", func() {
995996
}}, nil
996997
}
997998

998-
remoteRunnerFactory.Stub = func(host, user, privateKey string, publicKeyCallback gossh.HostKeyCallback, publicKeyAlgorithm []string, logger ssh.Logger) (ssh.RemoteRunner, error) {
999+
remoteRunnerFactory.Stub = func(host, user, privateKey string, publicKeyCallback gossh.HostKeyCallback, publicKeyAlgorithm []string, rateLimiter ratelimiter.RateLimiter, logger ssh.Logger) (ssh.RemoteRunner, error) {
9991000
if host == "10.0.0.0_job1" {
10001001
return remoteRunner, nil
10011002
}

cli/command/all_deployments.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/cloudfoundry-incubator/bosh-backup-and-restore/executor/deployment"
1616
"github.com/cloudfoundry-incubator/bosh-backup-and-restore/factory"
1717
"github.com/cloudfoundry-incubator/bosh-backup-and-restore/orchestrator"
18+
"github.com/cloudfoundry-incubator/bosh-backup-and-restore/ratelimiter"
1819
"github.com/urfave/cli"
1920
)
2021

@@ -128,6 +129,18 @@ func getDeploymentParams(c *cli.Context) (string, string, string, string, string
128129
return username, password, target, caCert, bbrVersion, debug, deployment, allDeployments
129130
}
130131

132+
func getConnectionRateLimiter(c *cli.Context) (ratelimiter.RateLimiter, error) {
133+
enabled := c.Parent().Bool("rate-limiting")
134+
maxConnections := c.Parent().Int("rate-limiting-max-connections")
135+
durationSeconds := c.Parent().Int("rate-limiting-duration-seconds")
136+
137+
if enabled {
138+
return ratelimiter.NewConnectionRateLimiter(maxConnections, durationSeconds)
139+
}
140+
return ratelimiter.NewNoOpRateLimiter(), nil
141+
142+
}
143+
131144
type DeploymentExecutable struct {
132145
action ActionFunc
133146
name string

cli/command/deployment_backup.go

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"github.com/cloudfoundry-incubator/bosh-backup-and-restore/executor/deployment"
88
"github.com/cloudfoundry-incubator/bosh-backup-and-restore/factory"
99
"github.com/cloudfoundry-incubator/bosh-backup-and-restore/orchestrator"
10+
"github.com/cloudfoundry-incubator/bosh-backup-and-restore/ratelimiter"
1011
"github.com/urfave/cli"
1112
)
1213

@@ -50,17 +51,23 @@ func (d DeploymentBackupCommand) Action(c *cli.Context) error {
5051
unsafeLockFree := c.Bool("unsafe-lock-free")
5152
artifactPath := c.String("artifact-path")
5253

54+
rateLimiter, err := getConnectionRateLimiter(c)
55+
56+
if err != nil {
57+
return err
58+
}
59+
5360
if allDeployments {
5461
if unsafeLockFree {
5562
return processError(orchestrator.NewError(fmt.Errorf("Cannot use the --unsafe-lock-free flag in conjunction with the --all-deployments flag")))
5663
}
57-
return backupAll(target, username, password, caCert, artifactPath, withManifest, bbrVersion, debug)
64+
return backupAll(target, username, password, caCert, artifactPath, withManifest, bbrVersion, debug, rateLimiter)
5865
}
5966

60-
return backupSingleDeployment(deployment, target, username, password, caCert, artifactPath, withManifest, bbrVersion, unsafeLockFree, debug)
67+
return backupSingleDeployment(deployment, target, username, password, caCert, artifactPath, withManifest, bbrVersion, unsafeLockFree, debug, rateLimiter)
6168
}
6269

63-
func backupAll(target, username, password, caCert, artifactPath string, withManifest bool, bbrVersion string, debug bool) error {
70+
func backupAll(target, username, password, caCert, artifactPath string, withManifest bool, bbrVersion string, debug bool, rateLimiter ratelimiter.RateLimiter) error {
6471
backupAction := func(deploymentName string) orchestrator.Error {
6572
timestamp := time.Now().UTC().Format(artifactTimeStampFormat)
6673
logFilePath, buffer, logger, logErr := createLogger(timestamp, artifactPath, deploymentName, debug)
@@ -76,6 +83,7 @@ func backupAll(target, username, password, caCert, artifactPath string, withMani
7683
withManifest,
7784
false,
7885
bbrVersion,
86+
rateLimiter,
7987
logger,
8088
timestamp,
8189
)
@@ -106,7 +114,7 @@ func backupAll(target, username, password, caCert, artifactPath string, withMani
106114
fmt.Println("Starting backup...")
107115

108116
logger, _ := factory.BuildBoshLoggerWithCustomBuffer(debug)
109-
boshClient, err := factory.BuildBoshClient(target, username, password, caCert, bbrVersion, logger)
117+
boshClient, err := factory.BuildBoshClient(target, username, password, caCert, bbrVersion, rateLimiter, logger)
110118
if err != nil {
111119
return processError(orchestrator.NewError(err))
112120
}
@@ -119,11 +127,11 @@ func backupAll(target, username, password, caCert, artifactPath string, withMani
119127
deployment.NewParallelExecutor())
120128
}
121129

122-
func backupSingleDeployment(deployment, target, username, password, caCert, artifactPath string, withManifest bool, bbrVersion string, unsafeLockFree, debug bool) error {
130+
func backupSingleDeployment(deployment, target, username, password, caCert, artifactPath string, withManifest bool, bbrVersion string, unsafeLockFree, debug bool, rateLimiter ratelimiter.RateLimiter) error {
123131
logger := factory.BuildBoshLogger(debug)
124132
timeStamp := time.Now().UTC().Format(artifactTimeStampFormat)
125133

126-
backuper, err := factory.BuildDeploymentBackuper(target, username, password, caCert, withManifest, unsafeLockFree, bbrVersion, logger, timeStamp)
134+
backuper, err := factory.BuildDeploymentBackuper(target, username, password, caCert, withManifest, unsafeLockFree, bbrVersion, rateLimiter, logger, timeStamp)
127135
if err != nil {
128136
return processError(orchestrator.NewError(err))
129137
}

cli/command/deployment_backup_cleanup.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"time"
66

77
"github.com/cloudfoundry-incubator/bosh-backup-and-restore/executor/deployment"
8+
"github.com/cloudfoundry-incubator/bosh-backup-and-restore/ratelimiter"
89

910
"github.com/cloudfoundry-incubator/bosh-backup-and-restore/factory"
1011
"github.com/cloudfoundry-incubator/bosh-backup-and-restore/orchestrator"
@@ -31,6 +32,12 @@ func (d DeploymentBackupCleanupCommand) Action(c *cli.Context) error {
3132

3233
username, password, target, caCert, bbrVersion, debug, deployment, allDeployments := getDeploymentParams(c)
3334

35+
rateLimiter, err := getConnectionRateLimiter(c)
36+
37+
if err != nil {
38+
return err
39+
}
40+
3441
if !allDeployments {
3542
logger := factory.BuildBoshLogger(debug)
3643

@@ -40,6 +47,7 @@ func (d DeploymentBackupCleanupCommand) Action(c *cli.Context) error {
4047
password,
4148
caCert,
4249
c.App.Version,
50+
rateLimiter,
4351
logger,
4452
)
4553
if err != nil {
@@ -50,10 +58,10 @@ func (d DeploymentBackupCleanupCommand) Action(c *cli.Context) error {
5058
return processError(cleanupErr)
5159
}
5260

53-
return cleanupAllDeployments(target, username, password, caCert, bbrVersion, debug)
61+
return cleanupAllDeployments(target, username, password, caCert, bbrVersion, debug, rateLimiter)
5462
}
5563

56-
func cleanupAllDeployments(target, username, password, caCert, bbrVersion string, debug bool) error {
64+
func cleanupAllDeployments(target, username, password, caCert, bbrVersion string, debug bool, rateLimiter ratelimiter.RateLimiter) error {
5765
cleanupAction := func(deploymentName string) orchestrator.Error {
5866
timestamp := time.Now().UTC().Format(artifactTimeStampFormat)
5967
logFilePath, buffer, logger, logErr := createLogger(timestamp, "", deploymentName, debug)
@@ -67,6 +75,7 @@ func cleanupAllDeployments(target, username, password, caCert, bbrVersion string
6775
password,
6876
caCert,
6977
bbrVersion,
78+
rateLimiter,
7079
logger,
7180
)
7281

@@ -93,7 +102,7 @@ func cleanupAllDeployments(target, username, password, caCert, bbrVersion string
93102

94103
logger, _ := factory.BuildBoshLoggerWithCustomBuffer(debug)
95104

96-
boshClient, err := factory.BuildBoshClient(target, username, password, caCert, bbrVersion, logger)
105+
boshClient, err := factory.BuildBoshClient(target, username, password, caCert, bbrVersion, rateLimiter, logger)
97106
if err != nil {
98107
return err
99108
}

cli/command/deployment_pre_backup_check.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,20 @@ func (d DeploymentPreBackupCheck) Cli() cli.Command {
3030

3131
func (d DeploymentPreBackupCheck) Action(c *cli.Context) error {
3232
username, password, target, caCert, bbrVersion, debug, deployment, allDeployments := getDeploymentParams(c)
33+
34+
rateLimiter, err := getConnectionRateLimiter(c)
35+
36+
if err != nil {
37+
return err
38+
}
39+
3340
var logger logger.Logger
3441
if allDeployments {
3542
logger, _ = factory.BuildBoshLoggerWithCustomBuffer(debug)
3643
} else {
3744
logger = factory.BuildBoshLogger(debug)
3845
}
39-
boshClient, err := factory.BuildBoshClient(target, username, password, caCert, bbrVersion, logger)
46+
boshClient, err := factory.BuildBoshClient(target, username, password, caCert, bbrVersion, rateLimiter, logger)
4047
if err != nil {
4148
return processError(orchestrator.NewError(err))
4249
}

0 commit comments

Comments
 (0)