github.com/AliyunContainerService/cli@v0.0.0-20181009023821-814ced4b30d0/cli/command/stack/swarm/deploy_bundlefile.go (about) 1 package swarm 2 3 import ( 4 "context" 5 "fmt" 6 "io" 7 "os" 8 9 "github.com/docker/cli/cli/command" 10 "github.com/docker/cli/cli/command/bundlefile" 11 "github.com/docker/cli/cli/command/stack/options" 12 "github.com/docker/cli/cli/compose/convert" 13 "github.com/docker/docker/api/types" 14 "github.com/docker/docker/api/types/swarm" 15 "github.com/pkg/errors" 16 ) 17 18 // DeployBundle deploy a bundlefile (dab) on a swarm. 19 func DeployBundle(ctx context.Context, dockerCli command.Cli, opts options.Deploy) error { 20 bundle, err := loadBundlefile(dockerCli.Err(), opts.Namespace, opts.Bundlefile) 21 if err != nil { 22 return err 23 } 24 25 if err := checkDaemonIsSwarmManager(ctx, dockerCli); err != nil { 26 return err 27 } 28 29 namespace := convert.NewNamespace(opts.Namespace) 30 31 if opts.Prune { 32 services := map[string]struct{}{} 33 for service := range bundle.Services { 34 services[service] = struct{}{} 35 } 36 pruneServices(ctx, dockerCli, namespace, services) 37 } 38 39 networks := make(map[string]types.NetworkCreate) 40 for _, service := range bundle.Services { 41 for _, networkName := range service.Networks { 42 networks[namespace.Scope(networkName)] = types.NetworkCreate{ 43 Labels: convert.AddStackLabel(namespace, nil), 44 } 45 } 46 } 47 48 services := make(map[string]swarm.ServiceSpec) 49 for internalName, service := range bundle.Services { 50 name := namespace.Scope(internalName) 51 52 var ports []swarm.PortConfig 53 for _, portSpec := range service.Ports { 54 ports = append(ports, swarm.PortConfig{ 55 Protocol: swarm.PortConfigProtocol(portSpec.Protocol), 56 TargetPort: portSpec.Port, 57 }) 58 } 59 60 nets := []swarm.NetworkAttachmentConfig{} 61 for _, networkName := range service.Networks { 62 nets = append(nets, swarm.NetworkAttachmentConfig{ 63 Target: namespace.Scope(networkName), 64 Aliases: []string{internalName}, 65 }) 66 } 67 68 serviceSpec := swarm.ServiceSpec{ 69 Annotations: swarm.Annotations{ 70 Name: name, 71 Labels: convert.AddStackLabel(namespace, service.Labels), 72 }, 73 TaskTemplate: swarm.TaskSpec{ 74 ContainerSpec: &swarm.ContainerSpec{ 75 Image: service.Image, 76 Command: service.Command, 77 Args: service.Args, 78 Env: service.Env, 79 // Service Labels will not be copied to Containers 80 // automatically during the deployment so we apply 81 // it here. 82 Labels: convert.AddStackLabel(namespace, nil), 83 }, 84 }, 85 EndpointSpec: &swarm.EndpointSpec{ 86 Ports: ports, 87 }, 88 Networks: nets, 89 } 90 91 services[internalName] = serviceSpec 92 } 93 94 if err := createNetworks(ctx, dockerCli, namespace, networks); err != nil { 95 return err 96 } 97 return deployServices(ctx, dockerCli, services, namespace, opts.SendRegistryAuth, opts.ResolveImage) 98 } 99 100 func loadBundlefile(stderr io.Writer, namespace string, path string) (*bundlefile.Bundlefile, error) { 101 defaultPath := fmt.Sprintf("%s.dab", namespace) 102 103 if path == "" { 104 path = defaultPath 105 } 106 if _, err := os.Stat(path); err != nil { 107 return nil, errors.Errorf( 108 "Bundle %s not found. Specify the path with --file", 109 path) 110 } 111 112 fmt.Fprintf(stderr, "Loading bundle from %s\n", path) 113 reader, err := os.Open(path) 114 if err != nil { 115 return nil, err 116 } 117 defer reader.Close() 118 119 bundle, err := bundlefile.LoadFile(reader) 120 if err != nil { 121 return nil, errors.Errorf("Error reading %s: %v\n", path, err) 122 } 123 return bundle, err 124 }