diff --git a/sdk/eventhubs/azure-messaging-eventhubs/samples/consume-events/consume_events.cpp b/sdk/eventhubs/azure-messaging-eventhubs/samples/consume-events/consume_events.cpp index 8b2f788ac..834bbba20 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/samples/consume-events/consume_events.cpp +++ b/sdk/eventhubs/azure-messaging-eventhubs/samples/consume-events/consume_events.cpp @@ -43,8 +43,15 @@ int main() auto partitionProperties{ consumerClient.GetPartitionProperties(eventhubProperties.PartitionIds[0])}; - Azure::Messaging::EventHubs::PartitionClient partitionClient{ - consumerClient.CreatePartitionClient(eventhubProperties.PartitionIds[0])}; + // Create a PartitionClient that we can use to read events from a specific partition. + // + // This partition client is configured to read events from the start of the partition, since the + // default is to read new events only. + Azure::Messaging::EventHubs::PartitionClientOptions partitionClientOptions; + partitionClientOptions.StartPosition.Earliest = true; + partitionClientOptions.StartPosition.Inclusive = true; + Azure::Messaging::EventHubs::PartitionClient partitionClient{consumerClient.CreatePartitionClient( + eventhubProperties.PartitionIds[0], partitionClientOptions)}; std::vector events = partitionClient.ReceiveEvents(4); diff --git a/sdk/eventhubs/azure-messaging-eventhubs/samples/consume-events/consume_events_aad.cpp b/sdk/eventhubs/azure-messaging-eventhubs/samples/consume-events/consume_events_aad.cpp index 69440e082..7c68271aa 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/samples/consume-events/consume_events_aad.cpp +++ b/sdk/eventhubs/azure-messaging-eventhubs/samples/consume-events/consume_events_aad.cpp @@ -52,8 +52,17 @@ int main() auto partitionProperties{ consumerClient.GetPartitionProperties(eventhubProperties.PartitionIds[0])}; - Azure::Messaging::EventHubs::PartitionClient partitionClient{ - consumerClient.CreatePartitionClient(eventhubProperties.PartitionIds[0])}; + // Create a PartitionClient that we can use to read events from a specific partition (in this + // case, the first partition). + // + // This partition client is configured to read events from the start of the partition, since the + // default is to read new events only. + Azure::Messaging::EventHubs::PartitionClientOptions partitionClientOptions; + partitionClientOptions.StartPosition.Earliest = true; + partitionClientOptions.StartPosition.Inclusive = true; + + Azure::Messaging::EventHubs::PartitionClient partitionClient{consumerClient.CreatePartitionClient( + eventhubProperties.PartitionIds[0], partitionClientOptions)}; std::vector events = partitionClient.ReceiveEvents(4); diff --git a/sdk/eventhubs/azure-messaging-eventhubs/test-resources-post.ps1 b/sdk/eventhubs/azure-messaging-eventhubs/test-resources-post.ps1 new file mode 100644 index 000000000..28e3cf0a9 --- /dev/null +++ b/sdk/eventhubs/azure-messaging-eventhubs/test-resources-post.ps1 @@ -0,0 +1,16 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +# The purpose of this script is to add a small delay between the creation of the live test resources +# and the execution of the live tests. This allows RBAC to replicate and avoids flakiness in the first set +# of live tests that might otherwise start running before RBAC has replicated. + +param ( + [hashtable] $DeploymentOutputs, + [string] $TenantId, + [string] $TestApplicationId, + [string] $TestApplicationSecret +) + +Write-Verbose "Sleeping for 60 seconds to let RBAC replicate" +Start-Sleep -s 60 diff --git a/sdk/eventhubs/azure-messaging-eventhubs/test-resources.json b/sdk/eventhubs/azure-messaging-eventhubs/test-resources.json index f5142ec47..0ee126aa8 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/test-resources.json +++ b/sdk/eventhubs/azure-messaging-eventhubs/test-resources.json @@ -1,5 +1,5 @@ { - "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": { "baseName": { @@ -9,70 +9,112 @@ "description": "The base resource name." } }, + "subscriptionId": { + "type": "string", + "defaultValue": "[subscription().subscriptionId]", + "metadata": { + "description": "The subscription ID to which the application and resources belong." + } + }, + "tenantId": { + "type": "string", + "defaultValue": "[subscription().tenantId]", + "metadata": { + "description": "The tenant ID to which the application and resources belong." + } + }, + "testApplicationOid": { + "type": "string", + "metadata": { + "description": "The client OID to grant access to test resources." + } + }, + "testApplicationId": { + "type": "string", + "metadata": { + "description": "The application client ID used to run tests." + } + }, + "testApplicationSecret": { + "type": "string", + "metadata": { + "description": "The application client secret used to run tests." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "The location of the resources. By default, this is the same as the resource group." + } + }, "storageEndpointSuffix": { "type": "string", "defaultValue": "core.windows.net", "metadata": { - "description": "Storage endpoint suffix. The default value uses Azure Public Cloud (core.windows.net)" + "description": "The url suffix to use when creating storage connection strings." + } + }, + "perTestExecutionLimitMinutes": { + "type": "string", + "defaultValue": "15", + "metadata": { + "description": "The maximum duration, in minutes, that a single test is permitted to run before it is considered at-risk for being hung." } } }, "variables": { "apiVersion": "2017-04-01", - "storageApiVersion": "2019-04-01", - "iotApiVersion": "2018-04-01", - "namespaceName": "[parameters('baseName')]", - "storageAccountName": "[concat('storage', parameters('baseName'))]", - "containerName": "container", - "authorizationName": "[concat(parameters('baseName'), '/RootManageSharedAccessKey')]", - "eventHubName": "eventhub", - "eventHubNameFull": "[concat(parameters('baseName'), '/eventhub')]", - "location": "[resourceGroup().location]" + "eventHubName": "eventHub", + "contributorRoleId": "b24988ac-6180-42a0-ab88-20f7382dd24c", + "eventHubsDataOwnerRoleId": "f526a384-b230-433a-b45c-95f59c4a2dec", + "storageDataOwnerRoleId": "b7e6dc6d-f1e8-4753-8033-0f276bb0955b", + "eventHubsNamespace": "[concat('eh-', parameters('baseName'))]", + "storageAccount": "[concat('blb', parameters('baseName'))]", + "defaultSASKeyName": "RootManageSharedAccessKey", + "eventHubsAuthRuleResourceId": "[resourceId('Microsoft.EventHub/namespaces/authorizationRules', variables('eventHubsNamespace'), variables('defaultSASKeyName'))]", + "storageAccountId": "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccount'))]", + "authorizationName": "[concat(variables('eventHubsNamespace'), '/RootManageSharedAccessKey')]" }, "resources": [ { - "type": "Microsoft.EventHub/namespaces", + "type": "Microsoft.EventHub/Namespaces", "apiVersion": "[variables('apiVersion')]", - "name": "[variables('namespaceName')]", - "location": "[variables('location')]", + "name": "[variables('eventHubsNamespace')]", + "location": "[parameters('location')]", "sku": { "name": "Standard", "tier": "Standard", "capacity": 5 - }, - "properties": { - "zoneRedundant": false, - "isAutoInflateEnabled": false, - "maximumThroughputUnits": 0 } }, { - "type": "Microsoft.EventHub/namespaces/AuthorizationRules", + "type": "Microsoft.EventHub/Namespaces/AuthorizationRules", "apiVersion": "[variables('apiVersion')]", "name": "[variables('authorizationName')]", - "location": "[variables('location')]", - "dependsOn": ["[resourceId('Microsoft.EventHub/namespaces', variables('namespaceName'))]"], + "location": "[parameters('location')]", + "dependsOn": [ "[resourceId('Microsoft.EventHub/namespaces', variables('eventHubsNamespace'))]" ], "properties": { - "rights": ["Listen", "Manage", "Send"] + "rights": [ "Listen", "Manage", "Send" ] } }, { - "type": "Microsoft.EventHub/namespaces/eventhubs", + "type": "Microsoft.EventHub/Namespaces/EventHubs", "apiVersion": "[variables('apiVersion')]", - "name": "[variables('eventHubNameFull')]", - "location": "[variables('location')]", - "dependsOn": ["[resourceId('Microsoft.EventHub/namespaces', variables('namespaceName'))]"], + "name": "[concat(variables('eventHubsNamespace'), '/', variables('eventHubName'))]", + "location": "[parameters('location')]", + "dependsOn": [ "[resourceId('Microsoft.EventHub/Namespaces', variables('eventHubsNamespace'))]" ], "properties": { "messageRetentionInDays": 1, "partitionCount": 4 } }, { - "type": "Microsoft.EventHub/namespaces/networkRuleSets", + "type": "Microsoft.EventHub/Namespaces/NetworkRuleSets", "apiVersion": "[variables('apiVersion')]", - "name": "[concat(variables('namespaceName'), '/default')]", - "location": "[variables('location')]", - "dependsOn": ["[resourceId('Microsoft.EventHub/namespaces', variables('namespaceName'))]"], + "name": "[concat(variables('eventHubsNamespace'), '/default')]", + "location": "[parameters('location')]", + "dependsOn": [ "[resourceId('Microsoft.EventHub/Namespaces', variables('eventHubsNamespace'))]" ], "properties": { "defaultAction": "Deny", "virtualNetworkRules": [], @@ -80,26 +122,26 @@ } }, { - "type": "Microsoft.EventHub/namespaces/eventhubs/consumergroups", + "type": "Microsoft.EventHub/Namespaces/EventHubs/ConsumerGroups", "apiVersion": "[variables('apiVersion')]", - "name": "[concat(variables('eventHubNameFull'), '/$Default')]", - "location": "[variables('location')]", + "name": "[concat(variables('eventHubsNamespace'), '/', variables('eventHubName'), '/$Default')]", + "location": "[parameters('location')]", "dependsOn": [ - "[resourceId('Microsoft.EventHub/namespaces/eventhubs', variables('namespaceName'), variables('eventHubName'))]", - "[resourceId('Microsoft.EventHub/namespaces', variables('namespaceName'))]" + "[resourceId('Microsoft.EventHub/namespaces/eventhubs', variables('eventHubsNamespace'), variables('eventHubName'))]", + "[resourceId('Microsoft.EventHub/namespaces', variables('eventHubsNamespace'))]" ], "properties": {} }, { "type": "Microsoft.Storage/storageAccounts", - "apiVersion": "[variables('storageApiVersion')]", - "name": "[variables('storageAccountName')]", - "location": "[resourceGroup().location]", + "apiVersion": "2019-04-01", + "name": "[variables('storageAccount')]", + "location": "[parameters('location')]", "sku": { - "name": "Standard_RAGRS", + "name": "Standard_LRS", "tier": "Standard" }, - "kind": "StorageV2", + "kind": "BlobStorage", "properties": { "networkAcls": { "bypass": "AzureServices", @@ -120,16 +162,66 @@ "keySource": "Microsoft.Storage" }, "accessTier": "Hot" - }, - "resources": [ - { - "name": "[concat('default/', variables('containerName'))]", - "type": "blobServices/containers", - "apiVersion": "[variables('storageApiVersion')]", - "dependsOn": ["[variables('storageAccountName')]"] - } - ] + } }, + { + "type": "Microsoft.Storage/storageAccounts/blobServices", + "apiVersion": "2019-04-01", + "name": "[concat(variables('storageAccount'), '/default')]", + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccount'))]" + ], + "properties": { + "cors": { + "corsRules": [] + }, + "deleteRetentionPolicy": { + "enabled": false + } + } + }, + { + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2019-04-01-preview", + "name": "[guid(resourceGroup().id, parameters('testApplicationOid'), variables('eventHubsDataOwnerRoleId'))]", + "dependsOn": [ + "[resourceId('Microsoft.EventHub/Namespaces', variables('eventHubsNamespace'))]", + "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccount'))]" + ], + "properties": { + "roleDefinitionId": "[resourceId('Microsoft.Authorization/roleDefinitions', variables('eventHubsDataOwnerRoleId'))]", + "principalId": "[parameters('testApplicationOid')]", + "scope": "[resourceGroup().id]" + } + }, + { + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2019-04-01-preview", + "name": "[guid(resourceGroup().id, parameters('testApplicationOid'), variables('contributorRoleId'))]", + "dependsOn": [ + "[resourceId('Microsoft.EventHub/Namespaces', variables('eventHubsNamespace'))]", + "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccount'))]" + ], + "properties": { + "roleDefinitionId": "[resourceId('Microsoft.Authorization/roleDefinitions', variables('contributorRoleId'))]", + "principalId": "[parameters('testApplicationOid')]", + "scope": "[resourceGroup().id]" + } + }, + { + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2019-04-01-preview", + "name": "[guid(resourceGroup().id, parameters('testApplicationOid'), variables('storageDataOwnerRoleId'))]", + "dependsOn": [ + "[resourceId('Microsoft.EventHub/Namespaces', variables('eventHubsNamespace'))]", + "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccount'))]" + ], + "properties": { + "roleDefinitionId": "[resourceId('Microsoft.Authorization/roleDefinitions', variables('storageDataOwnerRoleId'))]", + "principalId": "[parameters('testApplicationOid')]", + "scope": "[resourceGroup().id]" + } + } ], "outputs": { "EVENTHUB_NAME": { @@ -138,23 +230,39 @@ }, "EVENTHUBS_HOST": { "type": "string", - "value": "[concat(parameters('baseName'), '.servicebus.windows.net')]" + "value": "[concat(variables('eventHubsNamespace'), '.servicebus.windows.net')]" + }, + "EVENTHUB_STORAGE_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[parameters('storageEndpointSuffix')]" + }, + "EVENTHUB_PER_TEST_LIMIT_MINUTES": { + "type": "string", + "value": "[parameters('perTestExecutionLimitMinutes')]" }, "EVENTHUB_CONNECTION_STRING": { "type": "string", - "value": "[listKeys(resourceId('Microsoft.EventHub/namespaces/authorizationRules', variables('namespaceName'), 'RootManageSharedAccessKey'), variables('apiVersion')).primaryConnectionString]" + "value": "[listkeys(variables('eventHubsAuthRuleResourceId'), '2015-08-01').primaryConnectionString]" }, "CHECKPOINTSTORE_STORAGE_CONNECTION_STRING": { "type": "string", - "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), variables('storageApiVersion')).keys[0].value, ';EndpointSuffix=', parameters('storageEndpointSuffix'))]" - }, - "RESOURCE_GROUP": { - "type": "string", - "value": "[resourceGroup().name]" + "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccount'), ';AccountKey=', listKeys(variables('storageAccountId'), providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).keys[0].value, ';EndpointSuffix=', parameters('storageEndpointSuffix'))]" }, "AZURE_SUBSCRIPTION_ID": { "type": "string", "value": "[subscription().subscriptionId]" + }, + "AZURE_TENANT_ID": { + "type": "string", + "value": "[parameters('tenantId')]" + }, + "AZURE_CLIENT_ID": { + "type": "string", + "value": "[parameters('testApplicationId')]" + }, + "AZURE_CLIENT_SECRET": { + "type": "string", + "value": "[parameters('testApplicationSecret')]" } } }