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

ForceNew CNAMEs upon edit #95

Conversation

PhilipWhiteside
Copy link

CNAMEs are not updatable and result in a Terraform apply failure.

Issue to solve is #80

Original work done by @deromemont here hashicorp/terraform-provider-infoblox#41 . Copied to push into this new repo.

@natemellendorf
Copy link

natemellendorf commented Feb 25, 2021

@PhilipWhiteside Curious, have you tested with this? I wonder if we can use the same logic for other records as well.
Edit: Looks like it works for A records too. Any thoughts on updating both A and PRT records with the same correction?

We too would like to see this change accepted.
Without the ability to edit records, it makes the provider less useful for that.

@PhilipWhiteside
Copy link
Author

Hey @natemellendorf

Yes I can confirm this works.

Terraform

x1carbon ➜  test-ib-provider cat main.tf
terraform {
  required_providers {
    infoblox = {
      source  = "localhost/infoblox/infoblox"
      version = "0.0.1"
    }
  }
  required_version = "~> 0.14"
}

resource "infoblox_cname_record" "default" {
  canonical         = "pwhitesi-test01"
  alias             = "pwhitesi-dest01.core.bedfont.io"
  zone              = "bedfont.io"
  tenant_id         = "default"
  dns_view          = "testing"
}

x1carbon ➜  test-ib-provider terraform init    

Initializing the backend...

Initializing provider plugins...
- Reusing previous version of localhost/infoblox/infoblox from the dependency lock file
- Using previously-installed localhost/infoblox/infoblox v0.0.1

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
x1carbon ➜  test-ib-provider terraform apply 
provider.infoblox.server
  Infoblox server IP address.

  Enter a value: xx.xx.xx.xx


