コルネの進捗や備忘録が記されたなにか

進捗や成果物や備忘録てきななにかを雑に更新していきます。

Power Automateを使ってPower Automateを作成する


スポンサードリンク

はじめに

あまり参考文献がなかったので、この記事ではPower Automateの「フローの作成」アクションを用いてフローを作成する方法について記載しています。

learn.microsoft.com

どういうときに活躍するのか

こちらの記事に辿り着いた方はおそらく利用すべき要件があって辿り着いたかと思います。
そのような方はこちらは読み飛ばして貰えると。

フローの作成アクションは以下のようなシーンに役立ちます。

  • 同じような構成のフローだが、パラメータが異なる場合
    • 例えばトリガーに設定するパラメーターが異なる場合などが最も当てはまります。
      同じような構成だが、実行間隔が異なるものや、SharePoint リストが異なるものなどがこれに該当しますね。
  • 希望者にフローを配布したい場合
    • 作成したフローをそれぞれのマイフロー配下にて動かして欲しい場合などに利用できます。
      zip形式で配布する方法もありますが、これはソリューション化している場合は行えません。
      このようなシーンの対応としてはコピーの送信を利用するやり方もありますね。

フローの作成を行う

パラメーター

「フローの作成」アクションを実行する場合、5つのパラメーターの設定が必要です。

パラメーター 必須 説明
フローの表示名 必須 作成されるフローの名前を設定します
フロー定義 必須 作成するフローの情報
JSON形式で定義
フローの状態 必須 作成されるフローのON/OFFを設定
環境 必須 作成するフローの環境を設定
Flow/Properties/ConnectionReferences オプション 作成されるフローに利用される接続情報
※クラシックだと「connectionReferences」

フローの表示名

作成されるフローの名前を設定します。

ここは説明することもないので割愛。

フローの定義

作成するフローの定義をJSON形式で設定します。

たとえば、以下のようなシンプルなフローですと以下のような定義になります。

{
  "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
  "contentVersion": "undefined",
  "parameters": {
    "$authentication": {
      "defaultValue": {},
      "type": "SecureObject"
    },
    "$connections": {
      "defaultValue": {},
      "type": "Object"
    }
  },
  "triggers": {
    "manual": {
      "type": "Request",
      "kind": "Button",
      "inputs": {
        "schema": {
          "type": "object",
          "properties": {},
          "required": []
        }
      }
    }
  },
  "actions": {
    "作成": {
      "runAfter": {},
      "type": "Compose",
      "inputs": "AAA"
    }
  }
}

ただし、これをソラで0から記載するのはまぁ、時間の無駄ですので、まずは作成したいフローの基をクラウドフロー上で作成した後、「フローの取得」アクションを用いてフローの定義を取得するのが良いと思います。

これで得られた結果をPower Automate上で「作成」アクション内にべた書きしたり、テンプレートとなるフローから「フローの取得」アクションを用いて取得して作成したりすればいいですね。

前者の場合は、動的に変更したいパラメーターは動的なアクションを設定しておけばいいですね。

後者の場合は、「フローの取得」アクションで取得した動的な値の置換が必要です。

replace 関数 を用いて置換したい場合は、 string 関数 を用いてオブジェクト形式から文字列形式に変換した後に置換してあげる必要があります。
その後、 json 関数 を用いてオブジェクト形式に戻してあげます。

例えば以下のような形ですね。

json(
    replace(
        string(outputs('フローの取得')?['body/properties/definition']), 
        '置換前の値', 
        '置換後の値'
    )
)

文字列に戻すことなく、オブジェクト形式のままプロパティの編集を行う場合は setProperty 関数 を利用します。

今回更新するとなると入れ子になった値を更新することになるので、結構面倒です。(もっと楽なやり方あれば教えてください。)

例えばトリガーに設定されているパラメーターの値を変更する場合は以下のようになります。

setProperty(
   outputs('フローの取得')?['body/properties/definition'],
   'triggers',
   setProperty(
       outputs('フローの取得')?['body/properties/definition']?['triggers'],
       'トリガーの名前',
       setProperty(
           outputs('フローの取得')?['body/properties/definition']?['triggers']?['トリガーの名前'],
           'inputs',
           setProperty(
               outputs('フローの取得')?['body/properties/definition']?['triggers']?['トリガーの名前']?['inputs'],
               'parameters',
               setProperty(
                   outputs('フローの取得')?['body/properties/definition']?['triggers']?['トリガーの名前']?['inputs']?['parameters'],
                   '更新対象のパラメーター名',
                   '更新後の値'
               )
           )
       )
   )
)

フローの状態

作成されるフローのON/OFFを設定します。

ONの場合は"Started"
OFFの場合は"Stopped"
を設定します。

環境

フローを作成する環境を設定します。

Flow/Properties/ConnectionReferences

作成されるフローに設定する接続情報の定義を設定します。

こちらの定義はオプションですので、設定しなくともフローの作成自体は行えますが、接続情報が設定されていないフローが作成されますので、このままではフローは動作しません。

なので、だいたいの場合はこちらのパラメーターを設定することになりますが、こちらのパラメーターが少し曲者です。

まず、フローの作成経験がある方だと「フローの作成」アクションで得られた"connectionReferences"を動的な値として設定すればよいのでは?
と思われるかもしれません。

結論からいうとそれではだめです。

以下のようなエラーが表示されます。

