55	"log" 
66	"regexp" 
77	"strconv" 
8+ 	"strings" 
89
910	"github.com/f5devcentral/go-bigip" 
1011	"github.com/hashicorp/terraform/helper/schema" 
@@ -38,7 +39,7 @@ func resourceBigipLtmVirtualServer() *schema.Resource {
3839			"source" : {
3940				Type :        schema .TypeString ,
4041				Optional :    true ,
41- 				Default :      "0.0.0.0/0" ,
42+ 				Computed :    true ,
4243				Description : "Source IP and mask for the virtual server" ,
4344			},
4445
@@ -57,7 +58,7 @@ func resourceBigipLtmVirtualServer() *schema.Resource {
5758			"mask" : {
5859				Type :        schema .TypeString ,
5960				Optional :    true ,
60- 				Default :      "255.255.255.255" ,
61+ 				Computed :    true ,
6162				Description : "Mask can either be in CIDR notation or decimal, i.e.: \" 24\"  or \" 255.255.255.0\" . A CIDR mask of \" 0\"  is the same as \" 0.0.0.0\" " ,
6263			},
6364
@@ -162,9 +163,36 @@ func resourceBigipLtmVirtualServer() *schema.Resource {
162163	}
163164}
164165
166+ func  resourceBigipLtmVirtualServerAttrDefaults (d  * schema.ResourceData ) {
167+ 	_ , hasMask  :=  d .GetOk ("mask" )
168+ 	_ , hasSource  :=  d .GetOk ("source" )
169+ 
170+ 	// Set default mask if nil 
171+ 	if  ! hasMask  {
172+ 		// looks like IPv6, lets set to /128 
173+ 		if  strings .Contains (d .Get ("destination" ).(string ), ":" ) {
174+ 			d .Set ("mask" , "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" )
175+ 		} else  { // /32 for IPv4 
176+ 			d .Set ("mask" , "255.255.255.255" )
177+ 		}
178+ 	}
179+ 
180+ 	// set default source if nil 
181+ 	if  ! hasSource  {
182+ 		// looks like IPv6, lets set to ::/0 
183+ 		if  strings .Contains (d .Get ("destination" ).(string ), ":" ) {
184+ 			d .Set ("source" , "::/0" )
185+ 		} else  { // 0.0.0.0/0 
186+ 			d .Set ("source" , "0.0.0.0/0" )
187+ 		}
188+ 	}
189+ }
190+ 
165191func  resourceBigipLtmVirtualServerCreate (d  * schema.ResourceData , meta  interface {}) error  {
166192	client  :=  meta .(* bigip.BigIP )
167193
194+ 	resourceBigipLtmVirtualServerAttrDefaults (d )
195+ 
168196	name  :=  d .Get ("name" ).(string )
169197	port  :=  d .Get ("port" ).(int )
170198	TranslateAddress  :=  d .Get ("translate_port" ).(string )
@@ -215,18 +243,36 @@ func resourceBigipLtmVirtualServerRead(d *schema.ResourceData, meta interface{})
215243		return  nil 
216244	}
217245	// Extract destination address from "/partition_name/(virtual_server_address)[%route_domain]:port" 
218- 	regex  :=  regexp .MustCompile (`(\/.+\/)((?:[0-9]{1,3}\.){3}[0-9]{1,3})(?:\%\d+)?(\: \d+)` )
246+ 	regex  :=  regexp .MustCompile (`(\/.+\/)((?:[0-9]{1,3}\.){3}[0-9]{1,3})(?:\%\d+)?(?:\:( \d+) )` )
219247	destination  :=  regex .FindStringSubmatch (vs .Destination )
220- 	if  len (destination ) <  3  {
221- 		return  fmt .Errorf ("Unable to extract destination address from virtual server destination: "  +  vs .Destination )
248+ 	if  destination  ==  nil  {
249+ 		// We should try a IPv6 extraction 
250+ 
251+ 		regex  =  regexp .MustCompile (`^(\/.+\/)(.*:[^%]*)(?:\%\d+)?(?:\.(\d+))$` )
252+ 		destination  =  regex .FindStringSubmatch (vs .Destination )
253+ 
254+ 		if  destination  ==  nil  {
255+ 			return  fmt .Errorf ("Unable to extract destination address and port from virtual server destination: "  +  vs .Destination )
256+ 		}
222257	}
258+ 
223259	if  err  :=  d .Set ("destination" , destination [2 ]); err  !=  nil  {
224260		return  fmt .Errorf ("[DEBUG] Error saving Destination to state for Virtual Server  (%s): %s" , d .Id (), err )
225261	}
226262
227263	// Extract source address from "(source_address)[%route_domain](/mask)" groups 1 + 2 
228264	regex  =  regexp .MustCompile (`((?:[0-9]{1,3}\.){3}[0-9]{1,3})(?:\%\d+)?(\/\d+)` )
229265	source  :=  regex .FindStringSubmatch (vs .Source )
266+ 	if  source  ==  nil  {
267+ 		// We should try a IPv6 extraction 
268+ 
269+ 		regex  =  regexp .MustCompile (`^(.*:[^%]*)(?:\%\d+)?(\/\d+)$` )
270+ 		source  =  regex .FindStringSubmatch (vs .Source )
271+ 
272+ 		if  source  ==  nil  {
273+ 			return  fmt .Errorf ("Unable to extract source address and mask from virtual server destination: "  +  vs .Source )
274+ 		}
275+ 	}
230276	parsedSource  :=  source [1 ] +  source [2 ]
231277	if  err  :=  d .Set ("source" , parsedSource ); err  !=  nil  {
232278		return  fmt .Errorf ("[DEBUG] Error saving Source to state for Virtual Server  (%s): %s" , d .Id (), err )
@@ -241,15 +287,8 @@ func resourceBigipLtmVirtualServerRead(d *schema.ResourceData, meta interface{})
241287		return  fmt .Errorf ("[DEBUG] Error saving Mask to state for Virtual Server  (%s): %s" , d .Id (), err )
242288	}
243289
244- 	/* Service port is provided by the API in the destination attribute "/partition_name/virtual_server_address[%route_domain]:(port)" 
245- 	   so we need to extract it 
246- 	*/ 
247- 	regex  =  regexp .MustCompile (`\:(\d+)` )
248- 	port  :=  regex .FindStringSubmatch (vs .Destination )
249- 	if  len (port ) <  2  {
250- 		return  fmt .Errorf ("Unable to extract service port from virtual server destination: %s" , vs .Destination )
251- 	}
252- 	parsedPort , _  :=  strconv .Atoi (port [1 ])
290+ 	// Service port was extracted earlier 
291+ 	parsedPort , _  :=  strconv .Atoi (destination [3 ])
253292	d .Set ("port" , parsedPort )
254293
255294	d .Set ("irules" , makeStringList (& vs .Rules ))
@@ -330,6 +369,8 @@ func resourceBigipLtmVirtualServerExists(d *schema.ResourceData, meta interface{
330369func  resourceBigipLtmVirtualServerUpdate (d  * schema.ResourceData , meta  interface {}) error  {
331370	client  :=  meta .(* bigip.BigIP )
332371
372+ 	resourceBigipLtmVirtualServerAttrDefaults (d )
373+ 
333374	name  :=  d .Id ()
334375
335376	var  profiles  []bigip.Profile 
@@ -371,8 +412,13 @@ func resourceBigipLtmVirtualServerUpdate(d *schema.ResourceData, meta interface{
371412		rules  =  listToStringSlice (cfg_rules .([]interface {}))
372413	}
373414
415+ 	destPort  :=  fmt .Sprintf ("%s:%d" , d .Get ("destination" ).(string ), d .Get ("port" ).(int ))
416+ 	if  strings .Contains (d .Get ("destination" ).(string ), ":" ) {
417+ 		destPort  =  fmt .Sprintf ("%s.%d" , d .Get ("destination" ).(string ), d .Get ("port" ).(int ))
418+ 	}
419+ 
374420	vs  :=  & bigip.VirtualServer {
375- 		Destination :                fmt . Sprintf ( "%s:%d" ,  d . Get ( "destination" ).( string ),  d . Get ( "port" ).( int )) ,
421+ 		Destination :                destPort ,
376422		FallbackPersistenceProfile : d .Get ("fallback_persistence_profile" ).(string ),
377423		Source :                     d .Get ("source" ).(string ),
378424		Pool :                       d .Get ("pool" ).(string ),
0 commit comments