特定組織の全プロジェクトをリストするbashスクリプト

記事タイトルとURLをコピーする

G-gen の杉村です。特定の Google Cloud 組織配下にあるすべてのプロジェクトを取得する bash スクリプトを紹介します。

はじめに

概要

当記事で紹介するのは、指定した Google Cloud 組織またはフォルダの配下にあるすべてのプロジェクトの一覧を CSV ファイルに出力するためのスクリプトです。当スクリプトを使うことで、特定の Google Cloud 組織やフォルダ配下の全プロジェクトを一覧化することができます。

前提として、gcloud コマンドを使うと、自分のアカウントが get/list 権限を持つプロジェクトの一覧が取得できます。

gcloud projects list`

しかしこのコマンドでは、もし自分が複数の組織に対して権限を持っている場合、すべての組織配下のプロジェクトが一覧表示されてしまいます。特定の組織のみに所属するプロジェクトを一覧表示したい場合、少し工夫したスクリプトを書く必要があります。

前提条件

当 bash スクリプトは、Debian GNU/Linux 12 (bookworm) 上で開発され、動作確認されています。

また、以下のソフトウェアがインストールされていることが前提です。括弧内は開発時のバージョンです。

  • gcloud(Google Cloud SDK 488.0.0
  • jq (jq-1.6

また実行時は、gcloud コマンドの認証情報に、フォルダやプロジェクト一覧表示権限を持つ Google アカウントが設定されている必要があります。

免責事項

当記事で紹介するプログラムのソースコードは、ご自身の責任のもと、使用、引用、改変、再配布して構いません。

ただし、同ソースコードが原因で発生した不利益やトラブルについては、当社は一切の責任を負いません。

ソースコード

当ソースコードは、前述の 免責事項 をご理解のうえ、ご利用ください。

list_projects.sh

#!/bin/bash
  
# 引数チェック
if [ $# -ne 2 ]; then
  echo "ERROR : Please specify parent resource's ID and resource type (folder/organization)."
  echo "usage : $0 (resouce_id) (resource_type)"
  exit 1
fi
  
# 変数定義
root_parent_id=$1
root_parent_type=$2
datetime=`date "+%Y%m%d%H%M"`
file_name="projects_${datetime}.csv"
  
# 引数が想定した値であることをチェック
if [ "${root_parent_type}" != "organization" -a "${root_parent_type}" != "folder" ]; then
  echo "ERROR : resource_type must be (folder/organization)."
  echo "usage : $0 (resouce_id) (resource_type)"
  exit 1
fi
  
# フォルダを再帰的に取得する関数
function get_folders() {
  local parent_id=$1
  local resource_type=$2
  local depth=$3
  local next_depth=$(( ${depth} + 1 ))
  
  echo "Processing... parent_id: ${parent_id}, resource_type: ${resource_type}, depth: ${depth} " > `tty`
  
  if [ ${resource_type} == "organization" ]; then
    folders_result=`gcloud resource-manager folders list --format=json --organization=${parent_id}`
  elif [ ${resource_type} == "folder" ]; then
    folders_result=`gcloud resource-manager folders list --format=json --folder=${parent_id}`
  fi
  
  # system-gsuite フォルダを除外
  folders=`echo ${folders_result} | jq -r '.[] | select(.displayName != "system-gsuite") | .name' | cut -d / -f 2`
  
  if [ -n "${folders}" ]; then
    echo "${folders}"
  fi
  
  for folder in ${folders}; do
    get_folders ${folder} folder ${next_depth}
  done
  
  return 0
}
  
echo "Processing... root_parent_id: ${root_parent_id}, root_parent_type: ${root_parent_type}"
  
# プロジェクト一覧取得
projects=`gcloud projects list --format=json`
if [ $? -ne 0 ]; then
  echo "ERROR : gcloud projects list command finished with error."
  exit 1
fi
  
folder_ids=`get_folders ${root_parent_id} ${root_parent_type} 1`
LF=$'\n' root_and_folder_ids="${root_parent_id}${LF}${folder_ids}"
  
# 特定組織(フォルダ)の配下のみ抽出
for parent in ${root_and_folder_ids}; do 
  target_projects+=(`echo ${projects} |  jq -r ".[] | select(.parent.id == \"${parent}\") | .projectId"`)
done
  
# ソートしてファイルに書き込み
printf "%s\n" "${target_projects[@]}" | sort | tee -a ${file_name}
  
# スクリプト終了
echo "--------------------------------"
echo "${file_name} was generated."
ls -la "${file_name}"
  
exit 0

出力例

以下のようなテキストファイルが出力されます。

my-project-01
my-project-02
my-project-03

実行方法

入力情報の準備

まず、プロジェクトを一覧化したい組織やプロジェクトのリソース ID を確認します。リソース ID は、10桁〜13桁程度の数字です。

適切な権限を持っていれば、Google Cloud コンソールの「リソースの管理(Manage Resources)」画面から確認できます。

組織のリソース ID(組織 ID)を調べる方法については、以下でも詳細に説明されています。

blog.g-gen.co.jp

スクリプトの実行

その後、以下のようにスクリプトを実行します。

第1引数の 123456789012 は、組織やフォルダのリソース ID に置き換えてください。第2引数は、組織の場合は organization を、フォルダの場合は folder を指定してください。

./listl_projects.sh 123456789012 organization

ソースコードの説明

ネストされたフォルダ ID の取得

ソースコードの48行目では、gcloud projects list --format=json を実行し、Google アカウントが表示権限を持つすべてのプロジェクトの情報を JSON 形式で一括取得しています。

しかしこの JSON には、表示権限を持つすべてのプロジェクトの情報が格納されます。JSON は、以下のようなフォーマットです。

[
  {
    "createTime": "2024-08-22T03:15:08.530Z",
    "lifecycleState": "ACTIVE",
    "name": "my-project-01",
    "parent": {
      "id": "3456789xxx",
      "type": "organization"
    },
    "projectId": "my-project-01",
    "projectNumber": "123456789xxx"
  },
  {
    "createTime": "2024-08-28T11:22:45.210Z",
    "lifecycleState": "ACTIVE",
    "name": "my-project-02",
    "parent": {
      "id": "234567890xxx",
      "type": "folder"
    },
    "projectId": "my-project-02",
    "projectNumber": "987654321xxx"
  },
...
]

JSON 内の parent.id というキーには、そのプロジェクトの親リソース(組織やフォルダ)のリソース ID が格納されています。

組織の直下にあるプロジェクトは、parent.id が組織のリソース ID になります。またフォルダの中にあるプロジェクトは、parent.id がフォルダのリソース ID になります。そのため、組織の配下にあるすべてのプロジェクトを抽出するには、組織 ID と、すべてのフォルダのリソース ID でフィルタする必要があります。

当スクリプトでは、get_folders() 関数(17行目から定義)で、フォルダ内にネストしているフォルダを含めて、すべてのフォルダの ID を再帰的に取得しています。そして、取得したフォルダ ID を使ってすべてのプロジェクトを抽出します。これにより、組織配下のすべてのプロジェクトをリストアップします。

当スクリプトを実行すると以下のように処理経過が画面に出力されます。これは、ネストされたフォルダ内のフォルダのリソース ID を取得している様子を表しています。

Processing... root_parent_id: 3456789xxx, root_parent_type: organization
Processing... parent_id: 3456789xxx, resource_type: organization, depth: 1 
Processing... parent_id: 234567890xxx, resource_type: folder, depth: 2 
Processing... parent_id: 567890123xxx, resource_type: folder, depth: 3
...

depth は、スクリプト実行時に引数で与えた最初の組織またはフォルダを1として、ネストの深さを示しています。

システムに生成されたプロジェクトの除外

組織配下には、システムによって自動生成されたプロジェクトが存在する場合があります。

system-gsuite フォルダ配下の apps-script フォルダ内には、sys- で始まる ID のプロジェクトが格納されています。これは、Google Apps Script によって作成されたプロジェクトです。

また system-gsuite フォルダ配下の appsheet フォルダ内には、app- で始まる ID のプロジェクトが格納されています。これは、App Sheet によって作成されたプロジェクトです。

これらのプロジェクトを除外するため、get_folders() 関数内のソースコード32行目で、system-gsuite という表示名のフォルダは除外しています。

注意点

実行する Google アカウントで表示できるプロジェクトの数が多すぎる場合は、gcloud projects list コマンドが失敗する場合があります。

その場合、--page-size オプションを指定してレスポンスを制限する必要がありますが、当スクリプトはそのような場合には対応していません。--page-size オプションを指定しなかった場合、デフォルト値は unlimited であり、すべての結果が返されます。

杉村 勇馬 (記事一覧)

執行役員 CTO / クラウドソリューション部 部長

元警察官という経歴を持つ現 IT エンジニア。クラウド管理・運用やネットワークに知見。AWS 12資格、Google Cloud認定資格11資格。X (旧 Twitter) では Google Cloud や AWS のアップデート情報をつぶやいています。