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