Repository: jcrist/skein (python)

Issue:
Expose absolute path of container working directory in skein.properties
There are some subtleties to determining this from environment variables, and this might be useful for other users.

See https://github.com/dask/dask-yarn/issues/49#issuecomment-456923658.

Pull request:
Expose container working dir in properties
Adds `container_dir` attribute to `skein.properties`. If running in a
container, this is the absolute path of the container working directory,
otherwise this is `None`.

Fixes #138.

Patch:
diff --git a/skein/core.py b/skein/core.py
index 091022a..6104692 100644
--- a/skein/core.py
+++ b/skein/core.py
@@ -56,6 +56,9 @@ class Properties(Mapping):
     container_resources : Resources or None
         The resources allocated to the current container. None if not in a
         container.
+    container_dir : str or None
+        The absolute path to the working directory for this container. None if
+        not in a container.
     yarn_container_id : str or None
         The current YARN container id. None if not running in a container.
     """
@@ -73,12 +76,22 @@ class Properties(Mapping):
         except (ValueError, TypeError):
             container_resources = None
 
+        # Find the container directory from all the options
+        container_dir = None
+        if yarn_container_id is not None:
+            for path in os.environ.get('LOCAL_DIRS', '').split(','):
+                check_dir = os.path.join(path, yarn_container_id)
+                if os.path.exists(check_dir):
+                    container_dir = check_dir
+                    break
+
         mapping = dict(application_id=application_id,
                        appmaster_address=appmaster_address,
                        config_dir=config_dir,
                        container_id=container_id,
                        container_resources=container_resources,
-                       yarn_container_id=yarn_container_id)
+                       yarn_container_id=yarn_container_id,
+                       container_dir=container_dir)
 
         object.__setattr__(self, '_mapping', mapping)
 
diff --git a/skein/model.py b/skein/model.py
index c2cf798..32cd9d6 100644
--- a/skein/model.py
+++ b/skein/model.py
@@ -334,11 +334,9 @@ class Security(Specification):
 
         # Are we in a container started by skein?
         if properties.application_id is not None:
-            # Find the container directory from all the options
-            for path in os.environ.get('LOCAL_DIRS', '').split(','):
-                container_dir = os.path.join(path, properties.yarn_container_id)
-                cert_path = os.path.join(container_dir, '.skein.crt')
-                key_path = os.path.join(container_dir, '.skein.pem')
+            if properties.container_dir is not None:
+                cert_path = os.path.join(properties.container_dir, '.skein.crt')
+                key_path = os.path.join(properties.container_dir, '.skein.pem')
                 if os.path.exists(cert_path) and os.path.exists(key_path):
                     return Security(cert_file=cert_path, key_file=key_path)
             raise context.FileNotFoundError(


Test patch:
diff --git a/skein/test/test_core.py b/skein/test/test_core.py
index 58db792..e2529ab 100644
--- a/skein/test/test_core.py
+++ b/skein/test/test_core.py
@@ -264,7 +264,9 @@ def test_appclient_and_security_in_container(monkeypatch, tmpdir, security):
                      ('LOCAL_DIRS', bad_dir)]:
         monkeypatch.setenv(key, val)
 
-    monkeypatch.setattr(skein.core, 'properties', Properties())
+    properties = Properties()
+    assert properties.container_dir is None
+    monkeypatch.setattr(skein.core, 'properties', properties)
 
     # In container, but unable to find security configuration
     with pytest.raises(FileNotFoundError) as exc:
@@ -284,6 +286,10 @@ def test_appclient_and_security_in_container(monkeypatch, tmpdir, security):
         fil.write(security._get_bytes('key'))
     monkeypatch.setenv('LOCAL_DIRS', '%s,%s' % (bad_dir, good_dir))
 
+    properties = Properties()
+    assert properties.container_dir == local_dir
+    monkeypatch.setattr(skein.core, 'properties', properties)
+
     # Picks up full configuration from environment variables
     app = skein.ApplicationClient.from_current()
     assert app.id == app_id