IBM-Cloud / terraform-provider-ibm

https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs
Mozilla Public License 2.0
341 stars 670 forks source link

Nested "security-groups" property of ibm_is_instance conflicts with "ibm_is_security_group_target" definition #1665

Open l2fprod opened 4 years ago

l2fprod commented 4 years ago

Applying the following tf twice results in new changes detected.

I have this simple tf creating a VPC, one instance and two security groups:

data "ibm_is_image" "ds_image" {
  name = module.map_gen1_to_gen2.image
}

data "ibm_is_ssh_key" "ds_key" {
  name = var.ssh_keyname
}

data "ibm_resource_group" "group" {
  name = var.resource_group_name
}

resource "ibm_is_vpc" "vpc" {
  name           = var.vpc_name
  resource_group = data.ibm_resource_group.group.id
}

resource "ibm_is_public_gateway" "cloud" {
  vpc   = ibm_is_vpc.vpc.id
  name  = "${var.basename}-pubgw"
  zone  = var.subnet_zone
}

resource "ibm_is_vpc_address_prefix" "vpc_address_prefix" {
  name = "${var.basename}-prefix"
  zone = var.subnet_zone
  vpc  = ibm_is_vpc.vpc.id
  cidr = "192.168.0.0/16"
}

resource "ibm_is_subnet" "subnet" {
  name            = "${var.basename}-subnet"
  vpc             = ibm_is_vpc.vpc.id
  zone            = var.subnet_zone
  resource_group  = data.ibm_resource_group.group.id
  ipv4_cidr_block = ibm_is_vpc_address_prefix.vpc_address_prefix.cidr
}

resource "ibm_is_instance" "instance" {
  name           = "${var.basename}-instance"
  vpc            = ibm_is_vpc.vpc.id
  zone           = var.subnet_zone
  profile        = module.map_gen1_to_gen2.profile
  image          = data.ibm_is_image.ds_image.id
  keys           = [data.ibm_is_ssh_key.ds_key.id]
  resource_group = data.ibm_resource_group.group.id

  primary_network_interface {
    subnet = ibm_is_subnet.subnet.id
    security_groups = [
      ibm_is_security_group.instance-group.id
    ]
  }
}

resource "ibm_is_security_group" "instance-group" {
  name = "${var.basename}-instance-group"
  vpc            = ibm_is_vpc.vpc.id
  resource_group = data.ibm_resource_group.group.id
}

resource "ibm_is_security_group" "another-group" {
  name = "${var.basename}-another-group"
  vpc            = ibm_is_vpc.vpc.id
  resource_group = data.ibm_resource_group.group.id
}

resource "ibm_is_security_group_network_interface_attachment" "attach-instance" {
  network_interface = ibm_is_instance.instance.primary_network_interface.0.id
  security_group = ibm_is_security_group.another-group.id
}

On first terraform apply everything works as expected:

  Enter a value: yes
...

ibm_is_vpc.vpc: Creating...
ibm_is_vpc.vpc: Still creating... [10s elapsed]
ibm_is_vpc.vpc: Creation complete after 14s [id=r006-907dcb4a-cf71-4c29-bde9-150fe1064d1e]
ibm_is_vpc_address_prefix.vpc_address_prefix: Creating...
ibm_is_public_gateway.cloud: Creating...
ibm_is_security_group.instance-group: Creating...
ibm_is_security_group.another-group: Creating...
ibm_is_vpc_address_prefix.vpc_address_prefix: Creation complete after 1s [id=r006-907dcb4a-cf71-4c29-bde9-150fe1064d1e/r006-590a2f4e-e176-468c-8c14-ee0712f6b71d]
ibm_is_subnet.subnet: Creating...
ibm_is_security_group.another-group: Creation complete after 1s [id=r006-9abac3cb-073a-4af5-9802-0297ec5d9ad8]
ibm_is_security_group.instance-group: Creation complete after 1s [id=r006-eccc4214-cdc2-4c89-826c-1eec53ed84e5]
ibm_is_public_gateway.cloud: Still creating... [10s elapsed]
ibm_is_subnet.subnet: Still creating... [10s elapsed]
ibm_is_public_gateway.cloud: Creation complete after 12s [id=r006-416f5006-63ca-42f0-8e90-afae24dccf8e]
ibm_is_subnet.subnet: Creation complete after 12s [id=0717-153bc1c1-1147-4cca-bfe8-c50d86d7d222]
ibm_is_instance.instance: Creating...
ibm_is_instance.instance: Still creating... [10s elapsed]
ibm_is_instance.instance: Still creating... [20s elapsed]
ibm_is_instance.instance: Still creating... [30s elapsed]
ibm_is_instance.instance: Creation complete after 37s [id=0717_3260d7d5-fab1-41f6-a405-425cc961c0c2]
ibm_is_security_group_network_interface_attachment.attach-instance: Creating...
ibm_is_security_group_network_interface_attachment.attach-instance: Creation complete after 0s [id=r006-9abac3cb-073a-4af5-9802-0297ec5d9ad8/0717-fba3f8e8-1256-49a2-870a-ee01074be89f]

