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 }