Skip to content

Commit 4a7763e

Browse files
committed
TUN-3998: Allow to cleanup the connections of a tunnel limited to a single client
1 parent 9767ba1 commit 4a7763e

File tree

5 files changed

+52
-7
lines changed

5 files changed

+52
-7
lines changed

cmd/cloudflared/tunnel/subcommand_context.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ func (sc *subcommandContext) delete(tunnelIDs []uuid.UUID) error {
224224
return fmt.Errorf("Tunnel %s has already been deleted", tunnel.ID)
225225
}
226226
if forceFlagSet {
227-
if err := client.CleanupConnections(tunnel.ID); err != nil {
227+
if err := client.CleanupConnections(tunnel.ID, tunnelstore.NewCleanupParams()); err != nil {
228228
return errors.Wrapf(err, "Error cleaning up connections for tunnel %s", tunnel.ID)
229229
}
230230
}
@@ -276,13 +276,24 @@ func (sc *subcommandContext) run(tunnelID uuid.UUID) error {
276276
}
277277

278278
func (sc *subcommandContext) cleanupConnections(tunnelIDs []uuid.UUID) error {
279+
params := tunnelstore.NewCleanupParams()
280+
extraLog := ""
281+
if connector := sc.c.String("connector-id"); connector != "" {
282+
connectorID, err := uuid.Parse(connector)
283+
if err != nil {
284+
return errors.Wrapf(err, "%s is not a valid client ID (must be a UUID)", connector)
285+
}
286+
params.ForClient(connectorID)
287+
extraLog = fmt.Sprintf(" for connector-id %s", connectorID.String())
288+
}
289+
279290
client, err := sc.client()
280291
if err != nil {
281292
return err
282293
}
283294
for _, tunnelID := range tunnelIDs {
284-
sc.log.Info().Msgf("Cleanup connection for tunnel %s", tunnelID)
285-
if err := client.CleanupConnections(tunnelID); err != nil {
295+
sc.log.Info().Msgf("Cleanup connection for tunnel %s%s", tunnelID, extraLog)
296+
if err := client.CleanupConnections(tunnelID, params); err != nil {
286297
sc.log.Error().Msgf("Error cleaning up connections for tunnel %v, error :%v", tunnelID, err)
287298
}
288299
}

cmd/cloudflared/tunnel/subcommand_context_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@ import (
44
"encoding/base64"
55
"flag"
66
"fmt"
7-
"github.com/rs/zerolog"
87
"reflect"
98
"testing"
109
"time"
1110

11+
"github.com/rs/zerolog"
12+
1213
"github.com/cloudflare/cloudflared/connection"
1314
"github.com/cloudflare/cloudflared/tunnelstore"
1415
"github.com/google/uuid"
@@ -260,7 +261,7 @@ func (d *deleteMockTunnelStore) DeleteTunnel(tunnelID uuid.UUID) error {
260261
return nil
261262
}
262263

263-
func (d *deleteMockTunnelStore) CleanupConnections(tunnelID uuid.UUID) error {
264+
func (d *deleteMockTunnelStore) CleanupConnections(tunnelID uuid.UUID, _ *tunnelstore.CleanupParams) error {
264265
tunnel, ok := d.mockTunnels[tunnelID]
265266
if !ok {
266267
return fmt.Errorf("Couldn't find tunnel: %v", tunnelID)

cmd/cloudflared/tunnel/subcommands.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,12 @@ var (
126126
Usage: "Inverts the sort order of the tunnel info.",
127127
EnvVars: []string{"TUNNEL_INFO_INVERT_SORT"},
128128
}
129+
cleanupClientFlag = &cli.StringFlag{
130+
Name: "connector-id",
131+
Aliases: []string{"c"},
132+
Usage: `Constraints the cleanup to stop the connections of a single Connector (by its ID). You can find the various Connectors (and their IDs) currently connected to your tunnel via 'cloudflared tunnel info <name>'.`,
133+
EnvVars: []string{"TUNNEL_CLEANUP_CONNECTOR"},
134+
}
129135
)
130136

131137
func buildCreateCommand() *cli.Command {
@@ -600,6 +606,7 @@ func buildCleanupCommand() *cli.Command {
600606
Usage: "Cleanup tunnel connections",
601607
UsageText: "cloudflared tunnel [tunnel command options] cleanup [subcommand options] TUNNEL",
602608
Description: "Delete connections for tunnels with the given UUIDs or names.",
609+
Flags: []cli.Flag{cleanupClientFlag},
603610
CustomHelpTemplate: commandHelpTemplate(),
604611
}
605612
}

tunnelstore/cleanup_params.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package tunnelstore
2+
3+
import (
4+
"net/url"
5+
6+
"github.com/google/uuid"
7+
)
8+
9+
type CleanupParams struct {
10+
queryParams url.Values
11+
}
12+
13+
func NewCleanupParams() *CleanupParams {
14+
return &CleanupParams{
15+
queryParams: url.Values{},
16+
}
17+
}
18+
19+
func (cp *CleanupParams) ForClient(clientID uuid.UUID) {
20+
cp.queryParams.Set("client_id", clientID.String())
21+
}
22+
23+
func (cp CleanupParams) encode() string {
24+
return cp.queryParams.Encode()
25+
}

tunnelstore/client.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ type Client interface {
204204
DeleteTunnel(tunnelID uuid.UUID) error
205205
ListTunnels(filter *Filter) ([]*Tunnel, error)
206206
ListActiveClients(tunnelID uuid.UUID) ([]*ActiveClient, error)
207-
CleanupConnections(tunnelID uuid.UUID) error
207+
CleanupConnections(tunnelID uuid.UUID, params *CleanupParams) error
208208
RouteTunnel(tunnelID uuid.UUID, route Route) (RouteResult, error)
209209

210210
// Teamnet endpoints
@@ -370,8 +370,9 @@ func parseConnectionsDetails(reader io.Reader) ([]*ActiveClient, error) {
370370
return clients, err
371371
}
372372

373-
func (r *RESTClient) CleanupConnections(tunnelID uuid.UUID) error {
373+
func (r *RESTClient) CleanupConnections(tunnelID uuid.UUID, params *CleanupParams) error {
374374
endpoint := r.baseEndpoints.accountLevel
375+
endpoint.RawQuery = params.encode()
375376
endpoint.Path = path.Join(endpoint.Path, fmt.Sprintf("%v/connections", tunnelID))
376377
resp, err := r.sendRequest("DELETE", endpoint, nil)
377378
if err != nil {

0 commit comments

Comments
 (0)