Условное создание некоторых элементов ресурсов на основе переменных в Terraform?

Я изучаю Terraform для автоматического создания правил NAT на брандмауэре Пало-Альто, используя ресурс panos_nat_rule_group.

Правило NAT имеет несколько вариантов «Переведенного пакета». Мы можем преобразовать IP-адрес «Источника» и/или «Назначения» пакета. Кроме того, существует несколько вариантов перевода этих IP-адресов.

Можно ли создать переменную, включающую все возможные параметры, например:

variable natRules {
    description = "Variable for the NAT rules"
    type = list(object({
        name                    = string
        description             = string
        audit_comment           = string

        original_packet   = object({
            source_zones            = list(string)
            destination_zone        = string
            destination_interface   = string
            service                 = string
            source_addresses        = list(string)
            destination_addresses   = list(string)
        })

        translated_packet = object({
            source = object({
                static_ip = object({
                    translated_address = string
                    bi_directional = bool
                })
                dynamic_ip_and_port = object({
                    translated_address = object({
                        translated_addresses = list(string)
                    })
                    interface_address = object({
                        interface = string
                        ip_address = string
                    })
                })
                dynamic_ip = object({
                    translated_addresses = list(string)
                })
            })
            destination = object({
                static_translation = object({
                    address = string
                    port = number
                })
                dynamic_translation = object({
                    address = string
                    port = number
                    distribution = string
                })
            })
        })
    }))
}

Затем в «terraform.tfvars» поместите значения различных правил NAT, но заполняйте только то, что необходимо для конкретного правила. Например, если мы хотим преобразовать только исходный IP-адрес в определенный статический IP-адрес, чтобы заполнить в переменной только необходимые объекты, а остальные оставить пустыми. Если мы хотим сделать еще один перевод, снова поместите только необходимые значения.

natRules = [
    {
        name                    = "Static-IP-Port"
        description             = "Test nat rule"
        audit_comment           = ""

        original_packet = {
            source_zones            = ["Inside"]
            destination_zone        = "Outside"
            destination_interface   = "any"
            service                 = "any"
            source_addresses        = ["any"]
            destination_addresses   = ["any"]
        }

        translated_packet = {
            source = {
                static_ip = {
                    translated_address = "10.1.1.1"
                    bi_directional = false
                }
                dynamic_ip_and_port = {
                    translated_address = {
                        translated_addresses = [""]
                    }
                    interface_address = {
                        interface = ""
                        ip_address = ""
                    }
                }
                dynamic_ip = {
                    translated_addresses = [""]
                }
            }
            destination = {
                static_translation = {
                    address = ""
                    port = null
                }
                dynamic_translation = {
                    address = ""
                    port = null
                    distribution = ""
                }
            }
        }
    },
    {
        name                    = "Dynamic-IP-Port"
        description             = "Test nat rule"
        audit_comment           = ""

        original_packet = {
            source_zones            = ["Inside"]
            destination_zone        = "Outside"
            destination_interface   = "any"
            service                 = "any"
            source_addresses        = ["any"]
            destination_addresses   = ["any"]
        }

        translated_packet = {
            source = {
                static_ip = {
                    translated_address = ""
                    bi_directional = false
                }
                dynamic_ip_and_port = {
                    translated_address = {
                        translated_addresses = [""]
                    }
                    interface_address = {
                        interface = "ethernet1/1"
                        ip_address = "11.11.11.1/24"
                    }
                }
                dynamic_ip = {
                    translated_addresses = [""]
                }
            }
            destination = {
                static_translation = {
                    address = ""
                    port = null
                }
                dynamic_translation = {
                    address = ""
                    port = null
                    distribution = ""
                }
            }
        }
    }
]

Затем в main.tf должен быть только один ресурс, который будет проверять, какие переменные установлены, и на основе этого применять только эту часть ресурса. Какую условную проверку можно реализовать?

resource "panos_nat_rule_group" "CreateNATRules" {
    dynamic "rule" {
        for_each = var.natRules

        content {
            name                      = rule.value.name
            description               = rule.value.description
            audit_comment             = rule.value.audit_comment

            original_packet {
                source_zones          = rule.value.original_packet.source_zones
                destination_zone      = rule.value.original_packet.destination_zone
                destination_interface = rule.value.original_packet.destination_interface
                service               = rule.value.original_packet.service
                source_addresses      = rule.value.original_packet.source_addresses
                destination_addresses = rule.value.original_packet.destination_addresses               
            }

            translated_packet {
                source {
                    static_ip {
                        translated_address = rule.value.translated_packet.source.static_ip.translated_address
                        bi_directional = rule.value.translated_packet.source.static_ip.bi_directional
                    }
                    dynamic_ip_and_port {
                        interface_address {
                            interface = rule.value.translated_packet.source.dynamic_ip_and_port.interface_address.interface
                            ip_address = rule.value.translated_packet.source.dynamic_ip_and_port.interface_address.ip_address
                        }
                    }
                    dynamic_ip {
                        translated_addresses  = rule.value.translated_packet.source.dynamic_ip.translated_addresses 
                    }

                }
                destination {
                    }
            }  

        }
        
    }

    lifecycle {
        create_before_destroy = true
    }
}
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
54
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

