Terraform templatefile

huangapple go评论66阅读模式
英文:

Terraform templatefile

问题

I've translated the code for you:

下面的代码正在工作。我想将模板内容放在一个单独的文件中,而不是在main.tf中。我尝试使用templatefile方法,但没有成功。
最后,我展示了我尝试过的内容。也许是我设置metric_info变量的方式有问题,或者在实现templatefile函数之后需要重新构建模板。

main.tf:

locals {

基本变量

base_vars = yamldecode(file("env/${var.working_env}/vars.yaml")) # TF_VAR_working_env

指标子文件夹名称

metrics = distinct([
for dir_path in fileset("../metrics-table/", "//") :
basename(dirname(dir_path))
])

指标配置

metrics_config = flatten([
for subfolder in local.metrics :
[
for file in fileset("../metrics-table/${subfolder}", "metrics.yaml") :
merge(yamldecode(file("../metrics-table/${subfolder}/${file}")), { subfolder = subfolder })
]
])

指标信息

metric_info = [
{
metrics = merge([
for metric_config in local.metrics_config :
{
for metric_name, metric_data in metric_config.metrics :
metric_name => {
name = metric_data.name
metric_table = metric_config.metric_table
numerator = metric_data.numerator
denominator = metric_data.denominator
}
}
]...)
}
]

}

ALL_METRICS.SQL模板

