Skip to content

Commit 3a9850b

Browse files
Final commit after refactoring and updating documentation
1 parent 163c893 commit 3a9850b

File tree

4 files changed

+91
-35
lines changed

4 files changed

+91
-35
lines changed

documentation/Import-PnPFlow.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ Import-PnPFlow [-Environment <PowerAutomateEnvironmentPipeBind>] [-PackagePath <
2626
```
2727

2828
## DESCRIPTION
29-
This cmdlet Imports a Microsoft Power Automate Flow from a zip package.
29+
This cmdlet imports a Microsoft Power Automate Flow from a ZIP package. At present, only flows originating from the same tenant are supported.
3030

3131
Many times Importing a Microsoft Power Automate Flow will not be possible due to various reasons such as connections having gone stale, SharePoint sites referenced no longer existing or other configuration errors in the Flow. To display these errors when trying to Import a Flow, provide the -Verbose flag with your Import request. If not provided, these errors will silently be ignored.
3232

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace PnP.PowerShell.Commands.Model.PowerPlatform.PowerAutomate
8+
{
9+
public class ImportFlowResult
10+
{
11+
public string Name { get; set; }
12+
public string Status { get; set; }
13+
public ImportFlowDetails Details { get; set; }
14+
}
15+
16+
public class ImportFlowDetails
17+
{
18+
public string DisplayName { get; set; }
19+
public string Description { get; set; }
20+
public DateTime CreatedTime { get; set; }
21+
}
22+
}

src/Commands/PowerPlatform/PowerAutomate/ImportFlow.cs

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -30,23 +30,8 @@ protected override void ExecuteCmdlet()
3030
{
3131
var environmentName = GetEnvironmentName();
3232
string baseUrl = PowerPlatformUtility.GetBapEndpoint(Connection.AzureEnvironment);
33-
var sasUrl = ImportFlowUtility.GenerateSasUrl(Connection.HttpClient, AccessToken, baseUrl, environmentName);
34-
var blobUri = ImportFlowUtility.BuildBlobUri(sasUrl, PackagePath);
35-
ImportFlowUtility.UploadPackageToBlob(blobUri, PackagePath);
36-
var importParametersResponse = ImportFlowUtility.GetImportParameters(Connection.HttpClient, AccessToken, baseUrl, environmentName, blobUri);
37-
var importOperationsData = ImportFlowUtility.GetImportOperations(Connection.HttpClient, AccessToken, importParametersResponse.Location.ToString());
38-
var propertiesElement = ImportFlowUtility.GetPropertiesElement(importOperationsData);
39-
40-
ImportFlowUtility.ValidateProperties(propertiesElement);
41-
var resourcesObject = ImportFlowUtility.ParseResources(propertiesElement);
42-
var resource = ImportFlowUtility.TransformResources(resourcesObject, Name);
43-
var validatePackagePayload = ImportFlowUtility.CreateImportObject(propertiesElement, resourcesObject);
44-
var validateResponseData = ImportFlowUtility.ValidateImportPackage(Connection.HttpClient, AccessToken, baseUrl, environmentName, validatePackagePayload);
45-
var importPackagePayload = ImportFlowUtility.CreateImportObject(validateResponseData);
46-
var importResult = ImportFlowUtility.ImportPackage(Connection.HttpClient, AccessToken, baseUrl, environmentName, importPackagePayload);
47-
var importStatus = ImportFlowUtility.WaitForImportCompletion(Connection.HttpClient, AccessToken, importResult.Location.ToString());
48-
49-
WriteObject($"Import {importStatus}");
33+
var importStatus = ImportFlowUtility.ExecuteImportFlow(Connection.HttpClient,AccessToken,baseUrl,environmentName,PackagePath,Name);
34+
WriteObject(importStatus);
5035
}
5136

5237
private string GetEnvironmentName()

src/Commands/Utilities/ImportFlowUtility.cs

Lines changed: 66 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,33 @@
66
using PnP.Framework.Diagnostics;
77
using System.Net.Http;
88
using System.Text.Json.Nodes;
9+
using PnP.PowerShell.Commands.Model.PowerPlatform.PowerAutomate;
10+
using System.Threading;
911

1012
namespace PnP.PowerShell.Commands.Utilities
1113
{
1214
internal static class ImportFlowUtility
1315
{
16+
public static ImportFlowResult ExecuteImportFlow(HttpClient httpClient, string accessToken, string baseUrl, string environmentName, string packagePath, string name)
17+
{
18+
var sasUrl = GenerateSasUrl(httpClient, accessToken, baseUrl, environmentName);
19+
var blobUri = BuildBlobUri(sasUrl, packagePath);
20+
UploadPackageToBlob(blobUri, packagePath);
21+
var importParametersResponse = GetImportParameters(httpClient, accessToken, baseUrl, environmentName, blobUri);
22+
var importOperationsData = GetImportOperations(httpClient, accessToken, importParametersResponse.Location.ToString());
23+
var propertiesElement = GetPropertiesElement(importOperationsData);
24+
ValidateProperties(propertiesElement);
25+
var resourcesObject = ParseResources(propertiesElement);
26+
var resource = TransformResources(resourcesObject, name);
27+
var validatePackagePayload = CreateImportObject(propertiesElement, resourcesObject);
28+
var validateResponseData = ValidateImportPackage(httpClient, accessToken, baseUrl, environmentName, validatePackagePayload);
29+
var importPackagePayload = CreateImportObject(validateResponseData);
30+
var importResult = ImportPackage(httpClient, accessToken, baseUrl, environmentName, importPackagePayload);
31+
return WaitForImportCompletion(httpClient, accessToken, importResult.Location.ToString());
32+
}
1433
public static string GenerateSasUrl(HttpClient httpClient, string accessToken, string baseUrl, string environmentName)
1534
{
16-
var response = RestHelper.Post(PnPConnection.Current.HttpClient, $"{baseUrl}/providers/Microsoft.BusinessAppPlatform/environments/{environmentName}/generateResourceStorage?api-version=2016-11-01", accessToken);
35+
var response = RestHelper.Post(httpClient, $"{baseUrl}/providers/Microsoft.BusinessAppPlatform/environments/{environmentName}/generateResourceStorage?api-version=2016-11-01", accessToken);
1736
var data = JsonSerializer.Deserialize<JsonElement>(response);
1837
return data.GetProperty("sharedAccessSignature").GetString();
1938
}
@@ -187,19 +206,20 @@ public static System.Net.Http.Headers.HttpResponseHeaders ImportPackage(HttpClie
187206
return importResult;
188207
}
189208

190-
public static string WaitForImportCompletion(HttpClient httpClient, string accessToken, string importPackageResponseUrl)
209+
public static ImportFlowResult WaitForImportCompletion(HttpClient httpClient,string accessToken,string importPackageResponseUrl)
191210
{
192-
string status;
211+
string status = null;
193212
int retryCount = 0;
213+
JsonElement importResultDataElement = default;
194214

195215
do
196216
{
197-
System.Threading.Thread.Sleep(2500);
217+
Thread.Sleep(2500);
198218
var importResultData = RestHelper.Get(httpClient, importPackageResponseUrl, accessToken, accept: "application/json");
199-
var importResultDataElement = JsonSerializer.Deserialize<JsonElement>(importResultData);
219+
importResultDataElement = JsonSerializer.Deserialize<JsonElement>(importResultData);
200220

201-
if (importResultDataElement.TryGetProperty("properties", out JsonElement importResultPropertiesElement) &&
202-
importResultPropertiesElement.TryGetProperty("status", out JsonElement statusElement))
221+
if (importResultDataElement.TryGetProperty("properties", out JsonElement propertiesElement) &&
222+
propertiesElement.TryGetProperty("status", out JsonElement statusElement))
203223
{
204224
status = statusElement.GetString();
205225
}
@@ -209,31 +229,30 @@ public static string WaitForImportCompletion(HttpClient httpClient, string acces
209229
throw new Exception("Import status could not be determined.");
210230
}
211231

212-
213232
if (status == "Running")
214233
{
215234
Log.Debug("ImportFlowUtility", "Import is still running. Waiting for completion...");
216235
retryCount++;
217236
}
218237
else if (status == "Failed")
219238
{
220-
ThrowImportError(importResultData);
239+
ThrowImportError(importResultDataElement);
221240
}
241+
222242
} while (status == "Running" && retryCount < 5);
223243

224244
if (status == "Running")
225245
{
226246
throw new Exception("Import failed to complete after 5 attempts.");
227247
}
228-
229-
return status;
248+
return MapToImportFlowResult(importResultDataElement);
230249
}
231250

232-
public static void ThrowImportError(string importResultData)
251+
252+
public static void ThrowImportError(JsonElement importErrorResultData)
233253
{
234-
var importErrorResultData = JsonSerializer.Deserialize<JsonElement>(importResultData);
235-
if (importErrorResultData.TryGetProperty("properties", out JsonElement importErrorResultPropertiesElement) &&
236-
importErrorResultPropertiesElement.TryGetProperty("resources", out JsonElement resourcesElement))
254+
if (importErrorResultData.TryGetProperty("properties", out JsonElement propertiesElement) &&
255+
propertiesElement.TryGetProperty("resources", out JsonElement resourcesElement))
237256
{
238257
foreach (var resource in resourcesElement.EnumerateObject())
239258
{
@@ -244,15 +263,45 @@ public static void ThrowImportError(string importResultData)
244263
: errorElement.TryGetProperty("code", out JsonElement codeElement)
245264
? codeElement.GetString()
246265
: "Unknown error";
266+
247267
throw new Exception($"Import failed: {errorMessage}");
248268
}
249269
}
250270
throw new Exception("Import failed: No error details found in resources.");
251271
}
252-
else
272+
273+
throw new Exception("Import failed: Unknown error.");
274+
}
275+
276+
277+
private static ImportFlowResult MapToImportFlowResult(JsonElement importResultDataElement)
278+
{
279+
var result = new ImportFlowResult();
280+
281+
if (importResultDataElement.TryGetProperty("name", out var nameElement))
253282
{
254-
throw new Exception("Import failed: Unknown error.");
283+
result.Name = nameElement.GetString();
255284
}
285+
286+
if (importResultDataElement.TryGetProperty("properties", out var propertiesElement))
287+
{
288+
if (propertiesElement.TryGetProperty("status", out var statusElement))
289+
{
290+
result.Status = statusElement.GetString();
291+
}
292+
293+
var details = new ImportFlowDetails();
294+
if (propertiesElement.TryGetProperty("details", out var detailsElement))
295+
{
296+
details.DisplayName = detailsElement.GetProperty("displayName").GetString();
297+
details.Description = detailsElement.GetProperty("description").GetString();
298+
details.CreatedTime = detailsElement.GetProperty("createdTime").GetDateTime();
299+
}
300+
result.Details = details;
301+
}
302+
303+
return result;
256304
}
305+
257306
}
258307
}

0 commit comments

Comments
 (0)