Terraform aws_wafv2_ip_set delete ip on apply - amazon-web-services

I have a resource aws_wafv2_ip_set that is used by many different modules.
variable "addresses" {
type = set(string)
default = []
}
resource "aws_wafv2_ip_set" "ip_set" {
ip_address_version = "IPV4"
name = var.name
scope = "REGIONAL"
addresses = var.addresses
}
I need to create different ip sets that will be filled by a dynamic script from our admin section or directly from AWS console (not from terraform).
The problem is that every single apply detect that the ip set is not empty (like the var address), and so it delete all ip address added by console or by script.
How can I add aws_wafv2_ip_set without delete ip address on apply?
Thank you

According to the docs, adresses is an array of strings and is required.
Why don't you just go with the tf example:
resource "aws_wafv2_ip_set" "ip_set" {
name = "example"
description = "Example IP set"
scope = "REGIONAL"
ip_address_version = "IPV4"
addresses = ["YOUR_IP_1", "YOUR_IP_2"]
}

Related

Terraform gcp get internal private ip of instance and write to file

Working on the following example github i am trying to add a static internal ip value to terraform ( so instance will run with specific internal ip ) or at least get the internal ip of the instance so i can write it in the internal file of the instance.
Any suggestion or thoughts on this one?
Thank you in advance.
You might like to check how terraform works with an IP address resource
A particulare example (from the top of my head, assuming that the subnetwork (my_subnet) is created in the same terraform batch):
resource "google_compute_address" "my_internal_ip_addr" {
project = "my_target_project_id"
address_type = "INTERNAL"
region = "my_region"
subnetwork = data.google_compute_subnetwork.my_subnet.name
name = "my_ip_address_name"
description = "An internal IP address for my VM"
}
and for a compute engine (ony relevant elements):
resource "google_compute_instance" "my_vm" {
project = "my_target_project_id"
name = "my_vm"
# other items omitted
network_interface {
subnetwork = data.google_compute_subnetwork.my_subnet.name
subnetwork_project = "my_target_project_id"
network_ip = google_compute_address.my_internal_ip_addr.address
access_config {
# Include this section to give the VM an external IP address
}
}
# other items omitted
}
However, I don't know if the above can help you with your ultimate requirement to i can write it in the internal file of the instance and why you need that.

Terraform referenced module has no attributes error

