-
Notifications
You must be signed in to change notification settings - Fork 3
/
export.go
121 lines (97 loc) · 3.17 KB
/
export.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package main
import (
"encoding/json"
"fmt"
"os"
"strings"
"github.com/docker/docker/api/client/bundlefile"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/swarm"
"github.com/docker/docker/client"
"github.com/urfave/cli"
"golang.org/x/net/context"
)
func export(c *cli.Context) error {
swarm, swarmErr := client.NewEnvClient()
if swarmErr != nil {
return cli.NewExitError(swarmErr.Error(), 3)
}
services, servicesErr := swarm.ServiceList(context.Background(), types.ServiceListOptions{})
if len(services) == 0 {
fmt.Println("No services found to export")
return nil
}
if servicesErr != nil {
return cli.NewExitError(servicesErr.Error(), 3)
}
bundles := map[string]*bundlefile.Bundlefile{}
for _, service := range services {
var dab *bundlefile.Bundlefile
stackName := getStackName(service.Spec.Labels)
if dab = bundles[stackName]; dab == nil {
dab = &bundlefile.Bundlefile{Version: "0.1", Services: map[string]bundlefile.Service{}}
bundles[stackName] = dab
}
bundleService, err := getBundleService(service)
if err != nil {
return cli.NewExitError(servicesErr.Error(), 3)
}
// Remove the stackname from the service in DAB
service.Spec.Name = strings.TrimPrefix(service.Spec.Name, fmt.Sprintf("%s_", stackName))
dab.Services[service.Spec.Name] = *bundleService
}
for output, bundle := range bundles {
f, err := os.Create(fmt.Sprintf("%s.dab", output))
if err != nil {
return cli.NewExitError(servicesErr.Error(), 3)
}
err = json.NewEncoder(f).Encode(bundle)
if err != nil {
return cli.NewExitError(servicesErr.Error(), 3)
}
fmt.Printf("Swarm services exported successfuly for stack: %s \n", output)
for name, _ := range bundle.Services {
fmt.Println(name)
}
fmt.Println()
}
return nil
}
func getStackName(labels map[string]string) string {
if stackName, ok := labels["com.docker.stack.namespace"]; ok {
return stackName
}
return "services"
}
func getBundleService(service swarm.Service) (*bundlefile.Service, error) {
serviceBundle := &bundlefile.Service{
Image: service.Spec.TaskTemplate.ContainerSpec.Image,
ServiceLabels: service.Spec.TaskTemplate.ContainerSpec.Labels,
Labels: service.Spec.Labels,
Command: service.Spec.TaskTemplate.ContainerSpec.Command,
Args: service.Spec.TaskTemplate.ContainerSpec.Args,
Env: service.Spec.TaskTemplate.ContainerSpec.Env,
WorkingDir: &service.Spec.TaskTemplate.ContainerSpec.Dir,
User: &service.Spec.TaskTemplate.ContainerSpec.User,
Ports: []bundlefile.Port{},
Networks: []string{},
}
if service.Spec.Mode.Global != nil {
global := "global"
serviceBundle.Mode = &global
} else {
serviceBundle.Replicas = service.Spec.Mode.Replicated.Replicas
}
for _, portcfg := range service.Endpoint.Spec.Ports {
port := bundlefile.Port{
Protocol: string(portcfg.Protocol),
Port: portcfg.TargetPort,
PublishedPort: portcfg.PublishedPort,
}
serviceBundle.Ports = append(serviceBundle.Ports, port)
}
for _, net := range service.Spec.Networks {
serviceBundle.Networks = append(serviceBundle.Networks, net.Aliases...)
}
return serviceBundle, nil
}