dehio3’s diary

仕事、生活、趣味のメモ

terraformコマンドのコンテナイメージにtfnotifyを追加した

f:id:dehio3:20190710094851p:plain

はじめに

CIツールでterraformを実行する時に、tfnotifyを使いたい。

imageはhashicorp/terraformを使ってるので、terraformのイメージにtfnotifyをインストールする方法を確認する。

imageの取得

$docker pull hashicorp/terraform:0.11.11
0.11.11: Pulling from hashicorp/terraform
4fe2ade4980c: Pull complete 
9687e2aa6bcc: Pull complete 
99ae8338d458: Pull complete 
Digest: sha256:1641e454fddceb7ec3c4d2dea3ed98a12f8f9bc74490da680cc4901c49d793b0
Status: Downloaded newer image for hashicorp/terraform:0.11.11
$ docker images
REPOSITORY            TAG                 IMAGE ID            CREATED             SIZE
hashicorp/terraform   0.11.11             29edcab3b90b        5 months ago        131MB

コンテナ作成&起動

[]:~$ docker run -it hashicorp/terraform:0.11.11
Usage: terraform [-version] [-help] <command> [args]

The available commands for execution are listed below.
The most common, useful commands are shown first, followed by
less common or more advanced commands. If you're just getting
started with Terraform, stick with the common commands. For the
other commands, please read the help and docs before usage.

Common commands:
    apply              Builds or changes infrastructure
    console            Interactive console for Terraform interpolations
    destroy            Destroy Terraform-managed infrastructure
    env                Workspace management
    fmt                Rewrites config files to canonical format
    get                Download and install modules for the configuration
    graph              Create a visual graph of Terraform resources
    import             Import existing infrastructure into Terraform
    init               Initialize a Terraform working directory
    output             Read an output from a state file
    plan               Generate and show an execution plan
    providers          Prints a tree of the providers used in the configuration
    push               Upload this Terraform module to Atlas to run
    refresh            Update local state file against real resources
    show               Inspect Terraform state or plan
    taint              Manually mark a resource for recreation
    untaint            Manually unmark a resource as tainted
    validate           Validates the Terraform files
    version            Prints the Terraform version
    workspace          Workspace management

All other commands:
    debug              Debug output management (experimental)
    force-unlock       Manually unlock the terraform state
    state              Advanced state management
[]:~$

コンテナイメージのENTRYPOINTがterraformなのでterraformコマンドをオプションなしで打った結果が返ってくる

entrypointをbashに上書きして起動してみる

[]:~$ docker run --entrypoint 'bash' -it hashicorp/terraform:0.11.11
docker: Error response from daemon: OCI runtime create failed: container_linux.go:344: starting container process caused "exec: \"bash\": executable file not found in $PATH": unknown.

bashがない!!

alpine linuxのデフォルトのシェルは「ash」だった!

qiita.com

entrypointをashに変更して起動

[]:~$ docker run --entrypoint 'ash' -it hashicorp/terraform:0.11.11
/ # 
/ # uname -a
Linux 35b5b447d9a4 4.9.125-linuxkit #1 SMP Fri Sep 7 08:20:28 UTC 2018 x86_64 Linux
/ # 

起動してログインできた

tfnotifyのインストール

goが必要なため、インストールされているか確認

/ # go
ash: go: not found

入ってない。

goをインストールする(この後のtfnotifyのビルドの為にlibc-devも合わせてインストール)

/ # apk --update add go libc-dev
fetch http://dl-cdn.alpinelinux.org/alpine/v3.8/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.8/community/x86_64/APKINDEX.tar.gz
(1/13) Installing binutils (2.30-r5)
(2/13) Installing isl (0.18-r0)
(3/13) Installing libgomp (6.4.0-r9)
(4/13) Installing libatomic (6.4.0-r9)
(5/13) Installing pkgconf (1.5.3-r0)
(6/13) Installing libgcc (6.4.0-r9)
(7/13) Installing mpfr3 (3.1.5-r1)
(8/13) Installing mpc1 (1.0.3-r1)
(9/13) Installing libstdc++ (6.4.0-r9)
(10/13) Installing gcc (6.4.0-r9)
(11/13) Installing go (1.10.8-r0)
(12/13) Installing musl-dev (1.1.19-r10)
(13/13) Installing libc-dev (0.7.1-r0)
Executing busybox-1.28.4-r1.trigger
OK: 444 MiB in 63 packages

tfnotifyのインストール

