macOS Big Sur にアップデート

Big Sur がリリースされてから10日。2013 - 2014 の 13インチ MacBook Pro では起動しなくなる問題がある模様です。

support.apple.com

一応2015年モデルだし他に大きな不具合もなさそうということで、アップデートすることにしました。

f:id:kondoumh:20201122072428p:plain

ダウンロードは20分ぐらいでした。

f:id:kondoumh:20201122075126p:plain

真っ黒のインストール画面になって40分ぐらいで起動してきました。ダイアログの色味がちょっと茶色がかった気がします。

f:id:kondoumh:20201122090113p:plain

左が Catalina 右が Big Sur の Dock ですが角丸のラジアンが少し大きくなり画面端に少し隙間ができました。Safari、ターミナル、システム環境設定、スティッキーズなど組み込みアプリのアイコンも角丸になりました。

f:id:kondoumh:20201122093431p:plain

BetterTouchTool や Karabiner-Elements はそのまま動作しました。

Docker for Desktop も Big Sur 対応のアップデートを適用して Kubernetes と共に問題なく動作。

f:id:kondoumh:20201122093845p:plain

Yosemite に始まり Sierra ⇨ High Sierra ⇨ Mojave ⇨ Catalina ⇨ Big Sur とアップデートしてきました。来年は Apple Silicon の Mac に移行してるかな?

Octokit で GitHub repo からファイルの中身を取得する

GitHub では Octokit という API クライアントが提供されています。

github.com

GitHub の REST API は fetch でも叩けますが、octokit/rest が使いやすくラップしてくれてます。

リポジトリ内のファイルの中身は getContent で取得して Base64 デコードするだけで取れます。

const { Octokit } = require("@octokit/rest");

(async () => {
  const octokit = new Octokit();
  const content = await octokit.repos.getContent({
    owner: "kondoumh",
    repo: "mtwe",
    path: "README.md"
  });
  const data = new Buffer.from(content.data.content, content.data.encoding).toString();
  console.log(data);
})();

1MB を超えるファイルは Contents API では取れなくて Blob API を使う必要があります。まず対象ファイルの SHA を取得し、取得した SHA を指定して git.getBlob メソッドで blob を取得するという2段回になります。SHA はファイル名では取れないので、親ディレクトリ (下記の例では src ディレクトリ) を指定して getContent して得られたファイルリストから目的のファイル名で絞り込みます。

const { Octokit } = require("@octokit/rest");
const jq = require("node-jq");