В определении типа переменной добавьте необязательный модификатор к атрибутам объектов, которые не требуются в каждом сценарии, со значением по умолчанию, установленным на null.

Затем в tfvars укажите только те значения, которые необходимы в конкретном случае использования. Не задавайте им пустые строки, не указывайте их вообще.

На уровне ресурса используйте вложенные динамические блоки с условием в операторе for_each для перевода только необходимых значений:

for_each = <SOME_OBJECT_ATTRIBUTE> != null ? {SOME_MAP_FROM_VAR} : {}

Пустой {} означает ничего не делать, если результат условия ложный.

Спасибо, это помогло!

variable natRules {
    type = list(object({
        name                    = string
        description             = string
        audit_comment           = string

        original_packet   = object({
            source_zones            = list(string)
            destination_zone        = string
            destination_interface   = string
            service                 = string
            source_addresses        = list(string)
            destination_addresses   = list(string)
        })

        translated_packet = object({
            source = object({
                static_ip = optional(object({
                    translated_address = string
                    bi_directional = bool
                }))
                dynamic_ip_and_port = optional(object({
                    translated_address = optional(object({
                        translated_addresses = list(string)
                    }))
                    interface_address = optional(object({
                        interface = string
                        ip_address = string
                    }))
                }))
                dynamic_ip = optional(object({
                    translated_addresses = list(string)
                }))
            })
            destination = object({
                static_translation = optional(object({
                    address = string
                    port = optional(number)
                }))
                dynamic_translation = optional(object({
                    address = string
                    port = optional(number)
                    distribution = string
                }))
            })
        })
    }))
}
resource "panos_nat_rule_group" "CreateNATRules" {
    dynamic "rule" {
        for_each = var.natRules
        content {
            name                      = rule.value.name
            description               = rule.value.description
            audit_comment             = rule.value.audit_comment

            original_packet {
                source_zones          = rule.value.original_packet.source_zones
                destination_zone      = rule.value.original_packet.destination_zone
                destination_interface = rule.value.original_packet.destination_interface
                service               = rule.value.original_packet.service
                source_addresses      = rule.value.original_packet.source_addresses
                destination_addresses = rule.value.original_packet.destination_addresses               
            }

            translated_packet {
                source {
                    dynamic "static_ip" {
                        for_each = rule.value.translated_packet.source.static_ip != null ? [rule.value.translated_packet.source.static_ip] : []
                        content {
                            translated_address = static_ip.value.translated_address
                            bi_directional     = static_ip.value.bi_directional
                        }
                    }

                    dynamic "dynamic_ip_and_port" {
                        for_each = rule.value.translated_packet.source.dynamic_ip_and_port != null ? [rule.value.translated_packet.source.dynamic_ip_and_port] : []
                        content {
                            dynamic "translated_address" {
                                for_each = rule.value.translated_packet.source.dynamic_ip_and_port.translated_address != null ? [rule.value.translated_packet.source.dynamic_ip_and_port.translated_address] : []
                                content {
                                    translated_addresses = dynamic_ip_and_port.value.translated_address.translated_addresses
                                }
                            }
                            dynamic "interface_address" {
                                for_each = rule.value.translated_packet.source.dynamic_ip_and_port.interface_address != null ? [rule.value.translated_packet.source.dynamic_ip_and_port.interface_address] : []
                                content {
                                    interface = dynamic_ip_and_port.value.interface_address.interface
                                    ip_address = dynamic_ip_and_port.value.interface_address.ip_address
                                }
                            }
                        }
                    }

                    dynamic "dynamic_ip" {
                        for_each = rule.value.translated_packet.source.dynamic_ip != null ? [rule.value.translated_packet.source.dynamic_ip] : []
                        content {
                          translated_addresses = dynamic_ip.value.translated_addresses
                        }
                    }
                }
                
                destination {
                    dynamic "static_translation" {
                        for_each = rule.value.translated_packet.destination.static_translation != null ? [rule.value.translated_packet.destination.static_translation] : []
                        content {
                            address         = static_translation.value.address
                            port            = static_translation.value.port
                        }
                    }

                    dynamic "dynamic_translation" {
                        for_each = rule.value.translated_packet.destination.dynamic_translation != null ? [rule.value.translated_packet.destination.dynamic_translation] : []
                        content {
                            address         = dynamic_translation.value.address
                            port            = dynamic_translation.value.port
                            distribution    = dynamic_translation.value.distribution
                        }
                    }
                }
            }
        }
    }
}

Другие вопросы по теме