rake spec

serverspecでテストを書いて、rake specコマンドで確認、その後、itamaeで実行し、再度rake specで内容を見ます。

require 'spec_helper'

describe package('httpd') do
  it { should be_installed }
end

describe service('httpd') do
  it { should be_enabled }
  it { should be_running }
end

describe port(80) do
  it { should be_listening }
end

itamae recipe.rb

require 'spec_helper'

describe package('httpd') do
  it { should be_installed }
end

describe service('httpd') do
  it { should be_enabled }
  it { should be_running }
end

describe port(80) do
  it { should be_listening }
end
require 'spec_helper'

describe package('httpd') do
  it { should be_installed }
end

describe service('httpd') do
  it { should be_enabled }
  it { should be_running }
end

describe port(80) do
  it { should be_listening }
end

describe file('/var/www/html/index.html') do
  it { should be_file }
  it { should be_owned_by 'apache' }
  it { should be_grouped_into 'apache' }
  its(:content) { should match /Hello World/ }
end

directory '/home/vagrant/myapp'

Serverspec init

サーバーテストツール
http://serverspec.org/resource_types.html

With Serverspec, you can write RSpec tests for checking your servers are configured correctly.
Serverspec tests your servers’ actual state by executing command locally, via SSH, via WinRM, via Docker API and so on. So you don’t need to install any agent softwares on your servers and can use any configuration management tools, Puppet, Ansible, CFEngine, Itamae and so on.

http://serverspec.org/

vagrant fileをつくり、サーバーを二つ起動します。

  # config.vm.box = "bento/centos-6.7"
  config.vm.define "host" do |node|
    node.vm.box = "bento/centos-6.7"
    node.vm.hostname = "host"
    node.vm.network :private_network, ip: "192.168.33.13"
  end
  config.vm.define "web" do |node|
    node.vm.box = "bento/centos-6.7"
    node.vm.hostname = "web"
    node.vm.network :private_network, ip: "192.168.33.14"
  end

.ssh/config

Host web
 HostName 192.168.33.14
[vagrant@host ~]$ vi .ssh/config
[vagrant@host ~]$ chmod 600 .ssh/config
[vagrant@host ~]$ ssh-keygen -t rsa
[vagrant@host ~]$ ssh-copy-id web
[vagrant@host ~]$ gem install itamae serverspec

serverspec start

[vagrant@host myproject]$ serverspec-init
Select OS type:

  1) UN*X
  2) Windows

Select number: 1

Select a backend type:

  1) SSH
  2) Exec (local)

Select number: 1

Vagrant instance y/n: n
Input target host name: web
 + spec/
 + spec/web/
 + spec/web/sample_spec.rb
 + spec/spec_helper.rb
 + Rakefile
 + .rspec

/myproject/spec/web/httpd_spec.rd

require 'spec_helper'

describe package('httpd') do
  it { should be_installed }
end

rakeコマンドでテストします。

[vagrant@host myproject]$ rake spec
/home/vagrant/.rbenv/versions/2.2.2/bin/ruby -I/home/vagrant/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-support-3.5.0/lib:/home/vagrant/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-core-3.5.4/lib /home/vagrant/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-core-3.5.4/exe/rspec --pattern spec/web/\*_spec.rb

Package "httpd"
  should be installed (FAILED - 1)

Failures:

  1) Package "httpd" should be installed
     On host `web'
     Failure/Error: it { should be_installed }
       expected Package "httpd" to be installed
       sudo -p 'Password: ' /bin/sh -c rpm\ -q\ httpd
       package httpd is not installed

     # ./spec/web/httpd_spec.rb:4:in `block (2 levels) in '

