@ -13,6 +13,7 @@ import (
 
			
		
	
		
		
			
				
					
						"github.com/hashicorp/hcl/v2/gohcl" 
	"github.com/hashicorp/hcl/v2/gohcl" 
 
			
		
	
		
		
			
				
					
						"github.com/pkg/errors" 
	"github.com/pkg/errors" 
 
			
		
	
		
		
			
				
					
						"github.com/zclconf/go-cty/cty" 
	"github.com/zclconf/go-cty/cty" 
 
			
		
	
		
		
			
				
					
						"github.com/zclconf/go-cty/cty/gocty" 
 
			
		
	
		
		
			
				
					
					) )  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					type  Opt  struct  { type  Opt  struct  {  
			
		
	
	
		
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
					@ -48,11 +49,17 @@ type parser struct {
 
			
		
	
		
		
			
				
					
						attrs  map [ string ] * hcl . Attribute 
	attrs  map [ string ] * hcl . Attribute 
 
			
		
	
		
		
			
				
					
						funcs  map [ string ] * functionDef 
	funcs  map [ string ] * functionDef 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
						blocks       map [ string ] map [ string ] [ ] * hcl . Block 
 
			
		
	
		
		
			
				
					
						blockValues  map [ * hcl . Block ] reflect . Value 
 
			
		
	
		
		
			
				
					
						blockTypes   map [ string ] reflect . Type 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
						ectx  * hcl . EvalContext 
	ectx  * hcl . EvalContext 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
						progress   map [ string ] struct { } 
	progress   map [ string ] struct { } 
 
			
		
	
		
		
			
				
					
						progressF  map [ string ] struct { } 
	progressF  map [ string ] struct { } 
 
			
		
	
		
		
			
				
					
						progressB  map [ * hcl . Block ] map [ string ] struct { } 
 
			
		
	
		
		
			
				
					
						doneF      map [ string ] struct { } 
	doneF      map [ string ] struct { } 
 
			
		
	
		
		
			
				
					
						doneB      map [ * hcl . Block ] map [ string ] struct { } 
 
			
		
	
		
		
			
				
					
					} }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					func  ( p  * parser )  loadDeps ( exp  hcl . Expression ,  exclude  map [ string ] struct { } )  hcl . Diagnostics  { func  ( p  * parser )  loadDeps ( exp  hcl . Expression ,  exclude  map [ string ] struct { } )  hcl . Diagnostics  {  
			
		
	
	
		
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
					@ -79,6 +86,59 @@ func (p *parser) loadDeps(exp hcl.Expression, exclude map[string]struct{}) hcl.D
 
			
		
	
		
		
			
				
					
							if  _ ,  ok  :=  exclude [ v . RootName ( ) ] ;  ok  { 
		if  _ ,  ok  :=  exclude [ v . RootName ( ) ] ;  ok  { 
 
			
		
	
		
		
			
				
					
								continue 
			continue 
 
			
		
	
		
		
			
				
					
							} 
		} 
 
			
		
	
		
		
			
				
					
							if  _ ,  ok  :=  p . blockTypes [ v . RootName ( ) ] ;  ok  { 
 
			
		
	
		
		
			
				
					
								blockType  :=  v . RootName ( ) 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
								split  :=  v . SimpleSplit ( ) . Rel 
 
			
		
	
		
		
			
				
					
								if  len ( split )  ==  0  { 
 
			
		
	
		
		
			
				
					
									return  hcl . Diagnostics { 
 
			
		
	
		
		
			
				
					
										& hcl . Diagnostic { 
 
			
		
	
		
		
			
				
					
											Severity :  hcl . DiagError , 
 
			
		
	
		
		
			
				
					
											Summary :   "Invalid expression" , 
 
			
		
	
		
		
			
				
					
											Detail :    fmt . Sprintf ( "cannot access %s as a variable" ,  blockType ) , 
 
			
		
	
		
		
			
				
					
											Subject :   exp . Range ( ) . Ptr ( ) , 
 
			
		
	
		
		
			
				
					
											Context :   exp . Range ( ) . Ptr ( ) , 
 
			
		
	
		
		
			
				
					
										} , 
 
			
		
	
		
		
			
				
					
									} 
 
			
		
	
		
		
			
				
					
								} 
 
			
		
	
		
		
			
				
					
								blockName ,  ok  :=  split [ 0 ] . ( hcl . TraverseAttr ) 
 
			
		
	
		
		
			
				
					
								if  ! ok  { 
 
			
		
	
		
		
			
				
					
									return  hcl . Diagnostics { 
 
			
		
	
		
		
			
				
					
										& hcl . Diagnostic { 
 
			
		
	
		
		
			
				
					
											Severity :  hcl . DiagError , 
 
			
		
	
		
		
			
				
					
											Summary :   "Invalid expression" , 
 
			
		
	
		
		
			
				
					
											Detail :    fmt . Sprintf ( "cannot traverse %s without attribute" ,  blockType ) , 
 
			
		
	
		
		
			
				
					
											Subject :   exp . Range ( ) . Ptr ( ) , 
 
			
		
	
		
		
			
				
					
											Context :   exp . Range ( ) . Ptr ( ) , 
 
			
		
	
		
		
			
				
					
										} , 
 
			
		
	
		
		
			
				
					
									} 
 
			
		
	
		
		
			
				
					
								} 
 
			
		
	
		
		
			
				
					
								blocks  :=  p . blocks [ blockType ] [ blockName . Name ] 
 
			
		
	
		
		
			
				
					
								if  len ( blocks )  ==  0  { 
 
			
		
	
		
		
			
				
					
									continue 
 
			
		
	
		
		
			
				
					
								} 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
								var  target  * hcl . BodySchema 
 
			
		
	
		
		
			
				
					
								if  len ( split )  >  1  { 
 
			
		
	
		
		
			
				
					
									if  attr ,  ok  :=  split [ 1 ] . ( hcl . TraverseAttr ) ;  ok  { 
 
			
		
	
		
		
			
				
					
										target  =  & hcl . BodySchema { 
 
			
		
	
		
		
			
				
					
											Attributes :  [ ] hcl . AttributeSchema { { Name :  attr . Name } } , 
 
			
		
	
		
		
			
				
					
											Blocks :      [ ] hcl . BlockHeaderSchema { { Type :  attr . Name } } , 
 
			
		
	
		
		
			
				
					
										} 
 
			
		
	
		
		
			
				
					
									} 
 
			
		
	
		
		
			
				
					
								} 
 
			
		
	
		
		
			
				
					
								if  err  :=  p . resolveBlock ( blocks [ 0 ] ,  target ) ;  err  !=  nil  { 
 
			
		
	
		
		
			
				
					
									return  hcl . Diagnostics { 
 
			
		
	
		
		
			
				
					
										& hcl . Diagnostic { 
 
			
		
	
		
		
			
				
					
											Severity :  hcl . DiagError , 
 
			
		
	
		
		
			
				
					
											Summary :   "Invalid expression" , 
 
			
		
	
		
		
			
				
					
											Detail :    err . Error ( ) , 
 
			
		
	
		
		
			
				
					
											Subject :   v . SourceRange ( ) . Ptr ( ) , 
 
			
		
	
		
		
			
				
					
											Context :   v . SourceRange ( ) . Ptr ( ) , 
 
			
		
	
		
		
			
				
					
										} , 
 
			
		
	
		
		
			
				
					
									} 
 
			
		
	
		
		
			
				
					
								} 
 
			
		
	
		
		
			
				
					
							}  else  { 
 
			
		
	
		
		
			
				
					
								if  err  :=  p . resolveValue ( v . RootName ( ) ) ;  err  !=  nil  { 
			if  err  :=  p . resolveValue ( v . RootName ( ) ) ;  err  !=  nil  { 
 
			
		
	
		
		
			
				
					
									return  hcl . Diagnostics { 
				return  hcl . Diagnostics { 
 
			
		
	
		
		
			
				
					
										& hcl . Diagnostic { 
					& hcl . Diagnostic { 
 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -91,10 +151,13 @@ func (p *parser) loadDeps(exp hcl.Expression, exclude map[string]struct{}) hcl.D
 
			
		
	
		
		
			
				
					
									} 
				} 
 
			
		
	
		
		
			
				
					
								} 
			} 
 
			
		
	
		
		
			
				
					
							} 
		} 
 
			
		
	
		
		
			
				
					
						} 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
						return  nil 
	return  nil 
 
			
		
	
		
		
			
				
					
					} }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					// resolveFunction forces evaluation of a function, storing the result into the
  
			
		
	
		
		
			
				
					
					// parser.
  
			
		
	
		
		
			
				
					
					func  ( p  * parser )  resolveFunction ( name  string )  error  { func  ( p  * parser )  resolveFunction ( name  string )  error  {  
			
		
	
		
		
			
				
					
						if  _ ,  ok  :=  p . doneF [ name ] ;  ok  { 
	if  _ ,  ok  :=  p . doneF [ name ] ;  ok  { 
 
			
		
	
		
		
			
				
					
							return  nil 
		return  nil 
 
			
		
	
	
		
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
					@ -170,6 +233,8 @@ func (p *parser) resolveFunction(name string) error {
 
			
		
	
		
		
			
				
					
						return  nil 
	return  nil 
 
			
		
	
		
		
			
				
					
					} }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					// resolveValue forces evaluation of a named value, storing the result into the
  
			
		
	
		
		
			
				
					
					// parser.
  
			
		
	
		
		
			
				
					
					func  ( p  * parser )  resolveValue ( name  string )  ( err  error )  { func  ( p  * parser )  resolveValue ( name  string )  ( err  error )  {  
			
		
	
		
		
			
				
					
						if  _ ,  ok  :=  p . ectx . Variables [ name ] ;  ok  { 
	if  _ ,  ok  :=  p . ectx . Variables [ name ] ;  ok  { 
 
			
		
	
		
		
			
				
					
							return  nil 
		return  nil 
 
			
		
	
	
		
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
					@ -248,6 +313,157 @@ func (p *parser) resolveValue(name string) (err error) {
 
			
		
	
		
		
			
				
					
						return  nil 
	return  nil 
 
			
		
	
		
		
			
				
					
					} }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					// resolveBlock force evaluates a block, storing the result in the parser. If a
  
			
		
	
		
		
			
				
					
					// target schema is provided, only the attributes and blocks present in the
  
			
		
	
		
		
			
				
					
					// schema will be evaluated.
  
			
		
	
		
		
			
				
					
					func  ( p  * parser )  resolveBlock ( block  * hcl . Block ,  target  * hcl . BodySchema )  ( err  error )  {  
			
		
	
		
		
			
				
					
						name  :=  block . Labels [ 0 ] 
 
			
		
	
		
		
			
				
					
						if  err  :=  p . opt . ValidateLabel ( name ) ;  err  !=  nil  { 
 
			
		
	
		
		
			
				
					
							return  hcl . Diagnostics { 
 
			
		
	
		
		
			
				
					
								& hcl . Diagnostic { 
 
			
		
	
		
		
			
				
					
									Severity :  hcl . DiagError , 
 
			
		
	
		
		
			
				
					
									Summary :   "Invalid name" , 
 
			
		
	
		
		
			
				
					
									Detail :    err . Error ( ) , 
 
			
		
	
		
		
			
				
					
									Subject :   & block . LabelRanges [ 0 ] , 
 
			
		
	
		
		
			
				
					
								} , 
 
			
		
	
		
		
			
				
					
							} 
 
			
		
	
		
		
			
				
					
						} 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
						if  _ ,  ok  :=  p . doneB [ block ] ;  ! ok  { 
 
			
		
	
		
		
			
				
					
							p . doneB [ block ]  =  map [ string ] struct { } { } 
 
			
		
	
		
		
			
				
					
						} 
 
			
		
	
		
		
			
				
					
						if  _ ,  ok  :=  p . progressB [ block ] ;  ! ok  { 
 
			
		
	
		
		
			
				
					
							p . progressB [ block ]  =  map [ string ] struct { } { } 
 
			
		
	
		
		
			
				
					
						} 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
						if  target  !=  nil  { 
 
			
		
	
		
		
			
				
					
							// filter out attributes and blocks that are already evaluated
 
 
			
		
	
		
		
			
				
					
							original  :=  target 
 
			
		
	
		
		
			
				
					
							target  =  & hcl . BodySchema { } 
 
			
		
	
		
		
			
				
					
							for  _ ,  a  :=  range  original . Attributes  { 
 
			
		
	
		
		
			
				
					
								if  _ ,  ok  :=  p . doneB [ block ] [ a . Name ] ;  ! ok  { 
 
			
		
	
		
		
			
				
					
									target . Attributes  =  append ( target . Attributes ,  a ) 
 
			
		
	
		
		
			
				
					
								} 
 
			
		
	
		
		
			
				
					
							} 
 
			
		
	
		
		
			
				
					
							for  _ ,  b  :=  range  original . Blocks  { 
 
			
		
	
		
		
			
				
					
								if  _ ,  ok  :=  p . doneB [ block ] [ b . Type ] ;  ! ok  { 
 
			
		
	
		
		
			
				
					
									target . Blocks  =  append ( target . Blocks ,  b ) 
 
			
		
	
		
		
			
				
					
								} 
 
			
		
	
		
		
			
				
					
							} 
 
			
		
	
		
		
			
				
					
							if  len ( target . Attributes )  ==  0  &&  len ( target . Blocks )  ==  0  { 
 
			
		
	
		
		
			
				
					
								return  nil 
 
			
		
	
		
		
			
				
					
							} 
 
			
		
	
		
		
			
				
					
						} 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
						if  target  !=  nil  { 
 
			
		
	
		
		
			
				
					
							// detect reference cycles
 
 
			
		
	
		
		
			
				
					
							for  _ ,  a  :=  range  target . Attributes  { 
 
			
		
	
		
		
			
				
					
								if  _ ,  ok  :=  p . progressB [ block ] [ a . Name ] ;  ok  { 
 
			
		
	
		
		
			
				
					
									return  errors . Errorf ( "reference cycle not allowed for %s.%s.%s" ,  block . Type ,  name ,  a . Name ) 
 
			
		
	
		
		
			
				
					
								} 
 
			
		
	
		
		
			
				
					
							} 
 
			
		
	
		
		
			
				
					
							for  _ ,  b  :=  range  target . Blocks  { 
 
			
		
	
		
		
			
				
					
								if  _ ,  ok  :=  p . progressB [ block ] [ b . Type ] ;  ok  { 
 
			
		
	
		
		
			
				
					
									return  errors . Errorf ( "reference cycle not allowed for %s.%s.%s" ,  block . Type ,  name ,  b . Type ) 
 
			
		
	
		
		
			
				
					
								} 
 
			
		
	
		
		
			
				
					
							} 
 
			
		
	
		
		
			
				
					
							for  _ ,  a  :=  range  target . Attributes  { 
 
			
		
	
		
		
			
				
					
								p . progressB [ block ] [ a . Name ]  =  struct { } { } 
 
			
		
	
		
		
			
				
					
							} 
 
			
		
	
		
		
			
				
					
							for  _ ,  b  :=  range  target . Blocks  { 
 
			
		
	
		
		
			
				
					
								p . progressB [ block ] [ b . Type ]  =  struct { } { } 
 
			
		
	
		
		
			
				
					
							} 
 
			
		
	
		
		
			
				
					
						} 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
						// create a filtered body that contains only the target properties
 
 
			
		
	
		
		
			
				
					
						body  :=  func ( )  hcl . Body  { 
 
			
		
	
		
		
			
				
					
							if  target  !=  nil  { 
 
			
		
	
		
		
			
				
					
								return  FilterIncludeBody ( block . Body ,  target ) 
 
			
		
	
		
		
			
				
					
							} 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
							filter  :=  & hcl . BodySchema { } 
 
			
		
	
		
		
			
				
					
							for  k  :=  range  p . doneB [ block ]  { 
 
			
		
	
		
		
			
				
					
								filter . Attributes  =  append ( filter . Attributes ,  hcl . AttributeSchema { Name :  k } ) 
 
			
		
	
		
		
			
				
					
								filter . Blocks  =  append ( filter . Blocks ,  hcl . BlockHeaderSchema { Type :  k } ) 
 
			
		
	
		
		
			
				
					
							} 
 
			
		
	
		
		
			
				
					
							return  FilterExcludeBody ( block . Body ,  filter ) 
 
			
		
	
		
		
			
				
					
						} 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
						// load dependencies from all targeted properties
 
 
			
		
	
		
		
			
				
					
						t ,  ok  :=  p . blockTypes [ block . Type ] 
 
			
		
	
		
		
			
				
					
						if  ! ok  { 
 
			
		
	
		
		
			
				
					
							return  nil 
 
			
		
	
		
		
			
				
					
						} 
 
			
		
	
		
		
			
				
					
						schema ,  _  :=  gohcl . ImpliedBodySchema ( reflect . New ( t ) . Interface ( ) ) 
 
			
		
	
		
		
			
				
					
						content ,  _ ,  diag  :=  body ( ) . PartialContent ( schema ) 
 
			
		
	
		
		
			
				
					
						if  diag . HasErrors ( )  { 
 
			
		
	
		
		
			
				
					
							return  diag 
 
			
		
	
		
		
			
				
					
						} 
 
			
		
	
		
		
			
				
					
						for  _ ,  a  :=  range  content . Attributes  { 
 
			
		
	
		
		
			
				
					
							diag  :=  p . loadDeps ( a . Expr ,  nil ) 
 
			
		
	
		
		
			
				
					
							if  diag . HasErrors ( )  { 
 
			
		
	
		
		
			
				
					
								return  diag 
 
			
		
	
		
		
			
				
					
							} 
 
			
		
	
		
		
			
				
					
						} 
 
			
		
	
		
		
			
				
					
						for  _ ,  b  :=  range  content . Blocks  { 
 
			
		
	
		
		
			
				
					
							err  :=  p . resolveBlock ( b ,  nil ) 
 
			
		
	
		
		
			
				
					
							if  err  !=  nil  { 
 
			
		
	
		
		
			
				
					
								return  err 
 
			
		
	
		
		
			
				
					
							} 
 
			
		
	
		
		
			
				
					
						} 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
						// decode!
 
 
			
		
	
		
		
			
				
					
						var  output  reflect . Value 
 
			
		
	
		
		
			
				
					
						if  prev ,  ok  :=  p . blockValues [ block ] ;  ok  { 
 
			
		
	
		
		
			
				
					
							output  =  prev 
 
			
		
	
		
		
			
				
					
						}  else  { 
 
			
		
	
		
		
			
				
					
							output  =  reflect . New ( t ) 
 
			
		
	
		
		
			
				
					
							setLabel ( output ,  block . Labels [ 0 ] )  // early attach labels, so we can reference them
 
 
			
		
	
		
		
			
				
					
						} 
 
			
		
	
		
		
			
				
					
						diag  =  gohcl . DecodeBody ( body ( ) ,  p . ectx ,  output . Interface ( ) ) 
 
			
		
	
		
		
			
				
					
						if  diag . HasErrors ( )  { 
 
			
		
	
		
		
			
				
					
							return  diag 
 
			
		
	
		
		
			
				
					
						} 
 
			
		
	
		
		
			
				
					
						p . blockValues [ block ]  =  output 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
						// mark all targeted properties as done
 
 
			
		
	
		
		
			
				
					
						for  _ ,  a  :=  range  content . Attributes  { 
 
			
		
	
		
		
			
				
					
							p . doneB [ block ] [ a . Name ]  =  struct { } { } 
 
			
		
	
		
		
			
				
					
						} 
 
			
		
	
		
		
			
				
					
						for  _ ,  b  :=  range  content . Blocks  { 
 
			
		
	
		
		
			
				
					
							p . doneB [ block ] [ b . Type ]  =  struct { } { } 
 
			
		
	
		
		
			
				
					
						} 
 
			
		
	
		
		
			
				
					
						if  target  !=  nil  { 
 
			
		
	
		
		
			
				
					
							for  _ ,  a  :=  range  target . Attributes  { 
 
			
		
	
		
		
			
				
					
								p . doneB [ block ] [ a . Name ]  =  struct { } { } 
 
			
		
	
		
		
			
				
					
							} 
 
			
		
	
		
		
			
				
					
							for  _ ,  b  :=  range  target . Blocks  { 
 
			
		
	
		
		
			
				
					
								p . doneB [ block ] [ b . Type ]  =  struct { } { } 
 
			
		
	
		
		
			
				
					
							} 
 
			
		
	
		
		
			
				
					
						} 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
						// store the result into the evaluation context (so if can be referenced)
 
 
			
		
	
		
		
			
				
					
						outputType ,  err  :=  gocty . ImpliedType ( output . Interface ( ) ) 
 
			
		
	
		
		
			
				
					
						if  err  !=  nil  { 
 
			
		
	
		
		
			
				
					
							return  err 
 
			
		
	
		
		
			
				
					
						} 
 
			
		
	
		
		
			
				
					
						outputValue ,  err  :=  gocty . ToCtyValue ( output . Interface ( ) ,  outputType ) 
 
			
		
	
		
		
			
				
					
						if  err  !=  nil  { 
 
			
		
	
		
		
			
				
					
							return  err 
 
			
		
	
		
		
			
				
					
						} 
 
			
		
	
		
		
			
				
					
						var  m  map [ string ] cty . Value 
 
			
		
	
		
		
			
				
					
						if  m2 ,  ok  :=  p . ectx . Variables [ block . Type ] ;  ok  { 
 
			
		
	
		
		
			
				
					
							m  =  m2 . AsValueMap ( ) 
 
			
		
	
		
		
			
				
					
						} 
 
			
		
	
		
		
			
				
					
						if  m  ==  nil  { 
 
			
		
	
		
		
			
				
					
							m  =  map [ string ] cty . Value { } 
 
			
		
	
		
		
			
				
					
						} 
 
			
		
	
		
		
			
				
					
						m [ name ]  =  outputValue 
 
			
		
	
		
		
			
				
					
						p . ectx . Variables [ block . Type ]  =  cty . MapVal ( m ) 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
						return  nil 
 
			
		
	
		
		
			
				
					
					}  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					func  Parse ( b  hcl . Body ,  opt  Opt ,  val  interface { } )  hcl . Diagnostics  { func  Parse ( b  hcl . Body ,  opt  Opt ,  val  interface { } )  hcl . Diagnostics  {  
			
		
	
		
		
			
				
					
						reserved  :=  map [ string ] struct { } { } 
	reserved  :=  map [ string ] struct { } { } 
 
			
		
	
		
		
			
				
					
						schema ,  _  :=  gohcl . ImpliedBodySchema ( val ) 
	schema ,  _  :=  gohcl . ImpliedBodySchema ( val ) 
 
			
		
	
	
		
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
					@ -284,9 +500,16 @@ func Parse(b hcl.Body, opt Opt, val interface{}) hcl.Diagnostics {
 
			
		
	
		
		
			
				
					
							attrs :  map [ string ] * hcl . Attribute { } , 
		attrs :  map [ string ] * hcl . Attribute { } , 
 
			
		
	
		
		
			
				
					
							funcs :  map [ string ] * functionDef { } , 
		funcs :  map [ string ] * functionDef { } , 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
							blocks :       map [ string ] map [ string ] [ ] * hcl . Block { } , 
 
			
		
	
		
		
			
				
					
							blockValues :  map [ * hcl . Block ] reflect . Value { } , 
 
			
		
	
		
		
			
				
					
							blockTypes :   map [ string ] reflect . Type { } , 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
							progress :   map [ string ] struct { } { } , 
		progress :   map [ string ] struct { } { } , 
 
			
		
	
		
		
			
				
					
							progressF :  map [ string ] struct { } { } , 
		progressF :  map [ string ] struct { } { } , 
 
			
		
	
		
		
			
				
					
							progressB :  map [ * hcl . Block ] map [ string ] struct { } { } , 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
							doneF :  map [ string ] struct { } { } , 
		doneF :  map [ string ] struct { } { } , 
 
			
		
	
		
		
			
				
					
							doneB :  map [ * hcl . Block ] map [ string ] struct { } { } , 
 
			
		
	
		
		
			
				
					
							ectx :  & hcl . EvalContext { 
		ectx :  & hcl . EvalContext { 
 
			
		
	
		
		
			
				
					
								Variables :  map [ string ] cty . Value { } , 
			Variables :  map [ string ] cty . Value { } , 
 
			
		
	
		
		
			
				
					
								Functions :  stdlibFunctions , 
			Functions :  stdlibFunctions , 
 
			
		
	
	
		
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
					@ -337,22 +560,17 @@ func Parse(b hcl.Body, opt Opt, val interface{}) hcl.Diagnostics {
 
			
		
	
		
		
			
				
					
							_  =  p . resolveValue ( k ) 
		_  =  p . resolveValue ( k ) 
 
			
		
	
		
		
			
				
					
						} 
	} 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
						for  k  :=  range  p . attrs  { 
	for  _ ,  a  :=  range  content . Attributes  { 
 
			
				
				
			
		
	
		
		
			
				
					
							if  err  :=  p . resolveValue ( k ) ;  err  !=  nil  { 
 
			
		
	
		
		
			
				
					
								if  diags ,  ok  :=  err . ( hcl . Diagnostics ) ;  ok  { 
 
			
		
	
		
		
			
				
					
									return  diags 
 
			
		
	
		
		
			
				
					
								} 
 
			
		
	
		
		
	
		
		
			
				
					
							return  hcl . Diagnostics { 
		return  hcl . Diagnostics { 
 
			
		
	
		
		
			
				
					
								& hcl . Diagnostic { 
			& hcl . Diagnostic { 
 
			
		
	
		
		
			
				
					
									Severity :  hcl . DiagError , 
				Severity :  hcl . DiagError , 
 
			
		
	
		
		
			
				
					
									Summary :   "Invalid attribute" , 
				Summary :   "Invalid attribute" , 
 
			
		
	
		
		
			
				
					
										Detail :    err . Error ( )  , 
				Detail :    "global attributes currently not supported" , 
 
			
				
				
			
		
	
		
		
			
				
					
										 Subject :   & p.  attrs[ k ]  . Range , 
				Subject :   & . Range , 
 
			
				
				
			
		
	
		
		
			
				
					
										 Context :   & p.  attrs[ k ]  . Range , 
				Context :   & . Range , 
 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
								} , 
			} , 
 
			
		
	
		
		
			
				
					
							} 
		} 
 
			
		
	
		
		
			
				
					
						} 
	} 
 
			
		
	
		
		
			
				
					
						} 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
						for  k  :=  range  p . vars  { 
	for  k  :=  range  p . vars  { 
 
			
		
	
		
		
			
				
					
							if  err  :=  p . resolveValue ( k ) ;  err  !=  nil  { 
		if  err  :=  p . resolveValue ( k ) ;  err  !=  nil  { 
 
			
		
	
	
		
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
					@ -403,19 +621,6 @@ func Parse(b hcl.Body, opt Opt, val interface{}) hcl.Diagnostics {
 
			
		
	
		
		
			
				
					
							} 
		} 
 
			
		
	
		
		
			
				
					
						} 
	} 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
						for  _ ,  a  :=  range  content . Attributes  { 
 
			
		
	
		
		
			
				
					
							return  hcl . Diagnostics { 
 
			
		
	
		
		
			
				
					
								& hcl . Diagnostic { 
 
			
		
	
		
		
			
				
					
									Severity :  hcl . DiagError , 
 
			
		
	
		
		
			
				
					
									Summary :   "Invalid attribute" , 
 
			
		
	
		
		
			
				
					
									Detail :    "global attributes currently not supported" , 
 
			
		
	
		
		
			
				
					
									Subject :   & a . Range , 
 
			
		
	
		
		
			
				
					
									Context :   & a . Range , 
 
			
		
	
		
		
			
				
					
								} , 
 
			
		
	
		
		
			
				
					
							} 
 
			
		
	
		
		
			
				
					
						} 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
						m  :=  map [ string ] map [ string ] [ ] * hcl . Block { } 
 
			
		
	
		
		
			
				
					
						for  _ ,  b  :=  range  content . Blocks  { 
	for  _ ,  b  :=  range  content . Blocks  { 
 
			
		
	
		
		
			
				
					
							if  len ( b . Labels )  ==  0  ||  len ( b . Labels )  >  1  { 
		if  len ( b . Labels )  ==  0  ||  len ( b . Labels )  >  1  { 
 
			
		
	
		
		
			
				
					
								return  hcl . Diagnostics { 
			return  hcl . Diagnostics { 
 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -428,19 +633,16 @@ func Parse(b hcl.Body, opt Opt, val interface{}) hcl.Diagnostics {
 
			
		
	
		
		
			
				
					
									} , 
				} , 
 
			
		
	
		
		
			
				
					
								} 
			} 
 
			
		
	
		
		
			
				
					
							} 
		} 
 
			
		
	
		
		
			
				
					
							bm ,  ok  :=  m [ b . Type ] 
		bm ,  ok  :=  p. blocks  [ b . Type ] 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
							if  ! ok  { 
		if  ! ok  { 
 
			
		
	
		
		
			
				
					
								bm  =  map [ string ] [ ] * hcl . Block { } 
			bm  =  map [ string ] [ ] * hcl . Block { } 
 
			
		
	
		
		
			
				
					
								m [ b . Type ]  =  bm 
			p. blocks  [ b . Type ]  =  bm 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
							} 
		} 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
							lbl  :=  b . Labels [ 0 ] 
		lbl  :=  b . Labels [ 0 ] 
 
			
		
	
		
		
			
				
					
							bm [ lbl ]  =  append ( bm [ lbl ] ,  b ) 
		bm [ lbl ]  =  append ( bm [ lbl ] ,  b ) 
 
			
		
	
		
		
			
				
					
						} 
	} 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
						vt  :=  reflect . ValueOf ( val ) . Elem ( ) . Type ( ) 
 
			
		
	
		
		
			
				
					
						numFields  :=  vt . NumField ( ) 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
						type  value  struct  { 
	type  value  struct  { 
 
			
		
	
		
		
			
				
					
							reflect . Value 
		reflect . Value 
 
			
		
	
		
		
			
				
					
							idx  int 
		idx  int 
 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -452,9 +654,11 @@ func Parse(b hcl.Body, opt Opt, val interface{}) hcl.Diagnostics {
 
			
		
	
		
		
			
				
					
						} 
	} 
 
			
		
	
		
		
			
				
					
						types  :=  map [ string ] field { } 
	types  :=  map [ string ] field { } 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
						for  i  :=  0 ;  i  <  numFields ;  i ++  { 
	vt  :=  reflect . ValueOf ( val ) . Elem ( ) . Type ( ) 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
						for  i  :=  0 ;  i  <  vt . NumField ( ) ;  i ++  { 
 
			
		
	
		
		
			
				
					
							tags  :=  strings . Split ( vt . Field ( i ) . Tag . Get ( "hcl" ) ,  "," ) 
		tags  :=  strings . Split ( vt . Field ( i ) . Tag . Get ( "hcl" ) ,  "," ) 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
							p . blockTypes [ tags [ 0 ] ]  =  vt . Field ( i ) . Type . Elem ( ) . Elem ( ) 
 
			
		
	
		
		
			
				
					
							types [ tags [ 0 ] ]  =  field { 
		types [ tags [ 0 ] ]  =  field { 
 
			
		
	
		
		
			
				
					
								idx :     i , 
			idx :     i , 
 
			
		
	
		
		
			
				
					
								typ :     vt . Field ( i ) . Type , 
			typ :     vt . Field ( i ) . Type , 
 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -466,29 +670,29 @@ func Parse(b hcl.Body, opt Opt, val interface{}) hcl.Diagnostics {
 
			
		
	
		
		
			
				
					
						for  _ ,  b  :=  range  content . Blocks  { 
	for  _ ,  b  :=  range  content . Blocks  { 
 
			
		
	
		
		
			
				
					
							v  :=  reflect . ValueOf ( val ) 
		v  :=  reflect . ValueOf ( val ) 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
							t ,  ok  :=  types [ b . Type ] 
		err  :=  p . resolveBlock ( b ,  nil ) 
 
			
				
				
			
		
	
		
		
			
				
					
							if  ! ok  { 
		if  err  !=  nil  { 
 
			
				
				
			
		
	
		
		
			
				
					
								continue 
			if  diag ,  ok  :=  err . ( hcl . Diagnostics ) ;  ok  { 
 
			
				
				
			
		
	
		
		
			
				
					
							} 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
							vv  :=  reflect . New ( t . typ . Elem ( ) . Elem ( ) ) 
 
			
		
	
		
		
			
				
					
							diag  :=  gohcl . DecodeBody ( b . Body ,  p . ectx ,  vv . Interface ( ) ) 
 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
									if  diag . HasErrors ( )  { 
				if  diag . HasErrors ( )  { 
 
			
		
	
		
		
			
				
					
										diags  =  append ( diags ,  diag ... ) 
					diags  =  append ( diags ,  diag ... ) 
 
			
		
	
		
		
			
				
					
										continue 
					continue 
 
			
		
	
		
		
			
				
					
									} 
				} 
 
			
		
	
		
		
			
				
					
					
			}  else  { 
 
			
				
				
			
		
	
		
		
			
				
					
							if  err  :=  opt . ValidateLabel ( b . Labels [ 0 ] ) ;  err  !=  nil  { 
 
			
		
	
		
		
	
		
		
			
				
					
									return  hcl . Diagnostics { 
				return  hcl . Diagnostics { 
 
			
		
	
		
		
			
				
					
										& hcl . Diagnostic { 
					& hcl . Diagnostic { 
 
			
		
	
		
		
			
				
					
											Severity :  hcl . DiagError , 
						Severity :  hcl . DiagError , 
 
			
		
	
		
		
			
				
					
										Summary :   "Invalid nam , 
						Summary :   "Invalid attribut  e", 
 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
											Detail :    err . Error ( ) , 
						Detail :    err . Error ( ) , 
 
			
		
	
		
		
			
				
					
											Subject :   & b . LabelRanges [ 0 ] , 
						Subject :   & b . LabelRanges [ 0 ] , 
 
			
		
	
		
		
			
				
					
											Context :   & b . DefRange , 
 
			
		
	
		
		
			
				
					
										} , 
					} , 
 
			
		
	
		
		
			
				
					
									} 
				} 
 
			
		
	
		
		
			
				
					
								} 
			} 
 
			
		
	
		
		
			
				
					
							} 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
							vv  :=  p . blockValues [ b ] 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
							t  :=  types [ b . Type ] 
 
			
		
	
		
		
			
				
					
							lblIndex  :=  setLabel ( vv ,  b . Labels [ 0 ] ) 
		lblIndex  :=  setLabel ( vv ,  b . Labels [ 0 ] ) 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
							oldValue ,  exists  :=  t . values [ b . Labels [ 0 ] ] 
		oldValue ,  exists  :=  t . values [ b . Labels [ 0 ] ] 
 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -502,7 +706,6 @@ func Parse(b hcl.Body, opt Opt, val interface{}) hcl.Diagnostics {
 
			
		
	
		
		
			
				
					
										} 
					} 
 
			
		
	
		
		
			
				
					
									} 
				} 
 
			
		
	
		
		
			
				
					
								} 
			} 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
							} 
		} 
 
			
		
	
		
		
			
				
					
							if  exists  { 
		if  exists  { 
 
			
		
	
		
		
			
				
					
								if  m  :=  oldValue . Value . MethodByName ( "Merge" ) ;  m . IsValid ( )  { 
			if  m  :=  oldValue . Value . MethodByName ( "Merge" ) ;  m . IsValid ( )  { 
 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -523,6 +726,23 @@ func Parse(b hcl.Body, opt Opt, val interface{}) hcl.Diagnostics {
 
			
		
	
		
		
			
				
					
							return  diags 
		return  diags 
 
			
		
	
		
		
			
				
					
						} 
	} 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
						for  k  :=  range  p . attrs  { 
 
			
		
	
		
		
			
				
					
							if  err  :=  p . resolveValue ( k ) ;  err  !=  nil  { 
 
			
		
	
		
		
			
				
					
								if  diags ,  ok  :=  err . ( hcl . Diagnostics ) ;  ok  { 
 
			
		
	
		
		
			
				
					
									return  diags 
 
			
		
	
		
		
			
				
					
								} 
 
			
		
	
		
		
			
				
					
								return  hcl . Diagnostics { 
 
			
		
	
		
		
			
				
					
									& hcl . Diagnostic { 
 
			
		
	
		
		
			
				
					
										Severity :  hcl . DiagError , 
 
			
		
	
		
		
			
				
					
										Summary :   "Invalid attribute" , 
 
			
		
	
		
		
			
				
					
										Detail :    err . Error ( ) , 
 
			
		
	
		
		
			
				
					
										Subject :   & p . attrs [ k ] . Range , 
 
			
		
	
		
		
			
				
					
										Context :   & p . attrs [ k ] . Range , 
 
			
		
	
		
		
			
				
					
									} , 
 
			
		
	
		
		
			
				
					
								} 
 
			
		
	
		
		
			
				
					
							} 
 
			
		
	
		
		
			
				
					
						} 
 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
						return  nil 
	return  nil 
 
			
		
	
		
		
			
				
					
					} }