Finch を簡単なコードでまとめてみた（自作）

## Finch を自作してみた

最近 AWS が OSS と公開した Finch ですが、その Finch のソースコードを追ってみたら、`nerdctl` と `limactl` をコマンドで叩いているだけの簡単な CLIアプリ に見えました。
なので、そのコードを Javascript で再現してみました。

Finch の大まかな内容は、

https://qiita.com/yoshii0110/items/692018729b5b2f41b9ac

Finch のソースコードの説明は、

https://qiita.com/YmBIgo/items/96218278f40ec0f3d83b

にあります。

## 使い方

まずは、

https://github.com/YmBIgo/mini-finch/blob/master/requirement.bash

の内容を、

```bash
source requirement.bash
```

でインストールします（現状は lima だけですが、今後も増えるかもしれないので...）。

Finch は CLI ということで、自作では node で 動く CLI アプリのようなものにしました。
利用方法は、`finch vm init` が、

```
npm start vm init
```

`finch vm stop` が

```
npm start vm stop
```

`finch run --rm public.ecr.aws/finch/hello-finch` のような docker ライクな nerdctl コマンドが

```
npm start run --rm public.ecr.aws/finch/hello-finch
```

のように、`docker` の代わりに `npm start` を入れれば入力できるようになっています。

## 実装

コードは

https://github.com/YmBIgo/mini-finch/blob/master/index.js

にあります。

<details><summary>ソースコード</summary>

```javascript
/**
 * Usage
 * 
 * npm start vm [start/stop/remove/init]
 * npm start [build/run/commit/ps/image/run...] 
 * 
 */

const { exec } = require("child_process")

const [, , ...AllArgs] = process.argv
const nerdctlCommands = [
  'build',   'builder',   'commit',
  'compose', 'container', 'create',
  'events',  'exec',      'history',
  'image',   'images',    'info',
  'inspect', 'kill',      'load',
  'login',   'logout',    'logs',
  'network', 'pause',     'port',
  'ps',      'pull',      'push',
  'restart', 'rm',        'rmi',
  'run',     'save',      'start',
  'stats',   'stop',      'system',
  'tag',     'top',       'unpause',
  'update',  'volume',    'wait'
]
const limactlCommands = ["start", "stop", "remove", "init"]

if (AllArgs.length === 0) {
	console.error("Please pass argument.")
	process.exit(1)
}

const firstArg = AllArgs[0]

if (firstArg !== "vm" && nerdctlCommands.indexOf(firstArg) === -1 ) {
	console.log("Please pass correct argument.")
	process.exit(1)
}

if (AllArgs[0] === "vm") {
	const secondArg = AllArgs[1]
	if (secondArg === undefined) {
		console.log("Please pass correct argment")
		return
	}
	let limaCommand = ""
	switch (secondArg) {
		case 'start':
			console.log("vm starting...")
			console.log("結果が出てくるのに、数分かかります。")
			limaCommand = joinLimactlArray([secondArg, "mini-finch"])
			break;
		case 'stop':
			console.log("vm stopping...")
			limaCommand = joinLimactlArray([secondArg, "mini-finch"])
			break;
		case 'remove':
			console.log("vm removing...")
			limaCommand = joinLimactlArray([secondArg, "mini-finch"])
			break;
		case 'init':
			console.log("vm initing...")
			console.log("結果が出てくるのに、数分かかります。")
			limaCommand = joinLimactlArray(["start", "--name=mini-finch", "./finch.yaml", "--tty=false"])
			break;
		default:
			console.log("Please pass correct argment")
			return;
	}
	console.log(limaCommand)
	execCommand(limaCommand)
} else {
	const limaCommand = joinNerdctlArray(AllArgs)
	console.log(limaCommand)
	execCommand(limaCommand)
}

function joinNerdctlArray(array) {
	const limactlArray = ["limactl", "shell", "mini-finch", "nerdctl"]
	const limaCommand = limactlArray.concat(array)
	return limaCommand.join(" ")
}

function joinLimactlArray(array) {
	const limactlArray = ["limactl"]
	const limaCommand = limactlArray.concat(array)
	return limaCommand.join(" ")
}

function execCommand(command) {
	exec(command, (err, stdout, stderr) => {
		if (err) { 
			console.log(`error: ${stderr}`)
			return
		}
		console.log(`output: ${stdout}`)
	})
}
```

</details>

簡単に書いただけなので、間違っている部分などあったら指摘いただければと思います。