Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spoke delegated #315

Closed
wants to merge 11 commits into from
96 changes: 95 additions & 1 deletion ibm/service/vpc/resource_ibm_is_vpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,18 @@ func ResourceIBMISVPC() *schema.Resource {
Computed: true,
Description: "The type of the DNS resolver used for the VPC.- `delegated`: DNS server addresses are provided by the DNS resolver of the VPC specified in `dns.resolver.vpc`.- `manual`: DNS server addresses are specified in `dns.resolver.manual_servers`.- `system`: DNS server addresses are provided by the system.",
},

"dns_binding_id": &schema.Schema{
Type: schema.TypeString,
Computed: true,
Description: "The VPC dns binding id whose DNS resolver provides the DNS server addresses for this VPC.",
},
"dns_binding_name": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "The VPC dns binding name whose DNS resolver provides the DNS server addresses for this VPC.",
},
"vpc_id": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -714,6 +726,51 @@ func vpcCreate(d *schema.ResourceData, meta interface{}, name, apm, rg string, i
return err
}

if dnsresolvertpeOk, ok := d.GetOk("dns.0.resolver.0.type"); ok {
if dnsresolvertpeOk.(string) == "delegated" && d.Get("dns.0.resolver.0.vpc_id").(string) != "" {
vpcId := d.Get("dns.0.resolver.0.vpc_id").(string)
createDnsBindings := &vpcv1.CreateVPCDnsResolutionBindingOptions{
VPCID: vpc.ID,
VPC: &vpcv1.VPCIdentity{
ID: &vpcId,
},
}
if bindingNameOk, ok := d.GetOk("dns.0.resolver.0.dns_binding_name"); ok {
bindingName := bindingNameOk.(string)
createDnsBindings.Name = &bindingName
}
_, response, err := sess.CreateVPCDnsResolutionBinding(createDnsBindings)
if err != nil {
log.Printf("[DEBUG] CreateVPCDnsResolutionBindingWithContext failed %s\n%s", err, response)
return fmt.Errorf("[ERROR] CreateVPCDnsResolutionBinding failed in vpc resource %s\n%s", err, response)
}
resolverType := "delegated"
dnsPatch := &vpcv1.VpcdnsPatch{
Resolver: &vpcv1.VpcdnsResolverPatch{
Type: &resolverType,
VPC: &vpcv1.VpcdnsResolverVPCPatch{
ID: &vpcId,
},
},
}
vpcPatchModel := &vpcv1.VPCPatch{}
vpcPatchModel.Dns = dnsPatch
vpcPatchModelAsPatch, err := vpcPatchModel.AsPatch()
if err != nil {
return fmt.Errorf("[ERROR] CreateVPCDnsResolutionBinding failed in vpcpatch as patch %s", err)
}
updateVpcOptions := &vpcv1.UpdateVPCOptions{
ID: vpc.ID,
}
updateVpcOptions.VPCPatch = vpcPatchModelAsPatch
_, response, err = sess.UpdateVPC(updateVpcOptions)
if err != nil {
log.Printf("[DEBUG] Update vpc with delegated failed %s\n%s", err, response)
return fmt.Errorf("[ERROR] Update vpc with delegated failed in vpc resource %s\n%s", err, response)
}
}
}