(async () => {
  const octokit = new Octokit();
  const files = await octokit.repos.getContent({
    owner: "kondoumh",
    repo: "sbe",
    path: "src"
  });
  const data = await jq.run('.data | map(select(.name == "renderer.js")) | .[0].sha', files, {input: 'json'});
  const sha = data.replace(/['"]+/g, '');
  const blob = await octokit.git.getBlob({
    owner: "kondoumh",
    repo: "sbe",
    file_sha: sha
  });
  const content = new Buffer.from(blob.data.content, blob.data.encoding).toString();
  console.log(content);
})();

ファイルリストからの抽出に jq のラッパー node-jq を使いました。2回のクエリが必要だし、SHA 1個取るのに全ファイルのデータを取得してるので非効率ですね。

こういう用途ではやはり GraphQL を使った方がよさそうです。GraphQL 用の octokit/graphql も提供されてます。上記のファイルの中身を GraphQL で取得してみます。

const { graphql } = require("@octokit/graphql");

(async() => {
  const graphqla = graphql.defaults({
    headers: {
      authorization: `token ${process.env.GH_TOKEN}`,
    },
  });
  const { repository } = await graphqla(`
    {
      repository(owner: "kondoumh", name: "sbe") {
        content:object(expression: "master:src/renderer.js") {
          ... on Blob {
            text
          }
        }
      }
    }
  `);
  console.log(repository.content.text);
})();

GraphQL API は public repo でも認証情報が必須です。対象のファイルパスを expression で指定して一発で取れました。Base64 変換も不要。便利ですね。

GitHub リポジトリをバックエンドのデータストアとして Web アプリなどを作ることも可能ですね。

Windows Terminal で SSH 接続先毎に Profile を作る

仕事用マシンがようやく Windows 10 1909 (November 2019 Update) に更新されました。

これまで SSH するとき Git Bash や Cygwin を mintty で使ってました。タブ機能がないので接続先毎にウィンドウが散らばりますし、 コマンド実行時に横幅が足りなくて表示が崩れた時にウィンドウをリサイズしても改行位置はそのままです*1

ということで待望の Windows Terminal を導入しました。

Git Bash の設定。Campbell という標準的なカラースキーマを指定。フォントは Windows Terminal 標準の固定ピッチフォント Cascadia code を指定。

{
  "profiles": [
    {
      "guid": "{c0a23c69-addf-41c8-a214-dc4af501d7ec}",
      "name": "Git bash",
      "acrylicOpacity": 0.70,
      "closeOnExit": true,
      "colorScheme": "Campbell",
      "commandline": "C:\\Program Files\\Git\\bin\\bash.exe --login -i",
      "cursorColor": "#FFFFFF",
      "cursorShape": "bar",
      "fontFace": "cascadia code",
      "fontSize": 12,
      "historySize": 9001,
      "icon" : "C:\\Program Files\\Git\\mingw64\\share\\git\\git-for-windows.ico",
      "padding": "0, 0, 0, 0",
      "snapOnInput": true,
      "startingDirectory": "C:\\Users\\kondoh",
      "useAcrylic": true
    },
}

起動したところ。

f:id:kondoumh:20201022224648p:plain

仕事では複数のマシンに SSH 接続する必要があります。Windows Terminal に 接続先ごとに Profile を作ればメニューから一発で接続できます。

SSH 用の Profile。commandline に接続先を含めた SSH コマンドを指定。カラースキーマは Solarized Dark でフォントは oh-my-zsh に適した Source Code Pro for Powerline を指定してみました。

{
  "profiles": [
    {
      "guid": "{73DB597C-2D03-4BCE-9D9C-9DB0294BEC6C}",
      "name": "SSH to Mac",
      "acrylicOpacity": 0.70,
      "closeOnExit": true,
      "colorScheme": "Solarized Dark",
      "commandline": "ssh masa@10.0.1.4",
      "cursorColor": "#FFFFFF",
      "cursorShape":"filledBox",
      "fontFace": "Source Code Pro for Powerline",
      "fontSize": 12,
      "historySize": 9001,
      "icon": "C:\\Users\\kondoh\\Pictures\\Windows_Terminal_Logo_256x256.png",
      "padding": "0, 0, 0, 0",
      "snapOnInput": true,
      "useAcrylic": true
    },
}

起動したところ。

f:id:kondoumh:20201022224711p:plain

接続先によってカラースキーマを変えればオペミス防止にもなります。

ウィンドウ幅が足りずに kubectl の結果が崩れても

f:id:kondoumh:20201024095118p:plain:w300

リサイズすれば整形されます。

f:id:kondoumh:20201024095135p:plain

これで、快適なターミナル生活を送れます。

*1:コマンドプロンプトですら整形されるのに・・

Kubernetes ネイティブなカオスエンジニアリングツール Chaos Mesh を使ってみる

Netflix が提唱した耐障害テスト技法 Chaos Engineering。実行環境に実際に障害を発生させてアプリケーションの復旧をテストする方法です。

Chaos Mesh は Kubernetes クラスターで稼働するアプリケーションをターゲットに Chaos Engineering テストを実行できるツールです。CNCF でホストされており、最近 v1.0 に到達しました。

chaos-mesh.org

以下のような障害発生の Experiment を実施できます。

  • PodChaos : Pod に定期的にエラーを発生させたり、Kill したりする
  • NetworkChaos : Pod のネットワークを遮断したり、遅延やロスを発生させる
  • StressChaos : Pod に負荷をかける
  • TimeChaos : 時刻取得のシステムコールを置き換えて時刻同期を狂わせる
  • IOChaos : IO エラーを発生させる
  • KernelChaos : Linux Kernel レベルのエラーを発生させる (デフォルトでは無効化されておりプロダクション環境での使用は禁止)

v1.0.1 現在、素の Pod への Chaos 注入はサポートされておらず、deployment, statefulset, daemonset が対象とのことです。

Docker Desktop for Mac の Kubernetes 環境で動かしてみました。

ドキュメントにしたがって、インストール*1

% curl -sSL https://mirrors.chaos-mesh.org/v1.0.1/web-show/deploy.sh | sh

Install Chaos Mesh chaos-mesh
   :
Waiting for pod running
Chaos Mesh chaos-mesh is installed successfully

無事デプロイされ、namespace chaos-testing に次のような Pod や Service が起動しました。

% kubectl -n chaos-testing get po,svc,deploy
NAME                                            READY   STATUS    RESTARTS   AGE
pod/chaos-controller-manager-86c96f985f-pvjcv   1/1     Running   0          11m
pod/chaos-daemon-9n9mb                          1/1     Running   0          11m
pod/chaos-dashboard-5d8dff7df9-5hp6h            1/1     Running   0          11m

NAME                                    TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                       AGE
service/chaos-dashboard                 NodePort    10.97.228.5      <none>        2333:31287/TCP                11m
service/chaos-mesh-controller-manager   ClusterIP   10.106.150.179   <none>        10081/TCP,10080/TCP,443/TCP   11m

NAME                                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/chaos-controller-manager   1/1     1            1           11m
deployment.apps/chaos-dashboard            1/1     1            1           11m

次のような CRD (Custom Resource Definition) が適用されています。IO, Kernel, Network, Pod, Pod Network, Stress, Time などの Chaos type があるのがわかります。

% kubectl get crd
NAME                             CREATED AT
iochaos.chaos-mesh.org           2020-10-22T15:03:17Z
kernelchaos.chaos-mesh.org       2020-10-22T15:03:18Z
networkchaos.chaos-mesh.org      2020-10-22T15:03:18Z
podchaos.chaos-mesh.org          2020-10-22T15:03:18Z
podiochaos.chaos-mesh.org        2020-10-22T15:03:18Z
podnetworkchaos.chaos-mesh.org   2020-10-22T15:03:18Z
stresschaos.chaos-mesh.org       2020-10-22T15:03:18Z
timechaos.chaos-mesh.org         2020-10-22T15:03:18Z

Network chaos を引き起こすサンプルマニフェスト。NetworkChaos という CRD として適用され、10ms のレイテンシを web-show というラベルの Pod に 60秒毎に30秒の間発生させます。

apiVersion: chaos-mesh.org/v1alpha1
kind: NetworkChaos
metadata:
  name: web-show-network-delay
spec:
  action: delay # the specific chaos action to inject
  mode: one # the mode to run chaos action; supported modes are one/all/fixed/fixed-percent/random-max-percent
  selector: # pods where to inject chaos actions
    namespaces:
      - default
    labelSelectors:
      "app": "web-show"  # the label of the pod for chaos injection
  delay:
    latency: "10ms"
  duration: "30s" # duration for the injected chaos experiment
  scheduler: # scheduler rules for the running time of the chaos experiments about pods.
    cron: "@every 60s"

ターゲットとなる web-show アプリをデプロイ。これは、kube-system Pod に ping してレイテンシーを表示する React アプリです。

% curl -sSL https://mirrors.chaos-mesh.org/v1.0.1/web-show/deploy.sh | sh
service/web-show created
deployment.apps/web-show created
 :
Waiting for pod running

localhost:8081 に接続するとこんな感じで、レイテンシーの推移が表示されます。

f:id:kondoumh:20201023080812p:plain

この状態で先ほどの Network Chaos のサンプルを apply してみます。

% kubectl apply -f network-delay.yaml

Network Chaos の引き起こしたレイテンシが一定間隔で発生しているのが見て取れます。

f:id:kondoumh:20201023083219p:plain

Chaos Mesh のダッシュボードは Node Port で公開されているため port-forward して画面を表示します。

% kubectl port-forward -n chaos-testing svc/chaos-dashboard 2333:2333
Forwarding from 127.0.0.1:2333 -> 2333
Forwarding from [::1]:2333 -> 2333

localhost:2333 に接続するとダッシュボードが表示され、適用中の Experiment (この場合は Network Chaos) が確認できます。

f:id:kondoumh:20201023083729p:plain

タイムラインや詳細情報を閲覧できます。

f:id:kondoumh:20201023084221p:plain

f:id:kondoumh:20201023084243p:plain

このように Chaos Mesh はターゲットの Kubernetes アプリケーションに対して様々な障害を注入することで耐障害性をテストすることができます。ダッシュボードも見やすくて完成度が高い印象です。リリース前のシステムテストなどに組み込めば、アプリケーションのウィークポイントを発見したり、運用時の障害復旧のリハーサルにも活用できそうです。

*1:Helm でも導入可能です。

リモートワーク時代のスマホ活用 - Pixel + ThinkPad TrackPoint Keyboard

リモートワークになって、Pixel 3 XL の稼働率が如実に下がりました。外出しない日はほぼ電話を受けるだけなので、バッテリーもあまり減りません。

ところで、数ヶ月前に買った ThinkPad TrackPoint Keyboard 2

blog.kondoumh.com

最初は ThinkPad ファンとしてのノスタルジーもあって喜んで使ってたのですが、Ctrl キーが押しづらく長時間使ってると小指がつるようになり*1、結局 REALFORCE に回帰してしまいました。

サブマシンに iPad Pro + Trackpad + Magic Keyboard 使ってたのですが、奥さんが iPad Pro を再び使い始めたので TrackPoint Keyboard と Pixel 3 XL をペアリングしてみました。TrackPoint Keyboard 2 には Android 用のスイッチが用意されていて問題なく設定できました。

Nexus 6P を使ってた時に PC 用のキーボードを Bluetooth でペアリングできるデバイスを使ってたりしてたので、なんとなく使用感はわかっていました。

blog.kondoumh.com

Pixel 3 XL 買った直後は Termux + 物理キーボードでコード書いたりしてたし。

blog.kondoumh.com

信頼できるデバイスに登録することで、指紋センサーに触らなくてもロック解除できます。TrackPoint がポインティングデバイスになるので画面にタッチせずに操作も可能。

Zoom 会議も ペアリングしてる完全ワイヤレスのヘッドセットでこなせてシンプルになりました*2。画面小さいけど YouTube もランドスケープ&スレテオで普通に見れますし YouTube Music も流しっぱなしでいけます。ということでしばらく Pixel 3 XL を仕事中のサブマシンとして使っていこうと思います。

f:id:kondoumh:20201012225541j:plain

*1:CapsLock ももちろん Ctrl キーに割り当ててました・・が、Ctrl キーは小指の肉球で押す派なので・・。

*2:会議中に電話がなるとプチパニックになってしまいますが

野良 Scrapbox アプリ - プロジェクトを選択してページ一覧を開く UI

野良 Scrapbox アプリのページ一覧は Scrapbox のプロジェクトページよりも素早く開いて見通しがいいのですが、開くには対象のプロジェクトのページを開いておく必要がありました。なので、まずプロジェクトのホームかプロジェクト内の任意のページを開いてからページ一覧を開くという2ステップが必要でした。また、複数プロジェクトのページを開いている場合はアクティブなタブのプロジェクトの一覧が開かれるという仕様にしているため、どのプロジェクトのページ一覧が開くのか直観的に分かりづらい問題がありました*1

そこで、プロジェクトのページを開くたびにプロジェクト名の履歴を残しておき、セレクトボックスから直接ページ一覧画面を開くことができる UI を追加しました。

favs や History と同じ感じのセレクトボックス。

f:id:kondoumh:20200924125227p:plain

一度開いたプロジェクトが列挙されてます。

f:id:kondoumh:20200924125246p:plain

選択したプロジェクトのページ一覧が表示されます。

f:id:kondoumh:20200924125301p:plain

ということで v2.0.0 リリース。

Release v2.0.0 · kondoumh/sbe · GitHub

*1:プロジェクトを1個だけ扱ってる場合はさほど気になりませんが。

GitHub CLI 1.0 がリリースされたので使ってみる

GitHub の CLI 1.0 がリリースされました。

github.blog

macOS だと brew でインストールできます。

% brew install gh
Updating Homebrew...
==> Auto-updated Homebrew!

==> Downloading https://homebrew.bintray.com/bottles/gh-1.0.0.catalina.bottle.ta
==> Downloading from https://d29vzk4ow07wi7.cloudfront.net/77b42bd6b610134ee3b40
  :
==> Summary
🍺  /usr/local/Cellar/gh/1.0.0: 60 files, 16.2MB

gh auth login で対話的に認証設定ができます。Personal Access Token を使って認証するようにしました。reporead:org へのアクセスを許可した Token を指定する必要があります。

% gh auth login
? What account do you want to log into? GitHub.com
- Logging into github.com
? How would you like to authenticate? Paste an authentication token

Tip: you can generate a Personal Access Token here https://github.com/settings/tokens
The minimum required scopes are 'repo' and 'read:org'.
? Paste your authentication token: ****************************************
? Choose default git protocol SSH
- gh config set -h github.com git_protocol ssh
✓ Configured git protocol
✓ Logged in as kondoumh

ドキュメントは以下。

cli.github.com

Core commands として gist, issue, pr, release, repo のサブコマンドが、Additional commands として上記の auth や config, help などの補助的なサブコマンドが提供されています。

CORE COMMANDS
  gist:       Create gists
  issue:      Manage issues
  pr:         Manage pull requests
  release:    Manage GitHub releases
  repo:       Create, clone, fork, and view repositories

ADDITIONAL COMMANDS
  alias:      Create command shortcuts
  api:        Make an authenticated GitHub API request
  auth:       Login, logout, and refresh your authentication
  completion: Generate shell completion scripts
  config:     Manage configuration for gh
  help:       Help about any command

ローカルに Clone したリポジトリのディレクトリに移動して、gh release を使うとリリース一覧 や個別のリリースの ChangeLog や Assets を見ることができます。

f:id:kondoumh:20200920190935p:plain

release listrelease view などの サブコマンドに --web (-w) フラグをつけると Web ブラウザで該当ページを開きます。

% gh release view v1.9.0 -w
Opening github.com/kondoumh/sbe/releases/tag/v1.9.0 in your browser.

repo サブコマンドでは、clone や create ができますし、repo view でテキストブラウザ的に Terminal で リポジトリの README を閲覧できます。

f:id:kondoumh:20200920194424p:plain

サブコマンドの使い方を調べるには gh help issue list のように help を挟めば usage がプリントされます。

% gh help issue list
List and filter issues in this repository

USAGE
  gh issue list [flags]

FLAGS
  -a, --assignee string    Filter by assignee
  -A, --author string      Filter by author
  -l, --label strings      Filter by labels
  -L, --limit int          Maximum number of issues to fetch (default 30)
      --mention string     Filter by mention
  -m, --milestone number   Filter by milestone number or `title`
  -s, --state string       Filter by state: {open|closed|all} (default "open")
  -w, --web                Open the browser to list the issue(s)

INHERITED FLAGS
      --help              Show help for command
  -R, --repo OWNER/REPO   Select another repository using the OWNER/REPO format

EXAMPLES
  $ gh issue list -l "help wanted"
  $ gh issue list -A monalisa
  $ gh issue list --web
  $ gh issue list --milestone 'MVP'

ここでは、list や view などの参照系コマンドだけしか示してませんが、issue や Release や PR などを create したり delete したりする更新系のコマンドも利用できます。GitHub のページで Chrome のタブがいっぱいになりがちなので、CLI と Web をうまく使い分けられると効率が上がりそうですし、自動化にも役立ちそうです。Actions のサブコマンドも提供されるとよいと思いました。

Additonal commands として api があります。GitHub API を最初から認証された状態で呼び出せます。

% gh api repos/kondoumh/sbe/releases

curl で呼び出すのに比べると https://api.github.com という固定の base url を省略できたり、認証トークンを ヘッダーに渡す手間が省けるのでこれも便利だと思います。