From 90f932dbf86393e8e2a42680a97dff390cbbfac7 Mon Sep 17 00:00:00 2001 From: Weidong Xu Date: Mon, 29 Mar 2021 15:24:28 +0800 Subject: [PATCH] mitigate bug related to dot and flatten from azure-client-runtime (#1380) * test case for TagsPatchResource serialization, which fails * fluent API for tags update --- .../management/resources/TagOperations.java | 56 ++++++++++ .../management/resources/TagResource.java | 32 ++++++ .../implementation/ResourceManager.java | 12 ++ .../implementation/TagOperationsImpl.java | 64 +++++++++++ .../implementation/TagResourceImpl.java | 48 ++++++++ .../azure/management/resources/TagsTests.java | 39 +++++++ .../TypeSerializationTests.java | 80 +++++++++++++- .../session-records/canUpdateTag.json | 104 ++++++++++++++++++ .../com/microsoft/azure/management/Azure.java | 6 + 9 files changed, 438 insertions(+), 3 deletions(-) create mode 100644 azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/TagOperations.java create mode 100644 azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/TagResource.java create mode 100644 azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/implementation/TagOperationsImpl.java create mode 100644 azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/implementation/TagResourceImpl.java create mode 100644 azure-mgmt-resources/src/test/java/com/microsoft/azure/management/resources/TagsTests.java create mode 100644 azure-mgmt-resources/src/test/resources/session-records/canUpdateTag.json diff --git a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/TagOperations.java b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/TagOperations.java new file mode 100644 index 00000000000..15fea8e1e13 --- /dev/null +++ b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/TagOperations.java @@ -0,0 +1,56 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.azure.management.resources; + +import com.microsoft.azure.management.resources.fluentcore.arm.models.HasManager; +import com.microsoft.azure.management.resources.fluentcore.arm.models.Resource; +import com.microsoft.azure.management.resources.implementation.ResourceManager; +import rx.Observable; + +import java.util.Map; + +/** + * Entry point to tag management API. + */ +public interface TagOperations extends HasManager { + + /** + * Updates the tags of the Azure resource. + * + * @param resource the Azure resource to have its tags updated + * @param tags the tags + * @return the resource with updated tags + */ + TagResource updateTags(Resource resource, Map tags); + + /** + * Updates the tags of the Azure resource. + * + * @param resourceId the ID of the Azure resource to have its tags updated + * @param tags the tags + * @return the resource with updated tags + */ + TagResource updateTags(String resourceId, Map tags); + + /** + * Updates the tags of the Azure resource. + * + * @param resource the Azure resource to have its tags updated + * @param tags the tags + * @return the resource with updated tags + */ + Observable updateTagsAsync(Resource resource, Map tags); + + /** + * Updates the tags of the Azure resource. + * + * @param resourceId the ID of the Azure resource to have its tags updated + * @param tags the tags + * @return the resource with updated tags + */ + Observable updateTagsAsync(String resourceId, Map tags); +} diff --git a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/TagResource.java b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/TagResource.java new file mode 100644 index 00000000000..23b90c823da --- /dev/null +++ b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/TagResource.java @@ -0,0 +1,32 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.azure.management.resources; + + +import com.microsoft.azure.management.resources.fluentcore.arm.models.HasId; +import com.microsoft.azure.management.resources.fluentcore.arm.models.HasName; +import com.microsoft.azure.management.resources.fluentcore.model.HasInner; +import com.microsoft.azure.management.resources.implementation.TagsResourceInner; + +import java.util.Map; + +/** + * An immutable client-side representation of an Azure resource with tags. + */ +public interface TagResource extends + HasId, HasName, HasInner { + + /** + * @return the type of the resource + */ + String type(); + + /** + * @return the tags for the resource + */ + Map tags(); +} diff --git a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/implementation/ResourceManager.java b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/implementation/ResourceManager.java index 109f7b7577c..d6793f331a0 100644 --- a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/implementation/ResourceManager.java +++ b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/implementation/ResourceManager.java @@ -17,6 +17,7 @@ import com.microsoft.azure.management.resources.Providers; import com.microsoft.azure.management.resources.ResourceGroups; import com.microsoft.azure.management.resources.Subscriptions; +import com.microsoft.azure.management.resources.TagOperations; import com.microsoft.azure.management.resources.Tenants; import com.microsoft.azure.management.resources.fluentcore.arm.AzureConfigurable; import com.microsoft.azure.management.resources.fluentcore.arm.implementation.AzureConfigurableImpl; @@ -46,6 +47,7 @@ public final class ResourceManager extends ManagerBase implements HasInner tags) { + return this.updateTagsAsync(resource, tags).toBlocking().last(); + } + + @Override + public TagResource updateTags(String resourceId, Map tags) { + return this.updateTagsAsync(resourceId, tags).toBlocking().last(); + } + + @Override + public Observable updateTagsAsync(Resource resource, Map tags) { + return this.updateTagsAsync(Objects.requireNonNull(resource).id(), tags); + } + + @Override + public Observable updateTagsAsync(String resourceId, Map tags) { + TagsPatchResource parameters = new TagsPatchResource() + .withOperation(TagsPatchOperation.REPLACE) + .withProperties(new Tags().withTags(new TreeMap<>(tags))); + return this.manager().inner().tagOperations() + .updateAtScopeAsync(resourceId, parameters) + .map(new Func1() { + @Override + public TagResource call(TagsResourceInner inner) { + return new TagResourceImpl(inner); + } + }); + } + + @Override + public ResourceManager manager() { + return this.myManager; + } +} diff --git a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/implementation/TagResourceImpl.java b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/implementation/TagResourceImpl.java new file mode 100644 index 00000000000..37c09d25223 --- /dev/null +++ b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/implementation/TagResourceImpl.java @@ -0,0 +1,48 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.azure.management.resources.implementation; + +import com.microsoft.azure.management.resources.TagResource; + +import java.util.Collections; +import java.util.Map; + +final class TagResourceImpl implements TagResource { + + private final TagsResourceInner innerObject; + + TagResourceImpl(TagsResourceInner inner) { + this.innerObject = inner; + } + + @Override + public TagsResourceInner inner() { + return this.innerObject; + } + + @Override + public String id() { + return this.inner().id(); + } + + @Override + public String name() { + return this.inner().name(); + } + + @Override + public String type() { + return this.inner().type(); + } + + @Override + public Map tags() { + return this.inner().properties() == null + ? Collections.emptyMap() + : Collections.unmodifiableMap(this.inner().properties().tags()); + } +} diff --git a/azure-mgmt-resources/src/test/java/com/microsoft/azure/management/resources/TagsTests.java b/azure-mgmt-resources/src/test/java/com/microsoft/azure/management/resources/TagsTests.java new file mode 100644 index 00000000000..ff81272b57e --- /dev/null +++ b/azure-mgmt-resources/src/test/java/com/microsoft/azure/management/resources/TagsTests.java @@ -0,0 +1,39 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +package com.microsoft.azure.management.resources; + +import com.microsoft.azure.management.resources.implementation.TypeSerializationTests; +import org.junit.Assert; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +public class TagsTests extends ResourceManagerTestBase { + + @Test + public void canUpdateTag() throws Exception { + // assume there is a resource + GenericResource resource = resourceClient.genericResources().list().iterator().next(); + + Map originalTags = resource.tags(); + if (originalTags == null) { + originalTags = new HashMap<>(); + } + + TagResource updatedTags = resourceClient.tagOperations().updateTags(resource, new TypeSerializationTests.Map1<>("tag.1", "value.1")); + Assert.assertEquals(1, updatedTags.tags().size()); + Assert.assertTrue(updatedTags.tags().containsKey("tag.1")); + Assert.assertEquals("value.1", updatedTags.tags().get("tag.1")); + + updatedTags = resourceClient.tagOperations().updateTags(resource, new HashMap()); + Assert.assertEquals(0, updatedTags.tags().size()); + + updatedTags = resourceClient.tagOperations().updateTags(resource, originalTags); + Assert.assertEquals(originalTags, updatedTags.tags()); + } +} diff --git a/azure-mgmt-resources/src/test/java/com/microsoft/azure/management/resources/implementation/TypeSerializationTests.java b/azure-mgmt-resources/src/test/java/com/microsoft/azure/management/resources/implementation/TypeSerializationTests.java index f20cc8a8e14..05179656f88 100644 --- a/azure-mgmt-resources/src/test/java/com/microsoft/azure/management/resources/implementation/TypeSerializationTests.java +++ b/azure-mgmt-resources/src/test/java/com/microsoft/azure/management/resources/implementation/TypeSerializationTests.java @@ -7,15 +7,85 @@ package com.microsoft.azure.management.resources.implementation; import com.microsoft.azure.management.resources.DeploymentProperties; +import com.microsoft.azure.management.resources.Tags; +import com.microsoft.azure.management.resources.TagsPatchOperation; +import com.microsoft.azure.management.resources.TagsPatchResource; import com.microsoft.azure.serializer.AzureJacksonAdapter; import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; +import java.lang.reflect.Field; +import java.util.AbstractMap; +import java.util.Collections; +import java.util.HashSet; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + public class TypeSerializationTests { + public static final class Map1 extends AbstractMap { + private final K k0; + private final V v0; + + public Map1(K k0, V v0) { + this.k0 = Objects.requireNonNull(k0); + this.v0 = Objects.requireNonNull(v0); + } + + @Override + public Set> entrySet() { + Entry entry = new AbstractMap.SimpleEntry<>(k0, v0); + return new HashSet<>(Collections.singletonList(entry)); + } + + @Override + public V get(Object o) { + return o.equals(k0) ? v0 : null; + } + + @Override + public boolean containsKey(Object o) { + return o.equals(k0); + } + + @Override + public boolean containsValue(Object o) { + return o.equals(v0); // implicit nullcheck of o + } + + @Override + public int size() { + return 1; + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public int hashCode() { + return k0.hashCode() ^ v0.hashCode(); + } + } + + @Test + @Ignore("fails if Map is final") + public void testTagsPatchResourceSerialization() throws Exception { + Map tags = new Map1<>("tag.1", "value.1"); + + TagsPatchResource tagsPatchResource = new TagsPatchResource() + .withOperation(TagsPatchOperation.REPLACE) + .withProperties(new Tags().withTags(tags)); + + AzureJacksonAdapter serializerAdapter = new AzureJacksonAdapter(); + String tagsPatchResourceJson = serializerAdapter.serialize(tagsPatchResource); + Assert.assertTrue(tagsPatchResourceJson.contains("tag.1")); + } + @Test - @Ignore("To fix later as swagger changes on DeploymentExtendedInner") public void testDeploymentSerialization() throws Exception { final String templateJson = "{ \"/subscriptions//resourceGroups//providers/Microsoft.ManagedIdentity/userAssignedIdentities/\": {} }"; @@ -27,11 +97,15 @@ public void testDeploymentSerialization() throws Exception { Assert.assertTrue(deploymentJson.contains("Microsoft.ManagedIdentity")); } - private static DeploymentInner createRequestFromInner(DeploymentImpl deployment) { + private static DeploymentInner createRequestFromInner(DeploymentImpl deployment) throws NoSuchFieldException, IllegalAccessException { + Field field = DeploymentImpl.class.getDeclaredField("deploymentCreateUpdateParameters"); + field.setAccessible(true); + DeploymentInner implInner = (DeploymentInner) field.get(deployment); + DeploymentInner inner = new DeploymentInner() .withProperties(new DeploymentProperties()); inner.properties().withMode(deployment.mode()); - inner.properties().withTemplate("{\"$schema\":\"https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#\",\"contentVersion\":\"1.0.0.0\",\"parameters\":{\"vnetName\":{\"type\":\"string\",\"defaultValue\":\"VNet2\",\"metadata\":{\"description\":\"VNet name\"}},\"vnetAddressPrefix\":{\"type\":\"string\",\"defaultValue\":\"10.0.0.0/16\",\"metadata\":{\"description\":\"Address prefix\"}},\"subnet1Prefix\":{\"type\":\"string\",\"defaultValue\":\"10.0.0.0/24\",\"metadata\":{\"description\":\"Subnet 1 Prefix\"}},\"subnet1Name\":{\"type\":\"string\",\"defaultValue\":\"Subnet1\",\"metadata\":{\"description\":\"Subnet 1 Name\"}},\"subnet2Prefix\":{\"type\":\"string\",\"defaultValue\":\"10.0.1.0/24\",\"metadata\":{\"description\":\"Subnet 2 Prefix\"}},\"subnet2Name\":{\"type\":\"string\",\"defaultValue\":\"Subnet222\",\"metadata\":{\"description\":\"Subnet 2 Name\"}}},\"variables\":{\"apiVersion\":\"2015-06-15\"},\"resources\":[{\"apiVersion\":\"[variables('apiVersion')]\",\"type\":\"Microsoft.Network/virtualNetworks\",\"name\":\"[parameters('vnetName')]\",\"location\":\"[resourceGroup().location]\",\"properties\":{\"addressSpace\":{\"addressPrefixes\":[\"[parameters('vnetAddressPrefix')]\"]},\"subnets\":[{\"name\":\"[parameters('subnet1Name')]\",\"properties\":{\"addressPrefix\":\"[parameters('subnet1Prefix')]\"}},{\"name\":\"[parameters('subnet2Name')]\",\"properties\":{\"addressPrefix\":\"[parameters('subnet2Prefix')]\"}}]}}]}"); + inner.properties().withTemplate(implInner.properties().template()); inner.properties().withTemplateLink(deployment.templateLink()); inner.properties().withParameters(deployment.parameters()); inner.properties().withParametersLink(deployment.parametersLink()); diff --git a/azure-mgmt-resources/src/test/resources/session-records/canUpdateTag.json b/azure-mgmt-resources/src/test/resources/session-records/canUpdateTag.json new file mode 100644 index 00000000000..e80005146bd --- /dev/null +++ b/azure-mgmt-resources/src/test/resources/session-records/canUpdateTag.json @@ -0,0 +1,104 @@ +{ + "networkCallRecords" : [ { + "Method" : "GET", + "Uri" : "http://localhost:1234/subscriptions/00000000-0000-0000-0000-000000000000/resources?api-version=2020-06-01", + "Headers" : { + "User-Agent" : "Azure-SDK-For-Java/null OS:Windows 10/10.0 MacAddressHash:16d667ba85a69c1ee0ed809f30ffb817b9aa9960347395fa339605f5be4092c1 Java:15.0.1 (ResourceManagementClient, 2020-06-01)", + "Content-Type" : "application/json; charset=utf-8" + }, + "Response" : { + "date" : "Fri, 26 Mar 2021 07:33:10 GMT", + "content-length" : "6372", + "expires" : "-1", + "vary" : "Accept-Encoding", + "retry-after" : "0", + "x-ms-ratelimit-remaining-subscription-reads" : "11999", + "StatusCode" : "200", + "pragma" : "no-cache", + "strict-transport-security" : "max-age=31536000; includeSubDomains", + "x-ms-correlation-request-id" : "13af533f-3c67-47b6-871a-f2c824cbcca8", + "x-content-type-options" : "nosniff", + "x-ms-routing-request-id" : "SOUTHEASTASIA:20210326T073311Z:13af533f-3c67-47b6-871a-f2c824cbcca8", + "content-type" : "application/json; charset=utf-8", + "cache-control" : "no-cache", + "x-ms-request-id" : "13af533f-3c67-47b6-871a-f2c824cbcca8", + "Body" : "{\"value\":[{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/azfluent/providers/Microsoft.KeyVault/vaults/azfluent\",\"name\":\"azfluent\",\"type\":\"Microsoft.KeyVault/vaults\",\"location\":\"westus\",\"tags\":{}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/AzSecPackAutoConfigRG/providers/Microsoft.ManagedIdentity/userAssignedIdentities/AzSecPackAutoConfigUA-eastus2euap\",\"name\":\"AzSecPackAutoConfigUA-eastus2euap\",\"type\":\"Microsoft.ManagedIdentity/userAssignedIdentities\",\"location\":\"eastus2euap\",\"tags\":{}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/AzSecPackAutoConfigRG/providers/Microsoft.ManagedIdentity/userAssignedIdentities/AzSecPackAutoConfigUA-southcentralus\",\"name\":\"AzSecPackAutoConfigUA-southcentralus\",\"type\":\"Microsoft.ManagedIdentity/userAssignedIdentities\",\"location\":\"southcentralus\",\"tags\":{}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/AzSecPackAutoConfigRG/providers/Microsoft.ManagedIdentity/userAssignedIdentities/AzSecPackAutoConfigUA-westus2\",\"name\":\"AzSecPackAutoConfigUA-westus2\",\"type\":\"Microsoft.ManagedIdentity/userAssignedIdentities\",\"location\":\"westus2\",\"tags\":{}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/lenatest/providers/Microsoft.Network/expressRouteCircuits/lenatest\",\"name\":\"lenatest\",\"type\":\"Microsoft.Network/expressRouteCircuits\",\"sku\":{\"name\":\"Premium_UnlimitedData\",\"tier\":\"Premium\",\"family\":\"UnlimitedData\"},\"location\":\"westus2\"},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/NetworkWatcherRG/providers/Microsoft.Network/networkWatchers/NetworkWatcher_westus\",\"name\":\"NetworkWatcher_westus\",\"type\":\"Microsoft.Network/networkWatchers\",\"location\":\"westus\"},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-weidxu/providers/microsoft.alertsmanagement/smartDetectorAlertRules/Failure Anomalies - fa1weidxu\",\"name\":\"Failure Anomalies - fa1weidxu\",\"type\":\"microsoft.alertsmanagement/smartDetectorAlertRules\",\"location\":\"global\",\"tags\":{}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-weidxu/providers/Microsoft.Compute/images/vm1image1\",\"name\":\"vm1image1\",\"type\":\"Microsoft.Compute/images\",\"location\":\"westus2\",\"tags\":{}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-weidxu/providers/microsoft.insights/actiongroups/Application Insights Smart Detection\",\"name\":\"Application Insights Smart Detection\",\"type\":\"microsoft.insights/actiongroups\",\"location\":\"global\"},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-weidxu/providers/microsoft.insights/components/fa1weidxu\",\"name\":\"fa1weidxu\",\"type\":\"microsoft.insights/components\",\"kind\":\"web\",\"location\":\"centralus\",\"tags\":{}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-weidxu/providers/Microsoft.ServiceBus/namespaces/sb1weidxu\",\"name\":\"sb1weidxu\",\"type\":\"Microsoft.ServiceBus/namespaces\",\"sku\":{\"name\":\"Basic\",\"tier\":\"Basic\"},\"location\":\"westcentralus\",\"tags\":{}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-weidxu/providers/Microsoft.Storage/storageAccounts/lock1weidxu\",\"name\":\"lock1weidxu\",\"type\":\"Microsoft.Storage/storageAccounts\",\"sku\":{\"name\":\"Standard_LRS\",\"tier\":\"Standard\"},\"kind\":\"BlobStorage\",\"location\":\"eastus\",\"tags\":{}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-weidxu/providers/Microsoft.Storage/storageAccounts/storageaccountrgwei88db\",\"name\":\"storageaccountrgwei88db\",\"type\":\"Microsoft.Storage/storageAccounts\",\"sku\":{\"name\":\"Standard_LRS\",\"tier\":\"Standard\"},\"kind\":\"Storage\",\"location\":\"centralus\",\"tags\":{}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-weidxu/providers/Microsoft.Web/serverFarms/ASP-rgweidxu-8b75\",\"name\":\"ASP-rgweidxu-8b75\",\"type\":\"Microsoft.Web/serverFarms\",\"sku\":{\"name\":\"Y1\",\"tier\":\"Dynamic\",\"size\":\"Y1\",\"family\":\"Y\",\"capacity\":0},\"kind\":\"functionapp\",\"location\":\"centralus\"},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-weidxu/providers/Microsoft.Web/sites/fa1weidxu\",\"name\":\"fa1weidxu\",\"type\":\"Microsoft.Web/sites\",\"kind\":\"functionapp\",\"location\":\"centralus\"},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rgac6642161bef4/providers/Microsoft.Network/expressRouteCircuits/erc18d7754853f7\",\"name\":\"erc18d7754853f7\",\"type\":\"Microsoft.Network/expressRouteCircuits\",\"sku\":{\"name\":\"Premium_MeteredData\",\"tier\":\"Premium\",\"family\":\"MeteredData\"},\"location\":\"westus2\",\"tags\":{}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/subscriptionScrubber/providers/Microsoft.Automation/automationAccounts/cleanupResourcegroup\",\"name\":\"cleanupResourcegroup\",\"type\":\"Microsoft.Automation/automationAccounts\",\"location\":\"eastus2\",\"tags\":{}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/subscriptionScrubber/providers/Microsoft.Automation/automationAccounts/cleanupResourcegroup/runbooks/AzureClassicAutomationTutorial\",\"name\":\"cleanupResourcegroup/AzureClassicAutomationTutorial\",\"type\":\"Microsoft.Automation/automationAccounts/runbooks\",\"location\":\"eastus2\",\"tags\":{}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/subscriptionScrubber/providers/Microsoft.Automation/automationAccounts/cleanupResourcegroup/runbooks/AzureClassicAutomationTutorialScript\",\"name\":\"cleanupResourcegroup/AzureClassicAutomationTutorialScript\",\"type\":\"Microsoft.Automation/automationAccounts/runbooks\",\"location\":\"eastus2\",\"tags\":{}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/subscriptionScrubber/providers/Microsoft.Automation/automationAccounts/cleanupResourcegroup/runbooks/cleanupResourcegroup\",\"name\":\"cleanupResourcegroup/cleanupResourcegroup\",\"type\":\"Microsoft.Automation/automationAccounts/runbooks\",\"location\":\"eastus2\",\"tags\":{}},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/tanyi/providers/Microsoft.DomainRegistration/domains/testhub.biz\",\"name\":\"testhub.biz\",\"type\":\"Microsoft.DomainRegistration/domains\",\"location\":\"global\"},{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/tanyi/providers/Microsoft.Network/dnszones/testhub.biz\",\"name\":\"testhub.biz\",\"type\":\"Microsoft.Network/dnszones\",\"location\":\"global\",\"tags\":{}}]}" + } + }, { + "Method" : "PATCH", + "Uri" : "http://localhost:1234/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/azfluent/providers/Microsoft.KeyVault/vaults/azfluent/providers/Microsoft.Resources/tags/default?api-version=2020-06-01", + "Headers" : { + "User-Agent" : "Azure-SDK-For-Java/null OS:Windows 10/10.0 MacAddressHash:16d667ba85a69c1ee0ed809f30ffb817b9aa9960347395fa339605f5be4092c1 Java:15.0.1 (ResourceManagementClient, 2020-06-01)", + "Content-Type" : "application/json; charset=utf-8" + }, + "Response" : { + "date" : "Fri, 26 Mar 2021 07:33:16 GMT", + "content-length" : "265", + "expires" : "-1", + "vary" : "Accept-Encoding", + "x-ms-ratelimit-remaining-subscription-writes" : "1199", + "retry-after" : "0", + "StatusCode" : "200", + "pragma" : "no-cache", + "strict-transport-security" : "max-age=31536000; includeSubDomains", + "x-ms-correlation-request-id" : "f38266a2-5f3c-47de-8442-bd488b0cfa04", + "x-content-type-options" : "nosniff", + "x-ms-routing-request-id" : "SOUTHEASTASIA:20210326T073317Z:f38266a2-5f3c-47de-8442-bd488b0cfa04", + "content-type" : "application/json; charset=utf-8", + "cache-control" : "no-cache", + "x-ms-request-id" : "f38266a2-5f3c-47de-8442-bd488b0cfa04", + "Body" : "{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/azfluent/providers/Microsoft.KeyVault/vaults/azfluent/providers/Microsoft.Resources/tags/default\",\"name\":\"default\",\"type\":\"Microsoft.Resources/tags\",\"properties\":{\"tags\":{\"tag.1\":\"value.1\"}}}" + } + }, { + "Method" : "PATCH", + "Uri" : "http://localhost:1234/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/azfluent/providers/Microsoft.KeyVault/vaults/azfluent/providers/Microsoft.Resources/tags/default?api-version=2020-06-01", + "Headers" : { + "User-Agent" : "Azure-SDK-For-Java/null OS:Windows 10/10.0 MacAddressHash:16d667ba85a69c1ee0ed809f30ffb817b9aa9960347395fa339605f5be4092c1 Java:15.0.1 (ResourceManagementClient, 2020-06-01)", + "Content-Type" : "application/json; charset=utf-8" + }, + "Response" : { + "date" : "Fri, 26 Mar 2021 07:33:19 GMT", + "content-length" : "248", + "expires" : "-1", + "vary" : "Accept-Encoding", + "x-ms-ratelimit-remaining-subscription-writes" : "1198", + "retry-after" : "0", + "StatusCode" : "200", + "pragma" : "no-cache", + "strict-transport-security" : "max-age=31536000; includeSubDomains", + "x-ms-correlation-request-id" : "e1ef37a6-db62-49b8-9f0e-285888472631", + "x-content-type-options" : "nosniff", + "x-ms-routing-request-id" : "SOUTHEASTASIA:20210326T073320Z:e1ef37a6-db62-49b8-9f0e-285888472631", + "content-type" : "application/json; charset=utf-8", + "cache-control" : "no-cache", + "x-ms-request-id" : "e1ef37a6-db62-49b8-9f0e-285888472631", + "Body" : "{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/azfluent/providers/Microsoft.KeyVault/vaults/azfluent/providers/Microsoft.Resources/tags/default\",\"name\":\"default\",\"type\":\"Microsoft.Resources/tags\",\"properties\":{\"tags\":{}}}" + } + }, { + "Method" : "PATCH", + "Uri" : "http://localhost:1234/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/azfluent/providers/Microsoft.KeyVault/vaults/azfluent/providers/Microsoft.Resources/tags/default?api-version=2020-06-01", + "Headers" : { + "User-Agent" : "Azure-SDK-For-Java/null OS:Windows 10/10.0 MacAddressHash:16d667ba85a69c1ee0ed809f30ffb817b9aa9960347395fa339605f5be4092c1 Java:15.0.1 (ResourceManagementClient, 2020-06-01)", + "Content-Type" : "application/json; charset=utf-8" + }, + "Response" : { + "date" : "Fri, 26 Mar 2021 07:33:22 GMT", + "content-length" : "248", + "expires" : "-1", + "vary" : "Accept-Encoding", + "x-ms-ratelimit-remaining-subscription-writes" : "1197", + "retry-after" : "0", + "StatusCode" : "200", + "pragma" : "no-cache", + "strict-transport-security" : "max-age=31536000; includeSubDomains", + "x-ms-correlation-request-id" : "9cf9ea79-d336-4ff9-9faa-6fb694b34f20", + "x-content-type-options" : "nosniff", + "x-ms-routing-request-id" : "SOUTHEASTASIA:20210326T073323Z:9cf9ea79-d336-4ff9-9faa-6fb694b34f20", + "content-type" : "application/json; charset=utf-8", + "cache-control" : "no-cache", + "x-ms-request-id" : "9cf9ea79-d336-4ff9-9faa-6fb694b34f20", + "Body" : "{\"id\":\"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/azfluent/providers/Microsoft.KeyVault/vaults/azfluent/providers/Microsoft.Resources/tags/default\",\"name\":\"default\",\"type\":\"Microsoft.Resources/tags\",\"properties\":{\"tags\":{}}}" + } + } ], + "variables" : [ "1cc363e6-a49e-439f-8452-c385af0c1255", "1d2fe92a-043b-4019-832f-f24dd5a91172", "a1ec26f2-e413-4599-9e3b-41c754bf0b61", "5d45433e-18a2-4f3e-9cdc-611a7fce77a5", "95afbe75-395f-45c4-8934-8cf850fc86e5", "b16dc1a3-b42d-43c7-999e-02f322526334", "704be8c2-27af-46b1-989c-ff433a8f5bdd", "24082f76-8412-4b72-aceb-c9db457f72f7", "5cdc6fcd-7d17-43fa-a8ad-e04a07b9e1e7", "f500c6c1-47b3-4ad7-8ddd-505ddb5fed6d", "38508a42-ca87-4b51-b464-1049e9dffa9a", "6efca8c8-9f14-4f00-82ce-46c44248c601", "c0823bff-bfaa-4ccf-82f4-65adc64f4f25", "eb472b33-41c9-4f0d-980b-c8631fa796a7", "948c6d3d-f7c5-46ea-a570-79faa8a225f2", "259a139b-5bb0-48fe-90fb-e5d4209e0729", "debd6a1f-1d3f-4936-8996-538af520f9c1", "95488135-5917-4569-83de-8e5c47631f90", "a14a7eb6-d09c-46a2-94c6-20649d75f560", "64e12725-f6f5-4555-8766-64dff79ae238", "38ff2a86-b009-4da1-abea-285ebefe81a9", "9781e86b-f3ba-46d3-9da3-99b696badd96" ] +} \ No newline at end of file diff --git a/azure/src/main/java/com/microsoft/azure/management/Azure.java b/azure/src/main/java/com/microsoft/azure/management/Azure.java index dc8d420079a..75fa08a9668 100644 --- a/azure/src/main/java/com/microsoft/azure/management/Azure.java +++ b/azure/src/main/java/com/microsoft/azure/management/Azure.java @@ -102,6 +102,7 @@ import com.microsoft.azure.management.resources.ResourceGroups; import com.microsoft.azure.management.resources.Subscription; import com.microsoft.azure.management.resources.Subscriptions; +import com.microsoft.azure.management.resources.TagOperations; import com.microsoft.azure.management.resources.Tenants; import com.microsoft.azure.management.resources.fluentcore.arm.AzureConfigurable; import com.microsoft.azure.management.resources.fluentcore.arm.implementation.AzureConfigurableImpl; @@ -1036,4 +1037,9 @@ public BlobServices storageBlobServices() { public ManagementPolicies storageManagementPolicies() { return this.storageManager.managementPolicies(); } + + /** @return entry point to tag management management */ + public TagOperations tagOperations() { + return this.resourceManager.tagOperations(); + } }