Skip to content

Commit

Permalink
Merge pull request #6695 from medyagh/vol_fix
Browse files Browse the repository at this point in the history
improve docker volume clean up
  • Loading branch information
medyagh authored Feb 20, 2020
2 parents 8700f8a + 78c192c commit 0c6ad6f
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 24 deletions.
35 changes: 28 additions & 7 deletions cmd/minikube/cmd/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,13 +113,23 @@ func runDelete(cmd *cobra.Command, args []string) {
if profileFlag != constants.DefaultMachineName {
exit.UsageT("usage: minikube delete --all")
}
delLabel := fmt.Sprintf("%s=%s", oci.CreatedByLabelKey, "true")
errs := oci.DeleteAllContainersByLabel(oci.Docker, delLabel)
if len(errs) > 0 { // it will error if there is no container to delete
glog.Infof("error delete containers by label %q (might be okay): %+v", delLabel, err)
}

errs = oci.DeleteAllVolumesByLabel(oci.Docker, delLabel)
if len(errs) > 0 { // it will not error if there is nothing to delete
glog.Warningf("error delete volumes by label %q (might be okay): %+v", delLabel, errs)
}

err := oci.DeleteAllVolumesByLabel(oci.Docker, fmt.Sprintf("%s=%s", oci.CreatedByLabelKey, "=true"))
if err != nil { // if there is no volume there won't be any error
glog.Warningf("error deleting left docker volumes. \n%v:\nfor more information please refer to docker documentation: https://docs.docker.com/engine/reference/commandline/volume_prune/", err)
errs = oci.PruneAllVolumesByLabel(oci.Docker, delLabel)
if len(errs) > 0 { // it will not error if there is nothing to delete
glog.Warningf("error pruning volumes by label %q (might be okay): %+v", delLabel, errs)
}

errs := DeleteProfiles(profilesToDelete)
errs = DeleteProfiles(profilesToDelete)
if len(errs) > 0 {
HandleDeletionErrors(errs)
} else {
Expand Down Expand Up @@ -180,9 +190,20 @@ func DeleteProfiles(profiles []*pkg_config.Profile) []error {

func deleteProfile(profile *pkg_config.Profile) error {
viper.Set(pkg_config.MachineProfile, profile.Name)
err := oci.DeleteAllVolumesByLabel(oci.Docker, fmt.Sprintf("%s=%s", oci.ProfileLabelKey, profile.Name))
if err != nil { // if there is no volume there wont be any error
glog.Warningf("error deleting left docker volumes. To see the list of volumes run: 'docker volume ls' \n:%v", err)

delLabel := fmt.Sprintf("%s=%s", oci.ProfileLabelKey, profile.Name)
errs := oci.DeleteAllContainersByLabel(oci.Docker, delLabel)
if errs != nil { // it will error if there is no container to delete
glog.Infof("error deleting containers for %s (might be okay):\n%v", profile.Name, errs)
}
errs = oci.DeleteAllVolumesByLabel(oci.Docker, delLabel)
if errs != nil { // it will not error if there is nothing to delete
glog.Warningf("error deleting volumes (might be okay).\nTo see the list of volumes run: 'docker volume ls'\n:%v", errs)
}

errs = oci.PruneAllVolumesByLabel(oci.Docker, delLabel)
if len(errs) > 0 { // it will not error if there is nothing to delete
glog.Warningf("error pruning volume (might be okay):\n%v", errs)
}

api, err := machine.NewAPIClient()
Expand Down
47 changes: 36 additions & 11 deletions pkg/drivers/kic/oci/oci.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,31 @@ import (
"strings"
)

// DeleteAllContainersByLabel deletes all containers that have a specific label
// if there no containers found with the given label, it will return nil
func DeleteAllContainersByLabel(ociBin string, label string) []error {
var deleteErrs []error
if ociBin == Docker {
if err := PointToHostDockerDaemon(); err != nil {
return []error{errors.Wrap(err, "point host docker-daemon")}
}
}
cs, err := listContainersByLabel(ociBin, label)
if err != nil {
return []error{fmt.Errorf("listing containers by label %q", label)}
}
if len(cs) == 0 {
return nil
}
for _, c := range cs {
cmd := exec.Command(ociBin, "rm", "-f", "-v", c)
if out, err := cmd.CombinedOutput(); err != nil {
deleteErrs = append(deleteErrs, errors.Wrapf(err, "delete container %s: output %s", c, out))
}
}
return deleteErrs
}

// CreateContainerNode creates a new container node
func CreateContainerNode(p CreateParams) error {
if err := PointToHostDockerDaemon(); err != nil {
Expand Down Expand Up @@ -399,23 +424,23 @@ func withPortMappings(portMappings []PortMapping) createOpt {
}
}

// listContainersByLabel lists all the containres that kic driver created on user's machine using a label
// io.x-k8s.kic.cluster
// listContainersByLabel returns all the container names with a specified label
func listContainersByLabel(ociBinary string, label string) ([]string, error) {
if err := PointToHostDockerDaemon(); err != nil {
return nil, errors.Wrap(err, "point host docker-daemon")
}
cmd := exec.Command(ociBinary, "ps", "-a", "--filter", fmt.Sprintf("label=%s", label), "--format", "{{.Names}}")
var b bytes.Buffer
cmd.Stdout = &b
cmd.Stderr = &b
err := cmd.Run()
var lines []string
sc := bufio.NewScanner(&b)
for sc.Scan() {
lines = append(lines, sc.Text())
stdout, err := cmd.Output()
s := bufio.NewScanner(bytes.NewReader(stdout))
var names []string
for s.Scan() {
n := strings.TrimSpace(s.Text())
if n != "" {
names = append(names, n)
}
}
return lines, err

return names, err
}

// PointToHostDockerDaemon will unset env variables that point to docker inside minikube
Expand Down
60 changes: 54 additions & 6 deletions pkg/drivers/kic/oci/volumes.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,27 +17,75 @@ limitations under the License.
package oci

import (
"bufio"
"bytes"
"fmt"
"os/exec"
"strings"

"github.com/golang/glog"
"github.com/pkg/errors"
)

// DeleteAllVolumesByLabel deletes all volumes that have a specific label
// if there is no volume to delete it will return nil
func DeleteAllVolumesByLabel(ociBin string, label string) []error {
var deleteErrs []error
glog.Infof("trying to delete all %s volumes with label %s", ociBin, label)
if ociBin == Docker {
if err := PointToHostDockerDaemon(); err != nil {
return []error{errors.Wrap(err, "point host docker-daemon")}
}
}

vs, err := allVolumesByLabel(ociBin, label)
if err != nil {
return []error{fmt.Errorf("listing volumes by label %q: %v", label, err)}
}

for _, v := range vs {
cmd := exec.Command(ociBin, "volume", "rm", "--force", v)
if out, err := cmd.CombinedOutput(); err != nil {
deleteErrs = append(deleteErrs, fmt.Errorf("deleting volume %s: output: %s", v, string(out)))
}
}
return deleteErrs
}

// PruneAllVolumesByLabel deletes all volumes that have a specific label
// if there is no volume to delete it will return nil
// example: docker volume prune -f --filter label=name.minikube.sigs.k8s.io=minikube
func DeleteAllVolumesByLabel(ociBin string, label string) error {
func PruneAllVolumesByLabel(ociBin string, label string) []error {
var deleteErrs []error
glog.Infof("trying to prune all %s volumes with label %s", ociBin, label)
if ociBin == Docker {
if err := PointToHostDockerDaemon(); err != nil {
return errors.Wrap(err, "point host docker-daemon")
return []error{errors.Wrap(err, "point host docker-daemon")}
}
}
cmd := exec.Command(ociBin, "volume", "prune", "-f", "--filter", label)

// try to prune afterwards just in case delete didn't go through
cmd := exec.Command(ociBin, "volume", "prune", "-f", "--filter", "label="+label)
if out, err := cmd.CombinedOutput(); err != nil {
return errors.Wrapf(err, "output %s", string(out))
deleteErrs = append(deleteErrs, errors.Wrapf(err, "prune volume by label %s: %s", label, string(out)))
}
return nil
return deleteErrs
}

// allVolumesByLabel returns name of all docker volumes by a specific label
// will not return error if there is no volume found.
func allVolumesByLabel(ociBin string, label string) ([]string, error) {
cmd := exec.Command(ociBin, "volume", "ls", "--filter", "label="+label, "--format", "{{.Name}}")
stdout, err := cmd.Output()
s := bufio.NewScanner(bytes.NewReader(stdout))
var vols []string
for s.Scan() {
v := strings.TrimSpace(s.Text())
if v != "" {
vols = append(vols, v)
}
}
return vols, err
}

// createDockerVolume creates a docker volume to be attached to the container with correct labels and prefixes based on profile name
Expand All @@ -47,7 +95,7 @@ func createDockerVolume(name string) error {
if err := PointToHostDockerDaemon(); err != nil {
return errors.Wrap(err, "point host docker-daemon")
}
cmd := exec.Command(Docker, "volume", "create", name, "--label", "name.minikube.sigs.k8s.io="+name, "--label", "craeted_by_minikube.minikube.sigs.k8s.io=true")
cmd := exec.Command(Docker, "volume", "create", name, "--label", fmt.Sprintf("%s=%s", ProfileLabelKey, name), "--label", fmt.Sprintf("%s=%s", CreatedByLabelKey, "true"))
if out, err := cmd.CombinedOutput(); err != nil {
return errors.Wrapf(err, "output %s", string(out))
}
Expand Down

0 comments on commit 0c6ad6f

Please sign in to comment.