github.com/sams1990/dockerrepo@v17.12.1-ce-rc2+incompatible/plugin/v2/plugin_linux.go (about) 1 // +build linux 2 3 package v2 4 5 import ( 6 "os" 7 "path/filepath" 8 "runtime" 9 "strings" 10 11 "github.com/docker/docker/api/types" 12 "github.com/docker/docker/oci" 13 "github.com/docker/docker/pkg/system" 14 specs "github.com/opencontainers/runtime-spec/specs-go" 15 "github.com/pkg/errors" 16 ) 17 18 // InitSpec creates an OCI spec from the plugin's config. 19 func (p *Plugin) InitSpec(execRoot string) (*specs.Spec, error) { 20 s := oci.DefaultSpec() 21 s.Root = &specs.Root{ 22 Path: p.Rootfs, 23 Readonly: false, // TODO: all plugins should be readonly? settable in config? 24 } 25 26 userMounts := make(map[string]struct{}, len(p.PluginObj.Settings.Mounts)) 27 for _, m := range p.PluginObj.Settings.Mounts { 28 userMounts[m.Destination] = struct{}{} 29 } 30 31 execRoot = filepath.Join(execRoot, p.PluginObj.ID) 32 if err := os.MkdirAll(execRoot, 0700); err != nil { 33 return nil, errors.WithStack(err) 34 } 35 36 mounts := append(p.PluginObj.Config.Mounts, types.PluginMount{ 37 Source: &execRoot, 38 Destination: defaultPluginRuntimeDestination, 39 Type: "bind", 40 Options: []string{"rbind", "rshared"}, 41 }) 42 43 if p.PluginObj.Config.Network.Type != "" { 44 // TODO: if net == bridge, use libnetwork controller to create a new plugin-specific bridge, bind mount /etc/hosts and /etc/resolv.conf look at the docker code (allocateNetwork, initialize) 45 if p.PluginObj.Config.Network.Type == "host" { 46 oci.RemoveNamespace(&s, specs.LinuxNamespaceType("network")) 47 } 48 etcHosts := "/etc/hosts" 49 resolvConf := "/etc/resolv.conf" 50 mounts = append(mounts, 51 types.PluginMount{ 52 Source: &etcHosts, 53 Destination: etcHosts, 54 Type: "bind", 55 Options: []string{"rbind", "ro"}, 56 }, 57 types.PluginMount{ 58 Source: &resolvConf, 59 Destination: resolvConf, 60 Type: "bind", 61 Options: []string{"rbind", "ro"}, 62 }) 63 } 64 if p.PluginObj.Config.PidHost { 65 oci.RemoveNamespace(&s, specs.LinuxNamespaceType("pid")) 66 } 67 68 if p.PluginObj.Config.IpcHost { 69 oci.RemoveNamespace(&s, specs.LinuxNamespaceType("ipc")) 70 } 71 72 for _, mnt := range mounts { 73 m := specs.Mount{ 74 Destination: mnt.Destination, 75 Type: mnt.Type, 76 Options: mnt.Options, 77 } 78 if mnt.Source == nil { 79 return nil, errors.New("mount source is not specified") 80 } 81 m.Source = *mnt.Source 82 s.Mounts = append(s.Mounts, m) 83 } 84 85 for i, m := range s.Mounts { 86 if strings.HasPrefix(m.Destination, "/dev/") { 87 if _, ok := userMounts[m.Destination]; ok { 88 s.Mounts = append(s.Mounts[:i], s.Mounts[i+1:]...) 89 } 90 } 91 } 92 93 if p.PluginObj.Config.PropagatedMount != "" { 94 p.PropagatedMount = filepath.Join(p.Rootfs, p.PluginObj.Config.PropagatedMount) 95 s.Linux.RootfsPropagation = "rshared" 96 } 97 98 if p.PluginObj.Config.Linux.AllowAllDevices { 99 s.Linux.Resources.Devices = []specs.LinuxDeviceCgroup{{Allow: true, Access: "rwm"}} 100 } 101 for _, dev := range p.PluginObj.Settings.Devices { 102 path := *dev.Path 103 d, dPermissions, err := oci.DevicesFromPath(path, path, "rwm") 104 if err != nil { 105 return nil, errors.WithStack(err) 106 } 107 s.Linux.Devices = append(s.Linux.Devices, d...) 108 s.Linux.Resources.Devices = append(s.Linux.Resources.Devices, dPermissions...) 109 } 110 111 envs := make([]string, 1, len(p.PluginObj.Settings.Env)+1) 112 envs[0] = "PATH=" + system.DefaultPathEnv(runtime.GOOS) 113 envs = append(envs, p.PluginObj.Settings.Env...) 114 115 args := append(p.PluginObj.Config.Entrypoint, p.PluginObj.Settings.Args...) 116 cwd := p.PluginObj.Config.WorkDir 117 if len(cwd) == 0 { 118 cwd = "/" 119 } 120 s.Process.Terminal = false 121 s.Process.Args = args 122 s.Process.Cwd = cwd 123 s.Process.Env = envs 124 125 caps := s.Process.Capabilities 126 caps.Bounding = append(caps.Bounding, p.PluginObj.Config.Linux.Capabilities...) 127 caps.Permitted = append(caps.Permitted, p.PluginObj.Config.Linux.Capabilities...) 128 caps.Inheritable = append(caps.Inheritable, p.PluginObj.Config.Linux.Capabilities...) 129 caps.Effective = append(caps.Effective, p.PluginObj.Config.Linux.Capabilities...) 130 131 return &s, nil 132 }