if sgAclRules, ok := d.GetOk(isVPCNoSgAclRules); ok {
sgAclRules := sgAclRules.(bool)
if sgAclRules {
Expand Down Expand Up @@ -920,6 +977,38 @@ func vpcGet(d *schema.ResourceData, meta interface{}, id string) error {
if err != nil {
return err
}
resolverMapArray := dnsMap["resolver"].([]map[string]interface{})
resolverMap := resolverMapArray[0]
if resolverMap["type"] != nil && resolverMap["vpc_id"] != nil {
resType := resolverMap["type"].(*string)
resVpc := resolverMap["vpc_id"].(string)
if *resType == "delegated" {
listVPCDnsResolutionBindingOptions := &vpcv1.ListVPCDnsResolutionBindingsOptions{
VPCID: vpc.ID,
}

pager, err := sess.NewVPCDnsResolutionBindingsPager(listVPCDnsResolutionBindingOptions)
if err != nil {
return fmt.Errorf("[ERROR] Error getting VPC dns bindings: %s", err)
}
var allResults []vpcv1.VpcdnsResolutionBinding
for pager.HasNext() {
nextPage, err := pager.GetNext()
if err != nil {
return fmt.Errorf("[ERROR] Error getting VPC dns bindings pager next: %s", err)
}
allResults = append(allResults, nextPage...)
}
for _, binding := range allResults {
if *binding.VPC.ID == resVpc {
resolverMap["dns_binding_id"] = binding.ID
resolverMap["dns_binding_name"] = binding.Name
resolverMapArray[0] = resolverMap
dnsMap["resolver"] = resolverMapArray
}
}
}
}
if err = d.Set(isVPCDns, []map[string]interface{}{dnsMap}); err != nil {
return fmt.Errorf("[ERROR] Error setting dns: %s", err)
}
Expand Down Expand Up @@ -1543,7 +1632,11 @@ func resourceIBMIsVPCMapToVpcdnsPrototype(modelMap map[string]interface{}) (*vpc
func resourceIBMIsVPCMapToVpcdnsResolverPrototype(modelMap map[string]interface{}) (vpcv1.VpcdnsResolverPrototypeIntf, error) {
model := &vpcv1.VpcdnsResolverPrototype{}
if modelMap["type"] != nil && modelMap["type"].(string) != "" {
model.Type = core.StringPtr(modelMap["type"].(string))
if modelMap["type"].(string) == "delegated" {
model.Type = core.StringPtr("system")
} else {
model.Type = core.StringPtr(modelMap["type"].(string))
}
}
if modelMap["manual_servers"] != nil && modelMap["manual_servers"].(*schema.Set).Len() > 0 {
model.Type = core.StringPtr("manual")
Expand Down Expand Up @@ -1583,6 +1676,7 @@ func resourceIBMIsVPCVpcdnsToMap(model *vpcv1.Vpcdns, vpcId, vpcCrn string) (map
return modelMap, err
}
modelMap["resolver"] = []map[string]interface{}{resolverMap}

return modelMap, nil
}

Expand Down
110 changes: 110 additions & 0 deletions ibm/service/vpc/resource_ibm_is_vpc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,53 @@ func TestAccIBMISVPC_dns_delegated(t *testing.T) {
},
})
}
func TestAccIBMISVPC_dns_delegated_first(t *testing.T) {
var vpc string
name1 := fmt.Sprintf("terraformvpcuat-%d", acctest.RandIntRange(10, 100))
name2 := fmt.Sprintf("terraformvpcuat-%d", acctest.RandIntRange(10, 100))
subnet1 := fmt.Sprintf("terraformsubnet-%d", acctest.RandIntRange(10, 100))
subnet2 := fmt.Sprintf("terraformsubnet-%d", acctest.RandIntRange(10, 100))
resourecinstance := fmt.Sprintf("terraformresource-%d", acctest.RandIntRange(10, 100))
resolver1 := fmt.Sprintf("terraformresolver-%d", acctest.RandIntRange(10, 100))
binding := fmt.Sprintf("terraformbinding-%d", acctest.RandIntRange(10, 100))
enableHubTrue := true
enableHubFalse := false
resource.Test(t, resource.TestCase{
PreCheck: func() { acc.TestAccPreCheck(t) },
Providers: acc.TestAccProviders,
CheckDestroy: testAccCheckIBMISVPCDestroy,
Steps: []resource.TestStep{
{
Config: testAccCheckIBMISVPCDnsDelegatedFirstConfig(name1, name2, subnet1, subnet2, resourecinstance, resolver1, binding, enableHubTrue, enableHubFalse),
Check: resource.ComposeTestCheckFunc(
testAccCheckIBMISVPCExists("ibm_is_vpc.hub_true", vpc),
resource.TestCheckResourceAttr(
"ibm_is_vpc.hub_true", "name", name1),
resource.TestCheckResourceAttr(
"ibm_is_vpc.hub_false_delegated", "name", name2),
resource.TestCheckResourceAttr(
"ibm_is_vpc.hub_true", "dns.0.enable_hub", fmt.Sprintf("%t", enableHubTrue)),
resource.TestCheckResourceAttr(
"ibm_is_vpc.hub_true", "dns.0.resolver.0.type", "system"),
resource.TestCheckResourceAttr(
"ibm_is_vpc.hub_false_delegated", "dns.0.enable_hub", fmt.Sprintf("%t", enableHubFalse)),
resource.TestCheckResourceAttr(
"ibm_is_vpc.hub_false_delegated", "dns.0.resolver.0.type", "delegated"),
resource.TestCheckResourceAttr(
"ibm_is_vpc.hub_false_delegated", "dns.0.resolution_binding_count", "1"),
resource.TestCheckResourceAttr(
"ibm_is_vpc.hub_false_delegated", "dns.0.resolver.0.dns_binding_name", binding),
resource.TestCheckResourceAttrSet(
"ibm_is_vpc.hub_false_delegated", "dns.0.resolver.0.dns_binding_id"),
resource.TestCheckResourceAttrSet(
"ibm_is_vpc.hub_false_delegated", "dns.0.resolver.0.vpc_id"),
resource.TestCheckResourceAttrSet(
"ibm_is_vpc.hub_false_delegated", "dns.0.resolver.0.vpc_name"),
),
},
},
})
}

func TestAccIBMISVPC_basic_apm(t *testing.T) {
var vpc string
Expand Down Expand Up @@ -597,6 +644,69 @@ func testAccCheckIBMISVPCDnsDelegatedConfig(vpcname, vpcname2, subnetname1, subn

`, vpcname, enableHub, vpcname2, enablehubfalse, subnetname1, acc.ISZoneName, subnetname2, acc.ISZoneName, subnetname3, acc.ISZoneName, subnetname4, acc.ISZoneName, resourceinstance, resolver1, resolver2, bindingname)

}
func testAccCheckIBMISVPCDnsDelegatedFirstConfig(vpcname, vpcname2, subnetname1, subnetname2, resourceinstance, resolver1, bindingname string, enableHub, enablehubfalse bool) string {
return fmt.Sprintf(`
data "ibm_resource_group" "rg" {
is_default = true
}

resource ibm_is_vpc hub_true {
name = "%s"
dns {
enable_hub = %t
}
}

resource ibm_is_vpc hub_false_delegated {
depends_on = [ ibm_dns_custom_resolver.test_hub_true ]
name = "%s"
dns {
enable_hub = %t
resolver {
type = "delegated"
vpc_id = ibm_is_vpc.hub_true.id
dns_binding_name = "%s"
}
}
}

resource "ibm_is_subnet" "hub_true_sub1" {
name = "%s"
vpc = ibm_is_vpc.hub_true.id
zone = "%s"
total_ipv4_address_count = 16
}
resource "ibm_is_subnet" "hub_true_sub2" {
name = "%s"
vpc = ibm_is_vpc.hub_true.id
zone = "%s"
total_ipv4_address_count = 16
}
resource "ibm_resource_instance" "dns-cr-instance" {
name = "%s"
resource_group_id = data.ibm_resource_group.rg.id
location = "global"
service = "dns-svcs"
plan = "standard-dns"
}
resource "ibm_dns_custom_resolver" "test_hub_true" {
name = "%s"
instance_id = ibm_resource_instance.dns-cr-instance.guid
description = "new test CR - TF"
high_availability = true
enabled = true
locations {
subnet_crn = ibm_is_subnet.hub_true_sub1.crn
enabled = true
}
locations {
subnet_crn = ibm_is_subnet.hub_true_sub2.crn
enabled = true
}
}
`, vpcname, enableHub, vpcname2, enablehubfalse, bindingname, subnetname1, acc.ISZoneName, subnetname2, acc.ISZoneName, resourceinstance, resolver1)

}
func testAccCheckIBMISVPCDnsDelegatedUpdate1Config(vpcname, vpcname2, subnetname1, subnetname2, subnetname3, subnetname4, resourceinstance, resolver1, resolver2, bindingname string, enableHub, enablehubfalse bool) string {
return fmt.Sprintf(`
Expand Down
21 changes: 20 additions & 1 deletion website/docs/r/is_vpc.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,22 @@ resource "ibm_is_vpc" "example-system" {
}
}

// delegated type resolver

resource "ibm_is_vpc" "example-delegated" {
// required : add a dependency on ibm dns custom resolver of the hub vpc
depends_on = [ ibm_dns_custom_resolver.example-hub ]
name = "example-hub-false-delegated"
dns {
enable_hub = false
resolver {
type = "delegated"
vpc_id = ibm_is_vpc.example.id
dns_binding_name = "example-vpc-binding"
}
}
}

```

## Timeouts
Expand Down Expand Up @@ -116,6 +132,9 @@ Review the argument references that you can specify for your resource.
- `resolver` - (Optional, List) The zone list this backup policy plan will create snapshot clones in.
Nested scheme for `resolver`:

- `dns_binding_id` - (String) The VPC dns binding id whose DNS resolver provides the DNS server addresses for this VPC. (If any)
- `dns_binding_name` - (Optional, String) The VPC dns binding name whose DNS resolver provides the DNS server addresses for this VPC. Only applicable for `delegated`, providing value would create binding with this name.

~> **Note:**
`manual_servers` must be set if and only if `dns.resolver.type` is manual.
- `manual_servers` - (Optional, List) The DNS servers to use for this VPC, replacing any existing servers. All the DNS servers must either: **have a unique zone_affinity**, or **not have a zone_affinity**.
Expand All @@ -139,7 +158,7 @@ Review the argument references that you can specify for your resource.
~> **Note:**
Updating from `manual` requires dns resolver `manual_servers` to be specified as null.<br/>
Updating to `manual` requires dns resolver `manual_servers` to be specified and not empty.<br/>
Updating from `delegated` requires `dns.resolver.vpc` to be specified as null.
Updating from `delegated` requires `dns.resolver.vpc` to be specified as null. If type is `delegated` while creation then `vpc_id` is required
- `vpc_id` - (Optional, List) (update only) The VPC ID to provide DNS server addresses for this VPC. The specified VPC must be configured with a DNS Services custom resolver and must be in one of this VPC's DNS resolution bindings. Mutually exclusive with `vpc_crn`

~> **Note:**
Expand Down
Loading