github.com/MOXA-ISD/edge-library-libcompose@v0.4.1-0.20200417083957-c90441e63650/docker/project.go (about)

     1  package docker
     2  
     3  import (
     4  	"golang.org/x/net/context"
     5  
     6  	"github.com/docker/docker/api/types"
     7  	"github.com/docker/docker/api/types/filters"
     8  	"github.com/docker/libcompose/config"
     9  	"github.com/docker/libcompose/docker/auth"
    10  	"github.com/docker/libcompose/docker/client"
    11  	"github.com/docker/libcompose/docker/ctx"
    12  	"github.com/docker/libcompose/docker/network"
    13  	"github.com/docker/libcompose/docker/service"
    14  	"github.com/docker/libcompose/docker/volume"
    15  	"github.com/docker/libcompose/labels"
    16  	"github.com/docker/libcompose/project"
    17  )
    18  
    19  // NewProject creates a Project with the specified context.
    20  func NewProject(context *ctx.Context, parseOptions *config.ParseOptions) (project.APIProject, error) {
    21  
    22  	if err := context.LookupConfig(); err != nil {
    23  		logrus.Errorf("Failed to load docker config: %v", err)
    24  	}
    25  
    26  	if context.AuthLookup == nil {
    27  		context.AuthLookup = auth.NewConfigLookup(context.ConfigFile)
    28  	}
    29  
    30  	if context.ServiceFactory == nil {
    31  		context.ServiceFactory = service.NewFactory(context)
    32  	}
    33  
    34  	if context.ClientFactory == nil {
    35  		factory, err := client.NewDefaultFactory(client.Options{})
    36  		if err != nil {
    37  			return nil, err
    38  		}
    39  		context.ClientFactory = factory
    40  	}
    41  
    42  	if context.NetworksFactory == nil {
    43  		networksFactory := &network.DockerFactory{
    44  			ClientFactory: context.ClientFactory,
    45  		}
    46  		context.NetworksFactory = networksFactory
    47  	}
    48  
    49  	if context.VolumesFactory == nil {
    50  		volumesFactory := &volume.DockerFactory{
    51  			ClientFactory: context.ClientFactory,
    52  		}
    53  		context.VolumesFactory = volumesFactory
    54  	}
    55  
    56  	// FIXME(vdemeester) Remove the context duplication ?
    57  	runtime := &Project{
    58  		clientFactory: context.ClientFactory,
    59  	}
    60  	p := project.NewProject(&context.Context, runtime, parseOptions)
    61  
    62  	err := p.Parse()
    63  	if err != nil {
    64  		return nil, err
    65  	}
    66  
    67  	return p, err
    68  }
    69  
    70  // Project implements project.RuntimeProject and define docker runtime specific methods.
    71  type Project struct {
    72  	clientFactory client.Factory
    73  }
    74  
    75  // RemoveOrphans implements project.RuntimeProject.RemoveOrphans.
    76  // It will remove orphan containers that are part of the project but not to any services.
    77  func (p *Project) RemoveOrphans(ctx context.Context, projectName string, serviceConfigs *config.ServiceConfigs) error {
    78  	client := p.clientFactory.Create(nil)
    79  	filter := filters.NewArgs()
    80  	filter.Add("label", labels.PROJECT.EqString(projectName))
    81  	containers, err := client.ContainerList(ctx, types.ContainerListOptions{
    82  		Filters: filter,
    83  	})
    84  	if err != nil {
    85  		return err
    86  	}
    87  	currentServices := map[string]struct{}{}
    88  	for _, serviceName := range serviceConfigs.Keys() {
    89  		currentServices[serviceName] = struct{}{}
    90  	}
    91  	for _, container := range containers {
    92  		serviceLabel := container.Labels[labels.SERVICE.Str()]
    93  		if _, ok := currentServices[serviceLabel]; !ok {
    94  			if err := client.ContainerKill(ctx, container.ID, "SIGKILL"); err != nil {
    95  				return err
    96  			}
    97  			if err := client.ContainerRemove(ctx, container.ID, types.ContainerRemoveOptions{
    98  				Force: true,
    99  			}); err != nil {
   100  				return err
   101  			}
   102  		}
   103  	}
   104  	return nil
   105  }