executor.go 4.9 KB

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