def setUp(self, mocked_now): self.initials = dict(self.initials) self.initials.update(action_template=False) mocked_now.return_value = now1 super().setUp() with self.app2_context: mocked_now.return_value = now2 soft = Software(id='aaaaaaaa-1234-5678-1234-56781234aaa1', name='test', version='1', filename='file') at = ActionTemplate(id='aaaaaaaa-1234-5678-1234-56781234aaa2', name='mkdir', version=1, action_type=ActionType.SHELL, code='mkdir {dir}') db.session.add_all([soft, at]) db.session.commit() mocked_now.return_value = now3 ssa = SoftwareServerAssociation(software=soft, server=Server.get_current(), path='/root') db.session.add(ssa) db.session.commit() self.soft_json = soft.to_json() self.at_json = at.to_json() self.catalog = fetch_catalog(now1) self.mock_queue = mock.Mock() self.mock_dm = mock.Mock() self.mock_dm.flask_app = self.app self.mock_dm.engine = db.engine self.mock_dm.manager.dict.return_value = dict() self.mock_dm.server_id = self.s1.id self.cm = CatalogManager("Catalog", startup_event=threading.Event(), shutdown_event=threading.Event(), publish_q=self.mock_queue, event_q=None, dimensigon=self.mock_dm) db.session.commit()
def fill_database(self): self.at1 = ActionTemplate(id="aaaaaaaa-1234-5678-1234-56781234aaa1", action_type=ActionType.SHELL, code="mkdir {dir}", last_modified_at=defaults.INITIAL_DATEMARK, name="mkdir", version=1) self.at2 = ActionTemplate(id="aaaaaaaa-1234-5678-1234-56781234aaa2", action_type=ActionType.SHELL, code="rmdir {dir}", last_modified_at=defaults.INITIAL_DATEMARK, expected_stdout='output', expected_stderr='err', expected_rc=0, name="rmdir", system_kwargs={'kwarg1': 1}, pre_process='pre_process', post_process='post_process', version=1) with bypass_datamark_update(): db.session.add_all([self.at1, self.at2]) db.session.commit()
def fill_database(self): v1 = Vault(user_id=ROOT, name='home', value='home_content') v2 = Vault(user_id=ROOT, name='command', value='command_content') v3 = Vault(user_id=ROOT, name='foo', value='foo_content') at = ActionTemplate('vault var in mapping', 1, action_type=ActionType.TEST, code='{{input.command}}', schema=dict( input=dict(command=dict(type='string')), required=['command']), id=self.ACTION_TEMPLATE1) at2 = ActionTemplate('vault var in action template code', 1, action_type=ActionType.TEST, code='{{vault.foo}}', schema=dict(required=['vault.foo']), id=self.ACTION_TEMPLATE2) o = Orchestration('vault', 1, id=self.ORCH) s1 = o.add_step(False, name='vault var in step code', action_type=ActionType.TEST, code="{{vault.home}}") s2 = o.add_step( False, action_template=at, schema=dict(mapping={'command': { 'from': 'vault.command' }}), parents=[s1]) s3 = o.add_step(False, action_template=at2, parents=[s2]) db.session.add_all([v1, v2, v3, o])
def populate_initial_data(dm: Dimensigon): from dimensigon.domain.entities import ActionTemplate, Locker, Server, User, Parameter with session_scope(session=dm.get_session()) as session: gates = dm.config.http_conf.get('binds', None) SchemaChanges.set_initial(session) dm.server_id = Server.set_initial(session, gates) Locker.set_initial(session, unlock=True) ActionTemplate.set_initial(session) User.set_initial(session) Parameter.set_initial(session)
def fill_database(self): at1 = ActionTemplate(id='aaaaaaaa-1234-5678-1234-aaaaaaaa0001', name='create dir', version=1, action_type=ActionType.SHELL, code='useradd {{input.user}}; mkdir {{input.dir}}', expected_stdout='', expected_rc=0, system_kwargs={}) at2 = ActionTemplate(id='aaaaaaaa-1234-5678-1234-aaaaaaaa0002', name='rm dir', version=1, action_type=ActionType.SHELL, code='rmuser {{input.user}}', expected_stdout='', expected_rc=0, system_kwargs={}) at3 = ActionTemplate(id='aaaaaaaa-1234-5678-1234-aaaaaaaa0003', name='untar', version=1, action_type=ActionType.SHELL, code='tar -xf {{input.dir}}', expected_stdout='', expected_rc=0, system_kwargs={}) at4 = ActionTemplate(id='aaaaaaaa-1234-5678-1234-aaaaaaaa0004', name='install tibero', version=1, action_type=ActionType.SHELL, code='{{input.home}}/install_tibero.sh', expected_stdout='', expected_rc=0, system_kwargs={}) o = Orchestration('Test Orchestration', 1, 'description', id='bbbbbbbb-1234-5678-1234-bbbbbbbb0001') db.session.add(o) # Orch diagram # f f # 1-->3-->u4-->u5-->u6 # \/ \ \_____/ # /\ \ # 9-->u2 7-->u8 # b s1 = o.add_step(id='dddddddd-1234-5678-1234-dddddddd0001', undo=False, action_template=at1, parents=[], target=['frontend']) s2 = o.add_step(id='dddddddd-1234-5678-1234-dddddddd0002', undo=True, action_template=at2, parents=[s1], target=[]) s3 = o.add_step(id='dddddddd-1234-5678-1234-dddddddd0003', undo=False, action_template=at3, parents=[s1], target=['frontend']) s4 = o.add_step(id='dddddddd-1234-5678-1234-dddddddd0004', undo=True, action_template=at2, parents=[s3], target=[]) s5 = o.add_step(id='dddddddd-1234-5678-1234-dddddddd0005', undo=True, action_template=at2, parents=[s4], target=[]) s6 = o.add_step(id='dddddddd-1234-5678-1234-dddddddd0006', undo=True, action_template=at2, parents=[s4, s5], target=[]) s7 = o.add_step(id='dddddddd-1234-5678-1234-dddddddd0007', undo=False, action_template=at4, parents=[s3], target=[]) s8 = o.add_step(id='dddddddd-1234-5678-1234-dddddddd0008', undo=True, action_template=at2, parents=[s7], target=[]) s9 = o.add_step(id='dddddddd-1234-5678-1234-dddddddd0009', undo=False, action_template=at1, children=[s2, s3], target=['backend'])
def fill_database(self): # create data for orchestration at = ActionTemplate(name='mkdir', version=1, action_type=ActionType.SHELL, code='mkdir -f {{input.folder}}', schema={ 'input': { 'folder': { 'type': 'string' } }, 'required': ['folder'] }, expected_rc=0) o = Orchestration(name='Create folder', version=1, description="creates a folder") s = o.add_step(undo=False, action_template=at) db.session.add_all([at, o, s]) o_wrapper = Orchestration(name="launch create folder", version=1) s21 = o_wrapper.add_step( undo=False, action_template=ActionTemplate.query.get( ActionTemplate.ORCHESTRATION), schema={'mapping': { 'orchestration': str(o.id), }}, parents=[]) db.session.add_all([o_wrapper, s21])
def test_validate_input_chain_mapping_action_template(self): o = Orchestration("test", 1) at = ActionTemplate("action", 1, action_type=ActionType.SHELL, code='', schema={ 'input': { 'param1': {} }, 'required': ['param1'] }) s1 = o.add_step(undo=False, action_template=at, schema={'mapping': { 'param1': "value" }}) s2 = o.add_step(undo=False, action_type=ActionType.SHELL, schema={ 'input': { 'param2': {} }, 'required': ['param2'] }) validate_input_chain(o, params=dict(input={'param2'})) with self.assertRaises(errors.MissingParameters) as e: validate_input_chain(o, params=dict(input={'param1'})) self.assertEqual(['input.param2'], e.exception.parameters)
def fill_database(self): self.o = Orchestration(name='name', version=1, description='desc') self.at = ActionTemplate(name='action_name', version=1, action_type=ActionType.SHELL, code='') db.session.add_all([self.o, self.at])
class TestActionTemplate(TestDimensigonBase): def setUp(self) -> None: self.initials = dict(self.initials) self.initials.update(action_template=False) super().setUp() def fill_database(self): self.at1 = ActionTemplate(id="aaaaaaaa-1234-5678-1234-56781234aaa1", action_type=ActionType.SHELL, code="mkdir {dir}", last_modified_at=defaults.INITIAL_DATEMARK, name="mkdir", version=1) self.at2 = ActionTemplate(id="aaaaaaaa-1234-5678-1234-56781234aaa2", action_type=ActionType.SHELL, code="rmdir {dir}", last_modified_at=defaults.INITIAL_DATEMARK, expected_stdout='output', expected_stderr='err', expected_rc=0, name="rmdir", system_kwargs={'kwarg1': 1}, pre_process='pre_process', post_process='post_process', version=1) with bypass_datamark_update(): db.session.add_all([self.at1, self.at2]) db.session.commit() def test_action_template_list(self): response = self.client.get(url_for('api_1_0.actiontemplatelist'), headers=self.auth.header) self.assertListEqual( [self.at1.to_json(), self.at2.to_json()], response.get_json()) def test_action_template(self): response = self.client.get(url_for( 'api_1_0.actiontemplateresource', action_template_id="aaaaaaaa-1234-5678-1234-56781234aaa1"), headers=self.auth.header) self.assertDictEqual(self.at1.to_json(), response.get_json())
def test_to_from_json(self): now = defaults.INITIAL_DATEMARK at = ActionTemplate(id='aaaaaaaa-1234-5678-1234-56781234aaa1', name='ActionTest2', version=1, action_type=ActionType.ORCHESTRATION, code='test code', last_modified_at=now) db.session.add(at) at_json = at.to_json() self.assertDictEqual( dict(id='aaaaaaaa-1234-5678-1234-56781234aaa1', name='ActionTest2', version=1, action_type='ORCHESTRATION', code='test code', last_modified_at=now.strftime(defaults.DATEMARK_FORMAT)), at_json) at_json['name'] = "ChangedAction" smashed = ActionTemplate.from_json(at_json) self.assertEqual(at.id, smashed.id) self.assertIsNotNone(smashed.id) self.assertEqual("ChangedAction", smashed.name) self.assertIsNotNone(smashed.name) self.assertEqual(at.version, smashed.version) self.assertIsNotNone(smashed.version) self.assertEqual(at.action_type, smashed.action_type) self.assertIsNotNone(smashed.action_type) self.assertEqual(at.code, smashed.code) self.assertIsNotNone(smashed.code) self.assertEqual(at.last_modified_at, smashed.last_modified_at) self.assertIsNotNone(smashed.last_modified_at) db.session.commit() del at del smashed at = ActionTemplate.query.get(at_json['id']) self.assertEqual("ChangedAction", at.name)
def setUp(self): """Create and configure a new app instance for each test.""" # create the app with common test config self.app = create_app('test') self.app_context = self.app.app_context() self.app_context.push() self.client = self.app.test_client() self.auth = HTTPBearerAuth( create_access_token('00000000-0000-0000-0000-000000000001')) db.create_all() self.at = ActionTemplate(name='action', version=1, action_type=ActionType.SHELL, code='code to run', expected_stdout='expected output', expected_rc=0, system_kwargs={}) ActionTemplate.set_initial()
def test_catalog(self, mock_now, mock_get): mock_now.return_value = dt.datetime(2019, 4, 2, tzinfo=dt.timezone.utc) mock_get.return_value = [('ActionTemplate', ActionTemplate)] at1 = ActionTemplate(name='ActionTest1', version=1, action_type=ActionType.ORCHESTRATION, code='') db.session.add(at1) db.session.commit() resp = self.client.get( url_for('api_1_0.catalog', data_mark=dt.datetime(2019, 4, 1, tzinfo=dt.timezone.utc).strftime(defaults.DATEMARK_FORMAT)), headers=self.auth.header) self.assertDictEqual({'ActionTemplate': [at1.to_json()]}, resp.get_json()) mock_now.return_value = dt.datetime(2019, 4, 2, 1, tzinfo=dt.timezone.utc) at2 = ActionTemplate(name='ActionTest2', version=1, action_type=ActionType.ORCHESTRATION, code='') db.session.add(at2) db.session.commit() resp = self.client.get( url_for('api_1_0.catalog', data_mark=dt.datetime(2019, 4, 2, tzinfo=dt.timezone.utc).strftime(defaults.DATEMARK_FORMAT)), headers=self.auth.header) self.assertDictEqual({'ActionTemplate': [at2.to_json()]}, resp.get_json())
def test_validate_input_chain_mapping_default_value(self): o = Orchestration("test", 1) at1 = ActionTemplate("action1", 1, action_type=ActionType.SHELL, code='', schema={ 'input': { 'input1': {}, 'input2': { 'default': 1 } }, 'required': ['input1'], 'output': ['out1', 'out2'] }) at2 = ActionTemplate("action2", 1, action_type=ActionType.SHELL, code='', schema={ 'input': { 'out1': {}, 'out2': {}, 'input2': {} }, 'required': ['out1', 'out2', 'input2'], 'output': [] }) s1 = o.add_step(undo=False, action_template=at1, schema={}) s2 = o.add_step(undo=False, action_template=at2, schema={}, parents=[s1]) with self.assertRaises(errors.MissingParameters) as e: validate_input_chain(o, params=dict(input={'input1'})) self.assertEqual(['input.input2'], e.exception.parameters)
def fill_database(self): self.o = Orchestration('create user', version=1) self.at1 = ActionTemplate(action_type=ActionType.SHELL, name="create folder", version=1, code="sudo mkdir -p {{folder}}") self.at2 = ActionTemplate(action_type=ActionType.SHELL, name="delete folder", version=1, code="sudo rm -fr {{folder}}") self.at3 = ActionTemplate(action_type=ActionType.SHELL, name="create user", version=1, code="sudo useradd -d {{home}} {{user}}") self.at4 = ActionTemplate(action_type=ActionType.SHELL, name="delete user", version=1, code="sudo userdel {{user}}") self.st1 = self.o.add_step(undo=False, action_template=self.at1) self.st2 = self.o.add_step(undo=True, action_template=self.at2, parents=[self.st1]) self.st3 = self.o.add_step(undo=False, action_template=self.at3, parents=[self.st1]) self.st4 = self.o.add_step(undo=True, action_template=self.at4, parents=[self.st3]) db.session.add(self.o) self.o2 = Orchestration('create user', version=2) self.st21 = self.o2.add_step(undo=False, action_template=self.at1) db.session.add(self.o2) db.session.commit()
def fill_database(self): self.at = ActionTemplate(name='action_name', version=1, action_type=ActionType.SHELL, code='') self.o = Orchestration(name='name', version=1) self.st1 = self.o.add_step(undo=False, action_template=self.at) self.st2 = self.o.add_step(undo=False, action_template=self.at, children=[self.st1]) self.st3 = self.o.add_step(undo=False, action_template=self.at, children=[self.st2]) db.session.add_all([self.at, self.o])
def setUp(self): """Create and configure a new app instance for each test.""" # create the app with common test config self.app = create_app('test') self.app_context = self.app.app_context() self.app_context.push() self.client = self.app.test_client() self.headers = {"Authorization": f"Bearer {create_access_token('00000000-0000-0000-0000-000000000001')}"} db.create_all() self.at1 = ActionTemplate(id='11111111-2222-3333-4444-555555550001', name='action1', version=1, action_type=ActionType.SHELL, code='code to run', expected_stdout='expected output', expected_stderr='stderr', expected_rc=0, system_kwargs={}) self.at2 = ActionTemplate(id='11111111-2222-3333-4444-555555550002', name='action2', version=1, action_type=ActionType.SHELL, code='code to run', expected_stdout='expected output', expected_stderr='stderr', expected_rc=0, system_kwargs={}) self.o = Orchestration(id='11111111-2222-3333-4444-666666660001', name='orchestration_name', version=1, description='desc')
def test_create_cmd_from_orchestration_one_step(self): at = ActionTemplate(id='aaaaaaaa-1234-5678-1234-aaaaaaaa0001', name='create dir', version=1, action_type=ActionType.SHELL, code='mkdir {{dir}}', expected_stdout='', expected_rc=0, system_kwargs={}) o = Orchestration('Test Orchestration', 1, 'description', id='bbbbbbbb-1234-5678-1234-bbbbbbbb0001') me = Server('me', port=5000, me=True, id='cccccccc-1234-5678-1234-cccccccc0001') remote = Server('remote', port=5000, id='cccccccc-1234-5678-1234-cccccccc0002') db.session.add_all([me, remote, o]) s1 = o.add_step(id='eeeeeeee-1234-5678-1234-eeeeeeee0001', undo=False, action_template=at, parents=[], target=[]) cc = create_cmd_from_orchestration(o, Context({'dir': './test_folder'}), hosts={'all': [me.id]}, executor=None, register=mock.Mock()) c1, = cc._dag.get_nodes_at_level(1) self.assertTupleEqual(('cccccccc-1234-5678-1234-cccccccc0001', 'eeeeeeee-1234-5678-1234-eeeeeeee0001'), c1.id) self.assertIsInstance(c1, Command) self.assertTrue(c1.stop_on_error) self.assertTrue(c1.undo_on_error) self.assertIsNone(c1.stop_undo_on_error)
def post(self): json_data = request.get_json() if isinstance(json_data, dict): json_data = [json_data] resp_data = [] for json_at in json_data: json_at['action_type'] = ActionType[json_at['action_type']] if 'version' not in json_at: json_at['version'] = ActionTemplate.query.filter_by( name=json_at['name']).count() + 1 at = ActionTemplate(**json_at) db.session.add(at) data = {'id': at.id} if 'version' not in json_at: data.update(version=at.version) resp_data.append(data) db.session.commit() return resp_data[0] if isinstance(request.get_json(), dict) else resp_data, 201
def test_validate_input_chain_vault_container(self): o = Orchestration("test", 1) at1 = ActionTemplate("action1", 1, action_type=ActionType.SHELL, code='', schema={ 'input': { 'vault.var': {} }, 'required': ['vault.var'] }) s1 = o.add_step(undo=False, action_template=at1, schema={}) validate_input_chain(o, params=dict(vault={'var'})) with self.assertRaises(errors.MissingParameters) as e: validate_input_chain(o, params=dict()) self.assertEqual(['vault.var'], e.exception.parameters)
def test_parameters(self): o = Orchestration(id=1, name='Test Orchestration', version=1, description='description') s1 = o.add_step(undo=False, action_template=self.at, parents=[], children=[], stop_on_error=False, id=1) at = ActionTemplate(name='action', version=1, action_type=ActionType.SHELL, code='code to run', expected_stdout='expected output', expected_rc=0, system_kwargs={}) s1.action_template = at
def test_upgrade_catalog_catalog_mismatch(self, mock_lock, mock_entities): mock_lock.return_value.__enter__.return_value = 'applicant' mock_entities.return_value = [('ActionTemplate', ActionTemplate), ('Server', Server)] s = Server('server', last_modified_at=dt.datetime(2019, 4, 1, tzinfo=dt.timezone.utc), port=8000) Route(s, cost=0) at1 = ActionTemplate(id='aaaaaaaa-1234-5678-1234-56781234aaa1', name='mkdir', version=1, action_type=ActionType.SHELL, code='mkdir {dir}', expected_output=None, expected_rc=None, system_kwargs={}, last_modified_at=dt.datetime( 2019, 4, 1, tzinfo=dt.timezone.utc)) at2 = ActionTemplate(id='aaaaaaaa-1234-5678-1234-56781234aaa2', name='rmdir', version=1, action_type=ActionType.SHELL, code='rmdir {dir}', expected_output=None, expected_rc=None, system_kwargs={}, last_modified_at=dt.datetime( 2019, 4, 2, tzinfo=dt.timezone.utc)) responses.add( method='GET', url=re.compile('^' + s.url( 'api_1_0.catalog', data_mark='12345').replace('12345', '')), json={"ActionTemplate": [at1.to_json(), at2.to_json()]}) with self.assertRaises(errors.CatalogMismatch): upgrade_catalog_from_server(s)
def test_upgrade_catalog(self, mock_lock, mock_entities, mock_now, mock_tzlocal): mock_lock.return_value.__enter__.return_value = 'applicant' mock_entities.return_value = [('ActionTemplate', ActionTemplate), ('Server', Server), ('Gate', Gate)] mock_now.return_value = dt.datetime(2019, 4, 1, tzinfo=dt.timezone.utc) mock_tzlocal.return_value = dt.timezone.utc at1 = ActionTemplate(id='aaaaaaaa-1234-5678-1234-56781234aaa1', name='mkdir', version=1, action_type=ActionType.SHELL, code='mkdir {dir}', expected_output=None, expected_rc=None, system_kwargs={}) db.session.add(at1) db.session.commit() s = Server(id='aaaaaaaa-1234-5678-1234-56781234bbb1', name='server', last_modified_at=dt.datetime(2019, 4, 1, tzinfo=dt.timezone.utc)) s_json = s.to_json() g = Gate(server=s, port=80, dns='server', last_modified_at=dt.datetime(2019, 4, 1, tzinfo=dt.timezone.utc)) g_json = g.to_json() Route(s, cost=0) at2 = ActionTemplate(id='aaaaaaaa-1234-5678-1234-56781234aaa2', name='rmdir', version=1, action_type=ActionType.SHELL, code='rmdir {dir}', expected_output=None, expected_rc=None, system_kwargs={}, last_modified_at=dt.datetime( 2019, 4, 2, tzinfo=dt.timezone.utc)) at2_json = at2.to_json() del at2 at1_json = at1.to_json() del at1 at1_json['code'] = 'mkdir -p {dir}' responses.add( method='GET', url=re.compile('^' + s.url( 'api_1_0.catalog', data_mark='12345').replace('12345', '')), json={ "ActionTemplate": [at1_json, at2_json], "Server": [s_json], "Gate": [g_json] }) upgrade_catalog_from_server(s) db.session.expire_all() atl = [at.to_json() for at in ActionTemplate.query.all()] self.assertListEqual([at1_json, at2_json], atl) c = Catalog.query.get('ActionTemplate') self.assertEqual(dt.datetime(2019, 4, 2, tzinfo=dt.timezone.utc), c.last_modified_at) at1 = ActionTemplate.query.get('aaaaaaaa-1234-5678-1234-56781234aaa1') self.assertEqual('mkdir -p {dir}', at.code)
def test_create_cmd_from_orchestration(self): at = ActionTemplate(id='aaaaaaaa-1234-5678-1234-aaaaaaaa0001', name='create dir', version=1, action_type=ActionType.SHELL, code='mkdir {{dir}}', expected_stdout='', expected_rc=0, system_kwargs={}) o = Orchestration('Test Orchestration', 1, 'description', id='bbbbbbbb-1234-5678-1234-bbbbbbbb0001') me = Server('me', port=5000, me=True, id='cccccccc-1234-5678-1234-cccccccc0001') remote = Server('remote', port=5000, id='cccccccc-1234-5678-1234-cccccccc0002') db.session.add_all([me, remote, o]) s1 = o.add_step(id='eeeeeeee-1234-5678-1234-eeeeeeee0001', undo=False, action_template=at, parents=[], target=['frontend']) s2 = o.add_step(id='eeeeeeee-1234-5678-1234-eeeeeeee0002', undo=True, action_template=at, parents=[s1], stop_on_error=False, target=[]) s3 = o.add_step(id='eeeeeeee-1234-5678-1234-eeeeeeee0003', undo=False, action_template=at, parents=[s1], stop_on_error=False, stop_undo_on_error=False, target=['frontend']) s4 = o.add_step(id='eeeeeeee-1234-5678-1234-eeeeeeee0004', undo=True, action_template=at, parents=[s3], target=[]) s5 = o.add_step(id='eeeeeeee-1234-5678-1234-eeeeeeee0005', undo=True, action_template=at, parents=[s4], stop_on_error=True, target=[]) s6 = o.add_step(id='eeeeeeee-1234-5678-1234-eeeeeeee0006', undo=True, action_template=at, parents=[s4, s5], target=[]) s7 = o.add_step(id='eeeeeeee-1234-5678-1234-eeeeeeee0007', undo=False, action_template=at, parents=[s3], undo_on_error=False, target=[]) s8 = o.add_step(id='eeeeeeee-1234-5678-1234-eeeeeeee0008', undo=True, action_template=at, parents=[s7], target=[]) s9 = o.add_step(id='eeeeeeee-1234-5678-1234-eeeeeeee0009', undo=False, action_template=at, children=[s2, s3], target=['backend']) cc = create_cmd_from_orchestration(o, Context({'dir': 'C:\\test_folder'}), hosts={ 'all': [me.id, remote.id], 'frontend': [me.id], 'backend': [remote.id] }, executor=None, register=mock.Mock()) c1, c9 = cc._dag.get_nodes_at_level(1) self.assertTupleEqual(('cccccccc-1234-5678-1234-cccccccc0001', 'eeeeeeee-1234-5678-1234-eeeeeeee0001'), c1.id) self.assertIsInstance(c1, Command) self.assertTrue(c1.stop_on_error) self.assertTrue(c1.undo_on_error) self.assertIsNone(c1.stop_undo_on_error) self.assertTupleEqual(('cccccccc-1234-5678-1234-cccccccc0002', 'eeeeeeee-1234-5678-1234-eeeeeeee0009'), c9.id) self.assertIsInstance(c9, ProxyCommand) self.assertTrue(c9.stop_on_error) self.assertTrue(c9.undo_on_error) self.assertIsNone(c9.stop_undo_on_error) c21 = c1.undo_command self.assertTupleEqual(('cccccccc-1234-5678-1234-cccccccc0001', 'eeeeeeee-1234-5678-1234-eeeeeeee0002'), c21.id) self.assertIsInstance(c21, UndoCommand) self.assertFalse(c21.stop_on_error) c22 = c9.undo_command self.assertTupleEqual(('cccccccc-1234-5678-1234-cccccccc0002', 'eeeeeeee-1234-5678-1234-eeeeeeee0002'), c22.id) self.assertIsInstance(c22, ProxyUndoCommand) self.assertFalse(c22.stop_on_error) c3, = cc._dag.get_nodes_at_level(2) self.assertTupleEqual(('cccccccc-1234-5678-1234-cccccccc0001', 'eeeeeeee-1234-5678-1234-eeeeeeee0003'), c3.id) self.assertIsInstance(c3, Command) self.assertFalse(c3.stop_on_error) self.assertTrue(c3.undo_on_error) self.assertFalse(c3.stop_undo_on_error) self.assertTupleEqual(('undo', 'eeeeeeee-1234-5678-1234-eeeeeeee0003'), c3.undo_command.id) self.assertIsInstance(c3.undo_command, CompositeCommand) self.assertFalse(c3.undo_command.stop_on_error) self.assertIsNone(c3.undo_command.stop_undo_on_error) c4, = c3.undo_command._dag.get_nodes_at_level(1) self.assertIsInstance(c4, UndoCommand) self.assertFalse(c4.stop_on_error) c5, = c3.undo_command._dag.get_nodes_at_level(2) self.assertIsInstance(c5, UndoCommand) self.assertTrue(c5.stop_on_error) c6, = c3.undo_command._dag.get_nodes_at_level(3) self.assertIsInstance(c6, UndoCommand) self.assertFalse(c6.stop_on_error) cc7, = cc._dag.get_nodes_at_level(3) self.assertEqual('eeeeeeee-1234-5678-1234-eeeeeeee0007', cc7.id) self.assertIsInstance(cc7, CompositeCommand) self.assertFalse(cc7.stop_on_error) self.assertFalse(cc7.stop_undo_on_error) c71, c72 = cc7._dag.root self.assertTupleEqual(('cccccccc-1234-5678-1234-cccccccc0001', 'eeeeeeee-1234-5678-1234-eeeeeeee0007'), c71.id) self.assertIsInstance(c71, Command) self.assertTrue(c71.stop_on_error) self.assertFalse(c71.undo_on_error) self.assertIsNone(c71.stop_undo_on_error) self.assertTupleEqual(('cccccccc-1234-5678-1234-cccccccc0001', 'eeeeeeee-1234-5678-1234-eeeeeeee0008'), c71.undo_command.id) self.assertIsInstance(c71.undo_command, UndoCommand) self.assertTrue(c71.undo_command.stop_on_error) self.assertTupleEqual(('cccccccc-1234-5678-1234-cccccccc0002', 'eeeeeeee-1234-5678-1234-eeeeeeee0007'), c72.id) self.assertIsInstance(c72, ProxyCommand) self.assertTrue(c72.stop_on_error) self.assertFalse(c72.undo_on_error) self.assertIsNone(c72.stop_undo_on_error) self.assertTupleEqual(('cccccccc-1234-5678-1234-cccccccc0002', 'eeeeeeee-1234-5678-1234-eeeeeeee0008'), c72.undo_command.id) self.assertIsInstance(c72.undo_command, ProxyUndoCommand) self.assertTrue(c72.undo_command.stop_on_error)
def test_to_from_json(self): start = dt.datetime(2019, 4, 1, tzinfo=dt.timezone.utc) end = dt.datetime(2019, 4, 2, tzinfo=dt.timezone.utc) u = User('user', id='cccccccc-1234-5678-1234-56781234ccc1') db.session.add(u) o = Orchestration('run_orch', 1, id='eeeeeeee-1234-5678-1234-56781234eee1') s = o.add_step(undo=False, action_template=ActionTemplate('orchestration', 1, ActionType.ORCHESTRATION, code='')) co = Orchestration('child', 1, id='eeeeeeee-1234-5678-1234-56781234eee2') cs = o.add_step(undo=False, action_template=ActionTemplate('action', 1, ActionType.SHELL, code='')) db.session.add_all([o, s, co, cs]) oe = OrchExecution(id='bbbbbbbb-1234-5678-1234-56781234bbb1', start_time=start, end_time=end, target={'all': [str(self.me.id), str(self.remote.id)], 'backend': self.remote.name}, params={'params': 'content'}, executor=u, orchestration=o ) se = StepExecution(id='aaaaaaaa-1234-5678-1234-56781234aaa1', start_time=start, end_time=end, step=s, orch_execution_id=oe.id, params={'orchestration_id': 'eeeeeeee-1234-5678-1234-56781234eee2'}, rc=None, success=True, server=self.remote) coe = OrchExecution(id='bbbbbbbb-1234-5678-1234-56781234bbb2', start_time=start, end_time=end, target={'all': [str(self.me.id), str(self.remote.id)], 'backend': self.remote.name}, params={'params': 'content'}, executor=u, orchestration=o, parent_step_execution_id=se.id ) cse = StepExecution(id='aaaaaaaa-1234-5678-1234-56781234aaa2', start_time=start, end_time=end, step=s, orch_execution_id=coe.id, params={'param': 'data'}, rc=0, success=True, server=self.remote, ) se.child_orch_execution_id = coe.id db.session.add_all([oe, se, coe, cse]) db.session.commit() self.assertDictEqual(dict(id=str(oe.id), start_time=start.strftime(defaults.DATETIME_FORMAT), end_time=end.strftime(defaults.DATETIME_FORMAT), target={'all': [str(self.me.id), str(self.remote.id)], 'backend': self.remote.name}, params={'params': 'content'}, orchestration_id=str(o.id), success=None, undo_success=None, executor_id='cccccccc-1234-5678-1234-56781234ccc1', message=None), oe.to_json()) self.assertDictEqual(dict(id=str(oe.id), start_time=start.strftime(defaults.DATETIME_FORMAT), end_time=end.strftime(defaults.DATETIME_FORMAT), target={'all': [str(self.me), str(self.remote)], 'backend': self.remote.name}, params={'params': 'content'}, orchestration={'id': 'eeeeeeee-1234-5678-1234-56781234eee1', 'name': 'run_orch', 'version': 1}, success=None, undo_success=None, executor='user', message=None), oe.to_json(human=True)) dumped = oe.to_json(add_step_exec=True) self.assertEqual(1, len(dumped['steps'])) self.assertEqual('aaaaaaaa-1234-5678-1234-56781234aaa1', dumped['steps'][0]['id']) self.assertIn('orch_execution', dumped['steps'][0]) o_e_json = oe.to_json() db.session.commit() del oe # load existent object smashed = OrchExecution.from_json(o_e_json) self.assertEqual('bbbbbbbb-1234-5678-1234-56781234bbb1', smashed.id) self.assertEqual(start, smashed.start_time) self.assertEqual(end, smashed.end_time) self.assertEqual(o.id, smashed.orchestration.id) self.assertDictEqual({'all': [str(self.me.id), str(self.remote.id)], 'backend': self.remote.name}, smashed.target) self.assertDictEqual({'params': 'content'}, smashed.params) self.assertEqual(User.get_by_name('user'), smashed.executor) self.assertEqual(None, smashed.service) self.assertEqual(None, smashed.success) self.assertEqual(None, smashed.undo_success) # load new object and insert into database new_obj = OrchExecution.from_json(dict(id='bbbbbbbb-1234-5678-1234-56781234bbb3', start_time=start.strftime(defaults.DATETIME_FORMAT), end_time=end.strftime(defaults.DATETIME_FORMAT), target={'all': [str(self.me.id), str(self.remote.id)], 'backend': self.remote.name}, params={'params': 'content'}, orchestration_id=str(o.id), service_id=None, success=None, undo_success=None, executor_id='cccccccc-1234-5678-1234-56781234ccc1')) db.session.add(new_obj) db.session.commit()