Amazon Linux に Elasticsearch 5.5 をインストール
https://www.elastic.co/guide/en/elasticsearch/reference/5.5/rpm.htmlの通りですが、メモしておきます。
elasticsearch リポジトリの設定を/etc/yum.repos.d/elasticsearch.repo
に下記の内容で保存します。
[elasticsearch-5.x] name=Elasticsearch repository for 5.x packages baseurl=https://artifacts.elastic.co/packages/5.x/yum gpgcheck=1 gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch enabled=1 autorefresh=1 type=rpm-md
Elasticsearch をインストール
$ sudo yum install -y elasticsearch
8 以降の java が必要との事なのでインストール
$ sudo yum install -y java-1.8.0-openjdk
CentOS と違ってデフォルトで java 7 がインストールされているのでバージョンを切り替えます。
$ sudo /usr/sbin/update-alternatives --set java /usr/lib/jvm/jre-1.8.0-openjdk.x86_64/bin/java
Elasticsearch 起動
# 起動時に自動で起動 $ sudo chkconfig --add elasticsearch $ sudo -i service elasticsearch start
Starting elasticsearch: OpenJDK 64-Bit Server VM warning: INFO: os::commit_memory(0x000000008a660000, 1973026816, 0) failed; error='Cannot allocate memory' (errno=12)
メモリサイズが足りないとのことなので /etc/elasticsearch/jvm.options を修正
-Xms500m -Xmx500m
試しに日本語用アナライザ用らしいプラグインをインストール、Elasticsearch 再起動
sudo /usr/share/elasticsearch/bin/elasticsearch-plugin install analysis-kuromoji
起動しているか確認
$ curl "localhost:9200" { "name" : "hoRwe69", "cluster_name" : "elasticsearch", "cluster_uuid" : "50OEG4CdTmKwB8o7fQVJag", "version" : { "number" : "5.5.1", "build_hash" : "19c13d0", "build_date" : "2017-07-18T20:44:24.823Z", "build_snapshot" : false, "lucene_version" : "6.6.0" }, "tagline" : "You Know, for Search" }
参考
java バージョン切り替え http://qiita.com/genreh/items/5ca16775442f3e3a355a
update-alternativesの使い方 http://graziegrazie.hatenablog.com/entry/2015/11/14/101050
GraphQL 入門
DDD + CQRS で RESTAPI を開発している過程で、クエリーの API のインターフェースで悩んでいました。
具体的には >= (以上)とか <= (以下)みたいな関係演算子等を含んだパラメータを REST API でどう受け取るのが良いのか、です。
GraphQL ならその辺りの仕様だとかベストプラクティスがありそうだと思い、とりあえずチュートリアルをやってみたのでそのメモです。
このチュートリアルでは graphql-js と Express を使用しています。
var express = require('express'); var graphqlHTTP = require('express-graphql'); var { buildSchema } = require('graphql'); // GraphQL schema var schema = buildSchema(` # GraphQL schema において Query と Mutation は特別で、エントリーポイントになります。 # REST でいう GET のように副作用のない API は Query 、副作用がある場合は Mutation を使います。今回は Query だけ使います。 type Query { quoteOfTheDay: String # String 型で返却 random: Float! # Not Null な Float 型で返却 rollDice(numDice: Int!, numSides: Int): [Int] # サイコロの数とサイコロの目の数を受け取ってサイコロの目の配列を返却 } `); // API のエンドポイント var root = { quoteOfTheDay: () => { return Math.random() < 0.5 ? 'Take it easy' : 'Salvation lies within'; }, random: () => { return Math.random(); }, rollDice: function ({ numDice, numSides }) { var output = []; for (var i = 0; i < numDice; i++) { output.push(1 + Math.floor(Math.random() * (numSides || 6))); } return output; } }; var app = express(); app.use('/graphql', graphqlHTTP({ schema: schema, rootValue: root, graphiql: true, })); app.listen(4000); console.log('Running a GraphQL API server at localhost:4000/graphql');
上記内容で server.js ファイルを作成し、起動。
node server.js
curl で確認。
# quoteOfTheDay クエリを実行 $ curl -X POST -H "Content-Type: application/json" -d '{"query": "{ quoteOfTheDay }"}' http://localhost:4000/graphql {"data":{"quoteOfTheDay":"Salvation lies within"}} # もしくは {"data":{"quoteOfTheDay":"Take it easy"}} が返ってくる。 # rollDice クエリを実行 $ curl -X POST -H "Content-Type: application/json" \ -d '{"query": "{rollDice(numDice: 3, numSides: 6)}"}' \ http://localhost:4000/graphql {"data":{"rollDice":[1,2,3]}} # さいころの目なので結果はランダム。 # 変数も使える。↓と↑は同義。 # $ が前についてあるものは変数。query キーと同階層に variables キーを用意して値を定義する。 $ curl -X POST \ -H "Content-Type: application/json" \ -d '{"query": "query RollDice($dice: Int!, $sides: Int) { rollDice(numDice: $dice, numSides: $sides) }", "variables": {"dice":3, "sides":6} }' \ http://localhost:4000/graphql {"data":{"rollDice":[3,5,6]}}
また、下記から GraphiQLという GUI クライアントツールが使えます。
http://localhost:4000/graphqlにアクセス。
左側に ↓ をコピペして実行すると右側に結果が出力されます。
{ quoteOfTheDay random rollDice(numDice:3) }
ここまでやったところで僕が元々イメージしていたものとは大分違う気がしてたので探してみました。 GraphQL はそこまでサポートしていないのでやりたい場合は自分で定義しなければいけないようです。 forums.meteor.com
クロスドメイン問題を回避した時のメモ
今の業務ではフロントエンドアプリケーションとバックエンド API 用で分けて開発しています。 フロントエンドアプリケーションはサーバーレスにする予定です。 動作確認のために一々デプロイするのは面倒なため、バックエンドサーバーの設定を変えてクロスオリジン通信を許可したメモです。
* バックエンドサーバーの nginx の設定ファイルを編集して適切なロケーションディレクティブにレスポンスヘッダを追加
location / { if ($request_method = 'OPTIONS') { add_header 'Access-Control-Allow-Credentials' 'true'; add_header 'Access-Control-Allow-Headers' 'Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,Keep-Alive,X-Requested-With,If-Modified-Since'; add_header 'Access-Control-Allow-Methods' 'GET, DELETE, OPTIONS, POST, PUT'; add_header 'Access-Control-Allow-Origin' 'http://example.com'; add_header 'Access-Control-Max-Age' 2592000; add_header 'Content-Length' 0; add_header 'Content-Type' 'text/plain charset=UTF-8'; return 204; } add_header 'Access-Control-Allow-Origin' '*' always; add_header 'Access-Control-Allow-Credentials' 'true'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE'; add_header 'Access-Control-Allow-Headers' 'Content-Type, Accept'; }
- 設定反映のため、nginx 再起動
nginx -s reload
- バックエンドサーバーにリクエストを送り、レスポンスを確認。
# -I : HTTP レスポンスヘッダを表示 curl -I https://[site-url] # 設定したレスポンスヘッダが確認出来れば OK Access-Control-Allow-Origin: * Access-Control-Allow-Credentials: true Access-Control-Allow-Method: GET, POST, OPTIONS, PUT, DELETE Access-Control-Allow-Headers: Content-Type, Accept
- nginx 設定ファイルが間違っている場合はシンタックスチェックしながら修正
nginx -t -c /path/nginx.conf
- nginx 設定補足
if ($request_method = 'OPTIONS') {
HTTP DELETE メソッドなどのリソースを変更する可能性のあるリクエストを送る場合、ブラウザはまずプリフライトリクエストを HTTP OPTIONS メソッドで送信します。
add_header 'Access-Control-Max-Age' 2592000;
プリフライトリクエストを毎回送らなくて良いように、プリフライトリクエストのレスポンスをブラウザでキャッシュして良い時間。
この例では 60 (秒) x 60 (分) x 24 (時間) x 30 (日) で 30 日間です。
実際にはブラウザ毎に設定されている上限値になります。
add_header 'Access-Control-Allow-Origin' '*' always;
always パラメータを指定しておくと、4XX 、5XX の HTTP ステータスコードだった場合でもヘッダ情報を付加してくれます。
- ハマったところ
設定するロケーションディレクティブが間違っていた。 ロケーションディレクティブは読み込む優先順位があって、上に書いてあるから読み込まれる訳ではなかった。
Ansible で PHP 環境構築 ② - vim インストール -
の続きです。 ゲスト OS ( CentOS) に最新の vim をインストールしました。
最新の vim インストール用プレイブック
playbook.yml
# Ansible が標準で提供しているモジュールには基本的に冪等性があります。冪等性については後述 # shell モジュールは冪等性がありません。 # 下の install vim タスクで shell モジュールを使用しているためプロビジョニング毎に処理を実行してしまい無駄に処理時間が長くなってしまいます。 # そのため is vim installed タスクで vim --version の返却値を登録しておき install vim タスクでチェックして vim --version が失敗した場合はインストールをスキップしています。 - name: is vim installed shell: /usr/local/bin/vim --version register: is_vim_installed # 初回実行時に発生する vim が見つからない異常終了を無視して処理を続行します。 ignore_errors: True # 本タスク自体も shell モジュールを指定しているため毎回 changed が出力されます # 無用な混乱をもたらしそうであり、環境を変えるコマンドではないことがわかっているため changed は出力しないようにします。 changed_when: False # lua 付きの vim でないと使えないプラグインがあるため。ただ最新の vim をインストールするだけでは必ずしも必要ではないかと思います。 # vimの依存パッケージインストール - name: install dependency packeges yum: name: "{{ item }}" state: latest with_items: - lua-devel - ncurses-devel - name: download vim git: repo: 'https://github.com/vim/vim.git' dest: /usr/src/vim - name: install vim # --prefix: インストール先 shell: "{{ item }}" args: chdir: /usr/src/vim with_items: - make distclean - ./configure --prefix=/usr/local --enable-multibyte --with-features=huge --disable-selinux --enable-pythoninterp=yes --enable-luainterp=yes - make - make install when: is_vim_installed|failed - shell: /usr/local/bin/vim --version register: vim_version changed_when: False # register で登録された値の構成 # http://qiita.com/szk3/items/29e827f90a543c764a5e - debug: var=vim_version.stdout_lines[0]
プロビジョニングの結果、8.0 の vim がインストールされました。
TASK [debug] ******************************************************************* ok: [simple] => { "changed": false, "vim_version.stdout_lines[0]": "VIM - Vi IMproved 8.0 (2016 Sep 12, compiled May 13 2017 18:36:55)" }
冪等性について
上の install dependency packeges タスクは yum モジュールを使用していて初回実行時と 2 回目以降では結果が違います。 詳しいことはわかりませんが、2 回目以降はok が出力されていて変わっていないことが保証されています。
- 初回
TASK [install dependency packeges] ********************************************* changed: [simple] => (item=[u'lua-devel', u'ncurses-devel'])
- 2 回目以降
TASK [install dependency packeges] ********************************************* ok: [simple] => (item=[u'lua-devel', u'ncurses-devel'])
それに対して shell モジュールを使用している vim install タスクは何回やっても changedが出力されるため実行する度に環境が変わってしまっている可能性があります。
- 初回、2 回目以降
TASK [install vim] ************************************************************* changed: [simple] => (item=make distclean) changed: [simple] => (item=./configure --prefix=/usr/local --enable-multibyte --with-features=huge --disable-selinux --enable-pythoninterp=yes --enable-luainterp=yes) changed: [simple] => (item=make) changed: [simple] => (item=make install)
Ansible で PHP 環境構築 ① - git インストール -
seven-greenz.hatenablog.com Vagrant を使って仮装環境を作成しました。その CentOS 仮装環境上に PHP 環境を構築したいと思います。 が、トライしてみたところ全然進まなかったので今回は git のインストールまでです。
Vagrantfile
Vagrant.configure("2") do |config| config.vm.box = "centos7.2" config.vm.network "private_network", ip: "192.168.33.20" config.vm.define :simple do |simple| simple.vm.hostname = 'simple' # ゲスト側にansibleをインストール config.vm.provision 'ansible_local' do |ansible| ansible.playbook = './playbook.yml' end end end
playbook.yml
- hosts: simple become: yes tasks: # - name: upgrade all packeages # yum: # name: '*' # state: latest # 最新のgitをインストールするため - name: add IUS repository yum_repository: name: ius description: IUS YUM repo for install the latest git baseurl: https://dl.iuscommunity.org/pub/ius/stable/CentOS/7/x86_64 # https://access.redhat.com/documentation/ja-JP/Red_Hat_Enterprise_Linux/6/html/Security_Guide/sect-Security_Guide-Updating_Packages-Verifying_Signed_Packages.html gpgkey: https://dl.iuscommunity.org/pub/ius/IUS-COMMUNITY-GPG-KEY gpgcheck: yes - name: install git yum: # 2 系は git2u というパッケージ名のようです。 name: git2u enablerepo: ius state: present # インストールした git のバージョンの確認、いちいちログインするのが面倒だったため # もっと良いやり方がありそうなので調査 - shell: git --version register: result - debug: var=result
これで vagrant up
、もし起動済みであれば vagrant provision
すれば git がインストールされます。
$ vagrant up Bringing machine 'simple' up with 'virtualbox' provider... ==> simple: Importing base box 'centos7.2'... ==> simple: Matching MAC address for NAT networking... ==> simple: Setting the name of the VM: ansible-playbook_simple_1493999707194_20088 ==> simple: Fixed port collision for 22 => 2222. Now on port 2200. ==> simple: Clearing any previously set network interfaces... ==> simple: Preparing network interfaces based on configuration... simple: Adapter 1: nat simple: Adapter 2: hostonly ==> simple: Forwarding ports... simple: 22 (guest) => 2200 (host) (adapter 1) ==> simple: Booting VM... ==> simple: Waiting for machine to boot. This may take a few minutes... simple: SSH address: 127.0.0.1:2200 simple: SSH username: vagrant simple: SSH auth method: private key simple: Warning: Remote connection disconnect. Retrying... simple: Warning: Connection reset. Retrying... simple: Warning: Remote connection disconnect. Retrying... simple: simple: Vagrant insecure key detected. Vagrant will automatically replace simple: this with a newly generated keypair for better security. simple: simple: Inserting generated public key within guest... simple: Removing insecure key from the guest if it's present... simple: Key inserted! Disconnecting and reconnecting using new SSH key... ==> simple: Machine booted and ready! ==> simple: Checking for guest additions in VM... simple: The guest additions on this VM do not match the installed version of simple: VirtualBox! In most cases this is fine, but in rare cases it can simple: prevent things such as shared folders from working properly. If you see simple: shared folder errors, please make sure the guest additions within the simple: virtual machine match the version of VirtualBox you have installed on simple: your host and reload your VM. simple: simple: Guest Additions Version: 4.3.30 simple: VirtualBox Version: 5.1 ==> simple: Setting hostname... ==> simple: Configuring and enabling network interfaces... ==> simple: Mounting shared folders... simple: /vagrant => /Users/sevengreenz/dev/ansible-playbook ==> simple: Running provisioner: ansible_local... simple: Installing Ansible... simple: Running ansible-playbook... PLAY [simple] ****************************************************************** TASK [Gathering Facts] ********************************************************* ok: [simple] TASK [install IUS repository] ************************************************** changed: [simple] TASK [install git] ************************************************************* changed: [simple] TASK [command] ***************************************************************** changed: [simple] TASK [debug] ******************************************************************* ok: [simple] => { "changed": false, "result": { "changed": true, "cmd": "git --version", "delta": "0:00:00.008418", "end": "2017-05-05 16:58:27.387269", "rc": 0, "start": "2017-05-05 16:58:27.378851", "stderr": "", "stderr_lines": [], "stdout": "git version 2.12.2", "stdout_lines": [ "git version 2.12.2" ] } } PLAY RECAP ********************************************************************* simple : ok=5 changed=3 unreachable=0 failed=0
上に書いた通りですが下記にあげています。
https://github.com/sevengreenz/ansible-php/tree/v0.1.1
memo
playbook.yml の検証
プロビジョニングはゲスト側にインストールした Ansible を使用しているのでホスト側にはいらないのですが、playbook の検証のためにいれました。
$ sudo easy_install pip $ sudo pip install ansible # playbook.yml 読み込みにシンタックスエラーが発生しないか検証 $ ansible-playbook -i /dev/null playbook.yml --syntax-check
-i
オプションはインベントリファイル(プロビジョニング先の設定)の指定ですが、Vagrant 側でやっているのでインベントリファイルはありません。指定しないと怒られるので /dev/null
にしています。
モジュールについて
Ansible はモジュールと呼ばれるものを提供していて、リソースの管理やコマンドの実行を行えるようです。 今回だと playbook.yml の yum_repojitory と yum がモジュールに当たります。 Ansible で何かする時はモジュール一覧を見て提供されていないか確認するのが良さそうです。使用例も結構あって使い方も乗ってます。
VirtualBox + Vagrant で CentOS 環境構築[macOS]
macOS 上に VirtualBox と Vagrant を使った仮装環境( CentOS )の構築方法です。
環境
macOS Sierra(version 10.12.3)
VirtualBox
VirtualBox は仮想化ソフトです。今回の場合だと Mac OS 上で Linux OS を動かせるようになります。
下記からダウンロードします。
http://www.oracle.com/technetwork/server-storage/virtualbox/downloads/index.html?ssSourceSiteId=otnjp
Vagrant
Vagrant を使うと仮装環境( 今回の場合だと VirtualBox )上に簡単な設定で複製可能な環境を構築、配布できるようになります。
下記からダウンロードします。
https://www.vagrantup.com/downloads.html
準備
# 何らかの version が表示されれば OK $ VBoxManage -v 5.1.22r115126 $ vagrant -v Vagrant 1.9.4
仮装環境起動
# ベースとなるイメージファイルをダウンロード ( http://www.vagrantbox.es/ から使いたい box を選択 ) # ベースとなるイメージファイルは vagrant ユーザー作成、sshd 起動など必要最低限のものだけ設定されているようです。 $ vagrant box add centos7.2 https://github.com/CommanderK5/packer-centos-template/releases/download/0.7.2/vagrant-centos-7.2.box # カレントディレクトリに Vagrantfile を作成 $ vagrant init centos7.2 # 起動 $ vagrant up # ssh ログイン $ vagrant ssh Last login: Tue May 2 10:09:20 2017 from 10.0.2.2 [vagrant@localhost ~]$
後片付け
# Vagrant 管理している仮装環境の確認 $ vagrant status Current machine states: default running (virtualbox) // 起動中 # 仮装環境破棄 $ vagrant destory $ vagrant status Current machine states: default not created (virtualbox) // 仮装環境無し
発生したエラー
ヘルプが見れない
$ vagrant -h /opt/vagrant/embedded/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require': cannot load such file -- vagrant-share/helper/api (LoadError)
https://github.com/mitchellh/vagrant/issues/8519通りに下記でとりあえず解決
vagrant-share は別端末からインターネットで仮装環境にアクセスするためのプラグインのようです。何で解決するんだろ。。
$ vagrant plugin install vagrant-share --plugin-version 1.1.8