async def test_remove_account_namespace_app_id_does_not_have_namespace( self): app = ScheduledJob(**self.required_fields_scheduled_job) account = Account(**ACCOUNT_DEV_DICT) self.assertEqual(self.required_fields_scheduled_job["id"], app.id) app.remove_namespace(account) self.assertEqual(self.required_fields_scheduled_job["id"], app.id)
async def test_remove_namespace_only_once(self): account = Account(**ACCOUNT_DEV_DICT) self.required_fields_scheduled_job[ "id"] = f"{account.namespace}-{account.namespace}-my-app-with-ns" app = ScheduledJob(**self.required_fields_scheduled_job) app.remove_namespace(account) expected_app_id = f"{account.namespace}-my-app-with-ns" self.assertEqual(expected_app_id, app.id)
async def test_remove_namepace_returns_self(self): account = Account(**ACCOUNT_DEV_DICT) self.required_fields_scheduled_job[ "id"] = f"my-app-with-{account.namespace}-ns" app = ScheduledJob(**self.required_fields_scheduled_job) returned_app = app.remove_namespace(account) self.assertTrue(app is returned_app)
async def test_add_account_namespace_to_name(self): app = ScheduledJob(**self.required_fields_scheduled_job) account = Account(**ACCOUNT_DEV_DICT) self.assertEqual(self.required_fields_scheduled_job["id"], app.id) app.add_namespace(account) expected_app_id = ( f"{account.namespace}-{self.required_fields_scheduled_job['id'] }") self.assertEqual(expected_app_id, app.id)
async def test_add_namespace_app_id_has_namespace_in_the_middle(self): account = Account(**ACCOUNT_DEV_DICT) self.required_fields_scheduled_job[ "id"] = f"my-app-with-{account.namespace}-ns" app = ScheduledJob(**self.required_fields_scheduled_job) app.add_namespace(account) expected_app_id = ( f"{account.namespace}-{self.required_fields_scheduled_job['id'] }") self.assertEqual(expected_app_id, app.id)
async def test_remove_namespace_app_id_contains_namespace(self): """ Se o namepspace está no meio do nome, não deve ser removido """ account = Account(**ACCOUNT_DEV_DICT) self.required_fields_scheduled_job[ "id"] = f"my-app-with-{account.namespace}-ns" app = ScheduledJob(**self.required_fields_scheduled_job) app.remove_namespace(account) self.assertEqual(self.required_fields_scheduled_job["id"], app.id)
async def test_add_namespace_app_id_begins_with_namespace(self): """ Adicionamos o namespace independente da app já ter o nome com exatamente o namespace no começo. """ app = ScheduledJob(**self.required_fields_scheduled_job) account = Account(**ACCOUNT_DEV_DICT) self.assertEqual(self.required_fields_scheduled_job["id"], app.id) app.add_namespace(account) app.add_namespace(account) expected_app_id = f"{account.namespace}-{account.namespace }-{self.required_fields_scheduled_job['id']}" self.assertEqual(expected_app_id, app.id)
async def _save_job(self, job: ScheduledJob, user: User, account: Account) -> ScheduledJob: job.add_constraint(f"owner:LIKE:{account.owner}") [ job.add_fetch_uri(fetch) for fetch in settings.SCHEDULED_JOBS_DEFAULT_FETCH_URIS ] namespaced_job_id = f"{account.namespace}-{job.id}" chronos_job = ChronosScheduledJobConverter.to_client_model(job) chronos_job.name = namespaced_job_id cretaed_chronos_job = await self.client.create_job(chronos_job) asgard_job = ChronosScheduledJobConverter.to_asgard_model( cretaed_chronos_job) asgard_job.remove_namespace(account) return asgard_job
def to_asgard_model(cls, other: ChronosJob) -> ScheduledJob: env_dict = None fetch_list = None constraints_list = None if other.environmentVariables: env_dict = ChronosEnvSpecConverter.to_asgard_model( other.environmentVariables) if other.fetch: fetch_list = ChronosFetchURLSpecConverter.to_asgard_model( other.fetch) if other.constraints: constraints_list = ChronosConstraintSpecConverter.to_asgard_model( other.constraints) return ScheduledJob( id=other.name, description=other.description, command=other.command, arguments=other.arguments, cpus=other.cpus, mem=other.mem, disk=other.disk, pull_image=other.container.forcePullImage, enabled=not other.disabled, shell=other.shell, container=ChronosContainerSpecConverter.to_asgard_model( other.container), schedule=ScheduleSpec(value=other.schedule, tz=other.scheduleTimeZone), env=env_dict, fetch=fetch_list, constraints=constraints_list, )
async def test_valid_job_name(self): """ O nome de cada job so poderá ter [a-z0-9-] """ self.required_fields_scheduled_job["id"] = "a-valid-name-2" job = ScheduledJob(**self.required_fields_scheduled_job) self.assertEqual(self.required_fields_scheduled_job["id"], job.id)
async def test_serialized_parse_dict_required_fields(self): full_scheduled_job = { **self.required_fields_scheduled_job, "command": None, "arguments": None, "concurrent": True, "disk": 0, "container": { **self.container_spec, "parameters": None, "privileged": False, "pull_image": True, "volumes": None, "ports": None, "type": "DOCKER", }, "schedule": { **self.schedule_spec }, "env": None, "constraints": None, "fetch": None, "shell": False, "retries": 5, "enabled": True, } self.assertEqual(full_scheduled_job, ScheduledJob(**full_scheduled_job).dict())
async def test_to_client_model_required_fields(self, chronos_job_fixture): asgard_job_dict = ChronosScheduledJobConverter.to_asgard_model( ChronosJob(**chronos_job_fixture)).dict() del asgard_job_dict["env"] del asgard_job_dict["fetch"] del asgard_job_dict["constraints"] chronos_job = ChronosScheduledJobConverter.to_client_model( ScheduledJob(**asgard_job_dict)) chronos_converted = ChronosScheduledJobConverter.to_client_model( ChronosScheduledJobConverter.to_asgard_model(chronos_job)) self.assertEqual(chronos_converted.dict(), chronos_job.dict())
async def _wrapper(request: web.Request): try: req_body = await request.json() except JSONDecodeError as e: return web.json_response( ErrorResource(errors=[ErrorDetail(msg=str(e))]).dict(), status=HTTPStatus.BAD_REQUEST, ) try: job = ScheduledJob(**req_body) except ValidationError as e: return web.json_response( ErrorResource(errors=[ErrorDetail(msg=str(e))]).dict(), status=HTTPStatus.UNPROCESSABLE_ENTITY, ) request["types_registry"].set(job) return await call_http_handler(request, handler)
async def test_to_client_model_env_field(self): asgard_dict_with_env_data = { "id": "my-app", "cpus": 1, "mem": 32, "description": "Example", "schedule": { "value": "2019" }, "container": { "image": "alpine", "network": "BRIDGE" }, "env": { "SERVICE_A_ADDRESS": "https://a.service.local", "SERVICE_B_ADDRESS": "https://b.service.local", }, } asgard_scheduled_job = ScheduledJob(**asgard_dict_with_env_data) chronos_job = ChronosScheduledJobConverter.to_client_model( asgard_scheduled_job) self.assertEqual( [ { "name": "SERVICE_A_ADDRESS", "value": "https://a.service.local", }, { "name": "SERVICE_B_ADDRESS", "value": "https://b.service.local", }, ], [ chronos_job.environmentVariables[0].dict(), chronos_job.environmentVariables[1].dict(), ], )
async def update_job_by_id( request: web.Request, job: ScheduledJob, user: User, account: Account ): job.id = request.match_info["job_id"] return await _update_job(job, user, account)
async def test_invalid_job_name(self): with self.assertRaises(ValidationError): self.required_fields_scheduled_job["id"] = "InvalidJobName" ScheduledJob(**self.required_fields_scheduled_job)
async def test_invalid_job_name_with_slash(self): with self.assertRaises(ValidationError): self.required_fields_scheduled_job["id"] = "my/app" ScheduledJob(**self.required_fields_scheduled_job)
async def update_job_by_id(job_id: str, job: ScheduledJob, user: User, account: Account): job.id = job_id return await _update_job(job, user, account)