oracle / terraform-provider-oci

Terraform Oracle Cloud Infrastructure provider
https://www.terraform.io/docs/providers/oci/
Mozilla Public License 2.0
758 stars 680 forks source link

Enabling later Reassignment of reserved Public IPs to Private IPs in Terraform (as in the console) #1802

Open brokedba opened 1 year ago

brokedba commented 1 year ago

Community Note

Description

We would like to reuse existing reserved public IPs created using resource "oci_core_public_ip". But assign it afterward to any compute resource (lb,instance). But for now there is no way to do it in terraform.

However it is definitely possible to later assign an existing Public IP to a VNIC through rest API (UpdatePublicIp) or via the console as shown below image

New or Affected Resource(s)

either of the 2

  1. resource "oci_core_instance" could be modified to allow this option. Maybe a new resource to assign and unassign public ip.
  2. new/updated resource "oci_core_public_ip_assign/modify" to allow assignment modification

Potential Terraform Configuration

since REST API has it already it won't require reinventing the wheel.

Proposed Workaround that doesn't work

A workaround has already proposed couple of times here https://github.com/oracle/terraform-provider-oci/issues/1565#issuecomment-1097995590 and here https://github.com/oracle/terraform-provider-oci/issues/1649#issuecomment-1331860084 But it doesn't work example :

resource "oci_core_public_ip" "bastion_ip" {
  compartment_id = var.network_compartment_id != "" ? var.network_compartment_id : var.compartment_id
  display_name   = var.bastion_identifier != "" ? join("-", ["ip-bastion-pub", var.bastion_identifier]) : "ip-bastion-pub"
  lifetime       = "RESERVED"
  private_ip_id  = data.oci_core_private_ips.bastion.private_ips[0]["id"]

  defined_tags = var.defined_tags

  lifecycle {
    prevent_destroy = true
  }
}

But your terraform destroy will fail miserably as shown below .

╷
│ Error: Instance cannot be destroyed
│
│   on compute.tf line 91:
│   91: resource "oci_core_public_ip" "bastion_ip" {
│
│ Resource oci_core_public_ip.bastion has lifecycle.prevent_destroy set, but the plan calls for this resource to be destroyed. To
│ avoid this error and continue with the plan, either disable lifecycle.prevent_destroy or reduce the scope of the plan using the -target flag.
╵

terraform is clean, don't make it dirty.

ravinitp commented 1 year ago

Thank you for reporting the issue. We have raised an internal ticket to track this. Our service engineers will get back to you.

ravinitp commented 1 year ago

Thank you for reporting the issue. We have raised an internal ticket to track this. Our service engineers will get back to you.

ravinitp commented 1 year ago

Thank you for reporting the issue. We have raised an internal ticket to track this. Our service engineers will get back to you.

ravinitp commented 1 year ago

Thank you for reporting the issue. We have raised an internal ticket to track this. Our service engineers will get back to you.

ravinitp commented 1 year ago

We have notified our service engineer. Our service engineers will get back to you.

ravinitp commented 1 year ago

We have notified our service engineer. Our service engineers will get back to you.

brokedba commented 1 year ago

Any update on this request ?

fharris commented 1 year ago

Interested as well.

dhoogfr commented 1 year ago

You can reassign a reserved public IP (or set it "free") by changing the assignment. What I do is to create an instance with the "assign_public_ip" attribute set to "false". I reserve a public IP and then assign that public IP to the instance.

When I need to destroy the instance, I need to remove the assignment in the "oci_core_public_ip" resource or replace it with another assignment.

resource "oci_core_public_ip" "bastion" {
  compartment_id = var.network_compartment_id != "" ? var.network_compartment_id : var.compartment_id
  display_name   = var.bastion_identifier != "" ? join("-", ["ip-bastion-pub", var.bastion_identifier]) : "ip-bastion-pub"
  lifetime       = "RESERVED"
  private_ip_id  = data.oci_core_private_ips.bastion.private_ips[0]["id"]

  defined_tags = var.defined_tags

  lifecycle {
    prevent_destroy = true
  }

}

resource "oci_core_instance" "bastion" {
  compartment_id      = var.compartment_id
  availability_domain = var.availability_domain
  fault_domain        = var.fault_domain
  display_name        = var.bastion_identifier != "" ? join("-", ["bastion", var.bastion_identifier]) : "bastion"
  shape               = local.bastion_instance_shape

  create_vnic_details {
    display_name     = "primaryvnic"
    hostname_label   = var.bastion_hostname
    assign_public_ip = false
    subnet_id        = oci_core_subnet.bastion.id
    nsg_ids          = [oci_core_network_security_group.bastion_host.id]
  }

  source_details {
    source_type = "image"
    source_id   = var.bastion_image_id
  }

  shape_config {
    memory_in_gbs = var.bastion_memory
    ocpus         = var.bastion_ocpus
  }

  metadata = {
    ssh_authorized_keys = var.ssh_public_key
  }

  defined_tags  = var.defined_tags
  freeform_tags = var.freeform_tags

}
thpham commented 1 year ago

Any update on this request ? I'm interested too !

RenatoOneCloudSys commented 11 months ago

To destroy the instance without destroying the public ip, first I had to comment the line private_ip_id on the oci_core_public_ip that related to the instance and run apply so terraform will detach the ip from the instance, then I can destroy targeting the oci_core_instance

rafaelhneves commented 9 months ago

Hello, i am very interested in that.

Best Regards.