From 5c581805386d5088dabc3656df1afdb69084fb85 Mon Sep 17 00:00:00 2001
From: Tyler Fenby <tylerfenby@gmail.com>
Date: Thu, 6 Nov 2014 14:38:58 -0500
Subject: [PATCH] Add capability add/drop introduced in Docker 1.2

Signed-off-by: Tyler Fenby <tylerfenby@gmail.com>
---
 docs/yml.md                       | 14 ++++++++++++++
 fig/service.py                    | 10 +++++++---
 tests/integration/service_test.py | 10 ++++++++++
 3 files changed, 31 insertions(+), 3 deletions(-)

diff --git a/docs/yml.md b/docs/yml.md
index 059d165ca5d..3096ba83553 100644
--- a/docs/yml.md
+++ b/docs/yml.md
@@ -142,6 +142,20 @@ dns:
   - 9.9.9.9
 ```
 
+### cap_add, cap_drop
+
+Add or drop container capabilities.
+See `man 7 capabilities` for a full list.
+
+```
+cap_add:
+  - ALL
+
+cap_drop:
+  - NET_ADMIN
+  - SYS_ADMIN
+```
+
 ### working\_dir, entrypoint, user, hostname, domainname, mem\_limit, privileged, restart
 
 Each of these is a single value, analogous to its [docker run](https://docs.docker.com/reference/run/) counterpart.
diff --git a/fig/service.py b/fig/service.py
index 1685111ce64..645b6adfc91 100644
--- a/fig/service.py
+++ b/fig/service.py
@@ -15,7 +15,7 @@
 log = logging.getLogger(__name__)
 
 
-DOCKER_CONFIG_KEYS = ['image', 'command', 'hostname', 'domainname', 'user', 'detach', 'stdin_open', 'tty', 'mem_limit', 'ports', 'environment', 'dns', 'volumes', 'entrypoint', 'privileged', 'volumes_from', 'net', 'working_dir', 'restart']
+DOCKER_CONFIG_KEYS = ['image', 'command', 'hostname', 'domainname', 'user', 'detach', 'stdin_open', 'tty', 'mem_limit', 'ports', 'environment', 'dns', 'volumes', 'entrypoint', 'privileged', 'volumes_from', 'net', 'working_dir', 'restart', 'cap_add', 'cap_drop']
 DOCKER_CONFIG_HINTS = {
     'link'      : 'links',
     'port'      : 'ports',
@@ -261,6 +261,8 @@ def start_container(self, container=None, intermediate_container=None, **overrid
         privileged = options.get('privileged', False)
         net = options.get('net', 'bridge')
         dns = options.get('dns', None)
+        cap_add = options.get('cap_add', None)
+        cap_drop = options.get('cap_drop', None)
 
         restart = parse_restart_spec(options.get('restart', None))
 
@@ -272,7 +274,9 @@ def start_container(self, container=None, intermediate_container=None, **overrid
             privileged=privileged,
             network_mode=net,
             dns=dns,
-            restart_policy=restart
+            restart_policy=restart,
+            cap_add=cap_add,
+            cap_drop=cap_drop,
         )
         return container
 
@@ -379,7 +383,7 @@ def _get_container_create_options(self, override_options, one_off=False):
             container_options['image'] = self._build_tag_name()
 
         # Delete options which are only used when starting
-        for key in ['privileged', 'net', 'dns', 'restart']:
+        for key in ['privileged', 'net', 'dns', 'restart', 'cap_add', 'cap_drop']:
             if key in container_options:
                 del container_options[key]
 
diff --git a/tests/integration/service_test.py b/tests/integration/service_test.py
index 117cf99d634..9d3e0b126f4 100644
--- a/tests/integration/service_test.py
+++ b/tests/integration/service_test.py
@@ -376,6 +376,16 @@ def test_restart_on_failure_value(self):
         self.assertEqual(container['HostConfig']['RestartPolicy']['Name'], 'on-failure')
         self.assertEqual(container['HostConfig']['RestartPolicy']['MaximumRetryCount'], 5)
 
+    def test_cap_add_list(self):
+        service = self.create_service('web', cap_add=['SYS_ADMIN', 'NET_ADMIN'])
+        container = service.start_container().inspect()
+        self.assertEqual(container['HostConfig']['CapAdd'], ['SYS_ADMIN', 'NET_ADMIN'])
+
+    def test_cap_drop_list(self):
+        service = self.create_service('web', cap_drop=['SYS_ADMIN', 'NET_ADMIN'])
+        container = service.start_container().inspect()
+        self.assertEqual(container['HostConfig']['CapDrop'], ['SYS_ADMIN', 'NET_ADMIN'])
+
     def test_working_dir_param(self):
         service = self.create_service('container', working_dir='/working/dir/sample')
         container = service.create_container().inspect()