agent.go 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. package docker
  2. import (
  3. "context"
  4. "fmt"
  5. "strings"
  6. "github.com/docker/docker/api/types"
  7. "github.com/docker/docker/api/types/filters"
  8. "github.com/docker/docker/api/types/volume"
  9. "github.com/docker/docker/client"
  10. )
  11. // Agent is a Docker client for performing operations that interact
  12. // with the Docker engine over REST
  13. type Agent struct {
  14. client *client.Client
  15. ctx context.Context
  16. label string
  17. }
  18. // CreateLocalVolumeIfNotExist creates a volume using driver type "local" with the
  19. // given name if it does not exist. If the volume does exist but does not contain
  20. // the required label (a.label), an error is thrown.
  21. func (a *Agent) CreateLocalVolumeIfNotExist(name string) (*types.Volume, error) {
  22. volListBody, err := a.client.VolumeList(a.ctx, filters.Args{})
  23. if err != nil {
  24. return nil, a.handleDockerClientErr(err, "Could not list volumes")
  25. }
  26. for _, _vol := range volListBody.Volumes {
  27. if contains, ok := _vol.Labels[a.label]; ok && contains == "true" && _vol.Name == name {
  28. return _vol, nil
  29. } else if !ok && _vol.Name == name {
  30. return nil, fmt.Errorf("volume conflict for %s: please remove existing volume and try again", name)
  31. }
  32. }
  33. return a.CreateLocalVolume(name)
  34. }
  35. // CreateLocalVolume creates a volume using driver type "local" with no
  36. // configured options. The equivalent of:
  37. //
  38. // docker volume create --driver local [name]
  39. func (a *Agent) CreateLocalVolume(name string) (*types.Volume, error) {
  40. labels := make(map[string]string)
  41. labels[a.label] = "true"
  42. opts := volume.VolumeCreateBody{
  43. Name: name,
  44. Driver: "local",
  45. Labels: labels,
  46. }
  47. vol, err := a.client.VolumeCreate(a.ctx, opts)
  48. if err != nil {
  49. return nil, a.handleDockerClientErr(err, "Could not create volume "+name)
  50. }
  51. return &vol, err
  52. }
  53. // ------------------------- AGENT HELPER FUNCTIONS ------------------------- //
  54. func (a *Agent) handleDockerClientErr(err error, errPrefix string) error {
  55. if strings.Contains(err.Error(), "Cannot connect to the Docker daemon") {
  56. return fmt.Errorf("The Docker daemon must be running in order to start Porter: connection to %s failed", a.client.DaemonHost())
  57. }
  58. return fmt.Errorf("%s:%s", errPrefix, err.Error())
  59. }