AWS定義情報をGoogleスプレッドシートに出力する

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、城岸です。
今回はAWS定義情報をGoogleスプレッドシートに出力する方法を紹介したいと思います。

なぜやろうと思ったのか

弊社にはAWS定義情報を一撃でExcelに出力するツールが存在します。所謂Excel魔改造というやつです。

  • Excel改造 – シリーズ –
  • これ自体は非常に良くできていて利用する側の立場であればとても便利なものです。
    ですが、魔改造系の宿命でしょうか、メンテしようとすると結構ハードルが高いのです。

    そんなモヤモヤした気持ちでいた時に、ふと「AWS定義情報をスプレッドシートに出力できたらこの苦しみから解放されるんじゃないか?」という思いになったので実際にやって見ることにしました。

    完成系のイメージ

    今回はこのような情報を出力をします。

    aws cliでいうところのdescribe-instancesで取得できる情報(の一部)を出力します。

    事前準備

    Google Apps Script(以降、GAS)、、、??という状況だったので、GASについてさらっとドットインストールで勉強/準備をしました。全然知らなかったのですが、GAS≒JavaScriptなんですね。

    ということで、早速プロジェクトを作成していきます。ここからは、Googleスプレッドシート上でGASが実行できる前提で進めていきます!!

    やってみた

    プロジェクト作成

    新規にスプレッドシートを作成し、スクリプトエディタ(「ツール」-「スクリプト エディタ」)を起動します。
    起動後は以下のような画面に遷移します。※プロジェクト名、スクリプト名については任意のものに変更しておきましょう。

    AWS情報取得スクリプト作成

    node.js用のsdkを利用すればいけるかな思っていたのですが、そんな簡単にはいかず。。
    やりたいことを実現するための方法はいくつかありそうでしたが、最終的には以下を参考にAWS情報取得することにしました。
    このコードでは署名を作ってAWSのエンドポイントに対してリクエストを実行しています。

  • smithy545/aws-apps-scripts: An interface to authenticate AWS api requests from within google scripts
  • AWS情報表示スクリプト作成

    mainの関数になります。
    私JavaScriptに関してはほぼ初心者であるため、いけてないコードになっているかもしれませんが容赦ください。

    function myFunction(){
      
      //シートの取得
      var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
      var sheet = spreadsheet.getActiveSheet();
      
      //初期処理
      AWS.init("access_key", "secret_key");
      var instanceXML = AWS.request('ec2', 'ap-northeast-1', 'DescribeInstances', {"Version":"2015-10-01"});
      
      Logger.log(instanceXML.getContentText());
      
      var document = XmlService.parse(instanceXML.getContentText());
      var ec2 = XmlService.getNamespace('http://ec2.amazonaws.com/doc/2015-10-01/');
    
      var reservationSet = document.getRootElement().getChildren('reservationSet', ec2);
      var item = reservationSet[0].getChildren('item', ec2);
    
      var instancesSet;
      var instanceItem;
      var instanceName;
      var instanceId;
      var instanceType;
      var instanceState;
      var availabilityZone;
      var privateDnsName;
      var privateIpAddress;
      var vpcId;
      var subnetId;
      var imageId;
      var range;
      
      //一覧表の見出し  
      range = sheet.getRange("B2");
      range.setValue('■EC2インスタンス一覧');
      range = sheet.getRange("B3");
      range.setValue('InstanceName');
      range = sheet.getRange("C3");
      range.setValue('InstanceId');
      range = sheet.getRange("D3");
      range.setValue('InstanceType');
      range = sheet.getRange("E3");
      range.setValue('State');
      
      //一覧表見出の色付け  
      range = sheet.getRange("B3:E3")  		
      range.setBackground('#A8EFAF');  
      
      for (var i = 0; i < item.length; i++) {
    
        instancesSet = item[i].getChildren('instancesSet', ec2);
        instanceItem = instancesSet[0].getChildren('item', ec2);
    
        instanceName = instanceItem[0].getChildren('tagSet', ec2)[0].getChildren('item', ec2)[0].getChildText('value', ec2);  
        instanceId = instanceItem[0].getChildText('instanceId', ec2);
        instanceType = instanceItem[0].getChildText('instanceType', ec2);
        instanceState = instanceItem[0].getChildren('instanceState', ec2)[0].getChildText('name', ec2);  
        
        range = sheet.getRange(i+4,2);
        range.setValue(instanceName);
        
        range = sheet.getRange(i+4,3);
        range.setValue(instanceId);
        
        range = sheet.getRange(i+4,4);
        range.setValue(instanceType);
            
        range = sheet.getRange(i+4,5);
        range.setValue(instanceState);
    
      }
      
      //罫線
      range = sheet.getRange(3, 2, item.length+1, 4);
      range.setBorder(true, true, true, true, true, true, "black", SpreadsheetApp.BorderStyle.SOLID);
      
      //詳細の見出し
      var detailStartRow = item.length+5;
      var detailRow = item.length+5;
      
      for (var i = 0; i < item.length; i++) {
        
        range = sheet.getRange(detailStartRow,2);
        range.setValue('■EC2インスタンス');
        
        instancesSet = item[i].getChildren('instancesSet', ec2);
        instanceItem = instancesSet[0].getChildren('item', ec2);
        instanceName = instanceItem[0].getChildren('tagSet', ec2)[0].getChildren('item', ec2)[0].getChildText('value', ec2);  
        instanceId = instanceItem[0].getChildText('instanceId', ec2);
        instanceType = instanceItem[0].getChildText('instanceType', ec2);
        availabilityZone = instanceItem[0].getChildren('placement', ec2)[0].getChildText('availabilityZone', ec2);
        privateDnsName = instanceItem[0].getChildText('privateDnsName', ec2);
        privateIpAddress = instanceItem[0].getChildText('privateIpAddress', ec2);
        vpcId = instanceItem[0].getChildren('networkInterfaceSet', ec2)[0].getChildren('item', ec2)[0].getChildText('vpcId', ec2);  
        subnetId = instanceItem[0].getChildren('networkInterfaceSet', ec2)[0].getChildren('item', ec2)[0].getChildText('subnetId', ec2);  
        imageId = instanceItem[0].getChildText('imageId', ec2);
        
        range = sheet.getRange(detailStartRow,3);
        range.setValue(instanceName);
        detailRow++
        
        //Instance ID
        range = sheet.getRange(detailRow,2);
        range.setValue('instanceId');
        range.setBackground('#A8EFAF');  
        range = sheet.getRange(detailRow,3);
        range.setValue(instanceId);
        detailRow++
        
        //Instance type
        range = sheet.getRange(detailRow,2);
        range.setValue('instanceType');
        range.setBackground('#A8EFAF');  
        range = sheet.getRange(detailRow,3);
        range.setValue(instanceType);
        detailRow++
        
        //Availability zone
        range = sheet.getRange(detailRow,2);
        range.setValue('availabilityZone');
        range.setBackground('#A8EFAF');  
        range = sheet.getRange(detailRow,3);
        range.setValue(availabilityZone);
        detailRow++
        
        //Private DNS
        range = sheet.getRange(detailRow,2);
        range.setValue('privateDnsName');
        range.setBackground('#A8EFAF');  
        range = sheet.getRange(detailRow,3);
        range.setValue(privateDnsName);
        detailRow++
        
        //Private IP
        range = sheet.getRange(detailRow,2);
        range.setValue('privateIpAddress');
        range.setBackground('#A8EFAF');  
        range = sheet.getRange(detailRow,3);
        range.setValue(privateIpAddress);
        detailRow++
        
        //VPC ID
        range = sheet.getRange(detailRow,2);
        range.setValue('vpcId');
        range.setBackground('#A8EFAF');  
        range = sheet.getRange(detailRow,3);
        range.setValue(vpcId);
        detailRow++
        
        //Subnet ID
        range = sheet.getRange(detailRow,2);
        range.setValue('subnetId');
        range.setBackground('#A8EFAF');  
        range = sheet.getRange(detailRow,3);
        range.setValue(subnetId);
        detailRow++
        
        //AMI ID
        range = sheet.getRange(detailRow,2);
        range.setValue('imageId');
        range.setBackground('#A8EFAF');  
        range = sheet.getRange(detailRow,3);
        range.setValue(imageId);
        
        //罫線
        range = sheet.getRange(detailStartRow+1, 2, 8, 2);
        range.setBorder(true, true, true, true, true, true, "black", SpreadsheetApp.BorderStyle.SOLID);
        
        detailStartRow = detailRow+2;
        detailRow = detailRow+2;
      }
    }
    

    IAMユーザ作成

    次にAWS定義情報取得用のIAMユーザを作成します。権限としては参照権限があれば良いので以下のようにReadOnlyAccessのポリシーをアタッチしたユーザを作成します。アクセスキーとシークレットアクセスキーについてはメイン関数内に設定します。

    実行

    アクセスキーとシークレットアクセスキーをメイン関数内に設定した後、スクリプトエディタより実行します。※初回は承認ダイアログが表示されるので承認してください。


    スプレッドシートのメインの画面に戻ると。。

    AWS定義情報が出力されました!!

    まとめ

    AWS定義情報の出力は、Excelを利用するよりスプレッドシートを利用する方が若干ハードルが低い気がします。気になる方は是非試してみてください!!
    (スプレッドシートでもメンテは辛い。。)