diff --git a/sdk/core/azure-core/azure/core/rest/_helpers.py b/sdk/core/azure-core/azure/core/rest/_helpers.py index ac3582c9f08c..613ab723120a 100644 --- a/sdk/core/azure-core/azure/core/rest/_helpers.py +++ b/sdk/core/azure-core/azure/core/rest/_helpers.py @@ -35,13 +35,11 @@ Union, Mapping, Sequence, - List, Tuple, IO, Any, Dict, Iterable, - cast, MutableMapping, ) import xml.etree.ElementTree as ET diff --git a/sdk/eventhub/azure-eventhub/stress/Chart.lock b/sdk/eventhub/azure-eventhub/stress/Chart.lock new file mode 100644 index 000000000000..c3c0a4b0aa0b --- /dev/null +++ b/sdk/eventhub/azure-eventhub/stress/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: stress-test-addons + repository: https://stresstestcharts.blob.core.windows.net/helm/ + version: 0.1.6 +digest: sha256:b97697ef5f303eec43e9a94fca8e312d20b8aed71318250499344aeca9880d31 +generated: "2021-08-24T11:24:15.375395-07:00" diff --git a/sdk/eventhub/azure-eventhub/stress/Chart.yaml b/sdk/eventhub/azure-eventhub/stress/Chart.yaml new file mode 100644 index 000000000000..0f42b0429a4b --- /dev/null +++ b/sdk/eventhub/azure-eventhub/stress/Chart.yaml @@ -0,0 +1,13 @@ +apiVersion: v2 +name: python-eventhubs-stress-test +description: python event hubs stress test. +version: 0.1.2 +appVersion: v0.2 +annotations: + stressTest: 'true' + namespace: python-eventhubs-stress-test-ns + +dependencies: +- name: stress-test-addons + version: 0.1.6 + repository: https://stresstestcharts.blob.core.windows.net/helm/ \ No newline at end of file diff --git a/sdk/eventhub/azure-eventhub/stress/Dockerfile b/sdk/eventhub/azure-eventhub/stress/Dockerfile new file mode 100644 index 000000000000..05c55e17da28 --- /dev/null +++ b/sdk/eventhub/azure-eventhub/stress/Dockerfile @@ -0,0 +1,10 @@ +# syntax=docker/dockerfile:1 + +FROM python:3.8-slim-buster + +WORKDIR /app + +COPY ./scripts /app/stress/scripts + +WORKDIR /app/stress/scripts +RUN pip3 install -r dev_requirement.txt diff --git a/sdk/eventhub/azure-eventhub/stress/dev_requirement.txt b/sdk/eventhub/azure-eventhub/stress/dev_requirement.txt deleted file mode 100644 index e4817ded436f..000000000000 --- a/sdk/eventhub/azure-eventhub/stress/dev_requirement.txt +++ /dev/null @@ -1,8 +0,0 @@ -psutil -.. -../../azure-eventhub-checkpointstoreblob -../../azure-eventhub-checkpointstoreblob-aio -azure-servicebus==0.50.3 -azure-storage-blob -azure-identity -opencensus-ext-azure diff --git a/sdk/eventhub/azure-eventhub/stress/parameters.json b/sdk/eventhub/azure-eventhub/stress/parameters.json new file mode 100644 index 000000000000..2df20a6d1780 --- /dev/null +++ b/sdk/eventhub/azure-eventhub/stress/parameters.json @@ -0,0 +1,5 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { } +} \ No newline at end of file diff --git a/sdk/eventhub/azure-eventhub/stress/app_insights_metric.py b/sdk/eventhub/azure-eventhub/stress/scripts/app_insights_metric.py similarity index 97% rename from sdk/eventhub/azure-eventhub/stress/app_insights_metric.py rename to sdk/eventhub/azure-eventhub/stress/scripts/app_insights_metric.py index 7b0945eb07a1..9f814fdf2845 100644 --- a/sdk/eventhub/azure-eventhub/stress/app_insights_metric.py +++ b/sdk/eventhub/azure-eventhub/stress/scripts/app_insights_metric.py @@ -2,9 +2,6 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See License.txt in the project root for license information. # -------------------------------------------------------------------------------------------- - -import os - from opencensus.ext.azure import metrics_exporter from opencensus.stats import aggregation as aggregation_module from opencensus.stats import measure as measure_module @@ -26,7 +23,7 @@ def __init__(self, test_name, test_description=None): self.desc = test_description events_measure_name = "The number of events handled by " + self.name - events_measure_desc = "The number of events handled by " + self.desc if self.desc else None + events_measure_desc = "The number of events handled by" + self.desc if self.desc else None memory_measure_name = "memory usage percentage for " + self.name memory_measure_desc = "memory usage percentage for " + self.desc if self.desc else None cpu_measure_name = "cpu usage percentage for " + self.name diff --git a/sdk/eventhub/azure-eventhub/stress/azure_eventhub_consumer_stress_async.py b/sdk/eventhub/azure-eventhub/stress/scripts/azure_eventhub_consumer_stress_async.py similarity index 93% rename from sdk/eventhub/azure-eventhub/stress/azure_eventhub_consumer_stress_async.py rename to sdk/eventhub/azure-eventhub/stress/scripts/azure_eventhub_consumer_stress_async.py index ad99f73455c0..eadf7fe3f7f6 100644 --- a/sdk/eventhub/azure-eventhub/stress/azure_eventhub_consumer_stress_async.py +++ b/sdk/eventhub/azure-eventhub/stress/scripts/azure_eventhub_consumer_stress_async.py @@ -11,6 +11,7 @@ import logging from collections import defaultdict from functools import partial +from dotenv import load_dotenv from azure.identity.aio import ClientSecretCredential from azure.eventhub.aio import EventHubConsumerClient @@ -22,6 +23,9 @@ from process_monitor import ProcessMonitor from app_insights_metric import AzureMonitorMetric +ENV_FILE = os.environ.get('ENV_FILE') +load_dotenv(dotenv_path=ENV_FILE, override=True) + def parse_starting_position(args): starting_position = None @@ -39,25 +43,26 @@ def parse_starting_position(args): parser = argparse.ArgumentParser() -parser.add_argument("--link_credit", default=3000, type=int) -parser.add_argument("--output_interval", type=float, default=1000) -parser.add_argument("--duration", help="Duration in seconds of the test", type=int, default=30) -parser.add_argument("--consumer_group", help="Consumer group name", default="$default") +parser.add_argument("--link_credit", default=int(os.environ.get("LINK_CREDIT", 3000)), type=int) +parser.add_argument("--output_interval", type=float, default=int(os.environ.get("OUTPUT_INTERVAL", 5000))) +parser.add_argument("--duration", help="Duration in seconds of the test", type=int, default=int(os.environ.get("DURATION", 999999999))) +parser.add_argument("--consumer_group", help="Consumer group name", default=os.environ.get("CONSUMER_GROUP", "$default")) parser.add_argument("--auth_timeout", help="Authorization Timeout", type=float, default=60) -parser.add_argument("--starting_offset", help="Starting offset", type=str) +parser.add_argument("--starting_offset", help="Starting offset", type=str, default=os.environ.get("STARTING_OFFSET", "-1")) parser.add_argument("--starting_sequence_number", help="Starting sequence number", type=int) -parser.add_argument("--starting_datetime", help="Starting datetime string, should be format of YYYY-mm-dd HH:mm:ss", type=str) +parser.add_argument("--starting_datetime", help="Starting datetime string, should be format of YYYY-mm-dd HH:mm:ss") parser.add_argument("--partitions", help="Number of partitions. 0 means to get partitions from eventhubs", type=int, default=0) parser.add_argument("--recv_partition_id", help="Receive from a specific partition if this is set", type=int) -parser.add_argument("--max_batch_size", type=int, default=0, +parser.add_argument("--max_batch_size", type=int, default=int(os.environ.get("MAX_BATCH_SIZE", 0)), help="Call EventHubConsumerClient.receive_batch() if not 0, otherwise call receive()") parser.add_argument("--max_wait_time", type=float, default=0, help="max_wait_time of EventHubConsumerClient.receive_batch() or EventHubConsumerClient.receive()") + parser.add_argument("--track_last_enqueued_event_properties", action="store_true") parser.add_argument("--load_balancing_interval", help="time duration in seconds between two load balance", type=float, default=10) parser.add_argument("--conn_str", help="EventHub connection string", - default=os.environ.get('EVENT_HUB_PERF_32_CONN_STR')) -parser.add_argument("--eventhub", help="Name of EventHub") + default=os.environ.get('EVENT_HUB_CONN_STR')) +parser.add_argument("--eventhub", help="Name of EventHub", default=os.environ.get('EVENT_HUB_NAME')) parser.add_argument("--address", help="Address URI to the EventHub entity") parser.add_argument("--sas_policy", help="Name of the shared access policy to authenticate with") parser.add_argument("--sas_key", help="Shared access key") diff --git a/sdk/eventhub/azure-eventhub/stress/azure_eventhub_consumer_stress_sync.py b/sdk/eventhub/azure-eventhub/stress/scripts/azure_eventhub_consumer_stress_sync.py similarity index 91% rename from sdk/eventhub/azure-eventhub/stress/azure_eventhub_consumer_stress_sync.py rename to sdk/eventhub/azure-eventhub/stress/scripts/azure_eventhub_consumer_stress_sync.py index b7c74e765a71..534c4d8996b0 100644 --- a/sdk/eventhub/azure-eventhub/stress/azure_eventhub_consumer_stress_sync.py +++ b/sdk/eventhub/azure-eventhub/stress/scripts/azure_eventhub_consumer_stress_sync.py @@ -11,6 +11,7 @@ import logging from collections import defaultdict from functools import partial +from dotenv import load_dotenv from azure.identity import ClientSecretCredential from azure.eventhub.extensions.checkpointstoreblob import BlobCheckpointStore @@ -20,6 +21,9 @@ from process_monitor import ProcessMonitor from app_insights_metric import AzureMonitorMetric +ENV_FILE = os.environ.get('ENV_FILE') +load_dotenv(dotenv_path=ENV_FILE, override=True) + def parse_starting_position(args): starting_position = None @@ -37,17 +41,17 @@ def parse_starting_position(args): parser = argparse.ArgumentParser() -parser.add_argument("--link_credit", default=3000, type=int) -parser.add_argument("--output_interval", type=float, default=1000) -parser.add_argument("--duration", help="Duration in seconds of the test", type=int, default=30) -parser.add_argument("--consumer_group", help="Consumer group name", default="$default") +parser.add_argument("--link_credit", default=int(os.environ.get("LINK_CREDIT", 3000)), type=int) +parser.add_argument("--output_interval", type=float, default=int(os.environ.get("OUTPUT_INTERVAL", 5000))) +parser.add_argument("--duration", help="Duration in seconds of the test", type=int, default=int(os.environ.get("DURATION", 999999999))) +parser.add_argument("--consumer_group", help="Consumer group name", default=os.environ.get("CONSUMER_GROUP", "$default")) parser.add_argument("--auth_timeout", help="Authorization Timeout", type=float, default=60) -parser.add_argument("--starting_offset", help="Starting offset", type=str) +parser.add_argument("--starting_offset", help="Starting offset", type=str, default=os.environ.get("STARTING_OFFSET", "-1")) parser.add_argument("--starting_sequence_number", help="Starting sequence number", type=int) parser.add_argument("--starting_datetime", help="Starting datetime string, should be format of YYYY-mm-dd HH:mm:ss") parser.add_argument("--partitions", help="Number of partitions. 0 means to get partitions from eventhubs", type=int, default=0) parser.add_argument("--recv_partition_id", help="Receive from a specific partition if this is set", type=int) -parser.add_argument("--max_batch_size", type=int, default=0, +parser.add_argument("--max_batch_size", type=int, default=int(os.environ.get("MAX_BATCH_SIZE", 0)), help="Call EventHubConsumerClient.receive_batch() if not 0, otherwise call receive()") parser.add_argument("--max_wait_time", type=float, default=0, help="max_wait_time of EventHubConsumerClient.receive_batch() or EventHubConsumerClient.receive()") @@ -55,8 +59,8 @@ def parse_starting_position(args): parser.add_argument("--track_last_enqueued_event_properties", action="store_true") parser.add_argument("--load_balancing_interval", help="time duration in seconds between two load balance", type=float, default=10) parser.add_argument("--conn_str", help="EventHub connection string", - default=os.environ.get('EVENT_HUB_PERF_32_CONN_STR')) -parser.add_argument("--eventhub", help="Name of EventHub") + default=os.environ.get('EVENT_HUB_CONN_STR')) +parser.add_argument("--eventhub", help="Name of EventHub", default=os.environ.get('EVENT_HUB_NAME')) parser.add_argument("--address", help="Address URI to the EventHub entity") parser.add_argument("--sas-policy", help="Name of the shared access policy to authenticate with") parser.add_argument("--sas-key", help="Shared access key") @@ -82,7 +86,14 @@ def parse_starting_position(args): args = parser.parse_args() starting_position = parse_starting_position(args) -LOGGER = get_logger(args.log_filename, "stress_receive_sync", level=logging.INFO, print_console=args.print_console) +print_console = args.print_console or (os.environ.get("PRINT_CONSOLE") == "1") + +LOGGER = get_logger( + args.log_filename, + "stress_receive_sync", + level=logging.INFO, + print_console=print_console +) LOG_PER_COUNT = args.output_interval start_time = time.perf_counter() @@ -105,7 +116,6 @@ def on_event_received(process_monitor, partition_context, event): recv_cnt_map[partition_context.partition_id] += 1 if event else 0 if recv_cnt_map[partition_context.partition_id] % LOG_PER_COUNT == 0: total_time_elapsed = time.perf_counter() - start_time - partition_previous_time = recv_time_map.get(partition_context.partition_id) partition_current_time = time.perf_counter() recv_time_map[partition_context.partition_id] = partition_current_time @@ -213,7 +223,11 @@ def create_client(args): def run(args): - with ProcessMonitor("monitor_{}".format(args.log_filename), "consumer_stress_sync", print_console=args.print_console) as process_monitor: + with ProcessMonitor( + "monitor_{}".format(args.log_filename), + "consumer_stress_sync", + print_console=print_console + ) as process_monitor: kwargs_dict = { "prefetch": args.link_credit, "partition_id": str(args.recv_partition_id) if args.recv_partition_id else None, diff --git a/sdk/eventhub/azure-eventhub/stress/azure_eventhub_producer_stress.py b/sdk/eventhub/azure-eventhub/stress/scripts/azure_eventhub_producer_stress.py similarity index 97% rename from sdk/eventhub/azure-eventhub/stress/azure_eventhub_producer_stress.py rename to sdk/eventhub/azure-eventhub/stress/scripts/azure_eventhub_producer_stress.py index bf6812d82d46..acd275a5a2f6 100644 --- a/sdk/eventhub/azure-eventhub/stress/azure_eventhub_producer_stress.py +++ b/sdk/eventhub/azure-eventhub/stress/scripts/azure_eventhub_producer_stress.py @@ -9,6 +9,7 @@ import time import asyncio from argparse import ArgumentParser +from dotenv import load_dotenv from azure.eventhub import EventHubProducerClient, EventData, EventHubSharedKeyCredential, TransportType from azure.eventhub.exceptions import EventHubError @@ -20,6 +21,8 @@ from process_monitor import ProcessMonitor from app_insights_metric import AzureMonitorMetric +ENV_FILE = os.environ.get('ENV_FILE') + def handle_exception(error, ignore_send_failure, stress_logger, azure_monitor_metric): err_msg = "Sync send failed due to error: {}".format(repr(error)) @@ -89,9 +92,9 @@ async def stress_send_list_async(producer: EventHubProducerClientAsync, args, st class StressTestRunner(object): def __init__(self, argument_parser): self.argument_parser = argument_parser - self.argument_parser.add_argument("-m", "--method", required=True) - self.argument_parser.add_argument("--output_interval", type=float, default=1000) - self.argument_parser.add_argument("--duration", help="Duration in seconds of the test", type=int, default=30) + self.argument_parser.add_argument("-m", "--method", default="stress_send_list_sync") + self.argument_parser.add_argument("--output_interval", type=float, default=int(os.environ.get("OUTPUT_INTERVAL", 5000))) + self.argument_parser.add_argument("--duration", help="Duration in seconds of the test", type=int, default=int(os.environ.get("DURATION", 999999999))) self.argument_parser.add_argument( "--partitions", help="Number of partitions. 0 means to get partitions from eventhubs", @@ -109,9 +112,9 @@ def __init__(self, argument_parser): type=str ) self.argument_parser.add_argument("--conn_str", help="EventHub connection string", - default=os.environ.get('EVENT_HUB_PERF_32_CONN_STR')) + default=os.environ.get('EVENT_HUB_CONN_STR')) parser.add_argument("--auth_timeout", help="Authorization Timeout", type=float, default=60) - self.argument_parser.add_argument("--eventhub", help="Name of EventHub") + self.argument_parser.add_argument("--eventhub", help="Name of EventHub", default=os.environ.get('EVENT_HUB_NAME')) self.argument_parser.add_argument( "--transport_type", help="Transport type, 0 means AMQP, 1 means AMQP over WebSocket", @@ -412,6 +415,7 @@ async def run_test_method_parallel_async(self, test_method, worker, logger, proc if __name__ == '__main__': + load_dotenv(dotenv_path=ENV_FILE, override=True) parser = ArgumentParser() runner = StressTestRunner(parser) runner.run() diff --git a/sdk/eventhub/azure-eventhub/stress/common_use_scripts b/sdk/eventhub/azure-eventhub/stress/scripts/common_use_scripts similarity index 100% rename from sdk/eventhub/azure-eventhub/stress/common_use_scripts rename to sdk/eventhub/azure-eventhub/stress/scripts/common_use_scripts diff --git a/sdk/eventhub/azure-eventhub/stress/scripts/dev_requirement.txt b/sdk/eventhub/azure-eventhub/stress/scripts/dev_requirement.txt new file mode 100644 index 000000000000..d3ffc7a78295 --- /dev/null +++ b/sdk/eventhub/azure-eventhub/stress/scripts/dev_requirement.txt @@ -0,0 +1,9 @@ +psutil +azure-eventhub +azure-eventhub-checkpointstoreblob +azure-eventhub-checkpointstoreblob-aio +azure-servicebus==0.50.3 +azure-storage-blob +azure-identity +opencensus-ext-azure +python-dotenv diff --git a/sdk/eventhub/azure-eventhub/stress/logger.py b/sdk/eventhub/azure-eventhub/stress/scripts/logger.py similarity index 99% rename from sdk/eventhub/azure-eventhub/stress/logger.py rename to sdk/eventhub/azure-eventhub/stress/scripts/logger.py index 0875c2e8a7e0..f8014397569e 100644 --- a/sdk/eventhub/azure-eventhub/stress/logger.py +++ b/sdk/eventhub/azure-eventhub/stress/scripts/logger.py @@ -3,7 +3,6 @@ # Licensed under the MIT License. See License.txt in the project root for license information. # -------------------------------------------------------------------------------------------- -import os import sys import logging from logging.handlers import RotatingFileHandler diff --git a/sdk/eventhub/azure-eventhub/stress/process_monitor.py b/sdk/eventhub/azure-eventhub/stress/scripts/process_monitor.py similarity index 100% rename from sdk/eventhub/azure-eventhub/stress/process_monitor.py rename to sdk/eventhub/azure-eventhub/stress/scripts/process_monitor.py diff --git a/sdk/eventhub/azure-eventhub/stress/stress_runner.cfg b/sdk/eventhub/azure-eventhub/stress/scripts/stress_runner.cfg similarity index 100% rename from sdk/eventhub/azure-eventhub/stress/stress_runner.cfg rename to sdk/eventhub/azure-eventhub/stress/scripts/stress_runner.cfg diff --git a/sdk/eventhub/azure-eventhub/stress/stress_runner.py b/sdk/eventhub/azure-eventhub/stress/scripts/stress_runner.py similarity index 100% rename from sdk/eventhub/azure-eventhub/stress/stress_runner.py rename to sdk/eventhub/azure-eventhub/stress/scripts/stress_runner.py diff --git a/sdk/eventhub/azure-eventhub/stress/templates/network_loss.yaml b/sdk/eventhub/azure-eventhub/stress/templates/network_loss.yaml new file mode 100644 index 000000000000..4811c7a1b1a3 --- /dev/null +++ b/sdk/eventhub/azure-eventhub/stress/templates/network_loss.yaml @@ -0,0 +1,31 @@ +apiVersion: chaos-mesh.org/v1alpha1 +kind: NetworkChaos +metadata: + name: '{{ .Release.Name }}-{{ .Release.Revision }}' + namespace: {{ .Release.Namespace }} + annotations: + experiment.chaos-mesh.org/pause: 'true' + labels: + scenario: 'stress' + release: '{{ .Release.Name }}' + revision: '{{ .Release.Revision }}' +spec: + scheduler: + cron: '@every 30s' + duration: '10s' + action: loss + direction: to + externalTargets: + - 'eh-stress-{{ .Release.Name }}-{{ .Release.Revision }}.servicebus.windows.net' + mode: one + selector: + labelSelectors: + testInstance: "eventhub-{{ .Release.Name }}-{{ .Release.Revision }}" + chaos: 'true' + namespaces: + - {{ .Release.Namespace }} + podPhaseSelectors: + - 'Running' + loss: + loss: '100' + correlation: '100' diff --git a/sdk/eventhub/azure-eventhub/stress/templates/testjob.yaml b/sdk/eventhub/azure-eventhub/stress/templates/testjob.yaml new file mode 100644 index 000000000000..fde684783937 --- /dev/null +++ b/sdk/eventhub/azure-eventhub/stress/templates/testjob.yaml @@ -0,0 +1,16 @@ +{{- include "stress-test-addons.deploy-job-template.from-pod" (list . "stress.python-eh-stress") -}} +{{- define "stress.python-eh-stress" -}} +metadata: + labels: + testName: "deploy-python-eh-stress" + testInstance: "eventhub-{{ .Release.Name }}-{{ .Release.Revision }}" + chaos: "true" +spec: + containers: + - name: python-eh-stress + image: {{ default "stresstestregistry.azurecr.io/python" .Values.repository }}/stress:{{ default "v2" .Values.tag }} + command: ['bash', '-c', 'python3 azure_eventhub_producer_stress.py & python3 azure_eventhub_consumer_stress_sync.py'] + {{- include "stress-test-addons.container-env" . | nindent 6 }} + # async test command + # command: ['bash', '-c', 'python3 azure_eventhub_producer_stress.py -m stress_send_list_async & python3 azure_eventhub_consumer_stress_async.py'] +{{- end -}} diff --git a/sdk/eventhub/azure-eventhub/stress/test-resources.bicep b/sdk/eventhub/azure-eventhub/stress/test-resources.bicep new file mode 100644 index 000000000000..353192bab4f7 --- /dev/null +++ b/sdk/eventhub/azure-eventhub/stress/test-resources.bicep @@ -0,0 +1,107 @@ +@description('The base resource name.') +param baseName string = resourceGroup().name + +@description('The client OID to grant access to test resources.') +param testApplicationOid string + +@description('The location of the resources. By default, this is the same as the resource group.') +param location string = resourceGroup().location + +@description('The url suffix to use when creating storage connection strings.') +param storageEndpointSuffix string = 'core.windows.net' + +var ehVersion = '2017-04-01' +var contributorRoleId = 'b24988ac-6180-42a0-ab88-20f7382dd24c' +var eventHubsDataOwnerRoleId = 'f526a384-b230-433a-b45c-95f59c4a2dec' +var eventHubsNamespace_var = 'eh-${baseName}' +var eventHubName = 'eh-${baseName}-hub' +var eventHubAuthRuleName = 'eh-${baseName}-hub-auth-rule' +var storageAccount_var = replace('blb${baseName}', '-', '') +var containerName = 'your-blob-container-name' +var defaultSASKeyName = 'RootManageSharedAccessKey' +var eventHubsAuthRuleResourceId = resourceId('Microsoft.EventHub/namespaces/authorizationRules', eventHubsNamespace_var, defaultSASKeyName) +var storageAccountId = storageAccount.id + +resource eventHubsNamespace 'Microsoft.EventHub/Namespaces@[variables(\'ehVersion\')]' = { + name: eventHubsNamespace_var + location: location + sku: { + name: 'Standard' + tier: 'Standard' + } + properties: {} +} + +resource eventHubsNamespace_eventHubName 'Microsoft.EventHub/namespaces/eventhubs@[variables(\'ehVersion\')]' = { + name: '${eventHubsNamespace_var}/${eventHubName}' + location: location + properties: { + messageRetentionInDays: 1 + partitionCount: 32 + } + dependsOn: [ + eventHubsNamespace + ] +} + +resource eventHubsNamespace_eventHubName_eventHubAuthRuleName 'Microsoft.EventHub/namespaces/eventhubs/authorizationRules@[variables(\'ehVersion\')]' = { + name: '${eventHubsNamespace_var}/${eventHubName}/${eventHubAuthRuleName}' + properties: { + Rights: [ + 'Manage' + 'Send' + 'Listen' + ] + } + dependsOn: [ + eventHubsNamespace_eventHubName + ] +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2019-06-01' = { + name: storageAccount_var + location: location + sku: { + name: 'Standard_LRS' + tier: 'Standard' + } + kind: 'StorageV2' + properties: { + accessTier: 'Hot' + } +} + +resource storageAccount_default_containerName 'Microsoft.Storage/storageAccounts/blobServices/containers@2019-06-01' = { + name: '${storageAccount_var}/default/${containerName}' + dependsOn: [ + storageAccount + ] +} + +resource id_name_baseName_eventHubsDataOwnerRoleId_testApplicationOid 'Microsoft.Authorization/roleAssignments@2019-04-01-preview' = { + name: guid(resourceGroup().id, deployment().name, baseName, eventHubsDataOwnerRoleId, testApplicationOid) + properties: { + roleDefinitionId: resourceId('Microsoft.Authorization/roleDefinitions', eventHubsDataOwnerRoleId) + principalId: testApplicationOid + scope: resourceGroup().id + } +} + +resource id_name_baseName_contributorRoleId_testApplicationOid 'Microsoft.Authorization/roleAssignments@2019-04-01-preview' = { + name: guid(resourceGroup().id, deployment().name, baseName, contributorRoleId, testApplicationOid) + properties: { + roleDefinitionId: resourceId('Microsoft.Authorization/roleDefinitions', contributorRoleId) + principalId: testApplicationOid + scope: resourceGroup().id + } +} + +output EVENT_HUB_NAMESPACE string = eventHubsNamespace_var +output EVENT_HUB_HOSTNAME string = '${eventHubsNamespace_var}.servicebus.windows.net' +output EVENT_HUB_CONN_STR string = listkeys(eventHubAuthRuleName, ehVersion).primaryConnectionString +output EVENT_HUB_NAME string = eventHubName +output EVENT_HUB_SAS_POLICY string = eventHubAuthRuleName +output EVENT_HUB_SAS_KEY string = listkeys(eventHubAuthRuleName, ehVersion).primaryKey +output AZURE_STORAGE_CONN_STR string = 'DefaultEndpointsProtocol=https;AccountName=${storageAccount_var};AccountKey=${listKeys(storageAccountId, providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).keys[0].value};EndpointSuffix=${storageEndpointSuffix}' +output AZURE_STORAGE_ACCOUNT string = storageAccount_var +output AZURE_STORAGE_ACCESS_KEY string = listKeys(storageAccountId, providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).keys[0].value \ No newline at end of file diff --git a/sdk/eventhub/azure-eventhub/stress/test-resources.json b/sdk/eventhub/azure-eventhub/stress/test-resources.json new file mode 100644 index 000000000000..3b46c8e656a7 --- /dev/null +++ b/sdk/eventhub/azure-eventhub/stress/test-resources.json @@ -0,0 +1,169 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "baseName": { + "type": "string", + "defaultValue": "[resourceGroup().name]", + "metadata": { + "description": "The base resource name." + } + }, + "testApplicationOid": { + "type": "string", + "metadata": { + "description": "The client OID to grant access to test resources." + } + }, + "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": "The url suffix to use when creating storage connection strings." + } + } + }, + "variables": { + "ehVersion": "2017-04-01", + "contributorRoleId": "b24988ac-6180-42a0-ab88-20f7382dd24c", + "eventHubsDataOwnerRoleId": "f526a384-b230-433a-b45c-95f59c4a2dec", + "eventHubsNamespace": "[concat('eh-', parameters('baseName'))]", + "eventHubName": "[concat('eh-', parameters('baseName'), '-hub')]", + "eventHubAuthRuleName": "[concat('eh-', parameters('baseName'), '-hub-auth-rule')]", + "storageAccount": "[replace(concat('blb', parameters('baseName')), '-', '')]", + "containerName": "your-blob-container-name", + "defaultSASKeyName": "RootManageSharedAccessKey", + "eventHubsAuthRuleResourceId": "[resourceId('Microsoft.EventHub/namespaces/authorizationRules', variables('eventHubsNamespace'), variables('defaultSASKeyName'))]", + "storageAccountId": "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccount'))]" + }, + "resources": [ + { + "apiVersion": "[variables('ehVersion')]", + "name": "[variables('eventHubsNamespace')]", + "type": "Microsoft.EventHub/Namespaces", + "location": "[parameters('location')]", + "sku": { + "name": "Standard", + "tier": "Standard" + }, + "resources": [ + { + "type": "Microsoft.EventHub/namespaces/eventhubs", + "apiVersion": "[variables('ehVersion')]", + "name": "[concat(variables('eventHubsNamespace'), '/', variables('eventHubName'))]", + "location": "[parameters('location')]", + "dependsOn": [ + "[resourceId('Microsoft.EventHub/namespaces', variables('eventHubsNamespace'))]" + ], + "properties": { + "messageRetentionInDays": 1, + "partitionCount": 32 + }, + "resources": [ + { + "apiVersion": "[variables('ehVersion')]", + "name": "[variables('eventHubAuthRuleName')]", + "type": "authorizationRules", + "dependsOn": [ + "[variables('eventHubName')]" + ], + "properties": { + "Rights": ["Manage", "Send", "Listen"] + } + } + ] + } + ], + "properties": {} + }, + { + "type": "Microsoft.Storage/storageAccounts", + "apiVersion": "2019-06-01", + "name": "[variables('storageAccount')]", + "location": "[parameters('location')]", + "sku": { + "name": "Standard_LRS", + "tier": "Standard" + }, + "kind": "StorageV2", + "properties": { + "accessTier": "Hot" + }, + "resources": [ + { + "type": "blobServices/containers", + "apiVersion": "2019-06-01", + "name": "[concat('default/', variables('containerName'))]", + "dependsOn": [ + "[variables('storageAccount')]" + ] + } + ] + }, + { + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2019-04-01-preview", + "name": "[guid(resourceGroup().id, deployment().name, parameters('baseName'), variables('eventHubsDataOwnerRoleId'), parameters('testApplicationOid'))]", + "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, deployment().name, parameters('baseName'), variables('contributorRoleId'), parameters('testApplicationOid'))]", + "properties": { + "roleDefinitionId": "[resourceId('Microsoft.Authorization/roleDefinitions', variables('contributorRoleId'))]", + "principalId": "[parameters('testApplicationOid')]", + "scope": "[resourceGroup().id]" + } + } + ], + "outputs": { + "EVENT_HUB_NAMESPACE": { + "type": "string", + "value": "[variables('eventHubsNamespace')]" + }, + "EVENT_HUB_HOSTNAME": { + "type": "string", + "value": "[concat(variables('eventHubsNamespace'), '.servicebus.windows.net')]" + }, + "EVENT_HUB_CONN_STR": { + "type": "string", + "value": "[listkeys(variables('eventHubAuthRuleName'), variables('ehVersion')).primaryConnectionString]" + }, + "EVENT_HUB_NAME": { + "type": "string", + "value": "[variables('eventHubName')]" + }, + "EVENT_HUB_SAS_POLICY":{ + "type": "string", + "value": "[variables('eventHubAuthRuleName')]" + }, + "EVENT_HUB_SAS_KEY":{ + "type": "string", + "value": "[listkeys(variables('eventHubAuthRuleName'), variables('ehVersion')).primaryKey]" + }, + "AZURE_STORAGE_CONN_STR": { + "type": "string", + "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccount'), ';AccountKey=', listKeys(variables('storageAccountId'), providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).keys[0].value, ';EndpointSuffix=', parameters('storageEndpointSuffix'))]" + }, + "AZURE_STORAGE_ACCOUNT": { + "type": "string", + "value": "[variables('storageAccount')]" + }, + "AZURE_STORAGE_ACCESS_KEY":{ + "type": "string", + "value": "[listKeys(variables('storageAccountId'), providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).keys[0].value]" + } + } +}