@@ -64,12 +64,65 @@ class AppBuilderException(Exception):
6464 """
6565 pass
6666
67+ def _validate_system_requirements (system_requirements ):
68+ """
69+ Validates systemRequirements section of dxapp.json for instanceTypeSelector constraints.
70+
71+ :param system_requirements: The systemRequirements section from runSpec
72+ :type system_requirements: dict
73+ :raises AppBuilderException: If validation fails
74+ """
75+ if not isinstance (system_requirements , dict ):
76+ return
77+
78+ for entry_point , requirements in system_requirements .items ():
79+ if not isinstance (requirements , dict ):
80+ continue
81+
82+ has_instance_type = 'instanceType' in requirements
83+ has_instance_type_selector = 'instanceTypeSelector' in requirements
84+ has_cluster_spec = 'clusterSpec' in requirements
85+
86+ # Check mutual exclusivity: instanceType and instanceTypeSelector
87+ if has_instance_type and has_instance_type_selector :
88+ raise AppBuilderException (
89+ "instanceType and instanceTypeSelector keywords are mutually exclusive "
90+ "in systemRequirements for entry point '{}'" .format (entry_point )
91+ )
92+
93+ # Check mutual exclusivity: instanceTypeSelector and clusterSpec
94+ if has_instance_type_selector and has_cluster_spec :
95+ raise AppBuilderException (
96+ "instanceTypeSelector and clusterSpec keywords are mutually exclusive "
97+ "in systemRequirements for entry point '{}'" .format (entry_point )
98+ )
99+
67100def _validate_applet_spec (applet_spec ):
68101 if 'runSpec' not in applet_spec :
69102 raise AppBuilderException ("Required field 'runSpec' not found in dxapp.json" )
70103
104+ # Validate systemRequirements for instanceTypeSelector constraints in runSpec
105+ if 'systemRequirements' in applet_spec .get ('runSpec' , {}):
106+ _validate_system_requirements (applet_spec ['runSpec' ]['systemRequirements' ])
107+
108+ # Validate systemRequirements in regionalOptions for each region
109+ regional_options = applet_spec .get ('regionalOptions' , {})
110+ if isinstance (regional_options , dict ):
111+ for region , options in regional_options .items ():
112+ if isinstance (options , dict ) and 'systemRequirements' in options :
113+ _validate_system_requirements (options ['systemRequirements' ])
114+
71115def _validate_app_spec (app_spec ):
72- pass
116+ # Validate systemRequirements for instanceTypeSelector constraints in runSpec
117+ if 'runSpec' in app_spec and 'systemRequirements' in app_spec ['runSpec' ]:
118+ _validate_system_requirements (app_spec ['runSpec' ]['systemRequirements' ])
119+
120+ # Validate systemRequirements in regionalOptions for each region
121+ regional_options = app_spec .get ('regionalOptions' , {})
122+ if isinstance (regional_options , dict ):
123+ for region , options in regional_options .items ():
124+ if isinstance (options , dict ) and 'systemRequirements' in options :
125+ _validate_system_requirements (options ['systemRequirements' ])
73126
74127def _get_applet_spec (src_dir ):
75128 applet_spec_file = os .path .join (src_dir , "dxapp.json" )
0 commit comments