Skip to content

Comments

Enabling export of multiple instances#12

Merged
fredrodlima merged 8 commits intomainfrom
enabling-export-multiple-instances
Apr 16, 2025
Merged

Enabling export of multiple instances#12
fredrodlima merged 8 commits intomainfrom
enabling-export-multiple-instances

Conversation

@fredrodlima
Copy link
Contributor

@fredrodlima fredrodlima commented Apr 12, 2025

Solves

This PR updates the InstanceExport script and the documentation on README.md in order to enable that users can export more than one instance data in a single run of the script with the caveat that a given user should be added as Owner on each one of the instances they will have the manifest.

Description

When we created the InstanceExport tool we did a good job on allowing users to export a single instance when running it. We failed though to consider that we have some clients that may have multiple instances and the burden of running one by one would be a considerable effort.

I took a peak in order to update the script and allow that we could export more than one instances a given user has access to. I've tested in my tests with a Tech admin (us) users and users in the Owners group because I believe they will have the best set of permissions to be able to export everything successfully and with fewer possibility of facing any issues in the process.

When updating the script I've added a new parameter $instance for a few of the internal Cmdlets we've defined in InstanceExport so we would get the $manifestFilePath (a folder where users would save a manifest file or more than one manifest file) in order to export one or more instances in a single run of the script. Things should work pretty similar on how they used to work before the changes and how users that already used the tool will only have one different step (which is create a manifest folder) in their workflows which should be easy enough for them (I guess).

How To Test

