Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate Restore-AzStorageBlobRange and ManagementPolicy related cmdlets #14

Merged
merged 12 commits into from
Jun 10, 2022

Conversation

yifanz0
Copy link

@yifanz0 yifanz0 commented May 30, 2022

Description

Migrate Restore-AzStorageBlobRange and ManagementPolicy related cmdlets

Checklist

  • I have read the Submitting Changes section of CONTRIBUTING.md
  • The title of the PR is clear and informative
  • The appropriate ChangeLog.md file(s) has been updated:
    • For any service, the ChangeLog.md file can be found at src/{{SERVICE}}/{{SERVICE}}/ChangeLog.md
    • A snippet outlining the change(s) made in the PR should be written under the ## Upcoming Release header -- no new version header should be added
  • The PR does not introduce breaking changes
  • If applicable, the changes made in the PR have proper test coverage
  • For public API changes to cmdlets:
    • a cmdlet design review was approved for the changes in this repository (Microsoft internal only)
    • the markdown help files have been regenerated using the commands listed here

@yifanz0 yifanz0 requested a review from blueww May 30, 2022 07:53
using System.Management.Automation;
using Azure;
Copy link
Member

Choose a reason for hiding this comment

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

Put system and others assemblies in groups. VS sort-usings may help.

Copy link
Author

Choose a reason for hiding this comment

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

