def test_deploy_regular_with_instance_resume_running(self): """Tests the deploy mechanism in regular mode with instance within resume action for running service.""" instances = {"crypto": {"artifact": "cryptocurrency"}} cryptocurrency_advanced_config_dict = generate_config(self.network, instances=instances) cryptocurrency_advanced_config = Configuration(cryptocurrency_advanced_config_dict) with Launcher(cryptocurrency_advanced_config) as launcher: explorer = launcher.explorer() launcher.deploy_all() launcher.wait_for_deploy() launcher.start_all() launcher.wait_for_start() self.wait_for_api_restart() for artifact in launcher.launch_state.completed_deployments(): deployed = explorer.is_deployed(artifact) self.assertEqual(deployed, True) self.assertEqual(len(launcher.launch_state.completed_configs()), 1) # try to resume running service instances = {"crypto": {"artifact": "cryptocurrency", "action": "resume"}} cryptocurrency_advanced_config_dict = generate_config(self.network, instances=instances, artifact_action="none") cryptocurrency_advanced_config = Configuration(cryptocurrency_advanced_config_dict) with Launcher(cryptocurrency_advanced_config) as launcher: launcher.deploy_all() launcher.wait_for_deploy() launcher.start_all() with self.assertRaises(NotCommittedError): launcher.wait_for_start()
def test_declare_runtime(self) -> None: Configuration.declare_runtime("test", 2) runtimes = Configuration.runtimes() self.assertTrue("rust" in runtimes) self.assertTrue("test" in runtimes) self.assertEqual(runtimes["rust"], 0) self.assertEqual(runtimes["test"], 2)
def test_deploy_regular_invalid_artifact_name(self): """Tests the deploy mechanism in regular mode with invalid artifact""" cryptocurrency_advanced_config_dict = { "networks": launcher_networks(self.network), "deadline_height": 10000, "artifacts": { "cryptocurrency": { "runtime": "rust", "name": "test-service:0.13.0-rc.2" } }, # We aren't testing initialization here. "instances": {}, } cryptocurrency_advanced_config = Configuration( cryptocurrency_advanced_config_dict) with Launcher(cryptocurrency_advanced_config) as launcher: explorer = launcher.explorer() launcher.deploy_all() launcher.wait_for_deploy() # invalid artifact should not be deployed for artifact in launcher.launch_state.completed_deployments(): deployed = explorer.check_deployed(artifact) self.assertEqual(deployed, False)
def test_deploy_run_dev(self): """Tests the deploy mechanism in run-dev mode.""" cryptocurrency_advanced_config_dict = { "networks": launcher_networks(self.network), "deadline_height": 10000, "artifacts": { "cryptocurrency": { "runtime": "rust", "name": "exonum-cryptocurrency-advanced:0.13.0-rc.2" } }, # We aren't testing initialization here. "instances": {}, } cryptocurrency_advanced_config = Configuration( cryptocurrency_advanced_config_dict) with Launcher(cryptocurrency_advanced_config) as launcher: explorer = launcher.explorer() launcher.deploy_all() launcher.wait_for_deploy() for artifact in launcher.launch_state.completed_deployments(): deployed = explorer.check_deployed(artifact) self.assertEqual(deployed, True)
def test_deploy_dev_with_instance(self): """Tests the deploy mechanism in dev mode with instance.""" cryptocurrency_advanced_config_dict = { "networks": launcher_networks(self.network), "deadline_height": 10000, "artifacts": { "cryptocurrency": { "runtime": "rust", "name": "exonum-cryptocurrency-advanced", "version": "0.13.0-rc.2", } }, "instances": {"crypto": {"artifact": "cryptocurrency"}}, } cryptocurrency_advanced_config = Configuration( cryptocurrency_advanced_config_dict ) with Launcher(cryptocurrency_advanced_config) as launcher: explorer = launcher.explorer() launcher.deploy_all() launcher.wait_for_deploy() launcher.start_all() launcher.wait_for_start() for artifact in launcher.launch_state.completed_deployments(): deployed = explorer.check_deployed(artifact) self.assertEqual(deployed, True) self.assertEqual(len(launcher.launch_state.completed_configs()), 1)
def test_deploy_regular_exceed_deadline_height(self): """Tests the deploy mechanism in regular mode with exceeded deadline height""" cryptocurrency_advanced_config_dict = { "networks": launcher_networks(self.network), "deadline_height": 0, "artifacts": { "cryptocurrency": { "runtime": "rust", "name": "exonum-cryptocurrency-advanced", "version": "0.13.0-rc.2", } }, # We aren't testing initialization here. "instances": {}, } cryptocurrency_advanced_config = Configuration( cryptocurrency_advanced_config_dict) with Launcher(cryptocurrency_advanced_config) as launcher: explorer = launcher.explorer() launcher.deploy_all() launcher.wait_for_deploy() # artifact should not be deployed because of exceeded deadline height for artifact in launcher.launch_state.completed_deployments(): deployed = explorer.check_deployed(artifact) self.assertEqual(deployed, False)
def test_deploy_regular_with_invalid_consensus_config(self): """Tests the deploy mechanism in regular mode with invalid consensus config.""" cryptocurrency_advanced_config_dict = { "networks": launcher_networks(self.network), "deadline_height": 10000, "consensus": { "first_round_timeout": 3000, "status_timeout": 5000, "peers_timeout": 10000, "txs_block_limit": 1000, "max_message_len": 1048576, "min_propose_timeout": 10, "max_propose_timeout": 200, "propose_timeout_threshold": 500 }, "artifacts": { "cryptocurrency": { "runtime": "rust", "name": "exonum-cryptocurrency-advanced", "version": "0.13.0-rc.2", } }, "instances": {"crypto": {"artifact": "cryptocurrency"}}, } with self.assertRaises(RuntimeError): Configuration( cryptocurrency_advanced_config_dict)
def setUp(self): self.network = run_4_nodes("exonum-cryptocurrency-advanced") time.sleep(3) cryptocurrency_advanced_config_dict = { "networks": launcher_networks(self.network), "deadline_height": 10000, "artifacts": { "cryptocurrency": { "runtime": "rust", "name": "exonum-cryptocurrency-advanced:0.13.0-rc.2" } }, "instances": { "crypto": { "artifact": "cryptocurrency" } }, } cryptocurrency_advanced_config = Configuration( cryptocurrency_advanced_config_dict) with Launcher(cryptocurrency_advanced_config) as launcher: explorer = launcher.explorer() launcher.deploy_all() launcher.wait_for_deploy() launcher.start_all() launcher.wait_for_start() for artifact in launcher.launch_state.completed_deployments(): deployed = explorer.check_deployed(artifact) self.assertEqual(deployed, True) for instance in launcher.launch_state.completed_initializations(): explorer.wait_for_start(instance)
def test_deploy_regular_with_instance_stop_action_before_start(self): """Tests the deploy mechanism in regular mode with instance within stop action before start.""" cryptocurrency_advanced_config_dict = { "networks": launcher_networks(self.network), "deadline_height": 10000, "artifacts": { "cryptocurrency": { "runtime": "rust", "name": "exonum-cryptocurrency-advanced", "version": "0.13.0-rc.2", } }, "instances": {"crypto": {"artifact": "cryptocurrency", "action": "stop"}}, } cryptocurrency_advanced_config = Configuration( cryptocurrency_advanced_config_dict ) with Launcher(cryptocurrency_advanced_config) as launcher: launcher.deploy_all() launcher.wait_for_deploy() with self.assertRaises(RuntimeError): launcher.start_all()
def tearDown(self) -> None: # Clean global runtimes state after use. runtimes = Configuration.runtimes() if runtimes != _RUNTIMES_START_STATE: runtimes.clear() for key in _RUNTIMES_START_STATE: runtimes[key] = _RUNTIMES_START_STATE[key]
def setUp(self): try: self.network = run_4_nodes("exonum-cryptocurrency-advanced") wait_network_to_start(self.network) instances = {"crypto": {"artifact": "cryptocurrency"}} cryptocurrency_advanced_config_dict = generate_config( self.network, instances=instances) cryptocurrency_advanced_config = Configuration( cryptocurrency_advanced_config_dict) with Launcher(cryptocurrency_advanced_config) as launcher: explorer = launcher.explorer() launcher.deploy_all() launcher.wait_for_deploy() launcher.start_all() launcher.wait_for_start() for artifact in launcher.launch_state.completed_deployments(): deployed = explorer.check_deployed(artifact) self.assertEqual(deployed, True) # Launcher checks that config is applied, no need to check it again. except Exception as error: # If exception is raise in `setUp`, `tearDown` won't be called, # thus here we ensure that network is stopped and temporary data is removed. # Then we re-raise exception, since the test should fail. self.network.stop() self.network.deinitialize() raise error
def test_deploy_regular_with_invalid_action(self): """Tests the deploy mechanism in regular mode with invalid action.""" instances = {"crypto": {"artifact": "cryptocurrency", "action": "invalid_action"}} cryptocurrency_advanced_config_dict = generate_config(self.network, instances=instances) with self.assertRaises(RuntimeError): Configuration(cryptocurrency_advanced_config_dict)
def test_unload_artifact_of_running_service(self): """Tests unload logic when running service references to an artifact.""" # Deploy a service with 0.2.0 version. instances = {INSTANCE_NAME: {"artifact": "cryptocurrency"}} config_dict = generate_config(self.network, instances=instances) deploy_config = Configuration(config_dict) with Launcher(deploy_config) as launcher: launcher.deploy_all() launcher.wait_for_deploy() self.wait_for_api_restart() explorer = launcher.explorer() for artifact in launcher.launch_state.completed_deployments(): deployed = explorer.is_deployed(artifact) self.assertTrue(deployed) # Try to unload artifact with version 0.1.0 unload_config_dict = generate_config(self.network, instances=instances, artifact_action="unload", artifact_version="0.1.0") unload_config = Configuration(unload_config_dict) with Launcher(unload_config) as launcher: launcher.unload_all() launcher.wait_for_unload() self.wait_for_api_restart() explorer = launcher.explorer() for artifact in unload_config.artifacts.values(): deployed = explorer.is_deployed(artifact) self.assertTrue(deployed) # Not False !!! status, message = launcher.launch_state.unload_status self.assertEqual(status, ActionResult.Fail) self.assertIn( "service `101:cryptocurrency` references it as the current artifact", message)
def test_deploy_regular_with_consensus_config(self): """Tests the deploy mechanism in regular mode with consensus config.""" pub_configs = self.network._public_configs().split() validator_keys = [] for pub_config in pub_configs: keys = [] with open(pub_config, "r") as file: data = file.read() keys.append(re.search('consensus_key = "(.+?)"', data).group(1)) keys.append(re.search('service_key = "(.+?)"', data).group(1)) validator_keys.append(keys) consensus = { "validator_keys": validator_keys, "first_round_timeout": 3000, "status_timeout": 5000, "peers_timeout": 10000, "txs_block_limit": 5000, "max_message_len": 1048576, "min_propose_timeout": 10, "max_propose_timeout": 200, "propose_timeout_threshold": 500, } instances = {"crypto": {"artifact": "cryptocurrency"}} cryptocurrency_advanced_config_dict = generate_config( self.network, consensus=consensus, instances=instances ) cryptocurrency_advanced_config = Configuration( cryptocurrency_advanced_config_dict ) with Launcher(cryptocurrency_advanced_config) as launcher: explorer = launcher.explorer() launcher.deploy_all() launcher.wait_for_deploy() launcher.start_all() launcher.wait_for_start() for artifact in launcher.launch_state.completed_deployments(): deployed = explorer.check_deployed(artifact) self.assertEqual(deployed, True) self.assertEqual(len(launcher.launch_state.completed_configs()), 1) for validator_id in range(self.network.validators_count()): host, public_port, private_port = self.network.api_address(validator_id) client = ExonumClient(host, public_port, private_port) supervisor_api = client.service_apis("supervisor") consensus_config = supervisor_api[0].get_service("consensus-config").json() # check that initial config has been applied self.assertEqual(consensus_config["txs_block_limit"], 5000)
def test_migrate_running_service(self): """Tests migration flow when the migrating service is running.""" # Deploy a service with 0.2.0 version. instances = {INSTANCE_NAME: {"artifact": "cryptocurrency"}} config_dict = generate_config(self.network, instances=instances) deploy_config = Configuration(config_dict) with Launcher(deploy_config) as launcher: launcher.deploy_all() launcher.wait_for_deploy() self.wait_for_api_restart() explorer = launcher.explorer() for artifact in launcher.launch_state.completed_deployments(): deployed = explorer.is_deployed(artifact) self.assertTrue(deployed) # Migrate service data from 0.1.0 to 0.2.0 version migrations = { INSTANCE_NAME: { "runtime": "rust", "name": "exonum-cryptocurrency", "version": "0.2.0" } } migrations_dict = generate_migration_config(self.network, migrations) migration_config = Configuration(migrations_dict) with Launcher(migration_config) as launcher: launcher.migrate_all() launcher.wait_for_migration() for instance, ( status, message ) in launcher.launch_state.completed_migrations().items(): if instance == INSTANCE_NAME: self.assertEqual(status, ActionResult.Fail) self.assertIn("is not stopped or frozen", message)
def test_deploy_regular_with_instance_resume_action_before_start(self): """Tests the deploy mechanism in regular mode with instance within resume action before start.""" instances = {"crypto": {"artifact": "cryptocurrency", "action": "resume"}} cryptocurrency_advanced_config_dict = generate_config(self.network, instances=instances) cryptocurrency_advanced_config = Configuration(cryptocurrency_advanced_config_dict) with Launcher(cryptocurrency_advanced_config) as launcher: launcher.deploy_all() launcher.wait_for_deploy() with self.assertRaises(RuntimeError): launcher.start_all()
def test_freeze_service(self): host, public_port, private_port = self.network.api_address(0) client = ExonumClient(host, public_port, private_port) # Create wallet alice_keys = KeyPair.generate() with ExonumCryptoAdvancedClient(client) as crypto_client: crypto_client.create_wallet(alice_keys, "Alice") with client.create_subscriber("transactions") as subscriber: subscriber.wait_for_new_event() alice_balance = crypto_client.get_balance(alice_keys) self.assertEqual(alice_balance, 100) # Freeze the service instances = { "crypto": { "artifact": "cryptocurrency", "action": "freeze" } } cryptocurrency_advanced_config_dict = generate_config( self.network, instances=instances, artifact_action="none") cryptocurrency_advanced_config = Configuration( cryptocurrency_advanced_config_dict) with Launcher(cryptocurrency_advanced_config) as launcher: launcher.deploy_all() launcher.wait_for_deploy() launcher.start_all() launcher.wait_for_start() # Check that the service status has been changed to `frozen`. for service in client.public_api.available_services().json( )["services"]: if service["spec"]["name"] == "crypto": self.assertEqual(service["status"]["type"], "frozen") # Try to create a new wallet. The operation should fail. with ExonumCryptoAdvancedClient(client) as crypto_client: bob_keys = KeyPair.generate() response = crypto_client.create_wallet(bob_keys, "Bob") self.assertEqual(response.status_code, 400) # Because the service is frozen, transaction should be inadmissible. self.assertEqual(response.json()["title"], "Failed to add transaction to memory pool") # Check that we can use service endpoints for data retrieving. Check wallet once again. with ExonumCryptoAdvancedClient(client) as crypto_client: alice_balance = crypto_client.get_balance(alice_keys) self.assertEqual(alice_balance, 100)
def test_deploy_regular_exceed_deadline_height(self): """Tests the deploy mechanism in regular mode with exceeded deadline height""" cryptocurrency_advanced_config_dict = generate_config(self.network, deadline_height=0) cryptocurrency_advanced_config = Configuration(cryptocurrency_advanced_config_dict) with Launcher(cryptocurrency_advanced_config) as launcher: launcher.deploy_all() with self.assertRaises(NotCommittedError): launcher.wait_for_deploy() # artifact should not be deployed because of exceeded deadline height explorer = launcher.explorer() for artifact in launcher.launch_state.completed_deployments(): deployed = explorer.is_deployed(artifact) self.assertEqual(deployed, False)
def test_deploy_regular_without_instance(self): """Tests the deploy mechanism in regular mode without instance""" cryptocurrency_advanced_config_dict = generate_config(self.network) cryptocurrency_advanced_config = Configuration(cryptocurrency_advanced_config_dict) with Launcher(cryptocurrency_advanced_config) as launcher: launcher.deploy_all() launcher.wait_for_deploy() explorer = launcher.explorer() for artifact in launcher.launch_state.completed_deployments(): deployed = explorer.is_deployed(artifact) self.assertEqual(deployed, True)
def test_deploy_regular_invalid_artifact_name(self): """Tests the deploy mechanism in regular mode with invalid artifact""" cryptocurrency_advanced_config_dict = generate_config(self.network, artifact_name="test-artifact") cryptocurrency_advanced_config = Configuration(cryptocurrency_advanced_config_dict) with Launcher(cryptocurrency_advanced_config) as launcher: launcher.deploy_all() launcher.wait_for_deploy() # invalid artifact should not be deployed explorer = launcher.explorer() for artifact in launcher.launch_state.completed_deployments(): deployed = explorer.is_deployed(artifact) self.assertEqual(deployed, False)
def test_deploy_run_dev(self): """Tests the deploy mechanism in run-dev mode.""" cryptocurrency_advanced_config_dict = generate_config(self.network) cryptocurrency_advanced_config = Configuration(cryptocurrency_advanced_config_dict) with Launcher(cryptocurrency_advanced_config) as launcher: explorer = launcher.explorer() launcher.deploy_all() launcher.wait_for_deploy() for artifact in launcher.launch_state.completed_deployments(): deployed = explorer.is_deployed(artifact) self.assertTrue(deployed)
def test_deploy_regular_exceed_deadline_height(self): """Tests the deploy mechanism in regular mode with exceeded deadline height""" cryptocurrency_advanced_config_dict = generate_config(self.network, deadline_height=0) cryptocurrency_advanced_config = Configuration(cryptocurrency_advanced_config_dict) with Launcher(cryptocurrency_advanced_config) as launcher: launcher.deploy_all() launcher.wait_for_deploy() # artifact should not be deployed because of exceeded deadline height explorer = launcher.explorer() for artifact, (action_result, message) in launcher.launch_state.completed_deployments().items(): deployed = explorer.is_deployed(artifact) self.assertFalse(deployed) self.assertEqual(action_result, ActionResult.Fail) self.assertIn("Actual height for transaction is in the past", message)
def setUp(self): self.network = run_4_nodes("exonum-cryptocurrency-advanced") self.addCleanup(self._tear_down, False) wait_network_to_start(self.network) instances = {"crypto": {"artifact": "cryptocurrency"}} cryptocurrency_advanced_config_dict = generate_config( self.network, instances=instances) cryptocurrency_advanced_config = Configuration( cryptocurrency_advanced_config_dict) with Launcher(cryptocurrency_advanced_config) as launcher: explorer = launcher.explorer() for artifact in launcher.launch_state.completed_deployments(): deployed = explorer.is_deployed(artifact) self.assertEqual(deployed, True)
def test_deploy_regular_with_invalid_consensus_config(self): """Tests the deploy mechanism in regular mode with invalid consensus config.""" consensus = { "first_round_timeout": 3000, "status_timeout": 5000, "peers_timeout": 10000, "txs_block_limit": 1000, "max_message_len": 1048576, "min_propose_timeout": 10, "max_propose_timeout": 200, "propose_timeout_threshold": 500, } instances = {"crypto": {"artifact": "cryptocurrency"}} cryptocurrency_advanced_config_dict = generate_config(self.network, consensus=consensus, instances=instances) with self.assertRaises(RuntimeError): Configuration(cryptocurrency_advanced_config_dict)
def test_deploy_regular_with_invalid_instance(self): """Tests the deploy mechanism in regular mode with invalid instance.""" instances = {"": {"artifact": "cryptocurrency"}} cryptocurrency_advanced_config_dict = generate_config(self.network, instances=instances) cryptocurrency_advanced_config = Configuration(cryptocurrency_advanced_config_dict) with Launcher(cryptocurrency_advanced_config) as launcher: explorer = launcher.explorer() launcher.deploy_all() launcher.wait_for_deploy() launcher.start_all() with self.assertRaises(NotCommittedError): launcher.wait_for_start() for artifact in launcher.launch_state.completed_deployments(): deployed = explorer.is_deployed(artifact) self.assertEqual(deployed, True)
def test_deploy_regular_with_invalid_action(self): """Tests the deploy mechanism in regular mode with invalid action.""" cryptocurrency_advanced_config_dict = { "networks": launcher_networks(self.network), "deadline_height": 10000, "artifacts": { "cryptocurrency": { "runtime": "rust", "name": "exonum-cryptocurrency-advanced", "version": "0.13.0-rc.2", } }, "instances": {"crypto": {"artifact": "cryptocurrency", "action": "invalid_action"}}, } with self.assertRaises(RuntimeError): Configuration( cryptocurrency_advanced_config_dict)
def test_deploy_dev_with_instance(self): """Tests the deploy mechanism in dev mode with instance.""" instances = {"crypto": {"artifact": "cryptocurrency"}} cryptocurrency_advanced_config_dict = generate_config(self.network, instances=instances) cryptocurrency_advanced_config = Configuration(cryptocurrency_advanced_config_dict) with Launcher(cryptocurrency_advanced_config) as launcher: explorer = launcher.explorer() launcher.deploy_all() launcher.wait_for_deploy() launcher.start_all() launcher.wait_for_start() for artifact in launcher.launch_state.completed_deployments(): deployed = explorer.is_deployed(artifact) self.assertEqual(deployed, True) self.assertEqual(len(launcher.launch_state.completed_configs()), 1)
def full_migration_flow(self, action: str): host, public_port, private_port = self.network.api_address(0) client = ExonumClient(host, public_port, private_port) # Deploy a service with 0.2.0 version. instances = {INSTANCE_NAME: {"artifact": "cryptocurrency"}} config_dict = generate_config(self.network, instances=instances) deploy_config = Configuration(config_dict) with Launcher(deploy_config) as launcher: launcher.deploy_all() launcher.wait_for_deploy() self.wait_for_api_restart() explorer = launcher.explorer() for artifact in launcher.launch_state.completed_deployments(): deployed = explorer.is_deployed(artifact) self.assertTrue(deployed) # Create Alice's wallet with 0.1.0 version of the service alice_keys = self._create_wallet(client, "Alice", "0.1.0") # Stop the working service with version 0.1.0. instances = { INSTANCE_NAME: { "artifact": "cryptocurrency", "action": action } } stop_config_dict = generate_config(self.network, instances=instances, artifact_action="none", artifact_version="0.1.0") stop_config = Configuration(stop_config_dict) with Launcher(stop_config) as launcher: launcher.start_all() launcher.wait_for_start() self.wait_for_api_restart() # Check that the service status has been changed to `stopped`. for service in client.public_api.available_services().json( )["services"]: if service["spec"]["name"] == INSTANCE_NAME: self.assertEqual( service["status"]["type"], "stopped" if action == "stop" else "frozen") # Migrate service data from 0.1.0 to 0.2.0 version migrations = { INSTANCE_NAME: { "runtime": "rust", "name": "exonum-cryptocurrency", "version": "0.2.0" } } migrations_dict = generate_migration_config(self.network, migrations) migration_config = Configuration(migrations_dict) with Launcher(migration_config) as launcher: launcher.migrate_all() launcher.wait_for_migration() for service in client.public_api.available_services().json( )["services"]: if service["spec"]["name"] == INSTANCE_NAME: self.assertEqual(service["data_version"], "0.2.0") # Switch service artifact from 0.1.0 to 0.2.0 version with Launcher(migration_config) as launcher: launcher.migrate_all() launcher.wait_for_migration() for service in client.public_api.available_services().json( )["services"]: if service["spec"]["name"] == INSTANCE_NAME: self.assertEqual(service["spec"]["artifact"]["version"], "0.2.0") # Resume service with a new logic version 0.2.0 instances = { INSTANCE_NAME: { "artifact": "cryptocurrency", "action": "resume" } } resume_config_dict = generate_config(self.network, instances=instances, artifact_action="none") resume_config = Configuration(resume_config_dict) with Launcher(resume_config) as launcher: launcher.start_all() launcher.wait_for_start() self.wait_for_api_restart() # Check that the service status has been changed to `active`. for service in client.public_api.available_services().json( )["services"]: if service["spec"]["name"] == INSTANCE_NAME: self.assertEqual(service["status"]["type"], "active") self.assertEqual(service["spec"]["artifact"]["version"], "0.2.0") # Unload artifact with version 0.1.0 unload_config_dict = generate_config(self.network, instances=instances, artifact_action="unload", artifact_version="0.1.0") unload_config = Configuration(unload_config_dict) with Launcher(unload_config) as launcher: launcher.unload_all() launcher.wait_for_unload() self.wait_for_api_restart() explorer = launcher.explorer() for artifact in unload_config.artifacts.values(): deployed = explorer.is_deployed(artifact) self.assertFalse(deployed) # Create Bob's wallet with version 0.2.0 of the service. bob_keys = self._create_wallet(client, "Bob", "0.2.0") # Transfer some coins and check balances and history length. with ExonumCryptoAdvancedClient( client, instance_name=INSTANCE_NAME) as crypto_client: alice_balance = crypto_client.get_balance(alice_keys) self.assertEqual(alice_balance, 100) alice_history_len = crypto_client.get_history_len(alice_keys) self.assertEqual(alice_history_len, 0) bob_balance = crypto_client.get_balance(bob_keys) self.assertEqual(bob_balance, 100) crypto_client.transfer(20, alice_keys, bob_keys.public_key) with client.create_subscriber("transactions") as subscriber: subscriber.wait_for_new_event() alice_balance = crypto_client.get_balance(alice_keys) self.assertEqual(alice_balance, 80) # Get a value from the new field `history_len`. alice_history_len = crypto_client.get_history_len(alice_keys) self.assertEqual(alice_history_len, 1) bob_balance = crypto_client.get_balance(bob_keys) self.assertEqual(bob_balance, 120)
def test_migration_without_switching_artifact(self): """Tests migration flow without migration logic stage.""" host, public_port, private_port = self.network.api_address(0) client = ExonumClient(host, public_port, private_port) # Deploy a service with 0.2.0 version. instances = {INSTANCE_NAME: {"artifact": "cryptocurrency"}} config_dict = generate_config(self.network, instances=instances) deploy_config = Configuration(config_dict) with Launcher(deploy_config) as launcher: launcher.deploy_all() launcher.wait_for_deploy() self.wait_for_api_restart() explorer = launcher.explorer() for artifact in launcher.launch_state.completed_deployments(): deployed = explorer.is_deployed(artifact) self.assertTrue(deployed) # Stop the working service with version 0.1.0. instances = { INSTANCE_NAME: { "artifact": "cryptocurrency", "action": "stop" } } stop_config_dict = generate_config(self.network, instances=instances, artifact_action="none", artifact_version="0.1.0") stop_config = Configuration(stop_config_dict) with Launcher(stop_config) as launcher: launcher.start_all() launcher.wait_for_start() self.wait_for_api_restart() # Check that the service status has been changed to `stopped`. for service in client.public_api.available_services().json( )["services"]: if service["spec"]["name"] == INSTANCE_NAME: self.assertEqual(service["status"]["type"], "stopped") # Migrate service data from 0.1.0 to 0.2.0 version migrations = { INSTANCE_NAME: { "runtime": "rust", "name": "exonum-cryptocurrency", "version": "0.2.0" } } migrations_dict = generate_migration_config(self.network, migrations) migration_config = Configuration(migrations_dict) with Launcher(migration_config) as launcher: launcher.migrate_all() launcher.wait_for_migration() for service in client.public_api.available_services().json( )["services"]: if service["spec"]["name"] == INSTANCE_NAME: self.assertEqual(service["data_version"], "0.2.0") # Try to resume the service without a new logic migration to version 0.2.0 instances = { INSTANCE_NAME: { "artifact": "cryptocurrency", "action": "resume" } } resume_config_dict = generate_config(self.network, instances=instances, artifact_action="none") resume_config = Configuration(resume_config_dict) with Launcher(resume_config) as launcher: launcher.start_all() with self.assertRaises(ExecutionFailError) as e: launcher.wait_for_start() self.assertIn( f"Service `{INSTANCE_NAME}` has data version (0.2.0) differing from its artifact version", e)
def load_config(file_name: str) -> Configuration: """Loads Configuration from the sample .yml file""" config_path = os.path.join(_DIR_PATH, "test_data", file_name) return Configuration.from_yaml(config_path)