0 - Open DevResults project on main branch
1 - Make sure you build the site and run it
2 - Log in as Tech admin in a local instance
3 - Go to Users page
4 - Select a user in the Owners group for that site
5 - Make sure to copy the selected user email in a Notepad (you will need later)
6 - Follow the password reset flow so you create a new password for that user (in case you don't know it already)
7 - Log in as that user in the local instance
8 - Open another tab and go to another local instance
9 - Log in as you Tech admin user
10- Make sure the Tech admin user can Edit on that instance
11 - Go to Users page and add the user you've chosen on step 4 and using email saved on step 5
12 - Log in as that user in this other local instance
13 - Log out of both instances as the chosen user
14 - Log in as your Tech admin user on both instances
15 - Go to Instances page and download manifests file for each one of the instances
16 - Finally, go to DevResultsTools repo and copy the InstanceExport.ps1 from the enabling-export-multiple-instances branch
17 - Save the InstanceExport script in a folder in your machine
18 - Create a manifest folder in the same folder you've saved the InstanceExport script
19 - Open a PowerShell window. Here I recommend that you use PowerShell 7 but it might work if you use Windows Power Shell too
20 - Navigate to the directory you've saved the InstanceExport script
21 - Trigger the export using .\InstanceExport
22 - Follow the prompts providing the manifest folder
23 - The exportFilePath
24 - The chosen user login and password (with Owner permissions)
25 - Wait and see that data will be exported
26 - Check that a folder for the exportFilePath was created and inside you see two folder one for each instance
27 - Go inside each one of the folders and check the sub-folders and the log file and that they do make sense to you from what you've seen in your PS script logs in the command line.
28 - In the manifest folder delete move the all manifests to a different folder
29 - Try to run the script again and make sure you got an error and creates a folder in the provided exportFilePath with a log file
30 - Try to run the script again and provide in the manifestFilePath the path for one of the manifests you've download and make sure it runs without issues as the usual flow for single instance export

Verifications:

Submitter:

  • Assigned appropriate pull request labels

Data Reviewer:

  • Works as described
  • Tasks created for KB, RN, and client comms

Engineer Reviewer:

I've added the $instance parameter to a few Cmdlets and updated the logic of the Export code so we get the manifest folder path and look for each one of the instances manifest json files and create a folder for each instance that will be exported inside the exportFilePath people provide when running the script. Also updated the logging so it's friendly to users enough to understand where the script is at at any point in time.
The images were not updated yet. I'll do it using the github web version. More commits should be coming to update the readme images
Updating images and texts explaining the possibility of exporting multiple instances in a single run of InstanceExport script
@fredrodlima fredrodlima added documentation Improvements or additions to documentation tech/powershell Changes were made using powershell script language labels Apr 12, 2025
[Parameter(Mandatory = $true)][String]$logLevel,
[Parameter(Mandatory = $true)][String]$currentDate
[Parameter(Mandatory = $true)][String]$currentDate,
[Parameter(Mandatory = $true)][String]$instance
Copy link
Contributor Author

@fredrodlima fredrodlima Apr 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added the $instance parameter so we could create different folders for each exported instance as well as update log texts and messages appropriately

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dropped the $instance parameter in the Log and CreateDirectoryIfNotExits so the log is saved in the exportFilePath and has content for all instances that are exported

if ($manifestFilePathExists) {
$manifestFilePath = $manifestFilePath.TrimEnd('\') # Trim any trailing backslash if it exists

$manifesJsonFiles = Get-ChildItem -Path "$manifestFilePath\*" -Include "*.json"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the most important change in the script where we are getting all the .json files inside the manifestFilePath provided and running a foreach to export each one of the instances we would like to export in a single run of the script


foreach ($manifestFile in $manifesJsonFiles) {

$manifestFileExists = Test-Path -Path $manifestFile
Copy link
Contributor Author

@fredrodlima fredrodlima Apr 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From here is basically the same code we previously had for a single instance export. Just a few simple and small changes, nothing fancy to highlight if you see the changes hiding whitespaces


$manifestFileExists = Test-Path -Path $manifestFile

$instance = ($manifestFile.BaseName -split ' ')[0]
Copy link
Contributor Author

@fredrodlima fredrodlima Apr 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we are getting the instance name from the BaseName of a given manifest json file. We should recommend users to not edit the name of the files we provide in order to things run smoothly for them.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Each manifest has subdomain inside of it... probably better to use that than trust the filename

`Windows PowerShell` usually comes installed with Windows. It uses the `PowerShell 5` version as you can see from the image below:

![image](https://user-images.githubusercontent.com/67288628/225462134-9a8e0224-3638-46be-9758-5adaf401d655.png)
![image](https://github.com/user-attachments/assets/3f61a5d3-8b95-43cb-b85d-d030b598aa1f)
Copy link
Contributor Author

@fredrodlima fredrodlima Apr 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In case you want to see the images please go to the README.md file in the enabling-exporting-multiple-instances branch

@fredrodlima fredrodlima changed the title Enabling export multiple instances Enabling export of multiple instances Apr 12, 2025
Copy link
Member

@bigdogwillfeed bigdogwillfeed left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works to export multiple instances at once, assuming:

  1. user enters the correct values at each prompt (see below for unhandled edge cases)
  2. user has access to each of the multiple instances with the same username and password (I'm not sure how common that is, and certainly won't be the case if any instance has forced SSO login)

One additional concern I have is that the single instance export has certainly been the most common usage thus far, and I expect that to continue to be the case. Now the script enforces additional complexity to handle the case where the user wants to export multiple instances at once.

I haven't been part of the conversation on these changes, so apologies if it's already been considered, but I have two suggestions for paths forward:

  1. check the manifest path as provided. If it's a json file, export just that one file as before. If it's a folder, let the user know that you'll use each of the json files in that folder (perhaps listing the files that you will use or the number found or something). This keeps the experience simple for the simple case, and users don't need to do the additional folder setup for a single export.
  2. leave this script untouched, and use a separate script for exporting multiple instances. Each loop of the new script would invoke InstanceExport.ps1 providing as many of the required inputs as possible -- this would support using separate credentials for each instance.

I'm happy to support whichever direction you choose on this. If you choose to keep this approach, I suggest cleaning up the error handling to cover the issues below


$manifestFileExists = Test-Path -Path $manifestFile

$instance = ($manifestFile.BaseName -split ' ')[0]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Each manifest has subdomain inside of it... probably better to use that than trust the filename

Comment on lines 340 to 341
$displayMsg = "An error occurred when looking for manifest folder"
Log -msg "Error in finding manifest folder" -displayMsg $displayMsg -logLevel "error" -currentDate $currentDate
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is displayed if the manifest file doesn't exist, which 1) is confusing, because it's a file not found but the message says folder and 2) should rarely happen because we're iterating over the list of json files in the folder to begin with.

@reidmporter
Copy link
Contributor

I see that it worked for NG but I got this:
image

In general I think NG's right that this is probably a one-off case (Chemonics), at least for the foreseeable future, but worth the one-off given the scope of their portfolio. I'd support either a separate script or a "file or folder?" change to the existing script, whatever seems best, to avoid disrupting everyone else who is not Chemonics going forward.

@reidmporter reidmporter removed their assignment Apr 14, 2025
Also adding code to check if the manifestFilePath is a json file or it's a folder. If it's a json file it runs smoothly as before and if it's a folder try to find as many as manifests that are available there. Also updating $instance value to be coming from the subdomain and not relying in the manifest file name.
@fredrodlima
Copy link
Contributor Author

This works to export multiple instances at once, assuming:

  1. user enters the correct values at each prompt (see below for unhandled edge cases)
  2. user has access to each of the multiple instances with the same username and password (I'm not sure how common that is, and certainly won't be the case if any instance has forced SSO login)

One additional concern I have is that the single instance export has certainly been the most common usage thus far, and I expect that to continue to be the case. Now the script enforces additional complexity to handle the case where the user wants to export multiple instances at once.

I haven't been part of the conversation on these changes, so apologies if it's already been considered, but I have two suggestions for paths forward:

  1. check the manifest path as provided. If it's a json file, export just that one file as before. If it's a folder, let the user know that you'll use each of the json files in that folder (perhaps listing the files that you will use or the number found or something). This keeps the experience simple for the simple case, and users don't need to do the additional folder setup for a single export.
  2. leave this script untouched, and use a separate script for exporting multiple instances. Each loop of the new script would invoke InstanceExport.ps1 providing as many of the required inputs as possible -- this would support using separate credentials for each instance.

I'm happy to support whichever direction you choose on this. If you choose to keep this approach, I suggest cleaning up the error handling to cover the issues below

Thanks for your great review and points noted in the tests. I've updated the script to follow the pattern 1. from your suggestions on how to handle if user pass a json file or a folder in the manifestFilePath. The common workflow people are used to follow with the tool was kept and now it's also possible to export more than one instance at once if you provide the manifest folder and have one or more json files in there!

[Parameter(Mandatory = $false)][String]$displayMsg,
[Parameter(Mandatory = $true)][String]$logLevel,
[Parameter(Mandatory = $true)][String]$currentDate,
[Parameter(Mandatory = $true)][String]$instance
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The $instance parameter was removed here

param (
[Parameter(Mandatory = $true)][String]$directoryPath,
[Parameter(Mandatory = $true)][String] $currentDate,
[Parameter(Mandatory = $true)][String] $instance
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The $instance parameter was removed here

$manifesJsonFiles = Get-ChildItem -Path "$manifestFilePath\*" -Include "*.json"

foreach ($manifestFile in $manifesJsonFiles) {
if (!$target.PSIsContainer) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This checks if the manifestFilePath is not a container (a file) and if yes it follows the previous script flow. Otherwise we follow the updated pattern (with a provided folder)

Updating README.md file to explain the normal flow for a single instance export and the new flow for multiple instances export flow
foreach ($manifestFile in $manifesJsonFiles) {
if (!$target.PSIsContainer) {
$manifestJson = Get-Content -Raw -Path $manifestFilePath | ConvertFrom-Json
$instance = $manifestJson.subdomain
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$instance now is using subdomain from json file

if ($manifestFileExists) {
$manifestJson = Get-Content -Raw -Path $manifestFile | ConvertFrom-Json

$instance = $manifestJson.subdomain
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$instance now is using subdomain from json file

So we call it either for the single instance scenario or multiple instances scenario and simplifies the reading a bit
}

$directoryPath = $exportFilePath + "/" + $instance
try {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These lines were being duplicated here (single instance scenario) as well as in the multiple instances scenario. So, I've went ahead and created the ExportInstanceData function so we don't have it repeated here and have a new Function to handle that

$msg = "Manifest file path doesn't contain valid json file(s)."
Log -msg $msg -displayMsg $msg -logLevel "error" -currentDate $currentDate

$msg = "Exporting Instance script run finished with errors."
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Improving a tiny bit the Log here so users are aware that an error has occurred in their script run

Copy link
Contributor

@reidmporter reidmporter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me! Got it to work just fine.

@fredrodlima fredrodlima added the enhancement New feature or request label Apr 16, 2025
This way, if a user can't sign in to one of several instances, the logs will clearly show which instance was the problem
Copy link
Member

@bigdogwillfeed bigdogwillfeed left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍🏼 Nice! This works well, and I think the support of either single manifest file or folder of manifest files is a good choice. One thing I like about this approach is that the log file contains the entire run (rather than one log per instance)

Not a blocker by any means, but some feedback for the future: There's a bit of repetition (and difference) in the Export function on either side of the "is this a file or folder" branch. The script would be a little easier to maintain if an export of one manifest file was handled by the exact same code (and called once in the single-file version, or in the loop in the folder version)

@fredrodlima fredrodlima merged commit 74adba5 into main Apr 16, 2025
1 check passed
@fredrodlima fredrodlima deleted the enabling-export-multiple-instances branch April 16, 2025 19:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation enhancement New feature or request size/L tech/powershell Changes were made using powershell script language

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants