Habitatをためす

Chef社から出た、[Habitat](https://www.chef.io/blog/2016/06/14/introducing-habitat/)を試してみます。
Mac、Linuxがサポートされています。
ここでは、Ubuntu16.04で[チュートリアル](https://www.habitat.sh/tutorials/getting-started-overview/)にそって試してみます。

### Set up your environment

1. [How To Install and Use Docker on Ubuntu 16.04](https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-16-04)を参考にDockerをインストールします。
1. [ダウンロードページ](https://www.habitat.sh/docs/get-habitat/)からバイナリをダウンロードして、PATHを通します。
1. hab setupを実行して、初期設定を行います。      
 ここでの注意点はoriginの設定を行っておき、以降で設定するoriginはここで設定したものにします。

hab setupで設定する項目は以下の通りです。

```
$ hab setup
Set up a default origin? [Yes/no/quit]
Default origin name: [default: root]
Create an origin key for `root'? [Yes/no/quit]
Set up a default GitHub access token? [Yes/no/quit]
Enable analytics? [Yes/no/quit]
```

それぞれの設定項目に対応するドキュメントはいかにあります。

* [Set up a default origin](https://www.habitat.sh/docs/build-packages-overview/)
* [Create origin key pair](https://www.habitat.sh/docs/concepts-keys/#origin-keys)
* [GitHub Access Token](https://www.habitat.sh/docs/share-packages-overview/)
* [Analytics](https://www.habitat.sh/docs/about-analytics/)

### Review the source files

Tutorialにある通りアプリケーションを作っていきます。
作業完了後は以下のようなディレクトリ構成になります。
ディレクトリ名は、Create your first planで指定する設定ファイルに影響があるので下記の通りにする必要があります。

```
$ cd ~/
$ tree
.
└── mytutorialapp-0.1.0
    ├── config
    │   └── config.json
    ├── package.json
    └── server.js
```

後で、tgzに圧縮する必要があるので圧縮しsha256sumを取得しておきます。
ここではローカル環境にApacheを事前に立てておき、wgetで取得可能にします。

```
$ tar cvfz mytutorialapp-0.1.0.tgz mytutorialapp-0.1.0
$ sha256sum mytutorialapp-0.1.0.tgz 
426aa18efdad7c1932e6ac061342263f159b45f06e9fd1a58a132aa46a70af3e  mytutorialapp-0.1.0.tgz
$ mv mytutorialapp-0.1.0.tgz /var/www/html/
```

### Create your first plan

必要なディレクトリを作ってplan.shを作ります。
pkg_sourceはlcoalhostでは『wget: unable to resolve host address 'localhost'』となるため、IPアドレスを指定します。
また、pkg_originはhab setupのoriginを設定します。ここでは、デフォルトのrootから変更しhideji2としています。
pkg_sourceは上記で設定したapacheから取得していますが、他のところ(S3など）から取得することも可能です。

```
$ mkdir -p ~/plans/mytutorialapp
$ cd ~/plans/mytutorialapp
$ cat ~/plans/mytutorialapp/plan.sh 
```

```plan.sh 
pkg_origin=hideji2
pkg_name=mytutorialapp
pkg_version=0.1.0
pkg_maintainer="Your Name <your email address>"
pkg_license=()
pkg_source=http://10.240.0.5/${pkg_name}-${pkg_version}.tgz
pkg_shasum=426aa18efdad7c1932e6ac061342263f159b45f06e9fd1a58a132aa46a70af3e 
pkg_deps=(core/node)
pkg_expose=(8080)


do_build() {
  # The mytutorialapp source code is unpacked into a directory,
  # mytutorialapp-0.1.0, at the root of $HAB_CACHE_SRC_PATH. If you were downloading
  # an archive that didn't match your package name and version, you would have to
  # copy the files into $HAB_CACHE_SRC_PATH.

  # This installs both npm as well as the nconf module we listed as a
  # dependency in package.json.
  npm install
}

do_install() {
  # Our source files were copied over to the HAB_CACHE_SRC_PATH in do_build(),
  # so now they need to be copied into the root directory of our package through
  # the pkg_prefix variable. This is so that we have the source files available
  # in the package.
  cp package.json ${pkg_prefix}
  cp server.js ${pkg_prefix}

  # Copy over the nconf module to the package that we installed in do_build().
  mkdir -p ${pkg_prefix}/node_modules/
  cp -vr node_modules/* ${pkg_prefix}/node_modules/
}
```

ビルドを行います。
『hab studio enter』で独自のシェルを立ちげて、その中で作業するイメージです。

```
# cd ~/plans/mytutorialapp/
# hab studio enter
[1][default:/src:0]# build
[2][default:/src:0]# ls /src/results/
last_build.env  hideji2-mytutorialapp-0.1.0-20160617104409-x86_64-linux.hart
```

### Add hooks to your plan

ここでは初期化処理(hook)を定義します。

```
[6][default:/src:0]# cd /src
[7][default:/src:0]# mkdir -p hooks
[8][default:/src:0]# cd hooks
[9][default:/src/hooks:0]# touch init run
[10][default:/src/hooks:0]# ls
init  run
```

initスクリプトと、runスクリプトと必要なことを記述します。

#### initスクリプト

```
[13][default:/src/hooks:0]# cat init 
```
initスクリプトの内容

```init 
#!/bin/sh
#
ln -sf {{pkg.path}}/package.json {{pkg.svc_path}}
ln -sf {{pkg.path}}/server.js {{pkg.svc_path}}
ln -sf {{pkg.path}}/node_modules {{pkg.svc_path}}
```

#### runスクリプト

```
[14][default:/src/hooks:0]# cat run 
```
runスクリプトの内容

```
#!/bin/sh
#
cd {{pkg.svc_path}}
npm start
```

### Add configuration to your plan

ここではアプリケーションが使用するconfigファイルを作成します。
Review the source filesで作成したものと変わら無い場合は、他のファイルと同様にinitスクリプトで用意しても良さそうです。

```
[15][default:/src/hooks:0]# cd /src
[16][default:/src:0]#  mkdir -p config
[20][default:/src:0]# vim config/config.json                                                                                                                                                           
[21][default:/src:0]# cat  config/config.json
```

```config.json
{
    "message": "{{cfg.message}}",
    "port": "{{cfg.port}}"
}
```

config.jsonに埋め込む内容をtomlで定義します。

```
[24][default:/src:0]# vim default.toml 
[25][default:/src:0]# cat default.toml
```

```default.toml
# Message of the Day
message = "Hello, World!"

# The port number that is listening for requests.
port = 8080
[26][default:/src:0]# exit
```


### Run your service

再度buildを行い、Docker imageの作成を行います。

```
 # cd ~/plans/mytutorialapp
 # hab studio enter
 [1][default:/src:0]# build
 [2][default:/src:0]# hab pkg export docker hideji2/mytutorialapp
 [3][default:/src:0]# exit
```

ちなみにこの状態で、/src/results/を確認すると2つのPackage（hart）ができていることがわかります。

```
[1][default:/src:0]# ls /src/results/
hideji2-mytutorialapp-0.1.0-20160617104409-x86_64-linux.hart  last_build.env
hideji2-mytutorialapp-0.1.0-20160620045938-x86_64-linux.hart
```

docker imagesで、作成したIamgeを確認すると以下のようになります。

```
# docker images
REPOSITORY             TAG                    IMAGE ID            CREATED             SIZE
hideji2/mytutorialapp   0.1.0-20160620045938   4a23bcad07b5        About an hour ago   187.7 MB
hideji2/mytutorialapp   latest                 4a23bcad07b5        About an hour ago   187.7 MB
```

dockerで作成したイメージを実行することができます。

```
docker run -d -it -p 8080:8080 hideji2/mytutorialapp
```