2121
2222// Generator represents a generator for a container spec.
2323type Generator struct {
24- spec * rspec.Spec
24+ spec * rspec.Spec
25+ HostSpecific bool
2526}
2627
2728// New creates a spec Generator with the default spec.
@@ -139,12 +140,16 @@ func New() Generator {
139140 Devices : []rspec.Device {},
140141 },
141142 }
142- return Generator {& spec }
143+ return Generator {
144+ spec : & spec ,
145+ }
143146}
144147
145148// NewFromSpec creates a spec Generator from a given spec.
146149func NewFromSpec (spec * rspec.Spec ) Generator {
147- return Generator {spec }
150+ return Generator {
151+ spec : spec ,
152+ }
148153}
149154
150155// NewFromFile loads the template specifed in a file into a spec Generator.
@@ -166,16 +171,18 @@ func NewFromTemplate(r io.Reader) (Generator, error) {
166171 if err := json .NewDecoder (r ).Decode (& spec ); err != nil {
167172 return Generator {}, err
168173 }
169- return Generator {& spec }, nil
174+ return Generator {
175+ spec : & spec ,
176+ }, nil
170177}
171178
172179// SetSpec sets the spec in the Generator g.
173180func (g * Generator ) SetSpec (spec * rspec.Spec ) {
174181 g .spec = spec
175182}
176183
177- // GetSpec gets the spec in the Generator g.
178- func (g * Generator ) GetSpec () * rspec.Spec {
184+ // Spec gets the spec in the Generator g.
185+ func (g * Generator ) Spec () * rspec.Spec {
179186 return g .spec
180187}
181188
@@ -230,7 +237,9 @@ func (g *Generator) SetHostname(s string) {
230237
231238// ClearAnnotations clears g.spec.Annotations.
232239func (g * Generator ) ClearAnnotations () {
233- g .initSpec ()
240+ if g .spec == nil {
241+ return
242+ }
234243 g .spec .Annotations = make (map [string ]string )
235244}
236245
@@ -310,7 +319,9 @@ func (g *Generator) SetProcessArgs(args []string) {
310319
311320// ClearProcessEnv clears g.spec.Process.Env.
312321func (g * Generator ) ClearProcessEnv () {
313- g .initSpec ()
322+ if g .spec == nil {
323+ return
324+ }
314325 g .spec .Process .Env = []string {}
315326}
316327
@@ -322,7 +333,9 @@ func (g *Generator) AddProcessEnv(env string) {
322333
323334// ClearProcessAdditionalGids clear g.spec.Process.AdditionalGids.
324335func (g * Generator ) ClearProcessAdditionalGids () {
325- g .initSpec ()
336+ if g .spec == nil {
337+ return
338+ }
326339 g .spec .Process .User .AdditionalGids = []uint32 {}
327340}
328341
@@ -886,11 +899,26 @@ func (g *Generator) AddPostStartHook(s string) error {
886899
887900// AddTmpfsMount adds a tmpfs mount into g.spec.Mounts.
888901func (g * Generator ) AddTmpfsMount (dest string ) error {
889- mnt := rspec.Mount {
890- Destination : dest ,
891- Type : "tmpfs" ,
892- Source : "tmpfs" ,
893- Options : []string {"nosuid" , "nodev" , "mode=755" },
902+ mnt := rspec.Mount {}
903+
904+ parts := strings .Split (dest , ":" )
905+ if len (parts ) == 2 {
906+ options := strings .Split (parts [1 ], "," )
907+ mnt = rspec.Mount {
908+ Destination : parts [0 ],
909+ Type : "tmpfs" ,
910+ Source : "tmpfs" ,
911+ Options : options ,
912+ }
913+ } else if len (parts ) == 1 {
914+ mnt = rspec.Mount {
915+ Destination : parts [0 ],
916+ Type : "tmpfs" ,
917+ Source : "tmpfs" ,
918+ Options : []string {"rw" , "noexec" , "nosuid" , "nodev" , "size=65536k" },
919+ }
920+ } else {
921+ return fmt .Errorf ("invalid value for --tmpfs" )
894922 }
895923
896924 g .initSpec ()
@@ -953,6 +981,9 @@ func (g *Generator) SetupPrivileged(privileged bool) {
953981 // Add all capabilities in privileged mode.
954982 var finalCapList []string
955983 for _ , cap := range capability .List () {
984+ if g .HostSpecific && cap > lastCap () {
985+ continue
986+ }
956987 finalCapList = append (finalCapList , fmt .Sprintf ("CAP_%s" , strings .ToUpper (cap .String ())))
957988 }
958989 g .initSpecLinux ()
@@ -963,12 +994,25 @@ func (g *Generator) SetupPrivileged(privileged bool) {
963994 }
964995}
965996
966- func checkCap (c string ) error {
997+ func lastCap () capability.Cap {
998+ last := capability .CAP_LAST_CAP
999+ // hack for RHEL6 which has no /proc/sys/kernel/cap_last_cap
1000+ if last == capability .Cap (63 ) {
1001+ last = capability .CAP_BLOCK_SUSPEND
1002+ }
1003+
1004+ return last
1005+ }
1006+
1007+ func checkCap (c string , hostSpecific bool ) error {
9671008 isValid := false
9681009 cp := strings .ToUpper (c )
9691010
9701011 for _ , cap := range capability .List () {
9711012 if cp == strings .ToUpper (cap .String ()) {
1013+ if hostSpecific && cap > lastCap () {
1014+ return fmt .Errorf ("CAP_%s is not supported on the current host" , cp )
1015+ }
9721016 isValid = true
9731017 break
9741018 }
@@ -990,7 +1034,7 @@ func (g *Generator) ClearProcessCapabilities() {
9901034
9911035// AddProcessCapability adds a process capability into g.spec.Process.Capabilities.
9921036func (g * Generator ) AddProcessCapability (c string ) error {
993- if err := checkCap (c ); err != nil {
1037+ if err := checkCap (c , g . HostSpecific ); err != nil {
9941038 return err
9951039 }
9961040
@@ -1009,7 +1053,7 @@ func (g *Generator) AddProcessCapability(c string) error {
10091053
10101054// DropProcessCapability drops a process capability from g.spec.Process.Capabilities.
10111055func (g * Generator ) DropProcessCapability (c string ) error {
1012- if err := checkCap (c ); err != nil {
1056+ if err := checkCap (c , g . HostSpecific ); err != nil {
10131057 return err
10141058 }
10151059
0 commit comments