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

[Recovery Services] Service URI's don't support being URI Encoded #2284

Closed
tombuildsstuff opened this issue Jul 23, 2018 · 9 comments
Closed
Labels
Blocked customer-reported Issues that are reported by GitHub users external to the Azure organization. Recovery Services Backup Service Attention Workflow: This issue is responsible by Azure service team.

Comments

@tombuildsstuff
Copy link
Contributor

👋

So we've been working through adding support for Recovery Services Protected Items to Terraform using the 2016-06-01 SDK from v18.0.0.

We've noticed an issue when calling methods in this SDK (currently CreateOrUpdate and Get, but presumably all of them are affected) - where the URI encoding used by AutoRest causes 404's to be returned. This particular API (and SDK) is considerably different from the other API's/SDK's available - such that the identifiers are separated by semi-colons.

We're using the following Go code to create the Protected Item (I've tweaked the SDK as explained below to get this to work, but we'll come to that):

protectedItemName := fmt.Sprintf("VM;iaasvmcontainerv2;%s;%s", resourceGroup, vmName)
containerName := fmt.Sprintf("iaasvmcontainer;iaasvmcontainerv2;%s;%s", resourceGroup, vmName)
item := backup.ProtectedItemResource{
	Location: utils.String(location),
	Tags:     expandTags(tags),
	Properties: &backup.AzureIaaSComputeVMProtectedItem{
		PolicyID:          &backupPolicyId,
		ProtectedItemType: backup.ProtectedItemType(backup.ProtectedItemTypeMicrosoftClassicComputevirtualMachines),
		WorkloadType:      backup.VM,
		SourceResourceID:  utils.String(vmId),
		FriendlyName:      utils.String(vmName),
		VirtualMachineID:  utils.String(vmId),
	},
}

if _, err := client.CreateOrUpdate(ctx, vaultName, resourceGroup, "Azure", containerName, protectedItemName, item); err != nil {
	return fmt.Errorf("Error creating/updating Recovery Service Protected Item %q (Resource Group %q): %+v", name, resourceGroup, err)
}

Once the Protected Item exists we then obtain it via the Get SDK method using the values from above:

resp, err := client.Get(ctx, vaultName, resourceGroup, "Azure", containerName, protectedItemName, "")

makes the following Request to the Get endpoint:

GET /Subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/tfex-recovery_services-609/providers/Microsoft.RecoveryServices/vaults/example-recovery-vault/backupFabrics/Azure/protectionContainers/iaasvmcontainer%3Biaasvmcontainerv2%3Btfex-recovery_services-609%3Btfexrecove609vm/protectedItems/VM%3Biaasvmcontainerv2%3Btfex-recovery_services-609%3Btfexrecove609vm?api-version=2016-06-01 HTTP/1.1
Host: management.azure.com
User-Agent: Go/go1.10.2 (amd64-darwin) go-autorest/v10.12.0 Azure-SDK-For-Go/v18.0.0 backup/2016-06-01;HashiCorp-Terraform-v0.11.3
Accept-Encoding: gzip

{
	"error": {
		"code": "BMSUserErrorDataSourceObjectNotFound",
		"message": "Item not found.\r\nSelected item might have been deleted. Please check if item is registered to the vault.",
		"target": null,
		"details": null,
		"innerError": null
	}
}

After some investigation we noticed the segments of the URI were being uri-encoded, which means the semi-colon's are encoded and thus don't come through correctly at the other API. Using this as a hunch - we tweaked the SDK not to uri-encode the containerName and protectedItemName values, like so (for both CreateOrUpdate and Deleted):

// GetPreparer prepares the Get request.
func (client ProtectedItemsClient) GetPreparer(ctx context.Context, vaultName string, resourceGroupName string, fabricName string, containerName string, protectedItemName string, filter string) (*http.Request, error) {
	pathParameters := map[string]interface{}{
		"containerName":     containerName,
		"fabricName":        autorest.Encode("path", fabricName),
		"protectedItemName": protectedItemName,
		"resourceGroupName": autorest.Encode("path", resourceGroupName),
		"subscriptionId":    autorest.Encode("path", client.SubscriptionID),
		"vaultName":         autorest.Encode("path", vaultName),
	}

  # ...
}

which sent the following successful HTTP Request:

GET /Subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/tfex-recovery_services-609/providers/Microsoft.RecoveryServices/vaults/example-recovery-vault/backupFabrics/Azure/protectionContainers/iaasvmcontainer%3Biaasvmcontainerv2%3Btfex-recovery_services-609%3Btfexrecove609vm/protectedItems/VM%3Biaasvmcontainerv2%3Btfex-recovery_services-609%3Btfexrecove609vm?api-version=2016-06-01 HTTP/1.1
Host: management.azure.com
User-Agent: Go/go1.10.2 (amd64-darwin) go-autorest/v10.12.0 Azure-SDK-For-Go/v18.0.0 backup/2016-06-01;HashiCorp-Terraform-v0.11.3
Accept-Encoding: gzip

