[覚書]Ottoで開発環境を構築

1. [[覚書]Ottoで開発環境を構築](http://qiita.com/neogym/items/c0c3ba87e8535dabe878) ← **ここ**
2. [[覚書]OttoでAWSに本番環境構築＆デプロイ](http://qiita.com/neogym/items/e5e0bbf89df390aa9059)
3. [[覚書]Ottoで開発環境を構築 (Appfileをカスタマイズ → Rubyのバージョン指定)](http://qiita.com/neogym/items/73ee4bee570963751153)
4. [[覚書]Ottoで開発環境を構築 (MongoDBのDockerコンテナを動かす)](http://qiita.com/neogym/items/0d7aa2e07ea1da477f2f)

# 動機

`Vagrant`の後継ツールと言われている`Otto`を先取りしたい。

# 検証環境

* OS : OS X 10.10.5
    * `Homebrew` : 0.9.5
    * `brew cask` : 0.56.0
    * `VirtualBox` : 4.3.10 r93012

# インストール

`brew cask`でインストール。

```bash
$ brew install Caskroom/cask/otto
```

または、下記のサイトからダウンロード。

* [Download Otto - Otto by HashiCorp:](https://ottoproject.io/downloads.html)

インストールされたか確認。

```bash
$ otto
usage: otto [--version] [--help] <command> [<args>]

Available commands are:
    build      Build the deployable artifact for the app
    compile    Prepares your project for being run.
    deploy     Deploy the application
    dev        Start and manage a development environment
    infra      Builds the infrastructure for the Appfile
    status     Status of the stages of this application
    version    Prints the Otto version

$ otto --version
Otto v0.1.2
```

# 開発

## プロジェクト作成

プロジェクトをクローン。

```bash
$ git clone https://github.com/hashicorp/otto-getting-started.git
Cloning into 'otto-getting-started'...
remote: Counting objects: 28, done.
remote: Total 28 (delta 0), reused 0 (delta 0), pack-reused 28
Unpacking objects: 100% (28/28), done.
Checking connectivity... done.
```

ファイル確認。

```bash
$ cd otto-getting-started
$ tree .
.
├── Gemfile
├── Gemfile.lock
├── README.md
├── app.rb
├── config.ru
└── views
    ├── index.erb
    └── name.erb

1 directory, 7 files
$ ls -a
./            ../           .git/         Gemfile       Gemfile.lock  README.md     app.rb        config.ru     views/
$ ls -a views/
./         ../        index.erb  name.erb
```

## コンパイル

```bash
$ otto compile
==> Loading Appfile...
==> No Appfile found! Detecting project information...
    No Appfile was found. If there is no Appfile, Otto will do its best
    to detect the type of application this is and set reasonable defaults.
    This is a good way to get started with Otto, but over time we recommend
    writing a real Appfile since this will allow more complex customizations,
    the ability to reference dependencies, versioning, and more.
==> Fetching all Appfile dependencies...
==> Compiling...
    Application:    otto-getting-started (ruby)
    Project:        otto-getting-started
    Infrastructure: aws (simple)

    Compiling infra...
    Compiling foundation: consul
==> Compiling main application...
==> Compilation success!
    This means that Otto is now ready to start a development environment,
    deploy this application, build the supporting infrastructure, and
    more. See the help for more information.
    
    Supporting files to enable Otto to manage your application from
    development to deployment have been placed in the output directory.
    These files can be manually inspected to determine what Otto will do.
```

`.otto/`と`ottoid`が追加されている。

```bash
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Untracked files:
  (use "git add <file>..." to include in what will be committed)

	.otto/
	.ottoid

nothing added to commit but untracked files present (use "git add" to track)
```

追加されたファイルを確認。

```bash
$ cat .ottoid 
b22aad6b-9b44-a28c-6808-9e6d86498af4

DO NOT MODIFY OR DELETE THIS FILE!

This file should be checked in to version control. Do not ignore this file.

The first line is a unique UUID that represents the Appfile in this directory.
This UUID is used globally across your projects to identify this specific
Appfile. This UUID allows you to modify the name of an application, or have
duplicate application names without conflicting.

If you delete this file, then deploys may duplicate this application since
Otto will be unable to tell that the application is deployed.
```

```bash
$ tree .otto
.otto
├── appfile
│   ├── Appfile.compiled
│   └── version
├── compiled
│   ├── app
│   │   ├── build
│   │   │   ├── build-ruby.sh
│   │   │   └── template.json
│   │   ├── deploy
│   │   │   └── main.tf
│   │   ├── dev
│   │   │   └── Vagrantfile
│   │   └── foundation-consul
│   │       ├── app-build
│   │       │   ├── main.sh
│   │       │   └── upstart.conf
│   │       ├── app-deploy
│   │       │   └── main.sh
│   │       ├── app-dev
│   │       │   ├── main.sh
│   │       │   └── upstart.conf
│   │       ├── app-dev-dep
│   │       │   └── main.sh
│   │       └── deploy
│   │           ├── main.tf
│   │           ├── module-aws
│   │           │   ├── join.sh
│   │           │   ├── main.tf
│   │           │   ├── outputs.tf
│   │           │   └── variables.tf
│   │           ├── module-aws-simple
│   │           │   ├── main.tf
│   │           │   ├── outputs.tf
│   │           │   ├── setup.sh
│   │           │   └── variables.tf
│   │           └── variables.tf
│   ├── foundation-consul
│   │   ├── app-build
│   │   │   ├── main.sh
│   │   │   └── upstart.conf
│   │   ├── app-deploy
│   │   │   └── main.sh
│   │   ├── app-dev
│   │   │   ├── main.sh
│   │   │   └── upstart.conf
│   │   ├── app-dev-dep
│   │   │   └── main.sh
│   │   └── deploy
│   │       ├── main.tf
│   │       ├── module-aws
│   │       │   ├── join.sh
│   │       │   ├── main.tf
│   │       │   ├── outputs.tf
│   │       │   └── variables.tf
│   │       ├── module-aws-simple
│   │       │   ├── main.tf
│   │       │   ├── outputs.tf
│   │       │   ├── setup.sh
│   │       │   └── variables.tf
│   │       └── variables.tf
│   └── infra-otto-getting-started
│       ├── main.tf
│       └── outputs.tf
└── data
    └── dev_ip

24 directories, 41 files
```

変更のあったファイルをステージに退避。

```bash
$ git add .
```

## 開発環境の構築

開発環境の構築。

```bash
$ otto dev
==> Creating local development environment with Vagrant if it doesn't exist...
    Raw Vagrant output will begin streaming in below. Otto does
    not create this output. It is mirrored directly from Vagrant
    while the development environment is being created.
    
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'hashicorp/precise64'...
==> default: Matching MAC address for NAT networking...
==> default: Checking if box 'hashicorp/precise64' is up to date...
==> default: Setting the name of the VM: dev_default_1448338407953_36480
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
    default: Adapter 1: nat
    default: Adapter 2: hostonly
==> default: Forwarding ports...
    default: 22 => 2222 (adapter 1)
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
    default: SSH address: 127.0.0.1:2222
    default: SSH username: vagrant
    default: SSH auth method: private key
    default: Warning: Connection timeout. Retrying...
    default: Warning: Connection timeout. Retrying...
    default: 
    default: Vagrant insecure key detected. Vagrant will automatically replace
    default: this with a newly generated keypair for better security.
    default: 
    default: Inserting generated public key within guest...
    default: Removing insecure key from the guest if it's present...
    default: Key inserted! Disconnecting and reconnecting using new SSH key...
==> default: Machine booted and ready!
==> default: Checking for guest additions in VM...
    default: The guest additions on this VM do not match the installed version of
    default: VirtualBox! In most cases this is fine, but in rare cases it can
    default: prevent things such as shared folders from working properly. If you see
    default: shared folder errors, please make sure the guest additions within the
    default: virtual machine match the version of VirtualBox you have installed on
    default: your host and reload your VM.
    default: 
    default: Guest Additions Version: 4.2.0
    default: VirtualBox Version: 4.3
==> default: Configuring and enabling network interfaces...
==> default: Mounting shared folders...
    default: /vagrant => /Users/masaki/Documents/Development/github/hashicorp/otto-getting-started
    default: /otto/foundation-1 => /Users/masaki/Documents/Development/github/hashicorp/otto-getting-started/.otto/compiled/app/foundation-consul/app-dev
==> default: Running provisioner: shell...
    default: Running: inline script
==> default: stdin: is not a tty
==> default: [otto] Installing Consul...
==> default: [otto] Installing dnsmasq for Consul...
==> default: [otto] Configuring consul service: otto-getting-started
==> default: Running provisioner: shell...
    default: Running: inline script
==> default: stdin: is not a tty
==> default: [otto] Setting locale to en_US.UTF-8...
==> default: Running provisioner: shell...
    default: Running: inline script
==> default: [otto] Adding apt repositories and updating...
==> default: [otto] Installing Ruby 2.2 and supporting packages...
==> default: [otto] Configuring Ruby environment...
==> default: [otto] Installing Bundler...
==> default: [otto] Bundling gem dependencies...
==> default: [otto] Configuring Git to use SSH instead of HTTP so we can agent-forward private repo auth...

==> Caching SSH credentials from Vagrant...
==> Development environment successfully created!
    IP address: 100.104.209.165
    
    A development environment has been created for writing a generic
    Ruby-based app.
    
    Ruby is pre-installed. To work on your project, edit files locally on your
    own machine. The file changes will be synced to the development environment.
    
    When you're ready to build your project, run 'otto dev ssh' to enter
    the development environment. You'll be placed directly into the working
    directory where you can run 'bundle' and 'ruby' as you normally would.
    
    You can access any running web application using the IP above.
```

*内部的には、`Vagrant`を使って開発環境を構築しているようです。*

***初回コンパイル時は、仮想マシンのIPアドレスがブロードキャストアドレス(`100.114.244.255`)になっていました。`.ottoid`と`.otto/`を削除してコンパイルし直したところ新しいIPアドレスが割り振られました。(原因不明)***

```bash
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	new file:   .otto/appfile/Appfile.compiled
	new file:   .otto/appfile/version
	new file:   .otto/compiled/app/build/build-ruby.sh
	new file:   .otto/compiled/app/build/template.json
	new file:   .otto/compiled/app/deploy/main.tf
	new file:   .otto/compiled/app/dev/Vagrantfile
	new file:   .otto/compiled/app/foundation-consul/app-build/main.sh
	new file:   .otto/compiled/app/foundation-consul/app-build/upstart.conf
	new file:   .otto/compiled/app/foundation-consul/app-deploy/main.sh
	new file:   .otto/compiled/app/foundation-consul/app-dev-dep/main.sh
	new file:   .otto/compiled/app/foundation-consul/app-dev/main.sh
	new file:   .otto/compiled/app/foundation-consul/app-dev/upstart.conf
	new file:   .otto/compiled/app/foundation-consul/deploy/main.tf
	new file:   .otto/compiled/app/foundation-consul/deploy/module-aws-simple/main.tf
	new file:   .otto/compiled/app/foundation-consul/deploy/module-aws-simple/outputs.tf
	new file:   .otto/compiled/app/foundation-consul/deploy/module-aws-simple/setup.sh
	new file:   .otto/compiled/app/foundation-consul/deploy/module-aws-simple/variables.tf
	new file:   .otto/compiled/app/foundation-consul/deploy/module-aws/join.sh
	new file:   .otto/compiled/app/foundation-consul/deploy/module-aws/main.tf
	new file:   .otto/compiled/app/foundation-consul/deploy/module-aws/outputs.tf
	new file:   .otto/compiled/app/foundation-consul/deploy/module-aws/variables.tf
	new file:   .otto/compiled/app/foundation-consul/deploy/variables.tf
	new file:   .otto/compiled/foundation-consul/app-build/main.sh
	new file:   .otto/compiled/foundation-consul/app-build/upstart.conf
	new file:   .otto/compiled/foundation-consul/app-deploy/main.sh
	new file:   .otto/compiled/foundation-consul/app-dev-dep/main.sh
	new file:   .otto/compiled/foundation-consul/app-dev/main.sh
	new file:   .otto/compiled/foundation-consul/app-dev/upstart.conf
	new file:   .otto/compiled/foundation-consul/deploy/main.tf
	new file:   .otto/compiled/foundation-consul/deploy/module-aws-simple/main.tf
	new file:   .otto/compiled/foundation-consul/deploy/module-aws-simple/outputs.tf
	new file:   .otto/compiled/foundation-consul/deploy/module-aws-simple/setup.sh
	new file:   .otto/compiled/foundation-consul/deploy/module-aws-simple/variables.tf
	new file:   .otto/compiled/foundation-consul/deploy/module-aws/join.sh
	new file:   .otto/compiled/foundation-consul/deploy/module-aws/main.tf
	new file:   .otto/compiled/foundation-consul/deploy/module-aws/outputs.tf
	new file:   .otto/compiled/foundation-consul/deploy/module-aws/variables.tf
	new file:   .otto/compiled/foundation-consul/deploy/variables.tf
	new file:   .otto/compiled/infra-otto-getting-started/main.tf
	new file:   .otto/compiled/infra-otto-getting-started/outputs.tf
	new file:   .otto/data/dev_ip
	new file:   .ottoid

Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	deleted:    .otto/compiled/app/foundation-consul/app-dev/upstart.conf

Untracked files:
  (use "git add <file>..." to include in what will be committed)

	.otto/data/vagrant/

```

*`.otto/compiled/app/foundation-consul/app-dev/upstart.conf`が削除されて、`.otto/data/vagrant/`が追加されています。`upstart.conf`が何なのかは未確認です。。。*

## SSHおよび共有ファイル

開発環境へSSH接続。

```bash
$ otto dev ssh
==> Executing SSH. This may take a few seconds...
Welcome to Ubuntu 12.04 LTS (GNU/Linux 3.2.0-23-generic x86_64)

 * Documentation:  https://help.ubuntu.com/
New release '14.04.3 LTS' available.
Run 'do-release-upgrade' to upgrade to it.

Welcome to your Vagrant-built virtual machine.
Last login: Fri Sep 14 06:23:18 2012 from 10.0.2.2
vagrant@precise64:/vagrant$
```

共有ファイルの確認。

```bash
vagrant@precise64:/vagrant$ ls
app.rb  config.ru  Gemfile  Gemfile.lock  README.md  views
```

## Application-Specific Software

アプリケーションを起動。

```bash
vagrant@precise64:/vagrant$ bundle && rackup --host 0.0.0.0
Using rack 1.6.4
Using rack-protection 1.5.3
Using tilt 2.0.1
Using sinatra 1.4.6
Using bundler 1.10.6
Bundle complete! 1 Gemfile dependency, 5 gems now installed.
Use `bundle show [gemname]` to see where a bundled gem is installed.
[2015-11-24 04:20:19] INFO  WEBrick 1.3.1
[2015-11-24 04:20:19] INFO  ruby 2.2.3 (2015-08-18) [x86_64-linux-gnu]
[2015-11-24 04:20:19] INFO  WEBrick::HTTPServer#start: pid=6870 port=9292
```

上記コマンドを実行したまま、PC(ホストOS)からブラウザで`http://100.104.209.165:9292`にアクセス。
ブラウザに`Who are you?`と表示されたら成功です。
下記のアクセスログがコンソールに表示されているはずです。

```
WARN: tilt autoloading 'tilt/erb' in a non thread-safe way; explicit require 'tilt/erb' suggested.
100.104.209.1 - - [24/Nov/2015:04:33:20 +0000] "GET / HTTP/1.1" 200 424 0.0743
```

*作業を終了したい場合は、`Ctl` + `c`でコマンドを終了させて、`exit`コマンドでサーバログアウトしてください。ログアウト後、`otto dev halt`コマンドでサーバを停止できます。*

## 他のコマンド

下記のコマンドで、`otto dev`の他のコマンドを確認できます。

```bash
otto dev help
```

# 参考

* [Otto by HashiCorp:](https://ottoproject.io/)

以上