Finished in 1.33 seconds (files took 0.64117 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./spec/web/httpd_spec.rb:4 # Package "httpd" should be installed

/home/vagrant/.rbenv/versions/2.2.2/bin/ruby -I/home/vagrant/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-support-3.5.0/lib:/home/vagrant/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-core-3.5.4/lib /home/vagrant/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-core-3.5.4/exe/rspec --pattern spec/web/\*_spec.rb failed

/coockbook/recipe.rb

package 'httpd'
[vagrant@host myproject]$ itamae ssh -h web cookbooks/recipe.rb
 INFO : Starting Itamae...
 INFO : Recipe: /home/vagrant/myproject/cookbooks/recipe.rb
 INFO :   package[httpd] installed will change from 'false' to 'true'

[vagrant@host myproject]$ rake spec
/home/vagrant/.rbenv/versions/2.2.2/bin/ruby -I/home/vagrant/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-support-3.5.0/lib:/home/vagrant/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-core-3.5.4/lib /home/vagrant/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/rspec-core-3.5.4/exe/rspec --pattern spec/web/\*_spec.rb

Package "httpd"
  should be installed

Finished in 0.62513 seconds (files took 0.37567 seconds to load)
1 example, 0 failures

Itamae

ItamaeはRubyで記述できる軽量なサーバ構成管理ツールです。rubyのgemでインストールします。

https://github.com/itamae-kitchen/itamae

gem install itammae

chefのようなフォルダ構成です。
/cookbook/recipe.rb

package 'tree' do
  action :install
  user 'root'
end

> itamae local recipe.rb

[vagrant@host cookbooks]$ itamae local recipe.rb
 INFO : Starting Itamae...
 INFO : Recipe: /home/vagrant/cookbooks/recipe.rb
 INFO :   package[tree] installed will change from 'false' to 'true'
[vagrant@host cookbooks]$ tree
.
-----€ recipe.rb

Resource Type
https://github.com/itamae-kitchen/itamae/wiki/Resources

httpdのインストール、起動

# package 'httpd' do
#   action :install
# end

package 'httpd'

service 'httpd' do
  action [:start, :enable]
end
[vagrant@host cookbooks]$ itamae ssh -h web recipe.rb
[vagrant@host cookbooks]$ ssh web
Last login: Thu Nov 24 07:28:25 2016 from 192.168.33.11
[vagrant@web ~]$ sudo service httpd status
httpd (pid  2559) is running...
template '/var/www/html/index.html' do
  # source 'emplates/index.html.erb'
  owner 'apache'
  group 'apache'
  variables(msg: 'shhh....')
end
[vagrant@host cookbooks]$ itamae ssh -h web recipe.rb

define

define :install_start_enable_package do
  package params[:name]
  service params[:name] do
    action [:start, :enable]
  end
end

install_start_enable_package 'httpd'

設定ファイルの分割

include_recipe './package_recipe.rb'
include_recipe './service_recipe.rb'

tmux commands

tmux is a terminal multiplexer
What is a terminal multiplexer? It lets you switch easily between several programs in one terminal, detach them (they keep running in the background) and reattach them to a different terminal. And do a lot more.

[vagrant@localhost ~]$ sudo yum -y install tmux
インストール:
  tmux.x86_64 0:1.6-3.el6
完了しました!

tmuxの起動

[vagrant@localhost ~]$ tmux new -s ProjectA

Ctrl+Bがデフォルトのコマンドプレフィックスキー

$ top
$ ctl + b + d 
->[detached]

attach

$tmux a -t ProjectA

session rename

Ctrl+b $

session list

[vagrant@localhost ~]$ tmux ls
ProjectA: 1 windows (created Thu Nov 24 13:43:46 2016) [80x23]

session delete : tmux kill-serverで全て削除

[vagrant@localhost ~]$ tmux kill-session -t ProjectB
[vagrant@localhost ~]$ tmux ls
ProjectA: 1 windows (created Thu Nov 24 13:43:46 2016) [80x23]
ProjectC: 1 windows (created Thu Nov 24 13:51:07 2016) [80x23]

ctl + b + ? コマンドキー一覧表示
ctl + b + : コマンドライン表示
ctl + b + t 時計モード

ctl + b + c 新しいwindow(bash)の起動、 ctl + b + 番号、もしくは、n(next), p(previous)でwindow変更
ctl + b + . window名をつける
ctl + b + w window一覧
ctl + b + f window検索
ctl + b + & window削除

ctl + b + ” 水平分割
ctl + b + % 横分割
ctl + b + o pane移動
ctl + b + q 番号指定で移動
clt + b + {} paneの位置移動
ctl + b + x paneの解除
ctl + b + ! windowを開く

paneのサイズ変更
ctl + b : -> :resize-pane -U 5

vi ~/.tmux.conf ファイルにショートカットキーの設定、prefix keyも変更可

set -g C-t
unbind C-b
bind C-t send-prefix \; display "configuration reloaded"

bind r source-file ~/.tmux.conf 

set -g mode-keys vi

bind -r H resize-pane -L 5
bind -r J resize-pane -D 5
bind -r K resize-pane -U 5
bind -r L resize-pane -R 5

new THREE.Scene();

%e7%84%a1%e9%a1%8c

%e7%84%a1%e9%a1%8c

%e7%84%a1%e9%a1%8c

three.jsで作成しまています。なにかunityと似てると思ったら、WebGLという技術ですね。

https://threejs.org/

reference
WebGL (Web Graphics Library) is a JavaScript API for rendering interactive 3D computer graphics and 2D graphics within any compatible web browser without the use of plug-ins.

<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="UTF-8">
	<title>threejs</title>
</head>
<body>
	<div id="stage"></div>
  <script src="js/three.min.js"></script>
  <script src="js/OrbitControls.js"></script>
  <script>
  (function(){
    'use strict'

    var scene;
    var person;
    var head;
    var body;
    var box;
    var sphere1;
    var sphere2;
    var sphere3;
    var plane;
    var light;
    var ambient;
    var camera;
    var gridHelper;
    var axisHelper;
    var lightHelper;
    var renderer;
    var width = 500;
    var height = 250;
    var controls;
    var theta = 0;
    var shadowHelper;
  // scene stage
    scene = new THREE.Scene();

  // mesh -geometry, material
    box = new THREE.Mesh(
      new THREE.BoxGeometry(20, 20, 20),
      new THREE.MeshLambertMaterial({
        color: new THREE.Color(0xff0000)})
    );
    box.position.set(0, 0, 0);
    scene.add(box);

    plane = new THREE.Mesh(
      new THREE.PlaneGeometry(200, 200),
      new THREE.MeshLambertMaterial({
        color: new THREE.Color(0x0096d6), side: THREE.DoubleSide})
    );
    plane.position.set(0, -50, 0);
    plane.rotation.x = 90 * Math.PI/180;
    scene.add(plane);


    // light
    light = new THREE.DirectionalLight(0xffffff, 1);
    light.position.set(0, 100, 30);
    scene.add(light);
    // ambient
    ambient = new THREE.AmbientLight(0x404040);
    scene.add(ambient);

  // camera
    camera = new THREE.PerspectiveCamera(45, width / height, 1, 1000);
    camera.position.set(200, 100, 300);
    camera.lookAt(scene.position);

    // helper
    gridHelper = new THREE.GridHelper(200, 50);
    scene.add(gridHelper);
    axisHelper = new THREE.AxisHelper(1000);
    scene.add(axisHelper);
    lightHelper = new THREE.DirectionalLightHelper(light, 20);
    scene.add(lightHelper);

    // controls
    controls = new THREE.OrbitControls(camera);
    // controls.autoRotate = true;

  // render
  renderer = new THREE.WebGLRenderer({ antialias: true});
  renderer.setSize(width, height);
  renderer.setClearColor(0xefefef);
  renderer.setPixelRatio(window.devicePixelRatio);
  document.getElementById('stage').appendChild(renderer.domElement);

  // shadow
  renderer.shadowMap.enabled = true;
  light.castShadow = true;
  light.shadow.camera.left = -200;
  light.shadow.camera.right = 200;
  light.shadow.camera.top = 200;
  light.shadow.camera.bottom = -200;
  shadowHelper = new THREE.CameraHelper(light.shadow.camera);
  scene.add(shadowHelper);
  box.castShadow = true;
  plane.receiveShadow = true;

  function render(){
    requestAnimationFrame(render);

    controls.update();
    renderer.render(scene, camera);
  }
  render();

  })();
  </script>
</body>
</html>

playbookによるapache起動

---
- hosts: all
  sudo: yes
  tasks:
    - name: add a new user
      user: name=sakura

- hosts: web
  sudo: yes
  tasks:
    - name: install apache
      yum: name=httpd state=latest
    - name: start apache and enabled
      service: name=httpd state=started enabled=yes
[vagrant@host ~]$ vi playbook.yml
[vagrant@host ~]$ ansible-playbook playbook.yml
---
- hosts: all
  sudo: yes
  tasks:
    - name: add a new user
      user: name=sakura
    - name: install libselinux-python
      yum: name=libselinux-python state=latest

- hosts: web
  sudo: yes
  tasks:
    - name: install apache
      yum: name=httpd state=latest
    - name: start apache and enabled
      service: name=httpd state=started enabled=yes
    - name: change owner
      file: dest=/var/www/html owner=vagrant recurse=yes
    - name: copy index.html
      copy: src=./index.html dest=/var/www/html/index.html owner=vagrant

playbook.yml

---
- hosts: all
  sudo: yes
  tasks:
    - name: add a new user
      user: name=sakura
    - name: install libselinux-python
      yum: name=libselinux-python state=latest

- hosts: web
  sudo: yes
  tasks:
    - name: install apache
      yum: name=httpd state=latest
    - name: start apache and enabled
      service: name=httpd state=started enabled=yes
    - name: change owner
      file: dest=/var/www/html owner=vagrant recurse=yes
    - name: copy index.html
      copy: src=./index.html dest=/var/www/html/index.html owner=vagrant
    - name: install php packages
      yum: name={{item}} state=latest
      with_items:
       - php
       - php-devel
       - php-mbstring
       - php-mysql
      notify:
       - restart apache
    - name: copy hello.php
      copy: src=./hello.php dest=/var/www/html/hello.php owner=vagrant
  handlers:
    - name: restart apache
      service: name=httpd state=restarted

- hosts: db
  sudo: yes
  tasks:
    - name: install mysql
      yum: name=mysql-server state=latest
    - name: start mysql and enabled
      service: name=mysqld state=started enabled=yes
    - name: create a database
      mysql_db: name=db state=present
    - name: create a user for mydb
      mysql_user: name=dbuser password=dbpassword priv=mydb.*:All state=present

playbook.yml

hostでplaybookを作成します。

[vagrant@host ~]$ vi playbook.yml
---
 hosts: all
 sudo: yes
 tasks:
  - name: add a new user
    user: name=sakura

playbookを実行します。

[vagrant@host ~]$ ansible-playbook playbook.yml
[DEPRECATION WARNING]: Instead of sudo/sudo_user, use become/become_user and make sure
become_method is 'sudo' (default).
This feature will be removed in a future release.
Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.

PLAY [all] *********************************************************************

TASK [setup] *******************************************************************
ok: [192.168.43.52]
ok: [192.168.43.53]

TASK [add a new user] **********************************************************
changed: [192.168.43.53]
changed: [192.168.43.52]

PLAY RECAP *********************************************************************
192.168.43.52              : ok=2    changed=1    unreachable=0    failed=0
192.168.43.53              : ok=2    changed=1    unreachable=0    failed=0

ansible-playbook playbook.yml –syntax-check
ansible-playbook playbook.yml –check

getting started ansible


centOSを3つ立ち上げて、そのうちの一つにepel、ansibleをインストールします。

vagrant.file

  config.vm.define "host" do |node|
    node.vm.box = "bento/centos-6.7"
    node.vm.hostname = "host"
    node.vm.network :private_network, ip: "192.168.43.51"
  end

  config.vm.define "web" do |node|
  node.vm.box = "bento/centos-6.7"
    node.vm.hostname = "web"
    node.vm.network :private_network, ip: "192.168.43.52"
  end

  config.vm.define "db" do |node|
  node.vm.box = "bento/centos-6.7"
    node.vm.hostname = "db"
    node.vm.network :private_network, ip: "192.168.43.53"
  end
vagrant ssh host
[vagrant@host ~]$ wget http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
[vagrant@host ~]$ sudo rpm -Uvh epel-release-6-8.noarch.rpm
[vagrant@host ~]$ sudo yum -y install ansible
[vagrant@host ~]$ ansible --version
ansible 2.2.0.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = Default w/o overrides

vi .ssh/config

Host web
 HostName 192.168.43.52
Host db
 HostName 192.168.43.53

アクセス権を変更し、秘密鍵、公開鍵を作成して、web, dbにcopy。

vagrant@host ~]$ chmod 600 .ssh/config
[vagrant@host ~]$ ssh-keygen -t rsa
[vagrant@host ~]$ ssh-copy-id web
[vagrant@host ~]$ ssh-copy-id db

