FileMaker 17: Data Migration Tool (パート4) – すべてを統合する –

今回は、4回に渡って連載したData Migration Toolに関するブログシリーズの最終回です。サンプルファイルをダウンロードして実際に試してみてください。


ITSolutions

FileMaker 17: Data Migration Tool – Part Four

Putting it all together

(元記事はこちら)

2018/5/15
Colin Keefe

今回までのシリーズで、FileMakerのデプロイを管理する上でData Migration Toolがどのような問題を解決するのに適しているかを見てきました。前回までの内容は以下の通りです。

  • DMTの機能
  • スクリプトの作成
  • 実際のデプロイの現場でDMTなどのツールを使う場合の留意点

最終回となる今回は、デプロイの手順を管理するのに役立てるという観点で、再度DMTのスクリプトについて解説します。ここからの説明を理解するために、DMT Helper Fileのコピーを以下からダウンロードしてください。

DMTヘルパーファイルをダウンロード

今回のシナリオでは、ある開発チームが複数のFileMakerカスタムAppのデプロイを担当していて、それぞれのカスタムAppは、設定が異なり、1つかあるいは複数のファイルから構成されているものと想定します。シンプルにするために、セキュリティの考慮事項を無視して、作成するファイルにアカウント名/パスワードと暗号化キーを格納します。セキュリティ上の懸念を軽減する1つの方法は、特別な拡張アクセス権を使用して、管理者以外のアカウントで移行を管理できるようにすることです。

これから作成するツールは、複数ファイルの移行を管理し、個別のクライアントのソリューションの移行設定を保存します。ユーザの主な要求は以下の通りです。

ユーザの要求 メモ
ユーザはソリューションのプロファイルを作成できる。
プロファイルには、クライアント名、ソリューション名、バージョン番号が含まれる
ソリューションのプロファイルを追加したら、新規のFileMakerマイグレーションプロファイルも追加する
(ソリューションには最低1つのファイルが含まれるため)
ユーザは、ソリューションのプロファイルに、FileMakerファイルのマイグレーションプロファイルを追加できる ソリューションは複数のFileMakerファイルから構成される場合がある
ユーザがマイグレーションの実行に必要な引数を入力したら、[マイグレーションファイル]ボタンを有効化する 最低でもソースファイルとターゲットファイルのパスが必要
ユーザは1つのファイルに対し、マイグレーションを実行できる エラーをファイルリストとコンソール上に出力する
ユーザはソリューションの複数のファイルに対し、マイグレーションを実行できる エラーをファイルリストとコンソール上に出力する

これに対応するサンプル画面を以下に示します。

ソリューションプロファイルの管理画面

ここでは、左上にソリューションのリストと、その下にそれぞれに含まれるファイルのリストがあります。まだソリューションは作成されていません。

追加ボタン[+]をクリックして新しいソリューションを追加し、いくつかのフィールドに情報を入力します。

以下のように新規レコードが作成されます。

必要なフィールドに入力したら、選択したファイルに対してマイグレーションを実行できます。

マイグレーションを実行すると、最後の実行日時・結果・出力が以下のように表示されます。

以下のように別のファイルを追加でき、それぞれファイルごとに実行結果の値を持つことができます。

これにより、マイグレーションを一括で実行し、それぞれの成功/失敗の結果を確認することができます。以下の例では、最初のファイルは不正な認証が指定されたため失敗し、2番目のファイルは問題ありませんでした。

この推奨モデルでは、次のように複数のクライアントのマイグレーション用プロファイルを保存できます。

スクリプトの詳細
個々のDMTの呼び出しを行うスクリプトは以下のとおりです。次のようなことを行っています。

  • JSONを使ってスクリプトにパラメータを渡す (スクリプトの一番上のコメント部分に必要な引数を記述している)
  • JSONを取得する
  • 渡された引数の値に基づいてターミナルのコマンドライン命令を組み立てる
  • OSを特定し、それに対応した外部イベントの呼び出しを行う
  • 結果を取得してFileMakerのレコードを更新する(Macではこれは簡単でAppleScriptを使うだけです。Windowsではあるトリックを使います)

