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  }