locals { is_arm_shape = length(regexall("\\.A", var.oke_node_shape)) > 0 # Detecta se é um shape de nova geração (E5, E4, etc) que exige Gen2 is_gen2_required = length(regexall("\\.E[45]\\.", var.oke_node_shape)) > 0 # Pegamos a lista, ordenamos e revertemos para garantir que a seja a maior # A API do OCI costuma devolver ordenado, mas o sort/reverse garante a lógica latest_k8s_version = reverse(sort(data.oci_containerengine_cluster_option.oke_options.kubernetes_versions))[0] latest_k8s_version_clean = trimprefix(local.latest_k8s_version, "v") # Ex: transforma "1.31.1" em "1.31" para uma busca mais resiliente k8s_major_minor = join(".", slice(split(".", local.latest_k8s_version_clean), 0, 2)) all_sources = data.oci_containerengine_node_pool_option.oke_options.sources oke_images_list = [ for s in local.all_sources : { id = s.image_id name = s.source_name } if length(regexall("Oracle-Linux-8", s.source_name)) > 0 && length(regexall("OKE-${local.k8s_major_minor}", s.source_name)) > 0 && # Filtro robusto de arquitetura (local.is_arm_shape ? length(regexall("aarch64", s.source_name)) > 0 : length(regexall("aarch64", s.source_name)) == 0 ) && length(regexall("GPU", s.source_name)) == 0 && # Exclui imagens para GPU length(regexall("Minimal", s.source_name)) == 0 && # Exclui imagens Minimal # Garante que não pegamos imagens de teste ou versões experimentais length(regexall("Minimal|GPU|Arm", s.source_name)) == (local.is_arm_shape ? 1 : 0) && (local.is_arm_shape ? length(regexall("aarch64", s.source_name)) > 0 : length(regexall("aarch64", s.source_name)) == 0 ) ] # Pega o ID da primeira imagem que sobrou após os filtros # Se a lista estiver vazia, ele não quebra o Terraform, permitindo você ver o erro no plano selected_image_id = length(local.oke_images_list) > 0 ? local.oke_images_list[0].id : "IMAGEM-NAO-ENCONTRADA" selected_image_name = length(local.oke_images_list) > 0 ? local.oke_images_list[0].name : "IMAGEM-NAO-ENCONTRADA" } locals { # !!! Verifique esses parametro antes de implementar e seu ambiente !!! addon_clusterAutoscaler = { authType = { # O tipo de autenticação que o Cluster Autoscaler usa ao fazer solicitações, como um dos seguintes: # - instance: Instance Principal # - workload: Workload identity key = "authType" value = "instance" } nodes = { # Uma lista com número (mínimo:máximo) de nós e o OCID do Node Pool a ser gerenciado pelo cluster autoscaler. # O formato é ::, ::. # !! Formato JSON em texto simples ou codificado em Base64 !! key = "nodes" value = "${var.oke_autoscaler_min_nodes}:${var.oke_autoscaler_max_nodes}:${oci_containerengine_node_pool.cluster_app_node_pool.id}" } scaleDownDelayAfterAdd = { # Quanto tempo depois de ampliar essa avaliação de redução é retomado. (Default:10m) key = "scaleDownDelayAfterAdd" value = "${var.oke_autoscaler_down_delay_after_add}" } scaleDownUnneededTime = { # Por quanto tempo um nó deve ser desnecessário antes de ser elegível para redução. (Default:10m) key = "scaleDownUnneededTime" value = "${var.oke_autoscaler_down_unneeded_time}" } scaleDownUnreadyTime = { # Por quanto tempo um nó não pronto deve ser desnecessário antes de ser elegível para redução. (Default:20m) key = "scaleDownUnreadyTime" value = "${var.oke_autoscaler_down_unready_time}" } v = { # The number for the verbosity of logging. (Default:0) key = "v" value = "0" } skipNodesWithSystemPodsv = { # If true, cluster autoscaler will never delete nodes with pods from kube-system (except for DaemonSet or mirror pods).(Default:true) key = "skipNodesWithSystemPods" value = "${var.oke_autoscaler_skip_nodes_with_system_pods}" } } } locals { # 1. Regras Base (se houver alguma que sempre deve ser criada) base_statements = [ ] # 2. Regras do Split Compartment (condicionais) split_compartment_statements = [ "Allow any-user to manage instances in compartment id ${var.oke_compartment} where all { request.principal.id = '${oci_containerengine_cluster.containerengine_cluster.id}' }", "Allow any-user to use private-ips in compartment id ${data.oci_core_vcn.oke_vcn.compartment_id} where all { request.principal.id = '${oci_containerengine_cluster.containerengine_cluster.id}' }", "Allow any-user to use network-security-groups in compartment id ${data.oci_core_vcn.oke_vcn.compartment_id} where all { request.principal.id = '${oci_containerengine_cluster.containerengine_cluster.id}' }" ] # 3. Regras do Autoscaler (condicionais) autoscaler_statements = var.oke_enable_autoscaler ? [ "Allow dynamic-group ${oci_identity_dynamic_group.oke_nodes_dynamic_group.name} to manage cluster-node-pools in compartment id ${var.oke_compartment}", "Allow dynamic-group ${oci_identity_dynamic_group.oke_nodes_dynamic_group.name} to manage instance-family in compartment id ${var.oke_compartment}", "Allow dynamic-group ${oci_identity_dynamic_group.oke_nodes_dynamic_group.name} to use subnets in compartment id ${data.oci_core_vcn.oke_vcn.compartment_id}" ] : [] # 4. A MÁGICA: Junta tudo em uma lista final # O flatten() garante que tudo vire uma lista simples de strings, ignorando as listas vazias oke_all_policy_statements = flatten([ local.base_statements, local.split_compartment_statements, local.autoscaler_statements ]) } locals { network = { # OCIDs capturados dinamicamente via Data Source gateway = { internet = { id = length(data.oci_core_internet_gateways.igws.gateways) > 0 ? data.oci_core_internet_gateways.igws.gateways[0].id : null } nat = { id = length(data.oci_core_nat_gateways.ngws.nat_gateways) > 0 ? data.oci_core_nat_gateways.ngws.nat_gateways[0].id : null } service = { id = length(data.oci_core_service_gateways.sgws.service_gateways) > 0 ? data.oci_core_service_gateways.sgws.service_gateways[0].id : null all_services = { name = data.oci_core_services.all_services.services[0].name cidr = data.oci_core_services.all_services.services[0].cidr_block } object_storage = { name = data.oci_core_services.object_storage.services[0].name cidr = data.oci_core_services.object_storage.services[0].cidr_block } } } } }