このファイルは賢くなく、すべてのファイルがDataMigrationToolHelperファイルと同じディレクトリにあることを前提にしています。もう少し賢くなるよう改造してみてください!

#-------------------------------
#10/24/17 Colin Keefe, IT Solutions Consulting, Inc.
#2/20/18 Robin Story, IT Solutions Consulting, Inc. 
    (added Windows scripting)
#www.itsolutions-inc.com/filemaker 
#-------------------------------
#Parameters to supply to this script:
#JSONSetElement("";
 
// source
["src_path"; MigrationProfile::src_path; ""];
["src_account"; MigrationProfile::src_account; ""];
["src_pwd"; MigrationProfile::src_pwd; ""]; 
["src_key"; MigrationProfile::src_key; ""];
 
//clone
["clone_path"; MigrationProfile::clone_path; ""]; 
["clone_account"; MigrationProfile::clone_account; ""]; 
["clone_pwd"; MigrationProfile::clone_pwd; ""]; 
["clone_key"; MigrationProfile::clone_key; ""];
 
["target_path"; MigrationProfile::target_path; ""]; 
["ignore_valuelists"; MigrationProfile::ignore_valuelists; JSONString]; 
["ignore_accounts"; MigrationProfile::ignore_accounts; JSONString]; 
["mode"; MigrationProfile::mode; JSONString]; 
["cache_size"; MigrationProfile::cache_size; JSONString]; 
["opl"; MigrationProfile::opl; JSONString] ) 

エラー処理 [ オン ]
レコード/検索条件確定
    [ ダイアログなし ] #export FMDataMigration Tool to Temp Directory
If [ IsEmpty (Get(スクリプト引数) ) ]
    カスタムダイアログを表示 [ タイトル: "Error"; 
        メッセージ: "No parameters were supplied. Please see script
             documentation to learn how to pass required parameters to this script.";
        デフォルトボタン: 「OK」, 確定: 「いいえ」 ]
    現在のスクリプト終了 [ ]
End If

#2/12/18 RHS - WindowsかMacかを識別する値を持つ変数を作る
変数を設定 [ $isMac; 値: Get(システムプラットフォーム) = 1 ] 

#このスクリプトは賢くないので相対パスを理解しません。すべてのファイルが
    同じディレクトリにある前提で動作します。10/24/17 CK
If [ $isMac ]
    変数を設定 [ $q; 値:"'" ]
    変数を設定 [ $tmp; 値:Get(ファイルパス) & 
        "FMDataMigrationTool/FMDataMigration" ]
    変数を設定 [ $scriptLocation; 値: "'" & 
        Substitute($tmp; ["file:/Macintosh HD";""];
        [Get(ファイル名);""];[".fmp12";""]) & "'" ]
    変数を設定 [ $filesLocation; 値: Substitute(Get(ファイルパス); 
        ["file:/Macintosh HD";""];[Get(ファイル名);""];[".fmp12";""]) ]

Else
    #結果があるかどうか識別するための環境をリセット
    フィールド設定 [ MigrationProfile::Result; "" ]
    フィールド設定 [ MigrationProfile::win_container_result; "" ]
    フィールド内容のエクスポート[「file:result.txt」; 
        ディレクトリの作成:いいえ ]
    #
    変数を設定 [ $q; 値:"\"" ]
    変数を設定 [ $tmp; 値:Get(ファイルパス) & 
        "FMDataMigrationTool_WIN/FMDataMigration.exe" ]
    変数を設定 [ $filesLocation; 値:Substitute(Get(ファイルパス); 
        ["file:/";""];[Get(ファイル名);""];[".fmp12";""]; ["/"; "\\"]) ]
    変数を設定 [ $scriptLocation; 値:$q & Substitute($tmp; 
        ["file:/";""];[Get(ファイル名);""];[".fmp12";""]; ["/"; "\\"]) & $q ]