data "template_file" "all_metrics_sql" {
template = <<EOT

SQL文件的第一部分

-- SQL文件的第一部分开始
WITH
%{ for metric_info in local.metric_info }
%{ for metric_name, metric_data in metric_info.metrics }
${metric_name} AS (
SELECT
date,
'${metric_name}' AS metric_name,
experiment,
alternative,
context_id,
control,
CASE
WHEN version IS NULL THEN 'v1'
ELSE version
END AS version,
device_group,
platform,
SUM(${metric_data.denominator}) AS denominator,
SUM(${metric_data.numerator}) AS numerator,
SAFE_DIVIDE(SUM(${metric_data.numerator}), SUM(${metric_data.denominator})) AS metric_value
FROM ${local.base_vars.project}.ab_experiment_metrics.${metric_data.metric_table}
WHERE outlier = FALSE
GROUP BY
date,
experiment,
alternative,
context_id,
control,
version,
device_group,
platform,
metric_name
),

%{ endfor }
%{ endfor }

-- SQL文件的第一部分结束

SQL文件的第二部分

-- SQL文件的第二部分开始
all_metrics AS (
SELECT * FROM conversion_rate
%{ for metric_info in local.metric_info }
%{ for metric_name, _ in metric_info.metrics }
UNION ALL
SELECT * FROM ${metric_name}
%{ endfor }
%{ endfor }
),
all_metrics_final as
(
SELECT
date,
metric_name,
all_metrics.experiment,
alternative,
control,
version,
device_group,
platform,
denominator,
SUM(denominator) OVER (PARTITION BY metric_name, all_metrics.experiment, alternative, version, device_group, platform ORDER BY date ASC ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS denominator_cumsum,
numerator,
SUM(numerator) OVER (PARTITION BY metric_name, all_metrics.experiment, alternative, version, device_group, platform ORDER BY date ASC ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS numerator_cumsum,
metric_value
FROM all_metrics
)

SELECT *
FROM all_metrics_final
-- SQL文件的第二部分结束
EOT
}

创建ALL_METRICS.SQL文件

resource "local_file" "all_metrics_sql" {
filename = "all_metrics.sql"
content = data.template_file.all_metrics_sql.rendered
}

输出

output "metrics_config" {
value = local.metrics_config
}

output "metric_info" {
value = local.metric_info
}

output "all_metrics_sql_content" {
value = data.template_file.all_metrics_sql.rendered
}


对于以下代码片段的尝试,您可以尝试以下方法,但请注意修复模板的语法错误:

```text
data "template_file" "all_metrics_sql" {
  template = templatefile("${path.module}/template.tftpl", {
    metric_info = local.metric_info.metrics
  })
}

请注意,您需要确保模板文件${path.module}/template.tftpl存在并具有正确的语法。如果还有其他错误,请提供详细信息以获取更多帮助。

英文:

The code below is working. I would like the template content to be in a separate file and not within main.tf. I tried using the templatefile method but without success.
At the end I show what I tried. Maybe it's the way I set up the metric_info variable, or it's necessary to reformulate the template after I implement the templatefile function.

main.tf:

locals {
  # Base variables 
  base_vars = yamldecode(file(&quot;env/${var.working_env}/vars.yaml&quot;)) # TF_VAR_working_env

  # Metrics subfolder names
  metrics = distinct([
    for dir_path in fileset(&quot;../metrics-table/&quot;, &quot;*/*/&quot;) :
    basename(dirname(dir_path))
  ])

  # Metrics configuration 
  metrics_config = flatten([
    for subfolder in local.metrics :
    [
      for file in fileset(&quot;../metrics-table/${subfolder}&quot;, &quot;metrics.yaml&quot;) :
      merge(yamldecode(file(&quot;../metrics-table/${subfolder}/${file}&quot;)), { subfolder = subfolder })
    ]
  ])

  # Metrics info
  metric_info = [
    {
      metrics = merge([
        for metric_config in local.metrics_config :
        {
          for metric_name, metric_data in metric_config.metrics :
          metric_name =&gt; {
            name          = metric_data.name
            metric_table  = metric_config.metric_table
            numerator     = metric_data.numerator
            denominator   = metric_data.denominator
          }
        }
        ]...)
    }
  ]

}

#  TEMPLATE ALL_METRICS.SQL

data &quot;template_file&quot; &quot;all_metrics_sql&quot; {
  template = &lt;&lt;EOT
# Parte 1 do arquivo SQL
-- BEGIN Parte 1 do arquivo SQL
WITH
%{ for metric_info in local.metric_info }
  %{ for metric_name, metric_data in metric_info.metrics }
    ${metric_name} AS (
      SELECT
        date,
        &#39;${metric_name}&#39; AS metric_name,
        experiment,
        alternative,
        context_id,
        control,
        CASE
          WHEN version IS NULL THEN &#39;v1&#39;
          ELSE version
        END AS version,
        device_group,
        platform,
        SUM(${metric_data.denominator}) AS denominator,
        SUM(${metric_data.numerator}) AS numerator,
        SAFE_DIVIDE(SUM(${metric_data.numerator}), SUM(${metric_data.denominator})) AS metric_value
      FROM `${local.base_vars.project}.ab_experiment_metrics.${metric_data.metric_table}`
      WHERE outlier = FALSE
      GROUP BY
        date,
        experiment,
        alternative,
        context_id,
        control,
        version,
        device_group,
        platform,
        metric_name
    ),
      
  %{ endfor }
%{ endfor }

-- END Parte 1 do arquivo SQL

# Parte 2 do arquivo SQL
-- BEGIN Parte 2 do arquivo SQL
all_metrics AS (
    SELECT * FROM conversion_rate
    %{ for metric_info in local.metric_info }
        %{ for metric_name, _ in metric_info.metrics }
            UNION ALL
            SELECT * FROM ${metric_name}
        %{ endfor }
    %{ endfor }
),
all_metrics_final as
(
    SELECT
        date,
        metric_name,
        all_metrics.experiment,
        alternative,
        control,
        version,
        device_group,
        platform,
        denominator,
        SUM(denominator) OVER (PARTITION BY metric_name, all_metrics.experiment, alternative, version, device_group, platform ORDER BY date ASC ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS denominator_cumsum,
        numerator,
        SUM(numerator) OVER (PARTITION BY metric_name, all_metrics.experiment, alternative, version, device_group, platform ORDER BY date ASC ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS numerator_cumsum,
        metric_value
    FROM all_metrics
)

SELECT *
FROM all_metrics_final
-- END Parte 2 do arquivo SQL
EOT
}

# CREATE ALL_METRICS.SQL

resource &quot;local_file&quot; &quot;all_metrics_sql&quot; {
  filename = &quot;all_metrics.sql&quot;
  content  = data.template_file.all_metrics_sql.rendered
}



#   OUTPUTS
output &quot;metrics_config&quot; {
  value = local.metrics_config
}

output &quot;metric_info&quot; {
  value = local.metric_info
}

output &quot;all_metrics_sql_content&quot; {
  value = data.template_file.all_metrics_sql.rendered
}
Changes to Outputs:
  + metric_info    = [
      + {
          + metrics = {
              + time_to_first_play_per_login    = {
                  + denominator  = &quot;experiment_login_count&quot;
                  + metric_table = &quot;time_to_first_play&quot;
                  + name         = &quot;time_to_first_play_per_login&quot;
                  + numerator    = &quot;total_time_to_first_play&quot;
                }
              + time_to_first_play_per_session  = {
                  + denominator  = &quot;experiment_session_count&quot;
                  + metric_table = &quot;time_to_first_play&quot;
                  + name         = &quot;time_to_first_play_per_session&quot;
                  + numerator    = &quot;total_time_to_first_play&quot;
                }
              + time_to_first_play_per_user     = {
                  + denominator  = &quot;experiment_user_count&quot;
                  + metric_table = &quot;time_to_first_play&quot;
                  + name         = &quot;time_to_first_play_per_user&quot;
                  + numerator    = &quot;total_time_to_first_play&quot;
                }
              + time_to_second_play_per_creator = {
                  + denominator  = &quot;experiment_user_count&quot;
                  + metric_table = &quot;time_to_second_play&quot;
                  + name         = &quot;time_to_second_play_per_user&quot;
                  + numerator    = &quot;total_time_to_second_play&quot;
                }
              + time_to_second_play_per_login   = {
                  + denominator  = &quot;experiment_user_count&quot;
                  + metric_table = &quot;time_to_second_play&quot;
                  + name         = &quot;time_to_second_play_per_user&quot;
                  + numerator    = &quot;total_time_to_second_play&quot;
                }
              + time_to_second_play_per_name    = {
                  + denominator  = &quot;experiment_session_count&quot;
                  + metric_table = &quot;time_to_second_play&quot;
                  + name         = &quot;time_to_second_play_per_session&quot;
                  + numerator    = &quot;total_time_to_second_play&quot;
                }
            }
        },
    ]
  + metrics_config = [
      + {
          + metric_table = &quot;time_to_first_play&quot;
          + metrics      = {
              + time_to_first_play_per_login   = {
                  + active         = 1
                  + category       = &quot;M&#233;trica de v&#237;deo&quot;
                  + denominator    = &quot;experiment_login_count&quot;
                  + description    = &quot;Tempo m&#233;dio que cada usu&#225;rio leva para dar o primeiro play em algum v&#237;deo&quot;
                  + metric_title   = &quot;Tempo para o Primeiro Play por Usu&#225;rio&quot;
                  + metric_type_id = 2
                  + name           = &quot;time_to_first_play_per_login&quot;
                  + numerator      = &quot;total_time_to_first_play&quot;
                }
              + time_to_first_play_per_session = {
                  + active         = 1
                  + category       = &quot;M&#233;trica de v&#237;deo&quot;
                  + denominator    = &quot;experiment_session_count&quot;
                  + description    = &quot;Tempo m&#233;dio que cada sess&#227;o leva para dar o primeiro play em algum v&#237;deo&quot;
                  + metric_title   = &quot;Tempo para o Primeiro Play por Sess&#227;o&quot;
                  + metric_type_id = 2
                  + name           = &quot;time_to_first_play_per_session&quot;
                  + numerator      = &quot;total_time_to_first_play&quot;
                }
              + time_to_first_play_per_user    = {
                  + active         = 1
                  + category       = &quot;M&#233;trica de v&#237;deo&quot;
                  + denominator    = &quot;experiment_user_count&quot;
                  + description    = &quot;Tempo m&#233;dio que cada usu&#225;rio leva para dar o primeiro play em algum v&#237;deo&quot;
                  + metric_title   = &quot;Tempo para o Primeiro Play por Usu&#225;rio&quot;
                  + metric_type_id = 2
                  + name           = &quot;time_to_first_play_per_user&quot;
                  + numerator      = &quot;total_time_to_first_play&quot;
                }
            }
          + subfolder    = &quot;time_to_first_play&quot;
        },
      + {
          + metric_table = &quot;time_to_second_play&quot;
          + metrics      = {
              + time_to_second_play_per_creator = {
                  + active         = 1
                  + category       = &quot;M&#233;trica de v&#237;deo&quot;
                  + denominator    = &quot;experiment_user_count&quot;
                  + description    = &quot;Tempo m&#233;dio que cada usu&#225;rio leva para dar o primeiro play em algum v&#237;deo&quot;
                  + metric_title   = &quot;Tempo para o Primeiro Play por Usu&#225;rio&quot;
                  + metric_type_id = 2
                  + name           = &quot;time_to_second_play_per_user&quot;
                  + numerator      = &quot;total_time_to_second_play&quot;
                }
              + time_to_second_play_per_login   = {
                  + active         = 1
                  + category       = &quot;M&#233;trica de v&#237;deo&quot;
                  + denominator    = &quot;experiment_user_count&quot;
                  + description    = &quot;Tempo m&#233;dio que cada usu&#225;rio leva para dar o primeiro play em algum v&#237;deo&quot;
                  + metric_title   = &quot;Tempo para o Primeiro Play por Usu&#225;rio&quot;
                  + metric_type_id = 2
                  + name           = &quot;time_to_second_play_per_user&quot;
                  + numerator      = &quot;total_time_to_second_play&quot;
                }
              + time_to_second_play_per_name    = {
                  + active         = 1
                  + category       = &quot;M&#233;trica de v&#237;deo&quot;
                  + denominator    = &quot;experiment_session_count&quot;
                  + description    = &quot;Tempo m&#233;dio que cada sess&#227;o leva para dar o primeiro play em algum v&#237;deo&quot;
                  + metric_title   = &quot;Tempo para o Primeiro Play por Sess&#227;o&quot;
                  + metric_type_id = 2
                  + name           = &quot;time_to_second_play_per_session&quot;
                  + numerator      = &quot;total_time_to_second_play&quot;
                }
            }
          + subfolder    = &quot;time_to_second_play&quot;
        },
    ]

I tried to use the method below but return erros.

data &quot;template_file&quot; &quot;all_metrics_sql&quot; {
  template = templatefile(&quot;${path.module}/template.tftpl&quot;, {
    metric_info = local.metric_info.metrics
  })
}
╷
│ Error: Not enough function arguments
│ 
│   on main.tf line 69, in data &quot;template_file&quot; &quot;all_metrics_sql&quot;:
│   69:   template = templatefile(&quot;arquivo_template.tpl&quot;)
│ 
│ Function &quot;templatefile&quot; expects 2 argument(s). Missing value for
│ &quot;vars&quot;.
╵
╷
│ Error: Unsupported attribute
│ 
│   on main.tf line 72, in data &quot;template_file&quot; &quot;all_metrics_sql&quot;:
│   72:     metric_info = local.metric_info.metrics
│     ├────────────────
│     │ local.metric_info is tuple with 1 element
│ 
│ This value does not have any attributes.

答案1

得分: 2

You are using both the deprecated template_file data source and the templatefile function at the same time. These both perform the same operation, so it is incorrect to use them together.

你同时使用了已弃用的 template_file 数据源 templatefile 函数。它们都执行相同的操作,因此不应该同时使用它们。

You can use the templatefile function alone. You should never need to use the template_file data source in modern Terraform; it exists to support very old versions of Terraform that didn't have the templatefile function yet.

你可以单独使用 templatefile 函数。在现代 Terraform 中,你不应该再使用 template_file 数据源;它存在是为了支持旧版本的 Terraform,这些版本尚未引入 templatefile 函数。

The above assigns the result of template rendering directly to a resource argument, which is a concise way to write it when you only need the template result in one part of your configuration. If you want to reuse that template result in multiple locations then you can optionally assign its result to a local value:

上面的代码将模板渲染的结果直接分配给资源参数,这是在你的配置中只需在一个部分中使用模板结果时的简洁写法。如果你想在多个位置重用该模板结果,你可以选择将其结果分配给 本地值

英文:

You are using both the deprecated template_file data source and the templatefile function at the same time. These both perform the same operation, so it is incorrect to use them together.

You can use the templatefile function alone. You should never need to use the template_file data source in modern Terraform; it exists to support very old versions of Terraform that didn't have the templatefile function yet.

resource &quot;local_file&quot; &quot;all_metrics_sql&quot; {
  filename = &quot;all_metrics.sql&quot;
  content = templatefile(&quot;${path.module}/template.tftpl&quot;, {
    metric_info = local.metric_info.metrics
  })
}

The above assigns the result of template rendering directly to a resource argument, which is a concise way to write it when you only need the template result in one part of your configuration. If you want to reuse that template result in multiple locations then you can optionally assign its result to a local value:

locals {
  all_metrics_sql = templatefile(&quot;${path.module}/template.tftpl&quot;, {
    metric_info = local.metric_info.metrics
  })
}

resource &quot;local_file&quot; &quot;all_metrics_sql&quot; {
  filename = &quot;all_metrics.sql&quot;
  content  = local.all_metrics_sql
}

huangapple
  • 本文由 发表于 2023年6月26日 23:05:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/76557929.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定