exec.Executor interface
定义(位于agent/exec/executor.go
):
// Executor provides controllers for tasks.
type Executor interface {
// Describe returns the underlying node description.
Describe(ctx context.Context) (*api.NodeDescription, error)
// Configure uses the node object state to propagate node
// state to the underlying executor.
Configure(ctx context.Context, node *api.Node) error
// Controller provides a controller for the given task.
Controller(t *api.Task) (Controller, error)
// SetNetworkBootstrapKeys passes the symmetric keys from the
// manager to the executor.
SetNetworkBootstrapKeys([]*api.EncryptionKey) error
}
container Package
实现了executor
结构体(位于agent/exec/container/executor.go
):
import engineapi "github.com/docker/engine-api/client"
type executor struct {
client engineapi.APIClient
}
里面只有一个成员:一个Docker APIClient
。executor
结构体实际只实现了下面两个方法:
// Describe returns the underlying node description from the docker client.
func (e *executor) Describe(ctx context.Context) (*api.NodeDescription, error) {
info, err := e.client.Info(ctx)
if err != nil {
return nil, err
}
plugins := map[api.PluginDescription]struct{}{}
addPlugins := func(typ string, names []string) {
for _, name := range names {
plugins[api.PluginDescription{
Type: typ,
Name: name,
}] = struct{}{}
}
}
addPlugins("Volume", info.Plugins.Volume)
// Add builtin driver "overlay" (the only builtin multi-host driver) to
// the plugin list by default.
addPlugins("Network", append([]string{"overlay"}, info.Plugins.Network...))
addPlugins("Authorization", info.Plugins.Authorization)
pluginFields := make([]api.PluginDescription, 0, len(plugins))
for k := range plugins {
pluginFields = append(pluginFields, k)
}
sort.Sort(sortedPlugins(pluginFields))
// parse []string labels into a map[string]string
labels := map[string]string{}
for _, l := range info.Labels {
stringSlice := strings.SplitN(l, "=", 2)
// this will take the last value in the list for a given key
// ideally, one shouldn't assign multiple values to the same key
if len(stringSlice) > 1 {
labels[stringSlice[0]] = stringSlice[1]
}
}
description := &api.NodeDescription{
Hostname: info.Name,
Platform: &api.Platform{
Architecture: info.Architecture,
OS: info.OSType,
},
Engine: &api.EngineDescription{
EngineVersion: info.ServerVersion,
Labels: labels,
Plugins: pluginFields,
},
Resources: &api.Resources{
NanoCPUs: int64(info.NCPU) * 1e9,
MemoryBytes: info.MemTotal,
},
}
return description, nil
}
// Controller returns a docker container controller.
func (e *executor) Controller(t *api.Task) (exec.Controller, error) {
ctlr, err := newController(e.client, t)
if err != nil {
return nil, err
}
return ctlr, nil
}
Describe()
方法返回当前Docker engine
的资源配置信息,而Controller()
则返回一个container.controller
结构体。
其中关于client
的初始化位于:
client, err := engineapi.NewClient(engineAddr, "", nil, nil)
if err != nil {
return err
}
executor := container.NewExecutor(client)
如果没有对engineAddr
做特殊设置,就会使用其默认值:unix:///var/run/docker.sock
。client
值默认如下:
(dlv) p client
*github.com/docker/swarmkit/vendor/github.com/docker/engine-api/client.Client {
proto: "unix",
addr: "/var/run/docker.sock",
basePath: "",
transport: (unreadable interface type "*transport.apiTransport" not found for 0xc8202ecbd8: no type entry found, use 'types' for a list of valid types),
version: "",
customHTTPHeaders: map[string]string [],}