Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,15 @@ Initial setup of a GAMADV-XTD3 project and GYB project is required to provide ne

```bash
$ compiler-admin init -h
usage: compiler-admin init [-h] username
usage: compiler-admin init [-h] [--gam] [--gyb] username

positional arguments:
username The user's account name, sans domain.
username A Compiler user account name, sans domain.

options:
-h, --help show this help message and exit
--gam If provided, initialize a new GAM project.
--gyb If provided, initialize a new GYB project.
```

The `init` commands follows the steps in the [GAMADV-XTD3 Wiki](https://github.com/taers232c/GAMADV-XTD3/wiki/#requirements).
Expand Down
56 changes: 34 additions & 22 deletions compiler_admin/commands/init.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,44 +7,56 @@
from compiler_admin.services.google import USER_ARCHIVE, CallGAMCommand


CONFIG_DIR = os.environ.get("GAMCFGDIR", "./.config")
CONFIG_PATH = Path(CONFIG_DIR)
CONFIG_PATH_NAME = str(CONFIG_PATH)
GAM_CONFIG_DIR = os.environ.get("GAMCFGDIR", "./.config/gam")
GAM_CONFIG_PATH = Path(GAM_CONFIG_DIR)
GYB_CONFIG_PATH = GAM_CONFIG_PATH.parent / "gyb"


def _clean_config_dir():
for path in CONFIG_PATH.glob("**/*"):
def _clean_config_dir(config_dir: Path) -> None:
config_dir.mkdir(parents=True, exist_ok=True)
for path in config_dir.glob("**/*"):
if path.is_file():
path.unlink()
elif path.is_dir():
rmtree(path)


def init(admin_user: str) -> int:
def init(admin_user: str, gam: bool = False, gyb: bool = False) -> int:
"""Initialize a new GAM project.

See https://github.com/taers232c/GAMADV-XTD3/wiki/How-to-Install-Advanced-GAM

Args:
admin_user (str): The Compiler admin with which to initialize a new project.

gam (bool): If True, initialize a new GAM project.

gyb (bool): If True, initialize a new GYB project.

Returns:
A value indicating if the operation succeeded or failed.
"""
if CONFIG_PATH.exists():
_clean_config_dir()

res = CallGAMCommand(("config", "drive_dir", CONFIG_PATH_NAME, "verify"))
res += CallGAMCommand(("create", "project"))
res += CallGAMCommand(("oauth", "create"))
res += CallGAMCommand(("user", admin_user, "check", "serviceaccount"))

# download GYB installer to config directory
gyb = CONFIG_PATH / "gyb-install.sh"
with gyb.open("w+") as dest:
res += subprocess.call(("curl", "-s", "-S", "-L", "https://gyb-shortn.jaylee.us/gyb-install"), stdout=dest)

# install, giving values to options that prompt by default
# https://github.com/GAM-team/got-your-back/blob/main/install-gyb.sh
res += subprocess.call((gyb, "-u", admin_user, "-r", USER_ARCHIVE))
res = RESULT_SUCCESS

if gam:
_clean_config_dir(GAM_CONFIG_PATH)
# GAM is already installed via pyproject.toml
res += CallGAMCommand(("config", "drive_dir", str(GAM_CONFIG_PATH), "verify"))
res += CallGAMCommand(("create", "project"))
res += CallGAMCommand(("oauth", "create"))
res += CallGAMCommand(("user", admin_user, "check", "serviceaccount"))

if gyb:
_clean_config_dir(GYB_CONFIG_PATH)
# download GYB installer to config directory
gyb = GYB_CONFIG_PATH / "gyb-install.sh"
with gyb.open("w+") as dest:
res += subprocess.call(("curl", "-s", "-S", "-L", "https://gyb-shortn.jaylee.us/gyb-install"), stdout=dest)

# install, giving values to some options
# https://github.com/GAM-team/got-your-back/blob/main/install-gyb.sh
#
# use GYB_CONFIG_PATH.parent for the install directory option, otherwise we get a .config/gyb/gyb directory structure
res += subprocess.call((gyb, "-u", admin_user, "-r", USER_ARCHIVE, "-d", str(GYB_CONFIG_PATH.parent)))

return RESULT_SUCCESS if res == RESULT_SUCCESS else RESULT_FAILURE
6 changes: 4 additions & 2 deletions compiler_admin/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,12 @@ def _subcmd(name, help, add_username_arg=True) -> argparse.ArgumentParser:

_subcmd("info", help="Print configuration and debugging information.", add_username_arg=False)

_subcmd(
init_parser = _subcmd(
"init",
help="Initialize a new admin project. This command should be run once before any others.",
)
init_parser.add_argument("--gam", action="store_true", help="If provided, initialize a new GAM project.")
init_parser.add_argument("--gyb", action="store_true", help="If provided, initialize a new GYB project.")

_subcmd("create", help="Create a new user in the Compiler domain.")

Expand Down Expand Up @@ -70,7 +72,7 @@ def _subcmd(name, help, add_username_arg=True) -> argparse.ArgumentParser:
elif args.command == "delete":
return delete(args.username)
elif args.command == "init":
return init(args.username)
return init(args.username, gam=args.gam, gyb=args.gyb)
elif args.command == "offboard":
return offboard(args.username, args.alias)
elif args.command == "restore":
Expand Down
8 changes: 4 additions & 4 deletions compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ services:
dockerfile: .devcontainer/Dockerfile
image: compiler_admin:dev
environment:
GAMCFGDIR: /home/compiler/.config/gam
GAMCFGDIR: /home/compiler/.config/compiler-admin/gam
entrypoint: sleep infinity
volumes:
- ./:/home/compiler/admin
- ./.config/:/home/compiler/.config/gam
- ./.downloads/:/home/compiler/Downloads
- .:/home/compiler/admin
- ./.config:/home/compiler/.config/compiler-admin
- ./.downloads:/home/compiler/Downloads
56 changes: 43 additions & 13 deletions tests/commands/test_init.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
import pytest

from compiler_admin.commands.init import init, __name__ as MODULE
from compiler_admin.commands.init import _clean_config_dir, init, __name__ as MODULE


@pytest.fixture
def mock_CONFIG_PATH(mocker):
return mocker.patch(f"{MODULE}.CONFIG_PATH")
def mock_rmtree(mocker):
return mocker.patch(f"{MODULE}.rmtree")


@pytest.fixture
def mock_GAM_CONFIG_PATH(mocker):
return mocker.patch(f"{MODULE}.GAM_CONFIG_PATH")


@pytest.fixture
def mock_GYB_CONFIG_PATH(mocker):
return mocker.patch(f"{MODULE}.GYB_CONFIG_PATH")


@pytest.fixture
Expand All @@ -23,23 +33,43 @@ def mock_subprocess_call(mocker):
return mocker.patch(f"{MODULE}.subprocess.call")


def test_init_config_path_exists(mock_CONFIG_PATH, mock_clean_config_dir, mock_google_CallGAMCommand, mock_subprocess_call):
mock_CONFIG_PATH.exists.return_value = True
def test_clean_config_dir(mocker, mock_GAM_CONFIG_PATH, mock_rmtree):
mock_file = mocker.Mock(is_file=mocker.Mock(return_value=True))
mock_dir = mocker.Mock(is_file=mocker.Mock(return_value=False), is_dir=mocker.Mock(return_value=True))

init("username")
mock_GAM_CONFIG_PATH.glob.return_value = [mock_file, mock_dir]

mock_clean_config_dir.assert_called_once()
assert mock_google_CallGAMCommand.call_count > 0
assert mock_subprocess_call.call_count > 0
_clean_config_dir(mock_GAM_CONFIG_PATH)

mock_GAM_CONFIG_PATH.mkdir.assert_called_once()
mock_GAM_CONFIG_PATH.glob.assert_called_once()
mock_file.is_file.assert_called_once()
mock_file.unlink.assert_called_once()
mock_dir.is_file.assert_called_once()
mock_dir.is_dir.assert_called_once()
mock_rmtree.assert_called_once()
assert mock_dir in mock_rmtree.call_args.args

def test_init_config_path_does_not_exist(
mock_CONFIG_PATH, mock_clean_config_dir, mock_google_CallGAMCommand, mock_subprocess_call
):
mock_CONFIG_PATH.exists.return_value = False

def test_init_default(mock_clean_config_dir, mock_google_CallGAMCommand, mock_subprocess_call):
init("username")

assert mock_clean_config_dir.call_count == 0
assert mock_google_CallGAMCommand.call_count == 0
assert mock_subprocess_call.call_count == 0


def test_init_gam(mock_GAM_CONFIG_PATH, mock_clean_config_dir, mock_google_CallGAMCommand):
init("username", gam=True, gyb=False)

mock_clean_config_dir.assert_called_once()
assert mock_GAM_CONFIG_PATH in mock_clean_config_dir.call_args.args
assert mock_google_CallGAMCommand.call_count > 0


def test_init_gyb(mock_GYB_CONFIG_PATH, mock_clean_config_dir, mock_subprocess_call):
init("username", gam=False, gyb=True)

mock_clean_config_dir.assert_called_once()
assert mock_GYB_CONFIG_PATH in mock_clean_config_dir.call_args.args
assert mock_subprocess_call.call_count > 0
22 changes: 19 additions & 3 deletions tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,28 @@ def test_main_info_default(mock_commands_info):
mock_commands_info.assert_called_once()


def test_main_init(mock_commands_init):
def test_main_init_default(mock_commands_init):
main(argv=["init", "username"])

mock_commands_init.assert_called_once()
call_args = mock_commands_init.call_args.args
assert "username" in call_args
assert mock_commands_init.call_args.args == ("username",)
assert mock_commands_init.call_args.kwargs == {"gam": False, "gyb": False}


def test_main_init_gam(mock_commands_init):
main(argv=["init", "username", "--gam"])

mock_commands_init.assert_called_once()
assert mock_commands_init.call_args.args == ("username",)
assert mock_commands_init.call_args.kwargs == {"gam": True, "gyb": False}


def test_main_init_gyb(mock_commands_init):
main(argv=["init", "username", "--gyb"])

mock_commands_init.assert_called_once()
assert mock_commands_init.call_args.args == ("username",)
assert mock_commands_init.call_args.kwargs == {"gam": False, "gyb": True}


def test_main_init_no_username(mock_commands_init):
Expand Down