olas-operate-middleware 0.12.2__py3-none-any.whl → 0.13.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -105,6 +105,11 @@ class BaseDeploymentRunner(AbstractDeploymentRunner, metaclass=ABCMeta):
105
105
  START_TRIES = constants.DEPLOYMENT_START_TRIES_NUM
106
106
  logger = setup_logger(name="operate.base_deployment_runner")
107
107
 
108
+ def __init__(self, work_directory: Path, is_aea: bool) -> None:
109
+ """Initialize the deployment runner."""
110
+ super().__init__(work_directory)
111
+ self._is_aea = is_aea
112
+
108
113
  def _open_agent_runner_log_file(self) -> TextIOWrapper:
109
114
  """Open agent_runner.log file."""
110
115
  return (
@@ -186,6 +191,21 @@ class BaseDeploymentRunner(AbstractDeploymentRunner, metaclass=ABCMeta):
186
191
  """Setup agent."""
187
192
  working_dir = self._work_directory
188
193
  env = self._prepare_agent_env()
194
+ agent_alias_name = "agent"
195
+ agent_dir_full_path = Path(working_dir) / agent_alias_name
196
+ if not self._is_aea:
197
+ if agent_dir_full_path.exists():
198
+ # remove if exists before fetching! can have issues with retry mechanism of multiple start attempts
199
+ with suppress(Exception):
200
+ shutil.rmtree(agent_dir_full_path, ignore_errors=True)
201
+
202
+ # Add keys
203
+ agent_dir_full_path.mkdir(exist_ok=True, parents=True)
204
+ shutil.copy(
205
+ working_dir / "ethereum_private_key.txt",
206
+ working_dir / "agent" / "ethereum_private_key.txt",
207
+ )
208
+ return
189
209
 
190
210
  self._run_aea_command(
191
211
  "init",
@@ -199,10 +219,6 @@ class BaseDeploymentRunner(AbstractDeploymentRunner, metaclass=ABCMeta):
199
219
  cwd=working_dir,
200
220
  )
201
221
 
202
- agent_alias_name = "agent"
203
-
204
- agent_dir_full_path = Path(working_dir) / agent_alias_name
205
-
206
222
  if agent_dir_full_path.exists():
207
223
  # remove if exists before fetching! can have issues with retry mechanism of multiple start attempts
208
224
  with suppress(Exception):
@@ -264,13 +280,16 @@ class BaseDeploymentRunner(AbstractDeploymentRunner, metaclass=ABCMeta):
264
280
  def _start(self, password: str) -> None:
265
281
  """Start the deployment."""
266
282
  self._setup_agent(password=password)
267
- self._start_tendermint()
283
+ if self._is_aea:
284
+ self._start_tendermint()
285
+
268
286
  self._start_agent(password=password)
269
287
 
270
288
  def stop(self) -> None:
271
289
  """Stop the deployment."""
272
290
  self._stop_agent()
273
- self._stop_tendermint()
291
+ if self._is_aea:
292
+ self._stop_tendermint()
274
293
 
275
294
  def _stop_agent(self) -> None:
276
295
  """Start process."""
@@ -313,6 +332,24 @@ class BaseDeploymentRunner(AbstractDeploymentRunner, metaclass=ABCMeta):
313
332
  """Return aea_bin path."""
314
333
  raise NotImplementedError
315
334
 
335
+ def get_agent_start_args(self, password: str) -> List[str]:
336
+ """Return agent start arguments."""
337
+ return (
338
+ [self._agent_runner_bin]
339
+ + (
340
+ [
341
+ "-s",
342
+ "run",
343
+ ]
344
+ if self._is_aea
345
+ else []
346
+ )
347
+ + [
348
+ "--password",
349
+ password,
350
+ ]
351
+ )
352
+
316
353
 
317
354
  class PyInstallerHostDeploymentRunner(BaseDeploymentRunner):
318
355
  """Deployment runner within pyinstaller env."""
@@ -320,16 +357,8 @@ class PyInstallerHostDeploymentRunner(BaseDeploymentRunner):
320
357
  @property
321
358
  def _agent_runner_bin(self) -> str:
322
359
  """Return aea_bin path."""
323
- env = json.loads(
324
- (self._work_directory / "agent.json").read_text(encoding="utf-8")
325
- )
326
-
327
- agent_publicid_str = env["AEA_AGENT"]
328
360
  service_dir = self._work_directory.parent
329
-
330
- agent_runner_bin = get_agent_runner_path(
331
- service_dir=service_dir, agent_public_id_str=agent_publicid_str
332
- )
361
+ agent_runner_bin = get_agent_runner_path(service_dir=service_dir)
333
362
  return str(agent_runner_bin)
334
363
 
335
364
  @property
@@ -393,13 +422,7 @@ class PyInstallerHostDeploymentRunnerMac(PyInstallerHostDeploymentRunner):
393
422
  """Start agent process."""
394
423
  agent_runner_log_file = self._open_agent_runner_log_file()
395
424
  process = subprocess.Popen( # pylint: disable=consider-using-with,subprocess-popen-preexec-fn # nosec
396
- args=[
397
- self._agent_runner_bin,
398
- "-s",
399
- "run",
400
- "--password",
401
- password,
402
- ],
425
+ args=self.get_agent_start_args(password=password),
403
426
  cwd=working_dir / "agent",
404
427
  stdout=agent_runner_log_file,
405
428
  stderr=agent_runner_log_file,
@@ -431,9 +454,9 @@ class PyInstallerHostDeploymentRunnerMac(PyInstallerHostDeploymentRunner):
431
454
  class PyInstallerHostDeploymentRunnerWindows(PyInstallerHostDeploymentRunner):
432
455
  """Windows deployment runner."""
433
456
 
434
- def __init__(self, work_directory: Path) -> None:
457
+ def __init__(self, work_directory: Path, is_aea: bool) -> None:
435
458
  """Init the runner."""
436
- super().__init__(work_directory)
459
+ super().__init__(work_directory, is_aea=is_aea)
437
460
  self._job = self.set_windows_object_job()
438
461
 
439
462
  @staticmethod
@@ -519,13 +542,7 @@ class PyInstallerHostDeploymentRunnerWindows(PyInstallerHostDeploymentRunner):
519
542
  """Start agent process."""
520
543
  agent_runner_log_file = self._open_agent_runner_log_file()
521
544
  process = subprocess.Popen( # pylint: disable=consider-using-with # nosec
522
- args=[
523
- self._agent_runner_bin,
524
- "-s",
525
- "run",
526
- "--password",
527
- password,
528
- ], # TODO: Patch for Windows failing hash
545
+ args=self.get_agent_start_args(password=password),
529
546
  cwd=working_dir / "agent",
530
547
  stdout=agent_runner_log_file,
531
548
  stderr=agent_runner_log_file,
@@ -562,7 +579,12 @@ class HostPythonHostDeploymentRunner(BaseDeploymentRunner):
562
579
  @property
563
580
  def _agent_runner_bin(self) -> str:
564
581
  """Return aea_bin path."""
565
- return str(self._venv_dir / "bin" / "aea")
582
+ if self._is_aea:
583
+ return str(self._venv_dir / "bin" / "aea")
584
+
585
+ service_dir = self._work_directory.parent
586
+ agent_runner_bin = get_agent_runner_path(service_dir=service_dir)
587
+ return str(agent_runner_bin)
566
588
 
567
589
  def _start_agent(self, password: str) -> None:
568
590
  """Start agent process."""
@@ -573,13 +595,7 @@ class HostPythonHostDeploymentRunner(BaseDeploymentRunner):
573
595
  agent_runner_log_file = self._open_agent_runner_log_file()
574
596
 
575
597
  process = subprocess.Popen( # pylint: disable=consider-using-with # nosec
576
- args=[
577
- self._agent_runner_bin,
578
- "-s",
579
- "run",
580
- "--password",
581
- password,
582
- ], # TODO: Patch for Windows failing hash
598
+ args=self.get_agent_start_args(password=password),
583
599
  cwd=str(working_dir / "agent"),
584
600
  env={**os.environ, **env},
585
601
  stdout=agent_runner_log_file,
@@ -629,6 +645,9 @@ class HostPythonHostDeploymentRunner(BaseDeploymentRunner):
629
645
 
630
646
  def _setup_venv(self) -> None:
631
647
  """Perform venv setup, install deps."""
648
+ if not self._is_aea:
649
+ return
650
+
632
651
  self._venv_dir.mkdir(exist_ok=True)
633
652
  venv_cli(args=[str(self._venv_dir)])
634
653
  pbin = str(self._venv_dir / "bin" / "python")
@@ -655,6 +674,9 @@ class HostPythonHostDeploymentRunner(BaseDeploymentRunner):
655
674
  multiprocessing.set_start_method("spawn")
656
675
  self._setup_venv()
657
676
  super()._setup_agent(password=password)
677
+ if not self._is_aea:
678
+ return
679
+
658
680
  # Install agent dependencies
659
681
  self._run_cmd(
660
682
  args=[
@@ -690,9 +712,11 @@ class DeploymentManager:
690
712
  self.logger = setup_logger(name="operate.deployment_manager")
691
713
  self._states: Dict[Path, States] = {}
692
714
 
693
- def _get_deployment_runner(self, build_dir: Path) -> BaseDeploymentRunner:
715
+ def _get_deployment_runner(
716
+ self, build_dir: Path, is_aea: bool
717
+ ) -> BaseDeploymentRunner:
694
718
  """Get deploymnent runner instance."""
695
- return self._deployment_runner_class(build_dir)
719
+ return self._deployment_runner_class(build_dir, is_aea=is_aea)
696
720
 
697
721
  @staticmethod
698
722
  def _get_host_deployment_runner_class() -> Type[BaseDeploymentRunner]:
@@ -741,7 +765,9 @@ class DeploymentManager:
741
765
  "Failed to perform test connection to ipfs to check network connection!"
742
766
  )
743
767
 
744
- def run_deployment(self, build_dir: Path, password: str) -> None:
768
+ def run_deployment(
769
+ self, build_dir: Path, password: str, is_aea: bool = True
770
+ ) -> None:
745
771
  """Run deployment."""
746
772
  if self._is_stopping:
747
773
  raise RuntimeError("deployment manager stopped")
@@ -754,7 +780,9 @@ class DeploymentManager:
754
780
  self.logger.info(f"Starting deployment {build_dir}...")
755
781
  self._states[build_dir] = States.STARTING
756
782
  try:
757
- deployment_runner = self._get_deployment_runner(build_dir=build_dir)
783
+ deployment_runner = self._get_deployment_runner(
784
+ build_dir=build_dir, is_aea=is_aea
785
+ )
758
786
  deployment_runner.start(password=password)
759
787
  self.logger.info(f"Started deployment {build_dir}")
760
788
  self._states[build_dir] = States.STARTED
@@ -771,7 +799,9 @@ class DeploymentManager:
771
799
  )
772
800
  self.stop_deployment(build_dir=build_dir, force=True)
773
801
 
774
- def stop_deployment(self, build_dir: Path, force: bool = False) -> None:
802
+ def stop_deployment(
803
+ self, build_dir: Path, force: bool = False, is_aea: bool = True
804
+ ) -> None:
775
805
  """Stop the deployment."""
776
806
  if (
777
807
  self.get_state(build_dir=build_dir) in [States.STARTING, States.STOPPING]
@@ -780,7 +810,9 @@ class DeploymentManager:
780
810
  raise ValueError("Service already in transition")
781
811
  self.logger.info(f"Stopping deployment {build_dir}...")
782
812
  self._states[build_dir] = States.STOPPING
783
- deployment_runner = self._get_deployment_runner(build_dir=build_dir)
813
+ deployment_runner = self._get_deployment_runner(
814
+ build_dir=build_dir, is_aea=is_aea
815
+ )
784
816
  try:
785
817
  deployment_runner.stop()
786
818
  self.logger.info(f"Stopped deployment {build_dir}...")
@@ -794,14 +826,16 @@ class DeploymentManager:
794
826
  deployment_manager = DeploymentManager()
795
827
 
796
828
 
797
- def run_host_deployment(build_dir: Path, password: str) -> None:
829
+ def run_host_deployment(build_dir: Path, password: str, is_aea: bool = True) -> None:
798
830
  """Run host deployment."""
799
- deployment_manager.run_deployment(build_dir=build_dir, password=password)
831
+ deployment_manager.run_deployment(
832
+ build_dir=build_dir, password=password, is_aea=is_aea
833
+ )
800
834
 
801
835
 
802
- def stop_host_deployment(build_dir: Path) -> None:
836
+ def stop_host_deployment(build_dir: Path, is_aea: bool = True) -> None:
803
837
  """Stop host deployment."""
804
- deployment_manager.stop_deployment(build_dir=build_dir)
838
+ deployment_manager.stop_deployment(build_dir=build_dir, is_aea=is_aea)
805
839
 
806
840
 
807
841
  def stop_deployment_manager() -> None:
@@ -79,11 +79,13 @@ class FundingManager:
79
79
 
80
80
  def __init__(
81
81
  self,
82
+ keys_manager: KeysManager,
82
83
  wallet_manager: MasterWalletManager,
83
84
  logger: Logger,
84
85
  funding_requests_cooldown_seconds: int = DEFAULT_FUNDING_REQUESTS_COOLDOWN_SECONDS,
85
86
  ) -> None:
86
87
  """Initialize funding manager."""
88
+ self.keys_manager = keys_manager
87
89
  self.wallet_manager = wallet_manager
88
90
  self.logger = logger
89
91
  self.funding_requests_cooldown_seconds = funding_requests_cooldown_seconds
@@ -102,7 +104,7 @@ class FundingManager:
102
104
  f"Draining service agents {service.name} ({service_config_id=})"
103
105
  )
104
106
  for agent_address in service.agent_addresses:
105
- ethereum_crypto = KeysManager().get_crypto_instance(agent_address)
107
+ ethereum_crypto = self.keys_manager.get_crypto_instance(agent_address)
106
108
  balance = ledger_api.get_balance(agent_address)
107
109
  self.logger.info(
108
110
  f"Draining {balance} (approx) {get_currency_denom(chain)} from {agent_address} (agent) to {withdrawal_address}"
@@ -167,7 +169,7 @@ class FundingManager:
167
169
 
168
170
  # Safe not swapped
169
171
  if set(owners) == set(service.agent_addresses):
170
- ethereum_crypto = KeysManager().get_crypto_instance(
172
+ ethereum_crypto = self.keys_manager.get_crypto_instance(
171
173
  service.agent_addresses[0]
172
174
  )
173
175
  transfer_erc20_from_safe(
@@ -207,7 +209,7 @@ class FundingManager:
207
209
  )
208
210
 
209
211
  if set(owners) == set(service.agent_addresses):
210
- ethereum_crypto = KeysManager().get_crypto_instance(
212
+ ethereum_crypto = self.keys_manager.get_crypto_instance(
211
213
  service.agent_addresses[0]
212
214
  )
213
215
  transfer_from_safe(
@@ -109,9 +109,10 @@ NUM_LOCAL_AGENT_INSTANCES = 1
109
109
  class ServiceManager:
110
110
  """Service manager."""
111
111
 
112
- def __init__(
112
+ def __init__( # pylint: disable=too-many-arguments
113
113
  self,
114
114
  path: Path,
115
+ keys_manager: KeysManager,
115
116
  wallet_manager: MasterWalletManager,
116
117
  funding_manager: FundingManager,
117
118
  logger: logging.Logger,
@@ -126,7 +127,7 @@ class ServiceManager:
126
127
  :param logger: logging.Logger object.
127
128
  """
128
129
  self.path = path
129
- self.keys_manager = KeysManager()
130
+ self.keys_manager = keys_manager
130
131
  self.wallet_manager = wallet_manager
131
132
  self.funding_manager = funding_manager
132
133
  self.logger = logger
@@ -812,6 +813,9 @@ class ServiceManager:
812
813
  on_chain_metadata = self._get_on_chain_metadata(chain_config=chain_config)
813
814
  on_chain_hash = on_chain_metadata.get("code_uri", "")[len(IPFS_URI_PREFIX) :]
814
815
  on_chain_description = on_chain_metadata.get("description")
816
+ needs_update_agent_addresses = set(chain_data.instances) != set(
817
+ service.agent_addresses
818
+ )
815
819
 
816
820
  current_agent_bond = sftxb.get_agent_bond(
817
821
  service_id=chain_data.token, agent_id=target_staking_params["agent_ids"][0]
@@ -840,6 +844,7 @@ class ServiceManager:
840
844
  or current_staking_params["staking_token"]
841
845
  != target_staking_params["staking_token"]
842
846
  or on_chain_description != service.description
847
+ or needs_update_agent_addresses
843
848
  )
844
849
  )
845
850
 
@@ -1923,7 +1928,9 @@ class ServiceManager:
1923
1928
  # TODO: remove after staking contract directly starts sending the rewards to master safe
1924
1929
  amount_claimed = int(receipt["logs"][0]["data"].hex(), 16)
1925
1930
  self.logger.info(f"Claimed amount: {amount_claimed}")
1926
- ethereum_crypto = KeysManager().get_crypto_instance(service.agent_addresses[0])
1931
+ ethereum_crypto = self.keys_manager.get_crypto_instance(
1932
+ service.agent_addresses[0]
1933
+ )
1927
1934
  transfer_erc20_from_safe(
1928
1935
  ledger_api=ledger_api,
1929
1936
  crypto=ethereum_crypto,
@@ -2206,7 +2213,7 @@ class ServiceManager:
2206
2213
  chain=chain,
2207
2214
  )
2208
2215
 
2209
- def deploy_service_locally(
2216
+ def deploy_service_locally( # pylint: disable=too-many-arguments
2210
2217
  self,
2211
2218
  service_config_id: str,
2212
2219
  chain: t.Optional[str] = None,
@@ -2232,11 +2239,15 @@ class ServiceManager:
2232
2239
  use_kubernetes=use_kubernetes,
2233
2240
  force=True,
2234
2241
  chain=chain or service.home_chain,
2235
- password=self.wallet_manager.password,
2242
+ keys_manager=self.keys_manager,
2236
2243
  )
2237
2244
  if build_only:
2238
2245
  return deployment
2239
- deployment.start(password=self.wallet_manager.password, use_docker=use_docker)
2246
+ deployment.start(
2247
+ password=self.wallet_manager.password,
2248
+ use_docker=use_docker,
2249
+ is_aea=service.agent_release["is_aea"],
2250
+ )
2240
2251
  return deployment
2241
2252
 
2242
2253
  def stop_service_locally(
@@ -2256,7 +2267,11 @@ class ServiceManager:
2256
2267
  service = self.load(service_config_id=service_config_id)
2257
2268
  service.remove_latest_healthcheck()
2258
2269
  deployment = service.deployment
2259
- deployment.stop(use_docker=use_docker, force=force)
2270
+ deployment.stop(
2271
+ use_docker=use_docker,
2272
+ force=force,
2273
+ is_aea=service.agent_release["is_aea"],
2274
+ )
2260
2275
  if delete:
2261
2276
  deployment.delete()
2262
2277
  return deployment
@@ -79,6 +79,7 @@ from operate.keys import KeysManager
79
79
  from operate.ledger import get_default_ledger_api, get_default_rpc
80
80
  from operate.operate_http.exceptions import NotAllowed
81
81
  from operate.operate_types import (
82
+ AgentRelease,
82
83
  Chain,
83
84
  ChainAmounts,
84
85
  ChainConfig,
@@ -107,7 +108,7 @@ from operate.utils.ssl import create_ssl_certificate
107
108
  SAFE_CONTRACT_ADDRESS = "safe_contract_address"
108
109
  ALL_PARTICIPANTS = "all_participants"
109
110
  CONSENSUS_THRESHOLD = "consensus_threshold"
110
- SERVICE_CONFIG_VERSION = 8
111
+ SERVICE_CONFIG_VERSION = 9
111
112
  SERVICE_CONFIG_PREFIX = "sc-"
112
113
 
113
114
  NON_EXISTENT_MULTISIG = None
@@ -328,6 +329,8 @@ class HostDeploymentGenerator(BaseDeploymentGenerator):
328
329
  use_acn: bool = False,
329
330
  ) -> "HostDeploymentGenerator":
330
331
  """Generate agent and tendermint configurations"""
332
+ self.build_dir.mkdir(exist_ok=True, parents=True)
333
+ (self.build_dir / "agent").mkdir(exist_ok=True, parents=True)
331
334
  agent = self.service_builder.generate_agent(agent_n=0)
332
335
  agent = {key: f"{value}" for key, value in agent.items()}
333
336
  (self.build_dir / "agent.json").write_text(
@@ -395,7 +398,7 @@ class Deployment(LocalResource):
395
398
  if source_path.exists():
396
399
  shutil.copy(source_path, destination_path)
397
400
 
398
- def _build_kubernetes(self, password: str, force: bool = True) -> None:
401
+ def _build_kubernetes(self, keys_manager: KeysManager, force: bool = True) -> None:
399
402
  """Build kubernetes deployment."""
400
403
  k8s_build = self.path / DEPLOYMENT_DIR / "abci_build_k8s"
401
404
  if k8s_build.exists() and force:
@@ -407,7 +410,7 @@ class Deployment(LocalResource):
407
410
  keys_file.write_text(
408
411
  json.dumps(
409
412
  [
410
- KeysManager().get(address).get_decrypted(password)
413
+ keys_manager.get_decrypted(address)
411
414
  for address in service.agent_addresses
412
415
  ],
413
416
  indent=4,
@@ -437,7 +440,7 @@ class Deployment(LocalResource):
437
440
 
438
441
  def _build_docker(
439
442
  self,
440
- password: str,
443
+ keys_manager: KeysManager,
441
444
  force: bool = True,
442
445
  chain: t.Optional[str] = None,
443
446
  ) -> None:
@@ -462,7 +465,7 @@ class Deployment(LocalResource):
462
465
  keys_file.write_text(
463
466
  json.dumps(
464
467
  [
465
- KeysManager().get(address).get_decrypted(password)
468
+ keys_manager.get_decrypted(address)
466
469
  for address in service.agent_addresses
467
470
  ],
468
471
  indent=4,
@@ -551,7 +554,13 @@ class Deployment(LocalResource):
551
554
  self.status = DeploymentStatus.BUILT
552
555
  self.store()
553
556
 
554
- def _build_host(self, force: bool = True, chain: t.Optional[str] = None) -> None:
557
+ def _build_host(
558
+ self,
559
+ keys_manager: KeysManager,
560
+ force: bool = True,
561
+ chain: t.Optional[str] = None,
562
+ with_tm: bool = True,
563
+ ) -> None:
555
564
  """Build host depployment."""
556
565
  build = self.path / DEPLOYMENT_DIR
557
566
  if build.exists() and not force:
@@ -585,10 +594,7 @@ class Deployment(LocalResource):
585
594
  keys_file = self.path / DEFAULT_KEYS_FILE
586
595
  keys_file.write_text(
587
596
  json.dumps(
588
- [
589
- KeysManager().get(address).json
590
- for address in service.agent_addresses
591
- ],
597
+ [keys_manager.get(address).json for address in service.agent_addresses],
592
598
  indent=4,
593
599
  ),
594
600
  encoding="utf-8",
@@ -608,15 +614,21 @@ class Deployment(LocalResource):
608
614
  consensus_threshold=None,
609
615
  )
610
616
 
611
- (
612
- HostDeploymentGenerator(
613
- service_builder=builder,
614
- build_dir=build.resolve(),
615
- use_tm_testnet_setup=True,
616
- )
617
- .generate_config_tendermint()
618
- .generate()
619
- .populate_private_keys()
617
+ deployement_generator = HostDeploymentGenerator(
618
+ service_builder=builder,
619
+ build_dir=build.resolve(),
620
+ use_tm_testnet_setup=True,
621
+ )
622
+ if with_tm:
623
+ deployement_generator.generate_config_tendermint()
624
+
625
+ deployement_generator.generate()
626
+ deployement_generator.populate_private_keys()
627
+
628
+ # Add keys
629
+ shutil.copy(
630
+ build / "ethereum_private_key.txt",
631
+ build / "agent" / "ethereum_private_key.txt",
620
632
  )
621
633
 
622
634
  except Exception as e:
@@ -629,7 +641,7 @@ class Deployment(LocalResource):
629
641
 
630
642
  def build(
631
643
  self,
632
- password: str,
644
+ keys_manager: KeysManager,
633
645
  use_docker: bool = False,
634
646
  use_kubernetes: bool = False,
635
647
  force: bool = True,
@@ -665,9 +677,9 @@ class Deployment(LocalResource):
665
677
  )
666
678
  service.consume_env_variables()
667
679
  if use_docker:
668
- self._build_docker(password=password, force=force, chain=chain)
680
+ self._build_docker(keys_manager=keys_manager, force=force, chain=chain)
669
681
  if use_kubernetes:
670
- self._build_kubernetes(password=password, force=force)
682
+ self._build_kubernetes(keys_manager=keys_manager, force=force)
671
683
  else:
672
684
  ssl_key_path, ssl_cert_path = create_ssl_certificate(
673
685
  ssl_dir=service.path / DEPLOYMENT_DIR / "ssl"
@@ -679,12 +691,23 @@ class Deployment(LocalResource):
679
691
  }
680
692
  )
681
693
  service.consume_env_variables()
682
- self._build_host(force=force, chain=chain)
694
+ is_aea = service.agent_release["is_aea"]
695
+ self._build_host(
696
+ keys_manager=keys_manager,
697
+ force=force,
698
+ chain=chain,
699
+ with_tm=is_aea,
700
+ )
683
701
 
684
702
  os.environ.clear()
685
703
  os.environ.update(original_env)
686
704
 
687
- def start(self, password: str, use_docker: bool = False) -> None:
705
+ def start(
706
+ self,
707
+ password: str,
708
+ use_docker: bool = False,
709
+ is_aea: bool = True,
710
+ ) -> None:
688
711
  """Start the service"""
689
712
  if self.status != DeploymentStatus.BUILT:
690
713
  raise NotAllowed(
@@ -697,13 +720,15 @@ class Deployment(LocalResource):
697
720
  try:
698
721
  if use_docker:
699
722
  run_deployment(
700
- build_dir=self.path / "deployment",
723
+ build_dir=self.path / DEPLOYMENT_DIR,
701
724
  detach=True,
702
725
  project_name=self.path.name,
703
726
  )
704
727
  else:
705
728
  run_host_deployment(
706
- build_dir=self.path / "deployment", password=password
729
+ build_dir=self.path / DEPLOYMENT_DIR,
730
+ password=password,
731
+ is_aea=is_aea,
707
732
  )
708
733
  except Exception:
709
734
  self.status = DeploymentStatus.BUILT
@@ -713,7 +738,12 @@ class Deployment(LocalResource):
713
738
  self.status = DeploymentStatus.DEPLOYED
714
739
  self.store()
715
740
 
716
- def stop(self, use_docker: bool = False, force: bool = False) -> None:
741
+ def stop(
742
+ self,
743
+ use_docker: bool = False,
744
+ force: bool = False,
745
+ is_aea: bool = True,
746
+ ) -> None:
717
747
  """Stop the deployment."""
718
748
  if self.status != DeploymentStatus.DEPLOYED and not force:
719
749
  return
@@ -723,11 +753,11 @@ class Deployment(LocalResource):
723
753
 
724
754
  if use_docker:
725
755
  stop_deployment(
726
- build_dir=self.path / "deployment",
756
+ build_dir=self.path / DEPLOYMENT_DIR,
727
757
  project_name=self.path.name,
728
758
  )
729
759
  else:
730
- stop_host_deployment(build_dir=self.path / "deployment")
760
+ stop_host_deployment(build_dir=self.path / DEPLOYMENT_DIR, is_aea=is_aea)
731
761
 
732
762
  self.status = DeploymentStatus.BUILT
733
763
  self.store()
@@ -744,21 +774,20 @@ class Deployment(LocalResource):
744
774
  class Service(LocalResource):
745
775
  """Service class."""
746
776
 
777
+ name: str
747
778
  version: int
748
779
  service_config_id: str
780
+ path: Path
781
+ package_path: Path
749
782
  hash: str
750
783
  hash_history: t.Dict[int, str]
784
+ agent_release: AgentRelease
751
785
  agent_addresses: t.List[str]
752
786
  home_chain: str
753
787
  chain_configs: ChainConfigs
754
788
  description: str
755
789
  env_variables: EnvVariables
756
790
 
757
- path: Path
758
- package_path: Path
759
-
760
- name: t.Optional[str] = None
761
-
762
791
  _helper: t.Optional[ServiceHelper] = None
763
792
  _deployment: t.Optional[Deployment] = None
764
793
 
@@ -887,6 +916,7 @@ class Service(LocalResource):
887
916
  path=package_absolute_path.parent,
888
917
  package_path=Path(package_absolute_path.name),
889
918
  env_variables=service_template["env_variables"],
919
+ agent_release=service_template["agent_release"],
890
920
  )
891
921
  service.store()
892
922
  return service
@@ -1047,6 +1077,8 @@ class Service(LocalResource):
1047
1077
  )
1048
1078
  self.package_path = Path(package_absolute_path.name)
1049
1079
 
1080
+ self.agent_release = service_template.get("agent_release", self.agent_release)
1081
+
1050
1082
  # env_variables
1051
1083
  if partial_update:
1052
1084
  for var, attrs in service_template.get("env_variables", {}).items():
operate/wallet/master.py CHANGED
@@ -901,14 +901,14 @@ class MasterWalletManager:
901
901
  return [wallet.json for wallet in self]
902
902
 
903
903
  @property
904
- def password(self) -> str:
904
+ def password(self) -> t.Optional[str]:
905
905
  """Password string."""
906
906
  if self._password is None:
907
907
  raise ValueError("Password not set.")
908
908
  return self._password
909
909
 
910
910
  @password.setter
911
- def password(self, value: str) -> None:
911
+ def password(self, value: t.Optional[str]) -> None:
912
912
  """Set password value."""
913
913
  self._password = value
914
914