Open Rookian opened 4 years ago
@xccc-msft please take a look at this issue to see whether we support the case. //cc @yungezz
@Rookian This might be caused by the restriction on different versions from SQL service side. We will investigate if we could pick api version in better manner from SDK side. For now, you might want to use below snippet and retry:
string resourceProvider = ResourceUtils.ResourceProviderFromResourceId(id);
var provider = resourceManager.Providers.GetByName(resourceProvider);
Then follow same logic but try the other versions instead of picking the first one.
@xccc-msft I tried all versions with no success.
Could not get resource .../providers/Microsoft.Sql/servers/alextestsrc/databases/alextestdb with api version 2019-06-01-preview. Could not get resource .../providers/Microsoft.Sql/servers/alextestsrc/databases/alextestdb with api version 2018-06-01-preview. Could not get resource .../providers/Microsoft.Sql/servers/alextestsrc/databases/alextestdb with api version 2017-10-01-preview.
Could not get resource .../providers/Microsoft.Sql/servers/alextestsrc/databases/alextestdb with api version 2017-03-01-preview. Could not get resource .../providers/Microsoft.Sql/servers/alextestsrc/databases/alextestdb with api version 2015-05-01-preview. Could not get resource .../providers/Microsoft.Sql/servers/alextestsrc/databases/alextestdb with api version 2015-01-01. Could not get resource .../providers/Microsoft.Sql/servers/alextestsrc/databases/alextestdb with api version 2014-04-01-preview. Could not get resource .../providers/Microsoft.Sql/servers/alextestsrc/databases/alextestdb with api version 2014-04-01. Could not get resource .../providers/Microsoft.Sql/servers/alextestsrc/databases/alextestdb with api version 2014-01-01.
Code:
private async Task<IGenericResource> GetResourceById(IGenericResource resource)
{
try
{
var res = await _genericResources.GetByIdAsync(resource.Id);
return res;
}
catch (Exception)
{
var resourceProvider = ResourceUtils.ResourceProviderFromResourceId(resource.Id);
var provider = _genericResources.Manager.Providers.GetByName(resourceProvider);
var apiVersions = GetApiVersions(resource.Id, provider);
foreach (var apiVersion in apiVersions)
{
try
{
var res = await _genericResources.GetByIdAsync(resource.Id, apiVersion);
return res;
}
catch (Exception)
{
ConsoleEx.WriteWarningLine($"Could not get resource {resource.Id} with api version {apiVersion}.");
}
}
throw new Exception($"Could not get resource based on id {resource.Id}.");
}
}
private static IList<string> GetApiVersions(string id, IProvider provider)
{
var resourceType = ResourceUtils.ResourceTypeForApiVersion(id);
if (string.IsNullOrEmpty(resourceType))
{
return null;
}
foreach (var providerResourceType in provider.ResourceTypes)
{
if (string.Equals(resourceType, providerResourceType.ResourceType, StringComparison.OrdinalIgnoreCase)
&& providerResourceType.ApiVersions != null
&& providerResourceType.ApiVersions.Count > 0)
{
return providerResourceType.ApiVersions;
}
}
return new List<string>();
}
Thanks for the feedback! We are routing this to the appropriate team for follow-up. cc @armleads-azure.
@Rookian Thanks for the update. I just add a label so we can get help from service end to check this.
SQL team needs to investigate concerning their resource provider manifest and api version
Not sure if the problem is in the SDK or the input, but from telemetry the generated url is incorrect: https://management.azure.com:443/subscriptions/<subid>/resourcegroups/<rgname>/providers/Microsoft.Sql/subscriptions/<subid>/resourceGroups/<rgname>/providers/Microsoft.Sql/servers/alextestsrc/databases/alextestdb?api-version=2019-06-01-preview
Notice that the subscriptions, resourcegroups and providers segments are repeated in the request url.
@jamestao Thanks for sharing the observation. @Rookian I just commit changes to fix this. Before we release, you might use below code snippet as a workaround.
var resourceGroupName = ResourceUtils.GroupFromResourceId(id);
var resourceProviderNamespace = ResourceUtils.ResourceProviderFromResourceId(id);
//key step for parent resource path
var parentResourcePath = ResourceUtils.ParentResourcePathFromResourceId(id);
if (!string.IsNullOrEmpty(parentResourcePath))
{
parentResourcePath = ResourceUtils.NameFromResourceId(parentResourcePath);
}
var resourceType = ResourceUtils.ResourceTypeForResourceId(id);
var resourceName = ResourceUtils.NameFromResourceId(id);
var res = await _genericResources.GetAsync(resourceGroupName, resourceProviderNamespace, parentResourcePath, resourceType, resourceName, apiVersion);
return res;
Hello guys, the issue remains:
Setup:
The code fails at the line where the Tags are being updated:
await res.Update()
.WithApiVersion(res.ApiVersion)
.WithProperties(res.Properties)
.WithTags(...)
.ApplyAsync();
see https://github.com/Azure/azure-libraries-for-net/issues/978#issuecomment-588261592. I'm trying to set the Tags for the SQL Server Database.
For the SQL Server's Instance Resource, the code works fine.
resource ID: /subscriptions/(id)/resourceGroups/(id)/providers/Microsoft.Sql/servers/(sql_server_instance_id)/databases/(sql_server_db_name)
The workaround here that worked for me is to update Tags with using the SqlManagementClient class:
AzureCredentials credentials = ...
RestClient restClient = RestClient.Configure()
.WithEnvironment(AzureEnvironment.AzureGlobalCloud)
.WithLogLevel(HttpLoggingDelegatingHandler.Level.Basic)
.WithCredentials(credentials)
.Build();
_client = new SqlManagementClient(restClient)
{
SubscriptionId = ...
};
if (!string.IsNullOrWhiteSpace(resource.ParentResourceId))
{
string databaseName = ResourceUtils.NameFromResourceId(resource.Id);
string serverName = ResourceUtils.NameFromResourceId(resource.ParentResourceId);
await _client.Databases.UpdateAsync(resourceGroup,
serverName,
databaseName,
new DatabaseUpdateInner
{
Tags = new Dictionary<string, string>() { ... }
});
}
Please apply the fix in the Fluent API approach
@tony6636 Before you call res.Update()
, how did you get the var res
?
@tony6636 Before you call
res.Update()
, how did you get the varres
?
as mentioned, in the same was way as described here https://github.com/Azure/azure-libraries-for-net/issues/978#issuecomment-588261592
@tony6636 Thanks for confirmation. You need to insert one line as below:
await res.Update()
.WithApiVersion(res.ApiVersion)
.WithProperties(res.Properties)
// For resource with parent, insert below line
.WithParentResource(ResourceUtils.ParentRelativePathFromResourceId(res.Id))
.WithTags(...)
.ApplyAsync();
@tony6636 Thanks for confirmation. You need to insert one line as below:
await res.Update() .WithApiVersion(res.ApiVersion) .WithProperties(res.Properties) // For resource with parent, insert below line .WithParentResource(ResourceUtils.ParentRelativePathFromResourceId(res.Id)) .WithTags(...) .ApplyAsync();
Thanks, I've checked that approach and I'mgetting the error message like :
The Resource 'Microsoft.Sql/servers/(server-name)/databases/(db-name)' under resource group '(resource-group-name)' was not found.
physically that resource exists in that resource group
@tony6636 I cannot reproduce this from my end. For me, I could update tags for the SQL database via the code snippet I shared after creating it.
Can you please capture the request and verify what's the request Uri? Or just check what value you passed into withParentResource(value)
? Another option, you may verify via genericResources.checkExistenceById(id)
.
I still get an error without the solution from @xccc-msft :
Microsoft.Rest.Azure.CloudException: The resource type could not be found in the namespace 'Microsoft.Sql' for api version '2020-02-02-preview'.
With the solution from @xccc-msft, I also get an error:
Microsoft.Rest.Azure.CloudException: Long running operation failed with status 'Failed'. Additional Info:''System' is not a valid database edition in this version of SQL Server.' at Microsoft.Rest.ClientRuntime.Azure.LRO.AzureLRO
2.CheckForErrors() at Microsoft.Rest.ClientRuntime.Azure.LRO.PutLRO
2.CheckForErrors() at Microsoft.Rest.ClientRuntime.Azure.LRO.AzureLRO2.StartPollingAsync() at Microsoft.Rest.ClientRuntime.Azure.LRO.AzureLRO
2.BeginLROAsync() at Microsoft.Rest.Azure.AzureClientExtensions.GetLongRunningOperationResultAsync[TBody,THeader](IAzureClient client, AzureOperationResponse2 response, Dictionary
2 customHeaders, CancellationToken cancellationToken) at Microsoft.Rest.Azure.AzureClientExtensions.GetLongRunningOperationResultAsync[TBody](IAzureClient client, AzureOperationResponse1 response, Dictionary
2 customHeaders, CancellationToken cancellationToken) at Microsoft.Rest.Azure.AzureClientExtensions.GetPutOrPatchOperationResultAsync[TBody](IAzureClient client, AzureOperationResponse1 response, Dictionary
2 customHeaders, CancellationToken cancellationToken) at Microsoft.Azure.Management.ResourceManager.Fluent.ResourcesOperations.CreateOrUpdateWithHttpMessagesAsync(String resourceGroupName, String resourceProviderNamespace, String parentResourcePath, String resourceType, String resourceName, String apiVersion, GenericResourceInner parameters, Dictionary2 customHeaders, CancellationToken cancellationToken) at Microsoft.Azure.Management.ResourceManager.Fluent.ResourcesOperationsExtensions.CreateOrUpdateAsync(IResourcesOperations operations, String resourceGroupName, String resourceProviderNamespace, String parentResourcePath, String resourceType, String resourceName, String apiVersion, GenericResourceInner parameters, CancellationToken cancellationToken) at Microsoft.Azure.Management.ResourceManager.Fluent.GenericResourceImpl.CreateResourceAsync(CancellationToken cancellationToken) at Microsoft.Azure.Management.ResourceManager.Fluent.Core.ResourceActions.Creatable
4.Microsoft.Azure.Management.ResourceManager.Fluent.Core.ResourceActions.IResourceCreator.CreateResourceAsync(CancellationToken cancellationToken) at Microsoft.Azure.Management.ResourceManager.Fluent.Core.DAG.CreatorTaskItem 1.ExecuteAsync(CancellationToken cancellationToken) at Microsoft.Azure.Management.ResourceManager.Fluent.Core.DAG.TaskGroupBase
1.ExecuteNodeTaskAsync(DAGNode1 node, CancellationToken cancellationToken) at Microsoft.Azure.Management.ResourceManager.Fluent.Core.ResourceActions.CreatableUpdatable
5.ApplyAsync(CancellationToken cancellationToken, Boolean multiThreaded)
//cc @rthorn17
@Rookian It looks your long-running operation failed when polling status. Can you please retry again?
cc: @jamestao Do you know what the info means by Additional Info:''System' is not a valid database edition in this version of SQL Server.'
?
@Rookian It looks your long-running operation failed when polling status. Can you please retry again?
cc: @jamestao Do you know what the info means by
Additional Info:''System' is not a valid database edition in this version of SQL Server.'
?
It is not working.
Additional Info:''System' is not a valid database edition in this version of SQL Server.'?
This means that the database edition is unfortunately not set when retrieving the Azure resource. If you now update the resource you will get this exception. So this is a bug in my opinion.
@Rookian Can you please try with _genericResources.Inner.[operation]
to see if it is SDK issue or service issue? Thanks.
@Rookian Can you please try with
_genericResources.Inner.[operation]
to see if it is SDK issue or service issue? Thanks.
_genericResources.Inner
has no operations available.
_genericResources.Inner.Properties
or _genericResources.Properties
contains value:
{[currentSku, {{
"name": "System",
"tier": "System",
"capacity": 0
}}]}
I created the database with
.WithEdition(DatabaseEdition.Standard)
.WithServiceObjective(ServiceObjectiveName.S0)
@Rookian The code you shared before was var res = await _genericResources.GetByIdAsync(resource.Id);
I would suggest you to try _genericResources.Inner.[operation]
.
resource.Inner.Tags = Tags;
await _genericResources.Inner.UpdateAsync(
resourceGroup.Name, resource.ResourceProviderNamespace,
ResourceUtils.ParentRelativePathFromResourceId(res.Id), res.ResourceType,
res.Name, res.ApiVersion, resource.Inner);
Also fails with:
Microsoft.Rest.Azure.CloudException: Long running operation failed with status 'Failed'. Additional Info:''System' is not a valid database edition in this version of SQL Server.' at Microsoft.Rest.ClientRuntime.Azure.LRO.AzureLRO
2.CheckForErrors() at Microsoft.Rest.ClientRuntime.Azure.LRO.AzureLRO
2.StartPollingAsync() at Microsoft.Rest.ClientRuntime.Azure.LRO.AzureLRO2.BeginLROAsync() at Microsoft.Rest.Azure.AzureClientExtensions.GetLongRunningOperationResultAsync[TBody,THeader](IAzureClient client, >AzureOperationResponse
2 response, Dictionary2 customHeaders, CancellationToken cancellationToken) at Microsoft.Rest.Azure.AzureClientExtensions.GetLongRunningOperationResultAsync[TBody](IAzureClient client, AzureOperationResponse
1 response, Dictionary2 customHeaders, CancellationToken cancellationToken) at Microsoft.Rest.Azure.AzureClientExtensions.GetPutOrPatchOperationResultAsync[TBody](IAzureClient client, AzureOperationResponse
1 response, Dictionary2 customHeaders, CancellationToken cancellationToken) at Microsoft.Azure.Management.ResourceManager.Fluent.ResourcesOperations.UpdateWithHttpMessagesAsync(String resourceGroupName, String resourceProviderNamespace, String parentResourcePath, String resourceType, String resourceName, String apiVersion, GenericResourceInner parameters, Dictionary
2 customHeaders, CancellationToken cancellationToken) at Microsoft.Azure.Management.ResourceManager.Fluent.ResourcesOperationsExtensions.UpdateAsync(IResourcesOperations operations, String resourceGroupName, String resourceProviderNamespace, String parentResourcePath, String resourceType, String resourceName, String apiVersion, GenericResourceInner parameters, CancellationToken cancellationToken)
@Rookian Thanks for sharing. I noticed you mentioned the code for creating database:
.WithEdition(DatabaseEdition.Standard)
.WithServiceObjective(ServiceObjectiveName.S0)
Not sure if you have specific reason to use generic resources for updating tags. Can you try with below scenario to update in sql resource itself:
var sqlDatabase = sqlServer.Databases
.Define(SqlDatabaseName)
.WithCollation(Collation)
.WithEdition(DatabaseEdition.Standard)
.WithServiceObjective(ServiceObjectiveName.S0)
.WithTag("tag1", "value1")
.Create();
// try below update instead of generic resources
sqlServer.Update()
.WithTag("tag2", "value2")
.Apply();
If you have to use generic resources, you might try a different api version manually.
cc: @nickzhums
I have to use generic resources, because I would like to patch all resources with resource tags.
@Rookian I tried to create a database by the settings you mentioned
.WithEdition(DatabaseEdition.Standard)
.WithServiceObjective(ServiceObjectiveName.S0)
With this, I was able to get the database only with Standard
as
"currentSku":{"name":"Standard","tier":"Standard","capacity":10}
Then I could be able to update the tags successfully.
When I tried to create a database by setting System
edition, I got error as you provided
'System' is not a valid database edition in this version of SQL Server.
Could you share more details how you created the database with System edition? Thanks.
Describe the bug I created a SQL Azure database server with a database manually and also with code using the SDK.
I have some code snippet that tags all resources within a resource group. See https://github.com/Azure/azure-libraries-for-net/issues/978#issuecomment-588261592
When I try to receive the resource for the Azure database, I get the following errror:
Failing code:
Expected behavior It should be possible to retrieve and tag Azure Sql database resources.
Setup: