今週の学び part 1
関数とメソッドの違い
関数
pub fn add(a: i8, b: i8) i8 {
return a + b;
}
- 引数として操作対象のデータは明示的に指定される
- 戻り値として処理結果を返すことができる
メソッド
pub const Calculation = struct {
value: u16 = 0,
pub fn increment(self: *Calculation) u16 {
self.value += 1;
}
}
- レシーバによって操作対象のデータが暗黙的に渡される
- 構造体に格納されたデータに対して操作を行うことができる
Zig
最近勉強をしている。
comptime
これまで「この処理はコンパイル時に評価するのか、それとも実行時まで遅延するのか」という視点でコードを書いてこなかったので、なかなか comptime の使い時を感じ取れていない。
C# を書いてきたというのもあり、ジェネリクスの時に使うというのは理解できる。
fn max(comptime T: type, a: T, b: T) T {
return if (a < b) a else b;
}
fn gimmeTheBiggerFloat(a: f32, b: f32) f32 {
return max(f32, a, b);
}
fn gimmeTheBiggerInteger(a: u64, b: u64) u64 {
return max(u64, a, b);
}
コンパイラに怒られながら勘を養っていくことになるだろう。
Terraform
folder structure
.
├── README.md
├── main.tf
├── variables.tf
├── outputs.tf
これが基本系。
terraform {
required_providers {
aws = {
# 省略
}
tls = {
# 省略
}
}
required_version = ">= 1.10.0"
backend "s3" {
bucket = "some-bucket-name"
key = "app/terraform.tfstate"
region = "ap-northeast-1"
}
}
provider "aws" {
region = "ap-northeast-1"
}
resource "aws_s3_bucket" "app" {
bucket = var.bucket_name
}
variable "bucket_name" {
type = string
}
output "bucket_arn" {
value = aws_s3_bucket.app.arn
}
これは terraform apply すると s3 に bucket が作られるというシンプルな例。
普通のプロジェクトだと、下記のように子モジュールに切り分ける。
.
├── modules
│ ├── function
│ │ ├── main.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ ├── queue
│ │ ├── main.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ └── vpc
│ ├── main.tf
│ ├── outputs.tf
│ └── variables.tf
├── main.tf
├── outputs.tf
└── variables.tf
例として、root module から VPC の IP アドレス範囲を渡し、作成した VPC の ID を受け取る。
variable "vpc_cidr_block" {
type = string
default = "10.0.0.0/16"
}
VPC モジュールを呼び出す。terraform と provider の設定は前の例と同じもの。
module "vpc" {
source = "./modules/vpc"
cidr_block = var.vpc_cidr_block
}
variable "cidr_block" {
type = string
}
VPC モジュールを参照して、VPC の変数を root の変数で初期化する。
そして、VPC モジュールの main.tf は、受け取った値を VPC の作成に使う。
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
}
}
}
resource "aws_vpc" "this" {
cidr_block = var.cidr_block
}
VPC モジュールの outputs.tf で、作成した VPC の ID を親へ返す。
output "vpc_id" {
value = aws_vpc.this.id
}
output "vpc_id" {
value = module.vpc.vpc_id
}
複数の環境がある場合は下記のように、ルートモジュールをネストして配置する。
.
├── modules
│ ├── compute
│ │ └── main.tf
│ ├── database
│ │ └── main.tf
│ └── vpc
│ ├── main.tf
│ ├── outputs.tf
│ └── variables.tf
├── dev
│ ├── backend.tf
│ ├── main.tf
│ ├── outputs.tf
│ └── variables.tf
├── prod
│ ├── backend.tf
│ ├── main.tf
│ ├── outputs.tf
│ └── variables.tf
└── staging
├── backend.tf
├── main.tf
├── outputs.tf
└── variables.tf
子モジュールへの入力と出力の受け渡しは前の例と同じ。root module が dev/ に移るので、source のパスが変わる程度。
module "vpc" {
source = "../modules/vpc"
cidr_block = var.vpc_cidr_block
}
Terraform は各環境の root module を対象に実行し、state の保存先はそれぞれの backend.tf で分ける。
terraform {
backend "s3" {
bucket = "some-bucket-name"
key = "production/app/terraform.tfstate"
region = "ap-northeast-1"
}
}
このように key に環境を入れたりする。
variables.tf
メソッドの引数のようなものだと思えばいい。
値を渡すにはいくつかの方法がある。
see: https://developer.hashicorp.com/terraform/language/values/variables#assign-values-to-variables
.tfvars ファイルを実行対象のディレクトリに定義する
bucket_name = "unidog"
TF_VAR_${変数名} を実行環境の環境変数として定義する
TF_VAR_bucket_name=unidog terraform plan
CLI にて -var オプションで直接指定する
terraform plan -var='bucket_name=unidog'
outputs.tf
メソッドの返り値のようなものだと思えばいい。
output のユースケースには下記がある。
see: https://developer.hashicorp.com/terraform/language/values/outputs#use-outputs-to-expose-module-data
子モジュールから親モジュールへリソースの情報を渡す。例えば、VPC モジュールの出力を root の出力に使う。
output "vpc_id" {
value = module.vpc.vpc_id
}
root module の値を CLI で表示する。例えば、apply 後に VPC の ID を確認する。
terraform output vpc_id
別の Terraform 構成から remote state の出力を参照する。
data "terraform_remote_state" "network" {
backend = "s3"
config = {
bucket = "some-bucket-name"
key = "network/terraform.tfstate"
region = "ap-northeast-1"
}
}
locals {
vpc_id = data.terraform_remote_state.network.outputs.vpc_id
}
自動化ツールに値を渡す。例えば、CI の後続処理に渡すため、出力を JSON ファイルへ保存する。
terraform output -json > terraform-outputs.json