diff --git a/internal/cmd/start.go b/internal/cmd/start.go index f36bf48..05407e9 100644 --- a/internal/cmd/start.go +++ b/internal/cmd/start.go @@ -2,6 +2,7 @@ package cmd import ( "context" + "errors" "fmt" "io/ioutil" "log" @@ -98,9 +99,13 @@ func startCmd() *cobra.Command { utils.Logger.Error("could not create docker client", zap.Error(err)) } ctx := context.TODO() - _, err = dockerClient.CreateNetwork(ctx, config.DefaultNetworkName, types.NetworkCreate{}) + _, err = dockerClient.CreateNetwork(ctx, config.DefaultNetworkName, types.NetworkCreate{CheckDuplicate: true}) if err != nil { - utils.Logger.Fatal("unable to create docker network", zap.Error(err)) + if errors.Is(err, dockerservice.ErrDuplicateNetwork) { + utils.Logger.Fatal(fmt.Sprintf("found multiple docker networks with name: '%s', remove them and restart Spinup.", config.DefaultNetworkName)) + } else { + utils.Logger.Fatal("unable to create docker network", zap.Error(err)) + } } if config.Cfg.Common.Monitoring { diff --git a/internal/dockerservice/dockerservice.go b/internal/dockerservice/dockerservice.go index 12a2738..df6d661 100644 --- a/internal/dockerservice/dockerservice.go +++ b/internal/dockerservice/dockerservice.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "log" + "strings" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/filters" @@ -19,6 +20,8 @@ type Docker struct { Cli *client.Client } +var ErrDuplicateNetwork = errors.New("duplicate networks found with given name") + // GetContainer returns a docker container with the provided name (if any exists). // if no match exists, it returns a nil container and a nil error. func (d Docker) GetContainer(ctx context.Context, name string) (*Container, error) { @@ -39,8 +42,8 @@ func (d Docker) GetContainer(ctx context.Context, name string) (*Container, erro } c := &Container{ - ID: match.ID, - Name: name, + ID: match.ID, + Name: name, Config: *data.Config, NetworkConfig: network.NetworkingConfig{ EndpointsConfig: data.NetworkSettings.Networks, @@ -55,10 +58,29 @@ func (d Docker) GetContainer(ctx context.Context, name string) (*Container, erro // CreateNetwork creates a new Docker network. func (d Docker) CreateNetwork(ctx context.Context, name string, opt types.NetworkCreate) (types.NetworkCreateResponse, error) { networkResponse, err := d.Cli.NetworkCreate(ctx, name, opt) - if err != nil { - return types.NetworkCreateResponse{}, err + if err == nil { + return networkResponse, nil + } + + if !strings.Contains(err.Error(), fmt.Sprintf("network with name %s already exists", name)) { + return networkResponse, err + } else { + listFilters := filters.NewArgs() + listFilters.Add("name", name) + networks, err := d.Cli.NetworkList(ctx, types.NetworkListOptions{Filters: listFilters}) + if err != nil { + return networkResponse, err + } + + if len(networks) > 1 { + // multiple networks with the same name exists. + // we return an error and let the user clean them out + return networkResponse, ErrDuplicateNetwork + } + return types.NetworkCreateResponse{ + ID: networks[0].ID, + }, nil } - return networkResponse, nil } // RemoveNetwork removes an existing docker network.