Apply complete! Resources: 8 added, 0 changed, 0 destroyed.

Without changing anything, I run apply again, and I expect no changes to be applied but...

terraform apply
data.ibm_is_ssh_key.ds_key: Refreshing state...
data.ibm_is_image.ds_image: Refreshing state...
data.ibm_resource_group.group: Refreshing state...
ibm_is_vpc.vpc: Refreshing state... [id=r006-907dcb4a-cf71-4c29-bde9-150fe1064d1e]
ibm_is_security_group.another-group: Refreshing state... [id=r006-9abac3cb-073a-4af5-9802-0297ec5d9ad8]
ibm_is_public_gateway.cloud: Refreshing state... [id=r006-416f5006-63ca-42f0-8e90-afae24dccf8e]
ibm_is_vpc_address_prefix.vpc_address_prefix: Refreshing state... [id=r006-907dcb4a-cf71-4c29-bde9-150fe1064d1e/r006-590a2f4e-e176-468c-8c14-ee0712f6b71d]
ibm_is_security_group.instance-group: Refreshing state... [id=r006-eccc4214-cdc2-4c89-826c-1eec53ed84e5]
ibm_is_subnet.subnet: Refreshing state... [id=0717-153bc1c1-1147-4cca-bfe8-c50d86d7d222]
ibm_is_instance.instance: Refreshing state... [id=0717_3260d7d5-fab1-41f6-a405-425cc961c0c2]
ibm_is_security_group_network_interface_attachment.attach-instance: Refreshing state... [id=r006-9abac3cb-073a-4af5-9802-0297ec5d9ad8/0717-fba3f8e8-1256-49a2-870a-ee01074be89f]

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  ~ update in-place

Terraform will perform the following actions:

  # ibm_is_instance.instance will be updated in-place
  ~ resource "ibm_is_instance" "instance" {
        gpu                     = []
        id                      = "0717_3260d7d5-fab1-41f6-a405-425cc961c0c2"
        image                   = "r006-e0039ab2-fcc8-11e9-8a36-6ffb6501dd33"
        keys                    = [
            "r006-c42ad754-17c0-46a7-b8f1-fd57563a2ed8",
        ]
        memory                  = 4
        name                    = "fredl-0615-instance"
        profile                 = "cx2-2x4"
        resource_controller_url = "https://cloud.ibm.com/vpc-ext/compute/vs"
        resource_crn            = "crn:v1:bluemix:public:is:us-south-1:a/bfbfea4eadfc486e88755e6b5c1e51bf::instance:0717_3260d7d5-fab1-41f6-a405-425cc961c0c2"
        resource_group          = "3a88c5c244244cc08c48941ea06ef97d"
        resource_group_name     = "scratch"
        resource_name           = "fredl-0615-instance"
        resource_status         = "running"
        status                  = "running"
        tags                    = []
        vcpu                    = [
            {
                architecture = "amd64"
                count        = 2
            },
        ]
        volume_attachments      = [
            {
                id          = "0717-ac3e32c0-3a1f-42db-b095-24534d901771"
                name        = "volume-attachment"
                volume_crn  = "crn:v1:bluemix:public:is:us-south-1:a/xxx::volume:r006-ee1cadef-c2c2-11ea-ac25-feff0b340b37"
                volume_id   = "r006-ee1cadef-c2c2-11ea-ac25-feff0b340b37"
                volume_name = "darn-ninetieth-feminize-bolt-january-parasail"
            },
        ]
        volumes                 = []
        vpc                     = "r006-907dcb4a-cf71-4c29-bde9-150fe1064d1e"
        zone                    = "us-south-1"

        boot_volume {
            encryption = "crn:v1:bluemix:public:is:us-south-1:a/xxx::volume:r006-ee1cadef-c2c2-11ea-ac25-feff0b340b37"
            iops       = 0
            name       = "volume-attachment"
            size       = 0
        }

      ~ primary_network_interface {
            id                   = "0717-fba3f8e8-1256-49a2-870a-ee01074be89f"
            name                 = "panther-skillful-chastise-trifle-curling-erratic"
            port_speed           = 0
            primary_ipv4_address = "192.168.0.4"
          ~ security_groups      = [
              - "r006-9abac3cb-073a-4af5-9802-0297ec5d9ad8",
                "r006-eccc4214-cdc2-4c89-826c-1eec53ed84e5",
            ]
            subnet               = "0717-153bc1c1-1147-4cca-bfe8-c50d86d7d222"
        }
    }

Plan: 0 to add, 1 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:

Notice that Terraform detects that the security groups configuration for the instance needs to be changed.

This is because I specified one security group in the instance definition and then I used the security group network attachment so terraform is confused and tries to remove this other security group added by another mean.

