@ -42,24 +42,40 @@ func utilityPfwCheckPresence(d *schema.ResourceData, m interface{}) (string, err
 
			
		
	
		
			
				
						// method for the Terraform resource Exists method.
 
 
			
		
	
		
			
				
						//
 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
						// The string returned by this method mimics response of an imaginary API that will
 
 
			
		
	
		
			
				
						// report PFW rules (if any) as following:
 
 
			
		
	
		
			
				
						// {
 
 
			
		
	
		
			
				
						//    "header": {
 
 
			
		
	
		
			
				
						//	     "computeId": <int>,
 
 
			
		
	
		
			
				
						//       "vinsId": <int>,
 
 
			
		
	
		
			
				
						//       },
 
 
			
		
	
		
			
				
						//    "rules": [
 
 
			
		
	
		
			
				
						//	        {
 
 
			
		
	
		
			
				
						//	           "id": <int>,
 
 
			
		
	
		
			
				
						//	           "localPort": <int>,
 
 
			
		
	
		
			
				
						//	           "protocol": <int>,
 
 
			
		
	
		
			
				
						//	           "publicPortStart": <int>,
 
 
			
		
	
		
			
				
						//	           "publicPortEnd": <int>,
 
 
			
		
	
		
			
				
						//	           "vmId": <int>,
 
 
			
		
	
		
			
				
						//          },
 
 
			
		
	
		
			
				
						//	        {
 
 
			
		
	
		
			
				
						//	            ...
 
 
			
		
	
		
			
				
						//          },
 
 
			
		
	
		
			
				
						//       ],	
 
 
			
		
	
		
			
				
						// }
 
 
			
		
	
		
			
				
						// This response unmarshalls into ComputePfwListResp structure.
 
 
			
		
	
		
			
				
						// NOTE: If there are no rules for this compute, an empty string is returned along with err=nil
 
 
			
		
	
		
			
				
						//
 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
						controller  :=  m . ( * ControllerCfg ) 
 
			
		
	
		
			
				
						urlValues  :=  & url . Values { } 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
						// NOTE on importing PFW into TF state resource:
 
 
			
		
	
		
			
				
						//
 
 
			
		
	
		
			
				
						// Port forward rules are NOT represented by any "individual" resource in the platform.
 
 
			
		
	
		
			
				
						// Consequently, there is no unique ID reported by the platform that could be used to
 
 
			
		
	
		
			
				
						// identify PFW rule set. 
 
 
			
		
	
		
			
				
						// However, we need some ID to identify PFW resource in TF state, and compute ID is the most
 
 
			
		
	
		
			
				
						// convenient way, as it is:
 
 
			
		
	
		
			
				
						// 1) unique;
 
 
			
		
	
		
			
				
						// 2) compute may have only one PFW rule set.
 
 
			
		
	
		
			
				
						//
 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
						var  compId ,  vinsId  int 
 
			
		
	
		
			
				
						
 
			
		
	
		
			
				
						// PFW resource ID is a combination of compute_id and vins_id separated by ":"
 
 
			
		
	
		
			
				
						// See a note in "flattenPfw" method explaining the rationale behind this approach.
 
 
			
		
	
		
			
				
						if  d . Id ( )  !=  ""  { 
 
			
		
	
		
			
				
							log . Debugf ( "utilityPfwCheckPresence: setting context from d.Id() %s" ,  d . Id ( ) ) 
 
			
		
	
		
			
				
							log . Debugf ( "utilityPfwCheckPresence: setting context from PFW ID %s" ,  d . Id ( ) ) 
 
			
		
	
		
			
				
							idParts  :=  strings . SplitN ( d . Id ( ) ,  ":" ,  2 ) 
 
			
		
	
		
			
				
							compId ,  _  =  strconv . Atoi ( idParts [ 0 ] ) 
 
			
		
	
		
			
				
							vinsId ,  _  =  strconv . Atoi ( idParts [ 1 ] ) 
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -74,9 +90,9 @@ func utilityPfwCheckPresence(d *schema.ResourceData, m interface{}) (string, err
 
			
		
	
		
			
				
								log . Debugf ( "utilityPfwCheckPresence: setting Compute ID from schema" ) 
 
			
		
	
		
			
				
								compId  =  scId . ( int ) 
 
			
		
	
		
			
				
								vinsId  =  svId . ( int ) 
 
			
		
	
		
			
				
								log . Debugf ( "utilityPfwCheckPresence: extract t ed Compute ID %d, ViNS %d",  compId ,  vinsId ) 
 
			
		
	
		
			
				
								log . Debugf ( "utilityPfwCheckPresence: extract ed Compute ID %d, ViNS %d",  compId ,  vinsId ) 
 
			
		
	
		
			
				
							}  else  { 
 
			
		
	
		
			
				
								return  "" ,  fmt . Errorf ( "Cannot get context to check PFW rules neither from  d.Id()  nor from schema") 
 
			
		
	
		
			
				
								return  "" ,  fmt . Errorf ( "Cannot get context to check PFW rules neither from  PFW ID  nor from schema") 
 
			
		
	
		
			
				
							} 
 
			
		
	
		
			
				
						} 
 
			
		
	
		
			
				
						
 
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -145,18 +161,44 @@ func utilityPfwCheckPresence(d *schema.ResourceData, m interface{}) (string, err
 
			
		
	
		
			
				
							return  "" ,  err 
 
			
		
	
		
			
				
						} 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
						log . Debugf ( "utilityPfwCheckPresence: successfully read %d port forward rules for Compute ID %d, ViNS ID %d" , 
 
			
		
	
		
			
				
					               len ( pfwListResp . Rules ) ,  compId ,  pfwListResp . Header . VinsID ) 
 
			
		
	
		
			
				
						log . Debugf ( "utilityPfwCheckPresence: successfully read %d port forward rules for Compute ID %d" , 
 
			
		
	
		
			
				
					               len ( pfwListResp . Rules ) ,  compId ) 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
						if  len ( pfwListResp . Rules )  ==  0  { 
 
			
		
	
		
			
				
							// this compute technically can have rules, but no rules are currently defined
 
 
			
		
	
		
			
				
							return  "" ,  nil 
 
			
		
	
		
			
				
						} 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
						if  pfwListResp . Header . VinsID  !=  vinsId  { 
 
			
		
	
		
			
				
						// Now we can double check that the PFWs we've got do belong to the compute & ViNS specified in the
 
 
			
		
	
		
			
				
						// PFW definition. Do so by reading compute details and comparing NatableVinsID value with the
 
 
			
		
	
		
			
				
						// specified ViNS ID
 
 
			
		
	
		
			
				
						//
 
 
			
		
	
		
			
				
						// We may reuse urlValues here, as it already contains computeId field (see initialization above)
 
 
			
		
	
		
			
				
						apiResp ,  err ,  _  =  controller . decortAPICall ( "POST" ,  ComputeGetAPI ,  urlValues ) 
 
			
		
	
		
			
				
						if  err  !=  nil  ||  apiResp  ==  ""  { 
 
			
		
	
		
			
				
							log . Errorf ( "utilityPfwCheckPresence: failed to get Compute ID %d details" ,  compId ) 
 
			
		
	
		
			
				
							return  "" ,  err 
 
			
		
	
		
			
				
						} 
 
			
		
	
		
			
				
						compFacts  :=  ComputeGetResp { } 
 
			
		
	
		
			
				
						err  =  json . Unmarshal ( [ ] byte ( rulesResp ) ,  & apiResp ) 
 
			
		
	
		
			
				
						if  err  !=  nil  { 
 
			
		
	
		
			
				
							log . Errorf ( "utilityPfwCheckPresence: failed to unmarshal compute details for ID %d: %s" ,  compId ,  err ) 
 
			
		
	
		
			
				
							return  "" ,  err 
 
			
		
	
		
			
				
						} 
 
			
		
	
		
			
				
						if  compFacts . NatableVinsID  <=  0  { 
 
			
		
	
		
			
				
							log . Errorf ( "utilityPfwCheckPresence: compute ID %d is not connected to a NAT-able ViNS" ,  compId ) 
 
			
		
	
		
			
				
							return  "" ,  fmt . Errorf ( "Compute ID %d is not connected to a NAT-able ViNS" ,  compId ) 
 
			
		
	
		
			
				
						} 
 
			
		
	
		
			
				
						if  compFacts . NatableVinsID  !=  vinsId  { 
 
			
		
	
		
			
				
							log . Errorf ( "utilityPfwCheckPresence: ViNS ID mismatch for PFW rules on compute ID %d: actual %d, required %d" , 
 
			
		
	
		
			
				
									   compId ,  pfwListResp . Header . VinsID ,  vinsId ) 
 
			
		
	
		
			
				
									   compId ,  compFacts. Natable  VinsID,  vinsId ) 
 
			
		
	
		
			
				
							return  "" ,  fmt . Errorf ( "ViNS ID mismatch for PFW rules on compute ID %d: actual %d, required %d" , 
 
			
		
	
		
			
				
												  compId ,  pfwListResp . Header . VinsID ,  vinsId ) 
 
			
		
	
		
			
				
												  compId ,  compFacts. Natable  VinsID,  vinsId ) 
 
			
		
	
		
			
				
						} 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
						// reconstruct API response string for return
 
 
			
		
	
		
			
				
						// reconstruct API response string  to  return
 
			
		
	
		
			
				
						pfwListResp . Header . ComputeID  =  compId 
 
			
		
	
		
			
				
						pfwListResp . Header . VinsID  =  compFacts . NatableVinsID 
 
			
		
	
		
			
				
						reencodedItem ,  err  :=  json . Marshal ( pfwListResp ) 
 
			
		
	
		
			
				
						if  err  !=  nil  { 
 
			
		
	
		
			
				
							return  "" ,  err