我在Terraform中定义了一个f[a_, b_] := a*b;
g[c_, d_, e_] := c*e[c, d];
g[3, 5, f]
(* 45 *)
,以将事件从import UIKit
class NoBreakSectionCollectionViewLayout: UICollectionViewLayout {
var cachedItemAttributes = [IndexPath: UICollectionViewLayoutAttributes]()
var cachedContentSize = CGSize.zero
override func prepare() {
super.prepare()
calculateAttributes()
}
override func invalidateLayout() {
super.invalidateLayout()
cachedItemAttributes = [:]
calculateAttributes()
}
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
return cachedItemAttributes[indexPath]
}
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
return cachedItemAttributes.filter { rect.intersects($0.value.frame) }.map { $0.value }
}
override var collectionViewContentSize: CGSize {
return cachedContentSize
}
func calculateAttributes() {
var y = CGFloat(0)
var x = CGFloat(0)
var lastHeight = CGFloat(0)
let xSpacing = CGFloat(5)
let ySpacing = CGFloat(2)
if let collectionView = collectionView, let datasource = collectionView.dataSource, let sizeDelegate = collectionView.delegate as? UICollectionViewDelegateFlowLayout {
let sections = datasource.numberOfSections?(in: collectionView) ?? 1
for section in 0..<sections {
for item in 0..<datasource.collectionView(collectionView, numberOfItemsInSection: section){
let indexPath = IndexPath(item: item, section: section)
let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
if let size = sizeDelegate.collectionView?(collectionView, layout: self, sizeForItemAt: indexPath) {
if x > 0 && (x + size.width + xSpacing) > collectionView.bounds.width {
y += size.height + ySpacing
x = CGFloat(0)
}
attributes.frame = CGRect(x: x, y: y, width: size.width, height: size.height)
lastHeight = size.height
x += size.width + xSpacing
}
cachedItemAttributes[indexPath] = attributes
}
}
cachedContentSize = CGSize(width: collectionView.bounds.width, height: y + lastHeight)
}
}
}
发射到lambda。 aws_cloudwatch_event_target
字段是事件参数,例如:
cloudwatch
我想知道如何从外部文件加载input
json数据。
答案 0 :(得分:4)
这里的答案取决于几个不同的问题:
.tf
文件一起签入版本控制,还是在应用过程中动态生成?这两个问题构成了四个不同答案的矩阵:
| Literal Content Include Values from Elsewhere
-------------|----------------------------------------------------------
Static File | file(...) function templatefile(...) function
Dynamic File | local_file data source template_file data source
我将在下面更详细地描述这四个选项。
在所有这些示例中,一个共同的主题是对path.module
的引用,该变量的计算结果是从中加载当前模块的路径。另一种考虑方式是它是包含当前.tf
文件的目录。允许访问其他目录中的文件 ,但是在大多数情况下,通过将数据文件和配置文件保持在一起,使模块中的内容保持独立是适当的。
Terraform字符串是Unicode字符序列,因此Terraform只能读取包含有效UTF-8编码文本的文件。对于JSON来说,这没问题,但要记住其他通常不是UTF-8编码的文件格式。
file
函数 The file
function从磁盘读取文件的文字内容,作为对配置进行初始评估的一部分。为了验证目的,将文件的内容视为是文字字符串值,因此文件必须作为配置的静态部分存在于磁盘上(通常在版本控制中)。 ,而不是在terraform apply
期间动态生成。
resource "aws_cloudwatch_event_target" "data" {
rule = aws_cloudwatch_event_rule.scheduler.name
target_id = "finance_producer_cloudwatch"
arn = aws_lambda_function.finance_data_producer.arn
input = file("${path.module}/input.json")
}
这是最常见和最简单的选项。如果file
功能足以满足您的需求,那么最好将其用作默认选项。
templatefile
函数 The templatefile
function与file
函数类似,但是它不只是按字面意义返回文件内容,而是将文件内容解析为a string template,然后使用一组局部变量对其进行求值在第二个参数中给出。如果您需要从Terraform配置中的其他地方传递一些数据,这将很有用,如以下示例所示:
resource "aws_cloudwatch_event_target" "data" {
rule = aws_cloudwatch_event_rule.scheduler.name
target_id = "finance_producer_cloudwatch"
arn = aws_lambda_function.finance_data_producer.arn
input = templatefile("${path.module}/input.json.tmpl", {
instance_id = aws_instance.example.id
})
}
在input.json.tmpl
中,您可以使用Terraform模板语法替换该变量值:
{"instance_id":${jsonencode(instance_id)}}
在这样的情况下,整个 result 是JSON,我建议只使用jsonencode
生成整个结果,因为这样您就可以让Terraform担心JSON的转义,等等。只需使用Terraform的对象语法编写数据结构:
${jsonencode({
instance_id = instance_id
})}
与file
一样,由于templatefile
是一个函数,因此在配置的初始解码期间会对其进行评估,并将其结果验证为文字值。因此,模板文件还必须是作为配置的一部分分发的静态文件,而不是动态生成的文件。
local_file
数据源 Data sources是特殊的资源类型,用于读取现有对象或计算结果,而不是创建和管理新对象。因为它们是资源,所以它们可以参与依赖关系图,从而可以利用在terraform apply
期间由同一Terraform配置中的其他资源创建的对象(包括本地文件)。
The local_file
data source属于the local
provider,本质上是与file
函数等效的数据源。
在以下示例中,我使用var.input_file
作为占位符,以引用由相同配置中的其他资源创建的文件路径。在一个真实的示例中,最有可能直接引用资源的属性。
data "local_file" "input" {
filename = var.input_file
}
resource "aws_cloudwatch_event_target" "data" {
rule = aws_cloudwatch_event_rule.scheduler.name
target_id = "finance_producer_cloudwatch"
arn = aws_lambda_function.finance_data_producer.arn
input = data.local_file.input.content
}
template_file
数据源 The template_file
data source是等效于templatefile
函数的数据源。它的用法类似于local_file
,尽管在这种情况下,我们根据模板是否使用来使用file
函数或local_file
来将模板读取为静态文件,从而填充模板本身位于静态文件或动态生成的文件中,尽管如果它是静态文件,我们希望使用templatefile
函数,因此我们将在此处使用local_file
数据源:>
data "local_file" "input_template" {
filename = var.input_template_file
}
data "template_file" "input" {
template = data.local_file.input_template.content
vars = {
instance_id = aws_instance.example.id
}
}
resource "aws_cloudwatch_event_target" "data" {
rule = aws_cloudwatch_event_rule.scheduler.name
target_id = "finance_producer_cloudwatch"
arn = aws_lambda_function.finance_data_producer.arn
input = data.template_file.input.rendered
}
templatefile
函数是在Terraform 0.12.0中添加的,因此您可能会在其他地方看到使用template_file
数据源呈现静态模板文件的示例。这是一个旧模式,现在在Terraform 0.12中已弃用,因为在大多数情况下,templatefile
函数使配置更加直接和可读。
与template_file
函数相对,templatefile
数据源的一个怪癖是该数据源属于the template
provider而不是Terraform Core,因此,哪些模板功能可用于它取决于安装的提供程序版本,而不是安装的Terraform CLI版本。 template
提供程序在可用模板语言功能方面可能会落后于Terraform Core,这是在可能的情况下更喜欢templatefile
函数的另一个原因。
这个问题专门用于从文件中读取数据,但出于完整性考虑,我还想指出,对于小型JSON有效负载,有时最好将其直接内联为Terraform数据结构,并以{ {3}},就像这样:
resource "aws_cloudwatch_event_target" "data" {
rule = aws_cloudwatch_event_rule.scheduler.name
target_id = "finance_producer_cloudwatch"
arn = aws_lambda_function.finance_data_producer.arn
input = jsonencode({
instance_id = aws_instance.example.id
})
}
将数据结构作为Terraform表达式内联编写意味着将来的读者可以直接看到将要发送的内容,而无需引用单独的文件。但是,如果数据结构非常庞大和复杂,则内联包含它会损害整体可读性,因为它可能使同一文件中的其他配置不堪重负。
因此,选择哪个选项在很大程度上取决于特定的情况,但始终值得考虑的是,单独文件的间接访问是否是可读性最好的选择。
Terraform还具有jsonencode
(在撰写本文时进行实验),可以直接在.tf
文件内部或外部模板的插值序列中对YAML格式的数据结构进行类似的处理。
答案 1 :(得分:0)
您可以使用file()
operator从外部文件中提取数据:
input = "${file("myjson.json")}"
只需确保myjson.json
与其余Terraform文件位于同一目录的磁盘上。
答案 2 :(得分:0)
我将使用数据template_file资源。像这样...
data "template_file" "my_file" {
template = "${file("${path.module}/my_file.json")}"
vars = {
var_to_use_in_file = "${var.my_value}"
}
}
然后在您的资源块中。...
resource "aws_cloudwatch_event_target" "data" {
rule = "${aws_cloudwatch_event_rule.scheduler.name}"
target_id = "finance_producer_cloudwatch"
arn = "${aws_lambda_function.finance_data_producer.arn}"
input = "${data.template_file.my_file.rendered}"
}