OpenApiOperationParameterValidationFailed. The 'inputs.parameters' of workflow operation 'フローの作成' of type 'OpenApiConnection' is not valid. Error details: The API operation does not allow writing a value for parameter 'Flow/properties/connectionReferences[0]/displayName'. This parameter is read only.

"displayName"は読み取り専用だといわれていますね。

では、"connectionReferences"ではどのような値が返されるのかというと、Office 365 Usersコネクタを利用している場合は以下のような値が返されます。

[
  {
    "connectionName": "392f9b91fa9c4f52b1b2037c34108231",
    "displayName": "Office 365 ユーザー",
    "id": "/providers/Microsoft.PowerApps/apis/shared_office365users",
    "source": "Invoker"
  }
]

ここで"displayName"が返ってきていますね。
このパラメーターがダメだといわれています。

正直ドキュメントみてもよくわからんので、実際のアクションからこちらのパラメーターに設定が必要なJSON定義をみてみましょう。

こちらのパラメーターに適当な値を入力して「アレイ全体の入力に切り替える」を選択してみます。

すると以下のようにJSON定義を確認することができますので、この形式に変換してあげればいいということがわかります。

[
    {
        "connectionName": "A",
        "id": "B",
        "source": "C",
        "connectionReferenceLogicalName": "D"
    }
]

このような場合のJSONのキーの変更は「選択アクション」が利用できますね。

Map

{
  "connectionName": @{item()?['connectionName']},
  "id": @{item()?['id']},
  "source": @{item()?['source']}
}

これを「フローの作成」アクションの"connectionReferences"に設定すればフローの作成が行えます。

ただしこれは接続情報に「接続参照」が利用されていない場合のみできるお話です。

例えば、接続情報にDataverseの接続参照を利用している場合、"connectionReferences"は以下のような結果を返します。

[
  {
    "displayName": "Microsoft Dataverse",
    "id": "/providers/Microsoft.PowerApps/apis/shared_commondataserviceforapps",
    "source": "Embedded",
    "connectionReferenceLogicalName": "new_Dataverse"
  }
]

これを"displayName"を"connectionName"に変換したうえで設定すると以下のようなエラーが返ってきます。

XRM API に対する要求が失敗しました。エラー: 'Message: Request failed with: NotFound and error: {\"error\":{\"code\":\"ConnectionNotFound\",\"message\":\"Could not find connection 'new_Dataverse' for API 'shared_commondataserviceforapps'.\"}} and request url https://api.powerapps.com/providers/Microsoft.PowerApps/scopes/service/apis/shared_commondataserviceforapps/connections/new_Dataverse?api-version=2018-10-01&$expand=permissions($filter=maxAssignedTo('e1816e20-9788-43ef-a7f7-a415a67884d7')&$filter=environment eq '0e6b5ffb-79fd-e105-8b2e-8f15038badb6'\nCode: 0x80040265\nInnerError: '。

なぜこのようなエラーが発生してしまうのかというと、接続参照の場合の"connectionName"が異なるからです。

ではなにを設定すべきかというと、Dataverseの「つながり参照」テーブル(論理名「connectionreference」)の「つながり ID」(「ConnectionId」)列の値を設定する必要があります。

こちらのテーブルには「接続参照」の定義が格納されています。

この情報は「フローの取得」アクションでは得られません。

従って、面倒ではありますがDataverseのテーブルから情報を取得してフィルターみたいなことをする必要があります。

Power Automateで組み立てるのは正直面倒なので事前にJSON定義を作成しておくことを個人的にはお勧めします。

またこれはアクション側の問題だと思いますが、"connectionReferenceLogicalName"がうまく動作していないようで、同じ接続情報の接続参照が複数ある場合、どの接続参照が選ばれるかがわかりません。

これは「つながり ID」は接続参照に用いている情報が同じであれば共通のIDになるので、"connectionReferenceLogicalName"で接続参照の特定を行うことになるのですが、、、
これになにを設定しても指定した接続参照が指定できませんでした。。。

どうしてーーーー

また、トラブルシューティングとして私が遭遇した問題を記載しておくと"connectionReferences"の設定に問題がなさそうでも、引き続き上記と同じエラーが発生する場合があります。

XRM API に対する要求が失敗しました。エラー: 'Message: Request failed with: NotFound and error: {\"error\":{\"code\":\"ConnectionNotFound\",\"message\":\"Could not find connection 'new_Dataverse' for API 'shared_commondataserviceforapps'.\"}} and request url https://api.powerapps.com/providers/Microsoft.PowerApps/scopes/service/apis/shared_commondataserviceforapps/connections/new_Dataverse?api-version=2018-10-01&$expand=permissions($filter=maxAssignedTo('e1816e20-9788-43ef-a7f7-a415a67884d7')&$filter=environment eq '0e6b5ffb-79fd-e105-8b2e-8f15038badb6'\nCode: 0x80040265\nInnerError: '。

このような場合の原因のひとつフローの定義に問題がある場合があります。

フローの定義の

['actions']?['アクションの名前']?['inputs']?['host']?['connectionName']

* トリガーの場合は 'triggers' に置き換えてください。

をみてみると、コネクションの名前に "-1" が付与されている場合があります。

このような場合は、 "-1" を除去して試してみてください。

おわりに

思いもよらないところで躓いたーーーーorz

ちょっと調べてみたところあまり情報もなかったし、公式ドキュメントもわかりにくかったし。。。

でまとめてみましたが、他にいいやり方や、ここ違うよーなどあればコメントお願いします。


スポンサードリンク