def test_workflow_step_params_invalid(self): env = get_env("/test/support/", "/test/support/validations/") step_params = {"config_id": "5", "parameters": {"test_param": "test"}} # Broken dag, unreachable nodes # With strict DAG validation setting, throws an error earlier in validation. params = {"step_2": step_params} validated = self.validate_workflow(env, "workflow_basic", '3', params) assert (isinstance(validated, InvalidWorkflow)) # assert("Invalid DAG definition: Invalid Dag: Unreachable steps:" in validated.reason) # What's `Invalid Parameters: ` indicating? It's folllowed only by a blank for both of these. assert ( "Workflow Parameters for step:step_1 not specified. Invalid Parameters: " in validated.reason) assert ( "Workflow Parameters for step:step_3 not specified. Invalid Parameters: " in validated.reason) params = { "step_1": step_params, "step_2": step_params, "step_3": step_params } validated = self.validate_workflow(env, "workflow_basic", '3', params) assert (isinstance(validated, ValidWorkflow))
def test_workflow_multiple_roots_forest_valid(self): env = get_env("/test/support/", "/test/support/validations/") # DAG has multiple disconnected roots, but is structurally sound. step_params = {"config_id": "5", "parameters": {"test_param": "test"}} params = { "step_1": step_params, "step_2": step_params, "step_3": step_params, "step_4": step_params, "step_5": step_params } validated = self.validate_workflow(env, 'workflow_multiple_roots_forest', '3', params) assert (isinstance(validated, ValidWorkflow)) display = """ * step_1 | * step_2 * | step_4 | * step_3 * step_5 """ assert (clean_string(validated.dag.display()) == clean_string(display)) assert (len(validated.dag.valid_steps) == 5)
def test_workflow_parallel_without_cycles_valid(self): env = get_env("/test/support/", "/test/support/validations/") step_params = {"config_id": "5", "parameters": {"test_param": "test"}} params = { "step_1": step_params, "step_2": step_params, "step_3": step_params, "step_4": step_params, "step_5": step_params } validated = self.validate_workflow(env, 'workflow_parallel_without_cycles', '3', params) assert (isinstance(validated, ValidWorkflow)) # TODO: Improve asciidag rendering of this case display = """ * step_1 | * step_1 | * step_4 | * step_5 |/ * step_2 * step_3 """ assert (clean_string(validated.dag.display()) == clean_string(display))
def test_get_all(self): env = base.get_env("/test/support/", "/test/support/validations/") resources = Resources(env) all1 = resources.get_all() all2 = resources.get_all(env.mason_home) assert (len(all1) == 28) assert (len(all2) == 28)
def test_config_dne(self): env = base.get_env("/test/support/", "/test/support/validations/") base.set_log_level() response, status = get("config", 'monkeys', log_level="fatal", env=env) expects = {'Errors': ['No config matching monkeys. Register new resources with \'mason apply\'']} assert(response == expects) assert(status == 404)
def test_good_configs(self): env = base.get_env("/.tmp/", "/test/support/validations/") response, status = apply(from_root("/test/support/"), env=env, log_level="fatal") assert(len(response["Info"]) == 20) assert(len(response["Errors"]) == 8) assert(status == 200) response, status = get("config", env=env, log_level="fatal") assert(len(response["Configs"]) == 4)
def test_namespace(self): env = base.get_env("/test/support/") response, status = get("operator", "namespace1", env=env, log_level="fatal") operators = [{'namespace': 'namespace1', 'command': 'operator1', 'description': 'Test Operator', 'parameters': {'required': ['test_param'], 'optional': []}, 'supported_configurations': [{'metastore': 'test'}]}, {'namespace': 'namespace1', 'command': 'operator2', 'description': 'Test Operator', 'parameters': {'required': ['test_param'], 'optional': []}, 'supported_configurations': [{'metastore': 'test'}]}] assert(sorted(response['Operators'], key=lambda o: o['command']) == operators) # type: ignore assert(status == 200)
def test_good_operators(self): env = base.get_env("/.tmp/", "/test/support/validations/") response, status = apply(from_root("/test/support/"), env=env, log_level="fatal") assert(len(response["Info"]) == 20) assert(len(response["Errors"]) == 8) assert(status == 200) response, status = get("operator", env=env, log_level="fatal") assert(len(response["Operators"]) == 6) operators = sorted(list(map(lambda o: o["command"], response["Operators"]))) assert(operators == ["operator1", "operator2", "operator3", "operator4", "operator5", "operator6"])
def test_config_exists(self): env = base.get_env("/test/support/", "/test/support/validations/") response, status = get("config", '5', env=env) expects = [{'current': False, 'execution_client': [], 'id': '5', 'metastore_client': [{'name': 'test'}], 'scheduler_client': [], 'storage_client': []}] assert(response['Configs'] == expects) assert(status == 200)
def test_workflow_cycle_invalid(self): env = get_env("/test/support/", "/test/support/validations/") step_params = {"config_id": "5", "parameters": {"test_param": "test"}} params = { "step_1": step_params, "step_2": step_params, "step_3": step_params, "step_4": step_params, "step_5": step_params } validated = self.validate_workflow(env, "workflow_cycle", "3", params) assert (isinstance(validated, InvalidWorkflow)) assert ( validated.reason == 'Invalid DAG definition: Invalid Dag: Cycle detected. Repeated steps: step_2 Invalid Dag Steps: ' )
def test_get_resources(self): env = base.get_env("/test/support/", "/test/support/validations/") resources = Resources(env) operators = resources.get_operators() assert (len(operators) == 6) workflows = resources.get_workflows() assert (len(workflows) == 10) configs = resources.get_configs() assert (len(configs) == 4) bad = resources.get_bad() assert (len(bad) == 8) namespace1 = resources.get_operators("namespace1") assert (len(namespace1) == 2) testing_namespace = resources.get_workflows("testing_namespace") assert (len(testing_namespace) == 10) config5 = resources.get_configs("5") assert (len(config5) == 1) assert (isinstance(config5[0], Config)) malformed_config = resources.get_config("0") assert (isinstance(malformed_config, MalformedResource)) malformed_operator = resources.get_operator("namespace1", "operator3") assert (isinstance(malformed_operator, MalformedResource)) operator1 = resources.get_operator("namespace1", "operator1") assert (isinstance(operator1, Operator)) workflow_cycle = resources.get_workflow("testing_namespace", "workflow_cycle") assert (isinstance(workflow_cycle, Workflow)) best_config = resources.get_best_config() assert (isinstance(best_config, Config)) assert (best_config.id == '3') best_config = resources.get_best_config('5') assert (isinstance(best_config, Config)) assert (best_config.id == '5') resources.set_session_config('4') best_config = resources.get_best_config() assert (isinstance(best_config, Config)) assert (best_config.id == '4')
def test_workflow_basic_valid(self): env = get_env("/test/support/", "/test/support/validations/") step_params = {"config_id": "5", "parameters": {"test_param": "test"}} params = { "step_1": step_params, "step_2": step_params, "step_3": step_params } expects = [ 'Performing Dry Run for Workflow', '', 'Valid Workflow DAG Definition:', '--------------------------------------------------------------------------------', '\n* step_1\n* step_2\n* step_3\n', 'Finished' ] validated = self.validate_workflow(env, "workflow_basic", '3', params) run = validated.dry_run(env, Response()) assert (run.response.info == expects)
def test_workflow_operator_self_dependency_invalid(self): env = get_env("/test/support/", "/test/support/validations/") # DAG has step with dependency on itself. step_params = {"config_id": "5", "parameters": {"test_param": "test"}} params = { "step_1": step_params, "step_2": step_params, "step_3": step_params, "step_4": step_params, "step_5": step_params } validated = self.validate_workflow( env, "workflow_operator_self_dependency", '3', params) assert (isinstance(validated, InvalidWorkflow)) assert ( validated.reason == "Invalid DAG definition: Invalid Dag: Cycle detected. Repeated steps: step_2 Invalid Dag Steps: " )
def test_workflow_multiple_roots_cycle_invalid(self): env = get_env("/test/support/", "/test/support/validations/") # DAG has multiple roots, and a cycle occurs downstream of the second root. step_params = {"config_id": "5", "parameters": {"test_param": "test"}} params = { "step_1": step_params, "step_2": step_params, "step_3": step_params, "step_4": step_params, "step_5": step_params } validated = self.validate_workflow(env, 'workflow_multiple_roots_cycle', '3', params) assert (isinstance(validated, InvalidWorkflow)) assert ( validated.reason == "Invalid DAG definition: Invalid Dag: Cycle detected. Repeated steps: step_3 Invalid Dag Steps: " )
def test_all(self): env = get_env("/test/support/", "/test/support/validations/") res = base.Resources(env) config = res.get_config('3') assert (isinstance(config, Config)) execution_clients = list( map(lambda e: e.client.name(), config.execution_clients)) scheduler_clients = list( map(lambda e: e.client.name(), config.scheduler_clients)) storage_clients = list( map(lambda e: e.client.name(), config.storage_clients)) metastore_clients = list( map(lambda e: e.client.name(), config.metastore_clients)) assert (execution_clients == ["test2"]) assert (storage_clients == ["test"]) assert (scheduler_clients == ["test2"]) assert (metastore_clients == ["test"]) assert (config.metastore().client.name() == "test") assert (config.storage().client.name() == "test") assert (config.scheduler().client.name() == "test2") assert (config.execution().client.name() == "test2")
def test_workflow_with_multiple_roots_valid(self): env = get_env("/test/support/", "/test/support/validations/") step_params = {"config_id": "5", "parameters": {"test_param": "test"}} params = { "step_1": step_params, "step_2": step_params, "step_3": step_params, "step_4": step_params, "step_5": step_params } validated = self.validate_workflow(env, "workflow_multiple_roots", '3', params) assert (isinstance(validated, ValidWorkflow)) display = """ * step_1 | * step_4 |/ | * step_5 |/ * step_2 * step_3 """ assert (clean_string(validated.dag.display()) == clean_string(display))
def test_workflow_nonexistent_step_and_cycle_invalid(self): env = get_env("/test/support/", "/test/support/validations/") step_params = {"config_id": "5", "parameters": {"test_param": "test"}} params = { "strict": True, "step_1": step_params, "step_2": step_params, "step_3": step_params, "step_4": step_params } validated = self.validate_workflow( env, 'workflow_nonexistent_step_and_cycle', '3', params) assert (isinstance(validated, InvalidWorkflow)) assert ("Invalid DAG definition: Invalid DAG, contains invalid steps." in validated.reason) params["strict"] = False validated = self.validate_workflow( env, 'workflow_nonexistent_step_and_cycle', '3', params) assert (isinstance(validated, InvalidWorkflow)) assert ( "Invalid DAG definition: Invalid Dag: Unreachable steps: [\'step_4\'] Invalid Dag Steps: Undefined dependent steps:" in validated.reason)
def test_valid(self): env = base.get_env("/test/support/", "/test/support/validations/") response, status = run("operator", "namespace1", "operator1", "test_param:test", None, "3", log_level="fatal", env=env) expects = [{'Name': 'test_table', 'CreatedAt': '', 'CreatedBy': '', 'Schema': {}}] assert(response['Data'] == expects) assert(status == 200)
def test_config_malformed(self): env = base.get_env("/test/support/", "/test/support/validations/") base.set_log_level() response, status = get("config", "0", log_level="fatal", env=env) assert(response['Errors'][0][0:18] == "Malformed resource") assert(status == 400)
def test_invalid_config(self): env = base.get_env("/test/support/", "/test/support/validations/") response, status = validate("operator", "namespace1", "operator1", "test_param:test", None, "4", log_level="fatal", env=env) expects = {'Errors': ['Invalid Resource: Invalid config: Configuration 4 not supported by configured engines for operator namespace1:operator1. Clients [] do not include supported client test for metastore. Check operator.yaml for supported engine configurations.']} assert(response == expects) assert(status == 400)
def test_bad_parameters(self): env = base.get_env("/test/support/", "/test/support/validations/") response, status = validate("operator", "namespace1", "operator1", "test_bad_param:test", None, "3", log_level="fatal", env=env) expects = {'Errors': ['Invalid Resource: Invalid parameters. Required parameter not specified: test_param']} assert(response == expects) assert(status == 400)
def test_invalid_parameters(self): env = base.get_env("/test/support/", "/test/support/validations/") response, status = validate("operator", "namespace1", "operator1", "asdfalskdjf", None, "3", log_level="fatal", env=env) expects = {'Errors': ['Invalid Resource: Invalid parameters. Warning: Parameter string does not conform to needed pattern: <param1>:<value1>,<param2>:<value2>, Required parameter not specified: test_param']} assert(response == expects) assert(status == 400)
def test_valid(self): env = base.get_env("/test/support/", "/test/support/validations/") response, status = validate("operator", "namespace1", "operator1", "test_param:test", None, "3", log_level="fatal", env=env) expects = {'Info': ['Valid Operator: namespace1:operator1 with specified parameters.']} assert(response == expects) assert(status == 200)
def test_command_dne(self): env = base.get_env("/test/support/") response, status = get("operator", "namespace1", "bad_command", "fatal", env) expects = {'Errors' : ['No operator matching namespace1:bad_command. Register new resources with \'mason apply\'']} assert(response == expects) assert(status == 404)
def test_command_malformed(self): env = base.get_env("/test/support/") response, status = get("operator", "namespace1", "operator3", env=env) assert(response['Errors'][0][0:18] == "Malformed resource") assert(status == 400)
def before(self): return base.get_env("/test/support/", "/test/support/validations/")
def test_command_exists(self): env = base.get_env("/test/support/") response, status = get("operator", "namespace1", "operator1", env=env) expects = {'Operators': [{'command': 'operator1', 'description': 'Test Operator', 'namespace': 'namespace1', 'parameters': {'optional': [], 'required': ['test_param']}, 'supported_configurations': [{'metastore': 'test'}]}]} assert(response == expects) assert(status == 200)