Browse code

Refactor few spec generation ops

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>

Michael Crosby authored on 2019/04/10 05:51:40
Showing 1 changed files
... ...
@@ -1,6 +1,7 @@
1 1
 package daemon // import "github.com/docker/docker/daemon"
2 2
 
3 3
 import (
4
+	"context"
4 5
 	"fmt"
5 6
 	"io"
6 7
 	"os"
... ...
@@ -10,6 +11,8 @@ import (
10 10
 	"strconv"
11 11
 	"strings"
12 12
 
13
+	"github.com/containerd/containerd/containers"
14
+	coci "github.com/containerd/containerd/oci"
13 15
 	containertypes "github.com/docker/docker/api/types/container"
14 16
 	"github.com/docker/docker/container"
15 17
 	daemonconfig "github.com/docker/docker/daemon/config"
... ...
@@ -34,104 +37,6 @@ const (
34 34
 	inContainerInitPath = "/sbin/" + daemonconfig.DefaultInitBinary
35 35
 )
36 36
 
37
-func setResources(s *specs.Spec, r containertypes.Resources) error {
38
-	weightDevices, err := getBlkioWeightDevices(r)
39
-	if err != nil {
40
-		return err
41
-	}
42
-	readBpsDevice, err := getBlkioThrottleDevices(r.BlkioDeviceReadBps)
43
-	if err != nil {
44
-		return err
45
-	}
46
-	writeBpsDevice, err := getBlkioThrottleDevices(r.BlkioDeviceWriteBps)
47
-	if err != nil {
48
-		return err
49
-	}
50
-	readIOpsDevice, err := getBlkioThrottleDevices(r.BlkioDeviceReadIOps)
51
-	if err != nil {
52
-		return err
53
-	}
54
-	writeIOpsDevice, err := getBlkioThrottleDevices(r.BlkioDeviceWriteIOps)
55
-	if err != nil {
56
-		return err
57
-	}
58
-
59
-	memoryRes := getMemoryResources(r)
60
-	cpuRes, err := getCPUResources(r)
61
-	if err != nil {
62
-		return err
63
-	}
64
-	blkioWeight := r.BlkioWeight
65
-
66
-	specResources := &specs.LinuxResources{
67
-		Memory: memoryRes,
68
-		CPU:    cpuRes,
69
-		BlockIO: &specs.LinuxBlockIO{
70
-			Weight:                  &blkioWeight,
71
-			WeightDevice:            weightDevices,
72
-			ThrottleReadBpsDevice:   readBpsDevice,
73
-			ThrottleWriteBpsDevice:  writeBpsDevice,
74
-			ThrottleReadIOPSDevice:  readIOpsDevice,
75
-			ThrottleWriteIOPSDevice: writeIOpsDevice,
76
-		},
77
-		Pids: getPidsLimit(r),
78
-	}
79
-
80
-	if s.Linux.Resources != nil && len(s.Linux.Resources.Devices) > 0 {
81
-		specResources.Devices = s.Linux.Resources.Devices
82
-	}
83
-
84
-	s.Linux.Resources = specResources
85
-	return nil
86
-}
87
-
88
-func (daemon *Daemon) setDevices(s *specs.Spec, c *container.Container) error {
89
-	// Build lists of devices allowed and created within the container.
90
-	var devs []specs.LinuxDevice
91
-	devPermissions := s.Linux.Resources.Devices
92
-	if c.HostConfig.Privileged && !rsystem.RunningInUserNS() {
93
-		hostDevices, err := devices.HostDevices()
94
-		if err != nil {
95
-			return err
96
-		}
97
-		for _, d := range hostDevices {
98
-			devs = append(devs, oci.Device(d))
99
-		}
100
-		devPermissions = []specs.LinuxDeviceCgroup{
101
-			{
102
-				Allow:  true,
103
-				Access: "rwm",
104
-			},
105
-		}
106
-	} else {
107
-		for _, deviceMapping := range c.HostConfig.Devices {
108
-			d, dPermissions, err := oci.DevicesFromPath(deviceMapping.PathOnHost, deviceMapping.PathInContainer, deviceMapping.CgroupPermissions)
109
-			if err != nil {
110
-				return err
111
-			}
112
-			devs = append(devs, d...)
113
-			devPermissions = append(devPermissions, dPermissions...)
114
-		}
115
-
116
-		var err error
117
-		devPermissions, err = oci.AppendDevicePermissionsFromCgroupRules(devPermissions, c.HostConfig.DeviceCgroupRules)
118
-		if err != nil {
119
-			return err
120
-		}
121
-	}
122
-
123
-	s.Linux.Devices = append(s.Linux.Devices, devs...)
124
-	s.Linux.Resources.Devices = devPermissions
125
-
126
-	for _, req := range c.HostConfig.DeviceRequests {
127
-		if err := daemon.handleDevice(req, s); err != nil {
128
-			return err
129
-		}
130
-	}
131
-
132
-	return nil
133
-}
134
-
135 37
 func (daemon *Daemon) setRlimits(s *specs.Spec, c *container.Container) error {
136 38
 	var rlimits []specs.POSIXRlimit
137 39
 
... ...
@@ -151,17 +56,6 @@ func (daemon *Daemon) setRlimits(s *specs.Spec, c *container.Container) error {
151 151
 	return nil
152 152
 }
153 153
 
154
-func setUser(s *specs.Spec, c *container.Container) error {
155
-	uid, gid, additionalGids, err := getUser(c, c.Config.User)
156
-	if err != nil {
157
-		return err
158
-	}
159
-	s.Process.User.UID = uid
160
-	s.Process.User.GID = gid
161
-	s.Process.User.AdditionalGids = additionalGids
162
-	return nil
163
-}
164
-
165 154
 func readUserFile(c *container.Container, p string) (io.ReadCloser, error) {
166 155
 	fp, err := c.GetResourcePath(p)
167 156
 	if err != nil {
... ...
@@ -693,74 +587,201 @@ func (daemon *Daemon) populateCommonSpec(s *specs.Spec, c *container.Container)
693 693
 	return nil
694 694
 }
695 695
 
696
-func (daemon *Daemon) createSpec(c *container.Container) (retSpec *specs.Spec, err error) {
697
-	s := oci.DefaultSpec()
698
-	if err := daemon.populateCommonSpec(&s, c); err != nil {
699
-		return nil, err
700
-	}
696
+func withCgroups(daemon *Daemon, c *container.Container) coci.SpecOpts {
697
+	return func(ctx context.Context, _ coci.Client, _ *containers.Container, s *coci.Spec) error {
698
+		var cgroupsPath string
699
+		scopePrefix := "docker"
700
+		parent := "/docker"
701
+		useSystemd := UsingSystemd(daemon.configStore)
702
+		if useSystemd {
703
+			parent = "system.slice"
704
+		}
701 705
 
702
-	var cgroupsPath string
703
-	scopePrefix := "docker"
704
-	parent := "/docker"
705
-	useSystemd := UsingSystemd(daemon.configStore)
706
-	if useSystemd {
707
-		parent = "system.slice"
708
-	}
706
+		if c.HostConfig.CgroupParent != "" {
707
+			parent = c.HostConfig.CgroupParent
708
+		} else if daemon.configStore.CgroupParent != "" {
709
+			parent = daemon.configStore.CgroupParent
710
+		}
709 711
 
710
-	if c.HostConfig.CgroupParent != "" {
711
-		parent = c.HostConfig.CgroupParent
712
-	} else if daemon.configStore.CgroupParent != "" {
713
-		parent = daemon.configStore.CgroupParent
714
-	}
712
+		if useSystemd {
713
+			cgroupsPath = parent + ":" + scopePrefix + ":" + c.ID
714
+			logrus.Debugf("createSpec: cgroupsPath: %s", cgroupsPath)
715
+		} else {
716
+			cgroupsPath = filepath.Join(parent, c.ID)
717
+		}
718
+		s.Linux.CgroupsPath = cgroupsPath
719
+		p := cgroupsPath
720
+		if useSystemd {
721
+			initPath, err := cgroups.GetInitCgroup("cpu")
722
+			if err != nil {
723
+				return err
724
+			}
725
+			_, err = cgroups.GetOwnCgroup("cpu")
726
+			if err != nil {
727
+				return err
728
+			}
729
+			p = filepath.Join(initPath, s.Linux.CgroupsPath)
730
+		}
715 731
 
716
-	if useSystemd {
717
-		cgroupsPath = parent + ":" + scopePrefix + ":" + c.ID
718
-		logrus.Debugf("createSpec: cgroupsPath: %s", cgroupsPath)
719
-	} else {
720
-		cgroupsPath = filepath.Join(parent, c.ID)
721
-	}
722
-	s.Linux.CgroupsPath = cgroupsPath
732
+		// Clean path to guard against things like ../../../BAD
733
+		parentPath := filepath.Dir(p)
734
+		if !filepath.IsAbs(parentPath) {
735
+			parentPath = filepath.Clean("/" + parentPath)
736
+		}
723 737
 
724
-	if err := setResources(&s, c.HostConfig.Resources); err != nil {
725
-		return nil, fmt.Errorf("linux runtime spec resources: %v", err)
738
+		if err := daemon.initCgroupsPath(parentPath); err != nil {
739
+			return fmt.Errorf("linux init cgroups path: %v", err)
740
+		}
741
+		return nil
726 742
 	}
727
-	// We merge the sysctls injected above with the HostConfig (latter takes
728
-	// precedence for backwards-compatibility reasons).
729
-	for k, v := range c.HostConfig.Sysctls {
730
-		s.Linux.Sysctl[k] = v
743
+}
744
+
745
+func withContainerDevices(daemon *Daemon, c *container.Container) coci.SpecOpts {
746
+	return func(ctx context.Context, _ coci.Client, _ *containers.Container, s *coci.Spec) error {
747
+		// Build lists of devices allowed and created within the container.
748
+		var devs []specs.LinuxDevice
749
+		devPermissions := s.Linux.Resources.Devices
750
+		if c.HostConfig.Privileged && !rsystem.RunningInUserNS() {
751
+			hostDevices, err := devices.HostDevices()
752
+			if err != nil {
753
+				return err
754
+			}
755
+			for _, d := range hostDevices {
756
+				devs = append(devs, oci.Device(d))
757
+			}
758
+			devPermissions = []specs.LinuxDeviceCgroup{
759
+				{
760
+					Allow:  true,
761
+					Access: "rwm",
762
+				},
763
+			}
764
+		} else {
765
+			for _, deviceMapping := range c.HostConfig.Devices {
766
+				d, dPermissions, err := oci.DevicesFromPath(deviceMapping.PathOnHost, deviceMapping.PathInContainer, deviceMapping.CgroupPermissions)
767
+				if err != nil {
768
+					return err
769
+				}
770
+				devs = append(devs, d...)
771
+				devPermissions = append(devPermissions, dPermissions...)
772
+			}
773
+
774
+			var err error
775
+			devPermissions, err = oci.AppendDevicePermissionsFromCgroupRules(devPermissions, c.HostConfig.DeviceCgroupRules)
776
+			if err != nil {
777
+				return err
778
+			}
779
+		}
780
+
781
+		s.Linux.Devices = append(s.Linux.Devices, devs...)
782
+		s.Linux.Resources.Devices = devPermissions
783
+
784
+		for _, req := range c.HostConfig.DeviceRequests {
785
+			if err := daemon.handleDevice(req, s); err != nil {
786
+				return err
787
+			}
788
+		}
789
+		return nil
731 790
 	}
791
+}
732 792
 
733
-	p := s.Linux.CgroupsPath
734
-	if useSystemd {
735
-		initPath, err := cgroups.GetInitCgroup("cpu")
793
+func withResources(c *container.Container) coci.SpecOpts {
794
+	return func(ctx context.Context, _ coci.Client, _ *containers.Container, s *coci.Spec) error {
795
+		r := c.HostConfig.Resources
796
+		weightDevices, err := getBlkioWeightDevices(r)
736 797
 		if err != nil {
737
-			return nil, err
798
+			return err
738 799
 		}
739
-		_, err = cgroups.GetOwnCgroup("cpu")
800
+		readBpsDevice, err := getBlkioThrottleDevices(r.BlkioDeviceReadBps)
740 801
 		if err != nil {
741
-			return nil, err
802
+			return err
803
+		}
804
+		writeBpsDevice, err := getBlkioThrottleDevices(r.BlkioDeviceWriteBps)
805
+		if err != nil {
806
+			return err
807
+		}
808
+		readIOpsDevice, err := getBlkioThrottleDevices(r.BlkioDeviceReadIOps)
809
+		if err != nil {
810
+			return err
811
+		}
812
+		writeIOpsDevice, err := getBlkioThrottleDevices(r.BlkioDeviceWriteIOps)
813
+		if err != nil {
814
+			return err
815
+		}
816
+
817
+		memoryRes := getMemoryResources(r)
818
+		cpuRes, err := getCPUResources(r)
819
+		if err != nil {
820
+			return err
821
+		}
822
+		blkioWeight := r.BlkioWeight
823
+
824
+		specResources := &specs.LinuxResources{
825
+			Memory: memoryRes,
826
+			CPU:    cpuRes,
827
+			BlockIO: &specs.LinuxBlockIO{
828
+				Weight:                  &blkioWeight,
829
+				WeightDevice:            weightDevices,
830
+				ThrottleReadBpsDevice:   readBpsDevice,
831
+				ThrottleWriteBpsDevice:  writeBpsDevice,
832
+				ThrottleReadIOPSDevice:  readIOpsDevice,
833
+				ThrottleWriteIOPSDevice: writeIOpsDevice,
834
+			},
835
+			Pids: getPidsLimit(r),
742 836
 		}
743
-		p = filepath.Join(initPath, s.Linux.CgroupsPath)
837
+
838
+		if s.Linux.Resources != nil && len(s.Linux.Resources.Devices) > 0 {
839
+			specResources.Devices = s.Linux.Resources.Devices
840
+		}
841
+
842
+		s.Linux.Resources = specResources
843
+		return nil
744 844
 	}
845
+}
745 846
 
746
-	// Clean path to guard against things like ../../../BAD
747
-	parentPath := filepath.Dir(p)
748
-	if !filepath.IsAbs(parentPath) {
749
-		parentPath = filepath.Clean("/" + parentPath)
847
+func withSysctls(c *container.Container) coci.SpecOpts {
848
+	return func(ctx context.Context, _ coci.Client, _ *containers.Container, s *coci.Spec) error {
849
+		// We merge the sysctls injected above with the HostConfig (latter takes
850
+		// precedence for backwards-compatibility reasons).
851
+		for k, v := range c.HostConfig.Sysctls {
852
+			s.Linux.Sysctl[k] = v
853
+		}
854
+		return nil
750 855
 	}
856
+}
751 857
 
752
-	if err := daemon.initCgroupsPath(parentPath); err != nil {
753
-		return nil, fmt.Errorf("linux init cgroups path: %v", err)
858
+func withUser(c *container.Container) coci.SpecOpts {
859
+	return func(ctx context.Context, _ coci.Client, _ *containers.Container, s *coci.Spec) error {
860
+		uid, gid, additionalGids, err := getUser(c, c.Config.User)
861
+		if err != nil {
862
+			return err
863
+		}
864
+		s.Process.User.UID = uid
865
+		s.Process.User.GID = gid
866
+		s.Process.User.AdditionalGids = additionalGids
867
+		return nil
754 868
 	}
755
-	if err := daemon.setDevices(&s, c); err != nil {
756
-		return nil, fmt.Errorf("linux runtime spec devices: %v", err)
869
+}
870
+
871
+func (daemon *Daemon) createSpec(c *container.Container) (retSpec *specs.Spec, err error) {
872
+	var (
873
+		opts []coci.SpecOpts
874
+		s    = oci.DefaultSpec()
875
+	)
876
+	if err := daemon.populateCommonSpec(&s, c); err != nil {
877
+		return nil, err
757 878
 	}
879
+
880
+	opts = append(opts,
881
+		withCgroups(daemon, c),
882
+		withResources(c),
883
+		withSysctls(c),
884
+		withContainerDevices(daemon, c),
885
+		withUser(c),
886
+	)
887
+
758 888
 	if err := daemon.setRlimits(&s, c); err != nil {
759 889
 		return nil, fmt.Errorf("linux runtime spec rlimits: %v", err)
760 890
 	}
761
-	if err := setUser(&s, c); err != nil {
762
-		return nil, fmt.Errorf("linux spec user: %v", err)
763
-	}
764 891
 	if err := setNamespaces(daemon, &s, c); err != nil {
765 892
 		return nil, fmt.Errorf("linux spec namespaces: %v", err)
766 893
 	}
... ...
@@ -874,7 +895,9 @@ func (daemon *Daemon) createSpec(c *container.Container) (retSpec *specs.Spec, e
874 874
 			return nil, err
875 875
 		}
876 876
 	}
877
-	return &s, nil
877
+	return &s, coci.ApplyOpts(context.Background(), nil, &containers.Container{
878
+		ID: c.ID,
879
+	}, &s, opts...)
878 880
 }
879 881
 
880 882
 func clearReadOnly(m *specs.Mount) {