@ -8,8 +8,16 @@ import ( 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					var  (  
					 
					 
					 
					var  (  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						_  MachineIterator  =  ( * Region ) ( nil )   
					 
					 
					 
						_  MachineIterator  =  ( * Region ) ( nil )   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						_  ZoneIterator     =  ( * Region ) ( nil )   
					 
					 
					 
						_  ZoneIterator     =  ( * Region ) ( nil )   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
						_  RegionIterator  =  ( * Zone ) ( nil )   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
						_  RegionIterator  =  ( * Cluster ) ( nil )   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					)  
					 
					 
					 
					)  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					// A RegionIterator is a set of Regions we can iterate on
  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					type  RegionIterator  interface  {  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
						ForEachRegion ( func ( * Region )  bool )   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					}  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					// Region represents a group of zones geographically related
  
					 
					 
					 
					// Region represents a group of zones geographically related
  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					type  Region  struct  {  
					 
					 
					 
					type  Region  struct  {  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						m      * Cluster   
					 
					 
					 
						m      * Cluster   
				
			 
			
		
	
	
		
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
					 
					@ -145,6 +153,28 @@ func (m *Cluster) appendRegionRegions(name string, subs ...string) { 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						} )   
					 
					 
					 
						} )   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					}  
					 
					 
					 
					}  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					// ForEachRegion calls a function on all regions this zone belongs to.
  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					func  ( z  * Zone )  ForEachRegion ( fn  func ( * Region )  bool )  {  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
						if  fn  ==  nil  {   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
							return   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
						}   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
						z . zones . ForEachRegion ( func ( r  * Region )  bool  {   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
							var  match  bool   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
							r . ForEachZone ( func ( z2  * Zone )  bool  {   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
								match  =  ( z  ==  z2 )   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
								return  match   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
							} )   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
							if  match  &&  fn ( r )  {   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
								return  true   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
							}   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
							return  false   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
						} )   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					}  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					func  ( z  * Zone )  appendRegions ( regions  ... string )  error  {  
					 
					 
					 
					func  ( z  * Zone )  appendRegions ( regions  ... string )  error  {  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						for  _ ,  s  :=  range  regions  {   
					 
					 
					 
						for  _ ,  s  :=  range  regions  {   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							// TODO: validate
   
					 
					 
					 
							// TODO: validate
   
				
			 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
							 
						
					 
					 
					@ -168,7 +198,7 @@ func (m *Cluster) finishRegion(r *Region) { 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						r . m  =  m   
					 
					 
					 
						r . m  =  m   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						sub  :=  [ ] string { }   
					 
					 
					 
						sub  :=  [ ] string { }   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						for  _ ,  name  :=  range  r . Regions  {   
					 
					 
					 
						for  _ ,  name  :=  range  r . Regions  {   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							r2 ,  ok  :=  m . getRegion ( name )   
					 
					 
					 
							r2 ,  ok  :=  m . getFinish Region ( name )   
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
							if  ! ok  {   
					 
					 
					 
							if  ! ok  {   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
								m . warn ( nil ) . WithField ( "region" ,  name ) . Print ( "unknown region" )   
					 
					 
					 
								m . warn ( nil ) . WithField ( "region" ,  name ) . Print ( "unknown region" )   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
								continue   
					 
					 
					 
								continue   
				
			 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
							 
						
					 
					 
					@ -183,9 +213,7 @@ func (m *Cluster) finishRegion(r *Region) { 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					func  ( m  * Cluster )  getRegion ( name  string )  ( * Region ,  bool )  {  
					 
					 
					 
					func  ( m  * Cluster )  getRegion ( name  string )  ( * Region ,  bool )  {  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						for  i  :=  range  m . Regions  {   
					 
					 
					 
						for  i  :=  range  m . Regions  {   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							r  :=  & m . Regions [ i ]   
					 
					 
					 
							r  :=  & m . Regions [ i ]   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							if  name  ==  r . Name  {   
					 
					 
					 
							if  name  ==  r . Name  {   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
								m . finishRegion ( r )   
					 
					 
					 
					 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
								return  r ,  true   
					 
					 
					 
								return  r ,  true   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							}   
					 
					 
					 
							}   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						}   
					 
					 
					 
						}   
				
			 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
							 
						
					 
					 
					@ -193,6 +221,15 @@ func (m *Cluster) getRegion(name string) (*Region, bool) { 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						return  nil ,  false   
					 
					 
					 
						return  nil ,  false   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					}  
					 
					 
					 
					}  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					func  ( m  * Cluster )  getFinishRegion ( name  string )  ( * Region ,  bool )  {  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
						if  r ,  ok  :=  m . getRegion ( name ) ;  ok  {   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
							m . finishRegion ( r )   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
							return  r ,  true   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
						}   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
						return  nil ,  false   
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					}  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					// SyncRegions writes to the file system the regions this [Zone]
  
					 
					 
					 
					// SyncRegions writes to the file system the regions this [Zone]
  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					// belongs to.
  
					 
					 
					 
					// belongs to.
  
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					func  ( z  * Zone )  SyncRegions ( )  error  {  
					 
					 
					 
					func  ( z  * Zone )  SyncRegions ( )  error  {