From 381800d263b287461ddc241cc7405e8934ce17a6 Mon Sep 17 00:00:00 2001 From: Olivier 'reivilibre Date: Sun, 19 Sep 2021 13:44:00 +0100 Subject: [PATCH] Allow use of deploy keys for git --- scone/default/recipes/filesystem.py | 57 ++++++++++++++++++++++++- scone/default/steps/filesystem_steps.py | 5 +++ 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/scone/default/recipes/filesystem.py b/scone/default/recipes/filesystem.py index 533d354..db2866d 100644 --- a/scone/default/recipes/filesystem.py +++ b/scone/default/recipes/filesystem.py @@ -16,11 +16,13 @@ # along with Scone. If not, see . from pathlib import Path -from typing import List +from typing import List, Optional, Tuple from scone.common.modeutils import DEFAULT_MODE_DIR, parse_mode +from scone.default.steps import filesystem_steps, fridge_steps from scone.default.steps.basic_steps import exec_no_fails from scone.default.steps.filesystem_steps import depend_remote_file +from scone.default.steps.fridge_steps import FridgeMetadata, load_and_transform from scone.default.utensils.basic_utensils import ( Chmod, Chown, @@ -305,6 +307,26 @@ class GitCheckout(Recipe): self.expect: List[str] = check_type(args.get("expect", []), list) self.submodules = check_type(args.get("submodules", False), bool) + deploy_key = check_type_opt(args.get("deploy_key"), str) + if deploy_key is not None: + deploy_key_search = fridge_steps.search_in_fridge(head, deploy_key) + if deploy_key_search is None: + raise ValueError( + f"Cannot find deploy key: {deploy_key!r} in the fridge." + ) + + desugared_src, dk_fullpath = deploy_key_search + _unextended_path_str, dk_meta = fridge_steps.decode_fridge_extension( + str(dk_fullpath) + ) + + self.deploy_key: Optional[Tuple[Path, FridgeMetadata]] = ( + dk_fullpath, + dk_meta, + ) + else: + self.deploy_key = None + def prepare(self, preparation: Preparation, head: Head) -> None: super().prepare(preparation, head) parent = str(Path(self.dest_dir).parent) @@ -345,7 +367,38 @@ class GitCheckout(Recipe): ) # fetch the latest from the remote - await exec_no_fails(k, ["git", "fetch", "scone"], self.dest_dir) + if self.deploy_key: + deploy_key_full_path, deploy_key_fridge_metadata = self.deploy_key + remote_deploy_key = self.dest_dir.rstrip("/") + "~deploykey" + + data = await load_and_transform( + k, + deploy_key_fridge_metadata, + deploy_key_full_path, + self.recipe_context.variables, + ) + + await filesystem_steps.write_sous_file( + k, + remote_deploy_key, + # strict user-only access + parse_mode("u=rw,go=", directory=False), + data, + ) + await exec_no_fails( + k, + [ + "git", + "-c", + f"core.sshCommand=ssh -i {remote_deploy_key}", + "fetch", + "scone", + ], + self.dest_dir, + ) + await filesystem_steps.delete_sous_file(k, remote_deploy_key) + else: + await exec_no_fails(k, ["git", "fetch", "scone"], self.dest_dir) # figure out what ref we want to use # TODO(performance): fetch only this ref? diff --git a/scone/default/steps/filesystem_steps.py b/scone/default/steps/filesystem_steps.py index 6ab5a48..fcd8402 100644 --- a/scone/default/steps/filesystem_steps.py +++ b/scone/default/steps/filesystem_steps.py @@ -19,6 +19,7 @@ from typing import Any, Union from jinja2 import DictLoader, Environment +from scone.default.steps.basic_steps import exec_no_fails from scone.default.utensils.basic_utensils import WriteFile from scone.head.kitchen import Kitchen @@ -54,3 +55,7 @@ async def write_sous_file( await chan.send(None) if await chan.recv() != "OK": raise RuntimeError(f"WriteFile failed to {path}") + + +async def delete_sous_file(kitchen: Kitchen, path: str): + await exec_no_fails(kitchen, ["rm", path], "/")