{
	"id": "/Subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/tfex-recovery_services-609/providers/Microsoft.RecoveryServices/vaults/example-recovery-vault/backupFabrics/Azure/protectionContainers/IaasVMContainer;iaasvmcontainerv2;tfex-recovery_services-609;tfexrecove609vm/protectedItems/VM;iaasvmcontainerv2;tfex-recovery_services-609;tfexrecove609vm",
	"name": "VM;iaasvmcontainerv2;tfex-recovery_services-609;tfexrecove609vm",
	"type": "Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems",
	"properties": {
		"friendlyName": "tfexrecove609vm",
		"virtualMachineId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/tfex-recovery_services-609/providers/Microsoft.Compute/virtualMachines/tfexrecove609vm",
		"protectionStatus": "Healthy",
		"protectionState": "IRPending",
		"healthStatus": "Passed",
		"lastBackupStatus": "",
		"lastBackupTime": "2001-01-01T00:00:00Z",
		"protectedItemDataId": "175922524948328",
		"protectedItemType": "Microsoft.Compute/virtualMachines",
		"backupManagementType": "AzureIaasVM",
		"workloadType": "VM",
		"containerName": "iaasvmcontainerv2;tfex-recovery_services-609;tfexrecove609vm",
		"sourceResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/tfex-recovery_services-609/providers/Microsoft.Compute/virtualMachines/tfexrecove609vm",
		"policyId": "/Subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/tfex-recovery_services-609/providers/Microsoft.RecoveryServices/vaults/example-recovery-vault/backupPolicies/DefaultPolicy",
		"policyName": "DefaultPolicy"
	}
}

In general I'd expect the API to URI-decode the values as needed, but this API isn't doing that. It's also worth noting the ID's returned from this API are different to the other API's - where they're in the format:

/Subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/tfex-recovery_services-609/providers/Microsoft.RecoveryServices/vaults/example-recovery-vault/backupFabrics/Azure/protectionContainers/IaasVMContainer;iaasvmcontainerv2;tfex-recovery_services-609;tfexrecove609vm/protectedItems/VM;iaasvmcontainerv2;tfex-recovery_services-609;tfexrecove609vm

whereas usually we'd expect the Subscriptions component to be in lower-case; and the segments to be single values, rather than comprised of multiple-components.

Would it be possible for someone to take a look? In addition - given this API is so different to the other API's (specifically with the URI components), are there plans to standardise this API to match the conventions used by others in future?

Thanks!

@vladbarosan
Copy link

Hi @tombuildsstuff thanks for opening this issue. we will be reaching out to the Recovery Services Backup team.

@DheerendraRathor
Copy link

@tombuildsstuff Do you have request ids (x-ms-client-request-id header) for both scenarios? With that we can investigate in detail on service side.
I didn't find difference in final generated URL in both scenarios. Both have URL encoded semicolons.
Also both semicolon separated parts (container name & protected item name) are considered single value segment.

@tombuildsstuff
Copy link
Contributor Author

@tombuildsstuff Do you have request ids (x-ms-client-request-id header) for both scenarios? With that we can investigate in detail on service side.

@DheerendraRathor not to hand unfortunately - although this should be visible by using the Go SDK (or presumably any of the other SDK's)?

Thanks!

@mozehgir mozehgir added the Service Attention Workflow: This issue is responsible by Azure service team. label Sep 26, 2018
@pvrk
Copy link
Member

pvrk commented May 28, 2019

@tombuildsstuff: We still need the request ids for both scenarios. Any idea if you can repro and get it? It would greatly help.

Also, since you pointed out that this particular SDK is different, can you please share some of the standard/expected behaviors? I see that you have already mentioned two points.

  1. "Subscriptions" component should be lowercase: Is this a best practice or is something failing because of this? (I am asking since the issue is marked as blocked)
  2. "Segments to be in single values": We confirmed above that these are single values, just using ";" in between.

Anything else to change?

@pvrk
Copy link
Member

pvrk commented May 28, 2019

#customer-response-expected

@tombuildsstuff
Copy link
Contributor Author

@pvrk we're mostly AFK this week - but will try and provide a couple next week

@vladbarosan vladbarosan removed their assignment Jul 17, 2019
@pvrk
Copy link
Member

pvrk commented Aug 1, 2019

@tombuildsstuff: Do we have an update?

@pvrk
Copy link
Member

pvrk commented Sep 5, 2019

@tombuildsstuff : Another gentle reminder. Any update, please?

@pvrk
Copy link
Member

pvrk commented Oct 10, 2019

Closing this bug since we didn't get an update. Can re-open if updates are available

@pvrk pvrk closed this as completed Oct 10, 2019
@RickWinter RickWinter added the customer-reported Issues that are reported by GitHub users external to the Azure organization. label Jul 12, 2021
@github-actions github-actions bot locked and limited conversation to collaborators Apr 11, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Blocked customer-reported Issues that are reported by GitHub users external to the Azure organization. Recovery Services Backup Service Attention Workflow: This issue is responsible by Azure service team.
Projects
None yet
Development

No branches or pull requests

7 participants