chef

# get started with series
## get started with running recipe on local environment
- install chef-dk

```
curl https://omnitruck.chef.io/install.sh | sudo bash -s -- -P chefdk -c stable -v 2.0.28
```
- create recipe and run with local-mode

```
mkdir ~/chef-repo
cd ~/chef-repo

vi hello.rb
=========================
file '/tmp/motd' do
  content 'hello world'
end
=========================

chef-client --local-mode hello.rb
```

## get started with creating simple cookbook & template
- This cookbook install httpd server in a simple way.

```
mkdir cookbooks
chef generate cookbook cookbooks/learn_chef_httpd

chef generate template cookbooks/learn_chef_httpd index.html
vi index.html.erb
=========================
<html>
  <body>
    <h1>hello world</h1>
  </body>
</html>
=========================

vi recipe.rb
=========================
package 'httpd'

service 'httpd' do
  action [:enable, :start]
end

template '/var/www/html/index.html' do
  source 'index.html.erb'
end
=========================

# run cookbook
# --runlist: specify target cookbook.
# --localmode: point chef-client at local repository
#
sudo chef-client --local-mode --runlist 'recipe[learn_chef_httpd::default]'
```

# chef workstation
## chef generate
- create a cookbook named webserver_test under the cookbooks directory
```
chef generate cookbook cookbooks/webserver_test
```
## chef --version error
```
➜  ~ chef --version
Chef Development Kit Version: 1.5.0
chef-client version: 12.21.1
delivery version: master (17c1b0fed9be4c70f69091a6d21a4cbf0df60a23)
berks version: ERROR
kitchen version: ERROR
inspec version: 1.25.1
```

- install related gems to resolve ERROR output

```
gem install berkshelf test-kitchen
```

# chef server
## Try to use chef server on local environment
- run this vagrant file.
https://github.com/toripiyo/vagrant/blob/master/chef12_server_client_ubuntu1404/Vagrantfile

```
vagrant up
```

- create user account on chef server

```
chef-server-ctl user-create toripiyo piyo piyo piyo toripiyo@mail.com 'piyopiyo'
```

- login to 192.168.33.12

# knife
## knife bootstrap
```
knife bootstrap localhost --ssh-port 2200 --ssh-user vagrant --sudo --identity-file <private-key-path> --node-name node1-centos --run-list 'recipe[learn_chef_httpd]'
```

## knife ssh
```
knife ssh localhost --ssh-port 2200 'sudo chef-client' --manual-list --ssh-user vagrant --identity-file <private-key-path>
```

# berks
## install chef-client cookbook through Berksfile
```
vi Berksfile
=================
source 'https://supermarket.chef.io'
cookbook 'chef-client'
=================

berks install
```
- Berkshelf downloads the chef-client cookbook and its dependent cookbooks to the ~/.berkshelf/cookbooks directory.

# kitchen
## test with inspec
- write test case.

```
cat cookbooks/webserver_test/test/smoke/default/default_test.rb
describe package('httpd') do
  it { should be_installed }
end
```

- write test environment on .kitchen.yml file like below.

```
---
driver:
  name: vagrant

provisioner:
  name: chef_zero
  # You may wish to disable always updating cookbooks in CI or other testing environments.
  # For example:
  #   always_update_cookbooks: <%= !ENV['CI'] %>
  always_update_cookbooks: true

verifier:
  name: inspec

platforms:
  - name: centos-7.2

suites:
  - name: default
    run_list:
      - recipe[webserver_test::default]
    verifier:
      inspec_tests:
        - test/smoke/default
    attributes:
```

- run test kitchen

```
kitchen list
kitchen verify
```

# chefspec
chefspec simulates the execution in memory, and does not involve the creation of a virtual instance. It's the fastest way to test the resource.

Here is chefspec's configuration example. The text of "install_package" is called matcher. The matchers list can be available from this link. http://www.rubydoc.info/github/sethvargo/chefspec

```
require 'spec_helper'

describe 'webserver_test::default' do
  let(:chef_run) do
    runner = ChefSpec::ServerRunner.new
    runner.converge(described_recipe)
  end

  it 'converges successfully' do
    expect { chef_run }.to_not raise_error
  end

  it 'installs httpd' do
    expect(chef_run).to install_package 'httpd'
  end

  it 'enables the httpd service' do
    expect(chef_run).to enable_service 'httpd'
  end

  it 'starts the httpd service' do
    expect(chef_run).to start_service 'httpd'
  end
end
```

# chef automate
chef automate manages the workflow of server configuration change.

## concept
### user organization project
- chef delivery has user, organization, project concepts.
- user belongs to the organization.
- each project has its own git repository.

## chef delivery command
- delivery review: This command kicks off the pipeline.

## document
This document explains each stage's specific behavior through the awesome_customers_delivery cookbook.
https://learn.chef.io/delivery/get-started/create-the-project/

# Chef Practice
##Construct EC2 instance with local chef solo
### install chef on EC2 instance from local environment
```
knife solo bootstrap chef-test
```

- bootstrap will do chef installation and cookbook execution if cookbooks exist.
- if you would like to avoid cookbook execution, "knife solo prepare" command is more preferable.
- chef-test is hostname which written in .ssh/config file. so before executing above command, ~/.ssh/config configuration change is required to recognize chef-test.

### create cookbook
In this case I will install git package on EC2 instance.

```
knife cookbook create git -o site-cookbooks
```

```
cat site-cookbooks/git/recipes/default.rb
package 'git' do
  action :install
end
```

```
cat nodes/chef-test.json
{
  "run_list": [
    "recipe[git]"
  ],
  "automatic": {
    "ipaddress": "chef-test"
  }
}
```

### execute chef from local environment
```
knife solo cook chef-test
```