表参道Web勉強会 - スライド

# Submarine.js紹介

##### JavaScriptとShellScriptで、プログラマブルなインフラを実現

2019/12/12

[表参道Web勉強会](https://oweb.connpass.com/event/156818/?utm_campaign=event_participate_to_follower&utm_medium=twitter&utm_source=notifications)の発表スライドです

![osc19tk-screen3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416178/279a3d41-a9f9-3605-8d34-cec271b2d83d.gif)

---

## 自己紹介

* インフラ歴6年
* js歴6年(業務での利用経験はなし)

Twitterアカウント : @Mjusui

---

```messages.js
const TodaysMessages=[
  “Infrastructure as Codeの現状と課題 - Ansibleの場合",
  “Submarine.jsのアプローチ",
];
```

---

## インフラエンジニアの仕事

```shell-session:ServerA
# rm -rf /
```

---

## サービスが拡大し、サーバが増えてくると

```shell-session:ServerA
# rm -rf /
```
```shell-session:ServerB
# rm -rf /
```
```shell-session:ServerC
# rm -rf /
```
```shell-session:ServerD
# rm -rf /
```
```shell-session:ServerE
# rm -rf /
```
```shell-session:ServerF
# rm -rf /
```

---

## IaCとは

* Infrastructure as Code
* サーバの構築手順や作業を **コード化** すること

---

## インフラの構成管理の現状

AnsibleではYAMLで構成情報を管理 

```serverAtoZ.yaml
hosts: serverAtoZ
become: yes
tasks:
  - shell: 'rm -rf /'
```

---

## 冪等性とは

同じ操作を何回実行しても、同じ結果が得られること

```
x * 0 = 0
0 * 0 = 0
0 * 0 = 0
...
```

※Webの世界ではHTTPのGETやPUTメソッドは冪等だけど、POSTは冪等ではないなどと言われる

---
## インフラの世界における冪等性

* 何回同じコードを実行しても、同じサーバの状態が得られること
* つまり1度構築したサーバに対して、同じ処理はスキップされる

Ansibleをはじめ、構成管理ツールでは、この冪等性の概念が採用されている

---
## 冪等性の現実

しかし、冪等性を保証するのは難しい!!

* モジュール多い
* 自前のコード読みにくくなる  
  など

![2019-09-24 03.45.26 docs.ansible.com 916e0ba87951.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416178/0921b49b-492e-feb9-16d6-dfa766a9bd1e.png)

(引用 : https://docs.ansible.com/ansible/latest/modules/list_of_all_modules.html)

---

## そもそも冪等なコードとは?

1. **現在の状態** を確認する
2. **在るべき状態** と比較する
3. **状態を変更** する

という **3つのことを同時にやる** 複雑なコード

---

## Submarine.jsのアプローチ

それぞれ別のものとして扱う

1. 現在の状態の確認手段 -> `query`
2. 在るべき状態の定義 -> `test`
3. 状態を移行するための手段 -> `command`

```Correct-server-state-with-ssh.js
const Submarine=require('Submarine');

const CorrectServerState=class extends Submarine {
  query(){
    return {
      file_content: String.raw`
        test -r /tmp/submarine/hogehoge \
          && cat /tmp/submarine/hogehoge \
          || echo 'File not readable' \
            >&2
      `,
    };
  }

  test(r){
    const { stats }=r;

    return {
      file_content_is_hogehoge: stats.file_content === 'hogehoge',
    };
  }

  command(){
    return String.raw`
      mkdir -p /tmp/submarine \
        && echo 'hogehoge' \
          > /tmp/submarine/hogehoge
    `;
  }
 

}


const state=new CorrectServerState({
  conn: 'ssh',
  host: 'localhost',
});
    


state.correct()
  .then(console.log)
  .catch(console.error)
.finally(
  _ => state.close()
);

```

---

## Submarine.jsのアプローチ

状態の `参照` と `変更` を分離する考え方は、他の分野にもある

* オブジェクト指向 -> CQS(コマンド・クエリの分離)  
  https://en.wikipedia.org/wiki/Command–query_separation
* データベース -> CRUD(Create, Read, Update, Delete)
* REST API -> (GET, PUT, DELETE, POST)

---

## Submarine.jsの強み

* コードに秩序が生まれる
* Shellを使っていても、まあまあ見やすい  
  if文が少なくてすむ
* 膨大なモジュールを提供する必要がないのでコア機能の開発に注力できる  
  ユーザの学習コストも下がる
* queryだけ実行、testだけ実行も可能  
  Ansibleはサーバに変更がかかるか **コードを実行するまで分からない**
* バッチ実行前のテストに利用できる

## 他にも Submarine.jsの強み

Node.jsで開発したことにより

* 変数、定数のスコープがつかえる  
  Ansibleでは、ほとんどの変数・定数はグローバル
* classと継承の概念によりDIが可能に
* フロントエンド、サーバサイド、インフラの全てがJavaScriptで開発可能
* TypeScriptと組み合わせて静的型付けも可能

---

## これだけじゃない Submarine.jsの強み

Submarine.jsにしかないユニークな機能も


* Remote-to-remoteのファイルコピー  
  Ansibleではremote-to-local, local-to-remoteと段階を踏む必要がある
* query, test, commandの実行をHTTPエンドポイント化  
  JSON, HTMLでレスポンス可能

![osc19tk-screen3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416178/279a3d41-a9f9-3605-8d34-cec271b2d83d.gif)

---

## Submarine.jsを使ってみよう

* オフィシャルサイト - [https://www.submarinejs.blue](https://www.submarinejs.blue)
* インストール手順 - [https://gitlab.com/mjusui/submarine/tree/latest](https://gitlab.com/mjusui/submarine/tree/latest)
* 全機能のTutrial - [https://gitlab.com/mjusui/submarine/tree/latest/doc/en/Tutrial](https://gitlab.com/mjusui/submarine/tree/latest/doc/en/Tutrial)

![submarinejs.blue.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416178/00d6bd1e-67cd-dc9f-fd94-22693b8e786d.png)


---