I am trying to use a Palo Alto Networks module to deploy a panorama VM instance to GCP with Terraform. In the example module, I see they create a VPC together with a subnetwork, however, I have an existing VPC I am adding to. So I data source the VPC and create the subnetwork with a module. Upon referencing this subnetwork in my VM instance module, it complains it has no attributes:
Error: Incorrect attribute value type
on ../../../../modules/panorama/main.tf line 67, in resource "google_compute_instance" "panorama":
67: subnetwork = var.subnet
|----------------
| var.subnet is object with no attributes
Here is the subnet code:
data "google_compute_network" "panorama" {
project = var.project_id
name = "fed-il4-p-net-panorama"
}
module "panorama_subnet" {
source = "../../../../modules/subnetwork-module"
subnet_name = "panorama-${var.region_short_name[var.region]}"
subnet_ip = var.panorama_subnet
subnet_region = var.region
project_id = var.project_id
network = data.google_compute_network.panorama.self_link
}
Here is the panorama VM instance code:
module "panorama" {
source = "../../../../modules/panorama"
name = "${var.project_id}-panorama-${var.region_short_name[var.region]}"
project = var.project_id
region = var.region
zone = data.google_compute_zones.zones.names[0]
*# panorama_version = var.panorama_version
ssh_keys = (file(var.ssh_keys))
network = data.google_compute_network.panorama.self_link
subnet = module.panorama <====== I cannot do module.panorama.id or .name here
private_static_ip = var.private_static_ip
custom_image = var.custom_image_pano
#attach_public_ip = var.attach_public_ip
}
Can anyone tell me what I may be doing wrong. Any help would be appreciated. Thanks!
Edit:
parent module for vm instance
resource "google_compute_instance" "panorama" {
name = var.name
zone = var.zone
machine_type = var.machine_type
min_cpu_platform = var.min_cpu_platform
labels = var.labels
tags = var.tags
project = var.project
can_ip_forward = false
allow_stopping_for_update = true
metadata = merge({
serial-port-enable = true
ssh-keys = var.ssh_keys
}, var.metadata)
network_interface {
/*
dynamic "access_config" {
for_each = var.attach_public_ip ? [""] : []
content {
nat_ip = google_compute_address.public[0].address
}
}
*/
network_ip = google_compute_address.private.address
network = var.network
subnetwork = var.subnet
}
I've come across this issue var.xxx is object with [n] attributes multiple times, and 9/10 times it has got to do with wrong referencing of a variable. In your case, in the panorama VM module , you're assigning value of subnet as:
subnet = module.panorama
Now, its not possible to assign a module to an attribute within the module. From your problem statement, i see you're trying to get name attribute assigned to subnet. Try this:
subnet = this.id OR
subnet = this.name
Also, regarding what values can be called, the resources defined in a module are encapsulated, so the calling module cannot access their attributes directly. However, the child module can declare output values to selectively export certain values to be accessed by the calling module.
For example, if the ./panorama module referenced in the example below exported an output value named subnet
module "panorama" {
source = "../../../../modules/panorama"
output "subnet_name" {
value = var.subnet
}
OR WITHOUT SETTING subnet VALUE
output "subnet_name" {
value = var.name
}
then the calling module can reference that result using the expression module.panorama.outputs.subnet_name. Hope this helps

Terraform - How to output input variable?

I have a custom terraform module which create an AWS EC2 instance, so it's relying on the aws provider.
This terraform custom module is used as a base to describes the instance i want to create, but I also need some other information that will be reused later.
For example, i want to define a description to the VM as an input variable, but i don't need to use it at all to create my vm with the aws provider.
I just want this input variable to be sent directly as an output so it can be re-used later once terraform has done its job.
ex
What I have as input variable
variable "description" {
type = string
description = "Description of the instance"
}
what I wanna put as output variable
output "description" {
value = module.ec2_instance.description
}
What my main module is doing
module "ec2_instance" {
source = "./modules/aws_ec2"
ami_id = var.ami_id
instance_name = var.hostname
disk_size = var.disk_size
create_disk = var.create_disk
availability_zone = var.availability_zone
disk_type = var.disk_type
// I don't need the description variable for the module to work, and I don't wanna do anything with it here, i need it later as output
}
I feel stupid because i searched the web for an answer and can't find anything to do that.
Can you help ?
Thanks
EDIT: Added example of code
If you have an input variable declared like this:
variable "description" {
type = string
}
...then you can return its value as an output value like this, in the same module where you declared it:
output "description" {
value = var.description
}

GCP Terraform Forwarding Rule Target

Hey Terraform friends;
Trying to navigate my way through some basic load balancing in the GCP environment. First time doing it, so, still trying to pick up on some of the nuances between the various types and environments.
My goal is to have a target pool of hosts be the destination recipient for connections made to the forwarding rule, in whatever load balancing policy the business needs.
The setup is a bit awkward, because I have the project that I'm doing the work in, but the destination subnetworks are in a shared VPC in another project. Now, according to powers that implemented, the project has permissions to use that subnetwork, which, so far is accurate (I've deployed compute instances to it).
Here's my code:
#target pool
resource "google_compute_target_pool" "target_pool" {
name = "${var.name}-pool"
instances = var.instances
session_affinity = var.session_affinity
}
resource "google_compute_address" "lb_address" {
name = "${var.name}-load-balancer"
address_type = "INTERNAL"
address = "10.129.48.250" //cause fuck it I'm trying to figure it out
subnetwork = data.google_compute_subnetwork.gcp_subnetwork.name
project = var.subnetwork_project
}
#load balancer
resource "google_compute_forwarding_rule" "basic_load_balancer" {
name = var.name
target = google_compute_target_pool.target_pool.id
ip_address = google_compute_address.lb_address.address
port_range = join(",", var.port_range)
labels = var.labels
subnetwork = data.google_compute_subnetwork.gcp_subnetwork.name
project = var.subnetwork_project
load_balancing_scheme = var.lb_scheme
}
With the relevant data:
data "google_compute_subnetwork" "gcp_subnetwork" {
name = var.subnetwork
project = var.subnetwork_project
}
And variables:
variable "name" {
description = "Name of the application usage"
type = string
}
variable "port_range" {
description = "List of ports to load balance"
}
variable "port_range_health" {
description = "List of ports to health check"
type = list(string)
default = [ "" ]
}
variable "instances" {
description = "List of Instances by Zone/Name value"
type = list(string)
}
variable "backup_instances" {
description = "List of Instances by Zone/Name value for backup use"
type = list(string)
default = []
}
variable "session_affinity" {
description = "Load balancer session affinity type"
type = string
default = "NONE"
}
variable "labels" {
description = "Labels to apply to the load balancer"
type = map
default = {}
}
variable "lb_scheme" {
description = "What the LB Forwarding rule is to be used for"
type = string
default = "INTERNAL"
}
variable "subnetwork" {
description = "What network the load balancer should be deployed into"
type = string
}
variable "subnetwork_project" {
description = "Project that contains the subnetwork to deploy into"
type = string
default = ""
}
variable "project" {
description = "Project supplied by user"
type = string
}
My subnetwork project is set to the project id of my shared VPC, and I specify the name of the subnetwork. Instance
And when I try to apply, I keep getting hit with an error message about the structure of the target:
Error: Error creating ForwardingRule: googleapi: Error 400: Invalid value for field 'resource.target': 'projects/insight-dev-272215/regions/us-central1/targetPools/insight-dev-pool'. The URL is malformed. Must be a valid In-Project Target Proxy URL or a supported Google API bundle., invalid
│
│ with module.insight_solr_lb.google_compute_forwarding_rule.basic_load_balancer,
│ on ..\..\..\modules\load_balancer\gcp\basic\main.tf line 29, in resource "google_compute_forwarding_rule" "basic_load_balancer":
│ 29: resource "google_compute_forwarding_rule" "basic_load_balancer" {
│
I've beaten my head around a few times for a few things, but I'm not making much progress. Anyone experienced in the GCP Forwarding rules see my issue?
I've tried to pass the URI of the target group to the target, but it didn't like that either.
Thanks!

Terraform Resource attribute not being removed when passing in empty values

I am working with a GCP Cloud Composer resource and added in a dynamic block to create an attribute for the resource to set allowed_ip_ranges which can be used as an IP filter for accessing the Apache Airflow Web UI.
I was able to get the allowed ranges setup and can update them in place to new values also.
If I attempt to pass in a blank list I am expecting the IP address(es) to be removed as attributes for the resource but Terraform seems to think that no changes are needed.
There is probably something wrong in my code but I am not sure what exactly I would need to do. Does it involve adding in a conditional expression to the for_each loop in the dynamic block?
Child module main.tf
web_server_network_access_control {
dynamic "allowed_ip_range" {
for_each = var.allowed_ip_range
content {
value = allowed_ip_range.value["value"]
description = allowed_ip_range.value["description"]
}
}
}
Child module variables.tf
variable "allowed_ip_range" {
description = "The IP ranges which are allowed to access the Apache Airflow Web Server UI."
type = list(map(string))
default = []
}
Parent module terraform.tfvars
allowed_ip_range = [
{
value = "11.0.0.2/32"
description = "Test dynamic block 1"
},
]
You can set the default value in your variables.tf file:
variable "allowed_ip_range" {
description = "The IP ranges which are allowed to access the Apache Airflow Web Server UI"
type = list(map(string))
default = [
{
value = "0.0.0.0/0"
description = "Allows access from all IPv4 addresses (default value)"
},
{
value = "::0/0"
description = "Allows access from all IPv6 addresses (default value)"
},
]
}
And when you will delete your variable from terraform.tfvars, you will have the default values