container.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725
  1. package container // import "github.com/docker/docker/daemon/cluster/executor/container"
  2. import (
  3. "errors"
  4. "fmt"
  5. "net"
  6. "strconv"
  7. "strings"
  8. "github.com/docker/distribution/reference"
  9. "github.com/docker/docker/api/types"
  10. enginecontainer "github.com/docker/docker/api/types/container"
  11. "github.com/docker/docker/api/types/events"
  12. "github.com/docker/docker/api/types/filters"
  13. enginemount "github.com/docker/docker/api/types/mount"
  14. "github.com/docker/docker/api/types/network"
  15. "github.com/docker/docker/api/types/volume"
  16. "github.com/docker/docker/daemon/cluster/convert"
  17. executorpkg "github.com/docker/docker/daemon/cluster/executor"
  18. clustertypes "github.com/docker/docker/daemon/cluster/provider"
  19. netconst "github.com/docker/docker/libnetwork/datastore"
  20. "github.com/docker/go-connections/nat"
  21. "github.com/docker/go-units"
  22. gogotypes "github.com/gogo/protobuf/types"
  23. "github.com/moby/swarmkit/v2/agent/exec"
  24. "github.com/moby/swarmkit/v2/api"
  25. "github.com/moby/swarmkit/v2/api/genericresource"
  26. "github.com/moby/swarmkit/v2/template"
  27. "github.com/sirupsen/logrus"
  28. )
  29. const (
  30. // systemLabelPrefix represents the reserved namespace for system labels.
  31. systemLabelPrefix = "com.docker.swarm"
  32. )
  33. // containerConfig converts task properties into docker container compatible
  34. // components.
  35. type containerConfig struct {
  36. task *api.Task
  37. networksAttachments map[string]*api.NetworkAttachment
  38. }
  39. // newContainerConfig returns a validated container config. No methods should
  40. // return an error if this function returns without error.
  41. func newContainerConfig(t *api.Task, node *api.NodeDescription) (*containerConfig, error) {
  42. var c containerConfig
  43. return &c, c.setTask(t, node)
  44. }
  45. func (c *containerConfig) setTask(t *api.Task, node *api.NodeDescription) error {
  46. if t.Spec.GetContainer() == nil && t.Spec.GetAttachment() == nil {
  47. return exec.ErrRuntimeUnsupported
  48. }
  49. container := t.Spec.GetContainer()
  50. if container != nil {
  51. if container.Image == "" {
  52. return ErrImageRequired
  53. }
  54. if err := validateMounts(container.Mounts); err != nil {
  55. return err
  56. }
  57. }
  58. // index the networks by name
  59. c.networksAttachments = make(map[string]*api.NetworkAttachment, len(t.Networks))
  60. for _, attachment := range t.Networks {
  61. c.networksAttachments[attachment.Network.Spec.Annotations.Name] = attachment
  62. }
  63. c.task = t
  64. if t.Spec.GetContainer() != nil {
  65. preparedSpec, err := template.ExpandContainerSpec(node, t)
  66. if err != nil {
  67. return err
  68. }
  69. c.task.Spec.Runtime = &api.TaskSpec_Container{
  70. Container: preparedSpec,
  71. }
  72. }
  73. return nil
  74. }
  75. func (c *containerConfig) networkAttachmentContainerID() string {
  76. attachment := c.task.Spec.GetAttachment()
  77. if attachment == nil {
  78. return ""
  79. }
  80. return attachment.ContainerID
  81. }
  82. func (c *containerConfig) taskID() string {
  83. return c.task.ID
  84. }
  85. func (c *containerConfig) spec() *api.ContainerSpec {
  86. return c.task.Spec.GetContainer()
  87. }
  88. func (c *containerConfig) nameOrID() string {
  89. if c.task.Spec.GetContainer() != nil {
  90. return c.name()
  91. }
  92. return c.networkAttachmentContainerID()
  93. }
  94. func (c *containerConfig) name() string {
  95. if c.task.Annotations.Name != "" {
  96. // if set, use the container Annotations.Name field, set in the orchestrator.
  97. return c.task.Annotations.Name
  98. }
  99. slot := fmt.Sprint(c.task.Slot)
  100. if slot == "" || c.task.Slot == 0 {
  101. slot = c.task.NodeID
  102. }
  103. // fallback to service.slot.id.
  104. return fmt.Sprintf("%s.%s.%s", c.task.ServiceAnnotations.Name, slot, c.task.ID)
  105. }
  106. func (c *containerConfig) image() string {
  107. raw := c.spec().Image
  108. ref, err := reference.ParseNormalizedNamed(raw)
  109. if err != nil {
  110. return raw
  111. }
  112. return reference.FamiliarString(reference.TagNameOnly(ref))
  113. }
  114. func (c *containerConfig) portBindings() nat.PortMap {
  115. portBindings := nat.PortMap{}
  116. if c.task.Endpoint == nil {
  117. return portBindings
  118. }
  119. for _, portConfig := range c.task.Endpoint.Ports {
  120. if portConfig.PublishMode != api.PublishModeHost {
  121. continue
  122. }
  123. port := nat.Port(fmt.Sprintf("%d/%s", portConfig.TargetPort, strings.ToLower(portConfig.Protocol.String())))
  124. binding := []nat.PortBinding{
  125. {},
  126. }
  127. if portConfig.PublishedPort != 0 {
  128. binding[0].HostPort = strconv.Itoa(int(portConfig.PublishedPort))
  129. }
  130. portBindings[port] = binding
  131. }
  132. return portBindings
  133. }
  134. func (c *containerConfig) isolation() enginecontainer.Isolation {
  135. return convert.IsolationFromGRPC(c.spec().Isolation)
  136. }
  137. func (c *containerConfig) init() *bool {
  138. if c.spec().Init == nil {
  139. return nil
  140. }
  141. init := c.spec().Init.GetValue()
  142. return &init
  143. }
  144. func (c *containerConfig) exposedPorts() map[nat.Port]struct{} {
  145. exposedPorts := make(map[nat.Port]struct{})
  146. if c.task.Endpoint == nil {
  147. return exposedPorts
  148. }
  149. for _, portConfig := range c.task.Endpoint.Ports {
  150. if portConfig.PublishMode != api.PublishModeHost {
  151. continue
  152. }
  153. port := nat.Port(fmt.Sprintf("%d/%s", portConfig.TargetPort, strings.ToLower(portConfig.Protocol.String())))
  154. exposedPorts[port] = struct{}{}
  155. }
  156. return exposedPorts
  157. }
  158. func (c *containerConfig) config() *enginecontainer.Config {
  159. genericEnvs := genericresource.EnvFormat(c.task.AssignedGenericResources, "DOCKER_RESOURCE")
  160. env := append(c.spec().Env, genericEnvs...)
  161. config := &enginecontainer.Config{
  162. Labels: c.labels(),
  163. StopSignal: c.spec().StopSignal,
  164. Tty: c.spec().TTY,
  165. OpenStdin: c.spec().OpenStdin,
  166. User: c.spec().User,
  167. Env: env,
  168. Hostname: c.spec().Hostname,
  169. WorkingDir: c.spec().Dir,
  170. Image: c.image(),
  171. ExposedPorts: c.exposedPorts(),
  172. Healthcheck: c.healthcheck(),
  173. }
  174. if len(c.spec().Command) > 0 {
  175. // If Command is provided, we replace the whole invocation with Command
  176. // by replacing Entrypoint and specifying Cmd. Args is ignored in this
  177. // case.
  178. config.Entrypoint = append(config.Entrypoint, c.spec().Command...)
  179. config.Cmd = append(config.Cmd, c.spec().Args...)
  180. } else if len(c.spec().Args) > 0 {
  181. // In this case, we assume the image has an Entrypoint and Args
  182. // specifies the arguments for that entrypoint.
  183. config.Cmd = c.spec().Args
  184. }
  185. return config
  186. }
  187. func (c *containerConfig) labels() map[string]string {
  188. var (
  189. system = map[string]string{
  190. "task": "", // mark as cluster task
  191. "task.id": c.task.ID,
  192. "task.name": c.name(),
  193. "node.id": c.task.NodeID,
  194. "service.id": c.task.ServiceID,
  195. "service.name": c.task.ServiceAnnotations.Name,
  196. }
  197. labels = make(map[string]string)
  198. )
  199. // base labels are those defined in the spec.
  200. for k, v := range c.spec().Labels {
  201. labels[k] = v
  202. }
  203. // we then apply the overrides from the task, which may be set via the
  204. // orchestrator.
  205. for k, v := range c.task.Annotations.Labels {
  206. labels[k] = v
  207. }
  208. // finally, we apply the system labels, which override all labels.
  209. for k, v := range system {
  210. labels[strings.Join([]string{systemLabelPrefix, k}, ".")] = v
  211. }
  212. return labels
  213. }
  214. func (c *containerConfig) mounts(deps exec.VolumeGetter) []enginemount.Mount {
  215. var r []enginemount.Mount
  216. for _, mount := range c.spec().Mounts {
  217. if mount.Type == api.MountTypeCluster {
  218. r = append(r, c.convertCSIMount(mount, deps))
  219. } else {
  220. r = append(r, convertMount(mount))
  221. }
  222. }
  223. return r
  224. }
  225. // convertCSIMount matches the CSI mount with the path of the CSI volume.
  226. //
  227. // technically quadratic with respect to the number of CSI mounts, but that
  228. // number shouldn't ever be large enough for quadratic to matter.
  229. //
  230. // TODO(dperny): figure out a scheme for errors? or maybe add code to
  231. // checkMounts?
  232. func (c *containerConfig) convertCSIMount(m api.Mount, deps exec.VolumeGetter) enginemount.Mount {
  233. var mount enginemount.Mount
  234. // these are actually bind mounts
  235. mount.Type = enginemount.TypeBind
  236. for _, attach := range c.task.Volumes {
  237. if attach.Source == m.Source && attach.Target == m.Target {
  238. // we should not get an error here, because we should have checked
  239. // already that the volume is ready
  240. path, _ := deps.Get(attach.ID)
  241. mount.Source = path
  242. mount.Target = m.Target
  243. }
  244. }
  245. return mount
  246. }
  247. func convertMount(m api.Mount) enginemount.Mount {
  248. mount := enginemount.Mount{
  249. Source: m.Source,
  250. Target: m.Target,
  251. ReadOnly: m.ReadOnly,
  252. }
  253. switch m.Type {
  254. case api.MountTypeBind:
  255. mount.Type = enginemount.TypeBind
  256. case api.MountTypeVolume:
  257. mount.Type = enginemount.TypeVolume
  258. case api.MountTypeTmpfs:
  259. mount.Type = enginemount.TypeTmpfs
  260. case api.MountTypeNamedPipe:
  261. mount.Type = enginemount.TypeNamedPipe
  262. case api.MountTypeCluster:
  263. mount.Type = enginemount.TypeCluster
  264. }
  265. if m.BindOptions != nil {
  266. mount.BindOptions = &enginemount.BindOptions{
  267. NonRecursive: m.BindOptions.NonRecursive,
  268. }
  269. switch m.BindOptions.Propagation {
  270. case api.MountPropagationRPrivate:
  271. mount.BindOptions.Propagation = enginemount.PropagationRPrivate
  272. case api.MountPropagationPrivate:
  273. mount.BindOptions.Propagation = enginemount.PropagationPrivate
  274. case api.MountPropagationRSlave:
  275. mount.BindOptions.Propagation = enginemount.PropagationRSlave
  276. case api.MountPropagationSlave:
  277. mount.BindOptions.Propagation = enginemount.PropagationSlave
  278. case api.MountPropagationRShared:
  279. mount.BindOptions.Propagation = enginemount.PropagationRShared
  280. case api.MountPropagationShared:
  281. mount.BindOptions.Propagation = enginemount.PropagationShared
  282. }
  283. }
  284. if m.VolumeOptions != nil {
  285. mount.VolumeOptions = &enginemount.VolumeOptions{
  286. NoCopy: m.VolumeOptions.NoCopy,
  287. }
  288. if m.VolumeOptions.Labels != nil {
  289. mount.VolumeOptions.Labels = make(map[string]string, len(m.VolumeOptions.Labels))
  290. for k, v := range m.VolumeOptions.Labels {
  291. mount.VolumeOptions.Labels[k] = v
  292. }
  293. }
  294. if m.VolumeOptions.DriverConfig != nil {
  295. mount.VolumeOptions.DriverConfig = &enginemount.Driver{
  296. Name: m.VolumeOptions.DriverConfig.Name,
  297. }
  298. if m.VolumeOptions.DriverConfig.Options != nil {
  299. mount.VolumeOptions.DriverConfig.Options = make(map[string]string, len(m.VolumeOptions.DriverConfig.Options))
  300. for k, v := range m.VolumeOptions.DriverConfig.Options {
  301. mount.VolumeOptions.DriverConfig.Options[k] = v
  302. }
  303. }
  304. }
  305. }
  306. if m.TmpfsOptions != nil {
  307. mount.TmpfsOptions = &enginemount.TmpfsOptions{
  308. SizeBytes: m.TmpfsOptions.SizeBytes,
  309. Mode: m.TmpfsOptions.Mode,
  310. }
  311. }
  312. return mount
  313. }
  314. func (c *containerConfig) healthcheck() *enginecontainer.HealthConfig {
  315. hcSpec := c.spec().Healthcheck
  316. if hcSpec == nil {
  317. return nil
  318. }
  319. interval, _ := gogotypes.DurationFromProto(hcSpec.Interval)
  320. timeout, _ := gogotypes.DurationFromProto(hcSpec.Timeout)
  321. startPeriod, _ := gogotypes.DurationFromProto(hcSpec.StartPeriod)
  322. return &enginecontainer.HealthConfig{
  323. Test: hcSpec.Test,
  324. Interval: interval,
  325. Timeout: timeout,
  326. Retries: int(hcSpec.Retries),
  327. StartPeriod: startPeriod,
  328. }
  329. }
  330. func (c *containerConfig) hostConfig(deps exec.VolumeGetter) *enginecontainer.HostConfig {
  331. hc := &enginecontainer.HostConfig{
  332. Resources: c.resources(),
  333. GroupAdd: c.spec().Groups,
  334. PortBindings: c.portBindings(),
  335. Mounts: c.mounts(deps),
  336. ReadonlyRootfs: c.spec().ReadOnly,
  337. Isolation: c.isolation(),
  338. Init: c.init(),
  339. Sysctls: c.spec().Sysctls,
  340. CapAdd: c.spec().CapabilityAdd,
  341. CapDrop: c.spec().CapabilityDrop,
  342. }
  343. if c.spec().DNSConfig != nil {
  344. hc.DNS = c.spec().DNSConfig.Nameservers
  345. hc.DNSSearch = c.spec().DNSConfig.Search
  346. hc.DNSOptions = c.spec().DNSConfig.Options
  347. }
  348. c.applyPrivileges(hc)
  349. // The format of extra hosts on swarmkit is specified in:
  350. // http://man7.org/linux/man-pages/man5/hosts.5.html
  351. // IP_address canonical_hostname [aliases...]
  352. // However, the format of ExtraHosts in HostConfig is
  353. // <host>:<ip>
  354. // We need to do the conversion here
  355. // (Alias is ignored for now)
  356. for _, entry := range c.spec().Hosts {
  357. parts := strings.Fields(entry)
  358. if len(parts) > 1 {
  359. hc.ExtraHosts = append(hc.ExtraHosts, fmt.Sprintf("%s:%s", parts[1], parts[0]))
  360. }
  361. }
  362. if c.task.LogDriver != nil {
  363. hc.LogConfig = enginecontainer.LogConfig{
  364. Type: c.task.LogDriver.Name,
  365. Config: c.task.LogDriver.Options,
  366. }
  367. }
  368. if len(c.task.Networks) > 0 {
  369. labels := c.task.Networks[0].Network.Spec.Annotations.Labels
  370. name := c.task.Networks[0].Network.Spec.Annotations.Name
  371. if v, ok := labels["com.docker.swarm.predefined"]; ok && v == "true" {
  372. hc.NetworkMode = enginecontainer.NetworkMode(name)
  373. }
  374. }
  375. return hc
  376. }
  377. // This handles the case of volumes that are defined inside a service Mount
  378. func (c *containerConfig) volumeCreateRequest(mount *api.Mount) *volume.CreateOptions {
  379. var (
  380. driverName string
  381. driverOpts map[string]string
  382. labels map[string]string
  383. )
  384. if mount.VolumeOptions != nil && mount.VolumeOptions.DriverConfig != nil {
  385. driverName = mount.VolumeOptions.DriverConfig.Name
  386. driverOpts = mount.VolumeOptions.DriverConfig.Options
  387. labels = mount.VolumeOptions.Labels
  388. }
  389. if mount.VolumeOptions != nil {
  390. return &volume.CreateOptions{
  391. Name: mount.Source,
  392. Driver: driverName,
  393. DriverOpts: driverOpts,
  394. Labels: labels,
  395. }
  396. }
  397. return nil
  398. }
  399. func (c *containerConfig) resources() enginecontainer.Resources {
  400. resources := enginecontainer.Resources{}
  401. // set pids limit
  402. pidsLimit := c.spec().PidsLimit
  403. if pidsLimit > 0 {
  404. resources.PidsLimit = &pidsLimit
  405. }
  406. resources.Ulimits = make([]*units.Ulimit, len(c.spec().Ulimits))
  407. for i, ulimit := range c.spec().Ulimits {
  408. resources.Ulimits[i] = &units.Ulimit{
  409. Name: ulimit.Name,
  410. Soft: ulimit.Soft,
  411. Hard: ulimit.Hard,
  412. }
  413. }
  414. // If no limits are specified let the engine use its defaults.
  415. //
  416. // TODO(aluzzardi): We might want to set some limits anyway otherwise
  417. // "unlimited" tasks will step over the reservation of other tasks.
  418. r := c.task.Spec.Resources
  419. if r == nil || r.Limits == nil {
  420. return resources
  421. }
  422. if r.Limits.MemoryBytes > 0 {
  423. resources.Memory = r.Limits.MemoryBytes
  424. }
  425. if r.Limits.NanoCPUs > 0 {
  426. resources.NanoCPUs = r.Limits.NanoCPUs
  427. }
  428. return resources
  429. }
  430. // Docker daemon supports just 1 network during container create.
  431. func (c *containerConfig) createNetworkingConfig(b executorpkg.Backend) *network.NetworkingConfig {
  432. var networks []*api.NetworkAttachment
  433. if c.task.Spec.GetContainer() != nil || c.task.Spec.GetAttachment() != nil {
  434. networks = c.task.Networks
  435. }
  436. epConfig := make(map[string]*network.EndpointSettings)
  437. if len(networks) > 0 {
  438. epConfig[networks[0].Network.Spec.Annotations.Name] = getEndpointConfig(networks[0], b)
  439. }
  440. return &network.NetworkingConfig{EndpointsConfig: epConfig}
  441. }
  442. // TODO: Merge this function with createNetworkingConfig after daemon supports multiple networks in container create
  443. func (c *containerConfig) connectNetworkingConfig(b executorpkg.Backend) *network.NetworkingConfig {
  444. var networks []*api.NetworkAttachment
  445. if c.task.Spec.GetContainer() != nil {
  446. networks = c.task.Networks
  447. }
  448. // First network is used during container create. Other networks are used in "docker network connect"
  449. if len(networks) < 2 {
  450. return nil
  451. }
  452. epConfig := make(map[string]*network.EndpointSettings)
  453. for _, na := range networks[1:] {
  454. epConfig[na.Network.Spec.Annotations.Name] = getEndpointConfig(na, b)
  455. }
  456. return &network.NetworkingConfig{EndpointsConfig: epConfig}
  457. }
  458. func getEndpointConfig(na *api.NetworkAttachment, b executorpkg.Backend) *network.EndpointSettings {
  459. var ipv4, ipv6 string
  460. for _, addr := range na.Addresses {
  461. ip, _, err := net.ParseCIDR(addr)
  462. if err != nil {
  463. continue
  464. }
  465. if ip.To4() != nil {
  466. ipv4 = ip.String()
  467. continue
  468. }
  469. if ip.To16() != nil {
  470. ipv6 = ip.String()
  471. }
  472. }
  473. n := &network.EndpointSettings{
  474. NetworkID: na.Network.ID,
  475. IPAMConfig: &network.EndpointIPAMConfig{
  476. IPv4Address: ipv4,
  477. IPv6Address: ipv6,
  478. },
  479. DriverOpts: na.DriverAttachmentOpts,
  480. }
  481. if v, ok := na.Network.Spec.Annotations.Labels["com.docker.swarm.predefined"]; ok && v == "true" {
  482. if ln, err := b.FindNetwork(na.Network.Spec.Annotations.Name); err == nil {
  483. n.NetworkID = ln.ID()
  484. }
  485. }
  486. return n
  487. }
  488. func (c *containerConfig) virtualIP(networkID string) string {
  489. if c.task.Endpoint == nil {
  490. return ""
  491. }
  492. for _, eVip := range c.task.Endpoint.VirtualIPs {
  493. // We only support IPv4 VIPs for now.
  494. if eVip.NetworkID == networkID {
  495. vip, _, err := net.ParseCIDR(eVip.Addr)
  496. if err != nil {
  497. return ""
  498. }
  499. return vip.String()
  500. }
  501. }
  502. return ""
  503. }
  504. func (c *containerConfig) serviceConfig() *clustertypes.ServiceConfig {
  505. if len(c.task.Networks) == 0 {
  506. return nil
  507. }
  508. logrus.Debugf("Creating service config in agent for t = %+v", c.task)
  509. svcCfg := &clustertypes.ServiceConfig{
  510. Name: c.task.ServiceAnnotations.Name,
  511. Aliases: make(map[string][]string),
  512. ID: c.task.ServiceID,
  513. VirtualAddresses: make(map[string]*clustertypes.VirtualAddress),
  514. }
  515. for _, na := range c.task.Networks {
  516. svcCfg.VirtualAddresses[na.Network.ID] = &clustertypes.VirtualAddress{
  517. // We support only IPv4 virtual IP for now.
  518. IPv4: c.virtualIP(na.Network.ID),
  519. }
  520. if len(na.Aliases) > 0 {
  521. svcCfg.Aliases[na.Network.ID] = na.Aliases
  522. }
  523. }
  524. if c.task.Endpoint != nil {
  525. for _, ePort := range c.task.Endpoint.Ports {
  526. if ePort.PublishMode != api.PublishModeIngress {
  527. continue
  528. }
  529. svcCfg.ExposedPorts = append(svcCfg.ExposedPorts, &clustertypes.PortConfig{
  530. Name: ePort.Name,
  531. Protocol: int32(ePort.Protocol),
  532. TargetPort: ePort.TargetPort,
  533. PublishedPort: ePort.PublishedPort,
  534. })
  535. }
  536. }
  537. return svcCfg
  538. }
  539. func (c *containerConfig) networkCreateRequest(name string) (clustertypes.NetworkCreateRequest, error) {
  540. na, ok := c.networksAttachments[name]
  541. if !ok {
  542. return clustertypes.NetworkCreateRequest{}, errors.New("container: unknown network referenced")
  543. }
  544. options := types.NetworkCreate{
  545. // ID: na.Network.ID,
  546. Labels: na.Network.Spec.Annotations.Labels,
  547. Internal: na.Network.Spec.Internal,
  548. Attachable: na.Network.Spec.Attachable,
  549. Ingress: convert.IsIngressNetwork(na.Network),
  550. EnableIPv6: na.Network.Spec.Ipv6Enabled,
  551. CheckDuplicate: true,
  552. Scope: netconst.SwarmScope,
  553. }
  554. if na.Network.Spec.GetNetwork() != "" {
  555. options.ConfigFrom = &network.ConfigReference{
  556. Network: na.Network.Spec.GetNetwork(),
  557. }
  558. }
  559. if na.Network.DriverState != nil {
  560. options.Driver = na.Network.DriverState.Name
  561. options.Options = na.Network.DriverState.Options
  562. }
  563. if na.Network.IPAM != nil {
  564. options.IPAM = &network.IPAM{
  565. Driver: na.Network.IPAM.Driver.Name,
  566. Options: na.Network.IPAM.Driver.Options,
  567. }
  568. for _, ic := range na.Network.IPAM.Configs {
  569. c := network.IPAMConfig{
  570. Subnet: ic.Subnet,
  571. IPRange: ic.Range,
  572. Gateway: ic.Gateway,
  573. }
  574. options.IPAM.Config = append(options.IPAM.Config, c)
  575. }
  576. }
  577. return clustertypes.NetworkCreateRequest{
  578. ID: na.Network.ID,
  579. NetworkCreateRequest: types.NetworkCreateRequest{
  580. Name: name,
  581. NetworkCreate: options,
  582. },
  583. }, nil
  584. }
  585. func (c *containerConfig) applyPrivileges(hc *enginecontainer.HostConfig) {
  586. privileges := c.spec().Privileges
  587. if privileges == nil {
  588. return
  589. }
  590. credentials := privileges.CredentialSpec
  591. if credentials != nil {
  592. switch credentials.Source.(type) {
  593. case *api.Privileges_CredentialSpec_File:
  594. hc.SecurityOpt = append(hc.SecurityOpt, "credentialspec=file://"+credentials.GetFile())
  595. case *api.Privileges_CredentialSpec_Registry:
  596. hc.SecurityOpt = append(hc.SecurityOpt, "credentialspec=registry://"+credentials.GetRegistry())
  597. case *api.Privileges_CredentialSpec_Config:
  598. hc.SecurityOpt = append(hc.SecurityOpt, "credentialspec=config://"+credentials.GetConfig())
  599. }
  600. }
  601. selinux := privileges.SELinuxContext
  602. if selinux != nil {
  603. if selinux.Disable {
  604. hc.SecurityOpt = append(hc.SecurityOpt, "label=disable")
  605. }
  606. if selinux.User != "" {
  607. hc.SecurityOpt = append(hc.SecurityOpt, "label=user:"+selinux.User)
  608. }
  609. if selinux.Role != "" {
  610. hc.SecurityOpt = append(hc.SecurityOpt, "label=role:"+selinux.Role)
  611. }
  612. if selinux.Level != "" {
  613. hc.SecurityOpt = append(hc.SecurityOpt, "label=level:"+selinux.Level)
  614. }
  615. if selinux.Type != "" {
  616. hc.SecurityOpt = append(hc.SecurityOpt, "label=type:"+selinux.Type)
  617. }
  618. }
  619. }
  620. func (c containerConfig) eventFilter() filters.Args {
  621. filter := filters.NewArgs()
  622. filter.Add("type", events.ContainerEventType)
  623. filter.Add("name", c.name())
  624. filter.Add("label", fmt.Sprintf("%v.task.id=%v", systemLabelPrefix, c.task.ID))
  625. return filter
  626. }