🐹

tableau cloudのワークブックをS3にバックアップする

2024/01/15に公開

はじめに

いろいろなBIツールがありますが、その開発や運用時どのような管理をされていますか?
Lookerはgit管理できますが、tableauやPower BIはgit管理にあまり向いていない印象です。
ワークブックをgoogle drive等のツールで管理したり、tableau cloud上のみで管理するという方法もとりえますが、誤操作により予期せず削除等をしてしまうかもしれません。特にtableau cloudでは、現存しているワークブックの履歴管理はできますが、ワークブックを削除してしまった場合、元に戻すことはできないようです。意図せぬ操作をしてしまっても復旧できる準備しておく目的で、本記事ではtableau cloud上のワークブックをAWS S3にバックアップする方法を紹介します。

アーキ図

AWSのEventBridgeをトリガーに、Lambdaでサーバレスにtableau apiをたたき、tableau ワークブックをダウンロードしたうえ、S3にアップロードするという構成です。

また図には記載していませんが、lambdaの実行失敗時にはAWS SNSを通じてメール通知を行います。

準備

以下のAWSコンポートネントを利用します。なお本記事ではlambdaの実装以外の詳細は割愛します。

サービス 用途
IAM Policy 下記のS3にファイルをおく権限を持つ
IAM Policy 下記のSNS TOPICを利用する権限を持つ
IAM Role lambdaの実行ロール
IAM Role Event Bridgeの実行ロール
Lambda コードの実行
Event Bridge lambdaをトリガーする
S3 ワークブックの保存用
SNS lambdaが失敗したときの通知用

またtableau cloudより個人用アクセストークンを取得しておきます。
こちらのトークンは15日間利用がないと失効するようなので注意してください。

取得対象

tableau cloudでいわゆるフォルダはプロジェクトと呼ばれています。
以下のようなプロジェクト構成があるとして、今回はdefaultプロジェクト下の2つワークブックをS3に保存します。

├─default              #プロジェクト
│ ├─ダッシュボード1    #ワークブック
│ └─ダッシュボード2    #ワークブック
├─prod
│ ├─ダッシュボードA
│ └─ダッシュボードB

S3には以下のような構成で保存します。

├─workbook              
│ └─yyyymmdd           #実行日の日付
│   └─プロジェクト名
│        └─ワークブック(twb)

Lambdaの実装

以下のようなPythonコードで実装しています。
apiをたたくにはtableauserverclientというライブラリを用いました。

TOKEN_NAMEとTOKEN_VALUE、SNSのTOPIC_ARNは環境変数においています。
SITE_NAMEはtableau cloudのURLの以下の部分です。

https://{XXX}.tableau.com/#/site/{SITE_NAME}/

SERVER_URLは上のhttps~tableau.comの部分になります。

またデフォルトのタイムアウト時間は3秒ですが、今回は10秒以上かかる場合もあるため、
30秒に設定しました。

コード
import tableauserverclient as TSC
import os
import boto3
import logging
from datetime import datetime

logger = logging.getLogger()
logger.setLevel(logging.INFO)

TOKEN_NAME = os.environ['TOKEN_NAME']
TOKEN_VALUE = os.environ['TOKEN_VALUE']
TOPIC_ARN =os.environ['TOPIC_ARN']

SITE_NAME = 'あああ'
SERVER_URL ='いいい'
tableau_auth = TSC.PersonalAccessTokenAuth(TOKEN_NAME, TOKEN_VALUE, SITE_NAME)
server = TSC.Server(SERVER_URL, use_server_version=True)
project = 'default'
today_date = datetime.today().strftime('%Y%m%d')

def get_tableau_wb():
    with server.auth.sign_in(tableau_auth):
        # 対象プロジェクトのidを取得
        all_project_items, pagination_item = server.projects.get()
        project_id = [element.id for element in all_project_items if element.name == project][0]
        
        #lambdaの実行環境内にディレクトリを作成
        os.makedirs('/tmp/'+today_date+"/"+project+"/", exist_ok=True)

        # DL対象のwb名、id等を取得
        all_workbooks_items, pagination_item = server.workbooks.get()  
        target_wb_name = [wb.name for wb in all_workbooks_items if wb.project_id == project_id]
        target_wb_id = [wb.id for wb in all_workbooks_items if wb.project_id in project_id]

        # twbファイルを所定のパスにダウンロードする
        file_paths = []
        for id,wb in zip(target_wb_id,target_wb_name):
            file_path = server.workbooks.download(id,filepath ='/tmp/'+today_date+"/"+project+"/"+wb)
            logger.info(f"\nDownloaded the file to {file_path}")       
            file_paths.append(file_path)

        # s3にアップロードする
        s3 = boto3.resource('s3')
        s3_bucket_name = 'ううう'
        for lam_path in file_paths:
            s3_path = 'workbook'+lam_path.replace('tmp/','')
            s3.Bucket(s3_bucket_name).upload_file(lam_path, s3_path)        
            logger.info(f"\nUploaded the file to s3 {s3_path}")

def lambda_handler(event, context):
    try:
        get_tableau_wb()
        logger.info(f"\nUploaded completed!")
    except:
        sns = boto3.client('sns')
        import traceback
        sns.publish(
            TopicArn = TOPIC_ARN,
            Subject  = 'えええ',
            Message  = traceback.format_exc()
        )
        logger.error(f"\nUploaded failed!")
        raise

実行してみると、S3にワークブックが保存できていることを確認できました!

感想

lambdaの実装部分で、tableauserverclientというPythonライブラリを用いましたが、ワークブック周りの操作のほかにユーザー発行など複数の操作ができるようで、他の用途にも十分使えそうです。
また本機能は本番運用後の環境のみに適用できるバックアップ機能になりますが、開発時に皆さんがどのようにワークブックを管理されているのか気になっています。。。

参考

Discussion