@@ -940,7 +940,7 @@ protected virtual void Template(TemplateContext context, string deploymentName,
940
940
ContentVersion ( context , contentVersion ) ;
941
941
942
942
// Handle custom type definitions
943
- if ( TryObjectProperty ( template , PROPERTY_DEFINITIONS , out var definitions ) )
943
+ if ( ! isNested && TryObjectProperty ( template , PROPERTY_DEFINITIONS , out var definitions ) )
944
944
Definitions ( context , definitions ) ;
945
945
946
946
// Handle compile time function variables
@@ -993,24 +993,33 @@ protected virtual void Definitions(TemplateContext context, JObject definitions)
993
993
if ( definitions == null || definitions . Count == 0 )
994
994
return ;
995
995
996
+ var graph = new CustomTypeDependencyGraph ( ) ;
996
997
foreach ( var definition in definitions )
997
- Definition ( context , definition . Key , definition . Value as JObject ) ;
998
+ {
999
+ graph . Track ( definition . Key , definition . Value as JObject ) ;
1000
+ }
1001
+
1002
+ var ordered = graph . GetOrdered ( ) ;
1003
+ foreach ( var definition in ordered )
1004
+ {
1005
+ Definition ( context , definition . Key , definition . Value ) ;
1006
+ }
998
1007
}
999
1008
1000
- protected virtual void Definition ( TemplateContext context , string definitionName , JObject definition )
1009
+ protected virtual void Definition ( TemplateContext context , string definitionId , JObject definition )
1001
1010
{
1002
- if ( TryDefinition ( definition , out var value ) )
1003
- context . AddDefinition ( $ "#/definitions/ { definitionName } " , value ) ;
1011
+ if ( TryDefinition ( context , definition , out var value ) )
1012
+ context . AddDefinition ( definitionId , value ) ;
1004
1013
}
1005
1014
1006
- private static bool TryDefinition ( JObject definition , out ITypeDefinition value )
1015
+ private static bool TryDefinition ( TemplateContext context , JObject definition , out ITypeDefinition value )
1007
1016
{
1008
1017
value = null ;
1009
- var type = GetTypePrimitive ( definition ) ;
1018
+ var type = GetTypePrimitive ( context , definition ) ;
1010
1019
if ( type == TypePrimitive . None )
1011
1020
return false ;
1012
1021
1013
- var isNullable = definition . TryBoolProperty ( PROPERTY_NULLABLE , out var nullable ) && nullable . HasValue ;
1022
+ var isNullable = GetTypeNullable ( context , definition ) ;
1014
1023
1015
1024
value = new TypeDefinition ( type , definition , isNullable ) ;
1016
1025
return true ;
@@ -1121,7 +1130,7 @@ private static bool TryParameterType(ITemplateContext context, JObject parameter
1121
1130
value = new ParameterType ( definition . Type , type ) ;
1122
1131
1123
1132
// Try type
1124
- if ( parameter . TryGetProperty ( PROPERTY_TYPE , out type ) &&
1133
+ else if ( parameter . TryGetProperty ( PROPERTY_TYPE , out type ) &&
1125
1134
ParameterType . TrySimpleType ( type , out var v ) )
1126
1135
value = v ;
1127
1136
@@ -1396,7 +1405,7 @@ protected static bool IsDeploymentResource(string resourceType)
1396
1405
return string . Equals ( resourceType , RESOURCETYPE_DEPLOYMENT , StringComparison . OrdinalIgnoreCase ) ;
1397
1406
}
1398
1407
1399
- private static TemplateContext GetDeploymentContext ( TemplateContext context , string deploymentName , JObject resource , JObject properties )
1408
+ private TemplateContext GetDeploymentContext ( TemplateContext context , string deploymentName , JObject resource , JObject properties )
1400
1409
{
1401
1410
if ( ! TryObjectProperty ( properties , PROPERTY_EXPRESSIONEVALUATIONOPTIONS , out var options ) ||
1402
1411
! TryStringProperty ( options , PROPERTY_SCOPE , out var scope ) ||
@@ -1420,12 +1429,17 @@ private static TemplateContext GetDeploymentContext(TemplateContext context, str
1420
1429
TryObjectProperty ( template , PROPERTY_PARAMETERS , out var templateParameters ) ;
1421
1430
1422
1431
var deploymentContext = new TemplateContext ( context . Pipeline , subscription , resourceGroup , tenant , managementGroup , parameterDefaults ) ;
1432
+
1433
+ // Handle custom type definitions early to allow type mapping of parameters if required.
1434
+ if ( TryObjectProperty ( template , PROPERTY_DEFINITIONS , out var definitions ) )
1435
+ Definitions ( deploymentContext , definitions ) ;
1436
+
1423
1437
if ( TryObjectProperty ( properties , PROPERTY_PARAMETERS , out var innerParameters ) )
1424
1438
{
1425
1439
foreach ( var parameter in innerParameters . Properties ( ) )
1426
1440
{
1427
1441
var parameterType = templateParameters . TryGetProperty < JObject > ( parameter . Name , out var templateParameter ) &&
1428
- TryParameterType ( context , templateParameter , out var t ) ? t . Value . Type : TypePrimitive . None ;
1442
+ TryParameterType ( deploymentContext , templateParameter , out var t ) ? t . Value . Type : TypePrimitive . None ;
1429
1443
1430
1444
if ( parameter . Value is JValue parameterValueExpression )
1431
1445
parameter . Value = ResolveToken ( context , ResolveVariable ( context , parameterType , parameterValueExpression ) ) ;
@@ -1569,18 +1583,40 @@ protected void Outputs(TemplateContext context, JObject outputs)
1569
1583
1570
1584
protected virtual void Output ( TemplateContext context , string name , JObject output )
1571
1585
{
1572
- ResolveProperty ( context , output , PROPERTY_VALUE , GetTypePrimitive ( output ) ) ;
1586
+ ResolveProperty ( context , output , PROPERTY_VALUE , GetTypePrimitive ( context , output ) ) ;
1573
1587
context . CheckOutput ( name , output ) ;
1574
1588
context . AddOutput ( name , output ) ;
1575
1589
}
1576
1590
1577
1591
#endregion Outputs
1578
1592
1579
- private static TypePrimitive GetTypePrimitive ( JObject value )
1593
+ private static TypePrimitive GetTypePrimitive ( TemplateContext context , JObject value )
1594
+ {
1595
+ if ( value == null ) return TypePrimitive . None ;
1596
+
1597
+ // Find primitive.
1598
+ if ( value . TryGetProperty ( PROPERTY_TYPE , out var t ) && Enum . TryParse ( t , ignoreCase : true , result : out TypePrimitive type ) )
1599
+ return type ;
1600
+
1601
+ // Find primitive from parent type.
1602
+ if ( context != null && value . TryGetProperty ( PROPERTY_REF , out var id ) && context . TryDefinition ( id , out var definition ) )
1603
+ return GetTypePrimitive ( context , definition . Definition ) ;
1604
+
1605
+ return TypePrimitive . None ;
1606
+ }
1607
+
1608
+ private static bool GetTypeNullable ( TemplateContext context , JObject value )
1580
1609
{
1581
- return value == null ||
1582
- ! value . TryGetProperty ( PROPERTY_TYPE , out var t ) ||
1583
- ! Enum . TryParse ( t , ignoreCase : true , result : out TypePrimitive type ) ? TypePrimitive . None : type ;
1610
+ if ( value == null ) return false ;
1611
+
1612
+ // Find nullable from parent type.
1613
+ if ( value . TryBoolProperty ( PROPERTY_NULLABLE , out var nullable ) && nullable . Value )
1614
+ return nullable . Value ;
1615
+
1616
+ if ( context != null && value . TryGetProperty ( PROPERTY_REF , out var id ) && context . TryDefinition ( id , out var definition ) )
1617
+ return definition . Nullable ;
1618
+
1619
+ return false ;
1584
1620
}
1585
1621
1586
1622
protected static StringExpression < T > Expression < T > ( ITemplateContext context , string s )
0 commit comments