2727from aleph .sdk .query .responses import PriceResponse
2828from aleph .sdk .types import StorageEnum
2929from aleph .sdk .utils import calculate_firmware_hash
30- from aleph_message .models import InstanceMessage , StoreMessage
31- from aleph_message .models .base import Chain , MessageType
32- from aleph_message .models .execution .base import Payment , PaymentType
33- from aleph_message .models .execution .environment import (
34- GpuDeviceClass ,
35- GpuProperties ,
36- HostRequirements ,
37- HypervisorType ,
38- NodeRequirements ,
39- TrustedExecutionEnvironment ,
40- )
41- from aleph_message .models .item_hash import ItemHash
42- from click import echo
43- from rich import box
44- from rich .console import Console
45- from rich .prompt import Confirm , Prompt
46- from rich .table import Table
47- from rich .text import Text
48-
4930from aleph_client .commands import help_strings
5031from aleph_client .commands .instance .display import CRNTable
5132from aleph_client .commands .instance .network import (
6950)
7051from aleph_client .models import CRNInfo
7152from aleph_client .utils import AsyncTyper , sanitize_url
53+ from aleph_message .models import InstanceMessage , StoreMessage
54+ from aleph_message .models .base import Chain , MessageType
55+ from aleph_message .models .execution .base import Payment , PaymentType
56+ from aleph_message .models .execution .environment import (
57+ GpuDeviceClass ,
58+ GpuProperties ,
59+ HostRequirements ,
60+ HypervisorType ,
61+ NodeRequirements ,
62+ TrustedExecutionEnvironment ,
63+ )
64+ from aleph_message .models .item_hash import ItemHash
65+ from click import echo
66+ from rich import box
67+ from rich .console import Console
68+ from rich .prompt import Confirm , Prompt
69+ from rich .table import Table
70+ from rich .text import Text
7271
7372logger = logging .getLogger (__name__ )
7473app = AsyncTyper (no_args_is_help = True )
@@ -117,6 +116,7 @@ async def create(
117116 None ,
118117 help = help_strings .IMMUTABLE_VOLUME ,
119118 ),
119+ crn_auto_tac : bool = typer .Option (False , help = help_strings .CRN_AUTO_TAC ),
120120 channel : Optional [str ] = typer .Option (default = settings .DEFAULT_CHANNEL , help = help_strings .CHANNEL ),
121121 private_key : Optional [str ] = typer .Option (settings .PRIVATE_KEY_STRING , help = help_strings .PRIVATE_KEY ),
122122 private_key_file : Optional [Path ] = typer .Option (settings .PRIVATE_KEY_FILE , help = help_strings .PRIVATE_KEY_FILE ),
@@ -342,6 +342,7 @@ async def create(
342342 crn_info .get ("computing" , {}).get ("ENABLE_CONFIDENTIAL_COMPUTING" , False )
343343 ),
344344 gpu_support = bool (crn_info .get ("computing" , {}).get ("ENABLE_GPU_SUPPORT" , False )),
345+ terms_and_conditions = crn_info .get ("terms_and_conditions" ),
345346 )
346347 echo ("\n * Selected CRN *" )
347348 crn .display_crn_specs ()
@@ -409,6 +410,15 @@ async def create(
409410 device_id = selected_gpu .device_id ,
410411 )
411412 ]
413+ if crn .terms_and_conditions :
414+ accepted = await crn .display_terms_and_conditions (auto_accept = crn_auto_tac )
415+ if accepted is None :
416+ echo ("Failed to fetch terms and conditions.\n Contact support or use a different CRN." )
417+ raise typer .Exit (1 )
418+ elif not accepted :
419+ echo ("Terms & Conditions rejected: instance creation aborted." )
420+ raise typer .Exit (1 )
421+ echo ("Terms & Conditions accepted." )
412422
413423 async with AuthenticatedAlephHttpClient (account = account , api_server = settings .API_HOST ) as client :
414424 payment = Payment (
@@ -433,7 +443,12 @@ async def create(
433443 payment = payment ,
434444 requirements = (
435445 HostRequirements (
436- node = NodeRequirements (node_hash = crn .hash ),
446+ node = NodeRequirements (
447+ node_hash = crn .hash ,
448+ terms_and_conditions = (
449+ ItemHash (crn .terms_and_conditions ) if crn .terms_and_conditions else None
450+ ),
451+ ),
437452 gpu = gpu_requirement ,
438453 )
439454 if crn
@@ -685,7 +700,7 @@ async def _show_instances(messages: List[InstanceMessage], node_list: NodeInfo):
685700 chain_label , chain_color = "BASE" , "blue3"
686701 elif chain_label == "SOL" :
687702 chain_label , chain_color = "SOL " , "medium_spring_green"
688- else : # ETH
703+ elif len ( chain_label ) == 3 : # ETH
689704 chain_label += " "
690705 chain = Text .assemble ("Chain: " , Text (chain_label , style = chain_color ))
691706 created_at_parsed = str (str_to_datetime (str (info ["created_at" ]))).split ("." )[0 ]
@@ -730,6 +745,19 @@ async def _show_instances(messages: List[InstanceMessage], node_list: NodeInfo):
730745 Text (str (info ["ipv6_logs" ])),
731746 style = "bright_yellow" if len (str (info ["ipv6_logs" ]).split (":" )) == 8 else "dark_orange" ,
732747 ),
748+ (
749+ Text .assemble (
750+ Text (
751+ f"\n [{ '✅' if info ['terms_and_conditions' ]['accepted' ] else '❌' } ] Accepted Terms & Conditions:\n "
752+ ),
753+ Text (
754+ f"{ info ['terms_and_conditions' ]['url' ]} " ,
755+ style = "orange1" ,
756+ ),
757+ )
758+ if info ["terms_and_conditions" ]["hash" ]
759+ else ""
760+ ),
733761 )
734762 table .add_row (instance , specifications , status_column )
735763 table .add_section ()
@@ -1192,6 +1220,7 @@ async def confidential_create(
11921220 None ,
11931221 help = help_strings .IMMUTABLE_VOLUME ,
11941222 ),
1223+ crn_auto_tac : bool = typer .Option (False , help = help_strings .CRN_AUTO_TAC ),
11951224 channel : Optional [str ] = typer .Option (default = settings .DEFAULT_CHANNEL , help = help_strings .CHANNEL ),
11961225 private_key : Optional [str ] = typer .Option (settings .PRIVATE_KEY_STRING , help = help_strings .PRIVATE_KEY ),
11971226 private_key_file : Optional [Path ] = typer .Option (settings .PRIVATE_KEY_FILE , help = help_strings .PRIVATE_KEY_FILE ),
@@ -1223,6 +1252,7 @@ async def confidential_create(
12231252 ssh_pubkey_file = ssh_pubkey_file ,
12241253 crn_hash = crn_hash ,
12251254 crn_url = crn_url ,
1255+ crn_auto_tac = crn_auto_tac ,
12261256 confidential = True ,
12271257 confidential_firmware = confidential_firmware ,
12281258 skip_volume = skip_volume ,
0 commit comments