Skip to content

Commit

Permalink
feat: add CLI commands for config policies [CM-423] (#9911)
Browse files Browse the repository at this point in the history
  • Loading branch information
salonig23 authored Oct 1, 2024
1 parent ac54cf8 commit 0083d7e
Show file tree
Hide file tree
Showing 4 changed files with 378 additions and 0 deletions.
238 changes: 238 additions & 0 deletions e2e_tests/tests/cluster/test_config_policies.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
import json

import pytest
import yaml

from tests import api_utils
from tests import config as conf
from tests import detproc


@pytest.mark.e2e_cpu
def test_set_config_policies() -> None:
sess = api_utils.user_session()

workspace_name = api_utils.get_random_string()
create_workspace_cmd = ["det", "workspace", "create", workspace_name]
detproc.check_call(sess, create_workspace_cmd)

# valid path with experiment type
stdout = detproc.check_output(
sess,
[
"det",
"config-policies",
"set",
"experiment",
"--workspace",
workspace_name,
"--config-file",
conf.fixtures_path("config_policies/valid.yaml"),
],
)

with open(conf.fixtures_path("config_policies/valid.yaml"), "r") as f:
data = f.read()
print(stdout)
print(data)
assert data.rstrip() == stdout.rstrip()

# valid path with ntsc type
stdout = detproc.check_output(
sess,
[
"det",
"config-policies",
"set",
"ntsc",
"--workspace",
workspace_name,
"--config-file",
conf.fixtures_path("config_policies/valid.yaml"),
],
)

with open(conf.fixtures_path("config_policies/valid.yaml"), "r") as f:
data = f.read()
assert data.rstrip() == stdout.rstrip()

# invalid path
detproc.check_error(
sess,
[
"det",
"config-policies",
"set",
"experiment",
"--workspace",
workspace_name,
"--config-file",
conf.fixtures_path("config_policies/non-existent.yaml"),
],
"No such file or directory",
)

# workspace name not provided
detproc.check_error(
sess,
[
"det",
"config-policies",
"set",
"ntsc",
"--config-file",
conf.fixtures_path("config_policies/valid.yaml"),
],
"the following arguments are required: --workspace",
)

# path not provided
detproc.check_error(
sess,
[
"det",
"config-policies",
"set",
"ntsc",
"--workspace",
workspace_name,
],
"the following arguments are required: --config-file",
)


@pytest.mark.e2e_cpu
def test_describe_config_policies() -> None:
sess = api_utils.user_session()

workspace_name = api_utils.get_random_string()
create_workspace_cmd = ["det", "workspace", "create", workspace_name]
detproc.check_call(sess, create_workspace_cmd)

# set config policies
detproc.check_call(
sess,
[
"det",
"config-policies",
"set",
"ntsc",
"--workspace",
workspace_name,
"--config-file",
conf.fixtures_path("config_policies/valid.yaml"),
],
)

# no specified return type
stdout = detproc.check_output(
sess,
[
"det",
"config-policies",
"describe",
"ntsc",
"--workspace",
workspace_name,
],
)
with open(conf.fixtures_path("config_policies/valid.yaml"), "r") as f:
data = f.read()
assert data.rstrip() == stdout.rstrip()

# yaml return type
stdout = detproc.check_output(
sess,
[
"det",
"config-policies",
"describe",
"ntsc",
"--workspace",
workspace_name,
"--yaml",
],
)
with open(conf.fixtures_path("config_policies/valid.yaml"), "r") as f:
data = f.read()
assert data.rstrip() == stdout.rstrip()

# json return type
stdout = detproc.check_output(
sess,
[
"det",
"config-policies",
"describe",
"ntsc",
"--workspace",
workspace_name,
"--json",
],
)
with open(conf.fixtures_path("config_policies/valid.yaml"), "r") as f:
data = f.read()
original_data = yaml.load(data, Loader=yaml.SafeLoader)
# check if output is a valid json containing original data
assert original_data == json.loads(stdout)

# workspace name not provided
detproc.check_error(
sess,
[
"det",
"config-policies",
"describe",
"ntsc",
],
"the following arguments are required: --workspace",
)


@pytest.mark.e2e_cpu
def test_delete_config_policies() -> None:
sess = api_utils.user_session()

workspace_name = api_utils.get_random_string()
create_workspace_cmd = ["det", "workspace", "create", workspace_name]
detproc.check_call(sess, create_workspace_cmd)

# set config policies
detproc.check_call(
sess,
[
"det",
"config-policies",
"set",
"ntsc",
"--workspace",
workspace_name,
"--config-file",
conf.fixtures_path("config_policies/valid.yaml"),
],
)

stdout = detproc.check_output(
sess,
[
"det",
"config-policies",
"delete",
"ntsc",
"--workspace",
workspace_name,
],
)
assert "Successfully deleted" in stdout

# workspace name not provided
detproc.check_error(
sess,
[
"det",
"config-policies",
"delete",
"ntsc",
],
"the following arguments are required: --workspace",
)
6 changes: 6 additions & 0 deletions e2e_tests/tests/fixtures/config_policies/valid.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
constraints:
priority_limit: 10
resources:
max_slots: 4
invariant_config:
description: test
2 changes: 2 additions & 0 deletions harness/determined/cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
agent,
checkpoint,
command,
config_policies,
dev,
errors,
experiment,
Expand Down Expand Up @@ -163,6 +164,7 @@ def render_sequence(sequence: List[str]) -> str:
+ sso.args_description
+ oauth.args_description
+ dev.args_description
+ config_policies.args_description
)