An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # infoblox_cname_record.default will be created
  + resource "infoblox_cname_record" "default" {
      + alias     = "pwhitesi-dest01.core.bedfont.io"
      + canonical = "pwhitesi-test01"
      + dns_view  = "testing"
      + id        = (known after apply)
      + tenant_id = "default"
      + zone      = "bedfont.io"
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

infoblox_cname_record.default: Creating...
infoblox_cname_record.default: Creation complete after 2s [id=record:cname/ZG5zLmJpbmRfY25hbWUkLjcuaW8uYmVkZm9udC5jb3JlLnB3aGl0ZXNpLWRlc3QwMQ:pwhitesi-dest01.core.bedfont.io/testing]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
x1carbon ➜  test-ib-provider # Now updating by switching/fixing canonical and alias
x1carbon ➜  test-ib-provider cat main.tf        
terraform {
  required_providers {
    infoblox = {
      source  = "localhost/infoblox/infoblox"
      version = "0.0.1"
    }
  }
  required_version = "~> 0.14"
}

resource "infoblox_cname_record" "default" {
  canonical         = "pwhitesi-dest01.core.bedfont.io"
  alias             = "pwhitesi-test01"
  zone              = "bedfont.io"
  tenant_id         = "default"
  dns_view          = "testing"
}

x1carbon ➜  test-ib-provider terraform apply
provider.infoblox.server
  Infoblox server IP address.

  Enter a value: xx.xx.xx.xx

infoblox_cname_record.default: Refreshing state... [id=record:cname/ZG5zLmJpbmRfY25hbWUkLjcuaW8uYmVkZm9udC5jb3JlLnB3aGl0ZXNpLWRlc3QwMQ:pwhitesi-dest01.core.bedfont.io/testing]

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
-/+ destroy and then create replacement

Terraform will perform the following actions:

  # infoblox_cname_record.default must be replaced
-/+ resource "infoblox_cname_record" "default" {
      ~ alias     = "pwhitesi-dest01.core.bedfont.io" -> "pwhitesi-test01" # forces replacement
      ~ canonical = "pwhitesi-test01" -> "pwhitesi-dest01.core.bedfont.io" # forces replacement
      ~ id        = "record:cname/ZG5zLmJpbmRfY25hbWUkLjcuaW8uYmVkZm9udC5jb3JlLnB3aGl0ZXNpLWRlc3QwMQ:pwhitesi-dest01.core.bedfont.io/testing" -> (known after apply)
        # (3 unchanged attributes hidden)
    }

Plan: 1 to add, 0 to change, 1 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

infoblox_cname_record.default: Destroying... [id=record:cname/ZG5zLmJpbmRfY25hbWUkLjcuaW8uYmVkZm9udC5jb3JlLnB3aGl0ZXNpLWRlc3QwMQ:pwhitesi-dest01.core.bedfont.io/testing]
infoblox_cname_record.default: Destruction complete after 0s
infoblox_cname_record.default: Creating...
infoblox_cname_record.default: Creation complete after 2s [id=record:cname/ZG5zLmJpbmRfY25hbWUkLjcuaW8uYmVkZm9udC5wd2hpdGVzaS10ZXN0MDE:pwhitesi-test01.bedfont.io/testing]

Apply complete! Resources: 1 added, 0 changed, 1 destroyed.
x1carbon ➜  test-ib-provider 

IB GUI

Screenshot from 2021-03-03 10-29-23 568184640

Screenshot from 2021-03-03 10-29-35 826164099

Build

x1carbon ➜  terraform-provider-infoblox git:(force-new-cname-update) docker run --rm -ti --name golang -v ${PWD}:/src:z golang bash
root@499db7c0c0ed:/go# cd /src
root@499db7c0c0ed:/src# go mod tidy
go: downloading github.com/hashicorp/terraform v0.12.9
...
go: downloading github.com/hashicorp/golang-lru v0.5.1
root@499db7c0c0ed:/src# 
root@499db7c0c0ed:/src# go build -o terraform-provider-infoblox
root@499db7c0c0ed:/src# ls 
CHANGELOG.md  LICENSE	 examples  go.sum    main.go  terraform-provider-infoblox  website
GNUmakefile   README.md  go.mod    infoblox  scripts  vendor
root@499db7c0c0ed:/src# exit
exit

Please let me know if you need anything more

@PhilipWhiteside
Copy link
Author

Edit: Looks like it works for A records too. Any thoughts on updating both A and PRT records with the same correction?

I didn't realise A records had the same problem. I haven't hit this problem for A records myself. I'm not clear on what options within the A and PTR spec is immutable so would require force new.

I think as a first step it would be good to see this merged, and a separate stream for the A and PTR records.

@somashekhar
Copy link
Contributor

I do not see this as a clean implementation of update functionality. I suspect "Force new" is not the right way to update a resource(https://www.terraform.io/docs/extend/schemas/schema-behaviors.html#forcenew) @skudriavtsev can you have a look at this.
I would recommend writing an update functionality in go client and calling it for an update rather.

@gfenn-newbury
Copy link

I've forked this provider and am using the following to update CNAME and A records. It should be easy enough to port from the provider itself to the go client:

Within resource_infoblox_cname_record.go

func resourceCNAMERecordUpdate(d *schema.ResourceData, m interface{}) error {

	zone := d.Get("zone").(string)
	dnsView := d.Get("dns_view").(string)
	canonical := d.Get("canonical").(string)
	alias := d.Get("alias").(string)
	if !strings.Contains(alias, zone) {
		alias = d.Get("alias").(string) + "." + zone
	}
	vmId := d.Get("vm_id").(string)
	connector := m.(*ibclient.Connector)

	ea := make(ibclient.EA)

	ea["VM Name"] = canonical

	if vmId != "" {
		ea["VM ID"] = vmId
	}
	newcname := ibclient.NewRecordCNAME(ibclient.RecordCNAME{Ref: d.Id()})
	newcname.Name = alias
	newcname.Canonical = canonical
	refResp, err := connector.UpdateObject(newcname, d.Id())
	if err != nil {
		return fmt.Errorf("Getting CNAME RECORD failed from dns view(%s) : %s", dnsView, err)
	}
	newcname.Ref = refResp
	d.SetId(newcname.Ref)
	return resourceCNAMERecordGet(d, m)
}

Within resource_infoblox_a_record.go

func resourceARecordUpdate(d *schema.ResourceData, m interface{}) error {

	// This functionality doesn't actually exist in the Go Client, so will have to be done directly here
	recordname := d.Get("vm_name").(string)
	ipAddr := d.Get("ip_addr").(string)
	dnsview := d.Get("dns_view").(string)
	cidr := d.Get("cidr").(string)
	vmID := d.Get("vm_id").(string)
	vmName := d.Get("vm_name").(string)
	zone := d.Get("zone").(string)

	ea := make(ibclient.EA)

	ea["VM Name"] = vmName

	if vmID != "" {
		ea["VM ID"] = vmID
	}

	connector := m.(*ibclient.Connector)

	name := recordname + "." + zone
	updateRecordA := ibclient.NewRecordA(ibclient.RecordA{Ref: d.Id()})
	updateRecordA.Name = name
	if ipAddr != "" {
		updateRecordA.Ipv4Addr = ipAddr
	} else {
		updateRecordA.Ipv4Addr = fmt.Sprintf("func:nextavailableip:%s,%s", cidr, dnsview)
	}
	refResp, err := connector.UpdateObject(updateRecordA, d.Id())

	if err != nil {
		return fmt.Errorf("Error creating A Record from network block(%s): %s", cidr, err)
	}
	updateRecordA.Ref = refResp

	d.SetId(updateRecordA.Ref)
	d.Set("recordname", name)

	return resourceARecordGet(d, m)
}

The Go client already offers the connector.UpdateObject function. Why aren't we using this?

@gfenn-newbury
Copy link

I've provided a pull request on the infoblox-go-client repo to implement updating CNAME and A records: infobloxopen/infoblox-go-client#123

@gfenn-newbury
Copy link

When I have some time this week, I'll hopefully be able to provide a pull request to update A/CNAME records from the provider using what was merged to the go-client

@gfenn-newbury
Copy link

Just provided a pull request to add the ability to update A records: #117

@somashekhar
Copy link
Contributor

This particular feature is available under develop branch as of now. Please raise a new PR upon it if something more to be added. Closing this PR as of now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants