Chef SoloでRails環境構築

#　はじめに

前回のChefの勉強に引き続き、今度はChefでRails環境を仮想サーバーに構築します。

メモみたいなものです。どうかあしからず。

参考
手動でRails環境を仮想サーバーに構築した話
[CentOS x Ruby on Rails](https://qiita.com/enzen/items/4d38841e6fee730643dd)

Chef Soloの基礎的な操作法をまとめた記事
[Chef Solo入門](https://qiita.com/enzen/items/704c236489873ac4dc9a)

# 環境

### ホストOS環境

- OS X 10.13.1
- Vagrant 2.0.2
- VirtualBox 5.2.6
- Chef 13.6.4
- Chef Development Kit 2.4.17
- chef-client 13.6.4
- berks 6.3.1
- kitchen 1.19.2
- inspec 1.45.13

### ゲストOS

ゲストOS環境

- CentOS 7
- Chef 13.7.16
- Chef Development Kit 0.7.0
- chef-client 12.4.1
- berks 3.2.4
- kitchen 1.4.2

# 環境構築Rails編

前提としてホストOSとゲストOSに基本的なソフトウェア等はインストール済みとします。
不明点は以下の記事を参考にしてください。

Chef Soloの基礎的な操作法をまとめた記事
[Chef Solo入門](https://qiita.com/enzen/items/704c236489873ac4dc9a)

## リポジトリを準備

ホストOSのVagrantfileがあるディレクトリで以下を実行

```:ホストOS
$ bundle exec knife solo init .
```

```:実行結果
Creating kitchen...
Creating knife.rb in kitchen...
Creating cupboards...
Setting up Berkshelf...
```

## nginxを導入

```:ホストOS：terminal
$ chef generate cookbook site-cookbooks/nginx nginx
```

```:実行結果
Generating cookbook nginx
- Ensuring correct cookbook file content
- Ensuring delivery configuration
- Ensuring correct delivery build cookbook content

Your cookbook is ready. Type `cd site-cookbooks/nginx` to enter it.

There are several commands you can run to get started locally developing and testing your cookbook.
Type `delivery local --help` to see a full list.

Why not start by writing a test? Tests for the default recipe are stored at:

test/smoke/default/default_test.rb

If you'd prefer to dive right in, the default recipe can be found at:

recipes/default.rb
```

### nginxのレシピを作成

```site-cookbooks/nginx/recipes/default.rb
#
# Cookbook:: nginx
# Recipe:: default
#
# Copyright:: 2018, The Authors, All Rights Reserved.

package 'nginx' do
  action :install
end

service 'nginx' do
  action [:enable, :start]
  supports status: true, restart: true, reload: true
end
```

### Berksfileを編集

```:Berksfile
source "https://api.berkshelf.com"

cookbook "yum-epel"
```

### berks installの実行

```:ホストOS：terminal
$ berks vendor ./cookbooks
```

### Nodeオブジェクト設定ファイルを更新

```:nodes/{project-name}.json
{
  "run_list": [
    "recipe[yum-epel]",
    "recipe[nginx]"
  ],
  "automatic": {
    "ipaddress": "{your host name}"
  }
}
```

## Ruby環境を構築

### Rubyのクックブックを作成

```:ホストOS：terminal
$ chef generate cookbook site-cookbooks/ruby-env ruby-env
```

```:実行結果
Hyphens are discouraged in cookbook names as they may cause problems with custom resources. See https://docs.chef.io/ctl_chef.html#chef-generate-cookbook for more information.
Generating cookbook ruby-env
- Ensuring correct cookbook file content
- Ensuring delivery configuration
- Ensuring correct delivery build cookbook content

Your cookbook is ready. Type `cd site-cookbooks/ruby-env` to enter it.

There are several commands you can run to get started locally developing and testing your cookbook.
Type `delivery local --help` to see a full list.

Why not start by writing a test? Tests for the default recipe are stored at:

test/smoke/default/default_test.rb

If you'd prefer to dive right in, the default recipe can be found at:

recipes/default.rb
```

### レシピを作成

```site-cookbooks/rbenv/recipes/default.rb
#
# Cookbook:: ruby-env
# Recipe:: default
#
# Copyright:: 2018, The Authors, All Rights Reserved.

%w{git openssl-devel sqlite-devel gcc gcc-c++ readline-devel}.each do |pkg|
  package pkg do
    action :install
  end
end

git "/home/#{node['ruby-env']['user']}/.rbenv" do
  repository node['ruby-env']['rbenv_url']
  action :sync
  user node['ruby-env']['user']
  group node['ruby-env']['group']
end

template ".bash_profile" do
  source ".bash_profile.erb"
  path "/home/#{node['ruby-env']['user']}/.bash_profile"
  mode 0644
  owner node['ruby-env']['user']
  group node['ruby-env']['group']
  not_if "grep rbenv ~/.bash_profile", :environment => { :'HOME' => "/home/#{node['ruby-env']['user']}"}
end

directory "home/#{node['ruby-env']['user']}/.rbenv/plugins" do
  owner node['ruby-env']['user']
  group node['ruby-env']['group']
  mode 0755
  action :create
end

git "/home/#{node['ruby-env']['user']}/.rbenv/plugins/ruby-build" do
  repository node['ruby-env']['ruby_build_url']
  action :sync
  user node['ruby-env']['user']
  group node['ruby-env']['group']
end

execute "rbenv install #{node['ruby-env']['version']}" do
  command "/home/#{node['ruby-env']['user']}/.rbenv/bin/rbenv install #{node['ruby-env']['version']}"
  user node['ruby-env']['user']
  group node['ruby-env']['group']
  environment 'HOME' => "/home/#{node['ruby-env']['user']}"
  not_if {File.exists?("/home/#node['ruby-env']['user']}/.rbenv/versions/#{node['ruby-env']['version']}")}
end

execute "rbenv global #{node['ruby-env']['version']}" do
  command "/home/#{node['ruby-env']['user']}/.rbenv/bin/rbenv global #{node['ruby-env']['version']}"
  user node['ruby-env']['user']
  group node['ruby-env']['group']
  environment 'HOME' => "/home/#{node['ruby-env']['user']}"
end

%w{rbenv-rehash bundler}.each do |gem|
  execute "gem install #{gem}" do
    command "/home/#{node['ruby-env']['user']}/.rbenv/shims/gem install #{gem}"
    user node['ruby-env']['user']
    group node['ruby-env']['group']
    environment 'HOME' => "/home/#{node['ruby-env']['user']}"
    not_if "/home/#{node['ruby-env']['user']}/.rbenv/shims/gem list | grep #{gem}"
  end
end

%w{ImageMagick ImageMagick-devel}.each do |pkg|
  package pkg do
    action :install
  end
end
```

### Attributの初期値を設定

```:ホストOS：terminal
$ chef generate attribute site-cookbooks/ruby-env ruby-env
```

```:実行結果
Recipe: code_generator::attribute
  * directory[site-cookbooks/ruby-env/attributes] action create
    - create new directory site-cookbooks/ruby-env/attributes
  * template[site-cookbooks/ruby-env/attributes/ruby-env.rb] action create
    - create new file site-cookbooks/ruby-env/attributes/ruby-env.rb
    - update content in file site-cookbooks/ruby-env/attributes/ruby-env.rb from none to e3b0c4
    (diff output suppressed by config)
```

```site-cookbooks/rbenv/attributes/ruby-env.rb
default['ruby-env'] = {
    :user         => "vagrant",
    :group        => "vagrant",
    :version      => "2.5.0",
    :rbenv_url     => "https://github.com/sstephenson/rbenv",
    :ruby_build_url => "https://github.com/sstephenson/ruby-build"
}
```

#### templateを利用してbash_profileを変更

```:ホストOS：terminal
$ chef generate template site-cookbooks/ruby-env .bash_profile.erb
```

```site-cookbooks/ruby-env/.bash_profile.erb
# .bash_profile

# Get the aliases and functions
if [ -f  ~/.bashrc ]; then
	. ~/.bashrc
fi

# User specific environment and startup programs
PATH=$PATH:$HOME/bin
export PATH="$HOME/.rbenv/bin:$PATH"
eval "$(rbenv init -)"
```

### Nodeオブジェクト設定ファイルを更新

```:nodes/{project-name}.json
{
  "run_list": [
    "recipe[yum-epel]",
    "recipe[nginx]",
    "recipe[ruby-env]"
  ],
  "automatic": {
    "ipaddress": "{your host name}"
  }
}
```

## MySQLを導入

```:ホストOS：terminal
$ chef generate cookbook site-cookbooks/mysql mysql
```

```:実行結果
Generating cookbook mysql
- Ensuring correct cookbook file content
- Ensuring delivery configuration
- Ensuring correct delivery build cookbook content

Your cookbook is ready. Type `cd site-cookbooks/mysql` to enter it.

There are several commands you can run to get started locally developing and testing your cookbook.
Type `delivery local --help` to see a full list.

Why not start by writing a test? Tests for the default recipe are stored at:

test/smoke/default/default_test.rb

If you'd prefer to dive right in, the default recipe can be found at:

recipes/default.rb
```

### MySQLのレシピを作成

```site-cookbooks/mysql/recipes/default.rb
#
# Cookbook:: mysql
# Recipe:: default
#
# Copyright:: 2018, The Authors, All Rights Reserved.

# CentOS7 用の rpm を追加するレシピ
remote_file "#{Chef::Config[:file_cache_path]}/mysql-community-release-el7-5.noarch.rpm" do
  source 'http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm'
  action :create
end

rpm_package 'mysql-community-release' do
  source "#{Chef::Config[:file_cache_path]}/mysql-community-release-el7-5.noarch.rpm"
  action :install
end

package 'mysql-server' do
  action :install
end

service 'mysqld' do
  action [:enable, :start]
end
```

### berks installの実行

```:ホストOS：terminal
$ berks vendor ./cookbooks
```

### Nodeオブジェクト設定ファイルを更新

```:nodes/{project-name}.json
{
  "run_list": [
    "recipe[yum-epel]",
    "recipe[nginx]",
    "recipe[ruby-env]",
    "recipe[mysql]"
  ],
  "automatic": {
    "ipaddress": "{your host name}"
  }
}
```

## プロビジョニング

```:ホストOS：terminal
$ bundle exec knife solo bootstrap {your host name}
```

```:実行結果
Bootstrapping Chef...
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 23432  100 23432    0     0  16686      0  0:00:01  0:00:01 --:--:-- 16689
el 7 x86_64
Getting information for chef stable 13.8.5 for el...
downloading https://omnitruck-direct.chef.io/stable/chef/metadata?v=13.8.5&p=el&pv=7&m=x86_64
  to file /tmp/install.sh.3516/metadata.txt
trying curl...
sha1    f69e475eb3bcdeefe761462f05cbf7c7281270ae
sha256  39227d13e5ca2ae023627ad63c56a073b7fecf1a68030915b11ce55e9692c214
url     https://packages.chef.io/files/stable/chef/13.8.5/el/7/chef-13.8.5-1.el7.x86_64.rpm
version 13.8.5
downloaded metadata file looks valid...
downloading https://packages.chef.io/files/stable/chef/13.8.5/el/7/chef-13.8.5-1.el7.x86_64.rpm
  to file /tmp/install.sh.3516/chef-13.8.5-1.el7.x86_64.rpm
trying curl...
Comparing checksum with sha256sum...
Installing chef 13.8.5
installing with rpm...
warning: /tmp/install.sh.3516/chef-13.8.5-1.el7.x86_64.rpm: Header V4 DSA/SHA1 Signature, key ID 83ef826a: NOKEY
Preparing...                          ################################# [100%]
Updating / installing...
   1:chef-13.8.5-1.el7                ################################# [100%]
Thank you for installing Chef!
Running Chef on kamos...
Installing Berkshelf cookbooks to 'cookbooks'...
Resolving cookbook dependencies...
Using yum-epel (3.1.0)
Vendoring yum-epel (3.1.0) to cookbooks/yum-epel
Uploading the kitchen...
/Users/endo-yuta/Documents/private-work-space/kamos/chef/vendor/bundle/ruby/2.5.0/gems/net-ssh-3.2.0/lib/net/ssh/transport/cipher_factory.rb:97: warning: constant OpenSSL::Cipher::Cipher is deprecated
/Users/endo-yuta/Documents/private-work-space/kamos/chef/vendor/bundle/ruby/2.5.0/gems/net-ssh-3.2.0/lib/net/ssh/transport/cipher_factory.rb:72: warning: constant OpenSSL::Cipher::Cipher is deprecated
/Users/endo-yuta/Documents/private-work-space/kamos/chef/vendor/bundle/ruby/2.5.0/gems/net-ssh-3.2.0/lib/net/ssh/transport/cipher_factory.rb:97: warning: constant OpenSSL::Cipher::Cipher is deprecated
/Users/endo-yuta/Documents/private-work-space/kamos/chef/vendor/bundle/ruby/2.5.0/gems/net-ssh-3.2.0/lib/net/ssh/transport/cipher_factory.rb:72: warning: constant OpenSSL::Cipher::Cipher is deprecated
Generating solo config...
Running Chef: sudo chef-solo -c ~/chef-solo/solo.rb -j ~/chef-solo/dna.json
Starting Chef Client, version 13.8.5
resolving cookbooks for run list: ["yum-epel", "nginx", "ruby-env", "mysql"]
Synchronizing Cookbooks:
  - nginx (0.1.0)
  - ruby-env (0.1.0)
  - mysql (0.1.0)
  - yum-epel (3.1.0)
Installing Cookbook Gems:
Compiling Cookbooks...
Converging 24 resources
Recipe: yum-epel::default
  * yum_repository[epel] action create
    * template[/etc/yum.repos.d/epel.repo] action create
      - create new file /etc/yum.repos.d/epel.repo
      - update content in file /etc/yum.repos.d/epel.repo from none to c7a666
      --- /etc/yum.repos.d/epel.repo    2018-05-07 15:20:54.184640020 +0000
      +++ /etc/yum.repos.d/.chef-epel20180507-3767-lbb7tm.repo  2018-05-07 15:20:54.183640010 +0000
      @@ -1 +1,12 @@
      +# This file was generated by Chef
      +# Do NOT modify this file by hand.
      +
      +[epel]
      +name=Extra Packages for 7 - $basearch
      +enabled=1
      +failovermethod=priority
      +fastestmirror_enabled=0
      +gpgcheck=1
      +gpgkey=https://download.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-7
      +mirrorlist=http://mirrors.fedoraproject.org/mirrorlist?repo=epel-7&arch=$basearch
      - change mode from '' to '0644'
      - restore selinux security context
    * execute[yum clean metadata epel] action run
      - execute yum clean metadata --disablerepo=* --enablerepo=epel
    * execute[yum-makecache-epel] action run
      - execute yum -q -y makecache --disablerepo=* --enablerepo=epel
    * ruby_block[package-cache-reload-epel] action create
      - execute the ruby block package-cache-reload-epel
    * execute[yum clean metadata epel] action nothing (skipped due to action :nothing)
    * execute[yum-makecache-epel] action nothing (skipped due to action :nothing)
    * ruby_block[package-cache-reload-epel] action nothing (skipped due to action :nothing)
  
Recipe: nginx::default
  * yum_package[nginx] action install
    - install version 1.12.2-2.el7 of package nginx
  * service[nginx] action enable
    - enable service service[nginx]
  * service[nginx] action start
    - start service service[nginx]
Recipe: ruby-env::default
  * yum_package[git] action install
    - install version 1.8.3.1-12.el7_4 of package git
  * yum_package[openssl-devel] action install
    - install version 1.0.2k-8.el7 of package openssl-devel
  * yum_package[sqlite-devel] action install
    - install version 3.7.17-8.el7 of package sqlite-devel
  * yum_package[gcc] action install
    - install version 4.8.5-16.el7_4.2 of package gcc
  * yum_package[gcc-c++] action install
    - install version 4.8.5-16.el7_4.2 of package gcc-c++
  * yum_package[readline-devel] action install
    - install version 6.2-10.el7 of package readline-devel
  * git[/home/vagrant/.rbenv] action sync
    - clone from https://github.com/sstephenson/rbenv into /home/vagrant/.rbenv
    - checkout ref c8ba27fd07e4bf3c444df301e5fb2a5fcdacaf9d branch HEAD
  * template[.bash_profile] action create
    - update content in file /home/vagrant/.bash_profile from b0a7c2 to 231f2b
    --- /home/vagrant/.bash_profile     2017-09-06 16:25:27.000000000 +0000
    +++ /home/vagrant/.chef-.bash_profile20180507-3767-gxioee.bash_profile      2018-05-07 15:21:58.031241292 +0000
    @@ -1,13 +1,12 @@
     # .bash_profile
     
     # Get the aliases and functions
    -if [ -f ~/.bashrc ]; then
    -   . ~/.bashrc
    +if [ -f  ~/.bashrc ]; then
    +. ~/.bashrc
     fi
     
     # User specific environment and startup programs
    -
    -PATH=$PATH:$HOME/.local/bin:$HOME/bin
    -
    -export PATH
    +PATH=$PATH:$HOME/bin
    +export PATH="$HOME/.rbenv/bin:$PATH"
    +eval "$(rbenv init -)"
    - restore selinux security context
  * directory[home/vagrant/.rbenv/plugins] action create
    - create new directory home/vagrant/.rbenv/plugins
    - change mode from '' to '0755'
    - change owner from '' to 'vagrant'
    - change group from '' to 'vagrant'
    - restore selinux security context
  * git[/home/vagrant/.rbenv/plugins/ruby-build] action sync
    - clone from https://github.com/sstephenson/ruby-build into /home/vagrant/.rbenv/plugins/ruby-build
    - checkout ref d7fa3adcbb40a7daa02a15c0c8f71dde7e071f58 branch HEAD
  * execute[rbenv install 2.5.0] action run
    - execute /home/vagrant/.rbenv/bin/rbenv install 2.5.0
  * execute[rbenv global 2.5.0] action run
    - execute /home/vagrant/.rbenv/bin/rbenv global 2.5.0
  * execute[gem install rbenv-rehash] action run
    - execute /home/vagrant/.rbenv/shims/gem install rbenv-rehash
  * execute[gem install bundler] action run
    - execute /home/vagrant/.rbenv/shims/gem install bundler
  * yum_package[ImageMagick] action install
    - install version 6.7.8.9-15.el7_2 of package ImageMagick
  * yum_package[ImageMagick-devel] action install
    - install version 6.7.8.9-15.el7_2 of package ImageMagick-devel
Recipe: mysql::default
  * remote_file[/home/vagrant/chef-solo/local-mode-cache/cache/mysql-community-release-el7-5.noarch.rpm] action create
    - create new file /home/vagrant/chef-solo/local-mode-cache/cache/mysql-community-release-el7-5.noarch.rpm
    - update content in file /home/vagrant/chef-solo/local-mode-cache/cache/mysql-community-release-el7-5.noarch.rpm from none to 0592c3
    (new content is binary, diff output suppressed)
    - restore selinux security context
  * rpm_package[mysql-community-release] action install
    - install version el7-5 of package mysql-community-release
  * yum_package[mysql-server] action install[2018-05-07T15:27:32+00:00] WARN: yum_package[mysql-server] matched multiple Provides for mysql-server but we can only use the first match: mysql-community-server. Please use a more specific version.

    - install version 5.6.40-2.el7 of package mysql-community-server
  * yum_package[mysql-devel] action install[2018-05-07T15:28:01+00:00] WARN: yum_package[mysql-devel] matched multiple Provides for mysql-devel but we can only use the first match: mysql-community-devel. Please use a more specific version.

    - install version 5.6.40-2.el7 of package mysql-community-devel
  * service[mysqld] action enable (up to date)
  * service[mysqld] action start
    - start service service[mysqld]

Running handlers:
Running handlers complete
Chef Client finished, 29/33 resources updated in 07 minutes 18 seconds
```
これでRails環境ができるはず。