OmniAICreator/Qiita-1.07M huggingface dataset:
【地獄からの生還】SSH・ Connection refusedと言われたら

EC2にSSHして
`ssh: connect to host 13.112.***.*** port 22: Connection refused`
とか言われてしまったパターンです。これはスーパーきついです。なぜならサーバにログインして操作できないので何も処置が施せないわけです。

自分は日本語で普通に検索してもこれと言った方法がわからず、英語の文献も当たってやり方を調べたので備忘録的にここに残したいと思います。

まずそもそも何が起きているのかを調べるためにAWSのEC2画面に入って当該インスタンスを選択してActionsからInstanceSettingからGet Syslogでログを確認します。 Dmsgした結果と同等のものです。

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/1593/342425ce-8a4a-caea-0608-7465c4b6994b.png)

そうすると起きていることが何となく分かるわけですが、自分の場合はRailsのアプリを無理やりリリースするために/var配下をrootからec2-userの所有権に変えてしまったことが災いしておりました。

直したい・・・しかし（ログインできないので）直せない・・・ものすごい葛藤です。正直別インスタンス立てて諦めるところまで行きました。
ですが、諦めきれない人のために以下処方箋です。

簡単に言うと別インスタンスを作って、EBSボリュームを付け替えることによって操作するというやり方です。

【手順】

- 新規インスタンスを作成する（元のAmazonLinuxと同じ構成が望ましい）
- 元のインスタンスのインスタンスIDを控えてEC2の画面にあるElasticBlockStoreのVolumeから控えたインスタンスIDで検索して引っかかったボリュームを選択する
- 元のインスタンスのSyslogを再度見返してsshdより先に動いているスクリプト名を控えておく（画像参照）
- 元のインスタンスをSTOPする（こうしないと取り外せない）
- 元インスタンスのボリュームをActionからDetachする
- 続いて１．で作成したインスタンスにAttachする（この時デバイス名は/dev/xvdfとする）
- 新規作成のインスタンスにSSHでアクセスする
- Attachしたボリュームをマウントする

```
sudo mount /dev/xvdf1 /mnt/data -t ext4
注：マウントした先の名前と最後だけ変える
マウントしたボリュームの確認はmountコマンドで可能
```

- 再度元のインスタンスのSyslogと */mnt/data/etc/init.d* 配下のスクリプトを見返してsshd以外に動いているスクリプトを開く（今回はrngd）

```
sudo vi /etc/init.d/rngd （Syslog見てsshdより前に読み込むスクリプトならどれでもOK）

起動時に実行したいスクリプトを書き込む
chown -R root.root /var
```

- attachしたボリュームをアンマウントする

```
umont /mnt/data
```

- EC2の管理画面に戻って当該ボリュームをdetachした後、元のインスタンスにattachするこの際のマウント先は */dev/xvda* とする（そうしないと起動時ボリュームとして認識されないため）
- 元のインスタンスを起動して、Syslogを確認

これでエラーが出てないことが確認できればSSHでアクセスできると思います。ピンチのときには是非どうぞ。
Dockerのチートシート

# 起動中のコンテナ表示

`docker ps`

# 過去に起動していたコンテナの表示

`docker ps -a`

# コンテナの起動

`docker start [コンテナID]` #コンテナ名は上記のコマンドで確認

# コンテナの終了

`docker stop [コンテナID]`

# コンテナの削除

`docker rm [コンテナID]`

### イメージの表示

`docker images`

# イメージの削除

`docker rmi [イメージID]`