Done.

}
else
{
WriteWarning(string.Format("Restore blob ranges with Id started. Restore blob ranges time to complete is dependent on the size of the restore."));
Copy link
Member

Choose a reason for hiding this comment

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

duplicated spaces

Copy link
Author

Choose a reason for hiding this comment

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

Done

}
else
{
WriteWarning(string.Format("Restore blob ranges with Id started. Restore blob ranges time to complete is dependent on the size of the restore."));
Copy link
Member

Choose a reason for hiding this comment

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

may be "without id", since restoreId is not fetched?

Copy link
Member

Choose a reason for hiding this comment

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

Maybe we should remove "with Id" here. OR jut report error, since it should have the restore ID.

Copy link
Author

Choose a reason for hiding this comment

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

Per discussion, removed "with id", and simply print a warning of "cannot fetch id" here.

Uri queueEndpoint = storageAccountResource.Data.PrimaryEndpoints.Queue != null ? new Uri(storageAccountResource.Data.PrimaryEndpoints.Queue) : null;
Uri tableEndpoint = storageAccountResource.Data.PrimaryEndpoints.Table != null ? new Uri(storageAccountResource.Data.PrimaryEndpoints.Table) : null;
Uri fileEndpoint = storageAccountResource.Data.PrimaryEndpoints.File != null ? new Uri(storageAccountResource.Data.PrimaryEndpoints.File) : null;
string key = storageAccountResource.GetKeys().Value.Keys[0].Value;
Copy link
Member

@yaxia yaxia May 31, 2022

Choose a reason for hiding this comment

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

check: storageAccountResource.GetKeys()?.Value?.Keys != null && storageAccountResource.GetKeys().Value.Keys.Count > 0

Copy link
Author

Choose a reason for hiding this comment

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

Done

public static IList<Track2Models.BlobRestoreRange> ParseBlobRestoreRanges(PSBlobRestoreRange[] ranges)
{
IList<Track2Models.BlobRestoreRange> re = new List<Track2Models.BlobRestoreRange>();
if (ranges == null)
Copy link
Member

@yaxia yaxia May 31, 2022

Choose a reason for hiding this comment

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

Do you want to make sure there is at least one item in the list? If so, you need to handle to case when ranges contains 0 item as well.

Copy link
Member

@blueww blueww May 31, 2022

Choose a reason for hiding this comment

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

Per the PSH design, if user not input "-BlobRestoreRange", will restore all ranges (from " to "" ).
If user input the parameter "-BlobRestoreRange", normally willl input at least 1 range, and we will restore the ranged user specified.
However, there're special way to input an array with 0 range. If this happen, we will just restore with 0 ranges as user input. We have not get customer complain for this behavior before.

Track2.Models.DateAfterModification dateAfterModification = new Track2.Models.DateAfterModification();
dateAfterModification.DaysAfterLastAccessTimeGreaterThan = this.DaysAfterLastAccessTimeGreaterThan;
dateAfterModification.DaysAfterModificationGreaterThan = this.DaysAfterModificationGreaterThan;

Copy link
Member

@blueww blueww May 31, 2022

Choose a reason for hiding this comment

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

missed DaysAfterLastTierChangeGreaterThan

If SDK still not support it, please add a TODO comment for it, and add the left item to the progress track excel.

Copy link
Author

Choose a reason for hiding this comment

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

Done. It's not supported yet, so added a TODO comment for it

@@ -12,15 +12,17 @@
// limitations under the License.
// ----------------------------------------------------------------------------------

using Track2 = Azure.ResourceManager.Storage;
using Track2Models = Azure.ResourceManager.Storage.Models;
Copy link
Member

Choose a reason for hiding this comment

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

Should update Storage.Management.csproj, by remove following line to include the file in az.storage.

<Compile Remove="StorageAccount\RestoreAzStorageBlobRange.cs" />

Copy link
Author

Choose a reason for hiding this comment

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

Done.

}
catch (System.AggregateException ex) when (ex.InnerException is CloudException)
catch (Exception ex)
Copy link
Member

Choose a reason for hiding this comment

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

Please catch a specific type exception, instead of all exceptions.

Copy link
Author

Choose a reason for hiding this comment

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

Done

if (status != null && status.Status == BlobRestoreProgressStatus.Failed)
Track2.StorageAccountResource account = this.StorageClientTrack2.GetStorageAccount(this.ResourceGroupName, this.StorageAccountName);
var restoreLro = account.RestoreBlobRanges(
WaitUntil.Completed,
Copy link
Member

Choose a reason for hiding this comment

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

Here might should be "WaitUntil.Started", as it's for when waitForComplete is not specified .

Copy link
Author

Choose a reason for hiding this comment

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

Done

new Track2Models.BlobRestoreContent(
this.TimeToRestore.ToUniversalTime(),
ParseBlobRestoreRanges(this.BlobRestoreRange)));
if (restoreLro.Value != null && restoreLro.Value.Status != null && restoreLro.Value.Status == Track2Models.BlobRestoreProgressStatus.Failed)
Copy link
Member

Choose a reason for hiding this comment

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

This line of code won't work. As can't parse the restore status from the return value when use "WaitUntil.Started".
You might should make the parse rawresponds code to a function, and use it in both place.

Copy link
Author

Choose a reason for hiding this comment

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

Thanks for catching this! Fixed the implementation to fetch all the information we need from the raw response and create a BlobRestoreStatus.

/// <summary>
/// Parse from PSBlobRestoreRange list to BlobRestoreRange list
/// </summary>
public static IList<Track2Models.BlobRestoreRange> ParseBlobRestoreRanges(PSBlobRestoreRange[] ranges)
Copy link
Member

@blueww blueww May 31, 2022

Choose a reason for hiding this comment

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

This should be a function of class PSBlobRestoreRange.

Copy link
Author

Choose a reason for hiding this comment

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

Done. Didn't notice there's already a ParseBlobRestoreRanges in PSBlobRestoreRange. Therefore simply removing this duplicated function here.

Actions = this.Actions is null ? null : this.Actions.ParseManagementPolicyAction(),
Filters = this.Filters is null ? null : this.Filters.ParseManagementPolicyFilter()
};
Track2.Models.ManagementPolicyAction actions = this.Actions is null ? null : this.Actions.ParseManagementPolicyAction();
Copy link
Member

Choose a reason for hiding this comment

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

Try the syntactic sugar: actions = this.Actions?.ParseManagementPolicyAction();

Copy link
Author

Choose a reason for hiding this comment

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

Done

};
Track2.Models.ManagementPolicyAction actions = this.Actions is null ? null : this.Actions.ParseManagementPolicyAction();
Track2.Models.ManagementPolicyDefinition policyDefinition = new Track2.Models.ManagementPolicyDefinition(actions);
policyDefinition.Filters = this.Filters is null ? null : this.Filters.ParseManagementPolicyFilter();
Copy link
Member