Expand Down
132 changes: 132 additions & 0 deletions harness/determined/cli/config_policies.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import argparse

from determined import cli
from determined.cli import render
from determined.common import api, util
from determined.common.api import bindings


def describe_config_policies(args: argparse.Namespace) -> None:
sess = cli.setup_session(args)
workload_type = "EXPERIMENT"
if args.workload_type.upper() == "NTSC":
workload_type = "NTSC"

wksp = api.workspace_by_name(sess, args.workspace)
resp = bindings.get_GetWorkspaceConfigPolicies(
sess, workloadType=workload_type, workspaceId=wksp.id
)
if args.json:
render.print_json(resp.configPolicies)
else:
print(util.yaml_safe_dump(resp.configPolicies, default_flow_style=False))


def set_config_policies(args: argparse.Namespace) -> None:
sess = cli.setup_session(args)
try:
with open(args.config_file, "r") as f:
data = f.read()
except Exception as e:
raise cli.errors.CliError(f"Error opening file: {e}")
workload_type = "EXPERIMENT"
if args.workload_type.upper() == "NTSC":
workload_type = "NTSC"

wksp = api.workspace_by_name(sess, args.workspace)
body = bindings.v1PutWorkspaceConfigPoliciesRequest(
workloadType=workload_type, configPolicies=data, workspaceId=wksp.id
)
resp = bindings.put_PutWorkspaceConfigPolicies(
sess, workloadType=workload_type, workspaceId=wksp.id, body=body
)
print(util.yaml_safe_dump(resp.configPolicies, default_flow_style=False))


def delete_config_policies(args: argparse.Namespace) -> None:
sess = cli.setup_session(args)
workload_type = "EXPERIMENT"
if args.workload_type.upper() == "NTSC":
workload_type = "NTSC"

wksp = api.workspace_by_name(sess, args.workspace)
bindings.delete_DeleteWorkspaceConfigPolicies(
sess, workloadType=workload_type, workspaceId=wksp.id
)
print(f"Successfully deleted {workload_type} config policies for workspace {args.workspace}.")


args_description: cli.ArgsDescription = [
cli.Cmd(
"config-policies",
None,
"manage config policies",
[
cli.Cmd(
"describe",
describe_config_policies,
"describe config policies",
[
cli.Arg(
"workload_type",
type=str,
choices=["experiment", "ntsc"],
help="the type (Experiment or NTSC ) of config policies",
),
cli.Arg(
"--workspace",
type=str,
required=True, # change to false when adding --global
help="config policies for the given workspace",
),
cli.Group(cli.output_format_args["json"], cli.output_format_args["yaml"]),
],
is_default=True,
),
cli.Cmd(
"set",
set_config_policies,
"set config policies",
[
cli.Arg(
"workload_type",
type=str,
choices=["experiment", "ntsc"],
help="the type (Experiment or NTSC ) of config policies",
),
cli.Arg(
"--workspace",
type=str,
required=True, # change to false when adding --global
help="config policies for the given workspace",
),
cli.Arg(
"--config-file",
type=str,
required=True,
help="path to the yaml file containing defined config policies",
),
],
),
cli.Cmd(
"delete",
delete_config_policies,
"delete config policies",
[
cli.Arg(
"workload_type",
type=str,
choices=["experiment", "ntsc"],
help="the type (Experiment or NTSC ) of config policies",
),
cli.Arg(
"--workspace",
type=str,
required=True, # change to false when adding --global
help="config policies for the given workspace",
),
],
),
],
)
]

0 comments on commit 0083d7e

Please sign in to comment.