/ # go get -u -v github.com/mercari/tfnotify
github.com/mercari/tfnotify (download)
created GOPATH=/root/go; see 'go help gopath'
github.com/mattn/go-colorable (download)
github.com/mattn/go-isatty (download)
Fetching https://golang.org/x/sys/unix?go-get=1
Parsing meta tags from https://golang.org/x/sys/unix?go-get=1 (status code 200)
get "golang.org/x/sys/unix": found meta tag get.metaImport{Prefix:"golang.org/x/sys", VCS:"git", RepoRoot:"https://go.googlesource.com/sys"} at https://golang.org/x/sys/unix?go-get=1
get "golang.org/x/sys/unix": verifying non-authoritative meta tag
Fetching https://golang.org/x/sys?go-get=1
Parsing meta tags from https://golang.org/x/sys?go-get=1 (status code 200)
golang.org/x/sys (download)
Fetching https://gopkg.in/yaml.v2?go-get=1
Parsing meta tags from https://gopkg.in/yaml.v2?go-get=1 (status code 200)
get "gopkg.in/yaml.v2": found meta tag get.metaImport{Prefix:"gopkg.in/yaml.v2", VCS:"git", RepoRoot:"https://gopkg.in/yaml.v2"} at https://gopkg.in/yaml.v2?go-get=1
gopkg.in/yaml.v2 (download)
github.com/google/go-github (download)
github.com/google/go-querystring (download)
Fetching https://golang.org/x/oauth2?go-get=1
Parsing meta tags from https://golang.org/x/oauth2?go-get=1 (status code 200)
get "golang.org/x/oauth2": found meta tag get.metaImport{Prefix:"golang.org/x/oauth2", VCS:"git", RepoRoot:"https://go.googlesource.com/oauth2"} at https://golang.org/x/oauth2?go-get=1
golang.org/x/oauth2 (download)
Fetching https://golang.org/x/oauth2/internal?go-get=1
Parsing meta tags from https://golang.org/x/oauth2/internal?go-get=1 (status code 200)
get "golang.org/x/oauth2/internal": found meta tag get.metaImport{Prefix:"golang.org/x/oauth2", VCS:"git", RepoRoot:"https://go.googlesource.com/oauth2"} at https://golang.org/x/oauth2/internal?go-get=1
get "golang.org/x/oauth2/internal": verifying non-authoritative meta tag
Fetching https://golang.org/x/oauth2?go-get=1
Parsing meta tags from https://golang.org/x/oauth2?go-get=1 (status code 200)
Fetching https://golang.org/x/net/context/ctxhttp?go-get=1
Parsing meta tags from https://golang.org/x/net/context/ctxhttp?go-get=1 (status code 200)
get "golang.org/x/net/context/ctxhttp": found meta tag get.metaImport{Prefix:"golang.org/x/net", VCS:"git", RepoRoot:"https://go.googlesource.com/net"} at https://golang.org/x/net/context/ctxhttp?go-get=1
get "golang.org/x/net/context/ctxhttp": verifying non-authoritative meta tag
Fetching https://golang.org/x/net?go-get=1
Parsing meta tags from https://golang.org/x/net?go-get=1 (status code 200)
golang.org/x/net (download)
github.com/lestrrat-go/slack (download)
github.com/lestrrat-go/pdebug (download)
github.com/pkg/errors (download)
github.com/nulab/go-typetalk (download)
github.com/urfave/cli (download)
gopkg.in/yaml.v2
golang.org/x/sys/unix
github.com/mercari/tfnotify/config
github.com/mattn/go-isatty
github.com/mercari/tfnotify/notifier
github.com/google/go-querystring/query
github.com/mattn/go-colorable
github.com/mercari/tfnotify/terraform
github.com/google/go-github/github
golang.org/x/net/context/ctxhttp
golang.org/x/oauth2/internal
golang.org/x/oauth2
github.com/lestrrat-go/pdebug
github.com/lestrrat-go/slack/internal/option
github.com/pkg/errors
github.com/lestrrat-go/slack/objects
github.com/lestrrat-go/slack
github.com/mercari/tfnotify/notifier/slack
github.com/nulab/go-typetalk/typetalk/shared
github.com/nulab/go-typetalk/typetalk/internal
github.com/nulab/go-typetalk/typetalk/v1
github.com/mercari/tfnotify/notifier/typetalk
github.com/urfave/cli
github.com/mercari/tfnotify/notifier/github
github.com/mercari/tfnotify
/ #

コマンドパスを確認

~ # ls -l /root/go/bin/tfnotify 
-rwxr-xr-x    1 root     root      15842856 May 15 06:12 /root/go/bin/tfnotify

GOPATHを何も指定してないので、$HOME/go/bin配下にコマンドが配置

tfnofityコマンドを実行

/ # /root/go/bin/tfnotify 
NAME:
   tfnotify - Notify the execution result of terraform command

USAGE:
   tfnotify [global options] command [command options] [arguments...]

VERSION:
   0.3.0

COMMANDS:
     fmt      Parse stdin as a fmt result
     plan     Parse stdin as a plan result
     apply    Parse stdin as a apply result
     help, h  Shows a list of commands or help for one command

GLOBAL OPTIONS:
   --ci value        name of CI to run tfnotify
   --config value    config path
   --notifier value  notification destination
   --help, -h        show help
   --version, -v     print the version

circleciのconfig.yml

実際にCircleCIで実行する場合のconfig.ymlは以下

(追記)terraformのバージョン次第で、goのバージョンが違うので注意

古いとGOPATHを明示的に指定する必要がある。

hashicorp/terraform:0.10.8

/ # cat /proc/version 
Linux version 4.9.125-linuxkit (root@659b6d51c354) (gcc version 6.4.0 (Alpine 6.4.0) ) #1 SMP Fri Sep 7 08:20:28 UTC 2018
/ # 
/ # go version
go version go1.7.3 linux/amd64
/ # 
/ # go get -u -v github.com/mercari/tfnotify
package github.com/mercari/tfnotify: cannot download, $GOPATH not set. For more details see: go help gopath
/ #

hashicorp/terraform:0.11.11

/ # cat /proc/version 
Linux version 4.9.125-linuxkit (root@659b6d51c354) (gcc version 6.4.0 (Alpine 6.4.0) ) #1 SMP Fri Sep 7 08:20:28 UTC 2018
/ #
/ # go version
go version go1.10.8 linux/amd64
/ # 
/ # go get -u -v github.com/mercari/tfnotify
github.com/mercari/tfnotify (download)
created GOPATH=/root/go; see 'go help gopath'