アノテーション株式会社のあのふじたです。
最近、様々なプロダクトごとのEOL情報をまとめたサイト「endoflife.date」 を知りました。
このサイトのAPIを利用して、EOL情報を取得し、Googleスプレッドシートで一覧化してみたいと思います。
endoflife.date とは
endoflife.date は、様々な製品のEOL日付とサポートライフサイクルを文書化しているサイトです。
API のページ
APIの詳細は以下のリンクから確認できます。
API ドキュメント
現時点では3つのエンドポイントが説明されています。
- Get All Details
- Single cycle details
- All Products
All Products エンドポイントを使うと、全プロダクトの情報が取得できます。
全プロダクト情報
Get All Details は特定のプロダクトの全情報を
Single cycle details は特定のプロダクトの1つのリリースサイクルの情報を取得できます。
スプレッドシートの構成
全てのプロダクト一覧を取得するのは All Products エンドポイントで一発ですが、現在 309 プロダクトをトラックしているようです。必要なプロダクトのみに絞ってEOL情報を取得したいですね。
以下のようなシート構成にします。
- Productsシート: All Productsリクエストで取得したプロダクト一覧を記載
- GetProductsListシート: トラックしたいプロダクトを選別
- EOLシート: GetProductsListシートのプロダクト一覧を元に、Get All Detailsを複数回実行しEOL情報を記載
- Logsシート: 定期実行を前提に実行ログを記載
- Diffシート: 更新があった際の差分を記載
1. プロダクト一覧をシートに記載するスクリプト
まずは All Products へのリクエスト結果をスプレッドシートに記載するGoogle App Scriptを作成します。
拡張機能 > App Script からプロジェクトを立ち上げ、コード.gs を getAllProducts.gs に書き換えて以下のコードを記載します。
function writeToProdutsSheet() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName('Products') || ss.insertSheet('Products');
const url = 'https://endoflife.date/api/all.json';
const options = {
'method': 'GET',
'headers': {'Accept': 'application/json'},
'muteHttpExceptions': true // 例外をミュートにする
};
// データを取得してパースします
let response, data;
try {
response = UrlFetchApp.fetch(url, options);
// 正常なレスポンスを確認します
if (response.getResponseCode() === 200) {
data = JSON.parse(response.getContentText());
// スプレッドシートに書き込む前にデータを加工します
const dataArray = data.map((item, index) => [index + 1, item]);
// スプレッドシートの A1 セルからデータを書き込みます
const range = sheet.getRange(1, 1, dataArray.length, 2); // 行数と列数を指定します
range.setValues(dataArray);
} else {
throw new Error('非正常なレスポンス: ' + response.getResponseCode());
}
} catch (error) {
Logger.log(error.message);
}
}
実行を押すとアクセス権限のポップアップがでますが、承認し実行します。
シート[Products] で有効化したいプロダクトのC列に enable を入力しておきます。入力規則で enable を入力しやすくしておくのも良いかと思います。
今回は amazon と aws が含まれたプロダクトのみにします。
2. トラックしたいプロダクトのみに選別するシートの設定
GetProductListシートのA1にquery関数でProductsシートでenableとなった行のみ抽出します。
A1に =query(Products!A1:C500,"select A, B, C where C='enable'")
と入力します。
以下のように抽出されます
- amazon-cdk
- amazon-corretto
- amazon-eks
- amazon-glue
- amazon-linux
- amazon-neptune
- amazon-rds-mysql
- amazon-rds-postgresql
- aws-lambda
3. GetProductListシートからプロダクト一覧を取得し各プロダクトのEOL情報や差分をシートに記載する
EOL情報を記載する GoogleAppScript を作成します。
+をクリックしてスクリプトを追加し、コード.gs を getGetAllDetails.gs に書き換えて以下のコードを記載します。
function writeToEolSheet() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const eol_sheet = ss.getSheetByName('EOL');
const eoldiff_sheet = ss.getSheetByName('Diff') || ss.insertSheet('Diff'); // 差分シートがなければ作成
const logs_sheet = ss.getSheetByName('Logs') || ss.insertSheet('Logs'); // ログシートがなければ作成
const headers = ["Products", "Cycle", "Release Date", "EOL", "Latest", "latestReleaseDate", "LTS", "Support", "Discontinued", "Link"];
// 現在のデータを一時的に保存
const currentDataRange = eol_sheet.getDataRange();
const currentData = currentDataRange.getValues();
// データのみをクリア(フォーマットは保持)
eol_sheet.clearContents();
eol_sheet.appendRow(headers); // ヘッダーの追加
const sheet = ss.getSheetByName('GetProductsList');
const nameColumnIndex = 2;
const lastRow = sheet.getLastRow();
const productNamesRange = sheet.getRange(1, nameColumnIndex, lastRow - 1);
const productNames = productNamesRange.getValues(); // 一括でプロダクト名を取得
const dataToWrite = [];
// プロダクト名毎にAPIから情報を取得
productNames.forEach(function(row, index) {
const productName = row[0].trim();
if (productName) { // プロダクト名が空でない場合のみ処理
const url = 'https://endoflife.date/api/' + encodeURIComponent(productName) + '.json';
const options = {
method: 'get',
muteHttpExceptions: true
};
try {
const response = UrlFetchApp.fetch(url, options);
const statusCode = response.getResponseCode();
if (statusCode === 200) {
var data = JSON.parse(response.getContentText());
data.forEach(function(entry) {
dataToWrite.push([
productName,
entry.cycle || '',
entry.releaseDate || '',
entry.eol || '',
entry.latest || '',
entry.latestReleaseDate || '',
entry.lts || false,
entry.support || '',
entry.discontinued || '',
entry.link || ''
]);
});
} else {
console.error(`Product ${productName}: Failed to fetch data with status code ${statusCode}`);
}
} catch (e) {
console.error(`Unable to fetch data for ${productName}: ${e}`);
}
// 待機を挿入(最後のリクエストの後は不要)
if (index < productNames.length - 1) {
Utilities.sleep(500);
}
}
});
// 一括でデータを書き込む
if (dataToWrite.length > 0) {
eol_sheet.getRange(eol_sheet.getLastRow() + 1, 1, dataToWrite.length, headers.length).setValues(dataToWrite);
}
// 差分の計算と出力
const newDataRange = eol_sheet.getDataRange();
const newData = newDataRange.getValues();
const diffData = calculateEolDiff(currentData, newData);
if (diffData.length > 0) {
eoldiff_sheet.clearContents(); // 差分シートをクリア
eoldiff_sheet.getRange(1, 1, diffData.length, diffData[0].length).setValues(diffData); // 差分を出力
// ログシートに実行時間とメッセージを記載
const timestamp = new Date();
const logMessage = `Script executed at ${timestamp.toLocaleString()}: Updates found in EOL sheet.`;
logs_sheet.appendRow([logMessage]);
} else {
// ログシートに実行時間とメッセージを記載
const timestamp = new Date();
const logMessage = `Script executed at ${timestamp.toLocaleString()}: No Updates in EOL sheet.`;
logs_sheet.appendRow([logMessage]);
}
// 列の幅を整列
eol_sheet.autoResizeColumns(1, headers.length);
}
// 差分を計算する関数
function calculateEolDiff(oldData, newData) {
const diff = [];
const oldDataStringified = oldData.map(row => JSON.stringify(row));
const newDataStringified = newData.map(row => JSON.stringify(row));
// 新しいデータをチェックし、古いデータに存在しない行を検出
newDataStringified.forEach((newRow, i) => {
if (!oldDataStringified.includes(newRow)) {
diff.push(['+', ...newData[i]]); // 新規追加された行に "+" を追加
}
});
// 古いデータをチェックし、新しいデータに存在しない行を検出
oldDataStringified.forEach((oldRow, i) => {
if (!newDataStringified.includes(oldRow)) {
diff.push(['-', ...oldData[i]]); // 削除された行に "-" を追加
}
});
return diff;
}
処理の流れは以下の通りです。
- 現在のEOLシートのデータを一時的に保存
- データのみをクリア(フォーマットは保持)
- GetProductListシートから一括でプロダクト名を取得
- プロダクト名毎にAPIから情報を取得(少し待機を挿入)
- EOLシートに一括でデータを書き込む
- 差分があるか確認し、DiffシートとLogsシートに書き込む
実行後のEOLシートの状況です。
Diffシートは見やすいように条件付き書式A列の+-入力に応じて色を付けると良いでしょう。
まとめ
任意のプロダクトのEOLの一覧ページがざっくりと作成できました。 getGetAllDetails.gs を定期実行し、Slackなどに通知できるようにすれば、利用できる場面もあるのではないでしょうか。
アノテーション株式会社について
アノテーション株式会社はクラスメソッドグループのオペレーション専門特化企業です。
サポート・運用・開発保守・情シス・バックオフィスの専門チームが、最新 IT テクノロジー、高い技術力、蓄積されたノウハウをフル活用し、お客様の課題解決を行っています。
当社は様々な職種でメンバーを募集しています。「オペレーション・エクセレンス」と「らしく働く、らしく生きる」を共に実現するカルチャー・しくみ・働き方にご興味がある方は、アノテーション株式会社 採用サイトをぜひご覧ください。