# docker run／docker commitコマンドによるコンテナー作成の限界
>前回はDockerコンテナーを「docker run」コマンドで起動し、コンテナー内でソフトウェアのインストールやサービス起動など自由に構成できることを紹介しましたが、その構成を他のコンテナーに流用するためには、「docker commit」コマンドでDockerコンテナーから新しいDockerイメージを作成する必要がありました。
>この方法だと、構成内容をドキュメントに残しておく必要がありますし、汎用的なイメージや本番環境のイメージを手作業で構成することでミスを誘発する原因にもなるでしょう。
>そこで、Docker EngineにはDockerコンテナーの構成をまとめて記述する「Dockerfile」ファイル>と、それを適用しDockerイメージを作成する「docker build」コマンドがあります。(http://www.atmarkit.co.jp/ait/articles/1407/08/news031.html)

# Dockerfile
- [docker run]コマンドでコンテナを起動し、[docker commit]でイメージを作成して、他のコンテナ    
を作成することはできるが、設定の状態がわからない

- そこで、Dockerfileにサーバーの設定の状態を記述し、[docker build]コマンドで立ち上げることにより、新たなコンテナを作成するという手段が存在する

### Dockerfileの仕組み
- 1行につき1つの操作を｛命令｝と｛引数｝でスペース区切りで記述する

```
# コメント
{命令} {引数}
```

# Dockerfileの命令
- `From`        -> 元となるDockerイメージの指定
- `MAINTAINER`  -> Dockerfileの作成者の情報
- `RUN`         -> コマンドの実行
- `ADD`         -> ファイル/ディレクトリの追加(ホストマシン上にあるファイルをゲストマシンい移動させる)
- `CMD`         ->　コンテナの実行コマンド1
- `ENTRYPOINT`  -> コンテナの実行コマンド2
- `WORKDIR`     -> 作業ディレクトリの指定
- `ENV`         -> 環境変数の指定
- `USER`        -> 実行ユーザの指定
- `EXPOSE`      -> ポートの解放
- `VOLUME`      -> ボリュームのマウント

# Dockerfile例
```
FROM centos
MAINTAINER yyyoshiki <picolt10@gmail.com>
# RUN: build するときに実行される
RUN yum install -y httpd
# ADD: host に存在するファイルを取り込む
ADD ./index.html /va/www/html/
# EXPOSE: Port 80を開ける
EXPOSE 80
# CMD: RUN　するときに実行される
# apacheを裏側で起動,FOREGROUNDにすることで起動するまで他は実行しない
CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]
```

# Dockerfileの実行
```
# -tはイメージが作成されたときに適用するリポジトリ名をつけるためのオプション
# 最後の.は現在いるリポジトリのDockerfileを実行するため
docker build -t yyyoshiki/httpd .
```

# Dockerで立ち上げたコンテナに入る
```
docker exec -it [コンテナID] bash
```
【メモ】AWSのIAMユーザを棚卸し・クレンジングするときに使ったAWS CLIのコマンド

# モチベーション

そもそも不要なユーザをこの世から消し去りたい

随時更新する


# 使ったコマンド

## 調査

### 一度もログインしていないユーザの一覧を表示

**アクセスキーの発行のみを行っているユーザも含まれるので注意**

```bash:コマンド
aws iam list-users \
    --query "Users[?PasswordLastUsed==NULL].UserName"
```

### パスワードでのログイン実績があるユーザの一覧を、最終ログイン日でソートして表示

```bash:コマンド
aws iam list-users \
    --query "Users[?PasswordLastUsed!=NULL] | \
        sort_by([],&PasswordLastUsed)"
```

### ログインプロファイルの有無を確認

ユーザのログインプロファイルが存在していると、ユーザを削除できません

```bash:コマンド
USER_NAME="(User Name)"

aws iam get-login-profile --user-name ${USER_NAME}
```

### アクセスキーの有無を確認

```bash:コマンド
USER_NAME="(User Name)"

aws iam list-access-keys --user-name ${USER_NAME}
```


### ユーザが所属するグループを確認

ユーザがグループに所属していると、ユーザを削除できません

```bash:コマンド
USER_NAME="(User Name)"

aws iam list-groups-for-user --user-name ${USER_NAME}
```


### ユーザにアタッチされているポリシーを確認

ユーザにポリシーがアタッチされていると、ユーザを削除できません

```bash:コマンド
USER_NAME="(User Name)"

aws iam list-user-policies --user-name ${USER_NAME}
```


## 削除

### ログインプロファイル

```bash:コマンド
USER_NAME="(User Name)"

aws iam delete-login-profile --user-name ${USER_NAME}
```

### ユーザをグループから削除

```bash:コマンド
USER_NAME="(User Name)"
GROUP_NAME="(Group Name)"

aws iam remove-user-from-group --group-name ${GROUP_NAME} --user-name  ${USER_NAME}
```

### ユーザにアタッチされているポリシーをデタッチ

```bash:コマンド
USER_NAME="(User Name)"
POLICY_ARN="(Policy ARN)"

aws iam detach-user-policy --policy-arn ${POLICY_ARN} --user-name  ${USER_NAME}
```


### ユーザを削除

```bash:コマンド
USER_NAME="(User Name)"

aws iam delete-user --user-name ${USER_NAME}
```
プロジェクトを開いたり、アプリをrunすると "Xcodeが予期しない理由で終了しました。" となる

開発していたらXcodeがクラッシュするようになったのでメモ書き。

## 環境
Xcode 8.2.1
Swift 2.3 のプロジェクト

## 現象その１
特定のプロジェクトを開いただけで、"Xcodeが予期しない理由で終了しました。" となる。
他のプロジェクトは正常に開ける。
<img width="960" alt="スクリーンショット 2017-01-19 13.03.48.png" src="https://qiita-image-store.s3.amazonaws.com/0/92385/58e0d32f-184e-d9ca-6f14-3ba320acfcf1.png">

## 解決方法 for 現象その１
* Derived Data を削除することで改善した。

```
rm -r ~/Library/Developer/Xcode/DerivedData/
```

## 現象その２
無事プロジェクトが開いて、アプリを run すると
![スクリーンショット 2017-01-19 13.24.40.png](https://qiita-image-store.s3.amazonaws.com/0/92385/9513a102-72e9-da58-3a1c-efcd6a93db57.png)

"Xcodeが予期しない理由で終了しました。" となる
![スクリーンショット 2017-01-18 13.06.39.png](https://qiita-image-store.s3.amazonaws.com/0/92385/fbacd0b5-fa1d-e9e5-6ab7-92ae96c7f4ec.png)



## 解決方法 for 現象その２
* 対象の`.xcworkspace`ファイルを作成し直す。
* プロジェクトを開いただけでクラッシュする現象も、これだけで改善できるのかも（ためしてない）。

```
rm -r myapp.xcworkspace
pod install
```

## なぜクラッシュするかはわからず
なにやら`NSArray`で`NSRangeException`が起きたらしい。
以下クラッシュ時のメッセージ（上のほうだけ）。

```
Process:               Xcode [6316]
Path:                  /Applications/Xcode.app/Contents/MacOS/Xcode
Identifier:            com.apple.dt.Xcode
Version:               8.2.1 (11766.1)
Build Info:            IDEFrameworks-11766001000000000~5
App Item ID:           
App External ID:      
Code Type:             X86-64 (Native)
Parent Process:        ??? [1]
Responsible:           Xcode [6316]
User ID:               501

Date/Time:             2017-01-18 13:04:34.927 +0900
OS Version:            Mac OS X 10.12.2 (16C67)
Report Version:        12
Anonymous UUID:        


Time Awake Since Boot: 12000 seconds

System Integrity Protection: enabled

Crashed Thread:        0  Dispatch queue: com.apple.main-thread

Exception Type:        EXC_CRASH (SIGABRT)
Exception Codes:       0x0000000000000000, 0x0000000000000000
Exception Note:        EXC_CORPSE_NOTIFY

Application Specific Information:
ProductBuildVersion: 8C1002
UNCAUGHT EXCEPTION (NSRangeException): *** -[__NSArrayM objectAtIndex:]: index 3 beyond bounds [0 .. 2]
UserInfo: (null)
Hints: 
```

## 参考
http://stackoverflow.com/questions/40451843/xcode-crashing-on-a-specific-project
eZ Platform 標準フィールドタイプ一覧

https://doc.ez.no/display/DEVELOPER/Field+Types+reference

## 組み込みのフィールドタイプ
FieldType | 説明 | 旧ストレージエンジンでの検索
---|---|---
Author      |著者名とメールアドレスで構成される著者のリストを格納|No
BinaryFile  |ファイルを格納|Yes
Checkbox    |ブール値を格納|Yes
Country	    |国名を文字列で格納|Yes
DateAndTime |時間情報を含む完全な日付を格納|Yes
Date        |日付情報を格納|Yes
EmailAddress|メールアドレスを検証して格納|Yes
Float       |小数値を検証して格納|No
Image       |画像を検証して格納|No
Integer     |整数値を検証して格納|Yes
ISBN        |国際標準図書番号 (ISBN) を10桁または13桁の形式で処理|Yes
Keyword     |キーワードを格納|No
Landing Page|複数のゾーンで構成されるレイアウトのページを格納|No
MapLocation |地図座標を格納|Yes, with MapLocationDistance criterion
Media       |メディアファイルを検証して格納|No
Null        |フィールドタイプの欠落やテストのフォールバックとして使用|No
Rating      |評価を格納|	No
Relation    |コンテンツアイテムとのリレーションを検証して格納|Yes, with both Field and FieldRelation criterions
RelationList|コンテンツアイテムとのリレーションのリストを検証して格納|Yes, with FieldRelation criterion
RichText    |構造化されたリッチテキストを検証して格納し、いくつかの形式で公開|Yes
Selection   |オプションリストから単一の選択肢または複数の選択肢を検証して格納|Yes
TextBlock   |より大きいテキストブロックを検証して格納|No
TextLine    |1行のテキストを検証して格納|Yes
Time        |時間情報を格納|Yes
Url         |URL を格納|No
User        |ユーザーに関する情報を検証して格納|No
XmlText     |複数行の書式付きテキストを検証して格納|Yes

## コミュニティによるフィールドタイプ
FieldType|説明|検索|Editing support in UI
---|---|---|---
Tags	|Tags field and full fledge taxonomy management	|Yes	|No (See crowdfunding page)
Price	|Price field for product catalog use	|Yes	|No
Matrix	|Matrix field for matrix data	|Yes	|No
[Swift] Validatorで独自のValidationRuleを作成する

以前 [Validatorというライブラリを使ってValidationする](http://qiita.com/tenten0213/items/3248eb73852ef8dd12b0)という記事で、[Validator](https://github.com/adamwaite/Validator)の基本的な使い方を紹介しました。

実際のアプリケーションに適用する場合、単一のValidationルールでは足りないことがあります。
Validator自体は`ValidationRuleSet`という構造体で複数のルールを保持できるようになっていますが、都度都度`ValidationRuleSet`にルールを追加していくのも面倒ですし、同じ項目が複数箇所に出てきた際にロジックが分散するとちょっとイヤです。

* [Multiple Validation Rules (ValidationRuleSet)](https://github.com/adamwaite/Validator#multiple-validation-rules-validationruleset)

ユーザIDならユーザID用の精査ルールを持ちたいので、独自のルールを作成することにします。
以下に記載されている通り、`ValidationRule`プロトコルを適用した構造体を作成すれば良いです。

* https://github.com/adamwaite/Validator#create-your-own

## 独自のルールを作成する

独自のルールを作成するといっても、往々にして既存のルールの組み合わせなことがほとんどだと思います。
以下では、ユーザID用のルールを`ValidationRuleLength`と`ValidationRulePattern`の組み合わせで作成しました。

ルールとしては、

* 0桁以上16桁以下
* 英数字

と適当にしています。

英数字を表すパターンも独自に作成します。
こちらは`ValidationPattern`プロトコルを適用したenumです。
英数字以外にも英字、数字のみのパターンも用意してみました。

```swift
import Foundation
import Validator

public enum CharacterTypeValidationPattern: ValidationPattern {
    case alpha
    case alphaNumeric
    case numeric
    public var pattern: String {
        switch self {
        case .alpha: return "^[A-Za-z]+$"
        case .alphaNumeric :return "^[A-Za-z0-9]+$"
        case .numeric :return "^[0-9]+$"
        }
    }
}
```

作成したルールは以下です。
複数ルールを作成し、`validate`で両方のルールに適していれば`true`、片方でもValidationエラーの場合は`false`が返るようにしています。

```swift
import Foundation
import Validator

/**
 Validation rule for userId.
 */
public struct ValidationRuleUserId: ValidationRule {
    public typealias InputType = String
    public var error: Error
    public let lengthRule: ValidationRuleLength
    public let patternRule: ValidationRulePattern
    public init(error: Error) {
        self.error = error
        self.lengthRule = ValidationRuleLength(min: 0, max: 16, error: self.error)
        self.patternRule =
            ValidationRulePattern(pattern: CharacterTypeValidationPattern.alphaNumeric, error: self.error)
    }
    /**
     
     Validates the input.
     
     - Parameters:
     - input: Input to validate.
     
     - Returns:
     true: valid, false: inValid
     
     */
    public func validate(input: String?) -> Bool {
        return self.lengthRule.validate(input: input) && self.patternRule.validate(input: input)
    }
}
```

使い方はこんな感じで、通常のルールと同様です。


```swift
@IBOutlet weak var userIdInput: UITextField!
let userIdValidateResult = userIdInput.validate(rule: ValidationRuleUserId(error: ValidationError(message: "💩")))
```

実際もっとスマートな方法があるような気もするのですが、これでロジックの分散が防げ、この項目の精査はコレ、と迷わず選択できるようになると思います。
【参考しないように04.02.17】rasberry pi 3 で温度センサーをリアルタイムグラフで表示

申し訳御座いません。
たまたまmbassの関連でこちらの記事を際閲覧して見ましたが
出来ませんでしたので一度閲覧は中止します。
※たぶん、顔認識の学習を同一raspberry piで対応したため階層が違ったためだと思います。
  また原因等判明いたしましたら再開しますので宜しくお願いします。

今回はrasberry pi 3と20種類センサーの温度センサーを組み合わせて、
pythonでリアルタイムグラフに挑戦。

購入したのは、rasberry pi 3と２０種類センサー

配線の手順とデータの手順取得は下記のURL,
※このURLでもかかれてあるとおり、配線はGNDなどの順番が入り混じっているので、
とにかくこの際との通りの配線で問題なし↓。

https://colo-ri.jp/develop/2016/05/raspberry-pi-ds18b20.html

※04.02.17追記配線が若干理解しずらいかもしれないので。
まずはgpioについて
![gpio.PNG](https://qiita-image-store.s3.amazonaws.com/0/160387/2159fa27-c4d4-9e0f-055a-7254940c8301.png)

次は配線方法:
こちらはDQピンをGPIO4に、VDDピンを3.3V、GNDピンをGNDへ接続しました。
で、DQピンとVDDピンの間を10KΩの抵抗でプルアップします。

後個人的には、値のリアルタイムグラフ化をしたくて、下記のコードを作成。
実行すると、下記の画像の通り（※少しみづらいですが、左上にリアルタイムグラフ、左下にリアルタイムセンサーなどが表示されます。.右上のはキャプチャショットのプロンプトなので無視して下さい。）
<img width="639" alt="temp.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/160387/f3667b64-b3c9-41e0-9acf-a0b4afed5078.png">


＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝
↓ここからコピー

```py
#-*- coding: utf-8 -*-
#http://denshi.blog.jp/arduino/temperature-graph
import numpy as np
import matplotlib.pyplot as plt
import pygame
from pygame.locals import *
import serial
import sys
import os
import glob
from time import sleep

os.system('modprobe w1-gpio')
os.system('modprobe w1-gpio')

base_dir = '/sys/bus/w1/devices/'
device_folder = glob.glob(base_dir + '28*')[0]
device_file = device_folder + '/w1_slave'
def read_temp_raw():
f = open(device_file, 'r')
lines = f.readlines()
f.close()
return lines


def read_temp():
lines = read_temp_raw()
while lines[0].strip()[-3:] != 'YES':
sleep(0.2)
lines = read_temp_raw()
equals_pos = lines[1].find('t=')
if equals_pos != -1:
temp_string = lines[1][equals_pos + 2:]
temp_c = float(temp_string) / 1000.0
return temp_c
def main():

temps = [0]*100 # 温度格納
t = np.arange(0,100,1)
plt.ion()
pygame.init() # Pygameを初期化
screen = pygame.display.set_mode((200, 200)) # 画面作成(100×100)
pygame.display.set_caption("傾斜角度") # タイトルバー
font = pygame.font.Font(None, 50) # 文字の設定

while True:
screen.fill((0,0,0)) # 画面のクリア
deviceTemp = read_temp()
print(read_temp())
temp = str(deviceTemp) # \nまで読み込む(\nは削除)
text = font.render(temp + "[C]", False, (255,255,255)) # 表示する文字の設定
screen.blit(text, (10, 10)) # レンダ，表示位置
pygame.display.flip() # 画面を更新して、変更を反映
# 温度データのリスト更新
temps.pop(99)
temps.insert(0,float(temp))
# グラフ表示設定
line, = plt.plot(t, temps, 'r-',label="Temperature[C]") # Y軸更新
line.set_ydata(temps)
plt.title("Real-time temperature")
plt.xlabel("Time [s]")
plt.ylabel("Temperature [Celsius]")
plt.legend()
plt.grid()
plt.xlim([100,1])
plt.ylim([0,40])
plt.draw()
plt.clf()
#print(read_temp())
for event in pygame.event.get():
# 終了ボタンが押されたら終了処理
if event.type == QUIT:
pygame.quit()
ser.close()
plt.close()
sys.exit()


if __name__ == '__main__':
main()
```
Apex 日付

####現在時刻/今日の取得
`Datetime t = Datetime.now();`
`Date today = Date.today();`
`Long t = Datetime.now().getTime();` 1970年からのミリ秒

####Date型を文字列にした時のフォーマット
`2017-03-31 Date`
`2017-01-26T07:12:03.000Z  Datetime`

####フォーマットを指定してDatetime型を文字列にする (TimezoneはAsia/Tokyo)
`dt.format('yyyy/MM/dd HH:mm', UserInfo.getTimeZone().getId())`
####データ変換 (Date <-> String)
```java
String test_str = '2017-1-1 15:30:00';
Datetime test_dt = Datetime.valueOfGmt(test_str);`
//Datetime.valueOf()で変換するとGMT時間となり -9h されてしまうことに注意
Date dt = Date.valueOf('2019-1-20');

startDateTime.format('yyyyMMdd')`
```

####DatetimeからDate
`Date mdate = lastUpdateDatetime.date();  //date()でDate型を取得`
####ミリ秒数からの変換
`Long msec = mydatetime.getTime();  //1970 年 1 月 1 日 00:00:00 (GMT) を起点とした指定したミリ秒数(1341828183000L)`
`Datetime mydatetime = Datetime.newInstance(msec);`
####日付の差分を求める（Date.daysBetween()）
```java
Date lastUpdateDate = Datetime.newInstance(lastUpdateTime).date();
Integer sabun = Date.today().daysBetween(lastUpdateDate);
```
####GMT時間をローカル時間に補正する数値の算出
```java 
/*
 * get Timezone offset
 */ 
public static Double getTimezoneOffset(){
    TimeZone tz = UserInfo.getTimeZone();
    return tz.getOffset(DateTime.now()) / (1000 * 3600 * 24.0);
}

```
debian8のsamba4でport445をlistenしない場合

* proxmox 4.4 + samba 4.2.14+dfsg-0+deb8u2 にて確認。

```
apt install -y samba
```

OS起動直後はport445をlistenする。
`service samba restart` や `service smbd restart`をするとlistenしない。
エラー出力されていない？`testparm`もエラー無し

`sudo /usr/sbin/smbd`を実行したらport 445をlistenしました。
一応やりたいことはできた。


## サンプル設定

```apache:/etc/samba/smb.conf
[global]
	server role = standalone server
	map to guest = Bad User
	obey pam restrictions = Yes
	pam password change = Yes
	passwd program = /usr/bin/passwd %u
	passwd chat = *Enter\snew\s*\spassword:* %n\n *Retype\snew\s*\spassword:* %n\n *password\supdated\ssuccessfully* .
	unix password sync = Yes
	syslog = 0
	log file = /var/log/samba/log.%m
	max log size = 1000
	dns proxy = No
	usershare allow guests = Yes
	panic action = /usr/share/samba/panic-action %d
	idmap config * : backend = tdb


[homes]
	comment = Home Directories
	valid users = %S
	create mask = 0700
	directory mask = 0700
	browseable = No


[mnt]
	path = /mnt/
	guest ok = Yes
	writable = Yes
```
agoutiというWebDriverクライアントを使って面倒な作業を自動化する

![](http://agouti.org/images/agouti.png)

普段の仕事で定例化しているものや、同じ作業を何回もしていて面倒だと感じることって結構あると思います。
特にWebの操作はポチポチ何回もやるのは面倒です。

そこで、Selenium WebDriverを使って作業の自動化をしてみます。
WebDriverのクライアントは様々な言語から出ていますが、今回はGolangの[Agouti](http://agouti.org/)というライブラリを利用します。
Golangにしたのは、一つのバイナリになるのでチームなどへの連携、配布が楽ってのが大きな理由です。

## 事前準備

### WebDriverをインストール

* Chrome用のWebDriverをインストール

```bash
$ brew install chromedriver
```

他のブラウザでも構わないですが、以下の記事の通り、FireFoxはまだ動きませんでした。(2017/1/24時点)

* [Firefox 48以降でselenium\-webdriverが動作しない問題とその回避策 \- Qiita](http://qiita.com/jnchito/items/ab23c925a6a78345d737)

現状、chromedriverを利用するのが一番ラクそうです。

Safariを利用する場合は、以下からWebDriverのSafari拡張機能をインストールしてください。

* [http://www.seleniumhq.org/download/](http://www.seleniumhq.org/download/)

また、追加で`selenium-server-standalone`もインストールする必要があります。

```bash
$ brew install selenium-server-standalone
```

### agoutiをインストール

`go get`でインストールします。

```bash
$ go get github.com/sclevine/agouti
```

## Qiitaにログインしてみる

ログインだと要素の取得、値の設定、formのサブミットなどがあってちょうど良いので、Qiitaにログインしてみます。
以下のコードを実行すると、Qiitaにログインします。(適宜IDとパスワードは変更してください)

```bash
$ go run main.go
```

```go:main.go

package main

import (
	"github.com/sclevine/agouti"
	"log"
	"time"
)

func main() {
    // ブラウザはChromeを指定して起動
	driver := agouti.ChromeDriver(agouti.Browser("chrome"))
	if err := driver.Start(); err != nil {
		log.Fatalf("Failed to start driver:%v", err)
	}
	defer driver.Stop()

	page, err := driver.NewPage()
	if err != nil {
		log.Fatalf("Failed to open page:%v", err)
	}
    // ログインページに遷移
	if err := page.Navigate("https://qiita.com/login"); err != nil {
		log.Fatalf("Failed to navigate:%v", err)
	}
    // ID, Passの要素を取得し、値を設定
	identity := page.FindByID("identity")
	password := page.FindByID("password")
	identity.Fill("Your Id Here.")
	password.Fill("Your Passowrd Here.")
    // formをサブミット
	if err := page.FindByClass("loginSessionsForm_submit").Submit(); err != nil {
		log.Fatalf("Failed to login:%v", err)
	}
    // 処理完了後、3秒間ブラウザを表示しておく
	time.Sleep(3 * time.Second)
}
```

Safariで動かす場合は以下のように修正が必要です。

```diff
- driver := agouti.ChromeDriver(agouti.Browser("chrome"))
+ driver := agouti.Selenium(agouti.Browser("safari"))
```


実際に動かしてみると、こんな感じです。

![agouti-qiita.gif](https://qiita-image-store.s3.amazonaws.com/0/6092/665d100d-d5b4-f9f2-478a-35ef2f553f6d.gif)

どうでしょうか？agouti自体が結構シンプルに使えるようにできているので、簡単にログインくらいは自動化できると思います。

業務ではもう少し複雑なシステムへのログイン(CSVにログインに必要なマトリクスを保存しておき、DOMからマトリクスのA1,F2,B5,D1を入力しろといった指示を抽出してマッチングする)なんかを自動化しています。

他にも勤怠情報の登録や、定期的に行ってるRedmineからの情報収集なんかも自動化できそうです。

みなさんもagoutiを使って日々の面倒な作業を自動化してみてはいかがでしょうか？
【環境構築】vagrant up でこけた

vagrantで開発環境を作っていたらつまずいたので、こちらにメモを書く

## 使ってるマシン
* Macbook Pro:バージョン 10.11
* virtual Box:バージョン 5.1
* Vagrant: バージョン 1.8.5

## 事象
* `vagrant up`すると、`default: Warning: Authentication failure. Retrying...`
が出続ける

* `vagrant ssh`をすると、パスワードを聞かれる


## 原因
* ホストOS（MAC）とゲストOS（VM）のSSHキーが一致していないこと

## 対処方法
* SSHキーを作成し直し、ゲストOSに設定する

以下、手順
1: 現状のSSHキーを調べる
`$ vagrant ssh-config`
->`IdentityFile xxxx/vagrant_private_key`がでてくるはず

* 公開鍵を作成
`$ ssh-keygen -yf xxxx/vagrant_private_key > public_key`
    * `$ vi public_key` で作った公開鍵をコピーする

2: ゲストOSのキーを設定する
vagrantを起動している状態で(virtual Boxで立ち上げる)行う

* VirtualBoxからログインする
    * rootユーザでログイン
ユーザ：xxxx
パスワード：xxxx

* 公開鍵に1で作ったキーの内容を貼り付け

`# vi /home/vagrant/.ssh/authorized_keys`

```:authorized_keys
ssh-rsa 
HOGEHOGEHOGEHOGEHOGEHOGEHOGEHOGEHOGEHOGE
HOGEHOGEHOGEHOGEHOGEHOGEHOGEHOGEHOGEHOGEHOGE
HOGEHOGEHOGEHOGEHOGEHOGE
```
* パーミッションを変更  
`# chmod 600 /home/vagrant/.ssh/authorized_keys`

3:ログイン(ホストOS)
`$ vagrant ssh`

つながればおk！


## もしも、virtual Boxでの操作が面倒だった場合(コピペができない等)
手順2の`virtual Boxからログイン`ではなく、ローカルからログインする

`$ vagrant ssh`

ここでパスワードを聞かれるので、rootユーザと同じパスワードを入力
以降は同じ手順。



以上
Ruby｜パスからファイル名を取りたい


## 動作環境

Ruby 2.3.1
OS X El Capitan 10.11.6

## パス名を取ってみる
`basename`つかえとそれだけで終わりそうなんですが、
パスとファイル名を分けて返してほしいときがあったので忘備録です。

私が直面したシーンは、
・フルパスがわかっている
・末尾は必ずファイル
だったので既存のメソッドにまんま依存してます。

refinmentを使っているのは、普段つかわないので覚えるためにやってます。


```ruby
path = "/dev/src/ruby/sample.txt"

module Interpolation
  refine File.singleton_class do
    def partition(path)
      [self.dirname(path), self.basename(path)]
    end
  end
end

using Interpolation

p File.partition(path)
#=> ["/dev/src/ruby", "sample.txt"]
```
技術英語 > multiplication has [higher precedence than] addition, / Order of operations (or operator precedence)

@ Introducing Python: Modern Computing in Simple Packages by Bill Lubanovic
(No. 661 / 12833)

```
>>> 2 + 3 * 4
```

> In Python, as in most languages, multiplication has **<font color=red>higher precedence than</font>** addition, ...


https://www.merriam-webster.com/dictionary/precedence
> 1 b :  the fact of coming or occurring earlier in time
...
> 2 c :  priority of importance <your safety takes precedence>

この場合は「higher priority」とは言わないのか未消化。

<hr>

https://en.wikipedia.org/wiki/Order_of_operations

> In mathematics and computer programming, the order of operations (or **<font color=red>operator precedence</font>**) is ...

ここでもprecedenceが使われている。
【メモ】キャメルケース・スネークケース・ハイフン

cssの命名でキャメルケース、アンダースコア、ハイフン・・・

どれが一番頻繁に利用され使用しやすいのだろう？

【入社1年目ぐらい（アンダースコア）】
先輩方がアンダースコアを使っていたから。
なんとなく。

【今現在（ハイフン）】
Bootstrapがハイフンを使っていたから。
ぱっとみハイフンの方が見やすいから。
Googleが推奨していたから。

ちょっと調べてみました。
参考：
http://www.tecblo.com/programming/679.html
http://qiita.com/itagakishintaro/items/168667d5ee4c56b30d52

メモ
ハイフンはJavaScriptの変数名には使用できない
ハイフンはダブルクリックで選択不可
アンダースコアはShiftキー必要でやや手間？
Trello CSS Guideに沿う（恥ずかしながら初知り(/ _ ; )）
（ハイフンでつなぎ、js用のクラス属性にはjs-プレフィックスを使用）わかりやすいかも！
BEMに沿う
（ハイフン・アンダースコアどちらも使用）

確かハイフンにするとドリームウィーバーがマイナスかチェックするため重くなるという説が・・・
Ubuntu でFTPサーバを立てるときに注意すること

#きっかけ
AWSでFTPサーバを立てたが、セキュリティ・グループでTCP/20,21を解放したが、外部(WAN側)からFTP接続したとき何故か弾かれてしまった。


#原因
vsftpdインストール時、初期設定では
```
listen_address=127.0.0.1
```
となっていたが、これではlocalhostだけ受け付け、外部（WANとLAN）から接続できない状況になっていた。

#解決方法
そこで、listen_addressの値を空にすることで、とりあえずこの問題は解決した。
```
listen_address=
```
Storyboard Referenceを使ってみた

#はじめに
タイトルの通りですが、
Storyboard Referenceを使ったことなかったので、使ってみました。

#Storyboard Reference??
異なるStoryboard間をsegueでつなげられる機能です。
iOS8から使える機能ですが、
NavigationController, TabBarController, SplitViewControllerなど
Relationship Segueを利用する場合はiOS9以降でないと使えないようです。残念(>_<)/
![スクリーンショット 2017-01-25 2.24.39.png](https://qiita-image-store.s3.amazonaws.com/0/103695/a9ab076e-1fa4-e444-8ed7-992c9114d760.png)


使い方はとても簡単でした!!

Storyboard Referenceを選択して、
![スクリーンショット 2017-01-25 2.54.00.png](https://qiita-image-store.s3.amazonaws.com/0/103695/98750040-06fd-6f93-1c5b-39a17d3e560d.png)

遷移先のStoryboard名を選択する。
![スクリーンショット 2017-01-25 2.55.07.png](https://qiita-image-store.s3.amazonaws.com/0/103695/e2b79e39-e5ec-3bf7-85bd-74757e386801.png)

![スクリーンショット 2017-01-25 2.54.51.png](https://qiita-image-store.s3.amazonaws.com/0/103695/a78b64f0-b1f4-614e-5085-8c7fcc139900.png)

そして、紐付けるだけです!
![スクリーンショット 2017-01-25 2.58.40.png](https://qiita-image-store.s3.amazonaws.com/0/103695/fb84be9e-9f70-f729-6c82-249cceadd83b.png)

Storyboard Referenceを使えば、
以下のサンプルのように重たいStoryboardもスマートにできそうです。



#Before
Storyboard Referenceを使う前の状態です。
![スクリーンショット 2017-01-25 2.37.14.png](https://qiita-image-store.s3.amazonaws.com/0/103695/b125acde-75b5-7c23-f38b-38115dd413bf.png)

敢えて、1つのStoryboardに全画面実装してみました。
チーム開発だと絶対コンフリクト発生するパターンですね(笑)

#After (Storyboard Referenceを使った場合)
画面遷移するのにほとんどソースコードを書くこともなく、1画面1Storyboardに出来ました(^ω^)

![スクリーンショット 2017-01-25 2.41.28.png](https://qiita-image-store.s3.amazonaws.com/0/103695/77f69a7d-3575-5d9f-673d-0eebe4f964d5.png)

![スクリーンショット 2017-01-25 2.41.53.png](https://qiita-image-store.s3.amazonaws.com/0/103695/0425b208-f174-4924-53ab-4d21222e64a1.png)

![スクリーンショット 2017-01-25 2.42.14.png](https://qiita-image-store.s3.amazonaws.com/0/103695/62cdb213-f7fc-39b1-4935-49d172728f10.png)

![スクリーンショット 2017-01-25 2.42.33.png](https://qiita-image-store.s3.amazonaws.com/0/103695/98e3b3f7-db24-de3e-3f00-0c3a9fc94478.png)

![スクリーンショット 2017-01-25 2.42.52.png](https://qiita-image-store.s3.amazonaws.com/0/103695/ca94e7d5-7e3a-a4d9-2258-3c970f535f50.png)

#さいごに
Githubにサンプルプロジェクトをpushしました。
https://github.com/yuoku/StoryboardReference-Sample
ReactCSSTransitionGroupが動かないときのチェックリスト

React の Add-on のひとつである [ReactCSSTransitionGroup](https://facebook.github.io/react/docs/animation.html) (= `react-addons-css-transition-group`)が期待通りに動かないときのためのチェックリストです。

上記のドキュメントに明記されているものと、そうじゃないもので構成されています。


## チェックリスト
- [ ] ReactCSSTransitionGroup の `children` はそれぞれ `key` を付与されているか？
  - ドキュメント参照 
- [ ] `ReactCSSTransitionGroup` は常に存在しているか？
  - ドキュメント参照 
- [ ] 同コンポーネント内に `ReactCSSTransitionGroup` 自体が複数あるときに、それぞれ `key` が付与されているか？
  - `key` を明示しないと動きませんし、Warning も出ません。
  - Ref) https://github.com/facebook/react/issues/1850
- [ ] `children` に別の手段で `transition` スタイルが付与されているか？
  - そちら側の詳細度が勝っていませんか。


## 以上
他にもありましたら、追加願います！


## 2017-03-15 追記
以前このようなチェック項目をあげていましたが、現在の最新版で調査したところ少なくともこの制約はありませんでした。

- ~~[ ] `transitionName` が半角ハイフンを含んでいないか？~~
  - ~~`-` は解釈できないようです。`_` 半角アンダースコアは可のようです。~~

過去も、今回のケースをそのまま検証しているようなテストケースは見つかりませんでしたが、長い間修正されていない [類似のケース](https://github.com/facebook/react/blob/master/src/addons/transitions/__tests__/ReactCSSTransitionGroup-test.js#L217-L248) を見ると過去もそのような制約はなかったように見えます。

申し訳ない。
Reactおみくじ (getInitialState setState)

2017年、もうすぐ一月も終わりですが(......早い)、
Reactで簡単なおみくじをつくってみました。

[Reactおみくじ](http://codepen.io/may88/pen/BpNaEP?editors=0010)　CodePenデモ

[GitHub](https://github.com/may88seiji/ReactOracle)

この記事ではReactおみくじ作成の手順をまとめていこうと思います。

##はじめに
・対象者
Reactチュートリアルおわったぐらいの人
Reactでおみくじをひきたい人
正月におみくじをひきそこねた人

・学べること
`getInitialState　　setState`の使い方
`onClick`によるイベントの設定と`state`の受け渡し
乱数のつくりかた

##1　Hello World
Hello Worldを表示させた状態からはじめます。 
*Hello World、表示環境の簡単なつくりかたは[こちら](http://qiita.com/may88seiji/items/648f7e550538168f18f1)で。

コード

```index.html
  <div id="root"></div>
```

```style.css
body{
    background: #f2f2f2;
    text-align: center;
    color: red;
}
#root{
    font-size: 48px;
    font-weight: bold;            
}
```

```script.js
var Oracle = React.createClass({
//1
//2
  render: function(){
    return (
     <div>
        <p>Hello World</p> 
     </div>
    );
  }
});

ReactDOM.render(
  <Oracle />,
  document.getElementById('root')
);
```

上記のコードでHello Worldが表示されます。

##2 getInitialState
`getInitialState`を設定します。
getInitialStateはReactでstateという可変データの初期設定につかいます。
*stateについては@kyrieleison　さんの[React における State と Props の違い](http://qiita.com/kyrieleison/items/78b3295ff3f37969ab50)が参考になります。

```
   getInitialState:function(){
     return { result:"Reactおみくじ"};
   },
```

上記コードを`//1`のある行に上書きします。
`result`は"Reactおみくじ"にあたる値にアクセスする名前になります。
次に `<p>Hello World</p>`を`<p>{this.state.result}</p> `に上書きします。
`{}`を忘れないようにしてください。

`this`は`var Oracle`を示していて、`state.result`とつづけることで"getInitialStateのresultの値を取得します。
結果`Reactおみくじ`の文字が表示されます。

##3 乱数をつくるfunction
`//2`のある行に乱数をつくるfunctionを設定します。

・乱数のつくりかた
`Math.floor(Math.random()*arr.length);`
Math.floor()は小数点以下切り捨て。
Math.random()は0から1未満の数字を生成します。
乱数は配列の添字(index)として使うので、おみくじの結果の数に合わせて`*arr.length`とおきます。

```
show: function(){ 
   var arr = ['大吉', '小吉','中吉',"吉",'凶',"大凶"];
   var index = Math.floor(Math.random()*arr.length);
   this.setState({result: arr[index]});
  },
```
`show`はfunctionの名前で後でイベントに結びつけるときにつかいます。
最後の`,`を忘れないようにしてください。

4行目に`setState`がでてきました。
setStateはgetInitialStateで設定した値(result)を保存、更新する場所になります。
更新する値が`arr[index]`と初期値から変更されていて、イベントが発生するたびindexに設定された乱数によってarrの取得内容が更新されます。

##4 onClick
イベントハンドラのonClickを設定します。

```
<button onClick={this.show}>Push</button>
```
上記コードを`<p>{this.state.result}</p>`の次の行に足してください。ボタンが追加されます。
onClickはクリックイベントを判断します。buttonのattribute(属性)に設定されているので、buttonを押すたびにクリックイベントが発生します。
onClickの内容は{this.show}と設定されているので、イベント発生時に乱数をつくるshowが呼ばれます。
結果、stateの値が更新され、おみくじの内容が変わっていきます。

##おわり
以上でごくごく簡単なおみくじの説明を終わります。
不明な点、補足がありましたらコメントいただけると助かります。
ありがとうございました。


```
var Oracle = React.createClass({
  getInitialState:function(){
    return { result:"Reactおみくじ"};
  },
  
  show: function(){ 
    var arr = ['大吉', '小吉','中吉',"吉",'凶',"大凶"];
    var index = Math.floor(Math.random()*arr.length);
    this.setState({result: arr[index]});
  },
  
  render: function(){
    return (
     <div>
        <p>{this.state.result}</p> 
        <button onClick={this.show}>Push</button>
     </div>
    );
  }
});
ReactDOM.render(
  <Oracle　/>,
  document.getElementById('root')
);
```
systemdで管理するサービスが落ちたときにHipchat（他のSNSやメールも可）にアラートを飛ばす

# 目標：jenkinsがたまに勝手に落ちているが気づかないので、落ちたときにNotificationを飛ばす！

落ちたときに、また復活するようにするするためには、以下のように書いておく。（300sは任意の時間に変更可能）

```
[Service]
Restart=always
RestartSec=300s
```

参考ページ：http://northernlightlabs.se/systemd.status.mail.on.unit.failure



## 1. Notificationを飛ばしたいServiceのUnitファイル編集

[Unit]の中に、OnFailure=unit-status-notification@%n.serviceとかく

```
[Unit]
...
OnFailure=unit-status-notification@%n.service
...
```

## 2. notification用のサービスを作る

/etc/systemd/system/unit-status-notification@.serviceをつくる

```/etc/systemd/system/unit-status-notification@.service
[Unit]
Description="unit status notification"
After=network.target
[Service]
Type=simple
ExecStart=/path/to/notification_run %I
```
%Iは、サービス名が入るので、このunit-status-notification@.serviceはいろいろなサービスに使いまわしできる。（1.の部分を追加するだけで良い。）


## 2. notification_runというスクリプトを準備する
(今回はRubyを実行するScript)

```bash:notification_run
cd path/to/<notification.rbを置いてる場所>
/path/to/your/ruby notification.rb %I
```

注意：ここで`gem install bundler`をされてるRubyを指定しないと、DefaultのRubyになって、Systemdで、bundler not foundというエラーにハマるので注意！

## 3. rubyのファイルには、Notificationの実行内容を書く。

今回はHipchatへのNotificationだが、SlackやEmailへのNotificationの場合はも適宜変更。

```ruby:notification.rb
require 'hipchat_util.rb'
unit = ARGV[0]
msg = "the status of #{unit} is on failure."
HipchatUtil.new.send_msg('hipchat-room-name', 'Unit Status', msg, notify: true, color: 'red')
```
Hipchatは、メッセージを送れるように以下のように定義しておいた。

```ruby:hipchat_util.rb
class HipchatUtil
  def initialize
    api_keys = "<API_KEYS>"
    @hipchat_client = HipChat::Client.new(api_keys)
  end
  def send_msg(room, title, body, msg_format: :text, notify: false, color: 'gray')
    @hipchat_client[room]
      .send(title, body, message_format: msg_format, notify: notify, color: color)
  end
end
```

## （4. 最後に一応notification_runを実行可能にしておく）
必要かどうかわからないが、以下を実行しておいた。

```bash
chmod +x /path/to/notifiation_run
```

git でこのchmodの変更が反映されない場合は、以下を実行：

```
git update-index chmod=+x /path/to/notifiation_run
```
Laravel HTTPリクエスト受付からレスポンスまでの概略

# 何
LaravelのHTTPリクエスト受付からレスポンスまでの処理概略メモ

# 参照したバージョン
5.3

# メモ

```
public/index.php
    // Register The Auto Loader
    require bootstrap/autoload.php
        require vendor/autoload.php
        require bootstrap/cache/compiled.php

    // Turn On The Lights
    $app = require bootstrap/app.php
        // $appの生成
        $app = new Illuminate\Foundation\Application

        Http/Console Kernelのコンテナへの登録
            (Http Kernelの実体はapp/Http/Kernel.phpと親のIlluminate\Foundation\Http\Kernel)

    // Run The Application
    $kernel = $app->make(...)

    $response = $kernel->handle (= Illuminate\Foundation\Http\Kernelのhandleを呼び出し)
        $this->bootstrap();
            $this->app->bootstrapWith($this->bootstrappers());
                各要素をbootstrap
                protected $bootstrappers = [
                'Illuminate\Foundation\Bootstrap\DetectEnvironment', ->.envのload
                'Illuminate\Foundation\Bootstrap\LoadConfiguration', ->bootstrap/cache/config.phpまたは、config/*.phpの参照
                'Illuminate\Foundation\Bootstrap\ConfigureLogging',
                'Illuminate\Foundation\Bootstrap\HandleExceptions',
                'Illuminate\Foundation\Bootstrap\RegisterFacades',   ->config/app 'app.aliases'の参照
                'Illuminate\Foundation\Bootstrap\RegisterProviders', ->config/app 'app.providers'の参照
                'Illuminate\Foundation\Bootstrap\BootProviders',     ->Illuminate\Foundation\Applicationのboot
                ];
        Pipelineクラスにより、middleware/routerを経由してrequestを送信し、responseを得る
            (routerからのdispatchでコントローラのアクションの実施など、ビジネスロジック実施)

    $response->send (= Symfony\Component\HttpFoundationのsendメソッドを呼び出し)
        header関数やechoによる応答返却実施

    $kernel->terminate (= Illuminate\Foundation\Http\Kernelのterminateを呼び出し)
        各middlewareのterminateを呼び出し 

```
Linux mint 18にDockerをインストール

基本的に
https://docs.docker.com/engine/installation/linux/ubuntu/
の通り。

いくつかつまづきポイントがあったのでメモ。

以下、上記ページの通り進んでいき、つまづいた部分に注意書きを入れていきます↓

# Prerequirements
## Recommended extra packages

```shell-session
$ sudo apt-get update

$ sudo apt-get install curl \
    linux-image-extra-$(uname -r) \
    linux-image-extra-virtual
```

私の場合、`sudo apt-get install linux-image-extra-virtual` で

```shell-session
Reading package lists... Done
Building dependency tree       
Reading state information... Done
Some packages could not be installed. This may mean that you have
requested an impossible situation or if you are using the unstable
distribution that some required packages have not yet been created
or been moved out of Incoming.
The following information may help to resolve the situation:

The following packages have unmet dependencies:
 linux-image-extra-virtual : Depends: linux-image-generic (= 4.4.0.59.62) but it is not going to be installed
E: Unable to correct problems, you have held broken packages.
```

というエラーが出たので、

```shell-session
$ sudo apt-get install linux-image-generic
```

してから再度

```shell-session
$ sudo apt-get install linux-image-extra-virtual
```
を実行。

# Install docker
## Install using the repository
### Set up the repository
基本的に上記ページの通り。

```shell-session
$ sudo apt-get install apt-transport-https \
                       ca-certificates
```

```shell-session
$ curl -fsSL https://yum.dockerproject.org/gpg | sudo apt-key add -
```

```
$ apt-key fingerprint 58118E89F3A912897C070ADBF76221572C52609D
```

**↓ここで`lsb_release`を使わず、直接`ubuntu-xenial`と入力する (xenial = Ubuntu 16.04)。**
Linux mint 18はUbuntu 16.04ベースだが、`lsb_release`は"sarah"を返す。
dockerのリポジトリはUbuntu16.04用のものを使いたいので"sarah"ではなく、"xenial"を入力する。

```shell-session
sudo add-apt-repository "deb https://apt.dockerproject.org/repo/ ubuntu-xenial main"
```

もし間違ったリポジトリを登録してしまったら、メニューで"Software Sources"を選択して開き、"Additional repositories"から削除する。

### Install Docker
上記ページの通り普通にインストールする。

```shell-session
$ sudo apt-get update
```

```shell-session
$ sudo apt-get -y install docker-engine
```
Ansible の inventory 指定はディレクトリが良い

# Ansible の inventory をディレクトリにすると

そのディレクトリ以下のファイルをすべて inventory として読み込んでくれる。
※ -i オプションは１回しか指定できない

```
$ ansible-playbook -i inventories/vagrant/ playbooks/playbook.yml
```

# 確認のための準備

たとえば、以下の構成があったとする。

```
├── inventories
│   ├── IaaS
│   │   ├── all_vars
│   │   ├── consul
│   │   └── jenkins
│   └── vagrant
│       ├── all_vars
│       ├── consul
│       └── jenkins
└── playbooks
    └── playbook.yml
```

```inventories/IaaS/all_vars.
[all:vars]
datacenter='IaaS'
```
```inventories/IaaS/consul.
[consul_server]
2.2.2.2
```
```inventories/IaaS/jenkins.
[jenkins]
1.1.1.1
```
```inventories/vagrant/all_vars.
[all:vars]
datacenter = vagrant
```
```inventories/vagrant/consul.
[consul_server]
10.10.10.12
```
```inventories/vagrant/jenkins.
[jenkins]
10.10.10.11
```
```playbooks/playbook.yml
- hosts: localhost
  tasks:
    - debug:
        var: datacenter
    - debug:
        var: groups
```

# 確認してみる

インベントリディレクトリに inventories/vagrant/ を指定してみる

```
$ ansible-playbook -i inventories/vagrant/ playbooks/playbook.yml 

PLAY [localhost] ***************************************************************

TASK [setup] *******************************************************************
ok: [localhost]

TASK [debug] *******************************************************************
ok: [localhost] => {
    "datacenter": "vagrant"
}

TASK [debug] *******************************************************************
ok: [localhost] => {
    "groups": {
        "all": [
            "10.10.10.12", 
            "10.10.10.11"
        ], 
        "consul_server": [
            "10.10.10.12"
        ], 
        "jenkins": [
            "10.10.10.11"
        ], 
        "ungrouped": [
            "localhost"
        ]
    }
}

PLAY RECAP *********************************************************************
localhost                  : ok=3    changed=0    unreachable=0    failed=0
```

インベントリディレクトリに inventories/IaaS/ を指定してみる

```
$ ansible-playbook -i inventories/IaaS/ playbooks/playbook.yml 

PLAY [localhost] ***************************************************************

TASK [setup] *******************************************************************
ok: [localhost]

TASK [debug] *******************************************************************
ok: [localhost] => {
    "datacenter": "IaaS"
}

TASK [debug] *******************************************************************
ok: [localhost] => {
    "groups": {
        "all": [
            "2.2.2.2", 
            "1.1.1.1"
        ], 
        "consul_server": [
            "2.2.2.2"
        ], 
        "jenkins": [
            "1.1.1.1"
        ], 
        "ungrouped": [
            "localhost"
        ]
    }
}

PLAY RECAP *********************************************************************
localhost                  : ok=3    changed=0    unreachable=0    failed=0   
```

宣言した変数すべてが期待通りである。

# 便利です

このようなディレクトリ＆ファイル構成にしておけば、
各環境でインベントリファイルがそろっているかを比較しやすいし、
-i で指定するディレクトリ名を変えるだけで、テスト/本番の切り替えが楽にできますね。

それでは、良いインフラライフを。
GTX 1080 搭載のキューブ型PCを組み立てる

ディープラーニングで遊ぶのに十分そうな性能のPCを組み立てました。
2017/01/25現在の情報です。

2017/03/01追記：何か安くなったらしいです。。グラボを買うタイミングは、GDC(Game Developer Conference)の後が良いという事ですね。
http://www.anandtech.com/show/11173/nvidia-partners-to-begin-selling-geforce-gtx-1080s-gtx-1060s-with-faster-memory

2017/01/25の状況
===============

2017年01月というのは、自作PCを組み立てるには微妙なタイミングです。
まず、CPUが、Intel Core i7 7700　に、チップセットが270系に移行したばかりです。CPUはIntelの力で潤沢に供給されているのですが、マザーボードの供給が不足しています。特にキューブ型に使うMini-ITXは、店舗によって在庫がまちまちな状況となっています。では、古いチップセットのマザーボードでいいか、というとそうもいかず、170系のチップセットを搭載したマザーボードが、Core i7 7770に対応するにはBIOSのアップデートが必要です。が、このアップデートをインストールするには、Core i7 6700のCPUで一度動作指せる必要が有るという、詰んだ状況になります。じゃぁ、Core i7 6700 のCPUでいいか、と思っても、もう売っていません。6700は短命だったので、流量も少なく、ショップにはほとんど在庫が無い状況です。
ということで、流量の少ない270系のマザーボードと、Core i7 7700を選んで組み立てなければいけない、というのが今の状況です。

参考：i7 7700KなどIntel Kabylakeは10月発売か？　ASUSが対応BIOSを一斉配信
http://blog.livedoor.jp/wisteriear/archives/1061521769.html

部品選定
=======

ケース
----

THERMALTAKE CA-1B8-00S6WN-01 [Core V1 Snow Edition] 5.0
http://www.yodobashi.com/1/pd/100000001002932805/
いわゆるキューブ型のケースです。
ケースによって、搭載可能なGPUのサイズが決まりますので、まずケースを確認しましょう。このケースの場合、285mmです。ただし、285mmだと、かなりギリギリで、内部のシャーシからはみ出すので、取り付けに難儀します。（外側のケースからははみ出しません。）
http://www.thermaltake.com/products-model_Specification.aspx?id=C_00002701

GPU
---

ASUS TURBO-GTX1080-8G
http://www.yodobashi.com/1/pd/100000001003212192/
肝心のGPUは、ASUSのものにしました。
どこのものでも良かったのですが、価格が安めだったのと、ボード長が短かったためです。これは、ボード長267mmです。ケースの285mm制限よりは短いですが、内側シャーシの255mmより大きいので、取り付けには注意が必要です。具体的には、マザーボードを取り付けるより先に、ケースに入れておきましょう。そうしないと、マザーボードにぶつかって、GPUが入らなくなります。
https://www.asus.com/jp/Graphics-Cards/TURBO-GTX1080-8G/specifications/

CPU
---

Intel Core i7-7700 プロセッサー
http://www.yodobashi.com/1/pd/100000001003405341/
ファン付きのモデルです。7700K の方が、性能が良いらしいですが、ファンが別売りのため、7700にしました。

マザーボード
----------

MSI エムエスアイ H270I [GAMING PRO AC]
http://www.yodobashi.com/1/pd/100000001003405330/
これが最大の問題で、Intel Core i7-7700 は、Intel 270系のチップセットで無いと動作しません。正確には、BIOSアップデートすれば、170系のチップセットでも動作するらしいですが、アップデートには、i7-6700のCPUが必要、という無理ゲーな状況になります。
ただ、270系は新しくて、Ubuntuのサポートは弱い状況です。オンボードのWiFiを使おうと思ったら、Ubuntu 16.10にする必要が有ります。16.04 がLTSなのですが、残念ながらWiFiは使えません。（頑張って設定したら別ですが）

電源
---

玄人志向 KUROUTOSHIKOU KRPW-PB500W/85+ 
http://www.yodobashi.com/1/pd/100000001002163096/
キューブ型PCは中が狭いので、プラグイン式のにしましょう。

SSD
---

SAMSUNG MZ-N5E250B/CS [バルクSSD 850EVOシリーズ M.2 250GB]
http://www.yodobashi.com/1/pd/100000001002906273/
最近のPCは、SATAのI/Fではなく、M.2 というI/FでSSDを指すのですね。。知りませんでした。
これは特に性能の高いものではないのですが、結果的には十分でした。

メモリー
------

CFD W4U2400PS-8G [DDR4 Value Series]
http://www.yodobashi.com/1/pd/100000001003102304/
8Gの2枚差しです。デュアルチャンネルのため、2枚差しが基本です。

その他
------

購入する部品は以上です。他に適宜、マウス・キーボード・ディスプレイ等を用意してください。
DVDドライブ等は搭載せず、OSはUSBメモリでインストールします。

参考：Ubuntu 16.10 をインストールしてChainerを入れる
http://qiita.com/ikeyasu/items/5213b8902098b197f4d7

お値段
=====

2017/01/25 現在。価格はヨドバシドットコムのものです。

* GPU ASUS TURBO-GTX1080-8G : 83,320円
* ケース THERMALTAKE CA-1B8-00S6WN-01 : 6,270円
* CPU Intel Core i7-7700 プロセッサー : 45,430円
* マザーボード MSI H270I [GAMING PRO AC] : 17,750円
* 電源 玄人志向 KRPW-PB500W/85+ : 6,000円
* SSD SAMSUNG MZ-N5E250B/CS : 15,810円
* メモリ CFD W4U2400PS-8G : 12,490円

合計： 187,070円
ポイント 18,707円がつくので、うまく買えば、17万円ほどでした。
VFページ コントローラ

####標準コントローラを拡張するカスタムコントローラ

```html 
<!-- standardControllerにsObject名、extensionsに拡張コントローラクラスを指定 -->
<apex:page standardController="XX_c" sidebar="false" id="page" extensions="XX_VF_Ctrl">
</apex:page>
```
```java
//stdconを引数とするコンストラクタは必須 
public with sharing class XX_VF_Ctrl {
    
    XX__c crecord;
    
    /*
     * Constructor
     */ 
    public XX_VF_Ctrl(ApexPages.StandardController stdcon){
        crecord = (XX__c)stdcon.getRecord();
    }
}
```

####VFページを返すPOSTメソッド
```java
<apex:commandButton value="サブミット" action="{!xxxSubmit}" />

public PageReference xxxSubmit(){
    PageReference pr = Page.xxx_VFpage; //VFページの名前を指定
    ....
    return pr;
}
```

####パラメータを取得する
GETもPOSTも受け取れる
`String jsonstr = Apexpages.currentPage().getParameters().get('selectedCategories');  
`

####画面表示しない項目をコントローラ側から参照したい場合はaddFieldsを使う
```java:
public xx_Ctrl(ApexPages.StandardController stdcon) {
    //最初に実行すること （テスト時に失敗するため、画面から起動された場合のみで動くようにする）
    if (!Test.isRunningTest()) { 
        stdCon.addFields(new List<String>{'pageType__c', 'SnapshotData__c', 'approvalDate__c', 'status__c'});
    }
```

####cookieの参照・出力
クライアント側のJSで参照する場合はCookie名の前に自動的に共通の接頭辞 'apex__' が付くことに注意

```java
private static String COOKIE_NAME = 'myCookie';
private static Integer SESSION_COOKIE = -1;

private void setCookieValue(Integer v1, String v2){
    Map<String, Integer> data = new Map<String, Integer>();
    data.put('key1', v1);
    data.put('key2', v2);
    Cookie cvalue = new Cookie(COOKIE_NAME, JSON.serialize(data), null, SESSION_COOKIE, true);
    ApexPages.currentPage().setCookies(new Cookie[]{cvalue});
    }

private Map<String, Integer> getCookieValue(){
    Cookie cvalue = ApexPages.currentPage().getCookies().get(COOKIE_NAME);
    if (cvalue==null){
        return new Map<String, Integer>{'key1'=>0, 'key2'=>''};
    }else{
        String value = cvalue.getValue();
        return (Map<String, Integer>)JSON.deserialize(value, Map<String, Integer>.class);
    }
}

````
####エラーの出力
```java
//トリガー内ではオブジェクト/レコードに対して
XXX_c record;
...
this.record.addError('エラーメッセージ'); //オブジェクト全体に対するエラー
this.record.xxx_c.addError('エラーメッセージ');   //特定の項目に対するエラー

//VFコントローラ内ではフィールドまたはページに対して
try{
  ....
}catch(Exception e){
    //単にエラーメッセージを表示するケース
    ApexPages.addMessages(e);
    //sevirtyを指定
    ApexPages.addMessage(new ApexPages.Message(ApexPages.severity.Error,e.getMessage()));
    //ApexPages.severity.CONFIRM
    //ApexPages.severity.ERROR
    //ApexPages.severity.FATAL
    //ApexPages.severity.INFO
    //ApexPages.severity.WARNING

//エラーメッセージのクリア
ApexPages.getMessages().clear();

```
[参考サイト](https://freedom-man.com/blog/forcecom_apexmessage/)
【Parrotドローン】ARSDKのサンプルをコンパイルする(Mac)

# はじめに
MacでARSDKのiOS版サンプルアプリケーションをコンパイルする手順でつまずいた点について記しています。WindowsでAndroid版サンプルアプリケーションをコンパイルするうえでは、役に立たない話かもしれません。

# Parrot社のドローン
多くのメーカー製ドローンとおなじように、[Parrot](http://global.parrot.com/jp/)社が開発しているドローンは、スマートフォン上のアプリケーションから操作できるようになっています。
　
Parrot社はスマートフォンアプリケーション用SDKを一般に公開しているため、ドローンをプログラムで操作するスマートフォン用アプリケーションが開発できます。

# それではさっそく...
アプリケーションを開発してみようと言いたいところですが、まずはせっかくサンプルプログラムを公開してくれているので、そちらをコンパイルしてみましょう。

# ARSDKのサンプルコンパイル手順
iOS版、Android版とも[こちら](http://developer.parrot.com/docs/SDK3/#use-samples)に記されています。

手順どおり、gitからプロジェクトをcloneしてXCodeでプロジェクトを読み込み、実機もしくはシミュレータ向けにコンパイルすればよいのですが、手元の環境ではiOS版のコンパイルで一箇所だけうまくいかなかったところがあるので、そちらについて記します。

# コンパイルが失敗する
gitから取得したDroneProject.xcodeprojをxcodeで開いてビルドすると失敗しました。キャプチャを取り忘れてしまいましたが「ARSDK3_iOS_3_11_0.zipがみつかりません」のような内容がエラーメッセージに含まれていました。

# wgetがない
さきほどのエラーメッセージを読んでみると、Macにwgetがインストールされていないせいで、プリコンパイルしたARSDKがgithubからダウンロードできずにビルドが失敗しているようです。

Macにはwgetがデフォルトではインストールされていません。代わりにcurlがインストールされています。コマンドラインからのhttp、ftpによるダウンロードはcurlでことが足りてしまうので、忘れがちな事実です。

# wgetをインストール
Macにwgetをインストールすればこのエラーは解決しますが、ここで注意しなければならない点がひとつあります。wgetは、SSL通信に対応したものを用意する必要があります。SSLに対応していないwgetをインストールしてビルドすると、「wgetに-no-check-certificateを指定してね」という趣旨のエラーメッセージが出力されてしまいます。

SSL通信に対応したwgetを手に入れる方法は、主に次の2つではないでしょうか。

1. opensslを使ってSSL通信が可能なwgetを一からコンパイルする。
2. [homebrew](http://brew.sh/index_ja.html)でwgetをインストールする。

1については、opensslをインストールして、さらにconfigureでopensslを利用するためのオプションを設定してmakeする必要があります。

2については、opensslを利用する形でwgetをインストールしてくれます。opensslのインストールも併せて実行してくれます。

今回は「より楽に」ということで[homebrew](http://brew.sh/index_ja.html)でwgetをインストールしました。

# ビルドと実行
wgetをインストールしてサンプルプログラムをビルドすると、問題なく実行されるはずです。
VFページ(Action Function)

###VFページ側のAction Functionの例
パラメータを送信することも可能
name=>サーバーコール用のJS関数名
action=>サーバー側メソッド名
reRender=>サーバーコール後に再描画するノードのId

```java:
<apex:form">
  <apex:actionFunction name="updateXXXItem" action="{!updateXXXItem}" reRender="ChatterFeedsArea, xxx" >
    <!-- パラメータはオプション -->
    <apex:param name="feedItemId" value="" />
  </apex:actionFunction>
  <script>
        function doUpdateFeedItem(xxxItemId){
            updateXXXItem(xxxItemId);
        }
  </script>
</apex:form>
...
<apex:outputPanel id="ChatterFeedsArea">
...
```

###サーバー側メソッドの例
送信したパラメータはgetParametersで受け取る

```java
/*
 * update XXXItem
 * (action function)
 */
public void updateXXXItem() {
    String XXXItemId = Apexpages.currentPage().getParameters().get('XXXItemId');
    XXXHelper.updateXXXItem(xxxItemId, MessageBody, vRecordId);
    XXXItems = null;
} 

```
Pythonの抽象クラスで色々試してみた

#はじめに
どうも、Javaが未だに頭から離れないPythonistaです。
なんかPython界隈のすごい人って、抽象クラスとかあんまり使わないよね。
動的型付け言語の自由さを謳歌してるよね。
俺も早くそうなりたいな。でもね、Java脳が許してくれないの。抽象クラス使いたくなるの。別に悪いことじゃないんだけどね。

#あなたは本質を見ているか
急に真面目に話します。最近は便利な世の中で、ググれば大概の答えは出てきます。
Pythonで抽象クラスを使う(べきかどうかは別にして)にはabcモジュールを使えばいいといろんな所に書いています。ではそのabcモジュールがどんな機能を提供してくれているか、あなたは知っていますか？言われたままプログラム書いて、抽象クラス書いた気になってるだけじゃないですか？ちなみに私は何にも知りません。なので色々試して見ます。

#実験
典型的な抽象クラスを書きます。頭にAbsって書いちゃう時点でJava脳だよね。

```py3:hoge.py
class AbsAnimal(metaclass=ABCMeta):
    @abstractmethod
    def eat():
        pass

tmp = AbsAnimal()
>>>TypeError: Can't instantiate abstract class AbsAnimal with abstract methods eat
```
てな感じで、インスタンスの生成をするとエラーが出ます。抽象メソッドを持つ抽象クラスはインスタンスの生成ができないとのこと。いいね、Javaっぽくて。
ここで抽象メソッドのデコレータを削除した下記のクラスのインスタンスを生成するとどうなるのか試してみる。

```py3:hoge.py
class AbsAnimal(metaclass=ABCMeta):
    def eat():
        pass

tmp = AbsAnimal()
tmp.eat()
(エラー発生せず)
```
あれなんですね、抽象メソッドを持ってこその抽象クラスだといいたいのか(当たり前)。
じゃあ逆にmetaclassを外した下記のクラスはどうなるのか。

```py3:hoge.py
class AbsAnimal:
　　　　　　　　@abstractmethod
    def eat():
        pass

tmp = AbsAnimal()
tmp.eat()
(エラー発生せず)
```
あれなんですね、ABCMetaと@abstractmethodを一つのクラスに同時に使って、初めて意味があるということなんですね。ちなみにもっとガチガチに書こうと思ったら、「pass」じゃなくて「raise NotImplementedError()」って書いてもいいかもね。

次に試したのは抽象クラスを継承したクラスの動作。

```py3:hoge.py
class AbsAnimal(metaclass=ABCMeta):
    @abstractmethod
    def eat(self):
        pass

class Human(AbsAnimal):
　　　　　　　　#何も実装してなければエラーになるので、間に合わせ
    def __init__(self):
        pass

tmp = Human()
>>>TypeError: Can't instantiate abstract class Human with abstract methods eat
```

予想通り。次にeatをきちんと実装してみる。

```py3:hoge.py
class AbsAnimal(metaclass=ABCMeta):
    @abstractmethod
    def eat(self):
        pass

class Human(AbsAnimal):
    def eat(self):
        print('おいしい!')

tmp = Human()
tmp.eat()
>>>おいしい!
```

これも予想通り。次にHumanにも抽象メソッドアノテーションを持ったメソッドを追加してみる

```py3:hoge.py
class AbsAnimal(metaclass=ABCMeta):
    @abstractmethod
    def eat(self):
        pass

class Human(AbsAnimal):
    def eat(self):
        print('おいしい!')

    @abstractmethod
    def traning(self):
        pass
        

tmp = Human()
>>>TypeError: Can't instantiate abstract class Human with abstract methods traning
```
これは予想外。Humanクラスには「metaclass=ABCMeta」を指定してないから「@abstractmethod」は無視されると思ってた。
どうやら「metaclassは単一継承では引き継がれる」というPythonの仕様があるらしく、その影響でこのような動作になるらしい。なるほど。

#最後に
なまじ他言語のノウハウがあるばかりに、Pythonにもそれを強要してしまう所は早く治したい。
言語ごとに思想があるので、そこは尊重しなければ。

そんな弊社ですが、もし興味がありましたら、[Qiitaの弊社技術者ブログトップページの下の方](http://qiita.com/organizations/techbureau)から連絡いただけましたら嬉しいです。お待ちしています！