こんにちは、クラウドエース編集部です。
Cloud SQLは便利なサービスですが、比較的費用が高いサービスだと認識しています。
開発環境などでは、夜間は使われることが無いため停止しておいて少しでも節約しようと思ったのが事の発端でした。

最初に書いておくと、この記事はタイトルの内容を実現させる方法を紹介する、というよりはそのためにどのように情報を追ったのかを記載するのが目的です。
これを理解できれば、あらゆるGCPリソースに対して自動で〇〇することが可能になります。

真似しようとする

ところで、Compute Engineインスタンスであれば公式ドキュメントに自動停止/自動起動のためのサンプルがあるので、当初はこれを真似することを考えました。
@google-cloud/compute というパッケージを利用していたので、@google-cloud/sqlがきっとあるからそれを使えば良いと思いましたが、そんなものはありませんでした。
アーキテクチャは同様にしたかったので、Cloud FunctionsからSQLインスタンスに対してリクエストを送ることを考えるとREST APIを叩くしか無さそうだったため https://github.com/googleapis/google-api-nodejs-client を利用することを考えました。

メソッドを調べる

Q. SQLインスタンスを停止させたい時にNodejsのgoogleapisパッケージを利用した場合、どのメソッドを利用すれば良いでしょうか?

という問いに即答できるでしょうか?筆者はできません。
ドキュメントには必ずREST APIのリストがありますので(例えばCloud SQLだったらここ)、推測できればそれでも良いのですが、今回はわからなかったのでまずは gcloud コマンドでどのようにするのかを調べました。

すると、 gcloud sql instances patch というサブコマンドを発見できたので、REST APIでも patch で送れば良いことに検討をつけることができて、https://cloud.google.com/sql/docs/postgres/admin-api/rest/v1beta4/instances/patch へたどり着けます。
あとはparameterとbodyがわかれば良さそうです。

parameterとbodyを調べる

上記のドキュメントのリンクを踏むと、なんとドキュメントからAPIを叩けることに気づきます。
個人的にこういうところがすごくGoogleっぽいです(※ 他のパブリッククラウドは知りません。)
ドキュメントからRequest Bodyを辿ると、なんともまぁたくさんあることがわかります。

https://cloud.google.com/sql/docs/postgres/admin-api/rest/v1beta4/instances#DatabaseInstance

ここからは完全に個人の感覚だと思いますが、一瞥しただけではどのようなbodyを送れば良いのか全然わからなかったので (stateかと思ったら全然違った)、片っ端から調べると https://cloud.google.com/sql/docs/postgres/admin-api/rest/v1beta4/instances#sqlactivationpolicy がそれっぽいことがわかりました。
つまり送るべきRequest Bodyは

{
    settings: {
        activationPolicy: "NEVER",
    }
}

で良いことがわかります。

サラッと書きましたが、Cloud SQLのREST APIリファレンスを読むのは初めてだったので結構時間はかかっています。
あとはドキュメントを参考にコードを書くとざっとこんな感じでしょうか。
(※必要そうなところだけ適当に抜粋)

const {google} = require('googleapis');
const sqladmin = google.sqladmin("v1beta4");

const SQL_INSTANCE = process.env.SQL_INSTANCE;

exports.stopSqlInstance = async (event, context, callback) => {
  try {
    const result = await stopSqlInstance();
    callback();
  } catch (err) {
    callback(err);
  }
}

async function stopSqlInstance() {
  const authClient = await google.auth.getClient({
    scopes: [
      'https://www.googleapis.com/auth/cloud-platform',
      'https://www.googleapis.com/auth/sqlservice.admin',
    ],
  });

  const projectId = await google.auth.getProjectId();

  const body = {
    settings: {
      activationPolicy: "NEVER",
    }
  };
  const result = await sqladmin.instances.patch({
    auth: authClient,
    instance: SQL_INSTANCE,
    project: projectId,
    requestBody: body,
  });
  return result.data;
}

SQLインスタンス名は可変にするために環境変数に設定しました。
PubSubのメッセージでも良いと思います。

あとはCompute Engineと同じようにCloud SchedulerやCloud PubSubを設定してCloud Functionsにデプロイすれば終わりです。

今回筆者にとって収穫だったのは、これで事実上ほぼ全てのリソースをCloud Functionsから操作する方法を理解できたことにあります。