Repository: skypilot-org/skypilot
Pull request: Move user files to ~/.sky
Keeps all sky related files in `~/.sky` (like `.aws`). Closes #10

### Tested
- Launching a new cpunode and logging in

Problem statement:
Move local Sky keys/files/metadata to ~/.sky
Makes uninstallation easier and keeps things organized. Maybe not a huge deal, but as a user I feel a bit weird having a Sky app create and save a new SSH key under `~/.ssh/sky-key` without me knowing.

Placement and cleanup of generated cluster configs (`config/user/`)
Issue: A generated cluster config should be removed on `sky down` / `backend.teardown(terminate=True)`

To discuss: `<sky package dir>/config/user/` is currently used; but should probably (?) be changed to, say, `~/.sky/...`.  
  - Pro: it seems weird to have a pip package dir growing in size.  
  - Con: we may not want users to interact with these configs by hand.  Even as a developer, I haven't interacted with them manually for a while.

Hints from issue discussion:
Seconded
Ray autoscaler makes keys for the user too, just that the key is different across clouds. A temporary fix for this is just to add a log saying that Sky will create `sky-key` for them if the key is not specified.
Didn't know Ray did this as well. I'm wondering if there's a key design choice (no pun intended) here that I'm missing.
I think the general philosophy is that we should not stop and ask users for non-critical things (like the key name and key path) when we can do something sensible by default. I don't feel strongly about `~/.ssh/sky-key` vs `~/.sky/sky-key`. For example, Ray puts it in `~/.ssh`, but AWS puts it in `~/.aws`.
I think it makes sense to move to `~/.sky/...` since all our other user state lives there. We also don't really want users interacting with the `state.db` and `jobs.db` stored there (even though they could), so not sure if putting things in `.sky` necessarily encourages user interaction.

I would encourage the move to `.sky`, doesn't really make sense to store user-associated state within the package tree.

Commit message: fix long line

Patch to review:
diff --git a/prototype/sky/authentication.py b/prototype/sky/authentication.py
index 48750ee5afa..442bda67ad5 100644
--- a/prototype/sky/authentication.py
+++ b/prototype/sky/authentication.py
@@ -20,6 +20,7 @@
 # development.
 
 MAX_TRIALS = 64
+PRIVATE_SSH_KEY_PATH = '~/.ssh/sky-key'
 
 
 def generate_rsa_key_pair():
@@ -66,9 +67,8 @@ def get_public_key_path(private_key_path):
 def setup_aws_authentication(config):
     config = copy.deepcopy(config)
     private_key_path = config['auth'].get('ssh_private_key', None)
-    # Defeault to ~/.ssh/sky-key
     if private_key_path is None:
-        private_key_path = '~/.ssh/sky-key'
+        private_key_path = PRIVATE_SSH_KEY_PATH
         config['auth']['ssh_private_key'] = private_key_path
 
     private_key_path = os.path.expanduser(private_key_path)
@@ -133,9 +133,8 @@ def insert_char_every_n_chars(string, char='\n', every=2):
 def setup_gcp_authentication(config):
     config = copy.deepcopy(config)
     private_key_path = config['auth'].get('ssh_private_key', None)
-    # Defeault to ~/.ssh/sky-key
     if private_key_path is None:
-        private_key_path = '~/.ssh/sky-key'
+        private_key_path = PRIVATE_SSH_KEY_PATH
         config['auth']['ssh_private_key'] = private_key_path
 
     private_key_path = os.path.expanduser(private_key_path)
@@ -210,9 +209,8 @@ def setup_azure_authentication(config):
     # Doesn't need special library calls!
     config = copy.deepcopy(config)
     private_key_path = config['auth'].get('ssh_private_key', None)
-    # Defeault to ~/.ssh/sky-key
     if private_key_path is None:
-        private_key_path = '~/.ssh/sky-key'
+        private_key_path = PRIVATE_SSH_KEY_PATH
         config['auth']['ssh_private_key'] = private_key_path
 
     private_key_path = os.path.expanduser(private_key_path)
diff --git a/prototype/sky/backends/backend_utils.py b/prototype/sky/backends/backend_utils.py
index 38b39ae7df6..bd931d5f8cb 100644
--- a/prototype/sky/backends/backend_utils.py
+++ b/prototype/sky/backends/backend_utils.py
@@ -35,6 +35,7 @@
 IP_ADDR_REGEX = r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}'
 SKY_REMOTE_RAY_VERSION = '1.9.2'
 SKY_REMOTE_PATH = '~/.sky/sky_wheels'
+SKY_USER_FILE_PATH = '~/.sky/generated'
 
 BOLD = '\033[1m'
 RESET_BOLD = '\033[0m'
@@ -71,8 +72,8 @@ def to_absolute(path):
     if output_path is None:
         assert 'cluster_name' in variables, 'cluster_name is required.'
         cluster_name = variables['cluster_name']
-        output_path = pathlib.Path(
-            template_path).parents[0] / 'user' / f'{cluster_name}.yml'
+        output_path = pathlib.Path(os.path.expanduser(
+            SKY_USER_FILE_PATH)) / 'config' / f'{cluster_name}.yml'
         os.makedirs(output_path.parents[0], exist_ok=True)
         output_path = str(output_path)
     output_path = to_absolute(output_path)
@@ -487,10 +488,11 @@ def write_cluster_config(task: task_lib.Task,
                     'tpu_name': tpu_name,
                 }),
                 # Use new names for TPU scripts so that different runs can use
-                # different TPUs.  Put in config/user/ to be consistent with
-                # cluster yamls.
+                # different TPUs.  Put in ~/.sky/generated/config/ to be
+                # consistent with cluster yamls.
                 output_path=path.replace('.sh.j2', f'.{cluster_name}.sh').
-                replace('config/', 'config/user/'),
+                replace('config/',
+                        os.path.expanduser(f'{SKY_USER_FILE_PATH}/config/')),
             ) for path in
             ['config/gcp-tpu-create.sh.j2', 'config/gcp-tpu-delete.sh.j2'])
         config_dict['tpu-create-script'] = scripts[0]


Code review comments:
diff_hunk: @@ -487,10 +488,11 @@ def write_cluster_config(task: task_lib.Task,
                     'tpu_name': tpu_name,
                 }),
                 # Use new names for TPU scripts so that different runs can use
-                # different TPUs.  Put in config/user/ to be consistent with
-                # cluster yamls.
+                # different TPUs.  Put in ~/.sky/generated/config/ to be
path: prototype/sky/backends/backend_utils.py
text: @user1:
I'd just put generated/, save 1 level.