github.com/kaisenlinux/docker@v0.0.0-20230510090727-ea55db55fac7/swarmkit/agent/exec/dockerapi/executor.go (about) 1 package dockerapi 2 3 import ( 4 "context" 5 "sort" 6 "strings" 7 "sync" 8 9 "github.com/docker/docker/api/types/filters" 10 engineapi "github.com/docker/docker/client" 11 "github.com/docker/swarmkit/agent/exec" 12 "github.com/docker/swarmkit/agent/secrets" 13 "github.com/docker/swarmkit/api" 14 "github.com/docker/swarmkit/log" 15 ) 16 17 type executor struct { 18 client engineapi.APIClient 19 secrets exec.SecretsManager 20 genericResources []*api.GenericResource 21 mutex sync.Mutex // This mutex protects the following node field 22 node *api.NodeDescription 23 } 24 25 // NewExecutor returns an executor from the docker client. 26 func NewExecutor(client engineapi.APIClient, genericResources []*api.GenericResource) exec.Executor { 27 var executor = &executor{ 28 client: client, 29 secrets: secrets.NewManager(), 30 genericResources: genericResources, 31 } 32 return executor 33 } 34 35 // Describe returns the underlying node description from the docker client. 36 func (e *executor) Describe(ctx context.Context) (*api.NodeDescription, error) { 37 info, err := e.client.Info(ctx) 38 if err != nil { 39 return nil, err 40 } 41 42 plugins := map[api.PluginDescription]struct{}{} 43 addPlugins := func(typ string, names []string) { 44 for _, name := range names { 45 plugins[api.PluginDescription{ 46 Type: typ, 47 Name: name, 48 }] = struct{}{} 49 } 50 } 51 52 // add v1 plugins to 'plugins' 53 addPlugins("Volume", info.Plugins.Volume) 54 // Add builtin driver "overlay" (the only builtin multi-host driver) to 55 // the plugin list by default. 56 addPlugins("Network", append([]string{"overlay"}, info.Plugins.Network...)) 57 addPlugins("Authorization", info.Plugins.Authorization) 58 59 // retrieve v2 plugins 60 v2plugins, err := e.client.PluginList(ctx, filters.NewArgs()) 61 if err != nil { 62 log.L.WithError(err).Warning("PluginList operation failed") 63 } else { 64 // add v2 plugins to 'plugins' 65 for _, plgn := range v2plugins { 66 for _, typ := range plgn.Config.Interface.Types { 67 if typ.Prefix == "docker" && plgn.Enabled { 68 plgnTyp := typ.Capability 69 if typ.Capability == "volumedriver" { 70 plgnTyp = "Volume" 71 } else if typ.Capability == "networkdriver" { 72 plgnTyp = "Network" 73 } 74 plugins[api.PluginDescription{ 75 Type: plgnTyp, 76 Name: plgn.Name, 77 }] = struct{}{} 78 } 79 } 80 } 81 } 82 83 pluginFields := make([]api.PluginDescription, 0, len(plugins)) 84 for k := range plugins { 85 pluginFields = append(pluginFields, k) 86 } 87 sort.Sort(sortedPlugins(pluginFields)) 88 89 // parse []string labels into a map[string]string 90 labels := map[string]string{} 91 for _, l := range info.Labels { 92 stringSlice := strings.SplitN(l, "=", 2) 93 // this will take the last value in the list for a given key 94 // ideally, one shouldn't assign multiple values to the same key 95 if len(stringSlice) > 1 { 96 labels[stringSlice[0]] = stringSlice[1] 97 } 98 } 99 100 description := &api.NodeDescription{ 101 Hostname: info.Name, 102 Platform: &api.Platform{ 103 Architecture: info.Architecture, 104 OS: info.OSType, 105 }, 106 Engine: &api.EngineDescription{ 107 EngineVersion: info.ServerVersion, 108 Labels: labels, 109 Plugins: pluginFields, 110 }, 111 Resources: &api.Resources{ 112 NanoCPUs: int64(info.NCPU) * 1e9, 113 MemoryBytes: info.MemTotal, 114 Generic: e.genericResources, 115 }, 116 } 117 118 // Save the node information in the executor field 119 e.mutex.Lock() 120 e.node = description 121 e.mutex.Unlock() 122 123 return description, nil 124 } 125 126 func (e *executor) Configure(ctx context.Context, node *api.Node) error { 127 return nil 128 } 129 130 // Controller returns a docker container controller. 131 func (e *executor) Controller(t *api.Task) (exec.Controller, error) { 132 // Get the node description from the executor field 133 e.mutex.Lock() 134 nodeDescription := e.node 135 e.mutex.Unlock() 136 ctlr, err := newController(e.client, nodeDescription, t, secrets.Restrict(e.secrets, t)) 137 if err != nil { 138 return nil, err 139 } 140 141 return ctlr, nil 142 } 143 144 func (e *executor) SetNetworkBootstrapKeys([]*api.EncryptionKey) error { 145 return nil 146 } 147 148 func (e *executor) Secrets() exec.SecretsManager { 149 return e.secrets 150 } 151 152 type sortedPlugins []api.PluginDescription 153 154 func (sp sortedPlugins) Len() int { return len(sp) } 155 156 func (sp sortedPlugins) Swap(i, j int) { sp[i], sp[j] = sp[j], sp[i] } 157 158 func (sp sortedPlugins) Less(i, j int) bool { 159 if sp[i].Type != sp[j].Type { 160 return sp[i].Type < sp[j].Type 161 } 162 return sp[i].Name < sp[j].Name 163 }