From 2ec3efd877cf8fd80239eb20ef1c360856b1adaa Mon Sep 17 00:00:00 2001 From: Alvaro Saurin Date: Mon, 27 Jan 2020 16:11:42 +0100 Subject: [PATCH] New --prune option for delete Signed-off-by: Alvaro Saurin --- cli/commands.go | 20 +++++++++++++++++ cli/network.go | 55 +++++++++++++++++++++++++++++++++++++++-------- main.go | 4 ++-- tests/01-basic.sh | 18 ++++++++++++---- 4 files changed, 82 insertions(+), 15 deletions(-) diff --git a/cli/commands.go b/cli/commands.go index be6b6320..a0bd96bb 100644 --- a/cli/commands.go +++ b/cli/commands.go @@ -383,6 +383,26 @@ func DeleteCluster(c *cli.Context) error { log.Warningf("Couldn't disconnect Registry from network %s\n%+v", cluster.name, err) } + if c.IsSet("prune") { + // disconnect any other container that is connected to the k3d network + nid, err := getClusterNetwork(cluster.name) + if err != nil { + log.Warningf("Couldn't get the network for cluster %q\n%+v", cluster.name, err) + } + cids, err := getContainersInNetwork(nid) + if err != nil { + log.Warningf("Couldn't get the list of containers connected to network %q\n%+v", nid, err) + } + for _, cid := range cids { + err := disconnectContainerFromNetwork(cid, nid) + if err != nil { + log.Warningf("Couldn't disconnect container %q from network %q", cid, nid) + continue + } + log.Printf("...%q has been forced to disconnect from %q's network", cid, cluster.name) + } + } + if err := deleteClusterNetwork(cluster.name); err != nil { log.Warningf("Couldn't delete cluster network for cluster %s\n%+v", cluster.name, err) } diff --git a/cli/network.go b/cli/network.go index a036647e..e26a8b28 100644 --- a/cli/network.go +++ b/cli/network.go @@ -53,12 +53,11 @@ func createClusterNetwork(clusterName string) (string, error) { return resp.ID, nil } -// deleteClusterNetwork deletes a docker network based on the name of a cluster it belongs to -func deleteClusterNetwork(clusterName string) error { +func getClusterNetwork(clusterName string) (string, error) { ctx := context.Background() docker, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) if err != nil { - return fmt.Errorf(" Couldn't create docker client\n%+v", err) + return "", fmt.Errorf(" Couldn't create docker client\n%+v", err) } filters := filters.NewArgs() @@ -68,16 +67,54 @@ func deleteClusterNetwork(clusterName string) error { networks, err := docker.NetworkList(ctx, types.NetworkListOptions{ Filters: filters, }) + if err != nil { + return "", fmt.Errorf(" Couldn't find network for cluster %s\n%+v", clusterName, err) + } + if len(networks) == 0 { + return "", nil + } + // there should be only one network that matches the name... but who knows? + return networks[0].ID, nil +} + +// deleteClusterNetwork deletes a docker network based on the name of a cluster it belongs to +func deleteClusterNetwork(clusterName string) error { + nid, err := getClusterNetwork(clusterName) if err != nil { return fmt.Errorf(" Couldn't find network for cluster %s\n%+v", clusterName, err) } + if nid == "" { + log.Warningf("couldn't remove network for cluster %s: network does not exist", clusterName) + return nil + } - // there should be only one network that matches the name... but who knows? - for _, network := range networks { - if err := docker.NetworkRemove(ctx, network.ID); err != nil { - log.Warningf("couldn't remove network for cluster %s\n%+v", clusterName, err) - continue - } + ctx := context.Background() + docker, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) + if err != nil { + return fmt.Errorf(" Couldn't create docker client\n%+v", err) + } + if err := docker.NetworkRemove(ctx, nid); err != nil { + log.Warningf("couldn't remove network for cluster %s\n%+v", clusterName, err) } return nil } + +// getContainersInNetwork gets a list of containers connected to a network +func getContainersInNetwork(nid string) ([]string, error) { + ctx := context.Background() + docker, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) + if err != nil { + return nil, fmt.Errorf("Couldn't create docker client\n%+v", err) + } + + options := types.NetworkInspectOptions{} + network, err := docker.NetworkInspect(ctx, nid, options) + if err != nil { + return nil, err + } + cids := []string{} + for cid := range network.Containers { + cids = append(cids, cid) + } + return cids, nil +} diff --git a/main.go b/main.go index bab9fcdb..e1f46742 100644 --- a/main.go +++ b/main.go @@ -216,8 +216,8 @@ func main() { Usage: "Delete all existing clusters (this ignores the --name/-n flag)", }, cli.BoolFlag{ - Name: "registry-volume", - Usage: "Delete the local Docker registry volume", + Name: "prune", + Usage: "Disconnect any other non-k3d containers in the network before deleting the cluster", }, }, Action: run.DeleteCluster, diff --git a/tests/01-basic.sh b/tests/01-basic.sh index f4421731..a308dc51 100755 --- a/tests/01-basic.sh +++ b/tests/01-basic.sh @@ -15,7 +15,7 @@ REGISTRIES_YAML=$FIXTURES_DIR/01-registries-empty.yaml ######################################################################################### -info "Creating two clusters..." +info "Creating two clusters c1 and c2..." $EXE create --wait 60 --name "c1" --api-port 6443 -v $REGISTRIES_YAML:/etc/rancher/k3s/registries.yaml || failed "could not create cluster c1" $EXE create --wait 60 --name "c2" --api-port 6444 || failed "could not create cluster c2" @@ -23,9 +23,19 @@ info "Checking we have access to both clusters..." check_k3d_clusters "c1" "c2" || failed "error checking cluster" dump_registries_yaml_in "c1" "c2" -info "Deleting clusters..." -$EXE delete --name "c1" || failed "could not delete the cluster c1" -$EXE delete --name "c2" || failed "could not delete the cluster c2" +info "Creating a cluster with a wrong --registries-file argument..." +$EXE create --wait 60 --name "c3" --api-port 6445 --registries-file /etc/inexistant || passed "expected error with a --registries-file that does not exist" + +info "Attaching a container to c2" +background=$(docker run -d --rm alpine sleep 3000) +docker network connect "k3d-c2" "$background" + +info "Deleting clusters c1 and c2..." +$EXE delete --name "c1" || failed "could not delete the cluster c1" +$EXE delete --name "c2" --prune || failed "could not delete the cluster c2" + +info "Stopping attached container" +docker stop "$background" >/dev/null exit 0