OmniAICreator/Qiita-1.07M huggingface dataset:
【Node.js Express】Bcryptを用いて平文をハッシュ化する。

※当方駆け出しエンジニアのため、間違っていることも多々あると思いますので、ご了承ください。また、間違いに気付いた方はご一報いただけると幸いです。


#bcryptを用いたハッシュ化
bcrypt というパッケージを用いて、Node.jsでパスワードをハッシュ化し保存します。
例としてusersControllerでサインアップ時にパスワードをハッシュ化します。

bcryptをインストールします。

```
npm install bcrypt
```

ハッシュ化を実施するコントローラーでロードします。

以下のようなusresControllerがあるとします。サインアップ時に使用するコントローラーです。
ORMにsequelizeを用いています。

sequelizeについては、こちらをご覧ください。
[【Express】ExpressにSequelizeを導入しORMでデーターベースを操作する。(SQLite3)]
(https://qiita.com/sho_U/items/9df724192fd48e760f79)

```usersController.js

function signup(req, res) {
  db.sequelize.sync()
    .then(() => db.User.create({
      name: req.body.name,
      email: req.body.email,
      pass: req.body.password
    })).then(usr => {
      res.redirect('/home');
    })
}
```

bcryptをロードし、signup関数のpromiseチェーンに、ハッシュ化関数をかまします。

```usersController.js

const bcrypt = require('bcrypt');  //bcryptをロード

function signup(req, res) {
  db.sequelize.sync()
    .then(() => bcrypt.hash(req.body.password, 10)) 
    //ハッシュ化関数をかまします。第二引数はハッシュ化の強度となります。
    .then(hashedPassword => db.User.create({ 
    //生成されたハッシュを引数hashedPasswordで受け取ります。
      name: req.body.name,
      email: req.body.email,
      pass: hashedPassword //ハッシュ化されたものを保存します。
    })).then(usr => {
      res.redirect('/home');
    })
}
```

##ログイン時にハッシュ化したパスワードと入力したパスワードを比較する。



```js
function login(req, res) {
  db.User.findOne({ where: { email: req.body.email } })
    //入力されたemailユーザーを取得。
    .then((user) => {
      if (!user) {
        res.redirect("login");
      }
      return user; //ユーザーを非同期で返す。
    })
    .then((user) => {
      let resultMatch = bcrypt.compareSync(req.body.password, user.pass);
      //bcrypt.compareSync関数で(入力値, ハッシュ化されて保存している値)を比較。
      //一致したらtrueを返す。
      if (resultMatch) {
        res.redirect("/home");
      }
      res.redirect("login");
    })
}
```
bitbucketのprivateリポジトリからgo modする

# 背景
* bitbucketで管理しているprivateなリポジトリから他のgo言語のモジュールを使いたい
* ソースコードは公開したくない

# 前提

* bitbucketにアクセスできるSSH鍵を登録している
 * 補足：Personal settings > SSH 鍵 
* この記事はgo version go1.14.2 darwin/amd64　で書いています
 * これ以前のバージョンであると他の設定が必要かもしれません 

# ローカル設定

SSH鍵を登録していればgitコマンドを使用してcloneやpushなどSSHプロトコルで行うことができるがgo get はhttpsプロトコルを使ってアクセスしている。

なのでgit（bitbuket）からSSHプロトコルを使って取得するために以下の設定を行う

```
git config --global url."git@bitbucket.org:".insteadOf "https://bitbucket.org/"
```

以下が追加されていること

```
$ cat ~/.gitconfig 
[url "git@bitbucket.org:"]
	insteadOf = https://bitbucket.org/
```

go側も以下の設定をしておく

```
export GOPROXY=direct
export GOSUMDB=off
```

### Tips
```
	server response: Access denied. You must have write or admin access.
```
このエラーが出たら上記の設定が足りていない可能性がある


# Go Get

モジュールを取得

```
go get -v bitbucket.org/[WORKSPACES]/[repository]
```

## おまけ
別ブランチから取得したいなら

```
go get -v bitbucket.org/[WORKSPACES]/[repository]@[branch]
```
Rustのジェネリクスパラメーターに定数を渡せるようになる(const generics)

この記事は[Rust 2 Advent Calendar 2020](https://qiita.com/advent-calendar/2020/rust2) 22日目の記事です。

## const genericsとは
const genericsとは下記のようなジェネリクスパラメーターに定数を渡せる機能です。

```rust
struct Foo<const N: usize> {}
let v = Foo::<5> {};
```
記事を書いている2020/12/22時点ではstableに入っていませんが、[こちらのissue](https://github.com/rust-lang/rust/pull/79135)によるとRust 1.50でstableに入れることを予定しているそうです。
C++でテンプレートメタプログラミングをしていた方々には慣れ親しんだ機能だと思います。

### const genericsを利用する方法
const genericsを利用するにはnightlyチャンネルで`#![feature(min_const_generics)]`を書く必要があります


## 使用可能な箇所
基本的にジェネリクスを使用できる場所でならどこでも使用できます。

```rust
struct A<const N: i32>;
trait B<const N: i32> {}
fn function<const N: i32>() {}
enum E<const N: i32> {}
```

---
特定のパラメーターのものに対してtraitを実装することもできます。

```rust
struct A<const N: i32>;

trait Hoge {
    fn hoge();
}

// Nが0のときのみHogeを実装
impl Hoge for A<0> {
    fn hoge() {}
}

fn main() {
    A::<0>::hoge(); // OK
    A::<1>::hoge(); // コンパイルエラー
}
```

---
配列の長さに関わらず特定のtraitを実装することもできます。

```rust
trait Hoge {
    fn hoge(&self) { }
}

impl<T, const N: usize> Hoge for [T; N] {
    fn hoge(&self) { }
}
```

## パラメーターの制限
定数の型は整数型もしくは`bool`, `char`だけが許可されます。
具体的には`u8`, `u16`, `u32`, `u64`, `u128`, `usize`, `i8`, `i16`, `i32`, `i64`, `i128`, `isize`, `char`, `bool`だけが許可されます。

```rust
struct A<const N: f32>;
```
のように`f32`などを使用しようとするとコンパイルエラーが発生します。

```bash
error: `f32` is forbidden as the type of a const generic parameter
 --> src/lib.rs:3:19
  |
3 | struct A<const N: f32>;
  |                   ^^^
  |
  = note: the only supported types are integers, `bool` and `char`
  = help: more complex types are supported with `#[feature(const_generics)]`
```

---
計算結果や`const fn`の戻り値を渡すことができますが、{}で囲んでやる必要があります。

```rust
struct A<const N: i32>;

const fn function() -> i32 {
    42
}

fn main() {
    let _ = A::<{1 + 2}>{};      // OK
    let _ = A::<1 + 2>{};        // コンパイルエラー
    let _ = A::<{function()}>{}; // OK
    let _ = A::<function()>{};   // コンパイルエラー
}
```

---
下記のように定数の型をジェネリクスで指定することはできません。

```rust
struct A<T, const N: T>;
```
近い将来に実装される可能性も低いそうです。

---
順番にも制限があり、定数は型パラメーターよりも後に来る必要があります。

```rust
struct A<T, const N: i32>; // 型が先なのでOK
struct B<const N: i32, T>; // 型が後なのでコンパイルエラー
```

## あとがき
const genericsが使えるようになればジェネリックパラメーターに定数を渡せるようになります。
現状の予定では制限が多いですが便利な機能なのでstable入りが非常に楽しみです。

自分で使うことが少なくてもいろんなcrateがこの機能によって使いやすくなったり便利になったりするんじゃないかと思っています。

今回書いた内容は冒頭にもリンクを張った[こちらのissue](https://github.com/rust-lang/rust/pull/79135)を参考にしています。
興味がある方はissueの方も覗いてみてください。
【FileMaker】揺れを止めろ！

タイトル通りです。
まずは、動きを見てください。

# 動き
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">揺れ揺れ〜んなサンプル。<a href="https://twitter.com/hashtag/FileMaker?src=hash&amp;ref_src=twsrc%5Etfw">#FileMaker</a> <a href="https://twitter.com/hashtag/filemakergo?src=hash&amp;ref_src=twsrc%5Etfw">#filemakergo</a> <a href="https://t.co/2W0V5m0o83">pic.twitter.com/2W0V5m0o83</a></p>&mdash; Guppy Web Service (@GuppyWebService) <a href="https://twitter.com/GuppyWebService/status/1341359856985358339?ref_src=twsrc%5Etfw">December 22, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

さぁ、これはなんで揺れてるんでしょうか。

# 揺れの原因
答えは、ここです。
![スクリーンショット 2020-12-22 21.13.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/2105351e-27ee-65be-ad92-20dedcc3a945.png)
揺れるレイアウトの方は、横のサイズが1pt長いんです。

# 画面サイズを確認する方法
PCの主なサイズやiPhone,iPadの画面サイズのガイドは、ここで確認できます。
![スクリーンショット 2020-12-22 21.19.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/7d7eaa3a-2524-4d9d-6198-c7ba883d7ce3.png)
iPhoneのサイズ違いやiPad miniなどのサイズガイドはここにはありませんが、カスタムサイズとして調整できますので、このガイドを活用して、「揺れない画面」を目指しましょう。

# すごい表
驚異的な画面サイズの早見表を出してくれているすごい人も世の中にはいらっしゃるので、ブックマークしておくといいですよ。（もちろん私もブックマーク！）
[iPhone/iPad/Apple Watch解像度(画面サイズ)早見表](https://qiita.com/tomohisaota/items/f8857d01f328e34fb551)
【JavaScript】配列/オブジェクトの色々な値渡し

## 書くきっかけ
値渡しのやり方が色々あったのでまとめておこうと思いました。
配列やオブジェクトが入れ子になっていると書き方も変わります。（ここで結構ハマりました）

## 基本の参照渡し
配列やオブジェクトのコピーは基本的に参照渡しとなります。

```JavaScript
const xx = [0,1,2]
const yy = xx
yy[0] = 9    // xx[0]を変えているも同じ。
console.log(xx)    // [9,1,2]

const aa = { x:0, y:0 }
const bb = aa
bb.x = 1    // aa.xを変えているも同じ。
console.log(aa)    // { x:1, y:0 }
```

## 値渡し
単純に値だけのコピーをしたい時があります。
やり方を以下にまとめます。

### 配列の値コピー

```
const xx = [0,1,2]

const yy1 = xx.slice()      //値コピー
const yy2 = Array.from(xx)  //値コピー
const yy3 = xx.map(v => v)  //値コピー
const yy4 = xx.concat()     //値コピー
const yy5 = [...xx]         //値コピー
```

### 配列の値コピー（入れ子）

```
const xxNested = [{ x:0, y:0 }]

const yyNested = JSON.parse(JSON.stringify(xxNested))  //値コピー
```

### オブジェクトの値コピー

```
const aa = { x:0, y:0 }

const bb1 = Object.assign({}, aa)  //値コピー
const bb2 = {...aa}                //値コピー
```

### オブジェクトの値コピー（入れ子）

```
const aaNested = { x:[0,1,2] }

const bbNested = JSON.parse(JSON.stringify(aaNested))  //値コピー
```

こちらからは以上です。

## 参考
* [オブジェクト、配列のコピー](https://qiita.com/a12345/items/91507fb5752a6d7d866a)
* [【Javascript】オブジェクト配列のコピーに関する注意点](https://zenet-tech.hatenablog.com/entry/2019/04/22/173500)
macでjupyter-notebookのブラウザをgoogle chromeに設定する方法

#jupyter notebookの[]や候補予測がmacのsafariでは使いにくいのでchromeに変更

括弧などがsafariでjupyter notebookを開くと使いにくいのでchromeを既定ブラウザにしたいと思いました。
ただ、macだと少し設定が面倒らしいので今回は個人メモとして記述します。

<B>まずは、find.jupyterで.jupyterのファイルを検索

```python
.jupyter/jupyter_notebook_config.py
```
その中から上のファイルをコピー

```python

open .jupyter/jupyter_notebook_config.py
```
でファイルを開く。

その中から

```python
#c.NotebookApp.browser = ''
```
を探す。
私のターミナルだと99行にありました。

この#を外して

```python
NotebookApp.browser = '/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome %s'
```

としてjupyterを開くとchromeで開けるようになります。
Windowsドメイン信頼関係

フォレスト信頼：フォレスト全体で信頼し合うように。
便利な反面、何でもアクセスできてしまう恐れがあります。

外部信頼：フォレストの一部ドメインとピンポイントで信頼関係を結ぶことです。
必要最低限にしたい場合、これがよいと思われます。
FreeBSD 起動時 解像度 おかしい (MEMO)

# FreeBSD の起動時の画面モードがどうやらおかしそうだ

BSD デーモンかわいいですよね．球体に角の生えてる置物があったらほしいです．

インストール作業が一通り終わって再起動．
しかし再起動後の画面には先程までそこにあった解像度がありませんでした．

## tl;dr
(私の環境では) **/boot/loader.conf** に下記追加:

```
exec="mode 2"
```

---

## なんか突然めちゃくちゃ文字でかいですね

インストール作業中は引き締まったドットフォントの小さすぎるくらいの文字で表示していた FreeBSD くん．インストール作業が終わって再起動した瞬間に画面いっぱいを使って表示してくれたのは 80x25 文字の画面でした．更にそのまま続行していると vt のせいで画面がぐちゃぐちゃになります．

## とりあえず

起動時のメニューで 3. **Esc**ape to loader prompt を選択します．次のようにプロンプトが出ます．このプロンプトではカーネルを読み込む前にいろいろできるようです．

```
Exiting menu!


Type '?' for a list of commands, 'help' for more detailed help.
OK _
```

とりあえず <kbd>?</kbd> してそれっぽいものを探します．今回のそれっぽいものは  `mode` です．

## mode &#x2014; change or display EFI text modes

`mode` すると利用できるテキストの行と桁の一覧が出ます．一覧に表示される要素は環境によるんじゃないでしょうか．こんな感じに:

```
OK mode
mode 0: 80 columns, 25 rows
mode 2: 240 columns, 56 rows
mode 3: 100 columns, 31 rows
mode 4: 128 columns, 40 rows
mode 5: 160 columns, 53 rows
Select a mode with the command "mode <number>"
OK _
```

それっぽいのを選んで `mode `*`<number>`* します．こんな感じに:

```
OK mode 2
```

いい感じに表示されましたか？

## 起動

そのプロンプトで `boot` するとカーネルが読み込まれて起動します．多分．ね？

```
OK boot
```

## 毎回やるのは面倒なんじゃい

**/boot/loader.conf** に設定を書き書きすれば良いようです．`exec="hogehoge"` と書いてやるとさっきのプロンプトで `hogehoge` を実行することと同じなようです．今回実行したコマンド `mode `*`<number>`* を自動でしてくれるようにお願いしましょう．

```
# ed /boot/loader.conf
0
a
exec="mode 2"
.
w
14
q
```

そして再起動します．

```
# reboot
```

## おわり
おわりです．
FX3UでFX3U-USB-BD経由の通信ができなくなったときの処置

#１．はじめに

三菱電機のPLC「MELSEC FX3Uシリーズ CPU」に、あとからRS-485通信ユニットを拡張したときに、元々設置していたFX3U-USB-BD経由での通信ができずハマってしまいました。
ここではその対策について説明します。

#２．背景

##（１）元々の状況
 - [MELSEC FX3Uシリーズ](https://www.mitsubishielectric.co.jp/fa/products/faspec/point.do?kisyu=/plc_fx&formNm=640059145&category=ex&id=spec)には、CPU本体にUSB接続端子が無く、GXWorksからCPUへの通信はRS-485での通信だけになります
 - そのため、タッチパネル（GOT 1000）をRS-485に接続すると、GXWorksからCPUへの通信は、タッチパネル経由だけが可能になります
 - タッチパネル経由での通信速度は速くないので、[FX3U-USB-BD](https://www.mitsubishielectric.co.jp/fa/products/faspec/point.do?kisyu=/plc_fx&formNm=640058321&category=ex&id=spec)を拡張して、USB経由で接続できるようにしていました

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145581/4ab6d9f5-e721-4134-0ee7-c1d328d0128b.png)
　　　　　↑　CPU本体のRS-485端子（タッチパネルへ接続）
　　↑　FX3U-USB-BDのUSB端子（パソコンのGXWorksへ接続）

##（２）RS-485通信ユニットを拡張

 1. インバータ（[FREQROL D-700](https://www.mitsubishielectric.co.jp/fa/products/drv/inv/pmerit/fr_d/index.html)）を追加して、PLCからRS-485経由で速度可変できる状態にしたかった
 1. RS-485通信ユニット（[FX3U-485ADP-MB](https://www.mitsubishielectric.co.jp/fa/products/faspec/point.do?kisyu=/plc_fx&formNm=FX3U-485ADP-MB)）を追加
 1. GX Works2のPCパラメータ設定を変更
    - FX3U-485ADP-MBの設定を`1ch`側に追加
    - パラメータをPLCに書き込み
 1. **書き込んだ直後から通信ができなくなった！**

この時点のPCパラメータ設定状況
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145581/be197737-cd56-8a29-7794-90709349f695.png)

※どうしようもないので、CPU本体のRS-485端子から通信･･･（なのでタッチパネルが動かない

#３．処置

##（１）原因

FX3U-485ADP-MBを`1ch`に設定したことが原因でした。
実際は下記の様に割り当たっています。

|チャンネル番号|接続機器||
|:--|:--|:--|
|1ch|FX3U-USB-BD|これにもチャネルが割り当てられていた。しかも1ch！！|
|2ch|FX3U-485ADP-MB||

したがって、PCパラメータ設定・「PCシステム設定２」で、FX3U-485ADP-MBを1ch側で使う設定をしてしまうと、実は1ch側に割り当たっているFX3U-USB-BDの通信設定が上書きされてしまい、FX3U-USB-BD経由でのGXWorksとの通信ができなくなってしまいます。

さらに困ったことに、
**1chの設定を入れてしまったあとに気づいて「PCシステム設定２」の「ch1」のチェックを外してしまっても、シーケンサの中には設定が残って**しまい、GXWorkのPCパラメータ画面からは設定が直せなくなります。
（ひどい･･･）

##（２）処置

 1. GXWorksをCPU本体のRS-485端子から通信できるように接続
 2. モニタモードに切り替え
 1. `D8120`（通信フォーマット設定）の値を、現在値変更ウィンドウから強制的に`"0"`にする
  - これで、先ほどの「GXWorkのPCパラメータ画面から設定が直せない」が回避出来ます
  - D8120はバッテリーバックアップ対象なので、バッテリーを抜かない限り保持されたままになります･･･
 1. 下記の画像に従って、設定をし直す
 2. PLCにパラメータを書き込む 

**1ch側は空欄のままにしておく**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145581/2336ed1f-60e5-7515-8174-227e11c0851b.png)

**2ch側にFX3U-485ADP-MBの設定を入れる**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145581/56935869-ac6b-f417-dc0d-c1eeca0c02cc.png)

#３．まとめ

この復帰の手順は、おそらくマニュアルからは読み取れないです･･･
>FX3S・FX3G・FX3GC・FX3U・FX3UCシリーズ
プログラミングマニュアル［基本・応用命令解説編］
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145581/f24fe22c-c066-3ceb-c65e-a2cba10a2893.png)

なので、サポートセンターの方に相談して助けて頂きました。
（感謝
便利なvimコマンド

vimを学習し始めました。
コマンドを少しずつアウトプットしていきます。
間違いなどありましたら、お手数ですが、ご指摘頂けましたら幸いです。

【移動】

```
h・・・左へ移動
l・・・右へ移動
k・・・上へ移動
j・・・下へ移動

W・・・次の単語へ移動
B・・・次の単語の末尾へ移動
E・・・前の単語へ移動

^・・・現在の行の先頭位置へ移動
$・・・現在の行の末尾へ移動
-・・・前行の先頭へ移動
G・・・最終行の先頭へ移動
gg・・・開始行に移動
:数字 ・・・指定行に移動
```

【削除】

```
dw・・・1単語削除
dd・・・1行削除

diw・・・区切り文字(spaceや<等)を含めず単語をカット
daw・・・区切り文字(spaceや<等)を含めて単語をカット

di<・・・「<」 から 「>」 までの単語を 「<」 と 「>」 を含めずカット
da<・・・「<」 から 「>」 までの単語を 「<」 と 「>」 を含めてカット
di"・・・「"」 から 「"」 までの単語を 「"」 と 「"」 を含めずカット
da"・・・「"」 から 「"」 までの単語を 「"」 と 「"」 を含めてカット
di'・・・「'」 から 「'」 までの単語を 「'」 と 「'」 を含めずカット
da'・・・「'」 から 「'」 までの単語を 「'」 と 「'」 を含めてカット

x・・・カーソルの文字を１文字削除
X・・・カーソル直前の文字を指定数分削除
数字 + x ・・・カーソルから後ろに指定数分削除

ggdG ・・・全削除

<<<・・・インデントを一つ削除

```

【削除→入力】

```
c・・・行を削除して挿入モードへ
C・・・カーソル位置から行末まで削除して挿入モードへ
cw ・・・カーソル位置の単語を削除して挿入モードへ
s・・・一文字削除して挿入モードへ
S・・・行を削除して挿入モードへ
```

【入力】


```
a・・・カーソルの右から入力(a = Add)
A・・・行末から入力
i・・・カーソルの左から入力(i = Insert)
I・・・行頭から入力
o・・・現在の行の下に一行挿入し、その行頭から入力
O・・・現在の行の上に一行挿入し、その行頭から入力

```

【コピー】

```
yw・・・一単語コピー
yy・・・一行コピー
yiw・・・区切り文字(spaceや < 等)手前まで単語をコピー
yaw・・・区切り文字(spaceや < 等)を含めて単語をコピー
```


【ペースト】

```
P ・・・現カーソル位置の次の文字からペースト
```

【検索】

```
* ・・・現カーソル位置の単語を検索
/文字  ・・・「文字」 を検索
```



日々暴走中ですが、コツコツ継続して、vimを使いこなせるようになりたいです。
Flutterのget_itとRiverpodのProviderについて軽く紹介


お仕事でFlutterを触っており、
FlutterのDIでは[get_it](https://pub.dev/packages/get_it)パッケージが使用しています。
最近になって[riverpod](https://pub.dev/packages/riverpod)のProviderを使用して書く場面があって、それぞれの書き方を紹介します。

# `get_it`パッケージの場合

* https://pub.dev/packages/get_it

簡易な`get_it`パッケージで書いた例です。

まず、main.dartに該当する`main()`で初期化しています。
例えばネットワーク通信などを実装しているクラスを`ApiClient`として、`..registerLazySingleton<ApiClient>(() => ApiClient())`の`Get.instance`に登録します。

```Dart
GetIt getIt = GetIt.instance;

void main() {
    setupGetIt();
    runApp(App()):
}


void setupGetIt() {
    getIt
      ..registerLazySingleton<ApiClient>(() => ApiClient()) //ここ
}

class ApiClient {
    void method() {
    }
}

```

次に`ApiClient.method()`が呼ばれる側です。
`GetIt.instance`の`get<T>`でインスタンスを呼び出します。


```Dart

class App {
    void method() {
        getIt.get<App>().method();
    }
}
```

# riverPodのproviderを使った場合

* https://pub.dev/packages/riverpod

まずProviderを使用する場合、`ProviderScope`を設定します。

```Dart
void main() {
 runApp(ProviderScope(child: MyApp()));
}
```


次にProviderの宣言文は以下の通りです。

`final sampleProvider = Provider<T>((_) => T);`

下記では、[FirebaseAuth](https://firebase.flutter.dev/docs/auth/overview/)を使った例で書いています。

```Dart

///  Firebase Auth インスタンスの作成
final firebaseAuthProvider =
    Provider<FirebaseAuth>((_) => FirebaseAuth.instance);

/// firebaseAuthProviderを使ってProvider宣言
final authDataSourceProvider = Provider<AuthDataSource>(
    (ref) => AuthDataSourceImpl(ref.read(firebaseAuthProvider)));


abstract class AuthDataSource {
  Future<User> signIn();

  Future<void> signOut();
}


class AuthDataSourceImpl implements AuthDataSource {

  AuthDataSourceImpl(this._firebaseAuth);  
  final firebase.FirebaseAuth _firebaseAuth;

  @override
  Future<firebase.User> signIn() async {
      // 省略
  }

  @override
  Future<void> signOut() {
      // 省略
  }
  
}
```

`AuthDataSourceImpl`にある`signIn()`や`singOut()`に内部実装は割愛しましたが、
実際にはクレデンシャル(idToken,リフレッシュトークン)の設定や`FirebaseAuth.signInWithCredential()`などのログイン・ログアウトに関する詳細な実装が記述します。

上の例では、Providerから他のProviderにアクセスしています。

`final authDataSourceProvider = Provider<AuthDataSource>((ref) => AuthDataSourceImpl(ref.read(firebaseAuthProvider)));`

他のProviderにアクセスするには`ref.wathch`と`ref.read`が使われます。

`watch`の場合は、値が変更されたときに Provider が再生成されますが`read`の場合はされないです。


従来のProviderと比べてグローバル定数として変数宣言できます。
なので、従来のPrviderではツリー以外から参照しようとするとランタイム時にエラー(`ProviderNotFoundException`)が発生する場合がありますが、RiverPodのproviderでは起きないです。


個人的には`ProviderNotFoundException`が発生しないのはかなり魅力的に思えます。

ただ、riverpodが現在v0.12.0で破壊的変更が今後あるかもしれないとのことの。
ScalaのtoStringをフォーマットするアプリを作った

# 何を作ったか

ScalaでtoStringした結果をフォーマットするアプリです。

![スクリーンショット 2020-12-22 20.42.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/422592/bf4244d4-29d3-1dcd-a1c2-e4c461bf33ce.png)

https://immense-earth-74488.herokuapp.com/

Qiitaのアドベントカレンダーに投稿するために急いで作ったので、ラフな作りになっています。ちょっと複雑な文字列を入力欄に入れると、バグると思います。すいません😇

# 使い方

入力欄にtoStringした結果を貼り付けます。
入力し終えた場合は、入力欄の外側をクリックします。微妙なUIですね😇
(Vue.jsのv-on:changeで検出してます)

# 説明

バックエンドでは、 [scala-parser-combinators](https://github.com/scala/scala-parser-combinators)でパースして、パース結果をゴニョゴニョして、フォーマット後の文字列を生成しています。

フロントエンドは単一のhtmlファイル全てを書き込んでいます。

# おわりに

ご覧いただきありがとうございました！
かなりラフに作ったので、まともに使えるようになるように、今後バグ修正をチョコチョコやっていく予定です。
JMeter Client/Server Remote Testing on Docker

## はじめに

JMeterの複数VMを利用してClient、そして複数のServerを利用する際の設定についてまとめています。
ぐぐってもトップにヒットする情報(※)ではまともに動かなかった人(自分)向けです。
※Dockerを使った例では、ほとんどが1ホスト内で動かすものです。複数のサーバーを使った場合にハマりやすいです。

**実行したい環境**<br>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268550/dc991d06-2eb7-1799-177b-666aabbe99c4.png)


## 結論

### Serverの実行

```bash:JMeterSeverの起動
sudo docker run -it --rm \
     -p20000:20000 \
     justb4/jmeter:latest \
     -s -n -j /dev/stdout \
     -Dserver_port=20000 -Dserver.rmi.localport=20000 \
     -Dserver.rmi.ssl.disable=true \
     -Djava.rmi.server.hostname=$(host $(hostname)| awk '{print $4}') \
     -Jmode=Statistical
```

- `server_port` , `server.rmi.localport`で使うポートを指定して、`-p20000:20000` でポートを空ける。
- `server.rmi.ssl.disable=true` はSSLは利用しないので、無効化。
- `java.rmi.server.hostname`ではClientからはホストのIPでつけつけるので、ホストのIPを `$(host $(hostname)| awk '{print $4}')` で埋め込み。
- Cleint<->Server間の通信が多い(数千qps以上)ので、[Statistical](https://jmeter.apache.org/usermanual/remote-test.html#sendermode)で通信量削減します。


### Clientの起動

```bash:JMeterClientの起動
sudo docker run -it --rm \
     -v $(pwd):/script -p20001:20001 -p20002:20002 -p20003:20003 \
     justb4/jmeter:latest \
     -Dserver.rmi.ssl.disable=true  \
     -Djava.rmi.server.hostname=$(host $(hostname)| awk '{print $4}') \
     -Dclient.rmi.localport=20001 \
     -Jremote_hosts=server-1:20000,server-2:20000,.... -Jmode=Statistical \
     -t /script/1.jmx -n -l /script/test.jtl -e -r -X
```

- `client.rmi.localport=20001` でポート番号を固定化。最大3つ使われるので、 `-p20001:20001 -p20002:20002 -p20003:20003` でポートを空ける。
- `server.rmi.ssl.disable=true` はSSLは利用しないので、無効化。
- `java.rmi.server.hostname`ではClientからはホストのIPでつけつけるので、ホストのIPを `$(host $(hostname)| awk '{print $4}')` で埋め込み。
- `remote_hosts` でリモートサーバー指定。
- `-t` でスクリプトファイル、 `-l` で結果ファイルを指定します。

## ハマりどころ

### Server -> Clientにデータ送信時にエラーが発生する

```
2020-12-21 12:04:39,730 ERROR o.a.j.t.RemoteThreadsListenerWrapper: Exception invoking listener on threadStarted.
java.rmi.ConnectException: Connection refused to host: xxx.xxx.xxx.xxx; nested exception is:
	java.net.ConnectException: Connection refused (Connection refused)
```

> At the moment JMeter will open up to three ports beginning with the port defined in client.rmi.localport. If there are any firewalls or other network filters between JMeter client and server, you will need to make sure that they are set up to allow the connections through.
https://jmeter.apache.org/usermanual/remote-test.html#tips

`client.rmi.localport` を使ってポート番号固定化することは多々あると思います。
ただ、**使われるポートは、3つのポートが最大使われます。** (この例だと20001~20003 )
これがあまり書かれている記事がなくてハマります…。

## 動機

どうしてJMeter+Dockerで動かそうとしたのかという話です。

弊社でもJMeter,Gatling,WRK,Vegentaなど色々なストレスツールを使っています。
古いものだと、JMeterでストレステスト用のシナリオが存在します。
Gatlingなど、別のツールでまた書くのがめんどくさい。でも、JMeterの実行環境がそもそも存在しない。そしてとある事情により、サーバーは別部署が担当しており、Javaのインストールを依頼するのがめんどくさい。

Dockerでサクっと動かしたいというのが動機です。

「あれ？これ前もやってはまったな・・・」
となったので自分のためにも記録しておきました。
[100%] MaxProductOfThree (codility lessons)

> _Painless_
> ### [MaxProductOfThree](https://app.codility.com/programmers/lessons/6-sorting/max_product_of_three/)
> 任意のトリプレット（P、Q、R）に対してA [P] * A [Q] * A [R]を最大化します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196344/4df68f5b-77ca-26d3-b67d-f2b64abc8bb9.png)

#### タスク説明

N個の整数で構成される空でない配列Aが与えられます。 トリプレット（P、Q、R）の積は、A [P] * A [Q] * A [R]（0≤P<Q <R <N）に等しくなります。

たとえば、次のような配列A：

```js:例
   A [0] = -3
   A [1] = 1
   A [2] = 2
   A [3] = -2
   A [4] = 5
   A [5] = 6
```

次のトリプレットの例が含まれています。

* （0、1、2）、積は-3 * 1 * 2 = -6
* （1、2、4）、積は1 * 2 * 5 = 10
* （2、4、5）、積は2 * 5 * 6 = 60

あなたの目標は、トリプレットの最大の積を見つけることです。

関数を書く：

`class solution {public int solution(int [] A); }`

空でない配列Aが与えられると、任意のトリプレットの最大積の値を返します。

たとえば、次のような配列Aが与えられます。

```js:例
   A [0] = -3
   A [1] = 1
   A [2] = 2
   A [3] = -2
   A [4] = 5
   A [5] = 6
```

トリプレット（2、4、5）の積が最大であるため、関数は60を返す必要があります。

次の仮定のための**効率的**なアルゴリズムを記述します。

* Nは[3..100,000]の範囲内の整数です。
* 配列Aの各要素は、[-1,000..1,000]の範囲内の整数です。

---
#### 解く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196344/cd300b3b-0f02-876d-aa09-c3969a9c4bed.png)

#### Program
[MaxProductOfThreeSolution.java](https://github.com/yp2211/algorithm/blob/main/src/codility/lessons/Lesson6_Sorting/Solutions/MaxProductOfThreeSolution.java)

```java
    public int solution(int[] A) {
        int max1 = -9999;
        int max2 = -9999;
        int max3 = -9999;
        int min2 = 9999;
        int min1 = 9999;

        for (int a : A) {
            if (a > max1) {
                max3 = max2;
                max2 = max1;
                max1 = a;
            } else if (a > max2) {
                max3 = max2;
                max2 = a;
            } else if (a > max3) {
                max3 = a;
            }

            if (a < min1) {
                min2 = min1;
                min1 = a;
            } else if (a < min2) {
                min2 = a;
            }
        }

        int maxProduct = max1 * max2 * max3;

        if (max1 <= 0 || min1 >= 0) {
            // 全て負 || 全て正
            return maxProduct;
        } else {
            if (min2 < 0 ) {
                // せめて2つ負
                int temp = max1 * min1 * min2;
                if (temp > maxProduct) return temp;
            }
        }

        return maxProduct;
    }
```
Detected time complexity:

O(N * log(N))

#### jUnit 
[MaxProductOfThreeSolutionTest.java](https://github.com/yp2211/algorithm/blob/main/test/codility/lessons/Lesson6_Sorting/MaxProductOfThreeSolutionTest.java)

#### Report
[trainingUP9UFH-H2Y](https://app.codility.com/demo/results/trainingUP9UFH-H2Y/)

***
### See also: [CodilityのLessonsをすべて解く（更新中）](https://qiita.com/yp2211/items/537f733060bb0f2aba8f)
RPAは泥沼が多い

[RPA (Robotic Process Automation) Advent Calendar](https://qiita.com/advent-calendar/2020/rpa "RPA (Robotic Process Automation) Advent Calendar")２２日目です。
あと３日か。

#正直言うとRPAは画像認識が弱い
これはじつはある会社でRPAを組んでいたときに発覚したことなんですが。
Windows8からWindows10にアップデートしたPCにはフォントが多少違う部分があるらしい。
これを伝えてきたのはNTT代理店のBさんからだったんですけど。
今更それ言われてもね。
俺たちそれ信じて作ってるんだよと思いっきり上司がブチ切れてましたね。
どうしてかというとフォント自体の入れ替えはWindowsのアップデートではなかなかできない範囲なんですよ。
自分は知ってたので別の手でやろうと試みていたらブチ切れられ。
WinActorが嫌いになりました。
Xpathが使えるらしいけど多分使いこなせる人いないんじゃないかなってところですね。
#なんでPythonやTypescriptじゃなくVBScriptなの
RPAの一番イヤな部分の一つはカスタマイズしようとすると必ず出てくるヘタレ枯れた言語。
そうです。
VBScript。
これってもう何年もバージョンアップしてない上に危ないと思うんですけど。
せめてJavaかTypeScriptかPythonあたりでもいいじゃないですか。
ほんと枯れまくってる言語ほどカスタムにも向かないし正直セキュリティーがマジで怖い。
#フローチャート形式やめませんか
これマジで言いたい。
フローチャートちゃんと習った人が組んでれば問題ないんですが。
フローチャートから書く設計って今ほどんどないです。
マジでいうとフローよりもブロックにしたほうがいいんじゃないと思うの俺だけっすかね。
フローチャートがとっつきにくくしてる気がしてならないです。
だから俺はPowerAutomateに期待してしまうんです。
あれって作り方も簡単だし分岐も簡単。
フローチャートだとネストが深くなるととことん難易度が増す。
これが一番イヤなんです。
だからこそlambdaやnode−redに走っちゃうのかもしれませんね。
#PowerAutomateDesktopに期待しています
正直PowerAutomateは楽ですし。
クライアント版がプレリリース（インサイダー）状態なのでマジ気になります。
WindowsだけじゃなくMacやLinuxにも出してほしいですよ。
マジで一番欲しいRPAはPowerAutomateDesktopなんですから。
もっと仕事を楽にしたいんです。
ナジで期待してます。
おいおい機能も同じこと書いてなかったかｗ。
それぐらい期待してるツールなのでPowerAutomateだけでも一回触ってみることおすすめします。

こんな所で今日は締めます。

明日は[okamooon](https://qiita.com/okamooon "okamooon")さんです。
どうやらQiita初心者みたいなので暖かく見てあげてください。
BigQueryでデータの公開設定をする方法と公開設定の確認方法

[BigQuery Advent Calendar 2020](https://qiita.com/advent-calendar/2020/bigquery) 12/23の記事です。

BigQueryのデータには[一般公開](https://cloud.google.com/bigquery/public-data?hl=ja)されているデータが多くあります。
同じように自分で持つデータを一般公開したい場合もBigQueryでは簡単に出来ます.


## データを一般公開する方法
やり方はいたって簡単で、datasetに対し下記のいずれかのユーザの閲覧権限をつければよいだけです
 - allUsers
 - allAuthenticatedUsers

allAuthenticatedUsersとは、組織の認証を受けたユーザと勘違いしがちですが以下のユーザとなっております

```
allAuthenticatedUsers は、すべてのサービス アカウント、および Google アカウントで認証されたユーザー全員を表す特殊な識別子です。この ID には、個人用 Gmail アカウントなど、Google Workspace または Cloud Identity のドメインに接続していないアカウントも含まれます。認証されていないユーザー（匿名の訪問者など）は含まれません。
```

つまり、google認証通っているすべてのアカウントがallAuthenticatedUsersの対象となります。


### 一般公開の注意点
一般公開した場合は、監査ログからアクセス元のIDやIPは取れない[仕様](https://cloud.google.com/bigquery/docs/reference/auditlogs#ids)となっています。

## 公開設定しているデータセットの確認方法
意図した公開設定なら良いのですが、意図してないデータセットを公開してしまっている場合もあるかもしれません。
その際の確認方法としていくつかあるので紹介します。

### 組織単位での確認方法

- [Security Command Center](https://cloud.google.com/security-command-center)を使った確認方法
SecurityCommandCenter(以下SCC)ではBQの[公開設定](https://cloud.google.com/security-command-center/docs/concepts-vulnerabilities-findings)の検知が出来ます
SCCを使ってる人はまずはダッシュボードから確認するのがよいと思います

- [Cloud Asset Inventory](https://cloud.google.com/asset-inventory/docs/overview)を使った確認方法
CLIで確認したい場合はCloud Asset Inventoryの[search-all-iam-policies](https://cloud.google.com/asset-inventory/docs/searching-iam-policies)使って確認が出来ます
サンプルコマンドはこちらです

```
gcloud asset search-all-iam-policies --scope organizations/ORGANIZATION_NUMBER --query "policy:(allAuthenticatedUsers OR allUsers)"
```
 
### プロジェクト単位での確認方法
組織単位での確認権限が無いが自分のプロジェクトは確認しておきたいという場合もあるかと思います。

- [Cloud Asset Inventory](https://cloud.google.com/asset-inventory/docs/overview)を使った確認方法
検索の範囲をプロジェクトに絞ることで組織権限がなくても確認することが出来ます

```
gcloud asset search-all-iam-policies --scope projects/PROJECT_ID --query "policy:(allAuthenticatedUsers OR allUsers)"
```

## まとめ
BigQueryの公開設定方法と、公開設定の確認方法を共有させていただきました。
公開設定がされたかの検知をしたい場合はSCCでもCloudAssetInventoryでも検知結果をリアルタイムにpub/subに飛ばすことが出来るので、pub/subからslackなどに通知するシステムを作るのがいいのではないかと思います。
Python数学シリーズ② 行列の掛け算

## 経緯
[深層学習の本](https://www.amazon.co.jp/%E6%B7%B1%E5%B1%A4%E5%AD%A6%E7%BF%92-Ian-Goodfellow/dp/4048930621)を読み進めているのですが、ひたすら文字を読んでると眠くなってしまうので、出てきた項目をpythonで実装しながら理解を深めていこうと思います。需要があるかはわかりませんが、シリーズ化していています(笑)。目次は[こちら](https://qiita.com/Hiroaki-K4/items/90b2f86558ef825e5d21)です。今回は行列の掛け算をやっていこうと思います。pythonはライブラリが豊富なので、それに頼れば何も考えずに計算できるのですが、あえて自作しています。
***これは[adevent calendar](https://qiita.com/advent-calendar/2020/global_walkers)の自分の最後の記事です。カレンダーの最後は@bigface00さんが締めてくれます。***

## 行列の掛け算
行列の掛け算は下のようなイメージで計算できます。[参照元](https://atarimae.biz/archives/23930)
![Screenshot from 2020-12-22 20-40-38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663246/1eb84b89-62be-21e7-fc82-acf6da52249c.png)

## 簡単な実装
[こちら](https://note.nkmk.me/python-numpy-matrix/)の記事を参考にすると、numpy.dotかnumpy.matmalを使えば簡単に実装できるようです。

```python3
arr1 = np.arange(4).reshape((2, 2))
print(arr1)
# [[0 1]
#  [2 3]]

arr2 = np.arange(6).reshape((2, 3))
print(arr2)
# [[0 1 2]
#  [3 4 5]]

print(np.dot(arr1, arr2))
# [[ 3  4  5]
#  [ 9 14 19]]

print(arr1.dot(arr2))
# [[ 3  4  5]
#  [ 9 14 19]]

print(np.matmul(arr1, arr2))
# [[ 3  4  5]
#  [ 9 14 19]]
```

## 自作してみた
まずは最終的な答えの行数と列数を数えておきます。答えの行数は前の行列の行数で、答えの列数は後の行列の列数なので、それをもとにfor文を回しています。3つ目のfor文の中で、前の行列の行と、後の行列の列との計算をやっています。前の行列の列ごとの計算結果をtmp_listに入れておき、最終的にans_listに全ての計算結果を入れています。

```python3
def matrix_mlp(list1, list2):
	ans_row = len(list1)
	ans_col = len(list2[0])
	ans_list = []
	for i in range(ans_row):
		tmp_list = []
		for j in range(ans_col):
			tmp = 0
			for k in range(ans_row):
				tmp += list1[i][k] * list2[k][j]
			tmp_list.append(tmp)
		ans_list.append(tmp_list)
	return ans_list

def main():
	print("~~matrix_multiple_test~~")
	arr1 = np.arange(4).reshape((2, 2))
	arr2 = np.arange(6).reshape((2, 3))
	print("Before1  :", arr1.tolist())
	print("Before2  :", arr2.tolist())
	print("correct  :", np.dot(arr1, arr2).tolist())
	print("my_answer:", matrix_mlp(arr1.tolist(), arr2.tolist()))
```
このシリーズ恒例ですが、実装はさっき思いついたやつなので合っている保証はしていません(笑)。ここ違うとか、こういう方法あるよとかあれば教えてください。
こんな感じでゆる〜く読み進めてます。

**間違いや質問、ご意見等ありましたらお気軽にコメントください。頑張って答えますので(笑)。**
InfluxDBについて調べなおしたので自分用まとめ

InfluxDBについて調べなおしたので
忘れないうちに自分用にまとめておくことにした

##InfluxDBとは
・アメリカのinfluxdata社が開発している時系列のデータベースでOSS版もある
・TSMエンジンが採用され、高い取り込み速度とデータ圧縮を可能にしている
・ソースはGo言語で書かれている
・SQLに似たinfluxQLというものが採用されれている
・HTTPapiで操作ができる
・タグをうまく使用することによって効率的にクエリを実行できる
という特徴がある

自分も使用することが多いのだが、時系列にデータが保存されるのでIoTで使用するときに便利だと感じている
特にオープンソース版を使用することにより手軽に試すことができるのでプロトタイプに使用している

###入手方法
[こちら](https://portal.influxdata.com/downloads/)からダウンロードしてインストールすることにより、使用することができるようになる

ここからは使用OSがubuntuになる
コンソールからInfluxDBを立ち上げる

```
$sudo systemctl status influxdb
```
デフォルトの状態で8086のポートを使用するので開けておく必要がある

```
$sudo ufw status
```
現在の状態を確認して、必要があればポート開放

```
$ sudo ufw allow 8086
$ sudo ufw reload
```
###準備ができたのでInfluxDBを使用していく
コンソールからinfluxと入力することでCLIが立ち上がる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244155/baf0b4fa-9bc7-36fd-3098-3a2d0b6118a5.png)
きちんと立ち上がると、コマンドプロンプトの見た目が変化する

まずは新しいDBを作成する

```
$create database hogehogedb
```
作成したDBを確認する

```
show databases
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244155/acf0214d-39a3-9de4-cf76-d7d2b26bd552.png)
新しくDBが作成されていることを確認

データベースの作成が終ると
データベースはクエリと書き込みの準備ができている

###InfluxDBで使用される用語
MEASUREMENT
RDBでいうところのテーブルに該当する
概念的にはプライマリインデックスが常に次官であるSQLテーブルであると考えることができる
tagsとfieldsは事実上テーブルの列のことである

point
RDBでいうところのレコードの概念
timestamp, measurement, key, valueから形成される
実際にデータの部分をfieldといいkey, valueの形で格納されている

pointの書き込みにはILP(Influx Line Protocol)という形式が用いられる

```
<measurement>[,<tag-key>=<tag-value>...] <field-key>=<field-value>[,<field2-key>=<field2-value>...] [unix-nano-timestamp]
```
実際の書き込みにはINSERTコマンドが用いられる

```
INSERT <measurement>[,<tag-key>=<tag-value>...] <field-key>=<field-value>[,<field2-key>=<field2-value>...] [unix-nano-timestamp]
```

SELECTコマンドでデータのクエリを行うことができる
※クエリとはデータの問い合わせや参照のこと

###代表的なSQLの例
CREATE：データベース・テーブルの作成
ALTER：データベース・テーブルの定義変更
DROP：データベース・テーブルの削除
SELECT：データ検索
UPDATE：データ更新
INSERT：データ挿入
DELETE：データ削除

クエリに時間がかかっているときは
ctrl + cでクエリをキャンセルすることができる

以上のことがわかっていれば最低限の動作確認を行うことができる


###参考情報
[Helve’s Python memo ](https://helve-python.hatenablog.jp/entry/infludb-getting-started)
[みかんのゆるふわ技術ブログ](https://www.mikan-tech.net/entry/what-is-influxdb)
[influxdata document](https://docs.influxdata.com/influxdb/v1.8/)
GithubにSSHを用いて接続する

環境
=
macOS HighSierra 10.13.6

経緯
=
UdemyのGit講座を受講中、説明通りに下記コマンドを用いてGithubへpush

```
$ git remote add origin https://github.com/hoge/fuga.git
$ git push -u origin master
```

を打った際

```
remote: Repository not found.
fatal: repository 'http://github.com/hoge/fuga.git/' not found
```

というエラー文が出てきてしまい、　Githubへpushすることが出来なかった。

原因
=
プライベートリポジトリへの認証失敗
対策
=
SSHによる接続を行う(httpsではなくgit@)ことで解決
SSH Keyの確認
=

```
$ cd ~/.ssh
```

自分の場合恐らく昔訳も分からず作ったknown_hostsがあったが、一旦ゼロベースに戻すためにremove

下記コマンドでSSHの鍵を生成

```
$ ssh-keygen -t rsa

generation public/private rsa key pair
Enter file in which to save the key (/Users/PCのusername/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
```

途中パスフレーズの設定を聞かれるが、今回は何も入力せず全てエンターを押してskip。
後に設定することも可能なので現時点ではGithubへのpushまでの最短ルートとして。


.sshのディレクトリ内に

```
id_rsa(秘密鍵)　id_rsa.pub(公開鍵)
```

が作成されたら自身ターミナルで

```
$ pbcopy < ~/.ssh/id_rsa.pub
```

と叩くとid_rsa.pubがコピーされた状態になるので
https://github.com/settings/ssh
の画面右上からAdd SSH Keyの先にある
keyエリアにペーストしAdd SSH Keyで完了。

無事Githubへpushすることが出来た。
ArchUnit 実践：集約操作専用のリポジトリ（やDAO）によってのみ、集約が永続化されることを強制する②＜汎用 ver.＞

```
// 実行環境
* AdoptOpenJDK 11.0.9.1+1
* JUnit 5.7.0
* ArchUnit 0.14.1
```

## アーキテクチャテストのモチベーション

21 日目の [ArchUnit 実践：集約操作専用のリポジトリ（やDAO）によってのみ、集約が永続化されることを強制する①](https://qiita.com/kawanamiyuu/items/62f52b09c74369e95551) は特定の集約とその Dao クラス対して実装ルールを強制するアーキテクチャテストでした。
今回は実現したいことはそのままに、特定の Dao クラス名や AggregateDao クラス名をハードコードせず、汎用的なアーキテクチャテストとして実装します。

## アーキテクチャテストの実装

```java
package com.example;
　
import com.tngtech.archunit.base.DescribedPredicate;
import com.tngtech.archunit.core.domain.JavaClass;
import com.tngtech.archunit.core.domain.JavaClasses;
import com.tngtech.archunit.core.importer.ClassFileImporter;
import com.tngtech.archunit.core.importer.ImportOption;
import org.junit.jupiter.api.Test;

import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes;

class ArchitectureTest {

    // 検査対象のクラス
    private static final JavaClasses CLASSES =
            new ClassFileImporter()
                    .withImportOption(ImportOption.Predefined.DO_NOT_INCLUDE_TESTS)
                    .importPackages("com.example");

    @Test
    void AggregateDaoから使用されるDaoは他のクラスから使用されない() {
        classes().that()
            .haveSimpleNameEndingWith("Dao")
            .and(new DescribedPredicate<>("are injected into AggregateDao") {
                @Override
                public boolean apply(final JavaClass daoClass) {
                    // "AggregateDao から使用される Dao" を、
                    // "AggregateDao に対してコンストラクタ・インジェクションされる Dao" と、
                    // 解釈してみる。

                    Set<JavaConstructor> constructorsThatDaoClassIsInjectedInto =
                        daoClass.getConstructorsWithParameterTypeOfSelf();

                    return constructorsThatDaoClassIsInjectedInto.stream()
                        .map(JavaMember::getOwner)
                        .anyMatch(clazz -> clazz.getSimpleName().endsWith("AggregateDao"));
                }
            })
            .should()
            .onlyBeAccessed()
                .byClassesThat()
                .haveSimpleNameEndingWith("AggregateDao")
            .check(CLASSES);
    }
}
```
LeoNetで使える配信サービス

#どうしようもない回線で配信しようとしている人向け
一応本業はSEで、かつVtuberとして活動しているのですが、今住んでいるのはレオパレスに住んでおり、
固定回線が例外なくどうしょうもないLeoNet一択のみになっています。
もし同じような人で配信とかしようと思っている人向けの記事です。

まだ、検証していない配信サービスもあるのでおいおい追記していきます。

#検証に使用したソフト
OBS OBS Studio 26.1 
3tene FREE V1.10.17

#一応回線について
建物自体はFTTHだが、部屋の中にレオパレス管理のスイッチングハブが存在しており
このハブ自体の性能はIEEE802.3u(100BASE-TX)/IEEE802.3(10BASE-T)となっており宅内の理論的な速度は100Mbpsまでとなる

なお、各部屋の経路は以下のようになっているもよう

```
                                                                     |---監視カメラ(レオパレス管理)
インターネット --- ONU(レオパレス管理)---管理機器？<踏み台?>(レオパレス管理)|---各部屋のスイッチ(レオパレス管理)---各個人のルーターなど
                                                                     　　　|---機械警備機器(レオパレス管理?)
```

一応アカマイまでの応答速度
なお私の環境の場合特定の時間帯で速度が低下する場合があった（酷いときで128Kbpsぐらい）

```
C:\>ping 8.8.8.8

8.8.8.8 に ping を送信しています 32 バイトのデータ:
8.8.8.8 からの応答: バイト数 =32 時間 =8ms TTL=114
8.8.8.8 からの応答: バイト数 =32 時間 =31ms TTL=114
8.8.8.8 からの応答: バイト数 =32 時間 =5ms TTL=114
8.8.8.8 からの応答: バイト数 =32 時間 =41ms TTL=114

8.8.8.8 の ping 統計:
    パケット数: 送信 = 4、受信 = 4、損失 = 0 (0% の損失)、
ラウンド トリップの概算時間 (ミリ秒):
    最小 = 5ms、最大 = 41ms、平均 = 21ms
```

#YouTube
ここに関しては問題なく配信できます。
正直ここで配信できないとなった場合はあきらめるか、回線に問題が発生しているので調べること。
なお、多少遅延は発生しますが問題のない範囲だと思います(どれくらい遅延していたかは忘れた)
OBSの設定はYoutubeのプリセット設定で問題ないと思います。

#showroom
以前は配信出来ていたが、現在は配信不可。
一度テストで配信した際は映像がストリーミングできていたようだが、
現在は映像が映らず音声もおそらく流れていない可能性もある。
OBSの設定はshowroom推奨の設定であっても上の事象が発生した。

showroomでどうしても配信を行いたい人は無制限のデータ通信専用SIMを手に入れてモバイルルーターでやるしかないと思う

#ニコニコ生放送
一般会員なので３０分しか配信できないが問題なく配信できる。
遅延については不明。
多分Youtubeと同じぐらいだと思う。
OBSの設定はニコニコのプリセット設定で問題ないと思います。

#最後に
上にも書きましたが後々ほかのサービスについても追記していきます。
建物によって設備が違うと思うので、あくまで参考値程度と思ってください。
経路図についてはまずかったら消します。

個人的には回線速度は問題ないけどネットワーク管理側で何故かshowroomの配信ができないようにしているのはどうかと思う。
しかも半端な防ぎ方で、showroomのページにはアクセスでき、配信のトラフィックだけ止めているような状態です(pingも通る)。

LeoNetで配信するべきではないという声が聞こえてきそうですが、効果的な対策はモバイルルーターを使うか他の建物に引っ越して
別回線を契約するしかないという状況です。

もし、この回線で配信をやりたいという方はとんでもないドM野郎だと思いますし、すぐには引っ越せない人はモバイルルーターを使うしかないという状態です。
しかもほかの固定回線は契約不可というおまけもついてます。

あとパソコンと部屋にあるレオパレス管理のスイッチに直つなぎしてarpテーブルを調べると・・・
Telnetでガバガバやないかこれ・・・

となるのでお勧めしません。

#参考にしたサイト
[LSW3-TX-5NP/WH](https://www.buffalo.jp/product/detail/lsw3-tx-5np_wh.html)
[レオパレス21 レオネット被害者の会](https://w.atwiki.jp/leopalace-higai/)
アドベントカレンダー20日目：SREを読んでみた「Googleにおける自動化の進化」編⑥

前回は、Googleの自動化の2つ目の実例を扱いました。
Prodtestを拡張し、修正スクリプトを実装することで対応しましたが、現実の世界の変化には対応しきれませんでした。そこへきっかけはセキュリティ要件でしたが、Admin Serverからのサーバーへの変更の仕組みを取り入れることにより、自動化の仕組みからRPCが送られるようになりました。
今回は自動化の問題を考える上でたどり着いたもう一つの事例であるクラスタ管理システムの歴史を見ていきます。

## Borg：ウェルハウススケールコンピュータの誕生
初期のころのGoogleクラスタは、一般的な小さなネットワークと同じように設置されていました。特定の目的のためのさまざまな設定がなされたマシン群がラックに収められていました。プロダクション環境が成長していくにつれて、複数のクラスタが立ち上がりました。そして、さまざまなドメイン（クラスタ名）が加わっていきました。その際、それぞれのマシンが受け持つことを記述するファイルが必要になり、そのファイル内でゆるい命名方針でマシンがグルーピングされました。この記述ファイルと並列SSH相当のツールを使うことで、例えばすべての検索マシンを同時に再起動するということができるようになりました。
そして、自動化の開発が始まりました。処理の自動化は、サービス管理やサービスが動作しているマシンの追跡、ログメッセージのパースなどシンプルなものでした。最終的に自動化の仕組みはマシンの状態を追跡するデータベースへと変化するとともに洗練されたモニタリングツールを取り込みました。
このような融合型の自動化の仕組みが備わるとサービスの除去、サーバーの修理への配送、修理から戻ったマシンへの設定のリストアなどが自動で管理できるようになりました。
この自動化は有益ですが、システムが物理マシンに堅く結びついてしまっていました。
そこで誕生したのがBorgです。Borgによって、以前のようにホスト/ポート/ジョブの割り当てという方法からマシン群の集合をリソースプールとして扱うようになりました。
Borgの出現により、数千台のマシンが日々設置され、壊れ、修理に送られるものの、SREがそれに関して作業することは無くなりました。初期のクラスタ管理の自動化からシステム自体を自律的なものへと変化させました。
地球規模のコンピュータにおいて、一定のサイズを超えると大量の障害が発生することが日常になります。そうなれば、運用するには自己修復が必要不可欠になります。
システムが手動、自動、自律と進化するにつれて、自己検査の能力がなければ生き残れなくなります。

## 基本的機能としての信頼性
システムが成長するごとにやがて、自律的なものである必要が出てくることは、わかりましたが、しかし、同時に高度に自動化されたシステムによる弊害も指摘されています。
それは、自動化による人間が直接システムを扱う機会がなくなっていくことです。そして、自動化の仕組みに問題が生じたとき、人間にはうまく扱うことができなくなっています。
また、大規模に自動化を行ったことにより、問題が生じたときの影響範囲が大きくなることも考えられます。
しかし、多くのシステムにおいて、その規模に関係なく、自律的なシステムを求めるべきであるという主張もあります。その為、信頼性はオプションではなく、基本的な機能となります。
今後の学習でその理由について、見ていこうと思います。

##まとめ
* システムの進化は、手動、自動、自律
* 自律的なシステムにも問題が生じる。しかし、自律的なシステムを目指すべき。

#### 参考文献
1. Betsy Seyerほか　SRE サイトリライアビリティエンジニアリング　オライリー　86-89
フィボナッチ数列

\![Mac OS X-10.15.7](<https://img.shields.io/badge/MacOSX-10.15.7-brightgreen>) \![ruby-2.7.1p83](<https://img.shields.io/badge/ruby-2.7.1p83-brightgreen>) 


# 今回の問題

再帰を用いてフィボナッチ数列を求める．

はじめに

    p fib(0)

を実行するが，当然エラーが表示される．そのため，定義する．

```ruby
def fib(n)
  if n==0
    return 0
  end
end
```

これで，fib(0)に対して０が返される．

```ruby
require './assert_equal'
puts assert_equal(0, fib(0))
```

前回作成したassert\_equal.rbで確認をする．成功すれば”succeeded in assert\_equal”が表示される．

次にfib(1)を求める．先ほどのfib(n)にはnが0のときのみ0が返されるため，n=1のときにも返されるように変更しなければならない．

```ruby
def fib(n)
  if n==0
    return 0
  end
  if n==1
    return 1
  end
end
```

とすれば，よい．以下は配列を用いることで重複を避けていく．

```ruby

[[0,0],[1,1]].each do |pair|
  puts assert_equal(pair[1], fib(pair[0]))
end
```

[配列].each do |pair|を使うことで代入を複数行追加することなく，配列の要素の追加のみで済む．もう少し，理解しやすいように書き換えると

```ruby
require './assert_equal'
[[0,0],[1,1]].each do |index, expected|
  puts assert_equal(expected, fib(index))
end
```

こうすることで直感的に理解できる．このままfib(2),fib(3),…….fib(n)と配列の要素を増やした際に対応できるようにコードを変更する．

```ruby
def fib(n)
  return 0  if n==0
  return 1  if n<=2
  return fib(2) + fib(1)
end
```



------
 - **source** ~/grad_members_20f/members/szksjm/qiita_post/R3.org
obniz.repeatが便利なのにあんまり使われていない気がする話


[obniz Advent Calendar 2020](https://qiita.com/advent-calendar/2020/obniz)の１６日が開いていたので、
obnizには`obniz.repeat`という便利？関数の布教活動してみます。

`obniz.repeat`はあんまりみんなに使われていない気がするんですよね。

### obniz.repeatって何？

`obniz.repeat`はobnizで繰り返し処理をするときに設定する関数です。
arduinoで言うところのloopですね。

ずっと繰り返してくれる＝無限ループだ！　ってことで `while(true){}` と同じだと思われるんですが、
実ははうらで色々やってて、

- obnizデバイスとの接続が切れたら自動で止まるように
- 内部でエラーが出ても止まらずに次のループを動かしてくれる

という機能もついています


### とりあえずコードで比較


↓動くんだけど、のちにハマりやすい書き方

```javascript

let obniz = new Obniz("XXXXX");

obniz.onconnct = async ()=>{
   let led = obniz.wired("LED", {xxxx});

   while(true){
      led.on();
      await obniz.wait(1000);
      led.off();
      await obniz.wait(1000);
   }
}
```


↓おすすめの書き方

```javascript

let obniz = new Obniz("XXXXX");

obniz.onconnct = async ()=>{
   let led = obniz.wired("LED", {xxxx});

   obniz.repeat(async ()=>{
      led.on();
      await obniz.wait(1000);
      led.off();
      await obniz.wait(1000);
   }, 0); //リピートインターバルが0ms
}
```


`while(true)`と`obniz.repeat`の比較です。
書くコード量はどっちもそんなに変わらないし、どちらも同じようにかけます。


ただ、これが途中でデバイスとの接続が切れた！というときに、

while(true)はled.on()がうまく行かなくてthrow
 → try/catchはこのコードで書かれてないので、プログラム全体のエラーとなり、<font color="red">プログラムがクラッシュする</font>



obniz.repeatはthrowをハンドリングして、console.errorに出すだけでクラッシュしなくなる
& 自動で次のループも止めるので正常に<font color="blue">プログラムが動き続ける</font>


という違いが生まれます。
とりあえず繰り返し処理したいから`while(true)`だ！というのを、とりあえず`obniz.repeat`だ！に変えるだけで、ちょっとだけ安全なプログラムになるので、ぜひ使ってください


### オプション

obniz.repeatには第2引数があって、インターバル時間を指定できます。
repeatの第1引数で指定した関数を実行するときに、ちょっと待つってことができます。

一番高速で動かしたければゼロを指定すればOKですが、5分に１度だけ動かしたいなと言うときは5分＝300,000msなので300000と指定すればOKです

↓5分に１秒だけ光るLED．　タイミング見計らうのが難しそう

```javascript

let obniz = new Obniz("XXXXX");

obniz.onconnct = async ()=>{
   let led = obniz.wired("LED", {xxxx});

   obniz.repeat(async ()=>{
      led.on();
      await obniz.wait(1000);
      led.off();
   }, 300000); //リピートインターバルが300000ms = 5min
}
```


### ライフサイクル

ちなみに、全体的な挙動イメージはこんなライフサイクルになります。

![名称未設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/3d9e414f-f6e0-cbc9-e288-e869f5a32f7c.png)

右側に書いてるのはobniz.connectionStateで取れる値です。


`obniz.onconnect = async () => {}`でプログラムを書いている人が大半だと思いますが、実は`obniz.on('connect', async ()=>{})`って書き方でもOKだったり・・・！
プログラムの書き方Tipsはそのうちまた記事にしようと思います。
WasmBoxC などで, C/C++ コードをセキュアな環境でサンドボックス実行するメモ

## 背景

C/C++ プログラムを sandbox 環境的な状況で動かしたい.
e.g. サーバで動く画像処理(性能のために C/C++ で記述が必要)サービスで, ユーザーが malicous な画像データをアップロードしても堅牢に動いてくれるとか.
 
runC とか Docker コンテナとかありますが, そこまで大掛かりなもの(+ OS 依存のもの)は必要ない
(e.g. ネットワークは不要で, 演算(CPU/mem)だけセキュアに実行したい)

## WasmBoxC

WasmBoxC: Simple, Easy, and Fast VM-less Sandboxing
https://kripken.github.io/blog/wasm/2020/07/27/wasmboxc.html

ありがとうございます.

Wasm -> C にして, C/C++ と同等の速度でサンドボックス実行します.
ツールチェインとしては特に新規のものはなくて, wasm(emcc) の既存ツール環境で実現しています.

### 利用例

https://gist.github.com/kripken/2d982aede096e456591b2821a9d41b31

## その他

https://github.com/bytecodealliance/wasm-micro-runtime

一応こちらが WASM ランタイムの本命っぽい? AoT(事前コンパイル), interpreter, JIT 実行できます.

https://github.com/wasm3/wasm3

wasm 自体を高速インタプリタ実行


## TODO

* [ ] rust や go で書かれたコードなども, Wasm にすることで WasmBoxC で動かせるかためす. 
* [ ] 生成された C コードに fuzzer をかけたりしてさらなるセキュリティの向上をはかる.
[Sass] 基礎のまとめ

#入れ子構造
Sassは、1つのセレクタの中に別のセレクタを入れ子にして指定することができます。

通常のCSS

```
.header {
  color: red;
}
.header ul {
  color: blue;
}
```

Sass

```
.header {
  color: red;

  ul {
    color: blue;
  }
}
```

また、 `セレクタ:hover` を `&:hover` に書き換えることができます。（activeなどにも）

```
a {
  font-size: 20px;

  &:hover {
    opacity: 0.8;
  }
}
```

#変数

`$変数名`を記述するだけです。
変数は利用する箇所より前で定義することに注意です。

```
$btn-color:#22fe56;

h1 {
  color: $btn-color;
}
```

#mixin
いくつかのコードを1つにまとめて、複数の場所で呼び出すことができます。
同じコードを何度も書く必要がなくなるので、無駄なコードを省略することができます。

##mixinの定義

`@mixin mixin名` で定義します。

```
@mixin main-show {
  width: 300px;
  height: 500px;
}
```

##mixinの呼び出し

使用したいSassファイルの中で `@include mixin名` で呼び出します。

```
.user-1 {
  @include main-show;
}

.user-2 {
  @include main-show;
}
```

##mixinに引数を渡す
`@mixin mixin名(引数名)` で定義します。
`@include mixin名(引数)` で呼び出します。

```
@mixin main-show($color) {
  color: $color;
}

.user-1 {
  @include main-show(#3a783a);
}
```

#import
外部のファイルを読み込みます。
読み込み先のファイル名の先頭には`_colors.scss` のように `_（アンダーバー）` を付けなければいけません。
また、ファイルを読み込むには `@import "ファイル名"`とします。
(ファイル名は、 `_` と `拡張子（.scss）` を省略しても良いです。)

```
@import "colors";
```

importの使い方として、変数をまとめたファイルを作成し、使いたいファイル内で読み込みます。
こうすることで変数を記述した箇所がわかりやすくなります。
spring-kafkaで一度に複数メッセージをconsume

まず```BatchMessageListener```の実装を作成する。

```java
import java.util.List;

import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.kafka.listener.BatchMessageListener;
import org.springframework.stereotype.Component;

@Component
public class SampleBatchMessageListener implements BatchMessageListener<String, String> {
	@KafkaListener(topics = "mytopic2")
	@Override
	public void onMessage(List<ConsumerRecord<String, String>> data) {
		System.out.println(data.size() + ":" + data);
	}
}

```

次に```spring.kafka.listener.type```を```BATCH```に変更する。

```properties:src/main/resources/application.properties
spring.kafka.bootstrap-servers=localhost:32770
spring.kafka.consumer.group-id=sample-group
spring.kafka.listener.type=BATCH
```

これでspring-bootを起動して適当にpublishする。

```
5:[ConsumerRecord(topic = mytopic2, partition = 0, leaderEpoch = 0, offs（以下省略）
1:[ConsumerRecord(topic = mytopic2, partition = 0, leaderEpoch = 0, offset （以下省略）
3:[ConsumerRecord(topic = mytopic2, partition = 0, leaderEpoch = 0, o（以下省略）
```

一度にバラバラの件数でconsumeされているのが分かる。

以上で動作はするが、実運用では以下らへんのパラメータも指定しないとダメと思われる。バラバラの件数でメッセージが到着しているのを見ると、いわゆるRDBMSのコミット間隔とまったく同じように使えるというわけでもない。

```
spring.kafka.consumer.fetch-max-wait
spring.kafka.consumer.fetch-min-size
spring.kafka.consumer.max-poll-records
```

バッチ処理的な発想はkafkaでも有効だが、kafka固有の事情は考慮が必要と思われる。

ドキュメント https://docs.spring.io/spring-kafka/docs/current/reference/html/#message-listeners
GCP の Identity Aware-Proxy を使って SSH した話

#Cloud Identity Aware-Proxy とは？

一言で表すと、Google のアカウントを使ってセキュアにリソースに接続できるプロキシサービスです。

###何ができる？
- GCP 上の VM に対して、アクセス制御を行うことができる
- Google アカウントの ID を確認して、制御を行うことができる
- VPN を使用することなく、外部ネットワークからの作業ができる
- ゼロトラストのアクセスモデルを実装できる

[Identity-Aware Proxy 概要](https://cloud.google.com/iap?hl=ja)

##IAP との出会いの経緯
GCP 上の GCE にセキュアに SSH できる方法がないかを探しており、いくつかの候補を出していました。

1. GIP を使用して目的のインスタンスへ接続を行う
2. GIP を付与した踏み台インスタンスを作成し、踏み台インスタンスを経由して目的のインスタンスへ接続を行う

2 に関しては、[公式のドキュメント](https://cloud.google.com/solutions/connecting-securely?hl=ja#bastion)でも紹介されており、オンプレでの NW 構築を経験していた自分の中ではかなり有力な候補でした。

図にするとこのような感じ↓
GCP のサービスを使用せずに、PrivateサブネットのGIPを持たないインスタンスに接続する場合
![スクリーンショット 2020-12-17 16.47.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689597/efdb9c75-02d4-501f-5162-749394072f7b.png)


しかし、この方法だといくつか面倒なことが

- 鍵の管理が面倒
    - GCP のサービスを使用せずに GCE へとアクセスしようとすると、ローカルでの鍵の作成・保管が必要になる
    - ローカルで作成した公開鍵を、SSH 先のインスタンスに登録する必要がある

- GIP 関連
    - 固定の GIP を取得する必要がある
    - 常に不正にアクセスされるリスクがある  


まず、鍵の管理については、 [ gcloud コマンドを使用したSSH 接続の方法 ](https://cloud.google.com/sdk/gcloud/reference/compute/ssh)にて解決しました。
さすがクラウドって感じで、めんどくさい鍵周りの部分をやってくれます。

そして、 GIP を使用しないで SSH できないかと調べていたところ、たどり着いたのが IAP でした。


##IAP で使用した機能
IAP には様々な機能があるのですが、今回の GCE への SSH 接続には、[ Cloud IAP TCP Fowarding ](https://cloud.google.com/iap/docs/using-tcp-forwarding)という機能を使用しました。

###何ができるのか
- トンネルを使用した TCP 接続ができる

###通信のフロー
1. TCP のコネクションを IAP を使用して HTTPS でラッピングする
2. IAM にて権限を確認する
    3. 接続先のリソースの権限
    4. IAP トンネルを使用する権限
5. VPC に紐づく FW ルールを確認(ネットワークレベル)
    6. IAP から リソースへの接続が許可されているか



図にするとこのようになります↓
![_2020-12-21_17.22.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689597/cd8d40c2-ccf5-2f87-24f7-3736722b2089.png)

IAP が踏み台インスタンスの役割をしてくれてるため、インスタンスへ GIP を付与する必要がなくなり、当初考えていた面倒な点を解消することができました。

###一つ気になる点が
確かに IAP を使用することで、GCE へのセキュアな通信を確立することができましたが、1つ気になることが出てきてしまいました。
**Google アカウントが漏れたらやりたい放題じゃん...**

これを解決するために、[Access Context Manager](https://cloud.google.com/access-context-manager/docs?hl=JA) という機能を使用しました。
別の機能になってしまうので詳細な説明は割愛しますが、一言で言うと" IPやデバイスなどの単位で、プロジェクトやリソースへのアクセス制御が行えるサービス "です。
組織単位でポリシーを作成し、プロジェクト単位でポリシーを適用します。
今回の場合は、IP 制限のポリシーを作成し、IAP トンネルを使用する IAM ロールにアタッチして使用しました。
この機能を使用することで、万が一Google アカウントが流出した際も、IPアドレスなどで制御を行うことができ、セーフティーネットを張ることができます。

###最後に
IAP を使用した VM への接続は、今回のような GCE 以外にも、GKE への接続や GAE への接続など、様々な使い方ができる機能なので今後もお世話になりそうです。
私と同じような状況で迷っている方に、この記事が参考になりましたら幸いです。
最後までご覧いただきありがとうございました。
google docs (ドキュメント)のセクション区切りを消す方法

# 解決方法
セクション区切りは、

1. 上部メニューの 「表示」 > 「セクション区切りを表示」 をチェック。
2. セクションの線の上から下までドラッグして、セクションラインをまたぐ範囲が選択された状態にする。
3. BackSpace を押すと消える


# はまりどころ

「挿入」 > 「区切り」から追加した「改ページ」は BackSpace を押すと消えてくれるのですが、「セクション区切り（次のページ）」を入力すると、見た目は「改ページ」と全く同じなのですが BackSpace を押しても消えてくれません。

# 終わりに

google docs 便利ですよね。
無料なのに高機能、さらにシェアが容易にできるので、仕事でもプライベートでも重宝しています。
しかしたまに、ドキュメントに書いていない機能があるのでハマると解決が大変だったりします。

セクション区切りの機能がまさにそれで、公式ドキュメントを読んでもセクション区切りを追加する方法は書かれていますが、削除する方法は書かれていません。（見つけられていないだけかもしれませんが、結構時間をかけて探しましたが見つけられませんでした汗）