SONiCの最新ビルドイメージを取得する

# はじめに

以前 SONiCは公式CIとしてJenkinsによる定期ビルドが用意されていました。それが現在Azure pipelineに置き換わり、Webページを手繰って人間がビルド済みイメージを取得できたとしても、自動取得は難しいのでは? と思っていました。

今回トライしたところ、非公式の外部サービスを経由する形になりますが、自動取得ができましたので共有したいと思います。

# 非公式のイメージ取得用ページ

こちらです。

https://sonic.software/

みていただくとわかるのですが、下記のブランチとプラットフォームの組み合わせで、最後にビルド成功したイメージへのURLが提供されています。

- Branches
  - 202012
  - 202106
  - 202111
  - 202205
  - master
- Platforms
  - Broadcom (ONIE, ABOOT)
  - Mellanox
  - Barefoot
  - Virtual Switch

# Webスクレイピングする?

リンク先にマウスカーソルをかざすとそれぞれのイメージのURLがわかりますが、これはブランチやプラットフォームの情報だけでは生成できないものとわかります。これは埋め込まれてるURL情報をWebスクレイピングで切り出してくるしかないか? と思い、ひとまずWebページのソースコードをみてみました。するとそこには、下記のような記述が。

```JavaScript
fetch('builds.json')
    .then(res => res.json())
    .then((out) => {
	 let d = document.getElementById('builds');
	 for (var key in out) {
	    content = ''
	    if (Object.keys(out[key]).length == 0) {
		    content += '<div class="opacity-25"><i>No known successful builds</i></div>'
	    }
```

お? もしかして`builds.json`になんか書かれてる?

# `builds.json` を眺めてみる

こんなでした。

```json:builds.json
{
  "202012": {
    "sonic-broadcom.bin": {
      "url": "https://artprodcus3.artifacts.visualstudio.com/Af91412a5-a906-4990-9d7c-f697b81fc04d/be1b070f-be15-4154-aade-b1d3bfb17054/_apis/artifact/cGlwZWxpbmVhcnRpZmFjdDovL21zc29uaWMvcHJvamVjdElkL2JlMWIwNzBmLWJlMTUtNDE1NC1hYWRlLWIxZDNiZmIxNzA1NC9idWlsZElkLzE5MjExNy9hcnRpZmFjdE5hbWUvc29uaWMtYnVpbGRpbWFnZS5icm9hZGNvbQ2/content?format=file&subpath=/target/sonic-broadcom.bin",
      "build-url": "https://dev.azure.com/mssonic/build/_build/results?buildId=192117&view=results",
      "build": "192117",
      "date": "2022-12-21T08:00:25.9089741Z"
    },
    "sonic-aboot-broadcom.swi": {
      "url": "https://artprodcus3.artifacts.visualstudio.com/Af91412a5-a906-4990-9d7c-f697b81fc04d/be1b070f-be15-4154-aade-b1d3bfb17054/_apis/artifact/cGlwZWxpbmVhcnRpZmFjdDovL21zc29uaWMvcHJvamVjdElkL2JlMWIwNzBmLWJlMTUtNDE1NC1hYWRlLWIxZDNiZmIxNzA1NC9idWlsZElkLzE5MjExNy9hcnRpZmFjdE5hbWUvc29uaWMtYnVpbGRpbWFnZS5icm9hZGNvbQ2/content?format=file&subpath=/target/sonic-aboot-broadcom.swi",
      "build-url": "https://dev.azure.com/mssonic/build/_build/results?buildId=192117&view=results",
      "build": "192117",
      "date": "2022-12-21T08:00:25.9089741Z"
    },
    "sonic-mellanox.bin": {
```

ブランチと取得したいイメージファイル名がわかれば抽出できそうです。ヨシ！

# URLの抽出

`build.json` を取得するなら`curl`を、JSONの要素を抽出するなら `jq` を。ということで、試してみます。

```shell-session
$ curl https://sonic.software/builds.json | jq -r .master.\"sonic-vs.img.gz\".url
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 14728  100 14728    0     0  11925      0  0:00:01  0:00:01 --:--:-- 11925
https://artprodcus3.artifacts.visualstudio.com/Af91412a5-a906-4990-9d7c-f697b81fc04d/be1b070f-be15-4154-aade-b1d3bfb17054/_apis/artifact/cGlwZWxpbmVhcnRpZmFjdDovL21zc29uaWMvcHJvamVjdElkL2JlMWIwNzBmLWJlMTUtNDE1NC1hYWRlLWIxZDNiZmIxNzA1NC9idWlsZElkLzE5MjEyNC9hcnRpZmFjdE5hbWUvc29uaWMtYnVpbGRpbWFnZS52cw2/content?format=file&subpath=/target/sonic-vs.img.gz
$ 
```

いけました!
このURLを`curl`に与えればイメージファイルを取得できそうです。

# イメージファイルの取得

```shell-session
$ curl -O $(curl -s https://sonic.software/builds.json | jq -r .master.\"sonic-vs.img.gz\".url)
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  964M  100  964M    0     0  7225k      0  0:02:16  0:02:16 --:--:-- 6960k
$ ls -l sonic-vs.img.gz 
-rw-rw-r-- 1 masaru masaru 1011811282 Dec 22 05:12 sonic-vs.img.gz
$ 
```

無事取得できました!

# 注意点

外部サイトから情報を取得するということは、そのサイトが乗っ取られるなどした場合に取得者に被害をもたらす可能性が常にあります。またそうでなくても、非公式のURLだといつ消滅するかはわかりません。自己責任で利用するしかありませんので、このことを頭の片隅に入れておいていただければと思います。

# おわりに

Azure pipelinesのWebページをたどってたどって、という人間が手でやるときの手順をそのままツールでやらせるのかー、大変だなー、と思っていたのですが、存外簡単に取得できました。latestのみですが、環境構築の際に活用いただければ幸いです。