Terraform how to get IP address of aws_lb

不想你离开。 提交于 2020-02-24 05:26:31

问题


Question

If there a way to get the assigned IP address of an aws_lb resource at the time aws_lb is created by Terraform?

As in AWS documentation - NLB - To find the private IP addresses to whitelist, we can find out the IP address associated to ELB.

  1. Open the Amazon EC2 console at https://console.aws.amazon.com/ec2/.
  2. In the navigation pane, choose Network Interfaces.
  3. In the search field, type the name of your Network Load Balancer. There is one network interface per load balancer subnet.
  4. On the Details tab for each network interface, copy the address from Primary private IPv4 IP.

Background

To be able to setup security group to white list the ELB IP address as Network Load Balancer cannot not have Security Group as in Network Load Balancers don't have Security Groups.

Considered aws_network_interface but it does not work with an error.

Error: no matching network interface found

Also I think datasource assumes the resource already exists and cannot be used for the resource to be created by Terraform.


回答1:


Using external provider

Get the NLB IP using Python/boto3 invoking from external provider.

nlb_private_ips.tf

variable "nlb_name" {
}
variable "vpc_id" {
}
variable "region" {
}

data "external" "get_nlb_ips" {
  program = ["python", "${path.module}/get_nlb_private_ips.py"]
  query = {
    aws_nlb_name  = "${var.nlb_name}"
    aws_vpc_id    = "${var.vpc_id}"
    aws_region    = "${var.region}"
  }
}

output "aws_nlb_ip_decoded" {
  value = "${jsondecode(data.external.get_nlb_ips.result.private_ips)}"
}

output "aws_nlb_ip_encoded" {
  value = "${data.external.get_nlb_ips.result.private_ips}"
}

get_nlb_private_ips.py

import boto3
import json
import sys


def json_serial(obj):
    """JSON serializer for objects not serializable by default json code
        Args:
            obj: object to serialize into JSON
    """
    _serialize = {
        "int": lambda o: int(o),
        "float": lambda o: float(o),
        "decimal": lambda o: float(o) if o % 1 > 0 else int(o),
        "date": lambda o: o.isoformat(),
        "datetime": lambda o: o.isoformat(),
        "str": lambda o: o,
    }
    return _serialize[type(obj).__name__.lower()](obj)


def pretty_json(dict):
    """
    Pretty print Python dictionary
    Args:
        dict: Python dictionary
    Returns:
        Pretty JSON
    """
    return json.dumps(dict, indent=2, default=json_serial, sort_keys=True, )


def get_nlb_private_ips(data):
    ec2 = boto3.client('ec2', region_name=data['aws_region'])
    response = ec2.describe_network_interfaces(
        Filters=[
            {
                'Name': 'description',
                'Values': [
                    "ELB net/{AWS_NLB_NAME}/*".format(
                        AWS_NLB_NAME=data['aws_nlb_name'])
                ]
            },
            {
                'Name': 'vpc-id',
                'Values': [
                    data['aws_vpc_id']
                ]
            },
            {
                'Name': 'status',
                'Values': [
                    "in-use"
                ]
            },
            {
                'Name': 'attachment.status',
                'Values': [
                    "attached"
                ]
            }
        ]
    )

    # print(pretty_json(response))
    interfaces = response['NetworkInterfaces']

    # ifs = list(map(lamba index: interfaces[index]['PrivateIpAddresses'], xrange(len(interfaces))))
    # --------------------------------------------------------------------------------
    # Private IP addresses associated to an interface (ENI)
    # Each association has the format:
    #   {
    #     "Association": {
    #       "IpOwnerId": "693054447076",
    #       "PublicDnsName": "ec2-52-88-47-177.us-west-2.compute.amazonaws.com",
    #       "PublicIp": "52.88.47.177"
    #     },
    #     "Primary": true,
    #     "PrivateDnsName": "ip-10-5-1-205.us-west-2.compute.internal",
    #     "PrivateIpAddress": "10.5.1.205"
    #   },
    # --------------------------------------------------------------------------------
    associations = [
        association for interface in interfaces
        for association in interface['PrivateIpAddresses']
    ]

    # --------------------------------------------------------------------------------
    # Get IP from each IP association
    # --------------------------------------------------------------------------------
    private_ips = [
        association['PrivateIpAddress'] for association in associations
    ]

    return private_ips


def load_json():
    data = json.load(sys.stdin)
    return data


def main():
    data = load_json()
    """
    print(data['aws_region'])
    print(data['aws_vpc_id'])
    print(data['aws_nlb_name'])
    """
    ips = get_nlb_private_ips(data)
    print(json.dumps({"private_ips": json.dumps(ips)}))


if __name__ == '__main__':
    main()

Using aws_network_interfaces datasource

After aws_lb has been created.

data "aws_network_interfaces" "this" {
  filter {
    name = "description"
    values = ["ELB net/${aws_lb.this.name}/*"]
  }
  filter {
    name = "vpc-id"
    values = ["${var.vpc_id}"]
  }
  filter {
    name = "status"
    values = ["in-use"]
  }
  filter {
    name = "attachment.status"
    values = ["attached"]
  }
}

locals {
  nlb_interface_ids = "${flatten(["${data.aws_network_interfaces.this.ids}"])}"
}

data "aws_network_interface" "ifs" {
  count = "${length(local.nlb_interface_ids)}"
  id = "${local.nlb_interface_ids[count.index]}"
}

output "aws_lb_network_interface_ips" {
  value = "${flatten([data.aws_network_interface.ifs.*.private_ips])}"
}


来源:https://stackoverflow.com/questions/56713493/terraform-how-to-get-ip-address-of-aws-lb

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!