- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
《Terraform 101 从入门到实践》这本小册在 南瓜慢说官方网站 和 GitHub 两个地方同步更新,书中的示例代码也是放在GitHub上,方便大家参考查看.
介绍了Terraform一些比较基础的概念后,我们可以先了解一下Terraform的语法,也就是HCL的语法.
变量是实现代码复用的一种方式,同样的代码不同的变量往往会有不同的效果。而在Terraform里,有一个概念非常重要,就是变量都是从属于模块的。变量无法跨模块引用。即在模块A定义的变量X,无法在模块B中直接引用。但父模块的变量,可以作为子模块的入参;而子模块的输出变量可以被父模块获取.
跟任何编程语言一样,变量都是有类型的,Terraform的变量类型从语言的角度可分为两大类:基本类型和组合类型,具体如下:
基本类型:
"pkslow.com"
319
或 5.11
true
组合类型:
["dev", "uat", "prod"]
set(...)
{name="Larry", age="18"}
如果不想指定某个类型,可以用 any 来表示任意类型;或者不指定,默认为任意类型.
从功能角度来看,变量可以分为输入变量、输出变量和本地变量.
输入变量是模块接收外部变量的方式,它定义在 variable 块中,如下:
variable "image_id" {
type = string
}
variable "availability_zone_names" {
type = list(string)
default = ["us-west-1a"]
}
variable "docker_ports" {
type = list(object({
internal = number
external = number
protocol = string
}))
default = [
{
internal = 8300
external = 8300
protocol = "tcp"
}
]
}
输出变量定义了一个模块对外返回的变量,通过 output 块来定义,如下:
output "instance_ip_addr" {
value = aws_instance.server.private_ip
}
本地变量是模块内定义且可引用的临时变量,在 locals 块中定义,如下:
locals {
service_name = "forum"
owner = "Community Team"
}
输入变量是定义在 variable 块中的,它就像是函数的入参.
定义 variable 有很多可选属性:
false
; true
。 所有属性都显性指定如下面例子所示:
variable "env" {
type = string
default = "dev"
description = "environment name"
sensitive = false
nullable = false
validation {
condition = contains(["dev", "uat", "prod"], var.env)
error_message = "The env must be one of dev/uat/prod."
}
}
这个变量名为 env ,表示环境名,默认值为 dev ,这个值必须为 dev 、 uat 和 prod 中的其中一个。如果输出一个非法的值,会报错:
$ terraform plan -var="env=sit"
╷
│ Error: Invalid value for variable
│
│ on input.tf line 1:
│ 1: variable "env" {
│
│ The env must be one of dev/uat/prod.
只有定义了变量才可以使用,使用的方式是 var.name 。比如这里定义了两个变量 env 和 random_string_length :
variable "env" {
type = string
default = "dev"
}
variable "random_string_length" {
type = number
default = 10
}
则使用如下:
resource "random_string" "random" {
length = var.random_string_length
lower = true
special = false
}
locals {
instance_name = "${var.env}-${random_string.random.result}"
}
output "instance_name" {
value = local.instance_name
}
要从外部传入变量到根模块,有多种方式,常见的有以下几种,按优先级从低到高:
环境变量 export TF_VAR_image_id=ami-abc123 。
terraform.tfvars 文件; 。
terraform.tfvars.json 文件; 。
*.auto.tfvars 或 *.auto.tfvars.json 文件; 。
命令行参数 -var 传入一个变量;命令行参数 -var-file 传入一个变量的集合文件; 。
在实践中,最常用的还是通过命令行来传入参数,因为一般需要指定不同环境的特定变量,所以会把变量放到文件中,然后通过命令行指定特定环境的主文件:
$ terraform apply -var="env=uat"
$ terraform apply -var-file="prod.tfvars"
而 prod.tfvars 的内容如下:
env = "prod"
random_string_length = 12
我们可以定义 dev.tfvars 、 uat.tfvars 和 prod.tfvars 等,要使用不同环境的变量就直接改变文件名即可.
有输入就有输出,输出变量就像是模块的返回值,比如我们调用一个模块去创建一台服务,那就要获取服务的IP,这个IP事先是不知道,它是服务器创建完后的结果之一。输出变量有以下作用:
remote state
的方式共享给其它Terraform配置,作为数据源。 输出变量需要定义在 output 块中,如下:
output "instance_ip_addr" {
value = aws_instance.server.private_ip
}
这个 value 可以是reource的属性,也可以是各种变量计算后的结果。只要在执行apply的时候才会去计算输出变量,像plan是不会执行计算的.
还可以定义输出变量的一些属性:
description
:输出变量的描述,说明清楚这个变量是干嘛的; sensitive
:如果是 true
,就不会在控制台打印出来; depends_on
:显性地定义依赖关系。 完整的定义如下:
output "instance_ip_addr" {
value = aws_instance.server.private_ip
description = "The private IP address of the main server instance."
sensitive = false
depends_on = [
# Security group rule must be created before this IP address could
# actually be used, otherwise the services will be unreachable.
aws_security_group_rule.local_access,
]
}
引用输出变量很容易,表达式为 module.<module name>.<output name> ,如果前面的输出变量定义在模块 pkslow_server 中,则引用为: module.pkslow_server.instance_ip_addr .
本地变量有点类似于其它语言代码中的局部变量,在Terraform模块中,它的一个重要作用是避免重复计算一个值.
locals {
instance_name = "${var.env}-${random_string.random.result}-${var.suffix}"
}
这里定义了一个本地变量 instance_name ,它的值是一个复杂的表达式。这时我们可以通过 local.xxx 的形式引用,而不用再写复杂的表达式了。如下:
output "instance_name" {
value = local.instance_name
}
这里要特别注意:定义本地变量的关键字是 locals 块,里面可以有多个变量;而引用的关键字是 local ,并没有 s .
一般我们是建议需要重复引用的复杂的表达式才使用本地变量,不然太多本地变量就会影响可读性.
定义了变量就需要对其进行引用,前面的讲解其实已经讲过了部分变量的引用,这些把所有列出来.
类型 | 引用方式 |
---|---|
资源Resources | <Resource Type>.<Name> |
输入变量Input Variables | var.<NAME> |
本地变量Local Values | local.<NAME> |
子模块的输出 | module.<Module Name>.<output Name> |
数据源Data Sources | data.<Data Type>.<Name> |
路径和Terraform相关 | path.module :模块所在路径 path.root :根模块的路径 path.cwd :一般与根模块相同,其它高级用法除外 terraform.workspace :工作区名字 |
块中的本地变量 | count.index :count循环的下标; each.key / each.value :for each循环的键值; self :在provisioner的引用; |
上面都是单值的引用,如果是List或Map这种复杂类型,就要使用中括号 [] 来引用.
aws_instance.example[0].id :引用其中一个元素; 。
aws_instance.example[*].id :引用列表的所有id值; 。
aws_instance.example["a"].id :引用key为 a 的元素; 。
[for value in aws_instance.example: value.id] :返回所有id为列表; 。
与其它语言一样,Terraform也有运算符可以用,主要是用于数值计算和逻辑计算。以下运算符按优先级从高到低如下:
!
取反, -
取负 *
乘号, /
除号, %
取余 +
加号, -
减号 >
, >=
, <
, <=
:比较符号 ==
等于, !=
不等于 &&
与门 ||
或门 当然,用小括号可以改变这些优秀级,如 (1 + 2) * 3 .
注意:对于结构化的数据比较需要注意类型是否一致。比如 var.list == [] 按理说应该返回 true ,而 list 为空时。当 [] 实际表示是元组 tuple([]) ,所以它们不匹配。可以使用 length(var.list) == 0 的方式.
条件表达式的作用是在两个值之间选一个,条件为真则选第一个,条件为假则选第二个。形式如下:
condition ? true_value : false_value
示例如下:
env = var.env !="" ? var.env : "dev"
意思是给 env 赋值,如果 var.env 不为空就把输入变量 var.env 的值赋给它,如果为空则赋默认值 dev .
使用 for 表达式可以创建一些复杂的值,而且可以使用一些转换和计算对值计算再返回。如将字符串列表转化成大写:
> [for s in ["larry", "Nanhua", "Deng"] : upper(s)]
[
"LARRY",
"NANHUA",
"DENG",
]
可以获取下标和值:
> [for i,v in ["larry", "Nanhua", "Deng"] : "${i}.${v}"]
[
"0.larry",
"1.Nanhua",
"2.Deng",
]
对于Map的for表达式:
> [for k,v in {name: "Larry Deng", age: 18, webSite: "www.pkslow.com"} : "${k}: ${v}"]
[
"age: 18",
"name: Larry Deng",
"webSite: www.pkslow.com",
]
通过条件过滤数据:
> [for i in range(1, 10) : i*3 if i%2==0]
[
6,
12,
18,
24,
]
动态块的作用是根据变量重复某一块配置。这在Terraform是会遇见的.
resource "aws_elastic_beanstalk_environment" "tfenvtest" {
name = "tf-test-name"
application = "${aws_elastic_beanstalk_application.tftest.name}"
solution_stack_name = "64bit Amazon Linux 2018.03 v2.11.4 running Go 1.12.6"
dynamic "setting" {
for_each = var.settings
content {
namespace = setting.value["namespace"]
name = setting.value["name"]
value = setting.value["value"]
}
}
}
比如这里的例子,就会重复 setting 块。重复的次数取决于 for_each 后面跟的变量.
最后此篇关于《Terraform101从入门到实践》第五章HCL语法的文章就讲到这里了,如果你想了解更多关于《Terraform101从入门到实践》第五章HCL语法的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
Hive —— 入门 Hive介绍 Apache Hive是一款建立在Hadoop之上的开源数据仓库系统,可以将存储在Hadoop文件中的结构化、半结构化数据文件映射为一张数据库表,基于表提供了一
HBase —— 入门 HBase介绍 HBase是一个分布式的、面向列的开源数据库,该技术来源于 Fay Chang 所撰写的Google论文“Bigtable:一个结构化数据的分布式存储系统”
零:前端目前形势 前端的发展史 HTML(5)、CSS(3)、JavaScript(ES5、ES6):编写一个个的页面 -> 给后端(PHP、Python、Go、Java) ->
在本教程中,您将了解在计算机上运行 JavaScript 的不同方法。 JavaScript 是一种流行的编程语言,具有广泛的应用程序。 JavaScript 以前主要用于使网页具有交
我曾经是一个对编程一窍不通的小白,但因为对互联网世界的好奇心和求知欲的驱使,我踏入了编程的殿堂。在学习的过程中,我发现了一门神奇的编程语言——Python。Python有着简洁、易读的语法,让初学者能
嗨,亲爱的读者们! 今天我要给大家分享一些关于Python爬虫的小案例。你是否曾为了获取特定网页上的数据而烦恼过?或者是否好奇如何从网页中提取信息以供自己使用?那么,这篇文章将会给你一些启示和灵感。
关闭。这个问题是opinion-based 。目前不接受答案。 想要改进这个问题吗?更新问题,以便 editing this post 可以用事实和引文来回答它。 . 已关闭 8 年前。 Improv
我想创建一个像https://apprtc.appspot.com/?r=04188292这样的应用程序。我对 webrtc 了解一点,但无法掌握 google app-engine。如何为 java
我刚刚开始使用 Python 并编写了一个简单的周边程序。但是,每当我在终端中键入 python perimeter.py 时,都会收到以下错误,我不知道如何解决。 >>> python perime
Redis有5个基本数据结构,string、list、hash、set和zset。它们是日常开发中使用频率非常高应用最为广泛的数据结构,把这5个数据结构都吃透了,你就掌握了Redis应用知识的一半了
创建发布web项目 具体步骤: 1.在开发工具中创建一个dynamic web project helloword 2.在webContent中创建index.html文件 3.发布web应用到
如果你在 Ubuntu 上使用终端的时间很长,你可能会希望调整终端的字体和大小以获取一种良好的体验。 更改字体是一种最简单但最直观的 Linux 的终端自定义 的方法。让我
1. 前言 ADODB 是 Active Data Objects Data Base 的简称,它是一种 PHP 存取数据库的函式组件。现在 SFS3 系统 (校园自由软件交流网学务系统) 计划的
我对 neo4j 完全陌生,我很抱歉提出这样一个基本问题。我已经安装了neo4j,我正在使用shell“localhost:7474/webadmin/#/console/” 我正在寻找一个很好的例子
我正在阅读 ios 4 的核心音频,目的是构建一个小测试应用程序。 在这一点上,我对所有 api 的研究感到非常困惑。理想情况下,我想知道如何从两个 mp3 中提取一些样本到数组中。 然后在回调循环中
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是无关紧要的,因
我下载了 GNUStep并安装了它,但是我不确定在哪里可以找到 IDE。有谁知道什么程序可以用作 GNUStep IDE/从哪里获取它们?否则,有没有人知道有关如何创建和编译基本 GNUStep 程序
我正在尝试开始使用 Apache Solr,但有些事情我不清楚。通读tutorial ,我已经设置了一个正在运行的 Solr 实例。我感到困惑的是 Solr 的所有配置(架构等)都是 XML 格式的。
请问有没有关于如何开始使用 BruTile 的文档? 我目前正在使用 SharpMap,我需要预缓存切片以加快进程 最佳答案 我今天正在研究这个:)Mapsui项目site严重依赖 SharpMap
尽我所能,我无法让 CEDET 做任何事情。 Emacs 24.3。我下载了最新的 CEDET 快照。我从他的底部(不是这样)Gentle Introduction 中获取了 Alex Ott 的设置
我是一名优秀的程序员,十分优秀!