get.porter.sh/porter@v1.3.0/pkg/cnab/provider/driver.go (about)

     1  package cnabprovider
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"get.porter.sh/porter/pkg/cnab"
     7  	"get.porter.sh/porter/pkg/cnab/drivers"
     8  	"github.com/cnabio/cnab-go/driver"
     9  	"github.com/cnabio/cnab-go/driver/docker"
    10  	"github.com/docker/docker/api/types/container"
    11  )
    12  
    13  const (
    14  	// DriverNameDocker is the name of the CNAB Docker driver.
    15  	DriverNameDocker = "docker"
    16  
    17  	// DriverNameDebug is the name of the CNAB debug driver.
    18  	DriverNameDebug = "debug"
    19  )
    20  
    21  func (r *Runtime) newDriver(driverName string, args ActionArguments) (driver.Driver, error) {
    22  	var driverImpl driver.Driver
    23  	var err error
    24  
    25  	// Pull applicable extension from list of processed extensions
    26  	dockerExt, dockerRequired, err := r.Extensions.GetDocker()
    27  	if err != nil {
    28  		return nil, err
    29  	}
    30  
    31  	if args.AllowDockerHostAccess && driverName != DriverNameDocker {
    32  		return nil, fmt.Errorf("allow-docker-host-access was enabled, but the driver is %s", driverName)
    33  	}
    34  
    35  	if dockerRequired && !args.AllowDockerHostAccess {
    36  		return nil, fmt.Errorf("extension %q is required but allow-docker-host-access was not enabled", cnab.DockerExtensionKey)
    37  	}
    38  
    39  	if len(args.HostVolumeMounts) > 0 && driverName != DriverNameDocker {
    40  		return nil, fmt.Errorf("mount-host-volume was was used to mount a volume, but the driver is %s", driverName)
    41  	}
    42  
    43  	if !args.AllowDockerHostAccess && len(args.HostVolumeMounts) == 0 {
    44  		driverImpl, err = drivers.LookupDriver(r.Context, driverName)
    45  	}
    46  	if err != nil {
    47  		return nil, err
    48  	}
    49  
    50  	var d *docker.Driver
    51  	if args.AllowDockerHostAccess || len(args.HostVolumeMounts) > 0 {
    52  		d = &docker.Driver{}
    53  	}
    54  
    55  	if args.AllowDockerHostAccess {
    56  		driverImpl, err = r.dockerDriverWithHostAccess(dockerExt, d)
    57  	}
    58  	if err != nil {
    59  		return nil, err
    60  	}
    61  
    62  	if len(args.HostVolumeMounts) > 0 {
    63  		driverImpl, err = func(dr *docker.Driver) (driver.Driver, error) {
    64  
    65  			dr.AddConfigurationOptions(func(cfg *container.Config, hostCfg *container.HostConfig) error {
    66  				err := r.addVolumeMountsToHostConfig(hostCfg, args.HostVolumeMounts)
    67  				if err != nil {
    68  					return err
    69  				}
    70  				return nil
    71  			})
    72  
    73  			return driver.Driver(dr), nil
    74  		}(d)
    75  		if err != nil {
    76  			return nil, err
    77  		}
    78  	}
    79  
    80  	if configurable, ok := driverImpl.(driver.Configurable); ok {
    81  		driverCfg := make(map[string]string)
    82  		// Load any driver-specific config out of the environment
    83  		for env := range configurable.Config() {
    84  			if val, ok := r.LookupEnv(env); ok {
    85  				driverCfg[env] = val
    86  			}
    87  		}
    88  
    89  		err = configurable.SetConfig(driverCfg)
    90  		if err != nil {
    91  			return nil, err
    92  		}
    93  	}
    94  
    95  	return driverImpl, nil
    96  }
    97  
    98  func (r *Runtime) dockerDriverWithHostAccess(config cnab.Docker, d *docker.Driver) (driver.Driver, error) {
    99  
   100  	// Run the container with privileged access if necessary
   101  	if config.Privileged {
   102  		d.AddConfigurationOptions(func(cfg *container.Config, hostCfg *container.HostConfig) error {
   103  			// Equivalent of using: --privileged
   104  			// Required for DinD, or "Docker-in-Docker"
   105  			hostCfg.Privileged = true
   106  			return nil
   107  		})
   108  	}
   109  
   110  	// Mount the docker socket
   111  	d.AddConfigurationOptions(r.mountDockerSocket)
   112  
   113  	return driver.Driver(d), nil
   114  }
   115  
   116  func (r *Runtime) addVolumeMountsToHostConfig(hostConfig *container.HostConfig, mounts []HostVolumeMountSpec) error {
   117  	for _, mount := range mounts {
   118  		err := r.addVolumeMountToHostConfig(hostConfig, mount.Source, mount.Target, mount.ReadOnly)
   119  		if err != nil {
   120  			return err
   121  		}
   122  	}
   123  	return nil
   124  }