Repository: codalab/codalab-worksheets

Issue:
Worker manager prompts login even when specifying --password-file
Example command: 

```cl-worker-manager  --server https://codalab.stanford.edu --search "request_gpus=0" --min-seconds-between-workers 180 --sleep-time 60  --worker-shared-memory-size-gb 8 --min-workers 0 --max-workers 10 --worker-work-dir-prefix /scr/scr-with-most-space/ --worker-pass-down-termination --worker-delete-work-dir-on-exit --worker-exit-on-exception --worker-exit-after-num-runs 1 slurm-batch --partition john --cpus 10 --gpus 0 --memory-mb 240000 --password-file ~/.codalab/codalab-nlp.password --slurm-work-dir ~/scr/slurm_output/ --job-name codalab-slurm-worker-stanford-john ```


Expected behavior: The worker manager should start without having the user log in.

Discussion:

Patch:
diff --git a/codalab/lib/codalab_manager.py b/codalab/lib/codalab_manager.py
index c4bd4cf2..d4c3c2a9 100644
--- a/codalab/lib/codalab_manager.py
+++ b/codalab/lib/codalab_manager.py
@@ -127,8 +127,17 @@ class CodaLabManager(object):
 
         if self.temporary:
             self.config = config
-            self.state = {'auth': {}, 'sessions': {}}
             self.clients = clients
+
+            # Initialize `state` with the content in `self.state_path`, if it exists.
+            # Usually, a temp session is created when running cl-worker-manager. In this case, we want to have
+            # a temp session so that we don't interfere with state stored by "cl" processes.
+            # However, we want to initialize the temp session state with the state stored from the CodaLab CLI "cl",
+            # so that the user is not prompted again for their credentials.
+            if os.path.exists(self.state_path):
+                self.state = read_json_or_die(self.state_path)
+            else:
+                self.state = {'auth': {}, 'sessions': {}}
             return
 
         # Read config file, creating if it doesn't exist.


Test patch:
diff --git a/tests/unit/lib/codalab_manager_test.py b/tests/unit/lib/codalab_manager_test.py
index 6056a14f..3767e1e4 100644
--- a/tests/unit/lib/codalab_manager_test.py
+++ b/tests/unit/lib/codalab_manager_test.py
@@ -1,6 +1,9 @@
+import json
 import os
+import tempfile
 import unittest
 from pathlib import Path
+from typing import Dict
 
 from codalab.lib.codalab_manager import CodaLabManager
 
@@ -31,6 +34,10 @@ class CodalabManagerTest(unittest.TestCase):
             del os.environ['CODALAB_HOME']
 
     def test_temp_codalab_manager(self):
+        """
+        A codalab manager with temporary state should initialize its state from an existing
+        state.json file if it is present.
+        """
         manager: CodaLabManager = CodaLabManager(temporary=True)
         self.assertEqual(manager.state, {'auth': {}, 'sessions': {}})
         manager.save_state()
@@ -38,3 +45,19 @@ class CodalabManagerTest(unittest.TestCase):
             os.path.exists(manager.state_path),
             msg='Assert that the current state is not written out to state_path for a temporary CodaLabManager',
         )
+
+    def test_temp_codalab_manager_initialize_state(self):
+        initial_state: Dict = {
+            'auth': {"https://worksheets.codalab.org": {"token_info": {"access_token": "secret"}}},
+            'sessions': {},
+        }
+
+        cache_file = tempfile.NamedTemporaryFile(delete=False)
+        with open(cache_file.name, "w") as f:
+            json.dump(initial_state, f)
+        os.environ["CODALAB_STATE"] = cache_file.name
+
+        manager: CodaLabManager = CodaLabManager(temporary=True)
+
+        self.assertEqual(manager.state, initial_state)
+        os.remove(cache_file.name)