package service import ( "context" "fmt" "strings" "coopcloud.tech/abra/pkg/formatter" "github.com/AlecAivazis/survey/v2" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/swarm" "github.com/docker/docker/client" "github.com/sirupsen/logrus" ) // GetService retrieves a service container. If prompt is true and the retrievd // count of service containers does not match 1, then a prompt is presented to // let the user choose. A count of 0 is handled gracefully. func GetService(c context.Context, cl *client.Client, filters filters.Args, prompt bool) (swarm.Service, error) { serviceOpts := types.ServiceListOptions{Filters: filters} services, err := cl.ServiceList(c, serviceOpts) if err != nil { return swarm.Service{}, err } if len(services) == 0 { filter := filters.Get("name")[0] return swarm.Service{}, fmt.Errorf("no services matching the %v filter found?", filter) } if len(services) != 1 { var servicesRaw []string for _, service := range services { serviceName := service.Spec.Name created := formatter.HumanDuration(service.CreatedAt.Unix()) servicesRaw = append(servicesRaw, fmt.Sprintf("%s (created %v)", serviceName, created)) } if !prompt { err := fmt.Errorf("expected 1 service but found %v: %s", len(services), strings.Join(servicesRaw, " ")) return swarm.Service{}, err } logrus.Warnf("ambiguous service list received, prompting for input") var response string prompt := &survey.Select{ Message: "which service are you looking for?", Options: servicesRaw, } if err := survey.AskOne(prompt, &response); err != nil { return swarm.Service{}, err } chosenService := strings.TrimSpace(strings.Split(response, " ")[0]) for _, service := range services { serviceName := strings.ToLower(service.Spec.Name) if serviceName == chosenService { return service, nil } } logrus.Panic("failed to match chosen service") } return services[0], nil } // ContainerToServiceName converts a container name to a service name. func ContainerToServiceName(containerNames []string, stackName string) string { containerName := strings.Join(containerNames, "") trimmed := strings.TrimPrefix(containerName, "/") stackNameServiceName := strings.Split(trimmed, ".")[0] splitter := fmt.Sprintf("%s_", stackName) return strings.Split(stackNameServiceName, splitter)[1] }