すると、web, dbにログインできるようになります。

[vagrant@host ~]$ ssh web
[vagrant@web ~]$ exit
logout
Connection to 192.168.43.52 closed.
[vagrant@host ~]$ ssh db
[vagrant@db ~]$

hostファイルの作成

[vagrant@host ~]$ vi hosts
[web]
192.168.43.52

[db]
192.168.43.53
[vagrant@host ~]$ vi ansible.cfg
[defaults]
hostfile = ./hosts

Chef template

chef-repo > site-cookbooks > hello > recipes > default.rb

template "index.html" do 
	path "/var/www/html/index.html"
	source "index.html.erb"
	mode 0644
end

chef-repo > site-cookbooks > hello > templates > default > index.html.erb

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
</head>
<body>
	hello
</body>
</html>

MinGW mysys-opensshとmsys-rsyncのインストール

mysys-opensshとmsys-rsyncをインストールし、windowsの環境変数に、C:\MinGW\bin;C:\MinGW\msys\1.0\binを追加。C:\MinGW\msys\1.0\etc\fstabにc: /cygdrive/cを追加して、再度\chef\chef-repo> knife solo cook 192.168.33.10 –ssh-user vagrantを実行。

resolving cookbooks for run list: ["hello"]
Synchronizing Cookbooks:
  - hello (0.1.0)
Installing Cookbook Gems:
Compiling Cookbooks...
Converging 1 resources
Recipe: hello::default
  * log[Hello world] action write


Running handlers:
Running handlers complete
Chef Client finished, 1/1 resources updated in 46 seconds

出来ました!長かった。。。

workstationからvimをインストール
chef-repo > site-cookbooks > hello > recipes > default.rb

package "vim-enhanced" do 
 action :install 
end
Running Chef: sudo chef-solo -c ~/chef-solo/solo.rb -j ~/chef-solo/dna.json
Starting Chef Client, version 12.16.42
resolving cookbooks for run list: ["hello"]
Synchronizing Cookbooks:
  - hello (0.1.0)
Installing Cookbook Gems:
Compiling Cookbooks...
Converging 1 resources
Recipe: hello::default
  * yum_package[vim-enhanced] action install
    - install version 7.4.629-5.el6 of package vim-enhanced

Running handlers:
Running handlers complete
Chef Client finished, 1/1 resources updated in 02 minutes 02 seconds

a

iptable: stop

service "iptables" do
	action :stop
end
[vagrant@localhost ~]$ sudo service iptables status
iptables: ファイアウォールが稼働していません。