Choose a reason for hiding this comment

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

policyDefinition.Filters = this.Filters?.ParseManagementPolicyFilter();

Copy link
Author

Choose a reason for hiding this comment

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

Done

Dictionary<string, object> temp = restoreLro.GetRawResponse().Content.ToObjectFromJson() as Dictionary<string, object>;
object restoreId;

if (temp != null && temp.TryGetValue("restoreId", out restoreId))
Copy link
Member

Choose a reason for hiding this comment

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

We may return early when this condition is hit, otherwise all the places using temp.*** need a null-check.

Copy link
Author

Choose a reason for hiding this comment

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

Discussed offline with Wei and changed to throw an exception when temp is null. Thus temp referenced below is definitely not null.
Getting the raw response is a temporary workaround for this SDK issue. We will remove this chunk of code once the issue is fixed, and we should be able to get BlobRestoreStatus object directly with the SDK.

}

temp.TryGetValue("restoreId", out object restoreId);
Copy link
Member

Choose a reason for hiding this comment

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

temp.*** is not guarded by the null-check.

Copy link
Author

Choose a reason for hiding this comment

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

Changed to throw an exception when temp is null


PSBlobRestoreRange blobRestoreRange = new PSBlobRestoreRange
{
StartRange = startRange == null ? null : startRange.ToString(),
Copy link
Member

@yaxia yaxia Jun 6, 2022

Choose a reason for hiding this comment

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

startRange?.ToString() #Closed

Copy link
Member

Choose a reason for hiding this comment

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

same comment to the below

Copy link
Author

Choose a reason for hiding this comment

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

Done

}
public DateAfterCreation ParseDateAfterCreation()
{
return new DateAfterCreation(this.DaysAfterCreationGreaterThan, this.DaysAfterLastTierChangeGreaterThan);
Copy link
Member

Choose a reason for hiding this comment

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

Same comment should be add to code for SDK still not support "DaysAfterLastTierChangeGreaterThan". Like // TODO: DaysAfterLastTierChangeGreaterThan is still not supported by SDK, will add later.

Copy link
Author

Choose a reason for hiding this comment

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

Done

if (storageAccountResource.GetKeys()?.Value?.Keys != null && storageAccountResource.GetKeys().Value.Keys.Count > 0)
{
key = storageAccountResource.GetKeys().Value.Keys[0].Value;
} else
Copy link
Member

Choose a reason for hiding this comment

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

else

Minor: put else in a new line

Copy link
Author

Choose a reason for hiding this comment

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

Done

PSBlobRestoreParameters blobRestoreParameters = new PSBlobRestoreParameters();
Dictionary<string, object> paramMap = parameters as Dictionary<string, object>;

paramMap.TryGetValue("timetoRestore", out object timeToRestore);
Copy link
Member

@yaxia yaxia Jun 8, 2022

Choose a reason for hiding this comment

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

paramMap

could paraMap be null? #Closed

Copy link
Author

Choose a reason for hiding this comment

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

Fixed. Assign null to blobRestoreParameters when paramMap is null

Dictionary<string, object> paramMap = parameters as Dictionary<string, object>;

paramMap.TryGetValue("timetoRestore", out object timeToRestore);
DateTimeOffset.TryParse(timeToRestore.ToString(), out DateTimeOffset parseDate);
Copy link
Member

@yaxia yaxia Jun 8, 2022

Choose a reason for hiding this comment

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

timeToRestore

When paramMap.TryGetValue fails (e.g.: there is no "timetoRestore" field), the object is null. #Closed

Copy link
Author

Choose a reason for hiding this comment

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

Fixed

PSBlobRestoreParameters blobRestoreParameters = new PSBlobRestoreParameters();
Dictionary<string, object> paramMap = parameters as Dictionary<string, object>;

paramMap.TryGetValue("timetoRestore", out object timeToRestore);
Copy link
Member

@yaxia yaxia Jun 8, 2022

Choose a reason for hiding this comment

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

timetoRestore

is this case sensitive? Should it be timeToRestore?

Copy link
Author

Choose a reason for hiding this comment

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

Double checked the response. Weird but it's timetoRestore (might be a typo on the server side?), so I'm keeping timetoRestore here.

Copy link
Member

@yaxia yaxia left a comment

Choose a reason for hiding this comment

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

:shipit:

@yifanz0 yifanz0 merged commit d858c2d into wastoresh:track2review Jun 10, 2022
blueww pushed a commit that referenced this pull request Feb 12, 2025
* init add powershell cmdlet

* add customization for filedetails

* correct readme to include file workspace create

* add custom cmdlet for creating and uploading the file

* chunking logic for larger files

* add error for custom cmdlet when file too big

* combined cmdlets

* edit custom file upload command to not use default subscriptionid

* no default value for subid in custom file upload

* separate subscription and no subscription commands

* remove comments from combined cmd for file

* fix cmd

* custom no subscription file upload commands

* autogen docs for no sub file upload

* hide individual file commands

* add back workspace commands

* add name as alias for fileworkspacename fileworkspacesnosubscription

* remove update files and add alias for nosubscription file commands

* tests for get service

* tests for problem classification

* try adding erroractionpreference = stop

* tests for new file workspace

* tests for get file workspace

* more tests

* add tests for new file and upload, removefile name as a parameter

* remove new files no subscription

* tests for get file

* erroraction stop

* remove unnecessary comments and print statements

* docs for get support service

* problem classification docs

* add titles

* documentation for file workspace commands

* documentation for file/file workspace cmdlets

* documentation for checkNameAvailability

* added tests and documentation for operations, support ticket, communication and chat transcript cmdlets

* added examples for operations, support ticket, communication and chat transcript cmdlets

* resolve merge conflicts

* resolved PR comments

* get conflict file changes from grhuang/azsupport-autorest

* resolved merge conflict

* removed update communication sub and no sub scenarios

* Revert "removed update communication sub and no sub scenarios"

This reverts commit ccbfdee.

* removed update communication sub and no sub scenarios , updated readme

* make communiation and support ticket properties required in readme, edit get operation file name, edit calling internal cmdlets for file upload

* fix documentation

* fix top query

* add custom error handler

* consolidate list and get communicationsnosubscription and chattranscriptsnosubscription

* init changes to allow no subscription recording tests-need to use csp partner account in tenant 2e6a0c9f-986d-480e-ad4b-bdfddc047aba

* changes to not create new resources in playback

* remove custom error handler csharp

* init add changes to split subscription and no subscription tests

* update skip

* Update recordings

* update recordings

* add more examples to new-azsupportticket documentation

* update documentation and readme

* add directive back in

* make advanced diagnostic consent required

* Add custom error handling for New- and Update- cmdlets to print full details of error (#9)

* Add custom error handler

* Add default filter to retrieve tickets from the past week for Get-AzSupportTickets and Get-AzSupportTicketsNoSubscription (#10)

* add custom filtering for list support ticket if no filter is applied

* make transformations in swagger in readme to make enrollment id not readonly and show isTempTicket (#11)

* Add argument completer (#12)

* add argument completers

* add quotes to argument completers

* remove repeated time zone

* Regenerate powershell module with GA swagger (#13)

* Rerecord tests using GA version (#14)

* add tests for file size (will add recordings once Ga swagger available)

* Regenerate powershell module with GA swagger

* Rerecord tests with GA version

* Fix documentation

* fix url for file upload

---------

Co-authored-by: Grace Huang (from Dev Box) <[email protected]>
Co-authored-by: grhuangmsft <[email protected]>
Co-authored-by: Shreya Kumar <[email protected]>
Co-authored-by: Yunchi Wang <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants