├── .codecov.yml ├── .editorconfig ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── discussion.md │ ├── feature_request.md │ ├── proposal.md │ └── question.md ├── pull_request_template.md ├── scripts │ └── get_release_version.py └── workflows │ └── build.yaml ├── .gitignore ├── CODEOWNERS ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── all.sln ├── all.v3.ncrunchsolution ├── img ├── ConsulSample_HealthyServices.png └── ConsulSample_StartupProjects.png ├── properties ├── dapr_sidekick.snk ├── dapr_sidekick_common.props ├── dapr_sidekick_csharp.props ├── dapr_sidekick_nuget.props └── dapr_sidekick_package_icon.png ├── samples ├── Actor │ ├── ActorSample │ │ ├── ActorSample.ActorClient │ │ │ ├── ActorSample.ActorClient.csproj │ │ │ └── Program.cs │ │ ├── ActorSample.DemoActor │ │ │ ├── ActorSample.DemoActor.csproj │ │ │ ├── BankService.cs │ │ │ ├── DemoActor.cs │ │ │ ├── Program.cs │ │ │ ├── Properties │ │ │ │ └── launchSettings.json │ │ │ └── Startup.cs │ │ ├── ActorSample.IDemoActor │ │ │ ├── ActorSample.IDemoActor.csproj │ │ │ ├── IBankActor.cs │ │ │ └── IDemoActor.cs │ │ └── README.md │ └── README.md ├── AspNetCore │ ├── AppConfigurationSample │ │ ├── AppConfigurationSample │ │ │ ├── AppConfigurationSample.csproj │ │ │ ├── Controllers │ │ │ │ └── SampleController.cs │ │ │ ├── Dapr │ │ │ │ ├── Components │ │ │ │ │ └── secretstore.yaml │ │ │ │ └── secrets.json │ │ │ ├── Program.cs │ │ │ ├── Properties │ │ │ │ └── launchSettings.json │ │ │ ├── appsettings.Development.json │ │ │ └── appsettings.json │ │ └── README.md │ ├── ConsulSample │ │ ├── ConsulSample.Receiver │ │ │ ├── ConsulSample.Receiver.csproj │ │ │ ├── Controllers │ │ │ │ └── WeatherForecastController.cs │ │ │ ├── Program.cs │ │ │ ├── Properties │ │ │ │ └── launchSettings.json │ │ │ ├── Startup.cs │ │ │ ├── WeatherForecast.cs │ │ │ ├── appsettings.Development.json │ │ │ ├── appsettings.json │ │ │ └── dapr │ │ │ │ └── config.yaml │ │ ├── ConsulSample.Sender │ │ │ ├── ConsulSample.Sender.csproj │ │ │ ├── Controllers │ │ │ │ └── SenderController.cs │ │ │ ├── Program.cs │ │ │ ├── Properties │ │ │ │ └── launchSettings.json │ │ │ ├── Startup.cs │ │ │ ├── WeatherForecast.cs │ │ │ ├── appsettings.Development.json │ │ │ ├── appsettings.json │ │ │ └── dapr │ │ │ │ └── config.yaml │ │ └── README.md │ ├── ControllerSample │ │ ├── ControllerSample │ │ │ ├── Account.cs │ │ │ ├── ControllerSample.csproj │ │ │ ├── Controllers │ │ │ │ └── SampleController.cs │ │ │ ├── Program.cs │ │ │ ├── Properties │ │ │ │ └── launchSettings.json │ │ │ ├── Startup.cs │ │ │ ├── Transaction.cs │ │ │ ├── appsettings.json │ │ │ └── sample.http │ │ └── README.md │ ├── PlacementSample │ │ ├── PlacementSample │ │ │ ├── PlacementSample.csproj │ │ │ ├── Program.cs │ │ │ ├── Properties │ │ │ │ └── launchSettings.json │ │ │ ├── appsettings.Development.json │ │ │ ├── appsettings.json │ │ │ ├── dapr │ │ │ │ └── config.yaml │ │ │ └── placement │ │ │ │ └── config.yaml │ │ └── README.md │ ├── README.md │ ├── SchedulerSample │ │ ├── README.md │ │ └── SchedulerSample │ │ │ ├── Program.cs │ │ │ ├── Properties │ │ │ └── launchSettings.json │ │ │ ├── SchedulerSample.csproj │ │ │ ├── appsettings.Development.json │ │ │ ├── appsettings.json │ │ │ ├── dapr │ │ │ └── config.yaml │ │ │ └── scheduler │ │ │ └── config.yaml │ ├── SentrySample │ │ ├── README.md │ │ └── SentrySample │ │ │ ├── Program.cs │ │ │ ├── Properties │ │ │ └── launchSettings.json │ │ │ ├── SentrySample.csproj │ │ │ ├── appsettings.Development.json │ │ │ ├── appsettings.json │ │ │ ├── dapr │ │ │ └── config.yaml │ │ │ └── sentry │ │ │ ├── certs │ │ │ ├── ca.crt │ │ │ ├── issuer.crt │ │ │ └── issuer.key │ │ │ └── config.yaml │ └── ServiceInvocationSample │ │ ├── README.md │ │ └── ServiceInvocationSample │ │ ├── Controllers │ │ └── WeatherForecastController.cs │ │ ├── Program.cs │ │ ├── Properties │ │ └── launchSettings.json │ │ ├── ServiceInvocationSample.csproj │ │ ├── Startup.cs │ │ ├── WeatherForecast.cs │ │ └── appsettings.json ├── Directory.Build.props ├── NetFramework │ ├── README.md │ └── WcfSample │ │ ├── README.md │ │ └── WcfSample │ │ ├── IWeatherForecastService.cs │ │ ├── Program.cs │ │ ├── WcfSample.csproj │ │ ├── WeatherForecast.cs │ │ └── WeatherForecastService.cs ├── README.md └── Workflow │ └── ConsoleSample │ └── WorkflowConsoleApp │ ├── Activities │ ├── NotifyActivity.cs │ ├── ProcessPaymentActivity.cs │ ├── RequestApprovalActivity.cs │ ├── ReserveInventoryActivity.cs │ └── UpdateInventoryActivity.cs │ ├── Models.cs │ ├── Program.cs │ ├── Properties │ └── launchSettings.json │ ├── WorkflowConsoleApp.csproj │ ├── Workflows │ └── OrderProcessingWorkflow.cs │ ├── appsettings.json │ └── demo.http ├── src ├── Directory.build.props ├── Man.Dapr.Sidekick.AspNetCore │ ├── AssemblyInfo.cs │ ├── DaprHostedService.cs │ ├── DaprProcessHealthCheck.cs │ ├── DaprServiceCollectionExtensions.cs │ ├── DaprSidekickBuilder.cs │ ├── DaprSidekickServiceCollectionExtensions.cs │ ├── Http │ │ ├── DaprHttpContextHttpClientFactory.cs │ │ ├── HttpContextInvocationHandler.cs │ │ └── HttpHeaderConstants.cs │ ├── IDaprSidekickBuilder.cs │ ├── Man.Dapr.Sidekick.AspNetCore.csproj │ ├── Metrics │ │ ├── DaprMetricsConstants.cs │ │ ├── DaprMetricsMiddlewareExtensions.cs │ │ ├── DaprMetricsServerMiddleware.cs │ │ ├── DaprMetricsTextSerializer.cs │ │ ├── DaprProcessHostPrometheusCollector.cs │ │ ├── IDaprMetricsCollector.cs │ │ ├── IDaprMetricsCollectorRegistry.cs │ │ ├── IDaprMetricsSerializer.cs │ │ ├── IPrometheusCollector.cs │ │ ├── IPrometheusMetricFilter.cs │ │ ├── PROMETHEUS_LICENSE │ │ ├── PrometheusCollectorRegistry.cs │ │ ├── PrometheusLabelEnricher.cs │ │ ├── PrometheusModel.cs │ │ └── PrometheusTextReader.cs │ ├── Placement │ │ ├── DaprPlacementHealthCheck.cs │ │ ├── DaprPlacementHealthCheckBuilderExtensions.cs │ │ ├── DaprPlacementHostedService.cs │ │ ├── DaprPlacementMetricsCollector.cs │ │ └── DaprPlacementSidecarHostedService.cs │ ├── Properties │ │ └── launchSettings.json │ ├── Scheduler │ │ ├── DaprSchedulerHealthCheck.cs │ │ ├── DaprSchedulerHealthCheckBuilderExtensions.cs │ │ ├── DaprSchedulerHostedService.cs │ │ ├── DaprSchedulerMetricsCollector.cs │ │ └── DaprSchedulerSidecarHostedService.cs │ ├── Sentry │ │ ├── DaprSentryHealthCheck.cs │ │ ├── DaprSentryHealthCheckBuilderExtensions.cs │ │ ├── DaprSentryHostedService.cs │ │ ├── DaprSentryMetricsCollector.cs │ │ └── DaprSentrySidecarHostedService.cs │ └── Sidecar │ │ ├── DaprSidecarHealthCheck.cs │ │ ├── DaprSidecarHealthCheckBuilderExtensions.cs │ │ ├── DaprSidecarHostedService.cs │ │ ├── DaprSidecarMetricFilter.cs │ │ └── DaprSidecarMetricsCollector.cs ├── Man.Dapr.Sidekick.Extensions.Logging │ ├── DaprLogger.cs │ ├── DaprLoggerFactory.cs │ └── Man.Dapr.Sidekick.Extensions.Logging.csproj └── Man.Dapr.Sidekick │ ├── AssemblyInfo.cs │ ├── DaprClient │ ├── DAPR_DOTNET_SDK_LICENSE │ ├── DaprClient.cs │ ├── DirectInvocationHandler.cs │ └── InvocationHandler.cs │ ├── DaprConstants.cs │ ├── DaprDisposable.cs │ ├── DaprPlacementHost.cs │ ├── DaprSchedulerHost.cs │ ├── DaprSentryHost.cs │ ├── DaprSidecarHost.cs │ ├── DaprSidecarHost.net35.cs │ ├── DaprSidecarHost.net45.cs │ ├── DaprSidekick.cs │ ├── DaprSidekickBuilder.cs │ ├── Http │ ├── DaprProcessHttpClientFactory.cs │ ├── DaprProcessHttpClientFactory.net35.cs │ ├── DaprProcessHttpClientFactory.net45.cs │ ├── DaprSidecarHttpClientFactory.cs │ ├── DaprSidecarHttpClientFactory.net35.cs │ ├── DaprSidecarHttpClientFactory.net45.cs │ ├── IDaprProcessHttpClientFactory.cs │ ├── IDaprSidecarHttpClientFactory.cs │ └── UriHelper.cs │ ├── IDaprPlacementHost.cs │ ├── IDaprSchedulerHost.cs │ ├── IDaprSentryHost.cs │ ├── IDaprSidecarHost.cs │ ├── IDaprSidecarHost.net35.cs │ ├── IDaprSidecarHost.net45.cs │ ├── Logging │ ├── DaprColoredConsoleLoggerFactory.cs │ ├── DaprColoredConsoleLoggerOptions.cs │ ├── DaprEventId.cs │ ├── DaprLogLevel.cs │ ├── DaprLoggerExtensions.cs │ ├── DaprLoggerFactoryBase.cs │ ├── DaprLoggerFactoryExtensions.cs │ ├── DaprLoggerOfT.cs │ ├── IDaprLogger.cs │ ├── IDaprLoggerFactory.cs │ ├── Internal │ │ ├── DaprColoredConsoleLogger.cs │ │ ├── DaprFormattedLogValues.cs │ │ ├── DaprLogValuesFormatter.cs │ │ ├── ISystemConsole.cs │ │ ├── SystemConsole.cs │ │ └── TypeNameHelper.cs │ └── NET_EXTENSIONS_LICENSE │ ├── Man.Dapr.Sidekick.csproj │ ├── Native │ ├── NativeChildProcessTracker.cs │ └── NativeProcess.cs │ ├── Options │ ├── DaprManagedProcessOptions.cs │ ├── DaprMetricsOptions.cs │ ├── DaprOptions.cs │ ├── DaprPlacementOptions.cs │ ├── DaprProcessOptions.cs │ ├── DaprSchedulerOptions.cs │ ├── DaprSentryOptions.cs │ └── DaprSidecarOptions.cs │ ├── Process │ ├── AttachedProcess.cs │ ├── CommandLineArgumentBuilder.cs │ ├── DaprHealthResult.cs │ ├── DaprPlacementProcess.cs │ ├── DaprProcess.cs │ ├── DaprProcessEvents.cs │ ├── DaprProcessFactory.cs │ ├── DaprProcessHost.cs │ ├── DaprProcessHost.net35.cs │ ├── DaprProcessHost.net45.cs │ ├── DaprProcessInfo.cs │ ├── DaprProcessLogRecord.cs │ ├── DaprProcessLogger.cs │ ├── DaprSchedulerProcess.cs │ ├── DaprSentryProcess.cs │ ├── DaprSidecarProcess.cs │ ├── Enumerations.cs │ ├── EnvironmentVariableBuilder.cs │ ├── IDaprPlacementProcess.cs │ ├── IDaprProcess.cs │ ├── IDaprProcessFactory.cs │ ├── IDaprProcessHost.cs │ ├── IDaprProcessHost.ne35.cs │ ├── IDaprProcessHost.net45.cs │ ├── IDaprProcessUpdater.cs │ ├── IDaprSchedulerProcess.cs │ ├── IDaprSentryProcess.cs │ ├── IDaprSidecarProcess.cs │ ├── IDaprSidecarProcessInterceptor.cs │ ├── IPortAvailabilityChecker.cs │ ├── IProcess.cs │ ├── IProcessCommandLine.cs │ ├── IProcessFinder.cs │ ├── ISystemProcessController.cs │ ├── ManagedProcess.cs │ ├── PortAssignmentBuilder.cs │ ├── PortAvailabilityChecker.cs │ ├── ProcessCommandLine.cs │ ├── ProcessFinder.cs │ ├── SystemProcess.cs │ └── SystemProcessController.cs │ ├── Security │ ├── DaprApiTokenManager.cs │ ├── IDaprApiTokenAccessor.cs │ ├── IDaprApiTokenManager.cs │ ├── IDaprApiTokenProvider.cs │ ├── ISensitiveValue.cs │ ├── ObjectExtensions.cs │ ├── RandomStringApiTokenProvider.cs │ ├── SensitiveString.cs │ └── SensitiveStringConverter.cs │ ├── StringExtensions.cs │ └── Threading │ ├── DaprCancellationToken.cs │ ├── DaprCancellationToken.net35.cs │ ├── DaprCancellationToken.net45.cs │ └── Lazy.net35.cs └── tests ├── Directory.build.props ├── Man.Dapr.Sidekick.AspNetCore.Tests ├── DaprHostedServiceTests.cs ├── DaprProcessHealthCheckTests.cs ├── DaprServiceCollectionExtensionsTests.cs ├── DaprSidekickBuilderTests.cs ├── DaprSidekickServiceCollectionExtensionsTests.cs ├── Http │ ├── DaprHttpContextHttpClientFactoryTests.cs │ ├── HttpContextInvocationHandlerTests.cs │ ├── MockHttpContext.cs │ ├── MockHttpContextInvocationHandler.cs │ ├── MockHttpRequest.cs │ └── MockHttpResponse.cs ├── Man.Dapr.Sidekick.AspNetCore.Tests.csproj ├── Metrics │ ├── DaprMetricsMiddlewareExtensionsTests.cs │ ├── DaprMetricsServerMiddlewareTests.cs │ ├── DaprMetricsTextSerializerTests.cs │ ├── DaprProcessHostPrometheusCollectorTests.cs │ ├── PrometheusCollectorRegistryTests.cs │ ├── PrometheusLabelEnricherTests.cs │ ├── PrometheusModelTests.cs │ └── PrometheusTextReaderTests.cs ├── MockDaprProcessOptions.cs ├── Placement │ ├── DaprPlacementHealthCheckBuilderExtensionsTests.cs │ ├── DaprPlacementHealthCheckTests.cs │ ├── DaprPlacementHostedServiceTests.cs │ ├── DaprPlacementMetricsCollectorTests.cs │ └── DaprPlacementSidecarHostedServiceTests.cs ├── Sentry │ ├── DaprSentryHealthCheckBuilderExtensionsTests.cs │ ├── DaprSentryHealthCheckTests.cs │ ├── DaprSentryHostedServiceTests.cs │ ├── DaprSentryMetricsCollectorTests.cs │ └── DaprSentrySidecarHostedServiceTests.cs └── Sidecar │ ├── DaprSidecarHealthCheckBuilderExtensionsTests.cs │ ├── DaprSidecarHealthCheckTests.cs │ ├── DaprSidecarHostedServiceTests.cs │ ├── DaprSidecarMetricFilterTests.cs │ └── DaprSidecarMetricsCollectorTests.cs ├── Man.Dapr.Sidekick.Extensions.Logging.Tests ├── DaprLoggerFactoryTests.cs ├── DaprLoggerTests.cs └── Man.Dapr.Sidekick.Extensions.Logging.Tests.csproj └── Man.Dapr.Sidekick.Tests ├── DaprClient ├── DaprClientTests.cs └── InvocationHandlerTests.cs ├── DaprDisposableTests.cs ├── DaprPlacementHostTests.cs ├── DaprSentryHostTests.cs ├── DaprSidecarHostTests.cs ├── DaprSidecarHostTests.net35.cs ├── DaprSidecarHostTests.net45.cs ├── DaprSidekickBuilderTests.cs ├── Http ├── DaprProcessHttpClientFactoryTests.net35.cs ├── DaprProcessHttpClientFactoryTests.net45.cs ├── DaprSidecarHttpClientFactoryTests.net35.cs ├── DaprSidecarHttpClientFactoryTests.net45.cs ├── MockDaprSidecarHttpClientFactory.cs ├── MockHttpClientHandler.cs └── UriHelperTests.cs ├── Logging ├── DaprColoredConsoleLoggerFactoryTests.cs ├── DaprColoredConsoleLoggerOptionsTests.cs ├── DaprEventIdTests.cs ├── DaprLoggerExtensionsTests.cs ├── DaprLoggerFactoryExtensionsTests.cs ├── DaprLoggerOfTTests.cs └── Internal │ ├── DaprColoredConsoleLoggerTests.cs │ ├── SystemColorTests.cs │ └── TypeNameHelperTests.cs ├── Man.Dapr.Sidekick.Tests.csproj ├── MockDisposable.cs ├── Options ├── DaprMetricsOptionsTests.cs ├── DaprOptionsTests.cs ├── DaprPlacementOptionsTests.cs ├── DaprProcessOptionsTests.cs ├── DaprSentryOptionsTests.cs ├── DaprSidecarOptionsTests.cs └── MockDaprProcessOptions.cs ├── Process ├── AttachedProcessTests.cs ├── CommandLineArgumentBuilderTests.cs ├── DaprHealthResultTests.cs ├── DaprPlacementProcessTests.cs ├── DaprProcessFactoryTests.cs ├── DaprProcessHostTests.cs ├── DaprProcessInfoTests.cs ├── DaprProcessLoggerTests.cs ├── DaprProcessTests.cs ├── DaprSchedulerProcessTests.cs ├── DaprSentryProcessTests.cs ├── DaprSidecarProcessTests.cs ├── EnvironmentVariableBuilderTests.cs ├── ManagedProcessTests.cs ├── MockDaprProcess.cs ├── MockDaprProcessOptions.cs ├── MockPortAvailabilityChecker.cs ├── PortAssignmentBuilderTests.cs ├── PortAvailabilityCheckerTests.cs ├── ProcessCommandLineTests.cs ├── ProcessFinderTests.cs └── SystemProcessTests.cs ├── Resources └── ProcessProgram.cs ├── Security ├── DaprApiTokenManagerTests.cs ├── ObjectExtensionsTests.cs ├── RandomStringApiTokenProviderTests.cs ├── SensitiveStringConverterTests.cs └── SensitiveStringTests.cs ├── TestResourceHelper.cs ├── Threading ├── DaprCancellationTokenTests.net35.cs └── DaprCancellationTokenTests.net45.cs └── _TestHelpers ├── ExtensionMethods.cs └── LoggerCall.cs /.codecov.yml: -------------------------------------------------------------------------------- 1 | coverage: 2 | status: 3 | project: 4 | default: 5 | # basic 6 | target: auto 7 | threshold: 0% 8 | 9 | ignore: 10 | - test # - tests 11 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Report a bug in Dapr Sidekick 4 | title: '' 5 | labels: kind/bug 6 | assignees: '' 7 | 8 | --- 9 | ## Expected Behavior 10 | 11 | 12 | 13 | ## Actual Behavior 14 | 15 | 16 | 17 | ## Steps to Reproduce the Problem 18 | 19 | 20 | 21 | ## Release Note 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | RELEASE NOTE: 30 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/discussion.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Discussion 3 | about: Start a discussion for Dapr Sidekick 4 | title: '' 5 | labels: kind/discussion 6 | assignees: '' 7 | 8 | --- 9 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature Request 3 | about: Create a Feature Request for Dapr Sidekick 4 | title: '' 5 | labels: kind/enhancement 6 | assignees: '' 7 | 8 | --- 9 | ## Describe the feature 10 | 11 | 12 | ## Release Note 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | RELEASE NOTE: 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/proposal.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Proposal 3 | about: Create a proposal for Dapr Sidekick 4 | title: '' 5 | labels: kind/proposal 6 | assignees: '' 7 | 8 | --- 9 | ## Describe the proposal 10 | 11 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Question 3 | about: Ask a question about Dapr Sidekick 4 | title: '' 5 | labels: kind/question 6 | assignees: '' 7 | 8 | --- 9 | ## Ask your question here 10 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | # Description 2 | 3 | _Please explain the changes you've made_ 4 | 5 | ## Issue reference 6 | 7 | We strive to have all PR being opened based on an issue, where the problem or feature have been discussed prior to implementation. 8 | 9 | Please reference the issue this PR will close: #_[issue number]_ 10 | 11 | ## Checklist 12 | 13 | Please make sure you've completed the relevant tasks for this PR, out of the following list: 14 | 15 | * [ ] Code compiles correctly 16 | * [ ] Created/updated tests 17 | * [ ] Extended the documentation where possible 18 | -------------------------------------------------------------------------------- /.github/scripts/get_release_version.py: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------ 2 | # Copyright (c) Microsoft Corporation. 3 | # Licensed under the MIT License. 4 | # ------------------------------------------------------------ 5 | 6 | # This script parses release version from Git tag and set the parsed version to 7 | # environment variable, REL_VERSION. 8 | 9 | import os 10 | import sys 11 | 12 | gitRef = os.getenv("GITHUB_REF") 13 | tagRefPrefix = "refs/tags/v" 14 | 15 | with open(os.getenv("GITHUB_ENV"), "a") as githubEnv: 16 | if gitRef is None or not gitRef.startswith(tagRefPrefix): 17 | githubEnv.write("REL_VERSION=edge\n") 18 | print ("This is daily build from {}...".format(gitRef)) 19 | sys.exit(0) 20 | 21 | releaseVersion = gitRef[len(tagRefPrefix):] 22 | releaseNotePath="docs/release_notes/v{}.md".format(releaseVersion) 23 | 24 | if gitRef.find("-rc.") > 0: 25 | print ("Release Candidate build from {}...".format(gitRef)) 26 | else: 27 | # Set LATEST_RELEASE to true 28 | githubEnv.write("LATEST_RELEASE=true\n") 29 | print ("Release build from {}...".format(gitRef)) 30 | 31 | githubEnv.write("REL_VERSION={}\n".format(releaseVersion)) 32 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # These owners are the maintainers and approvers of this repo 2 | * @dapr-sidekick-maintainers -------------------------------------------------------------------------------- /all.v3.ncrunchsolution: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | .editorconfig 5 | 6 | True 7 | True 8 | Run Solution Unit Tests automatically [SnapshotShared] 9 | Optimised 10 | True 11 | True 12 | 13 | 14 | 15 | Run Solution Unit Tests automatically 16 | 17 | (DoesNotHaveCategory 'Component' AND DoesNotHaveCategory 'Database' AND DoesNotHaveCategory 'Integration') 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /img/ConsulSample_HealthyServices.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/man-group/dapr-sidekick-dotnet/7a47300a7eeb4fc5c3658554771cf4a51558bf2b/img/ConsulSample_HealthyServices.png -------------------------------------------------------------------------------- /img/ConsulSample_StartupProjects.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/man-group/dapr-sidekick-dotnet/7a47300a7eeb4fc5c3658554771cf4a51558bf2b/img/ConsulSample_StartupProjects.png -------------------------------------------------------------------------------- /properties/dapr_sidekick.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/man-group/dapr-sidekick-dotnet/7a47300a7eeb4fc5c3658554771cf4a51558bf2b/properties/dapr_sidekick.snk -------------------------------------------------------------------------------- /properties/dapr_sidekick_common.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | $(MSBuildThisFileDirectory)..\ 6 | minimal 7 | 8 | -------------------------------------------------------------------------------- /properties/dapr_sidekick_nuget.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Man Group 5 | true 6 | Apache-2.0 7 | images\dapr_sidekick_package_icon.png 8 | Dapr;Sidekick 9 | https://github.com/man-group/dapr-sidekick-dotnet 10 | git 11 | $(RepoRoot)bin\$(Configuration)\nugets 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | true 22 | snupkg 23 | 24 | 25 | -------------------------------------------------------------------------------- /properties/dapr_sidekick_package_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/man-group/dapr-sidekick-dotnet/7a47300a7eeb4fc5c3658554771cf4a51558bf2b/properties/dapr_sidekick_package_icon.png -------------------------------------------------------------------------------- /samples/Actor/ActorSample/ActorSample.ActorClient/ActorSample.ActorClient.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net8.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /samples/Actor/ActorSample/ActorSample.DemoActor/ActorSample.DemoActor.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /samples/Actor/ActorSample/ActorSample.DemoActor/BankService.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. 3 | // Licensed under the MIT License. 4 | 5 | using IDemoActorInterface; 6 | 7 | namespace DaprDemoActor 8 | { 9 | public class BankService 10 | { 11 | // Allow overdraft of up to 50 (of whatever currency). 12 | private readonly decimal _overdraftThreshold = -50m; 13 | 14 | public decimal Withdraw(decimal balance, decimal amount) 15 | { 16 | // Imagine putting some complex auditing logic here in addition to the basics. 17 | 18 | var updated = balance - amount; 19 | if (updated < _overdraftThreshold) 20 | { 21 | throw new OverdraftException(balance, amount); 22 | } 23 | 24 | return updated; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /samples/Actor/ActorSample/ActorSample.DemoActor/Program.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. 3 | // Licensed under the MIT License. 4 | // ------------------------------------------------------------ 5 | 6 | namespace DaprDemoActor 7 | { 8 | using Microsoft.AspNetCore.Hosting; 9 | using Microsoft.Extensions.Hosting; 10 | using Serilog; 11 | 12 | public class Program 13 | { 14 | public static void Main(string[] args) 15 | { 16 | // Add Serilog for enhanced console logging. 17 | Log.Logger = new LoggerConfiguration() 18 | .Enrich.FromLogContext() 19 | .WriteTo.Console(outputTemplate: "{Timestamp:HH:mm:ss.fff} [{Level:u3}] [{SourceContext}] {Scope} {Message:lj}{NewLine}{Exception}") 20 | .MinimumLevel.Override("Man.Dapr.Sidekick", Serilog.Events.LogEventLevel.Debug) 21 | .MinimumLevel.Override("Microsoft.AspNetCore", Serilog.Events.LogEventLevel.Warning) 22 | .CreateLogger(); 23 | 24 | CreateHostBuilder(args).Build().Run(); 25 | } 26 | 27 | public static IHostBuilder CreateHostBuilder(string[] args) => 28 | Host.CreateDefaultBuilder(args) 29 | .UseSerilog() 30 | .ConfigureWebHostDefaults(webBuilder => 31 | { 32 | webBuilder.UseStartup(); 33 | }); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /samples/Actor/ActorSample/ActorSample.DemoActor/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "DemoActor": { 4 | "commandName": "Project", 5 | "launchBrowser": false, 6 | "environmentVariables": { 7 | "ASPNETCORE_ENVIRONMENT": "Development" 8 | }, 9 | "applicationUrl": "http://localhost:5000/" 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /samples/Actor/ActorSample/ActorSample.DemoActor/Startup.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. 3 | // Licensed under the MIT License. 4 | // ------------------------------------------------------------ 5 | 6 | namespace DaprDemoActor 7 | { 8 | using Microsoft.AspNetCore.Builder; 9 | using Microsoft.AspNetCore.Hosting; 10 | using Microsoft.Extensions.Configuration; 11 | using Microsoft.Extensions.DependencyInjection; 12 | using Microsoft.Extensions.Hosting; 13 | 14 | public class Startup 15 | { 16 | public Startup(IConfiguration configuration) 17 | { 18 | Configuration = configuration; 19 | } 20 | 21 | public IConfiguration Configuration { get; } 22 | 23 | public void ConfigureServices(IServiceCollection services) 24 | { 25 | services.AddSingleton(); 26 | services.AddActors(options => 27 | { 28 | options.Actors.RegisterActor(); 29 | }); 30 | 31 | // Add Dapr Sidekick 32 | services.AddDaprSidekick(Configuration); 33 | } 34 | 35 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 36 | { 37 | if (env.IsDevelopment()) 38 | { 39 | app.UseDeveloperExceptionPage(); 40 | } 41 | else 42 | { 43 | app.UseHsts(); 44 | } 45 | 46 | app.UseRouting(); 47 | 48 | app.UseEndpoints(endpoints => 49 | { 50 | endpoints.MapActorsHandlers(); 51 | }); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /samples/Actor/ActorSample/ActorSample.IDemoActor/ActorSample.IDemoActor.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /samples/Actor/ActorSample/ActorSample.IDemoActor/IBankActor.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. 3 | // Licensed under the MIT License. 4 | // ------------------------------------------------------------ 5 | 6 | namespace IDemoActorInterface 7 | { 8 | using System; 9 | using System.Threading.Tasks; 10 | using Dapr.Actors; 11 | 12 | public interface IBankActor : IActor 13 | { 14 | Task GetAccountBalance(); 15 | 16 | Task Withdraw(WithdrawRequest withdraw); 17 | } 18 | 19 | public class AccountBalance 20 | { 21 | public string AccountId { get; set; } 22 | 23 | public decimal Balance { get; set; } 24 | } 25 | 26 | public class WithdrawRequest 27 | { 28 | public decimal Amount { get; set; } 29 | } 30 | 31 | public class OverdraftException : Exception 32 | { 33 | public OverdraftException(decimal balance, decimal amount) 34 | : base($"Your current balance is {balance:c} - that's not enough to withdraw {amount:c}.") 35 | { 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /samples/Actor/README.md: -------------------------------------------------------------------------------- 1 | # Actor Dapr integration examples 2 | 3 | - [Actor Sample](./ActorSample): How to use Dapr Sidekick to launch Dapr Sidecars and the Placement service and integrate with the Dapr SDK for .NET for virtual actor invocation. 4 | -------------------------------------------------------------------------------- /samples/AspNetCore/AppConfigurationSample/AppConfigurationSample/AppConfigurationSample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 10 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /samples/AspNetCore/AppConfigurationSample/AppConfigurationSample/Controllers/SampleController.cs: -------------------------------------------------------------------------------- 1 | using Dapr.Client; 2 | using Microsoft.AspNetCore.Mvc; 3 | 4 | namespace AppConfigurationSample.Controllers; 5 | 6 | [ApiController] 7 | [Route("[controller]")] 8 | public class SampleController : ControllerBase 9 | { 10 | [HttpGet(Name = "GetSecret")] 11 | public async Task Get([FromServices] DaprClient daprClient, [FromServices] IConfiguration configuration) 12 | { 13 | // Can read secrets by using the client or IConfiguration through DI as well 14 | var clientSecrets = await daprClient.GetSecretAsync("localsecretstore", "secret"); 15 | var clientSecret = string.Join(",", clientSecrets.Select(d => d.Value)); 16 | 17 | var configurationSecret = configuration.GetSection("secret").Value; 18 | 19 | return Ok(new 20 | { 21 | SecretFromClient = clientSecret, 22 | SecretFromConfiguration = configurationSecret 23 | }); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /samples/AspNetCore/AppConfigurationSample/AppConfigurationSample/Dapr/Components/secretstore.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: localsecretstore 5 | namespace: default 6 | spec: 7 | type: secretstores.local.file 8 | version: v1 9 | metadata: 10 | - name: secretsFile 11 | value: "Dapr/secrets.json" 12 | 13 | -------------------------------------------------------------------------------- /samples/AspNetCore/AppConfigurationSample/AppConfigurationSample/Dapr/secrets.json: -------------------------------------------------------------------------------- 1 | { 2 | "secret": "YourPasskeyHere" 3 | } 4 | -------------------------------------------------------------------------------- /samples/AspNetCore/AppConfigurationSample/AppConfigurationSample/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/launchsettings.json", 3 | "profiles": { 4 | "https": { 5 | "commandName": "Project", 6 | "dotnetRunMessages": true, 7 | "launchBrowser": true, 8 | "launchUrl": "swagger", 9 | "applicationUrl": "https://localhost:5000", 10 | "environmentVariables": { 11 | "ASPNETCORE_ENVIRONMENT": "Development" 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /samples/AspNetCore/AppConfigurationSample/AppConfigurationSample/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /samples/AspNetCore/AppConfigurationSample/AppConfigurationSample/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*" 9 | } 10 | -------------------------------------------------------------------------------- /samples/AspNetCore/ConsulSample/ConsulSample.Receiver/ConsulSample.Receiver.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | Always 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /samples/AspNetCore/ConsulSample/ConsulSample.Receiver/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Hosting; 2 | using Microsoft.Extensions.Hosting; 3 | using Serilog; 4 | 5 | namespace ConsulSample.Receiver 6 | { 7 | public class Program 8 | { 9 | public static void Main(string[] args) 10 | { 11 | // Add Serilog for enhanced console logging. 12 | Log.Logger = new LoggerConfiguration() 13 | .Enrich.FromLogContext() 14 | .WriteTo.Console() 15 | .CreateLogger(); 16 | 17 | CreateHostBuilder(args).Build().Run(); 18 | } 19 | 20 | public static IHostBuilder CreateHostBuilder(string[] args) => 21 | Host.CreateDefaultBuilder(args) 22 | .UseSerilog() 23 | .ConfigureWebHostDefaults(webBuilder => 24 | { 25 | webBuilder.UseStartup(); 26 | }); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /samples/AspNetCore/ConsulSample/ConsulSample.Receiver/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "profiles": { 4 | "ConsulSample.Receiver": { 5 | "commandName": "Project", 6 | "dotnetRunMessages": "true", 7 | "launchBrowser": false, 8 | "launchUrl": "swagger", 9 | "applicationUrl": "http://localhost:5001", 10 | "environmentVariables": { 11 | "ASPNETCORE_ENVIRONMENT": "Development" 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /samples/AspNetCore/ConsulSample/ConsulSample.Receiver/WeatherForecast.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ConsulSample.Receiver 4 | { 5 | public class WeatherForecast 6 | { 7 | public DateTime Date { get; set; } 8 | 9 | public int TemperatureC { get; set; } 10 | 11 | public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); 12 | 13 | public string Summary { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /samples/AspNetCore/ConsulSample/ConsulSample.Receiver/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /samples/AspNetCore/ConsulSample/ConsulSample.Receiver/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "DaprSidekick": { 3 | // Set the runtime location of config/components files to be the "dapr" folder under the deployed application 4 | "RuntimeDirectory": "dapr" 5 | }, 6 | "Logging": { 7 | "LogLevel": { 8 | "Default": "Information", 9 | "Microsoft": "Warning", 10 | "Microsoft.Hosting.Lifetime": "Information" 11 | } 12 | }, 13 | "AllowedHosts": "*" 14 | } 15 | -------------------------------------------------------------------------------- /samples/AspNetCore/ConsulSample/ConsulSample.Receiver/dapr/config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Configuration 3 | spec: 4 | nameResolution: 5 | component: "consul" 6 | configuration: 7 | selfRegister: true 8 | tags: 9 | - "dapr" 10 | checks: 11 | - name: "Service Health Status" 12 | checkID: "serviceHealth:${APP_ID}" 13 | interval: "5s" 14 | http: "http://127.0.0.1:${APP_PORT}/health" 15 | meta: 16 | DAPR_HTTP_PORT: "${DAPR_HTTP_PORT}" 17 | DAPR_GRPC_PORT: "${DAPR_GRPC_PORT}" 18 | DAPR_METRICS_PORT: "${DAPR_METRICS_PORT}" 19 | -------------------------------------------------------------------------------- /samples/AspNetCore/ConsulSample/ConsulSample.Sender/ConsulSample.Sender.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | Always 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /samples/AspNetCore/ConsulSample/ConsulSample.Sender/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Hosting; 2 | using Microsoft.Extensions.Hosting; 3 | using Serilog; 4 | 5 | namespace ConsulSample.Sender 6 | { 7 | public class Program 8 | { 9 | public static void Main(string[] args) 10 | { 11 | // Add Serilog for enhanced console logging. 12 | Log.Logger = new LoggerConfiguration() 13 | .Enrich.FromLogContext() 14 | .WriteTo.Console() 15 | .CreateLogger(); 16 | 17 | CreateHostBuilder(args).Build().Run(); 18 | } 19 | 20 | public static IHostBuilder CreateHostBuilder(string[] args) => 21 | Host.CreateDefaultBuilder(args) 22 | .UseSerilog() 23 | .ConfigureWebHostDefaults(webBuilder => 24 | { 25 | webBuilder.UseStartup(); 26 | }); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /samples/AspNetCore/ConsulSample/ConsulSample.Sender/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "profiles": { 4 | "ConsulSample.Sender": { 5 | "commandName": "Project", 6 | "dotnetRunMessages": "true", 7 | "launchBrowser": true, 8 | "launchUrl": "swagger", 9 | "applicationUrl": "http://localhost:5000", 10 | "environmentVariables": { 11 | "ASPNETCORE_ENVIRONMENT": "Development" 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /samples/AspNetCore/ConsulSample/ConsulSample.Sender/WeatherForecast.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ConsulSample.Sender 4 | { 5 | public class WeatherForecast 6 | { 7 | public DateTime Date { get; set; } 8 | 9 | public int TemperatureC { get; set; } 10 | 11 | public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); 12 | 13 | public string Summary { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /samples/AspNetCore/ConsulSample/ConsulSample.Sender/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /samples/AspNetCore/ConsulSample/ConsulSample.Sender/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "DaprSidekick": { 3 | // Set the runtime location of config/components files to be the "dapr" folder under the deployed application 4 | "RuntimeDirectory": "dapr" 5 | }, 6 | "Logging": { 7 | "LogLevel": { 8 | "Default": "Information", 9 | "Microsoft": "Warning", 10 | "Microsoft.Hosting.Lifetime": "Information" 11 | } 12 | }, 13 | "AllowedHosts": "*" 14 | } 15 | -------------------------------------------------------------------------------- /samples/AspNetCore/ConsulSample/ConsulSample.Sender/dapr/config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Configuration 3 | spec: 4 | nameResolution: 5 | component: "consul" 6 | configuration: 7 | selfRegister: true 8 | tags: 9 | - "dapr" 10 | checks: 11 | - name: "Service Health Status" 12 | checkID: "serviceHealth:${APP_ID}" 13 | interval: "5s" 14 | http: "http://127.0.0.1:${APP_PORT}/health" 15 | meta: 16 | DAPR_HTTP_PORT: "${DAPR_HTTP_PORT}" 17 | DAPR_GRPC_PORT: "${DAPR_GRPC_PORT}" 18 | DAPR_METRICS_PORT: "${DAPR_METRICS_PORT}" 19 | -------------------------------------------------------------------------------- /samples/AspNetCore/ControllerSample/ControllerSample/Account.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. 3 | // Licensed under the MIT License. 4 | // ------------------------------------------------------------ 5 | 6 | namespace ControllerSample 7 | { 8 | /// 9 | /// Class representing an Account for samples. 10 | /// 11 | public class Account 12 | { 13 | /// 14 | /// Gets or sets account id. 15 | /// 16 | public string Id { get; set; } 17 | 18 | /// 19 | /// Gets or sets account balance. 20 | /// 21 | public decimal Balance { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /samples/AspNetCore/ControllerSample/ControllerSample/ControllerSample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /samples/AspNetCore/ControllerSample/ControllerSample/Program.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. 3 | // Licensed under the MIT License. 4 | // ------------------------------------------------------------ 5 | 6 | namespace ControllerSample 7 | { 8 | using Microsoft.AspNetCore.Hosting; 9 | using Microsoft.Extensions.Hosting; 10 | using Serilog; 11 | 12 | /// 13 | /// Controller Sample. 14 | /// 15 | public class Program 16 | { 17 | /// 18 | /// Main for Controller Sample. 19 | /// 20 | /// Arguments. 21 | public static void Main(string[] args) 22 | { 23 | // Add Serilog for enhanced console logging. 24 | Log.Logger = new LoggerConfiguration() 25 | .Enrich.FromLogContext() 26 | .WriteTo.Console() 27 | .CreateLogger(); 28 | 29 | CreateHostBuilder(args).Build().Run(); 30 | } 31 | 32 | /// 33 | /// Creates WebHost Builder. 34 | /// 35 | /// Arguments. 36 | /// Returns IHostbuilder. 37 | public static IHostBuilder CreateHostBuilder(string[] args) => 38 | Host.CreateDefaultBuilder(args) 39 | .UseSerilog() 40 | .ConfigureWebHostDefaults(webBuilder => 41 | { 42 | webBuilder.UseStartup(); 43 | }); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /samples/AspNetCore/ControllerSample/ControllerSample/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "ControllerSample": { 4 | "commandName": "Project", 5 | "launchBrowser": true, 6 | "environmentVariables": { 7 | "ASPNETCORE_ENVIRONMENT": "Development" 8 | }, 9 | "applicationUrl": "http://localhost:5000/" 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /samples/AspNetCore/ControllerSample/ControllerSample/Transaction.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------ 2 | // Copyright (c) Microsoft Corporation. 3 | // Licensed under the MIT License. 4 | // ------------------------------------------------------------ 5 | 6 | namespace ControllerSample 7 | { 8 | using System.ComponentModel.DataAnnotations; 9 | 10 | /// 11 | /// Represents a transaction used by sample code. 12 | /// 13 | public class Transaction 14 | { 15 | /// 16 | /// Gets or sets account id for the transaction. 17 | /// 18 | [Required] 19 | public string Id { get; set; } 20 | 21 | /// 22 | /// Gets or sets amount for the transaction. 23 | /// 24 | [Range(0, double.MaxValue)] 25 | public decimal Amount { get; set; } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /samples/AspNetCore/ControllerSample/ControllerSample/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Serilog": { 3 | "MinimumLevel": "Debug" 4 | }, 5 | "Logging": { 6 | "LogLevel": { 7 | "Default": "Debug", 8 | "Microsoft": "Warning", 9 | "Microsoft.Hosting.Lifetime": "Information" 10 | } 11 | }, 12 | "AllowedHosts": "*" 13 | } 14 | -------------------------------------------------------------------------------- /samples/AspNetCore/ControllerSample/ControllerSample/sample.http: -------------------------------------------------------------------------------- 1 | //Deposit Money 2 | 3 | POST http://127.0.0.1:5000/deposit 4 | Content-Type: application/json 5 | 6 | { "id": "17", "amount": 12 } 7 | 8 | ### 9 | 10 | //Withdraw Money 11 | 12 | POST http://127.0.0.1:5000/withdraw 13 | Content-Type: application/json 14 | 15 | { "id": "17", "amount": 5 } 16 | 17 | ### 18 | 19 | //View Balance 20 | 21 | GET http://127.0.0.1:5000/17 22 | -------------------------------------------------------------------------------- /samples/AspNetCore/ControllerSample/README.md: -------------------------------------------------------------------------------- 1 | # ASP.NET Core Controller example 2 | 3 | This sample shows using Dapr with ASP.NET Core controllers. This application is a simple and not-so-secure banking application. The application uses the Dapr state-store for its data storage. The sample is a copy of the [Dapr .NET SDK Controller example](https://github.com/dapr/dotnet-sdk/tree/master/examples/AspNetCore/ControllerSample), but modified to include Dapr Sidekick integration for launching a Dapr sidecar. 4 | 5 | > See the [original source](https://github.com/dapr/dotnet-sdk/tree/master/examples/AspNetCore/ControllerSample) for more information on how to use the sample. 6 | 7 | ## How Dapr Sidekick was added 8 | 9 | The main change to the template code to add Dapr support can be found in the `ConfigureServices` method in `Startup.cs`: 10 | 11 | ```csharp 12 | public void ConfigureServices(IServiceCollection services) 13 | { 14 | ... 15 | // Add Dapr Sidekick 16 | services.AddDaprSidekick(Configuration); 17 | } 18 | ``` 19 | 20 | ## Running the sample 21 | 22 | To run the sample simply set `ControllerSample` as the startup project and run it in Visual Studio, it will launch the Dapr sidecar and connect to it. 23 | 24 | For all further instructions, including prerequisites and testing, please refer to the [original source](https://github.com/dapr/dotnet-sdk/tree/master/examples/AspNetCore/ControllerSample). 25 | -------------------------------------------------------------------------------- /samples/AspNetCore/PlacementSample/PlacementSample/PlacementSample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | Always 20 | 21 | 22 | Always 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /samples/AspNetCore/PlacementSample/PlacementSample/Program.cs: -------------------------------------------------------------------------------- 1 | using Man.Dapr.Sidekick; 2 | using Serilog; 3 | 4 | // Add Serilog for enhanced console logging. 5 | Log.Logger = new LoggerConfiguration() 6 | .Enrich.FromLogContext() 7 | .WriteTo.Console() 8 | .CreateLogger(); 9 | 10 | var builder = WebApplication.CreateBuilder(args); 11 | 12 | builder.Services.AddControllers(); 13 | 14 | // Add Dapr Sidekick with Placement 15 | builder.Services.AddDaprSidekick(builder.Configuration) 16 | .AddPlacement(); 17 | 18 | builder.Host.UseSerilog(); 19 | 20 | var app = builder.Build(); 21 | 22 | app.MapGet("/status", (IDaprSidecarHost sidecarHost, IDaprPlacementHost placementHost) => Results.Ok(new 23 | { 24 | sidecar = new 25 | { 26 | process = sidecarHost.GetProcessInfo(), // Information about the sidecar process such as if it is running 27 | options = sidecarHost.GetProcessOptions() // The sidecar options if running, including ports and locations 28 | }, 29 | placement = new 30 | { 31 | process = placementHost.GetProcessInfo(), // Information about the sentry process such as if it is running 32 | options = placementHost.GetProcessOptions() // The sentry options if running, including ports and locations 33 | }, 34 | })); 35 | 36 | // For Dapr 37 | app.MapHealthChecks("/health"); 38 | 39 | app.Run(); 40 | -------------------------------------------------------------------------------- /samples/AspNetCore/PlacementSample/PlacementSample/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "PlacementSample": { 4 | "commandName": "Project", 5 | "launchBrowser": true, 6 | "launchUrl": "status", 7 | "environmentVariables": { 8 | "ASPNETCORE_ENVIRONMENT": "Development" 9 | }, 10 | "applicationUrl": "http://localhost:5000" 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /samples/AspNetCore/PlacementSample/PlacementSample/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /samples/AspNetCore/PlacementSample/PlacementSample/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "DaprSidekick": { 3 | "Sidecar": { 4 | "RuntimeDirectory": "dapr" 5 | }, 6 | "Placement": { 7 | "RuntimeDirectory": "placement", 8 | "Id": "dapr-placement-0", // Optional unique identifier when used in a cluster 9 | "Port": 6051 // To avoid conflicts with local Dapr Placement container. Sidecar will use this automatically as well. 10 | } 11 | }, 12 | "Logging": { 13 | "LogLevel": { 14 | "Default": "Information", 15 | "Microsoft.AspNetCore": "Warning" 16 | } 17 | }, 18 | "AllowedHosts": "*" 19 | } 20 | -------------------------------------------------------------------------------- /samples/AspNetCore/PlacementSample/PlacementSample/dapr/config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Configuration 3 | metadata: 4 | name: daprsystem 5 | namespace: default 6 | spec: 7 | mtls: 8 | enabled: true -------------------------------------------------------------------------------- /samples/AspNetCore/PlacementSample/PlacementSample/placement/config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Configuration 3 | metadata: 4 | name: daprsystem 5 | namespace: default 6 | spec: 7 | -------------------------------------------------------------------------------- /samples/AspNetCore/README.md: -------------------------------------------------------------------------------- 1 | # ASP.NET Core Dapr integration examples 2 | 3 | - [Consul Sample](./ConsulSample): How to use Dapr Sidekick to launch the Dapr Sidecar and invoke remote services using Consul Service Discovery. 4 | - [Controller Sample](./ControllerSample): How to use Dapr Sidekick to launch the Dapr Sidecar integrated with the official Dapr .NET SDK with ASP.NET Core Controllers. 5 | - [Service Invocation Sample](./ServiceInvocationSample): How to use Dapr Sidekick to launch the Dapr Sidecar and invoke local services. 6 | 7 | -------------------------------------------------------------------------------- /samples/AspNetCore/SchedulerSample/SchedulerSample/Program.cs: -------------------------------------------------------------------------------- 1 | using Man.Dapr.Sidekick; 2 | using Serilog; 3 | 4 | // Add Serilog for enhanced console logging. 5 | Log.Logger = new LoggerConfiguration() 6 | .Enrich.FromLogContext() 7 | .WriteTo.Console() 8 | .CreateLogger(); 9 | 10 | var builder = WebApplication.CreateBuilder(args); 11 | 12 | builder.Services.AddControllers(); 13 | 14 | // Add Dapr Sidekick with Scheduler 15 | builder.Services.AddDaprSidekick(builder.Configuration) 16 | .AddScheduler(); 17 | 18 | builder.Host.UseSerilog(); 19 | 20 | var app = builder.Build(); 21 | 22 | app.MapGet("/status", (IDaprSidecarHost sidecarHost, IDaprSchedulerHost schedulerHost) => Results.Ok(new 23 | { 24 | sidecar = new 25 | { 26 | process = sidecarHost.GetProcessInfo(), // Information about the sidecar process such as if it is running 27 | options = sidecarHost.GetProcessOptions() // The sidecar options if running, including ports and locations 28 | }, 29 | scheduler = new 30 | { 31 | process = schedulerHost.GetProcessInfo(), // Information about the sentry process such as if it is running 32 | options = schedulerHost.GetProcessOptions() // The sentry options if running, including ports and locations 33 | }, 34 | })); 35 | 36 | // For Dapr 37 | app.MapHealthChecks("/health"); 38 | 39 | app.Run(); 40 | -------------------------------------------------------------------------------- /samples/AspNetCore/SchedulerSample/SchedulerSample/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "SchedulerSample": { 4 | "commandName": "Project", 5 | "launchBrowser": true, 6 | "launchUrl": "status", 7 | "environmentVariables": { 8 | "ASPNETCORE_ENVIRONMENT": "Development" 9 | }, 10 | "applicationUrl": "http://localhost:5000" 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /samples/AspNetCore/SchedulerSample/SchedulerSample/SchedulerSample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | Always 20 | 21 | 22 | Always 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /samples/AspNetCore/SchedulerSample/SchedulerSample/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /samples/AspNetCore/SchedulerSample/SchedulerSample/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "DaprSidekick": { 3 | "Sidecar": { 4 | "RuntimeDirectory": "dapr" 5 | }, 6 | "Scheduler": { 7 | "RuntimeDirectory": "scheduler", 8 | "Id": "dapr-scheduler-server-0", // Optional unique identifier when used in a cluster 9 | "Port": 6061 // To avoid conflicts with local Dapr Scheduler container. Sidecar will use this automatically as well. 10 | } 11 | }, 12 | "Logging": { 13 | "LogLevel": { 14 | "Default": "Information", 15 | "Microsoft.AspNetCore": "Warning" 16 | } 17 | }, 18 | "AllowedHosts": "*" 19 | } 20 | -------------------------------------------------------------------------------- /samples/AspNetCore/SchedulerSample/SchedulerSample/dapr/config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Configuration 3 | metadata: 4 | name: daprsystem 5 | namespace: default 6 | spec: 7 | mtls: 8 | enabled: true -------------------------------------------------------------------------------- /samples/AspNetCore/SchedulerSample/SchedulerSample/scheduler/config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Configuration 3 | metadata: 4 | name: daprsystem 5 | namespace: default 6 | spec: 7 | -------------------------------------------------------------------------------- /samples/AspNetCore/SentrySample/SentrySample/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "SentrySample": { 4 | "commandName": "Project", 5 | "launchBrowser": true, 6 | "launchUrl": "status", 7 | "environmentVariables": { 8 | "ASPNETCORE_ENVIRONMENT": "Development" 9 | }, 10 | "applicationUrl": "http://localhost:5000" 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /samples/AspNetCore/SentrySample/SentrySample/SentrySample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | Always 20 | 21 | 22 | Always 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /samples/AspNetCore/SentrySample/SentrySample/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /samples/AspNetCore/SentrySample/SentrySample/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "DaprSidekick": { 3 | "Sidecar": { 4 | "mTLS": true, 5 | "RuntimeDirectory": "dapr", 6 | "SentryAddress": "localhost:50001" 7 | }, 8 | "Sentry": { 9 | "RuntimeDirectory": "sentry", 10 | "TrustDomain": "cluster.local" // Certificates in /certs folder generated for this domain 11 | } 12 | }, 13 | "Logging": { 14 | "LogLevel": { 15 | "Default": "Information", 16 | "Microsoft.AspNetCore": "Warning" 17 | } 18 | }, 19 | "AllowedHosts": "*" 20 | } 21 | -------------------------------------------------------------------------------- /samples/AspNetCore/SentrySample/SentrySample/dapr/config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Configuration 3 | metadata: 4 | name: daprsystem 5 | namespace: default 6 | spec: 7 | mtls: 8 | enabled: true -------------------------------------------------------------------------------- /samples/AspNetCore/SentrySample/SentrySample/sentry/certs/ca.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIBcjCCARegAwIBAgIRAPNjhmnvu5t1cT4RleqbpIgwCgYIKoZIzj0EAwIwGDEW 3 | MBQGA1UEChMNY2x1c3Rlci5sb2NhbDAeFw0yNDA0MDkxNjMxNDVaFw0yNTA0MDkx 4 | NjQ2NDVaMBgxFjAUBgNVBAoTDWNsdXN0ZXIubG9jYWwwWTATBgcqhkjOPQIBBggq 5 | hkjOPQMBBwNCAAQnuU4Xu2OicVtxHSvpByI4Q3v3Ld4UKpMKvR3+iPs0goJRmkOd 6 | +rgKfUJRu99Al89iF1Jc0xp2G3hqsTJzRNGmo0IwQDAOBgNVHQ8BAf8EBAMCAqQw 7 | DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUClFVts/NEUrgwtxGRVHYdsr5MkAw 8 | CgYIKoZIzj0EAwIDSQAwRgIhAL1kZ/CgvaVstjh6Wl7Xpq9S5cqL/uDBP8qA535J 9 | gEEhAiEAiPkgINWSCjvunsyCS2MzGRqzXS5F9hSMsl8JJvAAk3A= 10 | -----END CERTIFICATE----- 11 | -------------------------------------------------------------------------------- /samples/AspNetCore/SentrySample/SentrySample/sentry/certs/issuer.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIBqzCCAVGgAwIBAgIRAIwB5uvnwvPxdYpnXs68vxAwCgYIKoZIzj0EAwIwGDEW 3 | MBQGA1UEChMNY2x1c3Rlci5sb2NhbDAeFw0yNDA0MDkxNjMxNDVaFw0yNTA0MDkx 4 | NjQ2NDVaMDgxNjA0BgNVBAoTLXNwaWZmZTovL2NsdXN0ZXIubG9jYWwvbnMvZGVm 5 | YXVsdC9kYXByLXNlbnRyeTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABIlCFe0s 6 | g2hyCoT+jtFfIUKPLcJmT6kI1cOWhd9lEdKxRQQK0WAIpgLoBU1dV/bQEh2vTI7h 7 | +UP8JYTib6RLy5mjXDBaMA4GA1UdDwEB/wQEAwIBpjAPBgNVHRMBAf8EBTADAQH/ 8 | MB0GA1UdDgQWBBRDRvGl7xL2km4sd7pln3ayKZEv3DAYBgNVHREEETAPgg1jbHVz 9 | dGVyLmxvY2FsMAoGCCqGSM49BAMCA0gAMEUCIGMbBjjNPM2lgSojy4Zdr3EZO4qZ 10 | 7QUC39qit7zrHEaUAiEA2GHEgHHu7gJdDoTz9Up+jSjIfDIRNgOqUpHsldEwN0c= 11 | -----END CERTIFICATE----- 12 | -------------------------------------------------------------------------------- /samples/AspNetCore/SentrySample/SentrySample/sentry/certs/issuer.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgwVI9SsqI5owZm19/ 3 | NI2uN4yp9WkqE8W8/zhM4AZOvwahRANCAASJQhXtLINocgqE/o7RXyFCjy3CZk+p 4 | CNXDloXfZRHSsUUECtFgCKYC6AVNXVf20BIdr0yO4flD/CWE4m+kS8uZ 5 | -----END PRIVATE KEY----- 6 | -------------------------------------------------------------------------------- /samples/AspNetCore/SentrySample/SentrySample/sentry/config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Configuration 3 | metadata: 4 | name: daprsystem 5 | namespace: default 6 | spec: 7 | mtls: 8 | enabled: true 9 | workloadCertTTL: "24h" 10 | allowedClockSkew: "15m" 11 | accessControl: 12 | defaultAction: allow -------------------------------------------------------------------------------- /samples/AspNetCore/ServiceInvocationSample/ServiceInvocationSample/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Hosting; 2 | using Microsoft.Extensions.Hosting; 3 | using Serilog; 4 | 5 | namespace ServiceInvocationSample 6 | { 7 | public class Program 8 | { 9 | public static void Main(string[] args) 10 | { 11 | // Add Serilog for enhanced console logging. 12 | Log.Logger = new LoggerConfiguration() 13 | .Enrich.FromLogContext() 14 | .WriteTo.Console() 15 | .CreateLogger(); 16 | 17 | CreateHostBuilder(args).Build().Run(); 18 | } 19 | 20 | public static IHostBuilder CreateHostBuilder(string[] args) => 21 | Host.CreateDefaultBuilder(args) 22 | .UseSerilog() 23 | .ConfigureWebHostDefaults(webBuilder => 24 | { 25 | webBuilder.UseStartup(); 26 | }); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /samples/AspNetCore/ServiceInvocationSample/ServiceInvocationSample/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "profiles": { 4 | "Console": { 5 | "commandName": "Project", 6 | "launchBrowser": true, 7 | "launchUrl": "weatherforecast/status", 8 | "applicationUrl": "http://localhost:5000", 9 | "environmentVariables": { 10 | "ASPNETCORE_ENVIRONMENT": "Development" 11 | } 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /samples/AspNetCore/ServiceInvocationSample/ServiceInvocationSample/ServiceInvocationSample.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /samples/AspNetCore/ServiceInvocationSample/ServiceInvocationSample/Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Extensions.Configuration; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.Extensions.Hosting; 6 | 7 | namespace ServiceInvocationSample 8 | { 9 | public class Startup 10 | { 11 | public Startup(IConfiguration configuration) 12 | { 13 | Configuration = configuration; 14 | } 15 | 16 | public IConfiguration Configuration { get; } 17 | 18 | // This method gets called by the runtime. Use this method to add services to the container. 19 | public void ConfigureServices(IServiceCollection services) 20 | { 21 | services.AddControllers(); 22 | 23 | // Add Dapr Sidekick 24 | services.AddDaprSidekick(Configuration); 25 | } 26 | 27 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 28 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 29 | { 30 | if (env.IsDevelopment()) 31 | { 32 | app.UseDeveloperExceptionPage(); 33 | } 34 | 35 | app.UseRouting(); 36 | 37 | app.UseAuthorization(); 38 | 39 | app.UseEndpoints(endpoints => 40 | { 41 | endpoints.MapControllers(); 42 | 43 | // For Dapr 44 | endpoints.MapHealthChecks("/health"); 45 | }); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /samples/AspNetCore/ServiceInvocationSample/ServiceInvocationSample/WeatherForecast.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ServiceInvocationSample 4 | { 5 | public class WeatherForecast 6 | { 7 | public DateTime Date { get; set; } 8 | 9 | public int TemperatureC { get; set; } 10 | 11 | public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); 12 | 13 | public string Summary { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /samples/AspNetCore/ServiceInvocationSample/ServiceInvocationSample/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "AllowedHosts": "*" 10 | } 11 | -------------------------------------------------------------------------------- /samples/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | $(RepoRoot)bin\$(Configuration)\samples\$(MSBuildProjectName)\ 7 | false 8 | 9 | 10 | -------------------------------------------------------------------------------- /samples/NetFramework/README.md: -------------------------------------------------------------------------------- 1 | # .NET Framework Dapr integration examples 2 | 3 | - [WCF Sample](./WcfSample): How to use Dapr Sidekick to launch the Dapr Sidecar and invoke local services on a WCF HTTP endpoint. 4 | -------------------------------------------------------------------------------- /samples/NetFramework/WcfSample/WcfSample/IWeatherForecastService.cs: -------------------------------------------------------------------------------- 1 | using System.ServiceModel; 2 | using System.ServiceModel.Channels; 3 | using System.ServiceModel.Web; 4 | 5 | namespace WcfSample 6 | { 7 | [ServiceContract] 8 | public interface IWeatherForecastService 9 | { 10 | [OperationContract] 11 | [WebGet] 12 | Message Health(); 13 | 14 | [OperationContract] 15 | [WebGet] 16 | Message Metadata(); 17 | 18 | [OperationContract] 19 | [WebGet] 20 | Message Metrics(); 21 | 22 | [OperationContract] 23 | [WebGet] 24 | Message Status(); 25 | 26 | [OperationContract] 27 | [WebGet] 28 | Message Weather(); 29 | 30 | [OperationContract] 31 | [WebGet] 32 | Message WeatherSidecar(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /samples/NetFramework/WcfSample/WcfSample/WcfSample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net45 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /samples/NetFramework/WcfSample/WcfSample/WeatherForecast.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.Serialization; 3 | 4 | namespace WcfSample 5 | { 6 | [DataContract] 7 | public class WeatherForecast 8 | { 9 | [DataMember] 10 | public DateTime Date { get; set; } 11 | 12 | [DataMember] 13 | public int TemperatureC { get; set; } 14 | 15 | [DataMember] 16 | public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); 17 | 18 | [DataMember] 19 | public string Summary { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /samples/README.md: -------------------------------------------------------------------------------- 1 | # Dapr Sidekick samples 2 | 3 | This repository contains samples that highlight the Dapr Sidekick capabilities: 4 | 5 | | Samples | Description | 6 | | -------------------------------- | ----------------------------------------------------------------------------- | 7 | | [Actor](./Actor) | Demonstrates creating virtual actors with the Dapr .NET SDK and Dapr Sidekick | 8 | | [ASP.NET Core](./AspNetCore) | Demonstrates ASP.NET Core integration with Dapr Sidekick | 9 | | [.NET Framework](./NetFramework) | Demonstrates .NET Framework integration with Dapr Sidekick | 10 | -------------------------------------------------------------------------------- /samples/Workflow/ConsoleSample/WorkflowConsoleApp/Activities/NotifyActivity.cs: -------------------------------------------------------------------------------- 1 | using Dapr.Workflow; 2 | using Microsoft.Extensions.Logging; 3 | 4 | namespace WorkflowConsoleApp.Activities 5 | { 6 | public class NotifyActivity(ILoggerFactory loggerFactory) : WorkflowActivity 7 | { 8 | private readonly ILogger _logger = loggerFactory.CreateLogger(); 9 | 10 | public override Task RunAsync(WorkflowActivityContext context, Notification notification) 11 | { 12 | _logger.LogInformation(notification.Message); 13 | 14 | return Task.FromResult(null); 15 | } 16 | } 17 | 18 | public record Notification(string Message); 19 | } 20 | -------------------------------------------------------------------------------- /samples/Workflow/ConsoleSample/WorkflowConsoleApp/Activities/ProcessPaymentActivity.cs: -------------------------------------------------------------------------------- 1 | using Dapr.Workflow; 2 | using Microsoft.Extensions.Logging; 3 | 4 | namespace WorkflowConsoleApp.Activities 5 | { 6 | public class ProcessPaymentActivity(ILoggerFactory loggerFactory) : WorkflowActivity 7 | { 8 | private readonly ILogger _logger = loggerFactory.CreateLogger(); 9 | 10 | public override async Task RunAsync(WorkflowActivityContext context, PaymentRequest req) 11 | { 12 | _logger.LogInformation( 13 | "Processing payment: {requestId} for {amount} {item} at ${currency}", 14 | req.RequestId, 15 | req.Amount, 16 | req.ItemName, 17 | req.Currency); 18 | 19 | // Simulate slow processing 20 | await Task.Delay(TimeSpan.FromSeconds(7)); 21 | 22 | _logger.LogInformation( 23 | "Payment for request ID '{requestId}' processed successfully", 24 | req.RequestId); 25 | 26 | return null; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /samples/Workflow/ConsoleSample/WorkflowConsoleApp/Activities/RequestApprovalActivity.cs: -------------------------------------------------------------------------------- 1 | using Dapr.Workflow; 2 | using Microsoft.Extensions.Logging; 3 | 4 | namespace WorkflowConsoleApp.Activities 5 | { 6 | public class RequestApprovalActivity(ILoggerFactory loggerFactory) : WorkflowActivity 7 | { 8 | private readonly ILogger _logger = loggerFactory.CreateLogger(); 9 | 10 | public override Task RunAsync(WorkflowActivityContext context, OrderPayload input) 11 | { 12 | var orderId = context.InstanceId; 13 | _logger.LogInformation("Requesting approval for order {orderId}", orderId); 14 | 15 | return Task.FromResult(null); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /samples/Workflow/ConsoleSample/WorkflowConsoleApp/Models.cs: -------------------------------------------------------------------------------- 1 | #pragma warning disable SA1649 // File name should match first type name 2 | namespace WorkflowConsoleApp 3 | { 4 | public record OrderPayload(string Name, double TotalCost, int Quantity = 1); 5 | 6 | public record InventoryRequest(string RequestId, string ItemName, int Quantity); 7 | 8 | public record InventoryResult(bool Success, InventoryItem OrderPayload); 9 | 10 | public record PaymentRequest(string RequestId, string ItemName, int Amount, double Currency); 11 | 12 | public record OrderResult(bool Processed); 13 | 14 | public record InventoryItem(string Name, double PerItemCost, int Quantity); 15 | 16 | public enum ApprovalResult 17 | { 18 | Unspecified = 0, 19 | Approved = 1, 20 | Rejected = 2, 21 | } 22 | } 23 | #pragma warning restore SA1649 // File name should match first type name 24 | -------------------------------------------------------------------------------- /samples/Workflow/ConsoleSample/WorkflowConsoleApp/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "OrderingWebApi": { 4 | "commandName": "Project", 5 | "launchBrowser": true, 6 | "environmentVariables": { 7 | "ASPNETCORE_ENVIRONMENT": "Development" 8 | }, 9 | "applicationUrl": "http://localhost:10080" 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /samples/Workflow/ConsoleSample/WorkflowConsoleApp/WorkflowConsoleApp.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | 612,618 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | Always 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /samples/Workflow/ConsoleSample/WorkflowConsoleApp/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug" 5 | } 6 | }, 7 | "DaprSidekick": { 8 | "Sidecar": { 9 | // Generic host build doesn't listen on an AppPort - disable here so Sidecar doesn't wait for it indefinitely 10 | "HasAppPort": false 11 | } 12 | } 13 | } 14 | 15 | -------------------------------------------------------------------------------- /samples/Workflow/ConsoleSample/WorkflowConsoleApp/demo.http: -------------------------------------------------------------------------------- 1 | ### Start order processing workflow - replace xxx with any id you like 2 | POST http://localhost:3500/v1.0-beta1/workflows/dapr/OrderProcessingWorkflow/start?instanceID=xxx 3 | Content-Type: application/json 4 | 5 | {"Name": "Paperclips", "TotalCost": 99.95, "Quantity": 1} 6 | 7 | ### Start order processing workflow - replace xxx with any id you like 8 | POST http://localhost:3500/v1.0-beta1/workflows/dapr/OrderProcessingWorkflow/start?instanceID=xxx 9 | Content-Type: application/json 10 | 11 | {"Name": "Cars", "TotalCost": 10000, "Quantity": 30} 12 | 13 | ### Query dapr sidecar - replace xxx with id from the workflow you've created above 14 | GET http://localhost:3500/v1.0-beta1/workflows/dapr/xxx 15 | 16 | ### Terminate the workflow - replace xxx with id from the workflow you've created above 17 | POST http://localhost:3500/v1.0-beta1/workflows/dapr/xxx/terminate -------------------------------------------------------------------------------- /src/Directory.build.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | $(RepoRoot)bin\$(Configuration)\prod\$(MSBuildProjectName)\ 8 | true 9 | $(OutputPath)$(MSBuildProjectName).xml 10 | 11 | 12 | 13 | 14 | true 15 | true 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | true 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick.AspNetCore/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly:InternalsVisibleTo("Man.Dapr.Sidekick.AspNetCore.Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010085db710a00eb960715161fe42d9c848ccb264b514f6c09875e2ef4e375ecb1b829795fdd33a842db71bd0fb9261fee0fc9634bdaca0f7900ddb8505069202c72f5eaddc39596c39ab31f7c68656e47631875ae7b2a70629f06946e7c4b59a41edd5110141f386442324bafe558140c26204f50309917063d3589a58057f453af")] 4 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick.AspNetCore/DaprHostedService.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | using Man.Dapr.Sidekick.Options; 4 | using Man.Dapr.Sidekick.Process; 5 | using Man.Dapr.Sidekick.Threading; 6 | using Microsoft.Extensions.Hosting; 7 | using Microsoft.Extensions.Options; 8 | 9 | namespace Man.Dapr.Sidekick.AspNetCore 10 | { 11 | public abstract class DaprHostedService : IHostedService 12 | where TProcessHost : IDaprProcessHost 13 | where TProcessOptions : DaprProcessOptions 14 | { 15 | private readonly TProcessHost _daprProcessHost; 16 | private readonly IOptionsMonitor _optionsAccessor; 17 | 18 | protected DaprHostedService( 19 | TProcessHost daprProcessHost, 20 | IOptionsMonitor optionsAccessor) 21 | { 22 | _daprProcessHost = daprProcessHost; 23 | _optionsAccessor = optionsAccessor; 24 | } 25 | 26 | public virtual Task StartAsync(CancellationToken cancellationToken) 27 | { 28 | _daprProcessHost.Start( 29 | () => 30 | { 31 | var options = _optionsAccessor.CurrentValue; 32 | OnStarting(options, cancellationToken); 33 | return options; 34 | }, 35 | new DaprCancellationToken(cancellationToken)); 36 | return Task.CompletedTask; 37 | } 38 | 39 | public Task StopAsync(CancellationToken cancellationToken) 40 | { 41 | return Task.Run(() => _daprProcessHost.Stop(new DaprCancellationToken(cancellationToken)), cancellationToken); 42 | } 43 | 44 | protected virtual void OnStarting(DaprOptions options, CancellationToken cancellationToken) 45 | { 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick.AspNetCore/DaprServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Hosting; 2 | 3 | namespace Microsoft.Extensions.DependencyInjection 4 | { 5 | public static class DaprServiceCollectionExtensions 6 | { 7 | public static IServiceCollection TryAddHostedService(this IServiceCollection services) 8 | where TImplementation : class, IHostedService 9 | { 10 | // Only add the service if an existing implementation does not exist 11 | if (!services.HasAssignableService()) 12 | { 13 | services.AddHostedService(); 14 | } 15 | 16 | return services; 17 | } 18 | 19 | public static bool HasAssignableService(this IServiceCollection services) 20 | { 21 | // Check to see if any existing service of type TImplementation (or a subclass) has been registered. 22 | foreach (var service in services) 23 | { 24 | if (service.ServiceType != typeof(TService)) 25 | { 26 | continue; 27 | } 28 | 29 | if (typeof(TImplementation).IsAssignableFrom(service.ImplementationType)) 30 | { 31 | // Already assigned 32 | return true; 33 | } 34 | } 35 | 36 | return false; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick.AspNetCore/Http/DaprHttpContextHttpClientFactory.cs: -------------------------------------------------------------------------------- 1 | using Man.Dapr.Sidekick.DaprClient; 2 | using Man.Dapr.Sidekick.Security; 3 | using Microsoft.AspNetCore.Http; 4 | 5 | namespace Man.Dapr.Sidekick.Http 6 | { 7 | internal class DaprHttpContextHttpClientFactory : DaprSidecarHttpClientFactory 8 | { 9 | private readonly IHttpContextAccessor _httpContextAccessor; 10 | 11 | public DaprHttpContextHttpClientFactory( 12 | IHttpContextAccessor httpContextAccessor, 13 | IDaprApiTokenAccessor daprApiTokenAccessor) 14 | : base(daprApiTokenAccessor) 15 | { 16 | _httpContextAccessor = httpContextAccessor; 17 | } 18 | 19 | protected override InvocationHandler CreateInvocationHandler() => new HttpContextInvocationHandler(_httpContextAccessor); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick.AspNetCore/Http/HttpHeaderConstants.cs: -------------------------------------------------------------------------------- 1 | namespace Man.Dapr.Sidekick.Http 2 | { 3 | /// 4 | /// Defines the constants used in Http request and response headers. 5 | /// 6 | public static class HttpHeaderConstants 7 | { 8 | /// 9 | /// Returns the Authorization header name. 10 | /// 11 | public const string Authorization = "Authorization"; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick.AspNetCore/IDaprSidekickBuilder.cs: -------------------------------------------------------------------------------- 1 | namespace Man.Dapr.Sidekick.AspNetCore 2 | { 3 | /// 4 | /// A builder used to register additional services for Dapr Sidekick. 5 | /// 6 | public interface IDaprSidekickBuilder 7 | { 8 | /// 9 | /// Adds the Dapr Placement service. 10 | /// 11 | /// This instance to allow calls to be chained. 12 | public IDaprSidekickBuilder AddPlacement(); 13 | 14 | /// 15 | /// Adds the Dapr Scheduler service. 16 | /// 17 | /// This instance to allow calls to be chained. 18 | public IDaprSidekickBuilder AddScheduler(); 19 | 20 | /// 21 | /// Adds the Dapr Sentry service. 22 | /// 23 | /// This instance to allow calls to be chained. 24 | public IDaprSidekickBuilder AddSentry(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick.AspNetCore/Man.Dapr.Sidekick.AspNetCore.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net462;netstandard2.0;net6.0;net8.0 5 | This package contains the reference assemblies for developing services using Dapr Sidekick and ASP.NET Core. 6 | Man.Dapr.Sidekick.AspNetCore 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick.AspNetCore/Metrics/DaprMetricsConstants.cs: -------------------------------------------------------------------------------- 1 | // This implementation is based on the approach used by prometheus-net. 2 | // See https://github.com/prometheus-net/prometheus-net/blob/master/Prometheus.NetStandard/PrometheusConstants.cs 3 | // See PROMETHEUS_LICENSE in this directory for license information. 4 | 5 | using System.Text; 6 | 7 | namespace Man.Dapr.Sidekick.AspNetCore.Metrics 8 | { 9 | public static class DaprMetricsConstants 10 | { 11 | public static readonly string AppLabelName = "app"; 12 | public static readonly string ServiceLabelName = "service"; 13 | 14 | public static readonly string DaprSidecarLabel = "dapr-sidecar"; 15 | public static readonly string DaprPlacementLabel = "dapr-placement"; 16 | public static readonly string DaprSchedulerLabel = "dapr-scheduler"; 17 | public static readonly string DaprSentryLabel = "dapr-sentry"; 18 | 19 | public static readonly string ExporterContentType = "text/plain; charset=utf-8"; 20 | 21 | // ASP.NET does not want to accept the parameters in PushStreamContent for whatever reason... 22 | public static readonly string ExporterContentTypeMinimal = "text/plain"; 23 | 24 | // Use UTF-8 encoding, but provide the flag to ensure the Unicode Byte Order Mark is never 25 | // pre-pended to the output stream. 26 | public static readonly Encoding ExportEncoding = new UTF8Encoding(false); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick.AspNetCore/Metrics/IDaprMetricsCollector.cs: -------------------------------------------------------------------------------- 1 | namespace Microsoft.Extensions.DependencyInjection 2 | { 3 | internal interface IDaprMetricsCollector 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick.AspNetCore/Metrics/IDaprMetricsCollectorRegistry.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | 4 | namespace Man.Dapr.Sidekick.AspNetCore.Metrics 5 | { 6 | public interface IDaprMetricsCollectorRegistry 7 | { 8 | /// 9 | /// Collects all metrics and exports them in text document format to the provided serializer. 10 | /// 11 | /// The serializer to which the metrics will be written. 12 | /// A token for cancelling the operation. 13 | /// A representing the asynchronous operation. 14 | Task CollectAndExportAsTextAsync(IDaprMetricsSerializer serializer, CancellationToken cancellationToken = default); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick.AspNetCore/Metrics/IDaprMetricsSerializer.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | 4 | namespace Man.Dapr.Sidekick.AspNetCore.Metrics 5 | { 6 | public interface IDaprMetricsSerializer 7 | { 8 | Task WriteLineAsync(string value, CancellationToken cancellationToken); 9 | 10 | Task FlushAsync(CancellationToken cancellationToken); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick.AspNetCore/Metrics/IPrometheusCollector.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | 4 | namespace Man.Dapr.Sidekick.AspNetCore.Metrics 5 | { 6 | public interface IPrometheusCollector 7 | { 8 | /// 9 | /// Populates the provided model with metrics text lines collected from the underlying source. 10 | /// 11 | /// The model into which the metrics will be stored. 12 | /// A token for cancelling the operation. 13 | /// A representing the asynchronous operation. 14 | Task CollectTextAsync(PrometheusModel model, CancellationToken cancellationToken = default); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick.AspNetCore/Metrics/IPrometheusMetricFilter.cs: -------------------------------------------------------------------------------- 1 | namespace Man.Dapr.Sidekick.AspNetCore.Metrics 2 | { 3 | public interface IPrometheusMetricFilter 4 | { 5 | /// 6 | /// Get a value that determines if the metric line should be excluded. 7 | /// 8 | /// The name of the metric. 9 | /// The full text of the metric line in Prometheus format. 10 | /// true if the metric line should be ignored, else false. 11 | bool ExcludeMetricLine(string name, string lineText); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick.AspNetCore/Metrics/PROMETHEUS_LICENSE: -------------------------------------------------------------------------------- 1 | This license applies to original files in this directory and its subdirectories originating from the following location/branch: 2 | https://github.com/prometheus-net/prometheus-net/blob/master/LICENSE 3 | 4 | The MIT License (MIT) 5 | 6 | Copyright (c) 2015 andrasm 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick.AspNetCore/Metrics/PrometheusModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Man.Dapr.Sidekick.AspNetCore.Metrics 4 | { 5 | public class PrometheusModel 6 | { 7 | public class Metric 8 | { 9 | public Metric(string name) 10 | { 11 | Name = name; 12 | MetricLines = new List(); 13 | } 14 | 15 | public string Name { get; } 16 | 17 | public string HelpLine { get; set; } 18 | 19 | public string TypeLine { get; set; } 20 | 21 | public List MetricLines { get; } 22 | 23 | public override string ToString() => Name; 24 | } 25 | 26 | public PrometheusModel() 27 | { 28 | Metrics = new Dictionary(); 29 | Unknown = new List(); 30 | } 31 | 32 | public Dictionary Metrics { get; } 33 | 34 | public List Unknown { get; } 35 | 36 | internal Metric GetOrAddMetric(string name) 37 | { 38 | if (Metrics.ContainsKey(name)) 39 | { 40 | return Metrics[name]; 41 | } 42 | else 43 | { 44 | var metric = new Metric(name); 45 | Metrics.Add(name, metric); 46 | return metric; 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick.AspNetCore/Placement/DaprPlacementHealthCheck.cs: -------------------------------------------------------------------------------- 1 | namespace Man.Dapr.Sidekick.AspNetCore.Placement 2 | { 3 | public class DaprPlacementHealthCheck : DaprProcessHealthCheck 4 | { 5 | public DaprPlacementHealthCheck( 6 | IDaprPlacementHost daprPlacementHost) 7 | : base(daprPlacementHost) 8 | { 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick.AspNetCore/Placement/DaprPlacementHealthCheckBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Man.Dapr.Sidekick.AspNetCore.Metrics; 3 | using Man.Dapr.Sidekick.AspNetCore.Placement; 4 | using Microsoft.Extensions.Diagnostics.HealthChecks; 5 | 6 | namespace Microsoft.Extensions.DependencyInjection 7 | { 8 | public static class DaprPlacementHealthCheckBuilderExtensions 9 | { 10 | /// 11 | /// Add a health check for the Dapr Placement. 12 | /// 13 | /// The . 14 | /// The health check name. Optional. If null the type name 'dapr_placement' will be used for the name. 15 | /// 16 | /// The that should be reported when the health check fails. Optional. If null then 17 | /// the default status of will be reported. 18 | /// 19 | /// A list of tags that can be used to filter sets of health checks. Optional. 20 | /// The to allow calls to be chained. 21 | public static IHealthChecksBuilder AddDaprPlacement( 22 | this IHealthChecksBuilder builder, 23 | string name = default, 24 | HealthStatus? failureStatus = default, 25 | IEnumerable tags = default) 26 | { 27 | builder.AddCheck(name ?? DaprMetricsConstants.DaprPlacementLabel, failureStatus, tags); 28 | return builder; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick.AspNetCore/Placement/DaprPlacementHostedService.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using Man.Dapr.Sidekick.AspNetCore.Metrics; 3 | using Microsoft.Extensions.Options; 4 | 5 | namespace Man.Dapr.Sidekick.AspNetCore.Placement 6 | { 7 | public class DaprPlacementHostedService : DaprHostedService 8 | { 9 | public DaprPlacementHostedService( 10 | IDaprPlacementHost daprPlacementHost, 11 | IOptionsMonitor optionsAccessor) 12 | : base(daprPlacementHost, optionsAccessor) 13 | { 14 | } 15 | 16 | protected override void OnStarting(DaprOptions options, CancellationToken cancellationToken) 17 | { 18 | // Assign metrics 19 | options.Placement ??= new DaprPlacementOptions(); 20 | options.Placement.Metrics ??= new DaprMetricsOptions(); 21 | options.Placement.Metrics.SetLabel(DaprMetricsConstants.ServiceLabelName, options.Sidecar?.AppId); 22 | options.Placement.Metrics.SetLabel(DaprMetricsConstants.AppLabelName, DaprMetricsConstants.DaprPlacementLabel); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick.AspNetCore/Placement/DaprPlacementMetricsCollector.cs: -------------------------------------------------------------------------------- 1 | using Man.Dapr.Sidekick.AspNetCore.Metrics; 2 | 3 | namespace Man.Dapr.Sidekick.AspNetCore.Placement 4 | { 5 | public class DaprPlacementMetricsCollector : DaprProcessHostPrometheusCollector 6 | { 7 | public DaprPlacementMetricsCollector(IDaprPlacementHost daprPlacementHost) 8 | : base(daprPlacementHost) 9 | { 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick.AspNetCore/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "Console": { 4 | "commandName": "Project", 5 | "launchBrowser": true, 6 | "environmentVariables": { 7 | "ASPNETCORE_ENVIRONMENT": "Development" 8 | }, 9 | "applicationUrl": "http://localhost:5000" 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick.AspNetCore/Scheduler/DaprSchedulerHealthCheck.cs: -------------------------------------------------------------------------------- 1 | namespace Man.Dapr.Sidekick.AspNetCore.Scheduler 2 | { 3 | public class DaprSchedulerHealthCheck : DaprProcessHealthCheck 4 | { 5 | public DaprSchedulerHealthCheck( 6 | IDaprSchedulerHost daprSchedulerHost) 7 | : base(daprSchedulerHost) 8 | { 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick.AspNetCore/Scheduler/DaprSchedulerHealthCheckBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Man.Dapr.Sidekick.AspNetCore.Metrics; 3 | using Man.Dapr.Sidekick.AspNetCore.Scheduler; 4 | using Microsoft.Extensions.Diagnostics.HealthChecks; 5 | 6 | namespace Microsoft.Extensions.DependencyInjection 7 | { 8 | public static class DaprSchedulerHealthCheckBuilderExtensions 9 | { 10 | /// 11 | /// Add a health check for the Dapr Scheduler. 12 | /// 13 | /// The . 14 | /// The health check name. Optional. If null the type name 'dapr_Scheduler' will be used for the name. 15 | /// 16 | /// The that should be reported when the health check fails. Optional. If null then 17 | /// the default status of will be reported. 18 | /// 19 | /// A list of tags that can be used to filter sets of health checks. Optional. 20 | /// The to allow calls to be chained. 21 | public static IHealthChecksBuilder AddDaprScheduler( 22 | this IHealthChecksBuilder builder, 23 | string name = default, 24 | HealthStatus? failureStatus = default, 25 | IEnumerable tags = default) 26 | { 27 | builder.AddCheck(name ?? DaprMetricsConstants.DaprSchedulerLabel, failureStatus, tags); 28 | return builder; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick.AspNetCore/Scheduler/DaprSchedulerHostedService.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using Man.Dapr.Sidekick.AspNetCore.Metrics; 3 | using Microsoft.Extensions.Options; 4 | 5 | namespace Man.Dapr.Sidekick.AspNetCore.Scheduler 6 | { 7 | public class DaprSchedulerHostedService : DaprHostedService 8 | { 9 | public DaprSchedulerHostedService( 10 | IDaprSchedulerHost daprSchedulerHost, 11 | IOptionsMonitor optionsAccessor) 12 | : base(daprSchedulerHost, optionsAccessor) 13 | { 14 | } 15 | 16 | protected override void OnStarting(DaprOptions options, CancellationToken cancellationToken) 17 | { 18 | // Assign metrics 19 | options.Scheduler ??= new DaprSchedulerOptions(); 20 | options.Scheduler.Metrics ??= new DaprMetricsOptions(); 21 | options.Scheduler.Metrics.SetLabel(DaprMetricsConstants.ServiceLabelName, options.Sidecar?.AppId); 22 | options.Scheduler.Metrics.SetLabel(DaprMetricsConstants.AppLabelName, DaprMetricsConstants.DaprSchedulerLabel); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick.AspNetCore/Scheduler/DaprSchedulerMetricsCollector.cs: -------------------------------------------------------------------------------- 1 | using Man.Dapr.Sidekick.AspNetCore.Metrics; 2 | 3 | namespace Man.Dapr.Sidekick.AspNetCore.Scheduler 4 | { 5 | public class DaprSchedulerMetricsCollector : DaprProcessHostPrometheusCollector 6 | { 7 | public DaprSchedulerMetricsCollector(IDaprSchedulerHost daprSchedulerHost) 8 | : base(daprSchedulerHost) 9 | { 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick.AspNetCore/Sentry/DaprSentryHealthCheck.cs: -------------------------------------------------------------------------------- 1 | namespace Man.Dapr.Sidekick.AspNetCore.Sentry 2 | { 3 | public class DaprSentryHealthCheck : DaprProcessHealthCheck 4 | { 5 | public DaprSentryHealthCheck( 6 | IDaprSentryHost daprSentryHost) 7 | : base(daprSentryHost) 8 | { 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick.AspNetCore/Sentry/DaprSentryHealthCheckBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Man.Dapr.Sidekick.AspNetCore.Metrics; 3 | using Man.Dapr.Sidekick.AspNetCore.Sentry; 4 | using Microsoft.Extensions.Diagnostics.HealthChecks; 5 | 6 | namespace Microsoft.Extensions.DependencyInjection 7 | { 8 | public static class DaprSentryHealthCheckBuilderExtensions 9 | { 10 | /// 11 | /// Add a health check for the Dapr Sentry. 12 | /// 13 | /// The . 14 | /// The health check name. Optional. If null the type name 'dapr_sentry' will be used for the name. 15 | /// 16 | /// The that should be reported when the health check fails. Optional. If null then 17 | /// the default status of will be reported. 18 | /// 19 | /// A list of tags that can be used to filter sets of health checks. Optional. 20 | /// The to allow calls to be chained. 21 | public static IHealthChecksBuilder AddDaprSentry( 22 | this IHealthChecksBuilder builder, 23 | string name = default, 24 | HealthStatus? failureStatus = default, 25 | IEnumerable tags = default) 26 | { 27 | builder.AddCheck(name ?? DaprMetricsConstants.DaprSentryLabel, failureStatus, tags); 28 | return builder; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick.AspNetCore/Sentry/DaprSentryHostedService.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using Man.Dapr.Sidekick.AspNetCore.Metrics; 3 | using Microsoft.Extensions.Options; 4 | 5 | namespace Man.Dapr.Sidekick.AspNetCore.Sentry 6 | { 7 | public class DaprSentryHostedService : DaprHostedService 8 | { 9 | public DaprSentryHostedService( 10 | IDaprSentryHost daprSentryHost, 11 | IOptionsMonitor optionsAccessor) 12 | : base(daprSentryHost, optionsAccessor) 13 | { 14 | } 15 | 16 | protected override void OnStarting(DaprOptions options, CancellationToken cancellationToken) 17 | { 18 | // Assign metrics 19 | options.Sentry ??= new DaprSentryOptions(); 20 | options.Sentry.Metrics ??= new DaprMetricsOptions(); 21 | options.Sentry.Metrics.SetLabel(DaprMetricsConstants.ServiceLabelName, options.Sidecar?.AppId); 22 | options.Sentry.Metrics.SetLabel(DaprMetricsConstants.AppLabelName, DaprMetricsConstants.DaprSentryLabel); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick.AspNetCore/Sentry/DaprSentryMetricsCollector.cs: -------------------------------------------------------------------------------- 1 | using Man.Dapr.Sidekick.AspNetCore.Metrics; 2 | 3 | namespace Man.Dapr.Sidekick.AspNetCore.Sentry 4 | { 5 | public class DaprSentryMetricsCollector : DaprProcessHostPrometheusCollector 6 | { 7 | public DaprSentryMetricsCollector(IDaprSentryHost daprSentryHost) 8 | : base(daprSentryHost) 9 | { 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick.AspNetCore/Sidecar/DaprSidecarHealthCheck.cs: -------------------------------------------------------------------------------- 1 | namespace Man.Dapr.Sidekick.AspNetCore.Sidecar 2 | { 3 | public class DaprSidecarHealthCheck : DaprProcessHealthCheck 4 | { 5 | public DaprSidecarHealthCheck( 6 | IDaprSidecarHost daprSidecarHost) 7 | : base(daprSidecarHost) 8 | { 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick.AspNetCore/Sidecar/DaprSidecarHealthCheckBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Man.Dapr.Sidekick.AspNetCore.Metrics; 3 | using Man.Dapr.Sidekick.AspNetCore.Sidecar; 4 | using Microsoft.Extensions.Diagnostics.HealthChecks; 5 | 6 | namespace Microsoft.Extensions.DependencyInjection 7 | { 8 | public static class DaprSidecarHealthCheckBuilderExtensions 9 | { 10 | /// 11 | /// Add a health check for the Dapr Sidecar. 12 | /// 13 | /// The . 14 | /// The health check name. Optional. If null the type name 'dapr_sidecar' will be used for the name. 15 | /// 16 | /// The that should be reported when the health check fails. Optional. If null then 17 | /// the default status of will be reported. 18 | /// 19 | /// A list of tags that can be used to filter sets of health checks. Optional. 20 | /// The to allow calls to be chained. 21 | public static IHealthChecksBuilder AddDaprSidecar( 22 | this IHealthChecksBuilder builder, 23 | string name = default, 24 | HealthStatus? failureStatus = default, 25 | IEnumerable tags = default) 26 | { 27 | builder.AddCheck(name ?? DaprMetricsConstants.DaprSidecarLabel, failureStatus, tags); 28 | return builder; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick.AspNetCore/Sidecar/DaprSidecarMetricFilter.cs: -------------------------------------------------------------------------------- 1 | using Man.Dapr.Sidekick.AspNetCore.Metrics; 2 | 3 | namespace Man.Dapr.Sidekick.AspNetCore.Sidecar 4 | { 5 | public class DaprSidecarMetricFilter : IPrometheusMetricFilter 6 | { 7 | public bool ExcludeMetricLine(string name, string lineText) 8 | { 9 | // Exclude calls rejected due to API tokens/security 10 | return lineText.Contains("status=\"401\""); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick.AspNetCore/Sidecar/DaprSidecarMetricsCollector.cs: -------------------------------------------------------------------------------- 1 | using Man.Dapr.Sidekick.AspNetCore.Metrics; 2 | 3 | namespace Man.Dapr.Sidekick.AspNetCore.Sidecar 4 | { 5 | public class DaprSidecarMetricsCollector : DaprProcessHostPrometheusCollector 6 | { 7 | public DaprSidecarMetricsCollector(IDaprSidecarHost daprSidecarHost) 8 | : base(daprSidecarHost) 9 | { 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick.Extensions.Logging/DaprLogger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Man.Dapr.Sidekick.Logging; 3 | using Microsoft.Extensions.Logging; 4 | 5 | namespace Man.Dapr.Sidekick.Extensions.Logging 6 | { 7 | /// 8 | /// A that delegates calls to an underling instance. 9 | /// 10 | public class DaprLogger : IDaprLogger 11 | { 12 | private readonly ILogger _logger; 13 | 14 | /// 15 | /// Initializes a new instance of the class using the underlying . 16 | /// 17 | /// The underlying instance to which logger calls will be delegated. 18 | public DaprLogger(ILogger logger) 19 | { 20 | _logger = logger ?? throw new ArgumentNullException(nameof(logger)); 21 | } 22 | 23 | public IDisposable BeginScope(TState state) => _logger.BeginScope(state); 24 | 25 | public bool IsEnabled(DaprLogLevel logLevel) => _logger.IsEnabled(ToLogLevel(logLevel)); 26 | 27 | public void Log(DaprLogLevel logLevel, DaprEventId eventId, TState state, Exception exception, Func formatter) => 28 | _logger.Log(ToLogLevel(logLevel), ToEventId(eventId), state, exception, formatter); 29 | 30 | private LogLevel ToLogLevel(DaprLogLevel logLevel) => (LogLevel)logLevel; 31 | 32 | private EventId ToEventId(DaprEventId eventId) => new EventId(eventId.Id, eventId.Name); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick.Extensions.Logging/DaprLoggerFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Man.Dapr.Sidekick.Logging; 3 | using Microsoft.Extensions.Logging; 4 | 5 | namespace Man.Dapr.Sidekick.Extensions.Logging 6 | { 7 | /// 8 | /// A that delegates logging calls to an underlying . 9 | /// 10 | public class DaprLoggerFactory : DaprLoggerFactoryBase 11 | { 12 | private readonly ILoggerFactory _loggerFactory; 13 | 14 | public DaprLoggerFactory(ILoggerFactory loggerFactory) 15 | { 16 | _loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory)); 17 | } 18 | 19 | protected override IDaprLogger CreateLoggerImpl(string categoryName) => new DaprLogger(_loggerFactory.CreateLogger(categoryName)); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick.Extensions.Logging/Man.Dapr.Sidekick.Extensions.Logging.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net45;net461;netstandard2.0;net6.0;net8.0 5 | This package contains the reference assemblies for routing Dapr Sidekick logging messages through the Microsoft Extensions Logging framework. 6 | Man.Dapr.Sidekick.Extensions.Logging 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly:InternalsVisibleTo("Man.Dapr.Sidekick.Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010085db710a00eb960715161fe42d9c848ccb264b514f6c09875e2ef4e375ecb1b829795fdd33a842db71bd0fb9261fee0fc9634bdaca0f7900ddb8505069202c72f5eaddc39596c39ab31f7c68656e47631875ae7b2a70629f06946e7c4b59a41edd5110141f386442324bafe558140c26204f50309917063d3589a58057f453af")] 4 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/DaprClient/DAPR_DOTNET_SDK_LICENSE: -------------------------------------------------------------------------------- 1 | This license applies to original files in this directory and its subdirectories originating from the following repository/branch: 2 | https://github.com/dapr/dotnet-sdk/blob/master/LICENSE 3 | 4 | Copyright (c) Microsoft Corporation. 5 | 6 | MIT License 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/DaprClient/DirectInvocationHandler.cs: -------------------------------------------------------------------------------- 1 | #if !NET35 2 | using System.Net.Http; 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | using Man.Dapr.Sidekick.Security; 6 | 7 | namespace Man.Dapr.Sidekick.DaprClient 8 | { 9 | internal class DirectInvocationHandler : DelegatingHandler 10 | { 11 | private readonly IDaprApiTokenAccessor _tokenAccessor; 12 | 13 | public DirectInvocationHandler(IDaprApiTokenAccessor tokenAccessor) 14 | { 15 | _tokenAccessor = tokenAccessor; 16 | } 17 | 18 | /// 19 | protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 20 | { 21 | var apiTokenHeader = DaprClient.GetDaprApiTokenHeader(_tokenAccessor.DaprApiToken); 22 | var isValidToken = apiTokenHeader.Key != null && apiTokenHeader.Value != null; 23 | 24 | try 25 | { 26 | if (isValidToken) 27 | { 28 | request.Headers.Add(apiTokenHeader.Key, apiTokenHeader.Value); 29 | } 30 | return await base.SendAsync(request, cancellationToken); 31 | } 32 | finally 33 | { 34 | if (isValidToken) 35 | { 36 | request.Headers.Remove(apiTokenHeader.Key); 37 | } 38 | } 39 | } 40 | } 41 | } 42 | #endif 43 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/DaprPlacementHost.cs: -------------------------------------------------------------------------------- 1 | using Man.Dapr.Sidekick.Http; 2 | using Man.Dapr.Sidekick.Logging; 3 | using Man.Dapr.Sidekick.Process; 4 | 5 | namespace Man.Dapr.Sidekick 6 | { 7 | public sealed class DaprPlacementHost : DaprProcessHost, IDaprPlacementHost 8 | { 9 | public DaprPlacementHost(IDaprProcessFactory daprProcessFactory, IDaprProcessHttpClientFactory daprHttpClientFactory, IDaprLoggerFactory loggerFactory) 10 | : base(() => daprProcessFactory.CreateDaprPlacementProcess(), daprHttpClientFactory, new DaprLogger(loggerFactory)) 11 | { 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/DaprSchedulerHost.cs: -------------------------------------------------------------------------------- 1 | using Man.Dapr.Sidekick.Http; 2 | using Man.Dapr.Sidekick.Logging; 3 | using Man.Dapr.Sidekick.Process; 4 | 5 | namespace Man.Dapr.Sidekick 6 | { 7 | public sealed class DaprSchedulerHost : DaprProcessHost, IDaprSchedulerHost 8 | { 9 | public DaprSchedulerHost(IDaprProcessFactory daprProcessFactory, IDaprProcessHttpClientFactory daprHttpClientFactory, IDaprLoggerFactory loggerFactory) 10 | : base(() => daprProcessFactory.CreateDaprSchedulerProcess(), daprHttpClientFactory, new DaprLogger(loggerFactory)) 11 | { 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/DaprSentryHost.cs: -------------------------------------------------------------------------------- 1 | using Man.Dapr.Sidekick.Http; 2 | using Man.Dapr.Sidekick.Logging; 3 | using Man.Dapr.Sidekick.Process; 4 | 5 | namespace Man.Dapr.Sidekick 6 | { 7 | public class DaprSentryHost : DaprProcessHost, IDaprSentryHost 8 | { 9 | public DaprSentryHost(IDaprProcessFactory daprProcessFactory, IDaprProcessHttpClientFactory daprHttpClientFactory, IDaprLoggerFactory loggerFactory) 10 | : base(() => daprProcessFactory.CreateDaprSentryProcess(), daprHttpClientFactory, new DaprLogger(loggerFactory)) 11 | { 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Http/DaprProcessHttpClientFactory.cs: -------------------------------------------------------------------------------- 1 | namespace Man.Dapr.Sidekick.Http 2 | { 3 | internal partial class DaprProcessHttpClientFactory : DaprDisposable, IDaprProcessHttpClientFactory 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Http/DaprProcessHttpClientFactory.net35.cs: -------------------------------------------------------------------------------- 1 | #if NET35 2 | using System.Net; 3 | 4 | namespace Man.Dapr.Sidekick.Http 5 | { 6 | internal partial class DaprProcessHttpClientFactory 7 | { 8 | public WebClient CreateDaprWebClient() 9 | { 10 | EnsureNotDisposed(); 11 | 12 | return new WebClient(); 13 | } 14 | } 15 | } 16 | #endif 17 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Http/DaprProcessHttpClientFactory.net45.cs: -------------------------------------------------------------------------------- 1 | #if !NET35 2 | using System.Net.Http; 3 | 4 | namespace Man.Dapr.Sidekick.Http 5 | { 6 | internal partial class DaprProcessHttpClientFactory 7 | { 8 | private HttpClient _httpClient; 9 | 10 | public DaprProcessHttpClientFactory() 11 | { 12 | _httpClient = new HttpClient(); 13 | } 14 | 15 | public DaprProcessHttpClientFactory(HttpClientHandler handler) 16 | { 17 | _httpClient = new HttpClient(handler); 18 | } 19 | 20 | public HttpClient CreateDaprHttpClient() 21 | { 22 | EnsureNotDisposed(); 23 | 24 | return _httpClient; 25 | } 26 | 27 | protected override void OnDisposing(bool disposing) 28 | { 29 | if (_httpClient != null) 30 | { 31 | _httpClient.Dispose(); 32 | _httpClient = null; 33 | } 34 | 35 | base.OnDisposing(disposing); 36 | } 37 | } 38 | } 39 | #endif 40 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Http/DaprSidecarHttpClientFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Man.Dapr.Sidekick.Http 4 | { 5 | public partial class DaprSidecarHttpClientFactory : DaprDisposable, IDaprProcessHttpClientFactory, IDaprSidecarHttpClientFactory 6 | { 7 | private const string DefaultDaprHttpPort = "3500"; 8 | 9 | internal static string GetDefaultDaprEndpoint() 10 | { 11 | var port = Environment.GetEnvironmentVariable(DaprConstants.DaprHttpPortEnvironmentVariable) ?? DefaultDaprHttpPort; 12 | 13 | // Since we're dealing with environment variables, treat empty the same as null. 14 | port = port?.Length == 0 ? DefaultDaprHttpPort : port; 15 | return $"http://{DaprConstants.LocalhostAddress}:{port}"; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Http/DaprSidecarHttpClientFactory.net35.cs: -------------------------------------------------------------------------------- 1 | #if NET35 2 | using System; 3 | using System.Net; 4 | using Man.Dapr.Sidekick.Security; 5 | 6 | namespace Man.Dapr.Sidekick.Http 7 | { 8 | public partial class DaprSidecarHttpClientFactory 9 | { 10 | private readonly IDaprApiTokenAccessor _tokenAccessor; 11 | 12 | public DaprSidecarHttpClientFactory(IDaprApiTokenAccessor tokenAccessor) 13 | { 14 | _tokenAccessor = tokenAccessor ?? throw new ArgumentNullException(nameof(tokenAccessor)); 15 | } 16 | 17 | public WebClient CreateDaprWebClient() 18 | { 19 | EnsureNotDisposed(); 20 | 21 | // Create a client 22 | var client = new WebClient 23 | { 24 | // The base address internally always has a final "/" 25 | // added to the end if it does not already exist. 26 | BaseAddress = GetDefaultDaprEndpoint() 27 | }; 28 | 29 | // Add the API token header 30 | var apiToken = _tokenAccessor.DaprApiToken; 31 | if (!string.IsNullOrEmpty(apiToken)) 32 | { 33 | client.Headers[DaprConstants.DaprApiTokenHeader] = apiToken; 34 | } 35 | 36 | return client; 37 | } 38 | 39 | public WebClient CreateInvokeWebClient(string appId) 40 | { 41 | EnsureNotDisposed(); 42 | 43 | if (appId.IsNullOrWhiteSpaceEx()) 44 | { 45 | throw new ArgumentNullException(nameof(appId)); 46 | } 47 | 48 | var client = CreateDaprWebClient(); 49 | client.BaseAddress += $"v1.0/invoke/{appId}/method"; 50 | return client; 51 | } 52 | } 53 | } 54 | #endif 55 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Http/IDaprProcessHttpClientFactory.cs: -------------------------------------------------------------------------------- 1 | namespace Man.Dapr.Sidekick.Http 2 | { 3 | /// 4 | /// Defines the methods for creating an HttpClient for direct access to the Dapr process endpoints. 5 | /// For internal use only. 6 | /// 7 | public interface IDaprProcessHttpClientFactory 8 | { 9 | #if NET35 10 | /// 11 | /// Creates a instance for invoking methods on the associated Dapr Process HTTP endpoints. 12 | /// 13 | /// A instance. 14 | System.Net.WebClient CreateDaprWebClient(); 15 | #else 16 | /// 17 | /// Creates a instance for invoking methods on the associated Dapr Process HTTP endpoints. 18 | /// 19 | /// A instance. 20 | System.Net.Http.HttpClient CreateDaprHttpClient(); 21 | #endif 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Http/UriHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Man.Dapr.Sidekick.Http 4 | { 5 | public static class UriHelper 6 | { 7 | public static Uri Parse(string uri) => 8 | string.IsNullOrEmpty(uri) ? null : 9 | Uri.TryCreate(AdjustUriHost(uri), UriKind.Absolute, out var result) ? result : 10 | null; 11 | 12 | private static string AdjustUriHost(string uri) 13 | { 14 | if (uri.Contains("*:")) 15 | { 16 | return uri.Replace("*:", $"{DaprConstants.LocalhostAddress}:"); 17 | } 18 | else if (uri.Contains("+:")) 19 | { 20 | return uri.Replace("+:", $"{DaprConstants.LocalhostAddress}:"); 21 | } 22 | else 23 | { 24 | return uri; 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/IDaprPlacementHost.cs: -------------------------------------------------------------------------------- 1 | using Man.Dapr.Sidekick.Process; 2 | 3 | namespace Man.Dapr.Sidekick 4 | { 5 | public interface IDaprPlacementHost : IDaprProcessHost 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/IDaprSchedulerHost.cs: -------------------------------------------------------------------------------- 1 | using Man.Dapr.Sidekick.Process; 2 | 3 | namespace Man.Dapr.Sidekick 4 | { 5 | public interface IDaprSchedulerHost : IDaprProcessHost 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/IDaprSentryHost.cs: -------------------------------------------------------------------------------- 1 | using Man.Dapr.Sidekick.Process; 2 | 3 | namespace Man.Dapr.Sidekick 4 | { 5 | public interface IDaprSentryHost : IDaprProcessHost 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/IDaprSidecarHost.cs: -------------------------------------------------------------------------------- 1 | using Man.Dapr.Sidekick.Process; 2 | 3 | namespace Man.Dapr.Sidekick 4 | { 5 | public partial interface IDaprSidecarHost : IDaprProcessHost 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/IDaprSidecarHost.net35.cs: -------------------------------------------------------------------------------- 1 | #if NET35 2 | using System.IO; 3 | 4 | namespace Man.Dapr.Sidekick 5 | { 6 | public partial interface IDaprSidecarHost 7 | { 8 | /// 9 | /// Retrieves metadata from the Dapr Sidecar and writes to the provided . 10 | /// 11 | /// A writeable stream to which the metadata will be written. 12 | /// The number of bytes written to the stream. 13 | int WriteMetadata(Stream stream); 14 | } 15 | } 16 | #endif 17 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/IDaprSidecarHost.net45.cs: -------------------------------------------------------------------------------- 1 | #if !NET35 2 | using System.IO; 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | 6 | namespace Man.Dapr.Sidekick 7 | { 8 | public partial interface IDaprSidecarHost 9 | { 10 | /// 11 | /// Retrieves metadata from the Dapr Sidecar and writes to the provided . 12 | /// 13 | /// A writeable stream to which the metadata will be written. 14 | /// A token for cancelling the operation. 15 | /// The number of bytes written to the stream. 16 | Task WriteMetadataAsync(Stream stream, CancellationToken cancellationToken); 17 | } 18 | } 19 | #endif 20 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Logging/DaprColoredConsoleLoggerFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Man.Dapr.Sidekick.Logging 4 | { 5 | /// 6 | /// An implementation of that logs all events to the system console using colors to differentiate log event levels. 7 | /// 8 | public class DaprColoredConsoleLoggerFactory : DaprLoggerFactoryBase 9 | { 10 | private readonly DaprColoredConsoleLoggerOptions _options; 11 | 12 | /// 13 | /// Initializes a new instance of the class. 14 | /// 15 | public DaprColoredConsoleLoggerFactory() 16 | : this(new DaprColoredConsoleLoggerOptions()) 17 | { 18 | } 19 | 20 | /// 21 | /// Initializes a new instance of the class 22 | /// with the specified . 23 | /// 24 | /// The console logger options. 25 | public DaprColoredConsoleLoggerFactory(DaprColoredConsoleLoggerOptions options) 26 | { 27 | _options = options ?? throw new ArgumentNullException(nameof(options)); 28 | } 29 | 30 | protected override IDaprLogger CreateLoggerImpl(string categoryName) => new Internal.DaprColoredConsoleLogger(categoryName, _options); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Logging/DaprEventId.cs: -------------------------------------------------------------------------------- 1 | // Based on https://github.com/dotnet/extensions/blob/release/2.1/src/Logging/Logging.Abstractions/src/DaprEventId.cs 2 | // Copyright (c) .NET Foundation. All rights reserved. 3 | // Licensed under the Apache License, Version 2.0. See NET_EXTENSIONS_LICENSE in this directory for license information. 4 | 5 | namespace Man.Dapr.Sidekick.Logging 6 | { 7 | public struct DaprEventId 8 | { 9 | public static implicit operator DaprEventId(int i) 10 | { 11 | return new DaprEventId(i); 12 | } 13 | 14 | public static bool operator ==(DaprEventId left, DaprEventId right) 15 | { 16 | return left.Equals(right); 17 | } 18 | 19 | public static bool operator !=(DaprEventId left, DaprEventId right) 20 | { 21 | return !left.Equals(right); 22 | } 23 | 24 | public DaprEventId(int id, string name = null) 25 | { 26 | Id = id; 27 | Name = name; 28 | } 29 | 30 | public int Id { get; } 31 | 32 | public string Name { get; } 33 | 34 | public override string ToString() 35 | { 36 | return Name ?? Id.ToString(); 37 | } 38 | 39 | public bool Equals(DaprEventId other) 40 | { 41 | return Id == other.Id; 42 | } 43 | 44 | public override bool Equals(object obj) 45 | { 46 | if (obj is null) 47 | { 48 | return false; 49 | } 50 | 51 | return obj is DaprEventId daprEventId && Equals(daprEventId); 52 | } 53 | 54 | public override int GetHashCode() 55 | { 56 | return Id; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Logging/DaprLoggerFactoryBase.cs: -------------------------------------------------------------------------------- 1 | // Based on https://github.com/dotnet/extensions/blob/release/2.1/src/Logging/Logging/src/LoggerFactory.cs 2 | // Copyright (c) .NET Foundation. All rights reserved. 3 | // Licensed under the Apache License, Version 2.0. See NET_EXTENSIONS_LICENSE in this directory for license information. 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | 8 | namespace Man.Dapr.Sidekick.Logging 9 | { 10 | /// 11 | /// Base class for implementations. 12 | /// 13 | public abstract class DaprLoggerFactoryBase : DaprDisposable, IDaprLoggerFactory 14 | { 15 | private readonly Dictionary _loggers = new Dictionary(StringComparer.Ordinal); 16 | private readonly object _sync = new object(); 17 | 18 | public IDaprLogger CreateLogger(string categoryName) 19 | { 20 | EnsureNotDisposed(); 21 | 22 | // Cannot use ConcurrentDictionary as need to support net35. 23 | // Standard check-lock-check approach 24 | if (!_loggers.TryGetValue(categoryName, out var logger)) 25 | { 26 | lock (_sync) 27 | { 28 | if (!_loggers.TryGetValue(categoryName, out logger)) 29 | { 30 | logger = CreateLoggerImpl(categoryName); 31 | _loggers[categoryName] = logger; 32 | } 33 | } 34 | } 35 | 36 | return logger; 37 | } 38 | 39 | protected abstract IDaprLogger CreateLoggerImpl(string categoryName); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Logging/DaprLoggerOfT.cs: -------------------------------------------------------------------------------- 1 | #pragma warning disable SA1649 // File name should match first type name 2 | // Based on https://github.com/dotnet/extensions/blob/release/2.1/src/Logging/Logging.Abstractions/src/LoggerOfT.cs 3 | // Copyright (c) .NET Foundation. All rights reserved. 4 | // Licensed under the Apache License, Version 2.0. See NET_EXTENSIONS_LICENSE in this directory for license information. 5 | 6 | using System; 7 | 8 | namespace Man.Dapr.Sidekick.Logging 9 | { 10 | public sealed class DaprLogger : IDaprLogger 11 | { 12 | private readonly IDaprLogger _logger; 13 | 14 | /// 15 | /// Initializes a new instance of the class. 16 | /// 17 | /// The factory. 18 | public DaprLogger(IDaprLoggerFactory factory) 19 | { 20 | if (factory == null) 21 | { 22 | throw new ArgumentNullException(nameof(factory)); 23 | } 24 | 25 | _logger = factory.CreateLogger(Internal.TypeNameHelper.GetTypeDisplayName(typeof(T))); 26 | } 27 | 28 | IDisposable IDaprLogger.BeginScope(TState state) 29 | { 30 | return _logger.BeginScope(state); 31 | } 32 | 33 | bool IDaprLogger.IsEnabled(DaprLogLevel logLevel) 34 | { 35 | return _logger.IsEnabled(logLevel); 36 | } 37 | 38 | void IDaprLogger.Log(DaprLogLevel logLevel, DaprEventId eventId, TState state, Exception exception, Func formatter) 39 | { 40 | _logger.Log(logLevel, eventId, state, exception, formatter); 41 | } 42 | } 43 | } 44 | #pragma warning restore SA1649 // File name should match first type name 45 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Logging/IDaprLoggerFactory.cs: -------------------------------------------------------------------------------- 1 | // Based on https://github.com/dotnet/extensions/blob/release/2.1/src/Logging/Logging.Abstractions/src/ILoggerFactory.cs 2 | // Copyright (c) .NET Foundation. All rights reserved. 3 | // Licensed under the Apache License, Version 2.0. See NET_EXTENSIONS_LICENSE in this directory for license information. 4 | 5 | namespace Man.Dapr.Sidekick.Logging 6 | { 7 | /// 8 | /// Represents a type used to configure the logging system and create instances of . 9 | /// 10 | public interface IDaprLoggerFactory 11 | { 12 | /// 13 | /// Creates a new instance. 14 | /// 15 | /// The category name for messages produced by the logger. 16 | /// The . 17 | IDaprLogger CreateLogger(string categoryName); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Logging/Internal/ISystemConsole.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Man.Dapr.Sidekick.Logging.Internal 4 | { 5 | public interface ISystemConsole 6 | { 7 | ConsoleColor ForegroundColor { get; set; } 8 | 9 | void WriteLine(string value); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Logging/Internal/SystemConsole.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Man.Dapr.Sidekick.Logging.Internal 4 | { 5 | internal class SystemConsole : ISystemConsole 6 | { 7 | public ConsoleColor ForegroundColor { get => Console.ForegroundColor; set => Console.ForegroundColor = value; } 8 | 9 | public void WriteLine(string value) => Console.WriteLine(value); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Man.Dapr.Sidekick.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net35;net45;net461;netstandard2.0;net6.0;net8.0 5 | true 6 | This package contains the reference assemblies for developing services using Dapr Sidekick. 7 | Man.Dapr.Sidekick 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Options/DaprManagedProcessOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Specialized; 3 | using Man.Dapr.Sidekick.Logging; 4 | using Man.Dapr.Sidekick.Threading; 5 | 6 | namespace Man.Dapr.Sidekick.Options 7 | { 8 | public class DaprManagedProcessOptions 9 | { 10 | /// 11 | /// Gets or sets the full path to the system process. 12 | /// 13 | public string Filename { get; set; } 14 | 15 | /// 16 | /// Gets or sets a working directory to be used by the managed process. 17 | /// This is required by some components that use relevant directory paths to load local files from the project folders. 18 | /// Defaults to %USERPROFILE%/.dapr ($HOME/.dapr on Linux) if not specified. 19 | /// 20 | public string WorkingDirectory { get; set; } 21 | 22 | /// 23 | /// Gets or sets optional command-line process arguments. 24 | /// 25 | public string Arguments { get; set; } 26 | 27 | /// 28 | /// Gets or sets an optional instance for receiving stdout log messages from the process. 29 | /// 30 | public IDaprLogger Logger { get; set; } 31 | 32 | /// 33 | /// Gets or sets a for aborting the process startup operation. 34 | /// 35 | public DaprCancellationToken CancellationToken { get; set; } = default; 36 | 37 | /// 38 | /// Gets or sets an optional action for configuring any environment variables for the process. 39 | /// 40 | public Action ConfigureEnvironmentVariables { get; set; } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Options/DaprOptions.cs: -------------------------------------------------------------------------------- 1 | namespace Man.Dapr.Sidekick 2 | { 3 | public class DaprOptions : Options.DaprProcessOptions 4 | { 5 | public const string SectionName = "DaprSidekick"; 6 | public const string EnvironmentVariablePrefix = "DAPRSIDEKICK_"; 7 | 8 | public DaprOptions() 9 | { 10 | // Set defaults for all components 11 | LogLevel = Process.DaprProcessLogger.DebugLevel; 12 | } 13 | 14 | public DaprSidecarOptions Sidecar { get; set; } = new(); 15 | 16 | public DaprPlacementOptions Placement { get; set; } = new(); 17 | 18 | public DaprSchedulerOptions Scheduler { get; set; } = new(); 19 | 20 | public DaprSentryOptions Sentry { get; set; } = new(); 21 | 22 | /// 23 | /// Creates a deep clone of this instance. 24 | /// 25 | /// A deep clone of this insteance. 26 | public new DaprOptions Clone() 27 | { 28 | var clone = (DaprOptions)base.Clone(); 29 | clone.Sidecar = Sidecar?.Clone(); 30 | clone.Placement = Placement?.Clone(); 31 | clone.Scheduler = Scheduler?.Clone(); 32 | clone.Sentry = Sentry?.Clone(); 33 | return clone; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Process/AttachedProcess.cs: -------------------------------------------------------------------------------- 1 | using Man.Dapr.Sidekick.Threading; 2 | 3 | namespace Man.Dapr.Sidekick.Process 4 | { 5 | internal class AttachedProcess : IProcess 6 | { 7 | private IProcess _systemProcess; 8 | 9 | public AttachedProcess(IProcess systemProcess) 10 | { 11 | _systemProcess = systemProcess; 12 | } 13 | 14 | public int? Id => _systemProcess?.Id; 15 | 16 | public string Name => _systemProcess?.Name; 17 | 18 | public bool IsRunning => _systemProcess?.IsRunning ?? false; 19 | 20 | public IProcessCommandLine GetCommandLine() => _systemProcess?.GetCommandLine(); 21 | 22 | public void Stop(int? waitForShutdownSeconds = null, DaprCancellationToken cancellationToken = default) 23 | { 24 | // Just detach 25 | _systemProcess = null; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Process/DaprHealthResult.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | 3 | namespace Man.Dapr.Sidekick.Process 4 | { 5 | /// 6 | /// The result of a Health Check executed against a Dapr process. 7 | /// 8 | public class DaprHealthResult 9 | { 10 | /// 11 | /// Gets a health result with an unknown status. 12 | /// 13 | public static DaprHealthResult Unknown => new DaprHealthResult(HttpStatusCode.ServiceUnavailable, "Unknown or unreachable"); 14 | 15 | public DaprHealthResult(HttpStatusCode statusCode, string statusDescription = null) 16 | { 17 | StatusCode = statusCode; 18 | StatusDescription = statusDescription; 19 | } 20 | 21 | /// 22 | /// Gets a value indicating whether the Dapr process is reachable and healthy. 23 | /// 24 | public bool IsHealthy => (int)StatusCode >= 200 && (int)StatusCode < 400; 25 | 26 | public HttpStatusCode StatusCode { get; } 27 | 28 | public string StatusDescription { get; } 29 | 30 | public override string ToString() => 31 | IsHealthy ? "Healthy" : 32 | string.IsNullOrEmpty(StatusDescription) ? string.Concat("Unhealthy (", StatusCode, ")") : 33 | string.Concat("Unhealthy (", StatusCode, ", ", StatusDescription, ")"); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Process/DaprProcessEvents.cs: -------------------------------------------------------------------------------- 1 | #pragma warning disable SA1649 // File name should match first type name 2 | using System; 3 | using Man.Dapr.Sidekick.Threading; 4 | 5 | namespace Man.Dapr.Sidekick.Process 6 | { 7 | public class DaprProcessStartingEventArgs : EventArgs 8 | { 9 | public DaprProcessStartingEventArgs(TOptions options) 10 | { 11 | Options = options; 12 | } 13 | 14 | public TOptions Options { get; } 15 | } 16 | 17 | public class DaprProcessStoppingEventArgs : EventArgs 18 | { 19 | public DaprProcessStoppingEventArgs(DaprCancellationToken cancellationToken) 20 | { 21 | CancellationToken = cancellationToken; 22 | } 23 | 24 | public DaprCancellationToken CancellationToken { get; } 25 | } 26 | } 27 | #pragma warning restore SA1649 // File name should match first type name 28 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Process/DaprProcessFactory.cs: -------------------------------------------------------------------------------- 1 | namespace Man.Dapr.Sidekick.Process 2 | { 3 | public class DaprProcessFactory : IDaprProcessFactory 4 | { 5 | public IDaprSidecarProcess CreateDaprSidecarProcess() => new DaprSidecarProcess(); 6 | 7 | public IDaprPlacementProcess CreateDaprPlacementProcess() => new DaprPlacementProcess(); 8 | 9 | public IDaprSchedulerProcess CreateDaprSchedulerProcess() => new DaprSchedulerProcess(); 10 | 11 | public IDaprSentryProcess CreateDaprSentryProcess() => new DaprSentryProcess(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Process/DaprProcessInfo.cs: -------------------------------------------------------------------------------- 1 | namespace Man.Dapr.Sidekick.Process 2 | { 3 | public class DaprProcessInfo 4 | { 5 | public static DaprProcessInfo Unknown => new DaprProcessInfo("unknown", null, null, DaprProcessStatus.Stopped, false); 6 | 7 | public DaprProcessInfo(string name, int? id, string version, DaprProcessStatus status) 8 | : this(name, id, version, status, false) 9 | { 10 | } 11 | 12 | public DaprProcessInfo(string name, int? id, string version, DaprProcessStatus status, bool isAttached) 13 | { 14 | Name = name; 15 | Id = id; 16 | Version = version; 17 | Status = status; 18 | IsAttached = isAttached; 19 | } 20 | 21 | public string Name { get; } 22 | 23 | public int? Id { get; } 24 | 25 | public string Version { get; } 26 | 27 | public DaprProcessStatus Status { get; } 28 | 29 | public bool IsRunning => Status == DaprProcessStatus.Started; 30 | 31 | public bool IsAttached { get; } 32 | 33 | public string Description => 34 | IsRunning ? (!string.IsNullOrEmpty(Version) ? $"Dapr process '{Name}' running, version {Version}" : $"Dapr process '{Name}' running, unverified version") : 35 | IsAttached ? (!string.IsNullOrEmpty(Version) ? $"Dapr process '{Name}' attached, version {Version}" : $"Dapr process '{Name}' attached, unverified version") : 36 | $"Dapr process '{Name}' not available, status is {Status}"; 37 | 38 | public override string ToString() => Description; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Process/DaprProcessLogRecord.cs: -------------------------------------------------------------------------------- 1 | namespace Man.Dapr.Sidekick.Process 2 | { 3 | internal class DaprProcessLogRecord 4 | { 5 | public string Msg { get; set; } 6 | 7 | public string Level { get; set; } 8 | 9 | public string Ver { get; set; } 10 | 11 | public string App_id { get; set; } 12 | 13 | public string Instance { get; set; } 14 | 15 | public string Scope { get; set; } 16 | 17 | public string Time { get; set; } 18 | 19 | public string Type { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Process/Enumerations.cs: -------------------------------------------------------------------------------- 1 | namespace Man.Dapr.Sidekick.Process 2 | { 3 | public enum DaprProcessStatus 4 | { 5 | Stopped = 0, 6 | Initializing = 1, 7 | Starting = 2, 8 | Started = 3, 9 | Stopping = 4, 10 | Disabled = 5 11 | } 12 | 13 | internal enum ProcessComparison 14 | { 15 | None = 0, 16 | Duplicate = 1, 17 | Attachable = 2 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Process/EnvironmentVariableBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Man.Dapr.Sidekick.Process 5 | { 6 | public class EnvironmentVariableBuilder 7 | { 8 | private readonly Dictionary _values = new Dictionary(); 9 | 10 | public EnvironmentVariableBuilder Add(string name, object value, Func predicate = null) 11 | { 12 | // Precondition checks 13 | if (name.IsNullOrWhiteSpaceEx() || value == null || predicate?.Invoke() == false) 14 | { 15 | return this; 16 | } 17 | 18 | // Add or replace 19 | _values[name] = value; 20 | 21 | return this; 22 | } 23 | 24 | public IDictionary ToDictionary() => new Dictionary(_values); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Process/IDaprPlacementProcess.cs: -------------------------------------------------------------------------------- 1 | namespace Man.Dapr.Sidekick.Process 2 | { 3 | public interface IDaprPlacementProcess : IDaprProcess 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Process/IDaprProcess.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Man.Dapr.Sidekick.Logging; 3 | using Man.Dapr.Sidekick.Threading; 4 | 5 | namespace Man.Dapr.Sidekick.Process 6 | { 7 | public interface IDaprProcess 8 | where TOptions : Options.DaprProcessOptions 9 | { 10 | /// 11 | /// Gets the options that were actually used to successfully start the process the last time it was launched. 12 | /// This will include all calculated file paths and auto-assigned ports. 13 | /// 14 | TOptions LastSuccessfulOptions { get; } 15 | 16 | DaprProcessInfo GetProcessInfo(); 17 | 18 | bool Start(Func optionsAccessor, IDaprLogger logger, DaprCancellationToken cancellationToken = default); 19 | 20 | void Stop(DaprCancellationToken cancellationToken = default); 21 | 22 | event EventHandler> Starting; 23 | 24 | event EventHandler Stopping; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Process/IDaprProcessFactory.cs: -------------------------------------------------------------------------------- 1 | namespace Man.Dapr.Sidekick.Process 2 | { 3 | public interface IDaprProcessFactory 4 | { 5 | IDaprSidecarProcess CreateDaprSidecarProcess(); 6 | 7 | IDaprPlacementProcess CreateDaprPlacementProcess(); 8 | 9 | IDaprSchedulerProcess CreateDaprSchedulerProcess(); 10 | 11 | IDaprSentryProcess CreateDaprSentryProcess(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Process/IDaprProcessHost.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Man.Dapr.Sidekick.Threading; 3 | 4 | namespace Man.Dapr.Sidekick.Process 5 | { 6 | public interface IDaprProcessHost : IDaprProcessHost 7 | where TOptions : Options.DaprProcessOptions 8 | { 9 | /// 10 | /// Gets the process options used to configure and start up the current running process. 11 | /// 12 | /// A instance, or null if the process is not currently running. 13 | new TOptions GetProcessOptions(); 14 | } 15 | 16 | public partial interface IDaprProcessHost 17 | { 18 | /// 19 | /// Gets the process options used to configure and start up the current running process. 20 | /// 21 | /// A instance, or null if the process is not currently running. 22 | Options.DaprProcessOptions GetProcessOptions(); 23 | 24 | /// 25 | /// Gets information about the currently running process. 26 | /// Returns if the process is not currently running. 27 | /// 28 | /// A instance. 29 | DaprProcessInfo GetProcessInfo(); 30 | 31 | bool Start(Func optionsAccessor, DaprCancellationToken cancellationToken); 32 | 33 | void Stop(DaprCancellationToken cancellationToken); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Process/IDaprProcessHost.ne35.cs: -------------------------------------------------------------------------------- 1 | #if NET35 2 | using System.IO; 3 | 4 | namespace Man.Dapr.Sidekick.Process 5 | { 6 | public partial interface IDaprProcessHost 7 | { 8 | /// 9 | /// Gets the current health of the Dapr Process. 10 | /// 11 | /// A . 12 | DaprHealthResult GetHealth(); 13 | 14 | /// 15 | /// Retrieves metrics from the Dapr Process and writes to the provided . 16 | /// 17 | /// A writeable stream to which the metrics will be written. 18 | /// The number of bytes written to the stream. 19 | int WriteMetrics(Stream stream); 20 | } 21 | } 22 | #endif 23 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Process/IDaprProcessHost.net45.cs: -------------------------------------------------------------------------------- 1 | #if !NET35 2 | using System.IO; 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | 6 | namespace Man.Dapr.Sidekick.Process 7 | { 8 | public partial interface IDaprProcessHost 9 | { 10 | /// 11 | /// Checks the current health of the Dapr Process. Returns true if healthy, else returns false. 12 | /// 13 | /// A token for cancelling the operation. 14 | /// A that will return the value when the operation has completed. 15 | Task CheckHealthAsync(CancellationToken cancellationToken = default); 16 | 17 | /// 18 | /// Gets the current health of the Dapr Process. 19 | /// 20 | /// A token for cancelling the operation. 21 | /// A . 22 | Task GetHealthAsync(CancellationToken cancellationToken); 23 | 24 | /// 25 | /// Retrieves metrics from the Dapr Process and writes to the provided . 26 | /// 27 | /// A writeable stream to which the metrics will be written. 28 | /// A token for cancelling the operation. 29 | /// The number of bytes written to the stream. 30 | Task WriteMetricsAsync(Stream stream, CancellationToken cancellationToken); 31 | } 32 | } 33 | #endif 34 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Process/IDaprProcessUpdater.cs: -------------------------------------------------------------------------------- 1 | namespace Man.Dapr.Sidekick.Process 2 | { 3 | public interface IDaprProcessUpdater 4 | { 5 | void UpdateStatus(DaprProcessStatus status); 6 | 7 | void UpdateVersion(string version); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Process/IDaprSchedulerProcess.cs: -------------------------------------------------------------------------------- 1 | namespace Man.Dapr.Sidekick.Process 2 | { 3 | public interface IDaprSchedulerProcess : IDaprProcess 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Process/IDaprSentryProcess.cs: -------------------------------------------------------------------------------- 1 | namespace Man.Dapr.Sidekick.Process 2 | { 3 | public interface IDaprSentryProcess : IDaprProcess 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Process/IDaprSidecarProcess.cs: -------------------------------------------------------------------------------- 1 | namespace Man.Dapr.Sidekick.Process 2 | { 3 | public interface IDaprSidecarProcess : IDaprProcess 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Process/IDaprSidecarProcessInterceptor.cs: -------------------------------------------------------------------------------- 1 | namespace Man.Dapr.Sidekick.Process 2 | { 3 | public interface IDaprSidecarProcessInterceptor 4 | { 5 | void OnStarting(DaprSidecarOptions options); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Process/IPortAvailabilityChecker.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Man.Dapr.Sidekick.Process 4 | { 5 | /// 6 | /// Checks operating system port availability.. 7 | /// 8 | public interface IPortAvailabilityChecker 9 | { 10 | /// 11 | /// Gets the next available port starting from 12 | /// excluding any defined in . 13 | /// 14 | /// The preferred starting port. If available this value will be returned, else it will be the next available incremental value above it. 15 | /// An optional list of reserved ports. If defined the returned value will not be one of the ports in this list. 16 | /// The next available port. 17 | int GetAvailablePort(int startingPort, IEnumerable reservedPorts = null); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Process/IProcess.cs: -------------------------------------------------------------------------------- 1 | using Man.Dapr.Sidekick.Threading; 2 | 3 | namespace Man.Dapr.Sidekick.Process 4 | { 5 | /// 6 | /// Represents a system process. 7 | /// 8 | public interface IProcess 9 | { 10 | /// 11 | /// Gets the unique process identifier (PID). 12 | /// 13 | int? Id { get; } 14 | 15 | /// 16 | /// Gets the process name. 17 | /// 18 | string Name { get; } 19 | 20 | /// 21 | /// Gets a value indicating whether the process is running or not. 22 | /// 23 | bool IsRunning { get; } 24 | 25 | /// 26 | /// Stops the running process. 27 | /// 28 | /// An optional number of seconds to wait for graceful shutdown. If null the process will be terminated immediately. 29 | /// An optional cancellation token. When set this will terminate the process immediately if has not yet elapsed. 30 | void Stop(int? waitForShutdownSeconds, DaprCancellationToken cancellationToken = default); 31 | 32 | /// 33 | /// Gets the command-line arguments that were passed to the process during initialization. 34 | /// 35 | /// A instance. 36 | IProcessCommandLine GetCommandLine(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Process/IProcessCommandLine.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Man.Dapr.Sidekick.Process 4 | { 5 | /// 6 | /// Represents the command line used to start a process. 7 | /// 8 | public interface IProcessCommandLine 9 | { 10 | /// 11 | /// Gets the process that was started with this command line. 12 | /// 13 | IProcess Process { get; } 14 | 15 | /// 16 | /// Gets the full command-line text. 17 | /// 18 | string CommandLine { get; } 19 | 20 | /// 21 | /// Gets all command-line arguments as a dictionary of name-value pairs separated by the specified . 22 | /// 23 | /// The argument separator or prefix. 24 | /// A dictionary of command-line arguments. 25 | IDictionary GetArgumentsAsDictionary(char separator); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Process/IProcessFinder.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Man.Dapr.Sidekick.Process 4 | { 5 | public interface IProcessFinder 6 | { 7 | IEnumerable FindExistingProcesses(string processName); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Process/ISystemProcessController.cs: -------------------------------------------------------------------------------- 1 | namespace Man.Dapr.Sidekick.Process 2 | { 3 | public interface ISystemProcessController 4 | { 5 | /// 6 | /// Immediately stops the system process. 7 | /// 8 | void Kill(); 9 | 10 | /// 11 | /// Starts the system process. 12 | /// 13 | /// true if the associated process was started; otherwise, false. 14 | bool Start(); 15 | 16 | /// 17 | /// Instructs the System Process to wait indefinitely for the associated process to exit. 18 | /// 19 | void WaitForExit(); 20 | 21 | /// 22 | /// Instructs the System Process to wait the specified number of milliseconds for the associated process to exit. 23 | /// 24 | /// The amount of time, in milliseconds, to wait for the associated process to exit. 25 | /// true if the associated process has exited; otherwise, false. 26 | bool WaitForExit(int milliseconds); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Process/ProcessFinder.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace Man.Dapr.Sidekick.Process 5 | { 6 | internal class ProcessFinder : IProcessFinder 7 | { 8 | public IEnumerable FindExistingProcesses(string processName) => 9 | System.Diagnostics.Process.GetProcessesByName(processName).Select(x => (IProcess)new SystemProcess(x)); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Process/SystemProcessController.cs: -------------------------------------------------------------------------------- 1 | namespace Man.Dapr.Sidekick.Process 2 | { 3 | internal class SystemProcessController : ISystemProcessController 4 | { 5 | private readonly System.Diagnostics.Process _process; 6 | 7 | public SystemProcessController(System.Diagnostics.Process process) 8 | { 9 | _process = process; 10 | } 11 | 12 | public void Kill() => _process.Kill(); 13 | 14 | public bool Start() => _process.Start(); 15 | 16 | public void WaitForExit() => _process.WaitForExit(); 17 | 18 | public bool WaitForExit(int milliseconds) => _process.WaitForExit(milliseconds); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Security/DaprApiTokenManager.cs: -------------------------------------------------------------------------------- 1 | namespace Man.Dapr.Sidekick.Security 2 | { 3 | public class DaprApiTokenManager : IDaprApiTokenManager 4 | { 5 | private readonly IDaprApiTokenProvider _tokenProvider; 6 | private SensitiveString _daprApiToken; 7 | private SensitiveString _appApiToken; 8 | 9 | public DaprApiTokenManager(IDaprApiTokenProvider tokenProvider) 10 | { 11 | _tokenProvider = tokenProvider; 12 | 13 | // Set the default values 14 | SetDaprApiToken(tokenProvider.GetDaprApiToken()); 15 | SetAppApiToken(tokenProvider.GetAppApiToken()); 16 | } 17 | 18 | public SensitiveString DaprApiToken => _daprApiToken; 19 | 20 | public SensitiveString AppApiToken => _appApiToken; 21 | 22 | public void SetDaprApiToken(SensitiveString apiToken) => _daprApiToken = apiToken; 23 | 24 | public void SetAppApiToken(SensitiveString apiToken) => _appApiToken = apiToken; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Security/IDaprApiTokenAccessor.cs: -------------------------------------------------------------------------------- 1 | namespace Man.Dapr.Sidekick.Security 2 | { 3 | public interface IDaprApiTokenAccessor 4 | { 5 | /// 6 | /// Gets the API Token that Dapr will expect to see in the header of each public API request to authenticate the caller. 7 | /// The Dapr process will be launched with the environment variable DAPR_API_TOKEN set to this value. 8 | /// See https://docs.dapr.io/operations/security/api-token/. 9 | /// 10 | public SensitiveString DaprApiToken { get; } 11 | 12 | /// 13 | /// Gets the API Token that Dapr will provide as a header in each request sent to an application from the sidecar. 14 | /// The Dapr process will be launched with the environment variable APP_API_TOKEN set to this value. 15 | /// See https://docs.dapr.io/operations/security/app-api-token/. 16 | /// 17 | public SensitiveString AppApiToken { get; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Security/IDaprApiTokenManager.cs: -------------------------------------------------------------------------------- 1 | namespace Man.Dapr.Sidekick.Security 2 | { 3 | public interface IDaprApiTokenManager : IDaprApiTokenAccessor 4 | { 5 | /// 6 | /// Sets the API Token that Dapr will expect to see in the header of each public API request to authenticate the caller. 7 | /// The Dapr process will be launched with the environment variable DAPR_API_TOKEN set to this value. 8 | /// See https://docs.dapr.io/operations/security/api-token/. 9 | /// 10 | /// An API Token. 11 | public void SetDaprApiToken(SensitiveString apiToken); 12 | 13 | /// 14 | /// Sets the API Token that Dapr will provide as a header in each request sent to an application from the sidecar. 15 | /// The Dapr process will be launched with the environment variable APP_API_TOKEN set to this value. 16 | /// See https://docs.dapr.io/operations/security/app-api-token/. 17 | /// 18 | /// An API Token. 19 | public void SetAppApiToken(SensitiveString apiToken); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Security/IDaprApiTokenProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Man.Dapr.Sidekick.Security 2 | { 3 | public interface IDaprApiTokenProvider 4 | { 5 | string GetDaprApiToken(); 6 | 7 | string GetAppApiToken(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Security/ISensitiveValue.cs: -------------------------------------------------------------------------------- 1 | namespace Man.Dapr.Sidekick.Security 2 | { 3 | public interface ISensitiveValue 4 | { 5 | object Value { get; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Security/ObjectExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Man.Dapr.Sidekick.Security 2 | { 3 | public static class ObjectExtensions 4 | { 5 | /// 6 | /// Gets the sensitive value for an object if it implements , else the original value. 7 | /// 8 | /// The object value. 9 | /// The sensitive value, or the original value if not sensitive. 10 | public static object SensitiveValue(this object value) => value is ISensitiveValue sensitiveValue ? sensitiveValue.Value : value; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Security/RandomStringApiTokenProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Man.Dapr.Sidekick.Security 4 | { 5 | public class RandomStringApiTokenProvider : IDaprApiTokenProvider 6 | { 7 | public string GetAppApiToken() => Guid.NewGuid().ToString(); 8 | 9 | public string GetDaprApiToken() => Guid.NewGuid().ToString(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Security/SensitiveStringConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Globalization; 4 | 5 | namespace Man.Dapr.Sidekick.Security 6 | { 7 | public class SensitiveStringConverter : TypeConverter 8 | { 9 | public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) 10 | { 11 | return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); 12 | } 13 | 14 | public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) 15 | { 16 | if (value is string sensitiveValue) 17 | { 18 | return new SensitiveString(sensitiveValue); 19 | } 20 | 21 | return base.ConvertFrom(context, culture, value); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/StringExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace System 2 | { 3 | /// 4 | /// Extension methods for the type for methods missing in .NET3.5. 5 | /// 6 | public static class StringExtensions 7 | { 8 | /// 9 | /// Indicates whether a specified string is null, empty, or consists only of white-space characters. 10 | /// 11 | /// The string to test. 12 | /// true if the value parameter is null or , or if consists exclusively of white-space characters. 13 | public static bool IsNullOrWhiteSpaceEx(this string value) 14 | { 15 | #if NET35 16 | if (value == null) 17 | { 18 | return true; 19 | } 20 | 21 | for (var i = 0; i < value.Length; i++) 22 | { 23 | if (!char.IsWhiteSpace(value[i])) 24 | { 25 | return false; 26 | } 27 | } 28 | 29 | return true; 30 | #else 31 | return string.IsNullOrWhiteSpace(value); 32 | #endif 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Threading/DaprCancellationToken.cs: -------------------------------------------------------------------------------- 1 | namespace Man.Dapr.Sidekick.Threading 2 | { 3 | public readonly partial struct DaprCancellationToken 4 | { 5 | /// 6 | /// Gets an empty CancellationToken value. 7 | /// 8 | /// 9 | /// The value returned by this property will be non-cancelable by default. 10 | /// 11 | public static DaprCancellationToken None => default; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Man.Dapr.Sidekick/Threading/DaprCancellationToken.net35.cs: -------------------------------------------------------------------------------- 1 | #if NET35 2 | namespace Man.Dapr.Sidekick.Threading 3 | { 4 | public partial struct DaprCancellationToken 5 | { 6 | /// 7 | /// Gets a value indicating whether cancellation has been requested for this token. 8 | /// 9 | /// Whether cancellation has been requested for this token. 10 | /// 11 | /// 12 | /// If this property is true, it only guarantees that cancellation has been requested. 13 | /// It does not guarantee that every registered handler 14 | /// has finished executing, nor that cancellation requests have finished propagating 15 | /// to all registered handlers. Additional synchronization may be required, 16 | /// particularly in situations where related objects are being canceled concurrently. 17 | /// 18 | /// 19 | public bool IsCancellationRequested => false; 20 | } 21 | } 22 | #endif 23 | -------------------------------------------------------------------------------- /tests/Directory.build.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | $(RepoRoot)bin\$(Configuration)\test\$(MSBuildProjectName)\ 8 | false 9 | true 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | runtime; build; native; contentfiles; analyzers; buildtransitive 26 | all 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.AspNetCore.Tests/Http/DaprHttpContextHttpClientFactoryTests.cs: -------------------------------------------------------------------------------- 1 | using Man.Dapr.Sidekick.DaprClient; 2 | using Man.Dapr.Sidekick.Security; 3 | using Microsoft.AspNetCore.Http; 4 | using NSubstitute; 5 | using NUnit.Framework; 6 | 7 | namespace Man.Dapr.Sidekick.Http 8 | { 9 | public class DaprHttpContextHttpClientFactoryTests 10 | { 11 | public class CreateInvocationHandler 12 | { 13 | [Test] 14 | public void Should_create_handler_with_context_accessor() 15 | { 16 | var httpContextAccessor = Substitute.For(); 17 | var daprApiTokenAccessor = Substitute.For(); 18 | 19 | var factory = new MockDaprHttpContextHttpClientFactory(httpContextAccessor, daprApiTokenAccessor); 20 | var client = factory.CreateInvokeHttpClient("TEST"); 21 | Assert.That(factory.CreatedInvocationHandler, Is.InstanceOf()); 22 | } 23 | } 24 | 25 | private class MockDaprHttpContextHttpClientFactory : DaprHttpContextHttpClientFactory 26 | { 27 | public MockDaprHttpContextHttpClientFactory(IHttpContextAccessor httpContextAccessor, IDaprApiTokenAccessor daprApiTokenAccessor) 28 | : base(httpContextAccessor, daprApiTokenAccessor) 29 | { 30 | } 31 | 32 | public InvocationHandler CreatedInvocationHandler { get; private set; } 33 | 34 | protected override InvocationHandler CreateInvocationHandler() 35 | { 36 | var handler = base.CreateInvocationHandler(); 37 | CreatedInvocationHandler = handler; 38 | return handler; 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.AspNetCore.Tests/Http/MockHttpContextInvocationHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Net.Http; 2 | using System.Threading; 3 | using Microsoft.AspNetCore.Http; 4 | 5 | namespace Man.Dapr.Sidekick.Http 6 | { 7 | internal class MockHttpContextInvocationHandler : HttpContextInvocationHandler 8 | { 9 | public MockHttpContextInvocationHandler(IHttpContextAccessor httpContextAccessor) 10 | : base(httpContextAccessor) 11 | { 12 | } 13 | 14 | public void InvokeBeforeSendAsync(HttpRequestMessage request, CancellationToken cancellationToken) => OnBeforeSendAsync(request, cancellationToken); 15 | 16 | public void InvokeAfterSendAsync(HttpRequestMessage request, CancellationToken cancellationToken) => OnAfterSendAsync(request, cancellationToken); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.AspNetCore.Tests/Http/MockHttpResponse.cs: -------------------------------------------------------------------------------- 1 | #pragma warning disable RCS1079 // Throwing of new NotImplementedException. 2 | using System; 3 | using System.IO; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Http; 6 | 7 | namespace Man.Dapr.Sidekick.Http 8 | { 9 | internal class MockHttpResponse : HttpResponse 10 | { 11 | public override Stream Body { get; set; } 12 | 13 | public override long? ContentLength { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } 14 | 15 | public override string ContentType { get; set; } 16 | 17 | public override IResponseCookies Cookies => throw new NotImplementedException(); 18 | 19 | public override bool HasStarted => throw new NotImplementedException(); 20 | 21 | public override IHeaderDictionary Headers => throw new NotImplementedException(); 22 | 23 | public override HttpContext HttpContext => throw new NotImplementedException(); 24 | 25 | public override int StatusCode { get; set; } 26 | 27 | public override void OnCompleted(Func callback, object state) 28 | { 29 | throw new NotImplementedException(); 30 | } 31 | 32 | public override void OnStarting(Func callback, object state) 33 | { 34 | throw new NotImplementedException(); 35 | } 36 | 37 | public override void Redirect(string location, bool permanent) 38 | { 39 | throw new NotImplementedException(); 40 | } 41 | } 42 | } 43 | #pragma warning restore RCS1079 // Throwing of new NotImplementedException. 44 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.AspNetCore.Tests/Man.Dapr.Sidekick.AspNetCore.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | false 6 | Man.Dapr.Sidekick.AspNetCore 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.AspNetCore.Tests/Metrics/PrometheusModelTests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | 3 | namespace Man.Dapr.Sidekick.AspNetCore.Metrics 4 | { 5 | public class PrometheusModelTests 6 | { 7 | public class Constructor 8 | { 9 | [Test] 10 | public void Should_initialize_properties() 11 | { 12 | var model = new PrometheusModel(); 13 | Assert.That(model.Metrics, Is.Not.Null); 14 | Assert.That(model.Unknown, Is.Not.Null); 15 | } 16 | } 17 | 18 | public class GetOrAddMetric 19 | { 20 | [Test] 21 | public void Should_add_new() 22 | { 23 | var model = new PrometheusModel(); 24 | var metric = model.GetOrAddMetric("TEST"); 25 | Assert.That(metric, Is.Not.Null); 26 | Assert.That(metric.Name, Is.EqualTo("TEST")); 27 | Assert.That(metric.ToString(), Is.EqualTo("TEST")); 28 | } 29 | 30 | [Test] 31 | public void Should_get_existing() 32 | { 33 | var model = new PrometheusModel(); 34 | var metric1 = model.GetOrAddMetric("TEST"); 35 | var metric2 = model.GetOrAddMetric("TEST"); 36 | Assert.That(metric1, Is.SameAs(metric2)); 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.AspNetCore.Tests/MockDaprProcessOptions.cs: -------------------------------------------------------------------------------- 1 | using Man.Dapr.Sidekick.Options; 2 | 3 | namespace Man.Dapr.Sidekick.AspNetCore 4 | { 5 | public class MockDaprProcessOptions : DaprProcessOptions 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.AspNetCore.Tests/Placement/DaprPlacementHealthCheckBuilderExtensionsTests.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | using Microsoft.Extensions.Diagnostics.HealthChecks; 3 | using NSubstitute; 4 | using NUnit.Framework; 5 | 6 | namespace Man.Dapr.Sidekick.AspNetCore.Placement 7 | { 8 | public class DaprPlacementHealthCheckBuilderExtensionsTests 9 | { 10 | public class AddDaprPlacement 11 | { 12 | [Test] 13 | public void Should_add_check_with_default_name() 14 | { 15 | var builder = Substitute.For(); 16 | builder.When(x => x.Add(Arg.Any())).Do(ci => 17 | { 18 | var registration = (HealthCheckRegistration)ci[0]; 19 | Assert.That(registration.Name, Is.EqualTo("dapr-placement")); 20 | }); 21 | 22 | builder.AddDaprPlacement(); 23 | builder.Received(1).Add(Arg.Any()); 24 | } 25 | 26 | [Test] 27 | public void Should_add_check_with_specified_name() 28 | { 29 | var builder = Substitute.For(); 30 | builder.When(x => x.Add(Arg.Any())).Do(ci => 31 | { 32 | var registration = (HealthCheckRegistration)ci[0]; 33 | Assert.That(registration.Name, Is.EqualTo("HOST_NAME")); 34 | }); 35 | 36 | builder.AddDaprPlacement("HOST_NAME"); 37 | builder.Received(1).Add(Arg.Any()); 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.AspNetCore.Tests/Placement/DaprPlacementHealthCheckTests.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Microsoft.Extensions.Diagnostics.HealthChecks; 3 | using NSubstitute; 4 | using NUnit.Framework; 5 | 6 | namespace Man.Dapr.Sidekick.AspNetCore.Placement 7 | { 8 | public class DaprPlacementHealthCheckTests 9 | { 10 | public class CheckHealthAsync 11 | { 12 | [Test] 13 | public async Task Should_get_health_from_host() 14 | { 15 | var host = Substitute.For(); 16 | var hc = new DaprPlacementHealthCheck(host); 17 | 18 | var result = await hc.CheckHealthAsync(null); 19 | 20 | Assert.That(result.Status, Is.EqualTo(HealthStatus.Unhealthy)); 21 | host.Received(1).GetProcessInfo(); 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.AspNetCore.Tests/Placement/DaprPlacementMetricsCollectorTests.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Man.Dapr.Sidekick.AspNetCore.Metrics; 3 | using NSubstitute; 4 | using NUnit.Framework; 5 | 6 | namespace Man.Dapr.Sidekick.AspNetCore.Placement 7 | { 8 | public class DaprPlacementMetricsCollectorTests 9 | { 10 | public class CollectTextAsync 11 | { 12 | [Test] 13 | public async Task Should_get_info_from_host() 14 | { 15 | var host = Substitute.For(); 16 | var collector = new DaprPlacementMetricsCollector(host); 17 | var model = new PrometheusModel(); 18 | 19 | await collector.CollectTextAsync(model); 20 | 21 | host.Received(1).GetProcessInfo(); 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.AspNetCore.Tests/Sentry/DaprSentryHealthCheckBuilderExtensionsTests.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | using Microsoft.Extensions.Diagnostics.HealthChecks; 3 | using NSubstitute; 4 | using NUnit.Framework; 5 | 6 | namespace Man.Dapr.Sidekick.AspNetCore.Sentry 7 | { 8 | public class DaprSentryHealthCheckBuilderExtensionsTests 9 | { 10 | public class AddDaprSentry 11 | { 12 | [Test] 13 | public void Should_add_check_with_default_name() 14 | { 15 | var builder = Substitute.For(); 16 | builder.When(x => x.Add(Arg.Any())).Do(ci => 17 | { 18 | var registration = (HealthCheckRegistration)ci[0]; 19 | Assert.That(registration.Name, Is.EqualTo("dapr-sentry")); 20 | }); 21 | 22 | builder.AddDaprSentry(); 23 | builder.Received(1).Add(Arg.Any()); 24 | } 25 | 26 | [Test] 27 | public void Should_add_check_with_specified_name() 28 | { 29 | var builder = Substitute.For(); 30 | builder.When(x => x.Add(Arg.Any())).Do(ci => 31 | { 32 | var registration = (HealthCheckRegistration)ci[0]; 33 | Assert.That(registration.Name, Is.EqualTo("HOST_NAME")); 34 | }); 35 | 36 | builder.AddDaprSentry("HOST_NAME"); 37 | builder.Received(1).Add(Arg.Any()); 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.AspNetCore.Tests/Sentry/DaprSentryHealthCheckTests.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Microsoft.Extensions.Diagnostics.HealthChecks; 3 | using NSubstitute; 4 | using NUnit.Framework; 5 | 6 | namespace Man.Dapr.Sidekick.AspNetCore.Sentry 7 | { 8 | public class DaprSentryHealthCheckTests 9 | { 10 | public class CheckHealthAsync 11 | { 12 | [Test] 13 | public async Task Should_get_health_from_host() 14 | { 15 | var host = Substitute.For(); 16 | var hc = new DaprSentryHealthCheck(host); 17 | 18 | var result = await hc.CheckHealthAsync(null); 19 | 20 | Assert.That(result.Status, Is.EqualTo(HealthStatus.Unhealthy)); 21 | host.Received(1).GetProcessInfo(); 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.AspNetCore.Tests/Sentry/DaprSentryMetricsCollectorTests.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Man.Dapr.Sidekick.AspNetCore.Metrics; 3 | using NSubstitute; 4 | using NUnit.Framework; 5 | 6 | namespace Man.Dapr.Sidekick.AspNetCore.Sentry 7 | { 8 | public class DaprSentryMetricsCollectorTests 9 | { 10 | public class CollectTextAsync 11 | { 12 | [Test] 13 | public async Task Should_get_info_from_host() 14 | { 15 | var host = Substitute.For(); 16 | var collector = new DaprSentryMetricsCollector(host); 17 | var model = new PrometheusModel(); 18 | 19 | await collector.CollectTextAsync(model); 20 | 21 | host.Received(1).GetProcessInfo(); 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.AspNetCore.Tests/Sidecar/DaprSidecarHealthCheckBuilderExtensionsTests.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | using Microsoft.Extensions.Diagnostics.HealthChecks; 3 | using NSubstitute; 4 | using NUnit.Framework; 5 | 6 | namespace Man.Dapr.Sidekick.AspNetCore.Sidecar 7 | { 8 | public class DaprSidecarHealthCheckBuilderExtensionsTests 9 | { 10 | public class AddDaprSidecar 11 | { 12 | [Test] 13 | public void Should_add_check_with_default_name() 14 | { 15 | var builder = Substitute.For(); 16 | builder.When(x => x.Add(Arg.Any())).Do(ci => 17 | { 18 | var registration = (HealthCheckRegistration)ci[0]; 19 | Assert.That(registration.Name, Is.EqualTo("dapr-sidecar")); 20 | }); 21 | 22 | builder.AddDaprSidecar(); 23 | builder.Received(1).Add(Arg.Any()); 24 | } 25 | 26 | [Test] 27 | public void Should_add_check_with_specified_name() 28 | { 29 | var builder = Substitute.For(); 30 | builder.When(x => x.Add(Arg.Any())).Do(ci => 31 | { 32 | var registration = (HealthCheckRegistration)ci[0]; 33 | Assert.That(registration.Name, Is.EqualTo("HOST_NAME")); 34 | }); 35 | 36 | builder.AddDaprSidecar("HOST_NAME"); 37 | builder.Received(1).Add(Arg.Any()); 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.AspNetCore.Tests/Sidecar/DaprSidecarHealthCheckTests.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Microsoft.Extensions.Diagnostics.HealthChecks; 3 | using NSubstitute; 4 | using NUnit.Framework; 5 | 6 | namespace Man.Dapr.Sidekick.AspNetCore.Sidecar 7 | { 8 | public class DaprSidecarHealthCheckTests 9 | { 10 | public class CheckHealthAsync 11 | { 12 | [Test] 13 | public async Task Should_get_health_from_host() 14 | { 15 | var host = Substitute.For(); 16 | var hc = new DaprSidecarHealthCheck(host); 17 | 18 | var result = await hc.CheckHealthAsync(null); 19 | 20 | Assert.That(result.Status, Is.EqualTo(HealthStatus.Unhealthy)); 21 | host.Received(1).GetProcessInfo(); 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.AspNetCore.Tests/Sidecar/DaprSidecarMetricFilterTests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | 3 | namespace Man.Dapr.Sidekick.AspNetCore.Sidecar 4 | { 5 | public class DaprSidecarMetricFilterTests 6 | { 7 | public class ExcludeMetricLine 8 | { 9 | [TestCase("EMPTY", false)] 10 | [TestCase("status=401", false)] 11 | [TestCase("STATUS=\"401\"", false)] 12 | [TestCase(" status=\"401\" ", true)] 13 | public void Should_exclude_expected_lines(string line, bool expected) 14 | { 15 | var filter = new DaprSidecarMetricFilter(); 16 | Assert.That(filter.ExcludeMetricLine(null, line), Is.EqualTo(expected)); 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.AspNetCore.Tests/Sidecar/DaprSidecarMetricsCollectorTests.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Man.Dapr.Sidekick.AspNetCore.Metrics; 3 | using NSubstitute; 4 | using NUnit.Framework; 5 | 6 | namespace Man.Dapr.Sidekick.AspNetCore.Sidecar 7 | { 8 | public class DaprSidecarMetricsCollectorTests 9 | { 10 | public class CollectTextAsync 11 | { 12 | [Test] 13 | public async Task Should_get_info_from_host() 14 | { 15 | var host = Substitute.For(); 16 | var collector = new DaprSidecarMetricsCollector(host); 17 | var model = new PrometheusModel(); 18 | 19 | await collector.CollectTextAsync(model); 20 | 21 | host.Received(1).GetProcessInfo(); 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.Extensions.Logging.Tests/Man.Dapr.Sidekick.Extensions.Logging.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | Man.Dapr.Sidekick.Extensions.Logging 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.Tests/DaprClient/DaprClientTests.cs: -------------------------------------------------------------------------------- 1 | #if !NET35 2 | using System; 3 | using NUnit.Framework; 4 | 5 | namespace Man.Dapr.Sidekick.DaprClient 6 | { 7 | public class DaprClientTests 8 | { 9 | public class CreateInvokeHttpClient 10 | { 11 | [Test] 12 | public void Should_create_client() 13 | { 14 | var client = DaprClient.CreateInvokeHttpClient( 15 | "APP_ID", 16 | "http://127.0.0.1:1234", 17 | "API_TOKEN"); 18 | 19 | Assert.That(client.BaseAddress.ToString(), Is.EqualTo("http://app_id/")); 20 | } 21 | 22 | [Test] 23 | public void Should_throw_exception_when_invalid_appid() 24 | { 25 | Assert.Throws( 26 | Is.InstanceOf().With.Message.StartsWith("The appId must be a valid hostname"), 27 | () => DaprClient.CreateInvokeHttpClient("!£$%^&*()_")); 28 | } 29 | } 30 | } 31 | } 32 | #endif 33 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.Tests/DaprPlacementHostTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Man.Dapr.Sidekick.Http; 3 | using Man.Dapr.Sidekick.Logging; 4 | using Man.Dapr.Sidekick.Process; 5 | using Man.Dapr.Sidekick.Threading; 6 | using NSubstitute; 7 | using NUnit.Framework; 8 | 9 | namespace Man.Dapr.Sidekick 10 | { 11 | public class DaprPlacementHostTests 12 | { 13 | public class Constructor 14 | { 15 | [Test] 16 | public void Should_set_properties() 17 | { 18 | var daprProcessFactory = Substitute.For(); 19 | var daprPlacementProcess = Substitute.For(); 20 | daprProcessFactory.CreateDaprPlacementProcess().Returns(daprPlacementProcess); 21 | var daprHttpClientFactory = Substitute.For(); 22 | var loggerFactory = Substitute.For(); 23 | 24 | var host = new DaprPlacementHost(daprProcessFactory, daprHttpClientFactory, loggerFactory); 25 | 26 | // Check HttpClientFactory 27 | Assert.That(host.DaprHttpClientFactory, Is.SameAs(daprHttpClientFactory)); 28 | 29 | // Check Logger 30 | Assert.That(host.Logger, Is.InstanceOf>()); 31 | loggerFactory.Received(1).CreateLogger("Man.Dapr.Sidekick.DaprPlacementHost"); 32 | 33 | // Check ProcessFactory 34 | var cancellationToken = DaprCancellationToken.None; 35 | host.Start(null, cancellationToken); 36 | daprPlacementProcess.Received(1).Start(Arg.Any>(), host.Logger, cancellationToken); 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.Tests/DaprSentryHostTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Man.Dapr.Sidekick.Http; 3 | using Man.Dapr.Sidekick.Logging; 4 | using Man.Dapr.Sidekick.Process; 5 | using Man.Dapr.Sidekick.Threading; 6 | using NSubstitute; 7 | using NUnit.Framework; 8 | 9 | namespace Man.Dapr.Sidekick 10 | { 11 | public class DaprSentryHostTests 12 | { 13 | public class Constructor 14 | { 15 | [Test] 16 | public void Should_set_properties() 17 | { 18 | var daprProcessFactory = Substitute.For(); 19 | var daprSentryProcess = Substitute.For(); 20 | daprProcessFactory.CreateDaprSentryProcess().Returns(daprSentryProcess); 21 | var daprHttpClientFactory = Substitute.For(); 22 | var loggerFactory = Substitute.For(); 23 | 24 | var host = new DaprSentryHost(daprProcessFactory, daprHttpClientFactory, loggerFactory); 25 | 26 | // Check HttpClientFactory 27 | Assert.That(host.DaprHttpClientFactory, Is.SameAs(daprHttpClientFactory)); 28 | 29 | // Check Logger 30 | Assert.That(host.Logger, Is.InstanceOf>()); 31 | loggerFactory.Received(1).CreateLogger("Man.Dapr.Sidekick.DaprSentryHost"); 32 | 33 | // Check ProcessFactory 34 | var cancellationToken = DaprCancellationToken.None; 35 | host.Start(null, cancellationToken); 36 | daprSentryProcess.Received(1).Start(Arg.Any>(), host.Logger, cancellationToken); 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.Tests/Http/DaprProcessHttpClientFactoryTests.net35.cs: -------------------------------------------------------------------------------- 1 | #if NET35 2 | using System; 3 | using NUnit.Framework; 4 | 5 | namespace Man.Dapr.Sidekick.Http 6 | { 7 | public class DaprProcessHttpClientFactoryTests 8 | { 9 | public class CreateDaprWebClient 10 | { 11 | [Test] 12 | public void Should_create_unique_instance_each_call() 13 | { 14 | var factory = new DaprProcessHttpClientFactory(); 15 | Assert.That(factory.CreateDaprWebClient(), Is.Not.SameAs(factory.CreateDaprWebClient())); 16 | } 17 | } 18 | 19 | [Test] 20 | public void Should_throw_exception_when_disposed() 21 | { 22 | var factory = new DaprProcessHttpClientFactory(); 23 | factory.Dispose(); 24 | Assert.Throws(Is.TypeOf(), () => factory.CreateDaprWebClient()); 25 | } 26 | } 27 | } 28 | #endif 29 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.Tests/Http/DaprProcessHttpClientFactoryTests.net45.cs: -------------------------------------------------------------------------------- 1 | #if !NET35 2 | using System; 3 | using System.Threading.Tasks; 4 | using NUnit.Framework; 5 | 6 | namespace Man.Dapr.Sidekick.Http 7 | { 8 | public class DaprProcessHttpClientFactoryTests 9 | { 10 | public class CreateDaprHttpClient 11 | { 12 | [Test] 13 | public void Should_reuse_same_instance_each_call() 14 | { 15 | var factory = new DaprProcessHttpClientFactory(); 16 | Assert.That(factory.CreateDaprHttpClient(), Is.SameAs(factory.CreateDaprHttpClient())); 17 | } 18 | 19 | [Test] 20 | public async Task Should_use_specified_handler() 21 | { 22 | var handler = new MockHttpClientHandler(); 23 | var factory = new DaprProcessHttpClientFactory(handler); 24 | var client = factory.CreateDaprHttpClient(); 25 | await client.GetAsync("http://does-not-exist"); 26 | Assert.That(handler.SendAsyncInvoked, Is.True); 27 | } 28 | 29 | [Test] 30 | public void Should_throw_exception_when_disposed() 31 | { 32 | var factory = new DaprProcessHttpClientFactory(); 33 | factory.Dispose(); 34 | Assert.Throws(Is.TypeOf(), () => factory.CreateDaprHttpClient()); 35 | } 36 | } 37 | } 38 | } 39 | #endif 40 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.Tests/Http/MockDaprSidecarHttpClientFactory.cs: -------------------------------------------------------------------------------- 1 | #if !NET35 2 | using System.Net.Http; 3 | using Man.Dapr.Sidekick.Security; 4 | 5 | namespace Man.Dapr.Sidekick.Http 6 | { 7 | public class MockDaprSidecarHttpClientFactory : DaprSidecarHttpClientFactory 8 | { 9 | public MockDaprSidecarHttpClientFactory(IDaprApiTokenAccessor tokenAccessor) 10 | : base(tokenAccessor) 11 | { 12 | InnerHandler = new MockHttpClientHandler(); 13 | } 14 | 15 | public MockHttpClientHandler InnerHandler { get; } 16 | 17 | protected override HttpMessageHandler CreateInnerHandler() => base.CreateInnerHandler() ?? InnerHandler; 18 | } 19 | } 20 | #endif 21 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.Tests/Http/MockHttpClientHandler.cs: -------------------------------------------------------------------------------- 1 | #if !NET35 2 | using System; 3 | using System.Net; 4 | using System.Net.Http; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | 8 | namespace Man.Dapr.Sidekick.Http 9 | { 10 | public class MockHttpClientHandler : HttpClientHandler 11 | { 12 | public HttpStatusCode ResponseCode { get; set; } = HttpStatusCode.NoContent; 13 | 14 | public bool SendAsyncInvoked => SendAsyncRequest != null; 15 | 16 | public HttpRequestMessage SendAsyncRequest { get; private set; } 17 | 18 | public Action OnSendAsyncRequest { get; set; } 19 | 20 | protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 21 | { 22 | SendAsyncRequest = request; 23 | OnSendAsyncRequest?.Invoke(request); 24 | return Task.FromResult(new HttpResponseMessage(ResponseCode)); 25 | } 26 | } 27 | } 28 | #endif 29 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.Tests/Http/UriHelperTests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | 3 | namespace Man.Dapr.Sidekick.Http 4 | { 5 | public class UriHelperTests 6 | { 7 | [TestCase(null, null)] 8 | [TestCase("", null)] 9 | [TestCase("http://localhost", 80)] 10 | [TestCase("http://bob@test*:1234", 1234)] 11 | [TestCase("http://*:2345", 2345)] 12 | [TestCase("http://+:3456", 3456)] 13 | [TestCase("http://+:4567/something?else", 4567)] 14 | [TestCase("https://www.something.com:5678", 5678)] 15 | public void Should_parse_uri(string uri, int? expected) 16 | { 17 | Assert.That(UriHelper.Parse(uri)?.Port, Is.EqualTo(expected)); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.Tests/Logging/DaprColoredConsoleLoggerFactoryTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NUnit.Framework; 3 | 4 | namespace Man.Dapr.Sidekick.Logging 5 | { 6 | public class DaprColoredConsoleLoggerFactoryTests 7 | { 8 | public class CreateLogger 9 | { 10 | [Test] 11 | public void Should_create_colored_console_logger() 12 | { 13 | var factory = new DaprColoredConsoleLoggerFactory(); 14 | var logger = factory.CreateLogger("test"); 15 | Assert.That(logger, Is.TypeOf()); 16 | } 17 | 18 | [Test] 19 | public void Should_create_new_instance_by_category() 20 | { 21 | var factory = new DaprColoredConsoleLoggerFactory(); 22 | Assert.That(factory.CreateLogger("test"), Is.Not.SameAs(factory.CreateLogger("test2"))); 23 | } 24 | 25 | [Test] 26 | public void Should_reuse_instance_for_same_category() 27 | { 28 | var factory = new DaprColoredConsoleLoggerFactory(); 29 | Assert.That(factory.CreateLogger("test"), Is.SameAs(factory.CreateLogger("test"))); 30 | } 31 | 32 | [Test] 33 | public void Should_throw_exception_when_disposed() 34 | { 35 | var factory = new DaprColoredConsoleLoggerFactory(); 36 | factory.Dispose(); 37 | Assert.Throws(Is.TypeOf(), () => factory.CreateLogger("test")); 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.Tests/Logging/DaprEventIdTests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | 3 | namespace Man.Dapr.Sidekick.Logging 4 | { 5 | public class DaprEventIdTests 6 | { 7 | [Test] 8 | public void Should_implement_equality() 9 | { 10 | Assert.That((DaprEventId)100, Is.EqualTo(new DaprEventId(100))); 11 | Assert.That((DaprEventId)100 == (DaprEventId)100, Is.True); 12 | Assert.That(new DaprEventId(200) == (DaprEventId)100, Is.False); 13 | Assert.That(new DaprEventId(200) != (DaprEventId)100, Is.True); 14 | Assert.That(new DaprEventId(200).Equals((DaprEventId)200), Is.True); 15 | Assert.That(new DaprEventId(200).Equals(null), Is.False); 16 | Assert.That((DaprEventId)200, Is.Not.EqualTo(new DaprEventId(100))); 17 | Assert.That(new DaprEventId(100).GetHashCode(), Is.EqualTo(100)); 18 | } 19 | 20 | [Test] 21 | public void Should_set_id_and_name() 22 | { 23 | var value = new DaprEventId(100, "TEST"); 24 | Assert.That(value.Id, Is.EqualTo(100)); 25 | Assert.That(value.Name, Is.EqualTo("TEST")); 26 | } 27 | 28 | [Test] 29 | public void Should_override_tostring() 30 | { 31 | Assert.That(new DaprEventId(100).ToString(), Is.EqualTo("100")); 32 | Assert.That(new DaprEventId(100, "TEST").ToString(), Is.EqualTo("TEST")); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.Tests/Logging/Internal/SystemColorTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NUnit.Framework; 3 | 4 | namespace Man.Dapr.Sidekick.Logging.Internal 5 | { 6 | public class SystemColorTests 7 | { 8 | public class ForegroundColor 9 | { 10 | [Test] 11 | public void Should_get_and_set_foreground_color() 12 | { 13 | var systemConsole = new SystemConsole(); 14 | 15 | Assert.DoesNotThrow(() => 16 | { 17 | var initialColor = systemConsole.ForegroundColor; 18 | systemConsole.ForegroundColor = ConsoleColor.DarkYellow; 19 | systemConsole.ForegroundColor = initialColor; 20 | }); 21 | } 22 | } 23 | 24 | public class WriteLine 25 | { 26 | [Test] 27 | public void Should_not_throw_exception() 28 | { 29 | var systemConsole = new SystemConsole(); 30 | 31 | Assert.DoesNotThrow(() => systemConsole.WriteLine("TEST")); 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.Tests/Logging/Internal/TypeNameHelperTests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | 3 | namespace Man.Dapr.Sidekick.Logging.Internal 4 | { 5 | public class TypeNameHelperTests 6 | { 7 | public class GetTypeDisplayName 8 | { 9 | [Test] 10 | public void Should_get_for_custom_type() 11 | { 12 | Assert.That(TypeNameHelper.GetTypeDisplayName(typeof(IDaprLoggerFactory)), Is.EqualTo("Man.Dapr.Sidekick.Logging.IDaprLoggerFactory")); 13 | } 14 | 15 | [Test] 16 | public void Should_get_for_nested_type() 17 | { 18 | Assert.That(TypeNameHelper.GetTypeDisplayName(typeof(DaprColoredConsoleLoggerOptions.LogLevelOptions)), Is.EqualTo("Man.Dapr.Sidekick.Logging.DaprColoredConsoleLoggerOptions.LogLevelOptions")); 19 | } 20 | 21 | [Test] 22 | public void Should_get_for_generic_type() 23 | { 24 | Assert.That(TypeNameHelper.GetTypeDisplayName(typeof(IDaprLogger)), Is.EqualTo("Man.Dapr.Sidekick.Logging.IDaprLogger")); 25 | } 26 | 27 | [Test] 28 | public void Should_get_for_builtin_type() 29 | { 30 | Assert.That(TypeNameHelper.GetTypeDisplayName(typeof(string)), Is.EqualTo("string")); 31 | } 32 | 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.Tests/Man.Dapr.Sidekick.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net35;net48;net8.0 5 | 8.0 6 | false 7 | Man.Dapr.Sidekick 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.Tests/MockDisposable.cs: -------------------------------------------------------------------------------- 1 | namespace Man.Dapr.Sidekick 2 | { 3 | public class MockDisposable : DaprDisposable 4 | { 5 | public bool? OnDisposingValue { get; set; } 6 | 7 | public bool? IsDisposingValue { get; set; } 8 | 9 | public void InvokeDispose(bool disposing) 10 | { 11 | Dispose(disposing); 12 | } 13 | 14 | public void InvokeEnsureNotDisposed() 15 | { 16 | EnsureNotDisposed(); 17 | } 18 | 19 | protected override void OnDisposing(bool disposing) 20 | { 21 | IsDisposingValue = IsDisposing; 22 | OnDisposingValue = disposing; 23 | base.OnDisposing(disposing); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.Tests/Options/MockDaprProcessOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Man.Dapr.Sidekick.Options 4 | { 5 | public class MockDaprProcessOptions : DaprProcessOptions 6 | { 7 | public int? HealthPort { get; set; } 8 | 9 | public int? MetricsPort { get; set; } 10 | 11 | protected override bool AddHealthUri(UriBuilder builder) 12 | { 13 | if (HealthPort.HasValue) 14 | { 15 | builder.Port = HealthPort.Value; 16 | return true; 17 | } 18 | else 19 | { 20 | return false; 21 | } 22 | } 23 | 24 | protected override bool AddMetricsUri(UriBuilder builder) 25 | { 26 | if (MetricsPort.HasValue) 27 | { 28 | builder.Port = MetricsPort.Value; 29 | return true; 30 | } 31 | else 32 | { 33 | return false; 34 | } 35 | } 36 | } 37 | 38 | public class MockDaprProcessOptionsNoOverrides : DaprProcessOptions 39 | { 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.Tests/Process/MockDaprProcessOptions.cs: -------------------------------------------------------------------------------- 1 | using Man.Dapr.Sidekick.Options; 2 | 3 | namespace Man.Dapr.Sidekick.Process 4 | { 5 | public class MockDaprProcessOptions : DaprProcessOptions 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.Tests/Process/MockPortAvailabilityChecker.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Man.Dapr.Sidekick.Process 4 | { 5 | public class MockPortAvailabilityChecker : IPortAvailabilityChecker 6 | { 7 | public int GetAvailablePort(int startingPort, IEnumerable reservedPorts = null) => startingPort; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.Tests/Process/PortAvailabilityCheckerTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NUnit.Framework; 3 | 4 | namespace Man.Dapr.Sidekick.Process 5 | { 6 | public class PortAvailabilityCheckerTests 7 | { 8 | public class GetAvailablePort 9 | { 10 | [Test] 11 | public void Should_throw_exception_when_invalid_startingport() 12 | { 13 | Assert.Throws( 14 | Is.InstanceOf().With.Message.StartsWith("Starting Port cannot be greater than 65535"), 15 | () => new PortAvailabilityChecker().GetAvailablePort(65536)); 16 | } 17 | 18 | [Test] 19 | public void Should_assign_next_available_port() 20 | { 21 | var result = new PortAvailabilityChecker().GetAvailablePort(65500); 22 | Assert.That(result, Is.GreaterThanOrEqualTo(65500)); 23 | } 24 | 25 | [Test] 26 | public void Should_not_assign_reserved_port() 27 | { 28 | var result = new PortAvailabilityChecker().GetAvailablePort(65500, new[] { 65500, 65501, 65502 }); 29 | Assert.That(result, Is.GreaterThan(65502)); 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.Tests/Process/ProcessFinderTests.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using NUnit.Framework; 3 | 4 | namespace Man.Dapr.Sidekick.Process 5 | { 6 | public class ProcessFinderTests 7 | { 8 | public class FindExistingProcesses 9 | { 10 | [Test] 11 | public void Should_find_by_name() 12 | { 13 | // We know at least the current process is running so see if we can find it. 14 | var process = System.Diagnostics.Process.GetCurrentProcess(); 15 | var finder = new ProcessFinder(); 16 | var result = finder.FindExistingProcesses(process.ProcessName); 17 | Assert.That(result.Count(), Is.GreaterThanOrEqualTo(1)); 18 | Assert.That(result.Any(x => x.Id == process.Id), Is.True); 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.Tests/Resources/ProcessProgram.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Man.Dapr.Sidekick.Resources 4 | { 5 | public class ProcessProgram 6 | { 7 | public class Program 8 | { 9 | public static void Main(string[] args) 10 | { 11 | // Write the arguments to the Console with a pipe separator 12 | Console.WriteLine("ARGS|" + string.Join("|", args)); 13 | Console.WriteLine("Program Started"); 14 | 15 | // Wait for 1 second to complete 16 | System.Threading.Thread.Sleep(1000); 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.Tests/Security/DaprApiTokenManagerTests.cs: -------------------------------------------------------------------------------- 1 | using NSubstitute; 2 | using NUnit.Framework; 3 | 4 | namespace Man.Dapr.Sidekick.Security 5 | { 6 | public class DaprApiTokenManagerTests 7 | { 8 | [Test] 9 | public void Should_initialize_tokens() 10 | { 11 | var provider = Substitute.For(); 12 | provider.GetAppApiToken().Returns("APP_TOKEN"); 13 | provider.GetDaprApiToken().Returns("DAPR_TOKEN"); 14 | var manager = new DaprApiTokenManager(provider); 15 | 16 | Assert.That(manager.AppApiToken.Value, Is.EqualTo("APP_TOKEN")); 17 | Assert.That(manager.DaprApiToken.Value, Is.EqualTo("DAPR_TOKEN")); 18 | } 19 | 20 | [Test] 21 | public void Should_set_app_api_token() 22 | { 23 | var provider = Substitute.For(); 24 | var manager = new DaprApiTokenManager(provider); 25 | 26 | manager.SetAppApiToken("SET_APP_TOKEN"); 27 | Assert.That(manager.AppApiToken.Value, Is.EqualTo("SET_APP_TOKEN")); 28 | } 29 | 30 | [Test] 31 | public void Should_set_dapr_api_token() 32 | { 33 | var provider = Substitute.For(); 34 | var manager = new DaprApiTokenManager(provider); 35 | 36 | manager.SetDaprApiToken("SET_DAPR_TOKEN"); 37 | Assert.That(manager.DaprApiToken.Value, Is.EqualTo("SET_DAPR_TOKEN")); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.Tests/Security/ObjectExtensionsTests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | 3 | namespace Man.Dapr.Sidekick.Security 4 | { 5 | public class ObjectExtensionsTests 6 | { 7 | public class SensitiveValue 8 | { 9 | [Test] 10 | public void Should_return_null_for_null_value() 11 | { 12 | Assert.That(((object)null).SensitiveValue, Is.Null); 13 | } 14 | 15 | [Test] 16 | public void Should_return_value_for_value() 17 | { 18 | Assert.That("NOT_SENSITIVE".SensitiveValue, Is.EqualTo("NOT_SENSITIVE")); 19 | } 20 | 21 | [Test] 22 | public void Should_return_value_for_sensitive_value() 23 | { 24 | var sensitiveValue = new SensitiveString("SENSITIVE"); 25 | Assert.That(((object)sensitiveValue).SensitiveValue, Is.EqualTo("SENSITIVE")); 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.Tests/Security/RandomStringApiTokenProviderTests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | 3 | namespace Man.Dapr.Sidekick.Security 4 | { 5 | public class RandomStringApiTokenProviderTests 6 | { 7 | public class GetAppApiToken 8 | { 9 | [Test] 10 | public void Should_return_different_tokens_each_call() 11 | { 12 | var provider = new RandomStringApiTokenProvider(); 13 | var token1 = provider.GetAppApiToken(); 14 | var token2 = provider.GetAppApiToken(); 15 | 16 | Assert.That(token1, Is.Not.Null); 17 | Assert.That(token2, Is.Not.Null); 18 | Assert.That(token1, Is.Not.EqualTo(token2)); 19 | } 20 | } 21 | 22 | public class GetDaprApiToken 23 | { 24 | [Test] 25 | public void Should_return_different_tokens_each_call() 26 | { 27 | var provider = new RandomStringApiTokenProvider(); 28 | var token1 = provider.GetDaprApiToken(); 29 | var token2 = provider.GetDaprApiToken(); 30 | 31 | Assert.That(token1, Is.Not.Null); 32 | Assert.That(token2, Is.Not.Null); 33 | Assert.That(token1, Is.Not.EqualTo(token2)); 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.Tests/Security/SensitiveStringConverterTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NUnit.Framework; 3 | 4 | namespace Man.Dapr.Sidekick.Security 5 | { 6 | public class SensitiveStringConverterTests 7 | { 8 | [Test] 9 | public void Should_convert_from_string_only() 10 | { 11 | var converter = new SensitiveStringConverter(); 12 | 13 | Assert.That(converter.CanConvertFrom(typeof(string)), Is.True); 14 | Assert.That(converter.CanConvertFrom(typeof(int)), Is.False); 15 | Assert.That(converter.CanConvertFrom(typeof(object)), Is.False); 16 | 17 | Assert.That(converter.ConvertFrom("TEST"), Is.EqualTo(new SensitiveString("TEST"))); 18 | Assert.Throws(Is.InstanceOf(), () => converter.ConvertFrom(100)); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.Tests/Threading/DaprCancellationTokenTests.net35.cs: -------------------------------------------------------------------------------- 1 | #if NET35 2 | using NUnit.Framework; 3 | 4 | namespace Man.Dapr.Sidekick.Threading 5 | { 6 | public class DaprCancellationTokenTests 7 | { 8 | [Test] 9 | public void Should_return_different_instance_for_none() 10 | { 11 | Assert.That(DaprCancellationToken.None, Is.Not.SameAs(DaprCancellationToken.None)); 12 | } 13 | 14 | [Test] 15 | public void Should_always_return_false_for_cancellation_requested() 16 | { 17 | Assert.That(default(DaprCancellationToken).IsCancellationRequested, Is.False); 18 | } 19 | } 20 | } 21 | #endif 22 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.Tests/Threading/DaprCancellationTokenTests.net45.cs: -------------------------------------------------------------------------------- 1 | #if !NET35 2 | using System.Threading; 3 | using NUnit.Framework; 4 | 5 | namespace Man.Dapr.Sidekick.Threading 6 | { 7 | public class DaprCancellationTokenTests 8 | { 9 | [Test] 10 | public void Should_return_different_instance_for_none() 11 | { 12 | Assert.That(DaprCancellationToken.None, Is.Not.SameAs(DaprCancellationToken.None)); 13 | } 14 | 15 | [Test] 16 | public void Should_wrap_cancellation_token() 17 | { 18 | var cts = new CancellationTokenSource(); 19 | var ct = new DaprCancellationToken(cts.Token); 20 | 21 | Assert.That(ct.IsCancellationRequested, Is.False); 22 | Assert.That(ct.CancellationToken, Is.EqualTo(cts.Token)); 23 | 24 | cts.Cancel(); 25 | Assert.That(ct.IsCancellationRequested, Is.True); 26 | } 27 | } 28 | } 29 | #endif 30 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.Tests/_TestHelpers/ExtensionMethods.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using Man.Dapr.Sidekick.Logging; 3 | using NSubstitute; 4 | 5 | namespace Man.Dapr.Sidekick 6 | { 7 | public static class ExtensionMethods 8 | { 9 | public static LoggerCall[] ReceivedLoggerCalls(this IDaprLogger logger) 10 | { 11 | return logger.ReceivedCalls().Select(x => new LoggerCall(x)).ToArray(); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/Man.Dapr.Sidekick.Tests/_TestHelpers/LoggerCall.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Man.Dapr.Sidekick.Logging; 3 | using NSubstitute.Core; 4 | 5 | namespace Man.Dapr.Sidekick 6 | { 7 | /// 8 | /// Supporting class for capturing details about calls made to the Microsoft Logging framework. 9 | /// 10 | public class LoggerCall 11 | { 12 | public LoggerCall(ICall call) 13 | { 14 | var args = call.GetArguments(); 15 | if (args.Length == 1) 16 | { 17 | // Scope message 18 | IsScope = true; 19 | Message = Convert.ToString(args[0]); 20 | } 21 | else 22 | { 23 | // Regular message 24 | LogLevel = (DaprLogLevel)args[0]; 25 | Message = Convert.ToString(args[2]); 26 | Exception = args.Length > 3 ? (Exception)args[3] : null; 27 | } 28 | } 29 | 30 | public DaprLogLevel? LogLevel { get; } 31 | 32 | public string Message { get; } 33 | 34 | public bool IsScope { get; } 35 | 36 | public Exception Exception { get; } 37 | } 38 | } 39 | --------------------------------------------------------------------------------