129 lines
3.4 KiB
Go
129 lines
3.4 KiB
Go
package stack
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
"unicode"
|
|
|
|
abraClient "coopcloud.tech/abra/client"
|
|
"coopcloud.tech/abra/client/convert"
|
|
"github.com/docker/cli/opts"
|
|
"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"
|
|
)
|
|
|
|
type StackStatus struct {
|
|
Services []swarm.Service
|
|
Err error
|
|
}
|
|
|
|
func getStackFilter(namespace string) filters.Args {
|
|
filter := filters.NewArgs()
|
|
filter.Add("label", convert.LabelNamespace+"="+namespace)
|
|
return filter
|
|
}
|
|
|
|
func getStackServiceFilter(namespace string) filters.Args {
|
|
return getStackFilter(namespace)
|
|
}
|
|
|
|
func getStackFilterFromOpt(namespace string, opt opts.FilterOpt) filters.Args {
|
|
filter := opt.Value()
|
|
filter.Add("label", convert.LabelNamespace+"="+namespace)
|
|
return filter
|
|
}
|
|
|
|
func getAllStacksFilter() filters.Args {
|
|
filter := filters.NewArgs()
|
|
filter.Add("label", convert.LabelNamespace)
|
|
return filter
|
|
}
|
|
|
|
func getStackServices(ctx context.Context, apiclient client.APIClient, namespace string) ([]swarm.Service, error) {
|
|
return apiclient.ServiceList(ctx, types.ServiceListOptions{Filters: getStackServiceFilter(namespace)})
|
|
}
|
|
|
|
// GetDeployedServicesByLabel filters services by label
|
|
func GetDeployedServicesByLabel(contextName string, label string) StackStatus {
|
|
cl, err := abraClient.NewClientWithContext(contextName)
|
|
if err != nil {
|
|
if strings.Contains(err.Error(), "does not exist") {
|
|
// No local context found, bail out gracefully
|
|
return StackStatus{[]swarm.Service{}, nil}
|
|
}
|
|
return StackStatus{[]swarm.Service{}, err}
|
|
}
|
|
|
|
ctx := context.Background()
|
|
filters := filters.NewArgs()
|
|
filters.Add("label", label)
|
|
services, err := cl.ServiceList(ctx, types.ServiceListOptions{Filters: filters})
|
|
if err != nil {
|
|
return StackStatus{[]swarm.Service{}, err}
|
|
}
|
|
|
|
return StackStatus{services, nil}
|
|
}
|
|
|
|
func GetAllDeployedServices(contextName string) StackStatus {
|
|
cl, err := abraClient.NewClientWithContext(contextName)
|
|
if err != nil {
|
|
if strings.Contains(err.Error(), "does not exist") {
|
|
// No local context found, bail out gracefully
|
|
return StackStatus{[]swarm.Service{}, nil}
|
|
}
|
|
return StackStatus{[]swarm.Service{}, err}
|
|
}
|
|
|
|
ctx := context.Background()
|
|
services, err := cl.ServiceList(ctx, types.ServiceListOptions{Filters: getAllStacksFilter()})
|
|
if err != nil {
|
|
return StackStatus{[]swarm.Service{}, err}
|
|
}
|
|
|
|
return StackStatus{services, nil}
|
|
}
|
|
|
|
func checkDaemonIsSwarmManager(contextName string) error {
|
|
cl, err := abraClient.NewClientWithContext(contextName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
info, err := cl.Info(context.Background())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !info.Swarm.ControlAvailable {
|
|
return errors.New("this server is not a swarm manager. Did you run \"abra server init\"?")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// validateStackName checks if the provided string is a valid stack name (namespace).
|
|
// It currently only does a rudimentary check if the string is empty, or consists
|
|
// of only whitespace and quoting characters.
|
|
func validateStackName(namespace string) error {
|
|
v := strings.TrimFunc(namespace, quotesOrWhitespace)
|
|
if v == "" {
|
|
return fmt.Errorf("invalid stack name: %q", namespace)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func quotesOrWhitespace(r rune) bool {
|
|
return unicode.IsSpace(r) || r == '"' || r == '\''
|
|
}
|
|
|
|
func DeployStack(namespace string) {
|
|
}
|
|
|
|
// TODO: Prune services from stack
|
|
|
|
func pruneServices() error {
|
|
return nil
|
|
}
|