End If

#toolに渡す引数を取り込む
#source file 変数
変数を設定 [ $src_path; 値:$q & $filesLocation & 
    JSONGetElement ( Get(スクリプト引数) ; "src_path" ) & $q ]
変数を設定 [ $src_account; 値:JSONGetElement ( Get(スクリプト引数) ; "src_account" ) ]
変数を設定 [ $src_pwd; 値:JSONGetElement ( Get(スクリプト引数) ; "src_pwd" ) ]
変数を設定 [ $src_key; 値:JSONGetElement ( Get(スクリプト引数) ; "src_key" ) ]

#destination file 変数
変数を設定 [ $clone_path; 値:$q & $filesLocation & 
    JSONGetElement ( Get(スクリプト引数) ; "clone_path" ) & $q ]
変数を設定 [ $clone_account; 値:JSONGetElement ( Get(スクリプト引数) ; "clone_account" ) ]
変数を設定 [ $clone_pwd; 値:JSONGetElement ( Get(スクリプト引数) ; "clone_pwd" ) ]
変数を設定 [ $clone_key; 値:JSONGetElement ( Get(スクリプト引数) ; "clone_key" ) ]
変数を設定 [ $target_path; 値:Let([
        _targetPath = JSONGetElement ( Get(スクリプト引数) ; "target_path" )
    ];
        Case(IsEmpty(_targetPath);"";
        $q & _targetPath & $q
        )
    )]
変数を設定 [ $ignore_accounts; 値:JSONGetElement ( Get(スクリプト引数) ; 
    "ignore_accounts" ) ]
変数を設定 [ $ignore_valuelists; 値:JSONGetElement ( Get(スクリプト引数) ; 
    "ignore_valuelists" ) ]
変数を設定 [ $mode; 値:JSONGetElement ( Get(スクリプト引数) ; "mode" ) ]
変数を設定 [ $cache_size; 値:JSONGetElement ( Get(スクリプト引数) ; "cache_size" ) ]
変数を設定 [ $opl; 値:JSONGetElement ( Get(スクリプト引数) ; "opl" ) ]

# エラー処理
If [ IsEmpty($src_path) ]
    カスタムダイアログを表示 [ タイトル: "Error"; 
        メッセージ: "Missing source path.";
        デフォルトボタン : 「OK」, 確定: 「いいえ」 ]
    現在のスクリプト終了 [ ]
Else If [ IsEmpty($clone_path) ]
    カスタムダイアログを表示 [ タイトル: "Error"; 
        メッセージ: "Missing clone path.";
        デフォルトボタン: 「OK」, 確定: 「いいえ」 ]
    現在のスクリプト終了 [ ]
End If
変数を設定 [ $parameters; 値:" -src_path " & $src_path &

    If(not IsEmpty($src_account); " -src_account " & $src_account;"") &
    If(not IsEmpty($src_pwd); " -src_pwd " & $src_pwd;"") &
    If(not IsEmpty($src_key); " -src_key " & $src_key ;"")&

    " -clone_path " & $clone_path &
    If(not IsEmpty($clone_account); " -clone_account " & $clone_account; "") &
    If(not IsEmpty($clone_pwd); " -clone_pwd " & $clone_pwd; "") &
    If(not IsEmpty($clone_key); " -clone_key " & $clone_key; "") &

    If(not IsEmpty($target_path); " -target_path " & $target_path; "") &
    If(not IsEmpty($ignore_valuelists); " -ignore_valuelists"; "") &
    If(not IsEmpty($ignore_accounts); " -ignore_accounts"; "") &
    If(not IsEmpty($mode); " -mode " & $mode; "") &
    If(not IsEmpty($cache_size); " -cache_size " & $cache_size; "") &
    If(not IsEmpty($opl); $opl; "") ]