Now if I do apply and then another apply, it will prompt again to re-add the group... an infinite loop of apply.

What is the proper way to handle this?

l2fprod commented 4 years ago

It seems that one option I have is to not use the "security_groups" attribute but only the attachment. This way it seems terraform does not look at the security groups during apply and thus does not try to change anything. But doing so I have to be careful to not touch the VPC default security group and just leave it with its almost empty rules.

BShrivastav commented 1 year ago

Hello @l2fprod ,

Could you please acknowledge if you are able to utilise the security group target to achieve the same, as the resource is deprecated also it will be removed as part of future release.

l2fprod commented 1 year ago

I replaced with ibm_is_security_group_target but there is still a bug if you apply this twice.

The reason is because of the nested security_groups in is_instance. If you attach groups outside of the instance in addition to using security_groups inside the instance, the code is not able to reconcile everything.

variable "ibmcloud_api_key" {}
variable "region" { default = "us-south" }
variable "basename" { default = "testbed" }

terraform {
  required_providers {
    ibm = {
      source = "IBM-Cloud/ibm"
    }
  }
  required_version = ">= 1.1.8"
}

provider "ibm" {
  ibmcloud_api_key = var.ibmcloud_api_key
  region           = var.region
}

data "ibm_is_image" "ds_image" {
  name = "ibm-centos-7-6-minimal-amd64-2"
}

variable "ssh_keyname" {}
data "ibm_is_ssh_key" "ds_key" {
  name = var.ssh_keyname
}

variable resource_group_name {}
data "ibm_resource_group" "group" {
  name = var.resource_group_name
}

resource "ibm_is_vpc" "vpc" {
  name           = "${var.basename}-vpc"
  resource_group = data.ibm_resource_group.group.id
}

resource "ibm_is_public_gateway" "cloud" {
  vpc   = ibm_is_vpc.vpc.id
  name  = "${var.basename}-pubgw"
  zone  = "${var.region}-1"
}

resource "ibm_is_vpc_address_prefix" "vpc_address_prefix" {
  name = "${var.basename}-prefix"
  zone = "${var.region}-1"
  vpc  = ibm_is_vpc.vpc.id
  cidr = "192.168.0.0/16"
}

resource "ibm_is_subnet" "subnet" {
  name            = "${var.basename}-subnet"
  vpc             = ibm_is_vpc.vpc.id
  zone            = "${var.region}-1"
  resource_group  = data.ibm_resource_group.group.id
  ipv4_cidr_block = ibm_is_vpc_address_prefix.vpc_address_prefix.cidr
}

resource "ibm_is_instance" "instance" {
  name           = "${var.basename}-instance"
  vpc            = ibm_is_vpc.vpc.id
  zone           = "${var.region}-1"
  profile        = "cx2-2x4"
  image          = data.ibm_is_image.ds_image.id
  keys           = [data.ibm_is_ssh_key.ds_key.id]
  resource_group = data.ibm_resource_group.group.id

  primary_network_interface {
    subnet = ibm_is_subnet.subnet.id
    security_groups = [
      ibm_is_security_group.instance-group.id
    ]
  }
}

resource "ibm_is_security_group" "instance-group" {
  name = "${var.basename}-instance-group"
  vpc            = ibm_is_vpc.vpc.id
  resource_group = data.ibm_resource_group.group.id
}

resource "ibm_is_security_group" "another-group" {
  name = "${var.basename}-another-group"
  vpc            = ibm_is_vpc.vpc.id
  resource_group = data.ibm_resource_group.group.id
}

resource "ibm_is_security_group_target" "attach-instance" {
  security_group = ibm_is_security_group.another-group.id
  target = ibm_is_instance.instance.primary_network_interface.0.id
}
BShrivastav commented 1 year ago

@l2fprod , thanks for more detail. Your observation is correct and logically right. As addition of security group as part of instance resource inline:

resource "ibm_is_instance" "example2" {
  name    = "example-instance-2"
  image   = ibm_is_image.example.id
  profile = "cx2-2x4"

  primary_network_interface {
    subnet          = ibm_is_subnet.example.id
    security_groups = [ibm_is_security_group.example.id]
  }
  dedicated_host_group = ibm_is_dedicated_host_group.example.id
  vpc                  = ibm_is_vpc.example.id
  zone                 = "us-south-1"
  keys                 = [ibm_is_ssh_key.example.id]
  depends_on           = [ibm_is_security_group_rule.example3]

  //User can configure timeouts
  timeouts {
    create = "15m"
    update = "15m"
    delete = "15m"
  }
}

or by using security group target

resource "ibm_is_security_group_target" "attach-instance" {
  security_group = ibm_is_security_group.another-group.id
  target = ibm_is_instance.instance.primary_network_interface.0.id
}

would create redundancy for the terraform, We recommend to use one of the both to achieve security group attachments. We will also try to enhance the documentation for the same.

As defined here for nics:

Screenshot 2022-12-13 at 8 36 44 AM