OmniAICreator/Qiita-1.07M huggingface dataset:
docker のネットワーク (docker0) 設定変更 (icc 変更編)

本稿では、icc (Inter-Container Communication) を誤って設定してしまった場合に、icc 設定を削除し、ネットワーク設定を変更する方法を記載します。

以前、「[docker のネットワーク (docker0) 設定変更 - Qiita](https://qiita.com/msi/items/d9cc1a2fd3f0fed3a901)」で docker ネットワーク(範囲)変更の方法を書きましたが、Raspbian (buster) の `docker-ce` では動作が異なり、変更ができませんでした (最悪、systemd による dockerd の起動が失敗し、立ち上がらなくなります)。

調べたところ、これは Raspbian によるものではなく、テストで一時的に icc を設定していたものが残っていたためでした。
しかし、docker で icc=false に設定しても systemd 側にネットワーク設定が残っており、これを削除する必要がありました。

## 現象

`systemctl start docker` で起動させようとすると以下のメッセージを出力し、エラー終了する。

```
Job for docker.service failed because the control process exited with error code. 
See “systemctl status docker.service” and “journalctl -xe” for details.
```
`systemctl status docker.service` と `journalctl -xe` で参照しても、よくわからず、システムログを参照しました。

`/var/log/daemon.log` に以下のような記録が出ていました。

```text:/var/log/daemon.log
failed to start daemon: Error initializing network controller: Error creating default "bridge" network: Poo
l overlaps with other one on this address space
```

各プラットフォームのログの場所とファイル名は「[Read the logs - Configure and troubleshoot the Docker daemon | Docker Documentation](https://docs.docker.com/config/daemon/#read-the-logs)] に記載があります。


## 1. dockerd の停止
dockerd を停止します。(念のため、container は事前にすべて停止してください)

```shell_session
systemctl stop docker
```


## 2. link デバイスの削除
`docker_gwbridge` インタフェース(ブリッジ)を削除します。

* ブリッジインタフェースを確認します。

```
ip link show
```

* ブリッジインタフェースを削除します。

```
ip link del docker_gwbridge
```

## 3. systemd の kv ファイルを削除と systemd のリロード
systemd に残っている Key-Value store の db を削除して、systemd のリロードを行います。

```
rm /var/lib/docker/network/files/local-kv.db
systemctl daemon-reload
```

## 4. dockerd の起動
dockerd の stop から 60秒以上経過していることを確認してください[^1]。

必要に応じて、icc や bip などを設定します。

```json:/etc/docker/daemon.json
{
        "icc": false,
        "bip": "172.17.1.254/24"
}
```

dockerd を起動します。

```
systemctl start docker
```

`docker_gwbridge` が作成されていないことを確認します。

```
ip addr
```

または

```
ip link show
```

docker 側のネットワークデバイスを確認します。

```
docker network ls
```

または

```
docker network inspect bridge
```


終了。


## さいごに
* `/var/lib/docker/network/files/local-kv.db` を削除するのが正しいオペレーションなのかどうか、わかっていません。
* docker のドキュメントを調べてもなかなか正解が見当たらず、systemd 側を調べて KV store に思い当たり、削除を試みました。
* systemd の dockerd のインターバル設定に気づかず、すぐに start させてしまうと設定が正しくてもエラーになり、これで時間を費やしました。





[^1]: dockerd の起動インターバルが 60s に設定されているため、すぐに起動すると、設定が正しくてもエラーになります。
人前でsudoの罵りを見られると色々マズイ[元：sudoするたびに可愛い女の子に罵られたい！！他]

お遊びなのでかなり適当です。すみません…

元ネタ：
・[sudoするたびに可愛い女の子に罵られたい！！](https://qiita.com/onokatio/items/561d544f07c03b26f4d7)
・[fishでもsudoで罵られたい！[元ネタ：sudoするたびに可愛い女の子に罵られたい！！]](https://qiita.com/tukapai/items/f9c33cc7b5ce85f74a1d) 

触発されて自分もツンツンさせてみた。

```sh
export SUDO_PROMPT="[sudo]sudoってあげるから、さっさとパスワードよこしなさい！>"
```

<img width="680" alt="fig1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163288/38f99e8b-7234-8b02-501b-10f90094d587.png">

あ、いいっすね…
でも、もしこれを人前でやってしまうと…。

## 起動時に選ぶ

自分はhomebrewで突っ込んだfishを使っているので、.config/fish/config.fishに…

```sh
read input
switch $input
	case "tsundere mode!"
		export SUDO_PROMPT="[sudo]sudoってあげるから、さっさとパスワードよこしなさい！>"
		echo "ツンデレモード！！！！"
end
```

## 対策後

<img width="1280" alt="スクリーンショット 2020-03-22 17.13.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163288/adbad993-70d1-bcf8-8858-268c4b2d5a8a.png">
Slack Event APIで同じEventが何回も発行される問題の原因と対処

Slack Botを開発するためにEvent APIを使用してEventをSubscribeすると、同一Eventのはずがリクエストが複数回発生してしまうという現象が発生したのでその原因と対処方法を検討した。

# 原因
Slack Event APIは到達率を上げるためにEventを発行してから指定時間以内にEventの発行先からレスポンスが返ってこないと３回リトライ処理を繰り返す。指定時間は以下のドキュメントによると3000ミリ秒とされている。

>Your app should respond to the event request with an HTTP 2xx within three seconds. If it does not, we'll consider the event delivery attempt failed. After a failure, we'll retry three times, backing off exponentially.
https://api.slack.com/events-api

FaaSなど常時起動ではない実行環境の場合、インスタンスの割り当てを行っているときに3000ミリ秒経ってしまって、Eventのリトライが発生してしまう。
Slack側はEventが到達していないと判断されて複数回リトライをするが、FaaS側はインスタンスが割当たったあとに１回目から実行してしまうので、結果として１回のEventにつき複数回の処理をしてしまう。

# 対処方法
## とりあえず複数回処理したくない（簡易編）
リトライされたリクエストには ```X-Slack-Retry-Num```　ヘッダーがついている。

```json
"X-Slack-Retry-Num": ["1"]
```
数字がリトライされた回数になる。
このヘッダーがなければ初回、あれば２回目以降のリトライ処理と判別できるので、C#なら以下のコードで判別できる。

``` req.cs
if (req.Headers.TryGetValue("X-Slack-Retry-Num", out StringValues val))
{
  //リトライなら何も処理せずに200を返す
  log.LogInformation("Retry request" + val);
  return (ActionResult)new OkResult();
}
// リトライでなければこれ以降の処理を続行
```

## 確実に処理をしたい場合
上記の方法だと本当のリトライ処理も捨ててしまうのでサーバーが一時的に利用不可でその後復帰しても処理は行われない。FaaSはステートレスなので、これを厳密に処理するには外部サービスをつかって前後のリクエストを比較する必要がある。リクエストに付加されてくる``` client_msg_id ```が固有のIDなのでこれを外部テーブルなどに入れておき、すでに処理したリクエストかどうかを判断してリトライ処理を受け入れるか破棄するかを判断する必要がある。

自分は１つ目のゆるい方法でやったので実際のコードはなし。
Laravel7 password_resetsテーブルはどこに消えた？

Laravel7がリリースされまして初記事です。

## 事件発生

事件はLaravel7をインストールした時、起こりました。

```
$ composer create-project --prefer-dist laravel/laravel .
$ php artisan -V
Laravel Framework 7.2.2

$ ls -1 ./database/migrations
2014_10_12_000000_create_users_table.php
2019_08_19_000000_create_failed_jobs_table.php
```

`password_resets` ファアイルが消えた...!?

## 失踪したファイル

- https://github.com/laravel/laravel/pull/5257/commits/13e43893ba2457c3e49898f0066a5ce8d7ea74f4

ファイルが削除されてしまっていた...！

## 転がり込んだファイル

- https://github.com/laravel/ui/pull/56/commits/10f59811f2ba4ff82d29d705d25471b469d5e215

[laravel/ui](https://github.com/laravel/ui) ライブラリに移動されました。

## 検証

laravel/ui インストール

```
$ composer require laravel/ui

$ composer show laravel/ui
name     : laravel/ui
descrip. : Laravel UI utilities and presets.
keywords : laravel, ui
versions : * v2.0.1
type     : library
license  : MIT License (MIT) (OSI approved) https://spdx.org/licenses/MIT.html#licenseText
source   : [git] https://github.com/laravel/ui.git 47a0a1dac76f5e73803c86e1f38b2c7e0ae7fa83
dist     : [zip] https://api.github.com/repos/laravel/ui/zipball/47a0a1dac76f5e73803c86e1f38b2c7e0ae7fa83 47a0a1dac76f5e73803c86e1f38b2c7e0ae7fa83
path     : /work/vendor/laravel/ui
names    : laravel/ui
```

```
$ php artisan ui vue --auth

$ ls -1 ./database/migrations
2014_10_12_000000_create_users_table.php
2014_10_12_100000_create_password_resets_table.php
2019_08_19_000000_create_failed_jobs_table.php
```

`--auth` オプションを付けて実行した際に認証系のファイルが生成されますが、その際に `2014_10_12_100000_create_password_resets_table.php` ファイルも生成されました。

謎はすべて解けた！

## 補足

### ui vue で生成されるファイル一覧

```
$ php artisan ui vue
```

```
package.json
resources/js/app.js
resources/js/bootstrap.js
resources/js/components/ExampleComponent.vue
resources/sass/_variables.scss
resources/sass/app.scss
webpack.mix.js
```

### ui vue --auth で生成されるファイル一覧

```
$ php artisan ui vue --auth
```

```
app/Http/Controllers/Auth/ConfirmPasswordController.php
app/Http/Controllers/Auth/ForgotPasswordController.php
app/Http/Controllers/Auth/LoginController.php
app/Http/Controllers/Auth/RegisterController.php
app/Http/Controllers/Auth/ResetPasswordController.php
app/Http/Controllers/Auth/VerificationController.php
app/Http/Controllers/HomeController.php
database/migrations/2014_10_12_100000_create_password_resets_table.php
resources/views/auth/login.blade.php
resources/views/auth/passwords/confirm.blade.php
resources/views/auth/passwords/email.blade.php
resources/views/auth/passwords/reset.blade.php
resources/views/auth/register.blade.php
resources/views/auth/verify.blade.php
resources/views/home.blade.php
resources/views/layouts/app.blade.php
routes/web.php
```
クラウド触ってみたいだけなのにサービス多すぎて困ったら読むメモ[2020/03時点GCP編]

# はじめに

平日はコンサル〜マネジメント中心でコードを書くことも読むこともあまりないので週末に気まぐれに開発をしていますが、普段は自分のPCで開発/実行しているだけでした。（よくて自分のAndroid端末にインストールするくらい）
GCPで無料枠でサーバーが立つという情報をゲットして、ちょっとクラウド触ってみたいなと思って登録はしたものの、サービスいっぱいありすぎて何からやればいいの！？状態になったので、簡単にメモします。

すでに各サービスの違いを知っていたり、公式ドキュメントをあちこち読み込める人にはライトすぎる情報を書くので、回れ右ください。

# 無料枠について

おそらくどこのクラウドベンダーも同じ方式ですが、無料枠には2種類あります。

* 登録から1年間、クレジットから割引される（基本的に利用サービスは縛りなし）
* 特定のサービス、決められた利用量までクレジットから割引される（基本的に永年適当）

GCPについていうと公式ページの以下のページが十分分かりやすいと思います。

[GCP公式]GCPの無料枠
https://cloud.google.com/free/?hl=ja

# ざっくりチャート

## その前に最低限の課金コントロールについて

パブリッククラウドは自分で利用料を把握/分析しながら使うことが前提ですが、この記事を読んでいるあなたはきっとアカウント登録して間も無く、まだほとんど利用していませんよね？
1年間の無料枠はかなり強力で、終わった後にきちんとリソースを開放できればチュートリアルで無料枠を越えることはなかなか考えにくいです。（チュートリアルの途中でリソースを放置する）

チュートリアルを実施する際に、Projectをそれ専用で作成して、終わったらProject自体を消すようにしておきましょう。
これで意図しない無料枠の消費や無料枠の超過をかなり防げるはずです。

## とりあえずHelloWorldで感動したい

ぼくはこのパターンでした。

[GCP公式]Google Cloud Platform ドキュメント
https://cloud.google.com/docs/?hl=ja

公式ドキュメント > Google Cloud を使ってみる > 「Hello, Google Cloud」プログラム > 好きな言語

Pythonの場合は以下ですね。

[GCP公式]App Engine フレキシブル環境での Python のクイックスタート
https://cloud.google.com/python/getting-started/hello-world?hl=ja

## Kubernetesやコンテナ使ってみたい

ぼくが2つ目にチャレンジしたのがこれでした。

公式ドキュメント > Google Cloud ソリューションの作成 > マネージド Kubernetes にウェブアプリをデプロイする

[GCP公式]コンテナ化されたウェブ アプリケーションのデプロイ
https://cloud.google.com/kubernetes-engine/docs/tutorials/hello-app?hl=ja

# サービスの解説

こちらは他の方も書いてくれているので、お任せします。
個人的にメインで使いそうなのは以下かなと思っています。

* Google Compute Engine (GCE): vmwareが最初からあるイメージ。VMから上を構築する。
* Google Kubernetes Engine (GKE): kubeが最初からあるイメージ。クラスタから上を構築する。
* Google App Engine (GAE): スケーラブルなWebサーバーが最初からあるイメージ。アプリだけ作る。
* Cloud Functions: FaaSプラットフォームが最初からあるイメージ。関数のロジックだけ作る。

[Qiita]Google Cloud Platform(GCP)入門
https://qiita.com/NagaokaKenichi/items/449902074e9994803cb8
"LF"のF(Feed)でなぜ改行を表すのか

# はじめに

ASCIIコードにおいて"0x0A"は"LF", "0x0D"は"CR"を表します。
"CR"は"Carrige Return"で、Carrigeをもとの位置に戻すという意味です。これはそのままの意味で理解しやすいです。

"LF"については、"Line Feed"ですが、"Feed"というのは家畜に餌を与えるニュアンスの強い言葉です。
何かを与えるという意味ではFeedを適用できるように思いますが、なんだかすごくもやもやしました。

# 割と納得したニュアンス

このサイトで私と同じ疑問を持った人の質問がされていました。
https://ell.stackexchange.com/questions/148702/the-origin-of-feed-in-line-feed?newreg=0915c3c567624e4ba5290d8070db6a45

Type Writerに紙を与えるというニュアンスです。
Type Writerの作動原理ですが、紙の乗ったCarrigeを動かして印字位置を移動させるというものとなります。
Type Writerに紙をfeedして、lineについてもfeedして、というニュアンスです。

まあ結局のところ母国話者じゃないのでわからないんですが、すっきりしたので良しとします。
あと、この記事にたどり着くまでに2時間くらいかかったので、共有の意味も込めてこの記事を書きます。
bundle install　あれこれ、、、、(☝︎ ՞ਊ ՞)☝︎

railsで便利な機能を加えるために使われるコマンド

```
bundle install
```
は、今まで何気なく使っていましたが、今回の、デプロイ作業の際に発生したエラーにより深く知る事ができました。。。

##簡単にbundle installのあれこれについて簡潔に解説します


##bundler

依存関係を持っている複数のものを一括でインストールしてくれるというものだ

##gemfile

bundle installをする際の設計図的な機能を持つファイル

##Gemfile.lock 

gemfile.lockは実際にインストールした結果図

##bundle install

gemfile・Gemfile.lock の内容を踏まえて必要な情報をインストールするコマンド

##bundle update

gemfileの内容を踏まえて、情報をアップデートするコマンド
また、その更新された情報ををGemfile.lockに記述します
AWS障害は全て通知されると思ってた話

# 結論からいうと
アカウント固有のリソース障害であっても、全ては通知されません。

# 背景
EC2のシステムステータスチェック失敗や、VPNのトンネルステータスがダウン時に、Personal Health Dashboardやメールにて通知されていないことに気づいたので、サポートに問い合わせてみた。

# 問合せ結果
以下、問合せ結果の抜粋です。
>Personal Health DashboardにはAWSアカウント固有のリソースに対するメンテナンス情報や、お客様が影響を受ける可能性のあるAWS大規模障害の情報などが通知されます。
あらかじめ予定されているイベント情報や事前に予兆を検知することのできた障害情報、および広範囲に渡って発生した障害情報などは適宜通知されますが、現時点では個別のリソースにおいて一時的に発生した障害情報などは通知されません。

# 障害に対してどうすべきか
今回のようなEC2やVPNの障害については、Cloudwatchのメトリクスを監視するアラームを作成し、Amazon SNS トピックへの通知、EC2アクション、EC2 AutoScalingアクションによる、ユーザ側での対応が可能です。

# まとめ
障害通知はAWS頼りにするのではなく、重要な箇所についてはユーザ側で監視するようにしましょう。
xcodeのシミュレーター起動せず Error: unable to boot the simulator

#状況
macOS ver10.13.6 なのでxcodeの最新バージョンは適用できず、過去バージョンである xcode10.1 をインストールした。試しにサンプルを起動するとシミュレーターが起動せず、しばらくすると "unable to boot the simulator" と画面にエラーが表示される。

#対処法
```
sudo mkdir /private/tmp 
sudo chmod 1777 /private/tmp
```
tmpフォルダが存在せず、権限に制限があったことが問題でした。

#参考
* https://qiita.com/coa00/items/6ae2766a2991424fd144
* https://stackoverflow.com/questions/46487099/xcode-9-simulator-error-unable-to-boot-the-simulator-launchd-failed-to-respond-m/48075384#48075384
Unknown action 

#Unknown action
railsでアプリを作成していたところ、初めて見るエラーが発生しました。
結果からいうとコードの誤記という恥ずかしいイージーミスでしたので、反省と忘れないために書きたいと思います。

##エラー発生
Users::RegistrationsControllerのnew_credit_cardアクションを実行したところ以下のエラーが発生しました。

````
Unknown action
````

````
The action 'new_creditcard' could not be found for Users::RegistrationsController
````

なるほど、アクションがないのか。
ということで、RegistrationsControllerを確認します。

##解決
以下がコントローラーで当該のアクションを呼び出してる箇所とroutes.rbです。

````uses/registrations_controller.rb
render :new_credit_card
````
````config/routes.rb
get 'creditcards', to: 'users/registrations#new_creditcard'
````

しっかりアクション名を書き間違えていました。
ということで、これを修正することでエラーが直りました。

#おわり
今回はアクション名がルーティングとコントローラーで不一致だったためエラーが起きましたが、呼び出したいアクションをコントローラーのprivate以下に書いた場合でも、今回と同じエラーが起きるそうです。
最後まで見ていただきありがとうございました。
ffmpegで使うコマンド

ffmpegでよく使うコマンドをまとめていきたいと思います。

# 静止画切り出し
```
ffmpeg -i input.mp4 -r 1/30　-q:v 1 -f image2 %06d.jpg
```

|オプション |内容|
|:--|:--|
| -i | 入力ファイル |
| -r | 1秒間に何枚切り出すか。1/30は30秒に1枚になる。|
| -f |フォーマット|
| -q:v | 画質 数字が大きくなると粗くなる |

# 解像度変更
```
ffmpeg -i input.mp4 -vf scale=-1:1080 out.mp4
```
|オプション |内容|
|:--|:--|
| -vf |scale　画像解像度の指定　横×縦 -1とすることで元画像の比率で調整される。 |

# 再生スピード
```
ffmpeg -i input.mp4 -vf setpts=PTS/100 out.mp4
```
|オプション |内容|
|:--|:--|
| -vf |setpts=PTS/xx　xxに何倍にするかの数値、例では１００倍|
laravel-ide-helperの"Str"と"Arr"がphpstormでコード補完されない

#起きたこと
laravel-ide-helperを入れてvscodeで開発していたが、気分でphpstormに切り替えたら全然コード補完してくれない。phpstormでも使いたいので対処方を記す。拡張機能はそれぞれ、vscodeにintelephense、phpstormにはlaravelくらいしか入れていない。

phpstorm
![1dfd7b29247b1751db1488f624b49485.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128655/0139fc0f-bafe-efb9-f774-c924b9c00385.gif)

vscode
![7ae9a559dba30c7b58d1289161bf4762.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128655/54b3fc0d-d1be-e2c6-09b4-ee0b1f2b5510.gif)

#原因
大体の流れはこれ
[Laravel added aliases for 'Arr' and 'Str' no autocomplete from helper #784](https://github.com/barryvdh/laravel-ide-helper/issues/784)
昨年2月にlaravel本体でマージされたalias追加でide-helperに不具合が生じた。対応は誰か試みたらしいがテストが通らないっぽくて放置されてる。

#対処方
生成した"_ide_helper.php"のnamespaceをコメントアウト（または削除）する。
![ba063115db4811efd422820b212549f9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128655/58dee076-90ae-c41b-c384-19f85fd766b2.png)

すると補完される。
![59cdfa7915b72c54394f910e2c7f6b03.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128655/a3c2dd5c-7ae4-b1c8-a844-14d753d371ee.gif)
NSQ環境をDockerで構築する(『Go言語によるWebアプリケーション開発』第5章)

[『Go言語によるWebアプリケーション開発』(Mat Ryer著、鵜飼文敏監訳、牧野聡訳; O'Reilly Japan)](https://www.oreilly.co.jp/books/9784873117522/)の「第5章　分散システムと柔軟なデータの処理」ではNSQというメッセージキューソフトウェアを利用して、Twitterのツイートを分析します。同書内ではNSQの構築をローカルマシンに直接インストールしているのですが、Dockerを利用して構築することも可能です。本記事では、Dockerを用いたNSQの構築手順について、簡単にまとめておきます。

# 前提

動作確認を行った環境は次の通りです。

- Windows 10 Home
- Docker ToolBox

また環境変数`DOCKER_HOST`は次の通りに設定されています。

```
DOCKER_HOST=tcp://192.168.99.100:2376
```

# 手順

まずはNSQのイメージを取得します。

```
docker pull nsqio/nsq
```

次に`nsqlookupd`を起動します。ここではコンテナ名を`go-webapp-nsqlookupd`としています。

```
docker run -d                 ^
  --name go-webapp-nsqlookupd ^
  -p 4160:4160 -p 4161:4161   ^
  nsqio/nsq /nsqlookupd
```

最後に`nsqd`を起動させれば完了です(コンテナ名は`go-webapp-nsqd`)。

```
docker run -d                               ^
  --name go-webapp-nsqd                     ^
  -p 4150:4150 -p 4151:4151                 ^
  nsqio/nsq /nsqd                           ^
  --broadcast-address=192.168.99.100        ^
  --lookupd-tcp-address=192.168.99.100:4160
```

わかりづらいのは`nsqlookupd`と`nsqd`で別のコンテナを起動する必要があるということ。また`--broadcast-address`や`--lookupd-tcp-address`に指定する値もわかりづらいのですが、おおよそ上記の通りに設定すればOKです。

# おまけ

同書では`nsq_tail`を利用しているのですが、Dockerを利用している場合は`nsq_tail`用にコンテナを作成します。たとえば`votes`というトピックを対象にする場合、以下のコマンドを実行します。

```
docker run --rm nsqio/nsq /nsq_tail          ^
  --lookupd-http-address=192.168.99.100:4161 ^
  -topic votes
```

# 参考

- https://nsq.io/deployment/docker.html
- https://github.com/nekoTheShadow/go-webapp
macOS Catalina で python の開発環境を作るメモ

*メモ随時更新予定*

狙いとしては python の開発環境の構築

Mojave から Catalina に上げた環境で、普通にやってるとバージョンの違いで `python3` とか `pip3` で期待通りに動かなかったので `pyenv` あたりを利用してうまいこと動かないか試す。

*本当は Docker とか使った方が良さそうだけどひとまず・・・*

# homebrew

ここからスタート。

```
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
```

# pyenv インストール

```
$ brew install pyenv
$ pyenv -v
pyenv 1.2.17
```

## プロファイルの設定

```
$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
$ echo -e 'if command -v pyenv 1>/dev/null 2>&1; then\n  eval "$(pyenv init -)"\nfi' >> ~/.bash_profile
```
https://github.com/pyenv/pyenv

ちなみに、zsh の場合には `.zshrc` に対して同様の設定を行えば良いみたいです。

> Zsh note: Modify your ~/.zshrc file instead of ~/.bash_profile.
https://github.com/pyenv/pyenv

`.zprofile` ではなく、`.zshrc` な理由は不明。


反映

```
$ source ~/.bash_profile
```

## バージョンを指定して python をインストール

インストール可能なバージョンを確認

```
$ pyenv install -l
```

使いたいバージョンをインストール

```
$ pyenv install 3.7.7
```

インストールの確認

```
$ pyenv versions
* system (set by /Users/ykinomt/.pyenv/version)
  3.7.7
```

## バージョン切り替え

現状確認

```
$ python -V
Python 2.7.16
```

切り替え

```
$ pyenv global 3.7.7
$ python -V
Python 3.7.7
```

そのディレクトリ単位で切り替えるなら local を使う。

```
$ python -V
Python 2.7.16
$ pyenv local 3.7.7
$ python -V
Python 3.7.7
```

localを使った場合、そのディレクトリに `.python-version` というファイルが作成され、そのディレクトリでは指定されたバージョンで動く。
アプリケーションを作成する様な場合は local で指定した方が良いかも。

# vscode の設定

特に必要ないが、インタープリタの設定で出てくるバージョンは VSCode 起動までにインストールされたモノみたいなので、上記の設定で新規にインストールした場合には一度 vscode を再起動しないと選択できないかも。
CNCF News (03/16 - 03/20 2020)


### [How to setup Role based access to Kubernetes Cluster](https://www.cncf.io/blog/2020/03/17/how-to-setup-role-based-access-to-kubernetes-cluster/) - March 17, 2020 

- ```CNCF Member Blog```
- Kubernetes の RBAC 設定方法。読んだ中では珍しく、ハンズオンな記事。Kubernetes 上のユーザ ```DevUser```を作成し、pod 作成権限を与える、という内容。ベーシックな内容ですが、Kubernetes におけるユーザや Role の概念を理解するのにはよいのではないでしょうか。CKA/CKAD 対策にも。
- この記事の中で実施していること
    - 前提： Minikube 環境
    - namespace ```develpment``` 作成
    - Kubernetes 接続用の Client certificate を作成
    - Client certificate を利用して、config ファイルを作成
      - ```kubectl```で Kubernetes のAPIサーバに接続するため
    - Role ```dev-role``` および RoleBinding ```dev-DevUser```を作成し、```DevUser``` に pod 作成権限を付与
    - ```kubectl run``` によって nginx コンテナを作成

### [My Internship with Thanos: A CNCF Project](https://www.cncf.io/blog/2020/03/20/my-internship-with-thanos-a-cncf-project/) - March 20, 2020

- ```Community Blog Post```
- Medium に投稿された、Thanos Project に参加したインターンシップ生（大学生）の記事。以下の内容を紹介している。
    1. どうやってCNCFを知り、インターンに選ばれたか
    1. Thanos project をについてどのように学んだか
    1. メンターたちとの議論
    - このプロジェクトからの学び
- Thanos とは、オブジェクトストレージをベースにした Prometheus の一括管理の仕組み。Prometheus を冗長化したり、メトリクス情報をオブジェクトストレージに蓄積することで、容量制限の無い仕組みを実現したり、冗長化された Prometheus 群に対するグローバルクエリを飛ばしたりできるようです。以下 Thanos のアーキテクチャ

![Thanos Architecture Overview](https://github.com/thanos-io/thanos/raw/master/docs/img/arch.jpg)
画像出典：https://github.com/thanos-io/thanos

1. どうやってCNCFを知り、インターンに選ばれたか
    - お兄さん（おそらく）がソフトウェア開発者をしていて、Prometheusのステッカーを持っていたことがきっかけ。
    - Google Summer of Code にて、Thanos, Prometheus, Cortext, Fluentd のプロジェクトに応募した。その際にメールで以下の質問を受けた。
        - なぜ Thanos に応募したのか？
        - 似たようなプロジェクトに携わった経験はあるか
        - Thanos project に関してやりたいアイデアはあるか？
        - このプロジェクトに何時間費やすことができるか？
    - できるだけ正直に答えることをおすすめする、とのこと。「クラウドネイティブのモニタリングソリューションに貢献したい、分散システムをもっと学びたい、オープンソースに貢献する非常に良い機会だと思う。」と言及したそう。

1. Thanos project をについてどのように学んだか
  - Youtube や playgolang.org などで、Golang の経験を積んだ

1. メンターたちとの議論
  - 毎週木曜にキャッチアップを行った
  - ミーティング前にアジェンダを用意し、各論点において、複数の異なるアプローチ、どれがいいのかを含めて議論をした。

1. このプロジェクトからの学び
  - CNCF Slack のチャネルでの議論内容を理解
  - Golang の仕組みを学んだ
        - channels, goroutiness, error handling, slices, interfaces, unit testing, table tests, benchmarking, etc
  - 問題は、プロジェクトが対象とする変更内容が変わっていったこと。

### ディスクレーマ
ニュースの内容は私自身の理解ですので、正しい内容はリンク先をご確認ください。
認識齟齬、誤記などありましたらご指摘いただけますと幸いです。
Spring Initializrで作ったプロジェクトがGradleWrapperでのコンパイルに失敗する

## 概要
Spring boot Initializrを使ってプロジェクトを作成後、梱包されているGradle wrapperでそのプロジェクトのコンパイルを試みるも、エラーになりました。
build.gradleに記述を追加することで、解決できたのでその方法を記述します。

## Spring boot プロジェクトの作成
依存パッケージの同時ダウンロードや、Spring bootのバージョン、コンパイラを指定して、プロジェクトを作成できる、Spring Initializrを使ってプロジェクトを作成しました。
プロジェクト作成時に以下のパラメータを指定しました。
https://start.spring.io/

- Project: Gradle Project
- Language: Java
- Spring Boot:  2.2.5

プロジェクト作成後、一緒に梱包されたGradle wrapperでコンパイルをすると、以下のコンパイルエラーになりました。

```
java.lang.NoClassDefFoundError: org/gradle/api/internal/plugins/DefaultConvention
	at org.jetbrains.plugins.gradle.tooling.builder.ProjectExtensionsDataBuilderImpl.buildAll(ProjectExtensionsDataBuilderImpl.groovy:50)
	at org.jetbrains.plugins.gradle.tooling.internal.ExtraModelBuilder.buildAll(ExtraModelBuilder.java:67)
	at org.gradle.tooling.provider.model.internal.DefaultToolingModelBuilderRegistry$BuildOperationWrappingToolingModelBuilder$1$1.create(DefaultToolingModelBuilderRegistry.java:104)
// 以下省略
```

いくつかのページを見て、Gradleのバージョンが悪そうだと見当をつけ、Gradle wrapperのバージョンを変更したらコンパイルが成功するのではないかと仮定しました。
https://github.com/gradle/gradle/issues/11769

## バージョンを指定してgradle　wrapperを作成する
build.gradleに以下を追記します。

```gradle:build.gradle
// 省略
wrapper {
	gradleVersion = '5.6'
}
```

一度、Gradle wrapperを削除し、先ほどの記述を追加したbuild.gradleと同じフォルダの階層で、以下コマンドでGradle　wrapperを作成しました。

```sh

$ gradle wrapper

// 作成後、バージョンを確認します。
$ ./gradlew --version
Downloading https://services.gradle.org/distributions/gradle-5.6-bin.zip
.........................................................................................

Welcome to Gradle 5.6!

Here are the highlights of this release:
 - Incremental Groovy compilation
 - Groovy compile avoidance
 - Test fixtures for Java projects
 - Manage plugin versions via settings script

For more details see https://docs.gradle.org/5.6/release-notes.html


------------------------------------------------------------
Gradle 5.6
------------------------------------------------------------
// 省略
```

コンパイルに若干時間がかかりますが、終了後、作成されたGradlewを使って,
Spring Initializrで作成したプロジェクトをコンパイルすると、無事にコンパイルできました。

### 追記
調べていてわかったのですが、build.gradleに記述を追加しなくても、Gradle wrapperのバージョンは変更できそうです。

```
$ gradle wrapper --gradle-version 5.6
```

## まとめ
Spring Initializrで作成したプロジェクトに梱包されたGradle wrapperで、プロジェクトをコンパイルできない時の解決方法を記述しました。
今回はSpring Initializr起因の問題の解決方法でしたが、
Gradle WrapperのGradleバージョンを変更する時にも、上記のコマンドは利用できると思うので、簡単にまとめておきます。
Wikipediaの国旗画像を一括ダウンロードする【Python】【BeautifulSoup】

#概要
[Wikipediaの国旗の一覧](https://ja.wikipedia.org/wiki/%E5%9B%BD%E6%97%97%E3%81%AE%E4%B8%80%E8%A6%A7)に載っている国旗画像をpythonでダウンロード（スクレイピング）しました。

#参考

* [国旗には何色がよく使われているのか？ - Pythonで色相の頻度分布を調べてみる](http://roomba.hatenablog.com/entry/2016/06/29/150003)
* [Python 3.6でWebスクレイピングしてみました](https://qiita.com/hirouen/items/7bc7fa05cc2d774edf44)

#環境
macOS Catalina
python3.8.0
#ライブラリのインストール

```shell
pip install beautifulsoup4
pip install requests
pip install urllib
pip install lxml
```
#実装
figsというフォルダを予め作成した状態で実行してください。

```Python
from bs4 import BeautifulSoup
import requests
import urllib
import os
import time

#wikipedia「国旗の一覧」のurl
wiki_url = "https://ja.wikipedia.org/wiki/%E5%9B%BD%E6%97%97%E3%81%AE%E4%B8%80%E8%A6%A7"

#htmlソースの取得とパース
html_text = requests.get(wiki_url).text
soup = BeautifulSoup(html_text,"lxml")

#imgタグの取得
imgs = soup.find_all("img")
#国旗画像URLの取得
flag_urls = []
for tag in imgs:
    #国旗画像のimgタグはalt属性が"〇〇の旗"という形式になっているので（2020年3月22日現在）、"旗"が含まれるものだけ処理する。
    if "旗" not in tag.get("alt"):
        continue
    url = tag.get("src") #src属性（urlの相対パス）を取得
    url = "https:"+url #https:を先頭につけて絶対URLにする
    flag_urls.append(url)

for url in flag_urls:
    #ダウンロード先のパスの指定
    #各URLの末尾は"125px-Flag_of_国名.svg.png"のようになっている。ここから"Flag_of_国名.png"をダウンロード後のファイル名にする
    png_name = url.split("px-")[-1].split(".")[0]+".png"
    #figsというディレクトリの下に保存する。figsは予め作っておく
    png_name = os.path.join("./figs",png_name)
    #ファイルが存在しない場合のみダウンロードする
    if os.path.exists(png_name): 
        print("File",png_name,"already exists")
        continue
    urllib.request.urlretrieve(url,png_name)
    print("File",png_name,"downloaded")
    #サーバに負荷を与えないため待機
    time.sleep(1)
```
ファイル名が一部文字化けしていましたが、ダウンロードは無事できました。

#おまけ
国旗ファイル名と日本語国名の対応表が欲しい場合は上記コードのimgs変数のalt属性から情報を取得できます

```Python
from bs4 import BeautifulSoup
import requests
import urllib
import os
import time

#wikipedia「国旗の一覧」のurl
wiki_url = "https://ja.wikipedia.org/wiki/%E5%9B%BD%E6%97%97%E3%81%AE%E4%B8%80%E8%A6%A7"

#htmlソースの取得とパース
html_text = requests.get(wiki_url).text
soup = BeautifulSoup(html_text,"lxml")
#imgタグの取得
imgs = soup.find_all("img")
#国名とファイル名の対応表を作る
table = []
for tag in imgs:
    #国旗画像のimgタグはalt属性が"〇〇の旗"という形式になっているので（2020年3月22日現在）、"旗"が含まれるものだけ処理する。
    if "旗" not in tag.get("alt"):
        continue
    country_name = tag.get("alt")[:-2] #"〇〇の旗"の"〇〇"(最後2文字以外）を取得
    url = tag.get("src") #src属性（urlの相対パス）を取得
    #各URLの末尾は"125px-Flag_of_国名.svg.png"のようになっている。ここから"Flag_of_国名.png"をダウンロード後のファイル名にする
    png_name = url.split("px-")[-1].split(".")[0]+".png"
    table.append(country_name+','+png_name)

with open("name_to_img.csv", "w") as f:
    f.write("\n".join(table))
    
```
Windows で相手のポートが開いているか確認する方法

# Windows で相手のポートが開いているか確認する方法
疎通確認などで、windowsの標準コマンドを利用して接続先のポートが開いているかの確認方法として
telnetを利用していたのですが、もうtelnetがデフォルトでインストールされないのでそれに代わるコマンドを紹介します。


# やりたいこと
接続先のポートが開いているかを確認したい。
かつ、それをWindowsの標準コマンドで確認したい。


# やり方
PowerShell で下記コマンドを実行します。
下記例は、接続先：192.168.11.100の3389ポートが開いているかの確認方法です。

```PowerShell
Test-NetConnection 192.168.11.100 -Port 3389
```

### 実行結果（成功例）
実行結果はこんな感じで表示されます。
SourceAddressが自分のIPでRemoteAddressが接続先のIPです。
TcpTestSucceededがTrueなので3389が開いているという確認が取れました。

```PowerShell
PS C:\Users\Administrator> Test-NetConnection 192.168.11.100 -Port 3389


ComputerName     : 192.168.11.100
RemoteAddress    : 192.168.11.100
RemotePort       : 3389
InterfaceAlias   : イーサネット 3
SourceAddress    : 192.168.11.10
TcpTestSucceeded : True
```
### 実行結果（失敗例）

接続先の3389を閉じて再度確認すると、下記のようになります。
3389はNGだったけど、pingは通ったよ。という結果に。
ping確認までしてくれるなんて結構親切です。

```PowerShell
PS C:\Users\Administrator> Test-NetConnection 192.168.11.100 -Port 3389
警告: TCP connect to 192.168.11.100:3389 failed


ComputerName           : 192.168.11.100
RemoteAddress          : 192.168.11.100
RemotePort             : 3389
InterfaceAlias         : イーサネット 3
SourceAddress          : 192.168.11.10
PingSucceeded          : True
PingReplyDetails (RTT) : 7 ms
TcpTestSucceeded       : False
```
DangerとGitHub ActionsでPull Request時に最低限のレビューを自動化する

# 概要

チーム開発において `Pull Request` 時のコードレビューは必要不可欠です。
コードレビューにはもちろん、レビューワーの工数がかかります。
そこで、レビューワーの負担を少なくするために、 
`GitHub Actions` と `Danger` で必要最低限のレビューを自動化し、本質的な部分のみ
レビューワーがチェックするようにしたいと思います。


# 実装

## ディレクトリ構造例

```text:tree
danger-github-actions
├── .eslintrc.js
├── .github
|  └── workflows
|    └── actions.yml
├── src
|  ├── greeting.js
|  └── greeting.test.js
├── dangerfile.js
├── package.json
└── yarn.lock
```


## Danger

`dangerfile.js` をルートディレクトリ配下に作成します。
`Danger` は `TypeScript` にも対応しているため、 `dangerfile.ts` としても問題ありません。
 
```js:danger.js
let isAllCheckPassed = true;

if (danger.github.pr.title.includes('[WIP]')) {
  fail("Should NOT inclued 'WIP' in your PR title");
}

if (!danger.github.pr.assignee) {
  warn("Should select PR reviewer");
  isAllCheckPassed = false;
}

const hasIssuesNumber = /#[0-9]/.test(danger.github.pr.title);
if (!hasIssuesNumber) {
  warn("Should include issues number in your PR title");
  isAllCheckPassed = false;
}

const diffSize = Math.max(danger.github.pr.additions, danger.github.pr.deletions);
if (diffSize > 500) {
  warn("Should reduce diffs less than 500");
  isAllCheckPassed = false;
}

if (danger.github.pr.changed_files > 10 ) {
  warn("Should reduce change files less than 10");
  isAllCheckPassed = false;
}

if (isAllCheckPassed) markdown('## All checkes have passed :tada:')
```

### チェック項目
- PR タイトルに'[WIP]'が含まれていないか
- レビューワー(assignree)が選択されているか
- PR タイトルにIssues番号(ex. #123)が含まれているか
- 追加行と削除行の合計が500行以下か
- 編集ファイル数が10ファイル以下か

`fail()` を呼び出すと `ci` は失敗し、マージできないようになります。
`warn()` の場合は警告を表示しますが、マージは可能です。

今回は使用していませんが `message()` でメッセージ表示ができます。 
`markdown()` とすることで `markdown` にも対応できます。

## package.json

`GitHub Actions` で実行したいコマンドを `package.json` に登録しておくと良いでしょう。

```json:package.json
{
  "scripts": {
    "lint": "eslint --ext .js ./src",
    "test": "jest",
    "danger": "danger ci"
  }
}
```

## actions.yml

`GitHub Actions` で実行したい `workflow` を記述します。

```yaml:.github/workflows/actions.yml
name: actions
on: [pull_request]

jobs:
  actions-ci:
    runs-on: ubuntu-latest
    
    steps:
    - name: Checkout Repository
      uses: actions/checkout@v2

    - name: Prepare Node Env
      uses: actions/setup-node@v1
      with:
        node-version: '12.x'
    
    - name: Install yarn
      run: npm i -g yarn

    - name: Install Dependencies
      run: yarn

    - name: Run ESLint
      run: yarn lint

    - name: Run Jest
      run: yarn test

    - name: Run Danger
      run: yarn danger:ci
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```

# 実行結果

`Pull Request` を作成すると `GitHub Actions` が実行され、
下記のように結果がコメントとして投稿されます。

<img width="746" alt="スクリーンショット 2020-03-22 16.18.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207520/8e3f7bf6-de89-1291-47c4-b4e2097f9c64.png">


# 最後に

`ESLint` のように設定をカスタマイズすることができます。
`Pull Request` 作成時にもチームとしてルールを設けて見てはいかがでしょうか ☺️


## refs
- https://danger.systems/reference.html
- https://danger.systems/js/
Vagrant で overmind s が実行できない場合の環境設定

## 起きているエラー🙈💭

```
$ overmind start
listen unix ./.overmind.sock: bind: operation not permitted
```
## エラーの内容🙊💭
`Vagrant` で `overmind` を使用する場合、マウントフォルダがユーザー配下でないため、デフォルトの `overmind s`が通らない

## 解決方法🌟
### 方法A: コマンド実行時パスを渡す
```
$ overmind s -s ~/.overmind.sock
```


### 方法B: 環境変数を `.env` に書く
`overmind` を実行するアプリケーションのルートに `.env`を作成し、環境変数で渡す

```..env
OVERMIND_SOCKET=/home/vagrant/overmind.sock
```
```
$ overmind s
```


これで Vagrant 環境下でも overmind コマンドが使えるようになりました🐈
なお `overmind` を常用する場合は、パスを指定する必要のなくなる、`方法B` がおすすめです✨
謎の余白の正体 CSS編

#余白ができた原因

・要素が二重で反映されている
・親要素からはみ出ている
・ファイルがダブっている

ここら辺を確認すると解決できます

##今回の謎の余白問題

私の場合、子要素に、親要素あてにfloat:left;を指定したことによって、、、

小要素が親要素から横幅が出たことによって生じた現象でした

また、この謎の余白は、、、検証ツールでは指定できません

ここが、また厄介なところです。。
フォルダ内のすべてのxlsxファイルを、CSVファイルに一括変換する

# 背景・前提・仕様とか

仕事用Excel操作ツール作成用メモ。
これ↓の派生。
[フォルダ内のすべてのxlsxファイル名を自然順のリストで取得して、絶対パスを構築する](https://qiita.com/Mistizz/items/715858aff435ad061e0c)


# 使い方

1. デスクトップ上に新しいフォルダを２つ、"folder1", "folder2"という名前で作る。

2. "folder1"内に、変換したいxlsxのファイルをすべて放り込む。

3. 動かす。

4. "folder2"内に、csvファイルに変換されて保存。



# 実行環境

実行環境と各ライブラリのバージョンは下記の通り。

- Windows10 pro
- Python 3.7.3
- natsort 7.0.1
- openpyxl 3.0.3

# フォルダ内のすべてのxlsxファイルを、CSVファイルに一括変換する。
```python:all_xlsx_to_csv.py
import os
import csv
import openpyxl
from natsort import natsorted


# デスクトップに作った任意のフォルダ名称

folder_name = "folder1"
folder_2_name = "folder2"


# 定数
desktop_path = os.getenv("HOMEDRIVE") + os.getenv("HOMEPATH") + "\\Desktop"
folder_path = os.path.join(desktop_path, folder_name)
folder_2_path = os.path.join(desktop_path, folder_2_name)


# Excelファイル名リストを自然順で取得
files = natsorted(os.listdir(folder_path))

#ファイル名リストをfor文でまわして各ファイルの絶対パスを構築
for filename in files:
    filepath = os.path.join(folder_path, filename)
    
    # xlsxファイルにアクセス→先頭シートのオブジェクトを取得
    wb = openpyxl.load_workbook(filepath)
    ws_name = wb.sheetnames[0]
    ws = wb[ws_name]
 
    # csvに変換して、folder2に保存
    savecsv_path = os.path.join(folder_2_path, filename.rstrip(".xlsx")+".csv")
    with open(savecsv_path, 'w', newline="") as csvfile:
        writer = csv.writer(csvfile)
        for row in ws.rows:
            writer.writerow([cell.value for cell in row])
    
```
【vue.js】３桁ごとにカンマを入れる正規表現【ES6】

## 3000000→3,000,000を表示されるようにしたい
```html:index.html
<body>
  <div id="app">
    <p>
      合計 {{ sum | numberWithDelimiter }}円  
    </p>
  </div>
  <script src="js/index.js"></script>
</body>
```

```js:index.js
new Vue({
  el: '#app',
  data() {
    return {
      sum: 3000000
    }
  },
  filters: {
    numberWithDelimiter(value) {
      if(!value) return '0'
      return value.toString().replace(/(\d)(?=(\d{3})+$)/g, '$1, ')
    }
  }
})

window.vm = vm
```
windowsで"tail -f "する

# windowsで"tail -f"する
linux だと"tail -f <ファイル名>"で、ログなどの出力を確認しつつ作業できるのですが、PowerShellを利用することで、Windowsでも同様のコマンドが利用できるので紹介します。

#やりたいこと
windowsでファイルに書き込まれる情報をリアルタイムに確認する。
かつ、それをWindowsの標準コマンドで実施したい。

通常、ファイルを一回開くと裏でシステムがファイルに書き込みを実施していても、開いているファイルには反映されないため、その内容を確認するためには、下記作業が必要です。
・ 一旦ファイルを閉じる
・ ファイルを開きなおす

これから紹介する方法でファイルを開くと、Windowsであっても、リアルタイムに書き込まれた情報を確認できます。

#やり方
PowerShell で下記コマンドを実行します。
下記例は、"C:\test.log"を監視する方法です。

```PowerShell
Get-Content -Path C:\test.log -wait -tail 0
```

たまに文字化けするので、文字コードを指定したい場合は"-Encoding"オプションを付けます。
例えば、UTF-8にしたい場合は下記となります。

```PowerShell
Get-Content -Path C:\test.log -wait -tail 0 -Encoding UTF8
```
EC2の起動設定と起動テンプレートの違い

# そもそも起動設定って何？
EC2インスタンスを起動するために、AutoScalingグループで使用される設定です。
よくあるユースケースとしてAutoHealingと呼ばれる、インスタンス障害発生時に障害インスタンスを削除し、新規インスタンスの起動で使用されます。

# 起動テンプレートと何が違うの？
起動テンプレートは起動設定の後継となるサービスとなります。
AWS公式ユーザガイドにも、以下のように記載されております。
>Amazon EC2 の最新機能を確実に使用できるようにするために、起動設定ではなく起動テンプレートを使用することをお勧めします。

起動設定と比較すると設定可能な項目が多いため、詳細なユースケースに対応することが可能です。
また、起動テンプレート単体でEC2起動が可能なので、AMIからの手動展開が楽になります。

# 小ネタ
AWSマネジメントコンソールにて、作成済みのEC2インスタンスをチェックし、アクションから「Create Template From Instance」をクリックすると、自動で起動テンプレートが作成されるのでオススメです。
![0CC3BE44-4518-470B-98B3-DAACC0DD0C9E_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596403/6cc11e5d-29fe-f8f7-ca9a-1b61f0dee601.jpeg)

# 参照
+ [Amazon EC2 AutoScaling ユーザガイド 起動テンプレート](https://docs.aws.amazon.com/ja_jp/autoscaling/ec2/userguide/LaunchTemplates.html)
CakePHP4でメール送信


CakePHP4のドキュメント
https://book.cakephp.org/4/en/core-libraries/email.html
を参考に、以下のコードでメールを送信しようとしたところ、

```php
        $mailer = new Mailer('default');
        $mailer->setFrom(['me@example.com' => 'My Site'])
            ->setTo('you@example.com')
            ->setSubject('About')
            ->deliver('My message');
```

以下のエラーとなった。

```
2020-03-22 16:02:04 Error: [InvalidArgumentException] Unknown email configuration "default". in /var/www/example/vendor/cakephp/cakephp/src/Mailer/Mailer.php on line 411
Stack Trace:
- /var/www/example/vendor/cakephp/cakephp/src/Mailer/Mailer.php:208
- /var/www/example/src/Controller/CategoriesController.php:30
- /var/www/example/vendor/cakephp/cakephp/src/Controller/Controller.php:524
- /var/www/example/vendor/cakephp/cakephp/src/Controller/ControllerFactory.php:79
- /var/www/example/vendor/cakephp/cakephp/src/Http/BaseApplication.php:229
- /var/www/example/vendor/cakephp/cakephp/src/Http/Runner.php:77
- /var/www/example/vendor/cakephp/authentication/src/Middleware/AuthenticationMiddleware.php:124
- /var/www/example/vendor/cakephp/cakephp/src/Http/Runner.php:73
- /var/www/example/vendor/cakephp/cakephp/src/Http/Runner.php:77
- /var/www/example/vendor/cakephp/cakephp/src/Http/Middleware/CsrfProtectionMiddleware.php:132
- /var/www/example/vendor/cakephp/cakephp/src/Http/Runner.php:73
- /var/www/example/vendor/cakephp/cakephp/src/Http/Runner.php:58
- /var/www/example/vendor/cakephp/cakephp/src/Routing/Middleware/RoutingMiddleware.php:162
- /var/www/example/vendor/cakephp/cakephp/src/Http/Runner.php:73
- /var/www/example/vendor/cakephp/cakephp/src/Routing/Middleware/AssetMiddleware.php:68
- /var/www/example/vendor/cakephp/cakephp/src/Http/Runner.php:73
- /var/www/example/vendor/cakephp/cakephp/src/Error/Middleware/ErrorHandlerMiddleware.php:118
- /var/www/example/vendor/cakephp/cakephp/src/Http/Runner.php:73
- /var/www/example/vendor/cakephp/debug_kit/src/Middleware/DebugKitMiddleware.php:60
- /var/www/example/vendor/cakephp/cakephp/src/Http/Runner.php:73
- /var/www/example/vendor/cakephp/cakephp/src/Http/Runner.php:58
- /var/www/example/vendor/cakephp/cakephp/src/Http/Server.php:90
- /var/www/example/webroot/index.php:40

Request URL: /
Referer URL: https://dev.example.com/
Client IP: 10.100.0.1
```

EMailのConfigが読めていない様子。

CakePHPのIssueを調査したところ、
CakePHP3.8から4にバージョンアップしたらメールが送信できなくなった旨が報告されていた。
https://github.com/cakephp/cakephp/issues/14152

↑のIssueを参考に以下のように実装したところ、メールを送信することができた。

```php
        TransportFactory::drop('default');
        TransportFactory::setConfig(Configure::consume('EmailTransport'));

        $mailer = new Mailer();
        $mailer->setTransport('default')
            ->setFrom(['me@example.com' => 'My Site'])
            ->setTo('you@example.com')
            ->setSubject('About')
            ->deliver('My message');
```
Vulkan TutorialのRust版をやってみた 〜グラフィックパイプライン編〜

Vulkanの入門をRustでやっていきます。[目次はこちら](https://qiita.com/kbone/items/1f8bc5d571dcc3ddaac3)。今回までの実装をした[GitHubはこちら](https://github.com/KBone12/vulkan-tutorial/tree/graphics_pipeline)。

# Vulkanのグラフィックパイプライン
VulkanのグラフィックパイプラインはOpenGL等と似たような感じで、図のようになっています。
![](https://vulkan-tutorial.com/images/vulkan_simplified_pipeline.svg)
(画像は[https://vulkan-tutorial.com/Drawing_a_triangle/Graphics_pipeline_basics/Introduction](https://vulkan-tutorial.com/Drawing_a_triangle/Graphics_pipeline_basics/Introduction)より引用)

## シェーダの作成と読み込み
Vulkanoの場合、[vulkano-shaders](https://crates.io/crates/vulkano-shaders)を利用してコンパイル時にGLSLをSPIR-Vに変換することができるので、今回はこれを使います。
まず、GLSLでvertex shaderとfragment shaderを作成します。このとき、

```
#extension GL_ARB_separate_shader_objects : enable
```

をつけてください。次に`main.rs`で

```rust
mod vertex_shader {
    vulkano_shaders::shader! {
        ty: "vertex",
        path: "path/to/vertex_shader"
    }
}
mod fragment_shader {
    vulkano_shaders::shader! {
            ty: "fragment",
            path: "path/to/fragment_shader"
        }
    }
vertex_shader::Shader::load(device.clone()).expect("Failed to load the vertex shader");
fragment_shader::Shader::load(device.clone()).expect("Failed to load the fragment shader");
```

とします。これで最低限のシェーダが読み込めました。

## render passの作成
[参考元](https://vulkan-tutorial.com/)と順番が異なりますが、Vulkanoではパイプラインを作るのにrender passが必要になるので先にこれを作ります。またVulkanoの場合は通常、`single_pass_renderpass!`マクロで各アタッチメントやパスを書いていくので、C/C++とは大分変わります。

```rust
let render_pass = single_pass_renderpass!(device.clone(),
    attachments: { /* 各アタッチメント */ },
    pass: { /* パス */ }
).unwrap()
```

### 各アタッチメントの設定
各アタッチメントは上の`attachments: `に書いていきます。今回は`colorAttachment`を設定します。

```rust
attachments: {
    color: {
        load: Clear,
        store: Store,
        format: swapchain.format(),
        samples: 1,
    }
},
```

ここで、`load`及び`store`はVulkanの`loadOp`及び`storeOp`に相当するもので、`samples`は今回はマルチサンプリングをしていないので`1`となっています。

### パスの設定
上で設定したアタッチメントを用いてパスを設定します。

```rust
pass: {
    color: [color],
    depth_stencil: {}
}
```

## fixed functionの設定
fixed functionとはViewportやラスタライザ等の総称のようです。Vulkanの場合、fixed functionに分類されるものはパイプライン毎に固定で基本は変更できないようです。ただし、Viewport等は設定時に動的に変換することも出来ます。
Vulkanoの場合は`vulkano::pipeline::GraphicsPipeline`にいわゆるビルダーパターンで作っていきます。

### vertex input及びvertex shaderの設定
今回の[参考元](https://vulkan-tutorial.com/)ではvertex shader自身がデータを持っているので外部から頂点データを入力する必要がありません。Vulkanoの場合、こういうときは`vulkano::pipeline::vertex::BufferlessDefinition`を使います。なお、頂点データを入力する際には`impl_vertex!`を使います。

```rust
.vertex_input(BufferlessDefinition)
.vertex_shader(vertex_shader.main_entry_point(), ())
```

### viewportの設定
上記のように動的なviewportにすることも可能ですがここでは固定サイズにし、scissorは全体を写すようにします。

```rust
let viewport = Viewport {
    origin: [0.0, 0.0],
    dimensions: [
        swapchain.dimensions()[0] as _,
        swapchain.dimensions()[1] as _
    ],
    depth_range: 0.0..1.0,
};
builder.viewports(vec![viewport]);
```

### `Subpass`の設定
上で作成したrender passを`Subpass`に変換して使います。

```rust
.render_pass(Subpass::from(render_pass, 0).unwrap())
```

# まとめと感想
今回も特に実行結果は変化せずシェーダの読み込みやパイプラインの作成で終わりましたが、次回はいよいよ描画できるはずです。
[Visual Studio Code] [MacOS] .nvmrcで指定したバージョンに自動で切り替えてプロジェクトをスタートする

複数の Node.js プロジェクトに参加していると、利用すべき Node のバージョンがプロジェクト毎に異なる場合があって、毎回手動で切り替えるのは大変面倒なので自動化します。

## 動作確認環境

- MacOS
- Visual Studio Code

にて動作を確認しております。Mac かつ VSCode で開発をしていて、ビルドなども VSCode 上のターミナルで行なっている方は参考になると思います。

## ロードマップ
1. nvmのインストール
2. Visual Studio Code のターミナルをzshに設定する
3. .zshrc を作成、または編集する
4. 自動バージョン切り替えを実行したいプロジェクトで .nvmrc を作成する

## 1.nvmのインストール

日本語の参考記事がたくさんありますのでそちらを参照してください。

`nvm use <バージョン>`

コマンドでいくつかの node バージョンを切り替えられるようになればOKです。

## 2.Visual Studio Code のターミナルをzshに設定する

まずは現在の VSCode のターミナルのシェルが何か、確認します。
[![Image from Gyazo](https://i.gyazo.com/8a2105d7a6d90b338cc2e3c9b5f26729.png)](https://gyazo.com/8a2105d7a6d90b338cc2e3c9b5f26729)

青枠部分がzshでない場合は設定で変更します。Mac 自体が2019年に、デフォルトの処理を bash から zsh に切り替えているので、基本的には VSCode もそれに沿う形で問題ないはずです。既に bash でいろいろ設定やってるよという方は zsh に切り替えることの影響を考慮する必要があります。
[![Image from Gyazo](https://i.gyazo.com/42bee9a56b71030af1ef54118a2e42e6.png)](https://gyazo.com/42bee9a56b71030af1ef54118a2e42e6)

`⌘ + ,`で設定パネルを開き、
`Terminal › Integrated › Automation Shell: Osx`
の項目で Edit in settings.jsをクリックします。

[![Image from Gyazo](https://i.gyazo.com/40dcc979b9ac40bcff85844bfb63ab83.png)](https://gyazo.com/40dcc979b9ac40bcff85844bfb63ab83)

`"terminal.integrated.shell.osx": "/bin/zsh"`
terminal.integrated.shell.osx の値を上記のようにします。基本的にこちらの値で問題ないと思いますが、環境によって、zshがインストールされていない、場所が違うなどあるかもしれませんのでご確認ください。

編集したら改めて VSCode 上のターミナルを確認し、zsh となっていればOKです。

### .zshrc を作成、または編集する

基本これで良いはず。

```console
$ vim .zshrc
```

```sh
source ~/.nvm/nvm.sh
# place this after nvm initialization!
autoload -U add-zsh-hook
load-nvmrc() {
  if [[ -f .nvmrc && -r .nvmrc ]]; then
    nvm use
  elif [[ $(nvm version) != $(nvm version default)  ]]; then
    echo "Reverting to nvm default version"
    nvm use default
  fi
}
add-zsh-hook chpwd load-nvmrc
load-nvmrc
```

既に .zshrc ファイルが存在している場合は既存の設定内容に影響がないか注意が必要です。また、１行目の nvm のパスも環境によっては違うかもしれません。

### 4.自動バージョン切り替えを実行したいプロジェクトで .nvmrc を作成する

ここまでくればただただバージョン番号が書かれた.nvmrcファイルがプロジェクトディレクトリの直下に存在していれば、プロジェクトを開いた際にnvmによるバージョン切り替えを行なってくれます。バージョン番号指定ではなく`lts/*`のように安定バージョンの最新というような書き方もできます。（が、該当バージョンをnvmでインストール済みでないと動かないと思います。私は常にバージョン番号で指定しているので未確認です。）

.nvmrc はコマンドラインでサクッと作成してしまいましょう。

```console
$ echo "8.13.0" > .nvmrc #番号指定
$ echo "lts/*" > .nvmrc #最新バージョン
```

以上で設定完了です。VSCode で該当プロジェクトを開き、VSCode 上のターミナルを立ち上げれば .nvmrc で指定したバージョンに切り替えたことを示すメッセージがターミナルで確認できるはずです。

また、複数でプロジェクトを進める際に node のバージョンをバシッと統一するときもこの形がスマートだと思います。

## 参考リンク

[https://qiita.com/ysd_marrrr/items/e58df8dfd509b25ff9c9](https://qiita.com/ysd_marrrr/items/e58df8dfd509b25ff9c9)
[https://medium.com/fbdevclagos/updating-visual-studio-code-default-terminal-shell-from-bash-to-zsh-711c40d6f8dc](https://medium.com/fbdevclagos/updating-visual-studio-code-default-terminal-shell-from-bash-to-zsh-711c40d6f8dc)
[https://medium.com/@kinduff/automatic-version-switch-for-nvm-ff9e00ae67f3](https://medium.com/@kinduff/automatic-version-switch-for-nvm-ff9e00ae67f3)
GitHubでソース管理をする流れ

環境
git version 2.25.1.windows.1


##手順
**1.リモートリポジトリをローカルに落とす**

```
$ git clone git@github.com:【ユーザー名】/【リポジトリ名】.git
```
落としたリポジトリの確認

```
$ git branch
* master
````
作成された段階のリポジトリには「master」ブランチのみが存在します。

**2.作業ブランチを作成する**
修正をする場合、masterをコピーしたブランチを触る。

```
$ git branch copy_branch
```
ブランチ一覧を確認すると、コピーしたブランチができている。

```
$ git branch
* master
copy_branch
```

**3.ブランチの移動**
アスタリスクがついているのが現在選択中のブランチ。
作業ブランチに移動する。

```
$ git checkout copy_branch
Switched to branch 'copy_branch'
```
ブランチ一覧を確認すると、copy_branchにアスタリスクがついているのが確認できる。

```
$ git branch
master
* copy_branch    
```
**4.ファイルを作成する**
今回は単なるテキストファイルを作成します。

```
$ vi a.txt  
```

**5.作成したファイルをバージョン管理の対象に追加する**

コミットする前には必ずaddしなければなりません。
addすることでGitのコミット対象になります。

```
$ git add a.txt  
```

**6.コミットする内容を確認する**

```
$ git status
On branch copy_branch
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file:   a.txt
```
a.txtが追加されていることが確認できます。

**7.コミットする**

きちんとaddされている状態でコミットします。

```
$ git commit -m "test commit"
[xxx e6b74e6] test commit
1 files changed, 1 insertion(+)
create mode 100644 a.txt
```
コミットコメントはダブルクオートで囲んで記入します。

コミットが完了すると、statusは以下のようになります。

```
$ git status
On branch copy_branch
nothing to commit, working tree clean
```

**8.GitHubへプッシュする**
ローカル環境でコミットが完了したので、次にGitHubへ反映させます。

```
$ git push origin copy_branch
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 4 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 300 bytes | 150.00 KiB/s, done.
remote:
remote: Create a pull request for 'test' on GitHub by visiting:
remote:      https://github.com/user/test/pull/new/test
remote:
Total 3 (delta 0), reused 0 (delta 0)
To https://github.com/user/test.git
   e6b74e6..dd1235a  copy_branch -> copy_branch
```

**9.プルリクを送る**
先ほどpushしたときに出た`https://github.com/user/test/pull/new/test` へアクセスすると、プルリクを送れる画面に行けるのでコメント残してぽちります。

**10.ローカルブランチを削除する**

作業ブランチを違うブランチに切り替えてから削除を行います。

```
$ git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.

$ git branch --d copy_branch
Deleted branch copy_branch (was dd1235a).
```
作業ブランチを変えないまま削除しようとすると、下記のようなエラーになります。

```
$ git branch --d copy_branch
error: Cannot delete branch 'copy_branch' checked out at 'C:/Users/test'
```

**11.リモートリポジトリの最新を取得する**
常に最新のmasterを取得し、それをコピーしたbranchで作業を行います。

```
$ git pull origin master
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (1/1), 621 bytes | 20.00 KiB/s, done.
From https://github.com/user/test
 * branch            master     -> FETCH_HEAD
   f8999d2..8d6e7ad  master     -> origin/master
Updating f8999d2..8d6e7ad
Fast-forward
 a.txt | 1 +
 b.txt | 0
 2 files changed, 1 insertion(+)
 create mode 100644 b.txt
```
Dockerのマルチステージビルドについて

## マルチステージビルドとは？[1]

[公式ドキュメント](https://docs.docker.com/develop/develop-images/multistage-build/)

> With multi-stage builds, you use multiple `FROM` statements in your Dockerfile. Each `FROM` instruction can use a different base, and each of them begins a new stage of the build. You can selectively copy artifacts from one stage to another, leaving behind everything you don’t want in the final image. 

簡単にいうと，ひとつの Dockerfile で複数のビルドができ，各ビルドの段階で必要な部分だけコピーして（残りは破棄される），最終的に使用したいベースイメージにペーストできる機能です。
## 参考文献
[1]. [Docker に Composer をインストールするベストプラクティス（と解説）](https://qiita.com/kotarella1110/items/634f6fafeb33ae0f51dc)
魔法JS☆あれい 第9話「someなの、everyが許さない」

登場人物

丹生（にゅう）あれい
魔法少女「魔法（マジカル）JS（女子小学生）☆あれい」として活動中。

イテレー太
正体不明の魔法生物。

第1部「ミューテーター・メソッド編」
* [第1話「popでpushした、ような……」](https://qiita.com/8amjp/items/e44e707ccc8c95b4a40d)
* [第2話「shiftはとってもunshiftって」](https://qiita.com/8amjp/items/3fc1b2defd28ba1c2df3)
* [第3話「もうsortもreverseも怖くない」](https://qiita.com/8amjp/items/86f5294981fbebd3fe2d)
* [第4話「fillも、spliceも、copyWithinもあるんだよ」](https://qiita.com/8amjp/items/0741e35b70ea32711265)

第2部「アクセサ・メソッド編」
* [第5話「joinなんて、concatなわけない」](https://qiita.com/8amjp/items/229c41ad2146728abd89)
* [第6話「indexOfなの絶対lastIndexOf」](https://qiita.com/8amjp/items/f7e421722e419c1c0a7d)
* [第7話「includesのsliceと向き合えますか？」](https://qiita.com/8amjp/items/007ac192399225db3843)

第3部「イテレーション・メソッド編」
* [第8話「filterって、ほんとfindとfindIndex」](https://qiita.com/8amjp/items/f7014b09c5c2a6440a74)

## some()

イテレー太「さあ、戦いはまだまだ続くよ！」
あれい「ちょっと休憩させろよ駄犬」
イ「召喚したデータは[前回](https://qiita.com/8amjp/items/f7014b09c5c2a6440a74)を参照してね！　そして、今回の敵の弱点は、『'JavaScript'というタグを含む記事一覧』だよ！　さあ、条件に合致するデータを`return`して敵を倒してよ！」
あ「面倒くせえなあ……」

```js
return items.filter(item => item.tags.some(tag => tag.name === 'JavaScript'))
```

あ「これでいいのか」
イ「あれい、また解説をお願い！」
あ「ああん？　面倒くせえなあ……だから、それぞれの記事アイテムの`tags`プロパティを`some()` メソッドで検索して、`name`が'JavaScript'のタグが1個でもあれば`true`を返してだな、それを`filter()`メソッドで抽出してるんだよ」
イ「さすがはあれい！　口は悪いけど仕事は早いね！」
あ「やかましいわ」

### 解説

> `some()` メソッドは、配列の少なくとも 1 つの要素が、渡された関数によって実施されるテストに通るかどうかをテストします。

（[MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/some)より）

配列のすべての要素に対してテスト関数を実行し、条件に合致する要素が1つでもあれば`true`を、なければ`false`を返します。
テスト関数に渡される引数は`filter()` メソッドと同じです。

## every()

イ「問題。『本文（`body`）中に'JavaScript'という文字列を含む記事は、必ず'JavaScript'というタグが付けられている』。○か×か？」
あ「なんだよ急に。ウルトラクイズか」
イ「なんで女子小学生がウルトラクイズを知ってるのかは置いといて、その答えが次の敵の弱点だよ！　さあ、答えを調査して、敵を倒してよ！」
あ「面倒くせえ事この上ねえな……」
イ「頑張れ！　あれい！」

```js
return items.filter(item  => /JavaScript/.test(item.body))
.every(item => item.tags.some(tag => tag.name === 'JavaScript'));
```

あ「これでいいのかよ」
イ「あれい、また解説をお願い！」
あ「ああん？　面倒くせえなあ……だから、まずは本文中に'JavaScript'という文字列を含む記事だけを抽出してだな、次にその記事が'JavaScript'タグを含むかを`some()` メソッドで判定し、最後にすべてが`true`を返したかを`every()` メソッドで判定してるんだよ」
イ「さすがはあれい！　女子小学生らしさは皆無だけど仕事は早いね！」
あ「黙れ」

### 解説

> `every()` メソッドは、与えられた関数によって実行されるテストに、配列のすべての要素が通るかどうかをテストします。

（[MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/every)より）

`every()` メソッドは、配列のすべての要素に対してテスト関数を実行し、すべての要素が条件に合致した場合のみ`true`を、そうでなければ`false`を返します。
テスト関数に渡される引数は`filter()` メソッドと同じです。

## 次回予告

誰も、コールバック関数から逃れられない。
誰も、コールバック関数からthisを参照できない。

[第10話 もうmapにもforEachにも頼らない](https://qiita.com/8amjp/items/25859c085119cdceed89)