github.com/olljanat/moby@v1.13.1/daemon/cluster/executor/container/executor.go (about) 1 package container 2 3 import ( 4 "sort" 5 "strings" 6 7 "github.com/docker/docker/api/types" 8 "github.com/docker/docker/api/types/network" 9 executorpkg "github.com/docker/docker/daemon/cluster/executor" 10 clustertypes "github.com/docker/docker/daemon/cluster/provider" 11 networktypes "github.com/docker/libnetwork/types" 12 "github.com/docker/swarmkit/agent/exec" 13 "github.com/docker/swarmkit/agent/secrets" 14 "github.com/docker/swarmkit/api" 15 "golang.org/x/net/context" 16 ) 17 18 type executor struct { 19 backend executorpkg.Backend 20 secrets exec.SecretsManager 21 } 22 23 // NewExecutor returns an executor from the docker client. 24 func NewExecutor(b executorpkg.Backend) exec.Executor { 25 return &executor{ 26 backend: b, 27 secrets: secrets.NewManager(), 28 } 29 } 30 31 // Describe returns the underlying node description from the docker client. 32 func (e *executor) Describe(ctx context.Context) (*api.NodeDescription, error) { 33 info, err := e.backend.SystemInfo() 34 if err != nil { 35 return nil, err 36 } 37 38 plugins := map[api.PluginDescription]struct{}{} 39 addPlugins := func(typ string, names []string) { 40 for _, name := range names { 41 plugins[api.PluginDescription{ 42 Type: typ, 43 Name: name, 44 }] = struct{}{} 45 } 46 } 47 48 // add v1 plugins 49 addPlugins("Volume", info.Plugins.Volume) 50 // Add builtin driver "overlay" (the only builtin multi-host driver) to 51 // the plugin list by default. 52 addPlugins("Network", append([]string{"overlay"}, info.Plugins.Network...)) 53 addPlugins("Authorization", info.Plugins.Authorization) 54 55 // add v2 plugins 56 v2Plugins, err := e.backend.PluginManager().List() 57 if err == nil { 58 for _, plgn := range v2Plugins { 59 for _, typ := range plgn.Config.Interface.Types { 60 if typ.Prefix != "docker" || !plgn.Enabled { 61 continue 62 } 63 plgnTyp := typ.Capability 64 if typ.Capability == "volumedriver" { 65 plgnTyp = "Volume" 66 } else if typ.Capability == "networkdriver" { 67 plgnTyp = "Network" 68 } 69 plugins[api.PluginDescription{ 70 Type: plgnTyp, 71 Name: plgn.Name, 72 }] = struct{}{} 73 } 74 } 75 } 76 77 pluginFields := make([]api.PluginDescription, 0, len(plugins)) 78 for k := range plugins { 79 pluginFields = append(pluginFields, k) 80 } 81 82 sort.Sort(sortedPlugins(pluginFields)) 83 84 // parse []string labels into a map[string]string 85 labels := map[string]string{} 86 for _, l := range info.Labels { 87 stringSlice := strings.SplitN(l, "=", 2) 88 // this will take the last value in the list for a given key 89 // ideally, one shouldn't assign multiple values to the same key 90 if len(stringSlice) > 1 { 91 labels[stringSlice[0]] = stringSlice[1] 92 } 93 } 94 95 description := &api.NodeDescription{ 96 Hostname: info.Name, 97 Platform: &api.Platform{ 98 Architecture: info.Architecture, 99 OS: info.OSType, 100 }, 101 Engine: &api.EngineDescription{ 102 EngineVersion: info.ServerVersion, 103 Labels: labels, 104 Plugins: pluginFields, 105 }, 106 Resources: &api.Resources{ 107 NanoCPUs: int64(info.NCPU) * 1e9, 108 MemoryBytes: info.MemTotal, 109 }, 110 } 111 112 return description, nil 113 } 114 115 func (e *executor) Configure(ctx context.Context, node *api.Node) error { 116 na := node.Attachment 117 if na == nil { 118 return nil 119 } 120 121 options := types.NetworkCreate{ 122 Driver: na.Network.DriverState.Name, 123 IPAM: &network.IPAM{ 124 Driver: na.Network.IPAM.Driver.Name, 125 }, 126 Options: na.Network.DriverState.Options, 127 CheckDuplicate: true, 128 } 129 130 for _, ic := range na.Network.IPAM.Configs { 131 c := network.IPAMConfig{ 132 Subnet: ic.Subnet, 133 IPRange: ic.Range, 134 Gateway: ic.Gateway, 135 } 136 options.IPAM.Config = append(options.IPAM.Config, c) 137 } 138 139 return e.backend.SetupIngress(clustertypes.NetworkCreateRequest{ 140 na.Network.ID, 141 types.NetworkCreateRequest{ 142 Name: na.Network.Spec.Annotations.Name, 143 NetworkCreate: options, 144 }, 145 }, na.Addresses[0]) 146 } 147 148 // Controller returns a docker container runner. 149 func (e *executor) Controller(t *api.Task) (exec.Controller, error) { 150 if t.Spec.GetAttachment() != nil { 151 return newNetworkAttacherController(e.backend, t, e.secrets) 152 } 153 154 ctlr, err := newController(e.backend, t, e.secrets) 155 if err != nil { 156 return nil, err 157 } 158 159 return ctlr, nil 160 } 161 162 func (e *executor) SetNetworkBootstrapKeys(keys []*api.EncryptionKey) error { 163 nwKeys := []*networktypes.EncryptionKey{} 164 for _, key := range keys { 165 nwKey := &networktypes.EncryptionKey{ 166 Subsystem: key.Subsystem, 167 Algorithm: int32(key.Algorithm), 168 Key: make([]byte, len(key.Key)), 169 LamportTime: key.LamportTime, 170 } 171 copy(nwKey.Key, key.Key) 172 nwKeys = append(nwKeys, nwKey) 173 } 174 e.backend.SetNetworkBootstrapKeys(nwKeys) 175 176 return nil 177 } 178 179 func (e *executor) Secrets() exec.SecretsManager { 180 return e.secrets 181 } 182 183 type sortedPlugins []api.PluginDescription 184 185 func (sp sortedPlugins) Len() int { return len(sp) } 186 187 func (sp sortedPlugins) Swap(i, j int) { sp[i], sp[j] = sp[j], sp[i] } 188 189 func (sp sortedPlugins) Less(i, j int) bool { 190 if sp[i].Type != sp[j].Type { 191 return sp[i].Type < sp[j].Type 192 } 193 return sp[i].Name < sp[j].Name 194 }