If [ $isMac ]

    #実行するApplescriptを生成
    変数を設定 [ $command; 値:"set mySlug to do shell script \"" & 
        $scriptLocation &
        $parameters & "\" "
        &¶ &
        "tell application \"FileMaker Pro Advanced\"¶set cell \"Result\" 
        of current record to mySlug¶end tell" ]

    #toolを実行
    AppleScript を実行 [ 計算済みの AppleScript: $command ]
    変数を設定 [ $lastError; 値:Get(最終エラー) ]
    フィールド設定 [ MigrationProfile::LastRunTimestamp; Get(タイムスタンプ) ]

Else
    #実行するWindowsのバッチコードを生成
    変数を設定 [ $command; 値:"cmd /c \"" & $scriptLocation &
        $parameters &
        " > " & Quote($filesLocation & "result.txt")
        & "\" " ]

    #toolを実行
    Event を送信 [ 文書を開く; $command ]
        [ アプリケーションを手前に表示 ]
    変数を設定 [ $lastError; 値:Get(最終エラー) ]

    #結果を待つ
    変数を設定 [ $resultFileLocation; 値:Substitute($filesLocation; "\\"; "/") & 
        "result.txt" ]
    If [ $lastError = 0 ]
        Loop
            ファイルを挿入 [ MigrationProfile::win_container_result;「file:result.txt」]
            Exit Loop If [ Get(最終エラー) = 0 ]
            スクリプト一時停止/続行 [ 間隔(秒): 1 ]
        End Loop
    End If

    フィールド設定 [ MigrationProfile::LastRunTimestamp; Get(タイムスタンプ) ]

    #result.txtの内容をResultに書き込む
    URL から挿入 [ MigrationProfile::Result; "file:///" & $resultFileLocation ]
        [ URL を自動的にエンコードしない; 選択; ダイアログなし ]
    レコード/検索条件確定
        [ ダイアログなし ]

End If
If [ IsEmpty ( MigrationProfile::Result ) and MigrationProfile::mode="-q" ]
    フィールド設定 [ MigrationProfile::Result; "Successful run in Quiet Mode.
        If you really wanted this to run without messages you could edit
        the Run Migration script to not write this message! But hey, we're testing
        features." ]
    フィールド設定 [ MigrationProfile::LastRunSuccess; 1 ]
Else If [ $lastError ≠ 0 or Left(GetValue ( MigrationProfile::Result ; 
        If($isMac; 12; 23));5) ≠ "Start" ]
    フィールド設定 [ MigrationProfile::Result; Let([
            _message =     If ($lastError ≠ 0;"Error: " & $lastError & "¶¶";"") &
            "Migration Failed.¶¶Command attempted was:¶¶" &
            $command
            ];
            TextColor ( _message ; RGB ( 255 ; 0 ; 0 ) )
        )
        &
        "¶¶" &
        "Result was:¶¶"
        & MigrationProfile::Result ]
    フィールド設定[ MigrationProfile::LastRunSuccess; 0 ]

Else
    変数を設定 [ $start; 値:Let([
        _Timestamp = GetValue ( MigrationProfile::Result ; 14);
        _TimestampValue = Substitute(_Timestamp;"Start: "; "");
        _TS = Left ( _TimestampValue ; Length ( _TimestampValue )-5 )
        ];
        _TS
        )]
    変数を設定 [ $end; 値:Let([
        _Timestamp = GetValue ( MigrationProfile::Result ; ValueCount ( MigrationProfile::Result ));
        _TimestampValue = Substitute(_Timestamp;"End: "; "");
        _TS = Left ( _TimestampValue ; Length ( _TimestampValue )-5 )
        ];
        _TS
        )]
    フィールド設定 [ MigrationProfile::LastRunSuccess; 1 ]
    カスタムダイアログを表示 [ タイトル: "Time Elapsed";
        メッセージ: $start & " - " & $end; デフォルトボタン: 「OK」, 確定: 「いいえ」 ]
End If

関連記事:

Leave a Reply