├── .devcontainer ├── Dockerfile ├── devcontainer.json ├── library-scripts │ ├── cloud-clis-debian.sh │ ├── common-debian.sh │ ├── dev-tools-debian.sh │ ├── docker-in-docker-debian.sh │ └── powershell-debian.sh └── on-create.sh ├── .github └── workflows │ └── demo_devops.yml ├── .gitignore ├── .images ├── ActionsSecrets.png ├── CodespaceSecrets.png ├── DebugPane.png ├── DevOpsAppOverview.png ├── OpenWorkspace.png ├── OpenWorkspaceFileMenu.png ├── RunWorkflow.png ├── SendRequest.png ├── Services.png └── Zipkin.png ├── .scripts ├── cleanUpAll.ps1 ├── common.ps1 ├── demos.ps1 └── deployAll.ps1 ├── Binding ├── .scripts │ ├── Deploy-AWSInfrastructure.ps1 │ └── Deploy-AzureInfrastructure.ps1 ├── README.md ├── cleanUp.ps1 ├── components │ ├── aws │ │ ├── binding.aws.s3.yaml │ │ └── secretstore.yaml │ ├── azure │ │ ├── azurestorage.yaml │ │ └── secretstore.yaml │ └── local │ │ └── localstorage.yaml ├── demo.ps1 ├── deploy │ ├── aws │ │ ├── main.tf │ │ └── variables.tf │ └── azure │ │ ├── binding.bicep │ │ └── main.bicep ├── sampleRequests.http └── tempfiles │ └── .gitkeep ├── DevOps ├── .gitignore ├── .scripts │ └── Deploy-AzureInfrastructure.ps1 ├── .vscode │ ├── launch.json │ └── tasks.json ├── README.md ├── charts │ ├── Chart.yaml │ ├── templates │ │ └── NOTES.txt │ └── values.yaml ├── cleanUp.ps1 ├── components │ ├── charts │ │ ├── appinsights │ │ │ ├── .helmignore │ │ │ ├── Chart.yaml │ │ │ ├── templates │ │ │ │ ├── open-telemetry-collector-appinsights.yaml │ │ │ │ └── tracing.yaml │ │ │ └── values.yaml │ │ ├── components │ │ │ ├── .helmignore │ │ │ ├── Chart.yaml │ │ │ ├── templates │ │ │ │ ├── demo-bus-secret.yaml │ │ │ │ ├── demo-processor-secret.yaml │ │ │ │ ├── demo-state-secret.yaml │ │ │ │ ├── demo-twitter-secret.yaml │ │ │ │ ├── pubsub.yaml │ │ │ │ ├── statestore.yaml │ │ │ │ └── twitter.yaml │ │ │ └── values.yaml │ │ └── zipkin │ │ │ ├── .helmignore │ │ │ ├── Chart.yaml │ │ │ ├── templates │ │ │ ├── tracing.yaml │ │ │ └── zipkin.yaml │ │ │ └── values.yaml │ └── local │ │ ├── pubsub.yaml │ │ ├── secretstore.yaml │ │ ├── statestore.yaml │ │ └── twitter.yaml ├── demo.ps1 ├── deploy │ ├── azure │ │ ├── devops.bicep │ │ └── main.bicep │ └── local │ │ ├── devops.bicep │ │ └── main.bicep └── src │ ├── csharp_processor │ ├── Dockerfile │ ├── Program.cs │ ├── Properties │ │ └── launchSettings.json │ ├── appsettings.Development.json │ ├── appsettings.json │ ├── charts │ │ └── processor │ │ │ ├── .helmignore │ │ │ ├── Chart.yaml │ │ │ ├── templates │ │ │ └── processor.yaml │ │ │ └── values.yaml │ └── processor.csproj │ ├── csharp_provider │ ├── Dockerfile │ ├── Program.cs │ ├── Properties │ │ └── launchSettings.json │ ├── appsettings.Development.json │ ├── appsettings.json │ ├── charts │ │ └── provider │ │ │ ├── Chart.yaml │ │ │ ├── templates │ │ │ └── provider.yaml │ │ │ └── values.yaml │ └── provider.csproj │ ├── csharp_viewer │ ├── Controllers │ │ └── TweetController.cs │ ├── Dockerfile │ ├── Hubs │ │ └── TweetHub.cs │ ├── Pages │ │ ├── Error.cshtml │ │ ├── Error.cshtml.cs │ │ ├── Index.cshtml │ │ ├── Index.cshtml.cs │ │ ├── Privacy.cshtml │ │ ├── Privacy.cshtml.cs │ │ ├── Shared │ │ │ ├── _Layout.cshtml │ │ │ └── _ValidationScriptsPartial.cshtml │ │ ├── _ViewImports.cshtml │ │ └── _ViewStart.cshtml │ ├── Program.cs │ ├── Properties │ │ └── launchSettings.json │ ├── appsettings.Development.json │ ├── appsettings.json │ ├── charts │ │ └── viewer │ │ │ ├── .helmignore │ │ │ ├── Chart.yaml │ │ │ ├── templates │ │ │ └── viewer.yaml │ │ │ └── values.yaml │ ├── libman.json │ ├── viewer.csproj │ └── wwwroot │ │ ├── css │ │ └── site.css │ │ ├── favicon.ico │ │ ├── img │ │ ├── dapr.svg │ │ ├── negative.svg │ │ ├── neutral.svg │ │ ├── positive.svg │ │ ├── tw.svg │ │ └── unknown.svg │ │ ├── js │ │ ├── signalr │ │ │ └── dist │ │ │ │ └── browser │ │ │ │ └── signalr.min.js │ │ ├── site.js │ │ └── tweet.js │ │ └── lib │ │ ├── bootstrap │ │ ├── LICENSE │ │ └── dist │ │ │ ├── css │ │ │ ├── bootstrap-grid.css │ │ │ ├── bootstrap-grid.css.map │ │ │ ├── bootstrap-grid.min.css │ │ │ ├── bootstrap-grid.min.css.map │ │ │ ├── bootstrap-reboot.css │ │ │ ├── bootstrap-reboot.css.map │ │ │ ├── bootstrap-reboot.min.css │ │ │ ├── bootstrap-reboot.min.css.map │ │ │ ├── bootstrap.css │ │ │ ├── bootstrap.css.map │ │ │ ├── bootstrap.min.css │ │ │ └── bootstrap.min.css.map │ │ │ └── js │ │ │ ├── bootstrap.bundle.js │ │ │ ├── bootstrap.bundle.js.map │ │ │ ├── bootstrap.bundle.min.js │ │ │ ├── bootstrap.bundle.min.js.map │ │ │ ├── bootstrap.js │ │ │ ├── bootstrap.js.map │ │ │ ├── bootstrap.min.js │ │ │ └── bootstrap.min.js.map │ │ ├── jquery-validation-unobtrusive │ │ ├── LICENSE.txt │ │ ├── jquery.validate.unobtrusive.js │ │ └── jquery.validate.unobtrusive.min.js │ │ ├── jquery-validation │ │ ├── LICENSE.md │ │ └── dist │ │ │ ├── additional-methods.js │ │ │ ├── additional-methods.min.js │ │ │ ├── jquery.validate.js │ │ │ └── jquery.validate.min.js │ │ └── jquery │ │ ├── LICENSE.txt │ │ └── dist │ │ ├── jquery.js │ │ ├── jquery.min.js │ │ └── jquery.min.map │ ├── java_viewer │ ├── .gitignore │ ├── Dockerfile │ ├── pom.xml │ └── src │ │ └── main │ │ ├── java │ │ └── io │ │ │ └── dapr │ │ │ └── apps │ │ │ └── twitter │ │ │ └── viewer │ │ │ ├── Application.java │ │ │ ├── ApplicationController.java │ │ │ ├── SocketTextHandler.java │ │ │ ├── WebSocketConfig.java │ │ │ └── WebSocketPubSub.java │ │ └── resources │ │ ├── application.properties │ │ └── static │ │ ├── css │ │ └── app.css │ │ ├── img │ │ ├── dapr.svg │ │ ├── favicon.ico │ │ ├── negative.svg │ │ ├── neutral.svg │ │ ├── positive.svg │ │ ├── tw.svg │ │ └── unknown.svg │ │ ├── index.html │ │ └── js │ │ └── app.js │ ├── python_provider │ ├── provider.py │ └── requirements.txt │ ├── twitter.sln │ ├── tye_cloud.yaml │ ├── tye_local.yaml │ └── tye_multi.yaml ├── MyApp ├── .gitignore ├── .scripts │ ├── Deploy-AWSInfrastructure.ps1 │ └── Deploy-AzureInfrastructure.ps1 ├── README.md ├── cleanUp.ps1 ├── components │ ├── aws │ │ ├── pubsub.yaml │ │ ├── pubsub_subscription.yaml │ │ ├── secretstore.yaml │ │ └── state.aws.dynamodb.yaml │ ├── azure │ │ ├── secretstore.yaml │ │ ├── servicebus.yaml │ │ ├── servicebus_subscription.yaml │ │ └── statestore.yaml │ └── local │ │ ├── pubsub.yaml │ │ └── statestore.yaml ├── demo.ps1 ├── deploy │ ├── aws │ │ ├── main.tf │ │ └── variables.tf │ └── azure │ │ ├── main.bicep │ │ └── myapp.bicep └── sampleRequests.http ├── Observability ├── .gitignore ├── .scripts │ └── Deploy-AzureInfrastructure.ps1 ├── .vscode │ ├── launch.json │ └── tasks.json ├── README.md ├── cleanUp.ps1 ├── config │ └── azure │ │ └── otel-local-config.yaml ├── demo.ps1 ├── deploy │ └── azure │ │ ├── main.bicep │ │ └── observability.bicep ├── sampleRequests.http └── src │ ├── serviceA │ ├── Program.cs │ ├── appsettings.Development.json │ ├── appsettings.json │ └── serviceA.csproj │ ├── serviceB │ ├── Program.cs │ ├── appsettings.Development.json │ ├── appsettings.json │ └── serviceB.csproj │ ├── serviceC │ ├── Program.cs │ ├── appsettings.Development.json │ ├── appsettings.json │ └── serviceC.csproj │ ├── services.sln │ ├── tye_cloud.yaml │ └── tye_local.yaml ├── PubSub ├── .gitignore ├── .scripts │ ├── Deploy-AWSInfrastructure.ps1 │ └── Deploy-AzureInfrastructure.ps1 ├── .vscode │ ├── launch.json │ └── tasks.json ├── README.md ├── cleanUp.ps1 ├── components │ ├── aws │ │ ├── pubsub1.yaml │ │ ├── pubsub1_subscription.yaml │ │ ├── pubsub2.yaml │ │ ├── pubsub2_subscription.yaml │ │ ├── secretstore.yaml │ │ └── state.aws.dynamodb.yaml │ ├── azure │ │ ├── eventhubs.yaml │ │ ├── eventhubs_subscription.yaml │ │ ├── secretstore.yaml │ │ ├── servicebus.yaml │ │ ├── servicebus_subscription.yaml │ │ └── statestore.yaml │ └── local │ │ ├── pubsub1.yaml │ │ ├── pubsub1_subscription.yaml │ │ ├── pubsub2.yaml │ │ ├── pubsub2_subscription.yaml │ │ └── statestore.yaml ├── demo.ps1 ├── deploy │ ├── aws │ │ ├── main.tf │ │ └── variables.tf │ └── azure │ │ ├── main.bicep │ │ └── pubsub.bicep ├── sampleRequests.http └── src │ ├── Program.cs │ ├── Properties │ └── launchSettings.json │ ├── appsettings.Development.json │ ├── appsettings.json │ └── src.csproj ├── README.md ├── Secrets ├── .scripts │ ├── Deploy-AWSInfrastructure.ps1 │ └── Deploy-AzureInfrastructure.ps1 ├── README.md ├── cleanUp.ps1 ├── components │ ├── aws │ │ ├── secret.aws.secrets.manager.yaml │ │ └── secretstore.yaml │ ├── azure │ │ ├── secretstore.yaml │ │ └── strongbox.yaml │ └── local │ │ ├── local_secrets.json │ │ └── secretstore.yaml ├── demo.ps1 ├── deploy │ ├── aws │ │ ├── main.tf │ │ └── variables.tf │ └── azure │ │ ├── main.bicep │ │ └── secrets.bicep └── sampleRequests.http ├── StateStore ├── .scripts │ ├── Deploy-AWSInfrastructure.ps1 │ └── Deploy-AzureInfrastructure.ps1 ├── README.md ├── cleanUp.ps1 ├── components │ ├── aws │ │ └── state.aws.dynamodb.yaml │ ├── azure │ │ ├── secretstores.local.file.yaml │ │ └── state.azure.cosmosdb.yaml │ └── local │ │ └── state.redis.yaml ├── demo.ps1 ├── deploy │ ├── aws │ │ ├── main.tf │ │ └── variables.tf │ └── azure │ │ ├── main.bicep │ │ └── stateStore.bicep └── sampleRequests.http ├── default.code-workspace ├── demo_binding.code-workspace ├── demo_devops.code-workspace ├── demo_myapp.code-workspace ├── demo_observability.code-workspace ├── demo_pubsub.code-workspace ├── demo_secrets.code-workspace └── demo_statestore.code-workspace /.devcontainer/Dockerfile: -------------------------------------------------------------------------------- 1 | # Note: You can use any Debian/Ubuntu based image you want. 2 | FROM mcr.microsoft.com/vscode/devcontainers/base:bullseye 3 | 4 | # [Option] Install zsh 5 | ARG INSTALL_ZSH="true" 6 | # [Option] Upgrade OS packages to their latest versions 7 | ARG UPGRADE_PACKAGES="false" 8 | # [Option] Enable non-root Docker access in container 9 | ARG ENABLE_NONROOT_DOCKER="true" 10 | # [Option] Use the OSS Moby Engine instead of the licensed Docker Engine 11 | ARG USE_MOBY="true" 12 | # [Option] Engine/CLI Version 13 | ARG DOCKER_VERSION="latest" 14 | 15 | # Enable new "BUILDKIT" mode for Docker CLI 16 | ENV DOCKER_BUILDKIT=1 17 | 18 | # Install needed packages and setup non-root user. Use a separate RUN statement to add your 19 | # own dependencies. A user of "automatic" attempts to reuse an user ID if one already exists. 20 | ARG USERNAME=automatic 21 | ARG USER_UID=1000 22 | ARG USER_GID=$USER_UID 23 | COPY library-scripts/*.sh /tmp/library-scripts/ 24 | RUN apt-get update \ 25 | && /bin/bash /tmp/library-scripts/common-debian.sh "${INSTALL_ZSH}" "${USERNAME}" "${USER_UID}" "${USER_GID}" "${UPGRADE_PACKAGES}" "true" "true" \ 26 | # Use Docker script from script library to set things up 27 | && /bin/bash /tmp/library-scripts/docker-in-docker-debian.sh "${ENABLE_NONROOT_DOCKER}" "${USERNAME}" "${USE_MOBY}" "${DOCKER_VERSION}" 28 | 29 | RUN /bin/bash /tmp/library-scripts/dev-tools-debian.sh 30 | 31 | RUN /bin/bash /tmp/library-scripts/powershell-debian.sh 32 | 33 | RUN /bin/bash /tmp/library-scripts/cloud-clis-debian.sh \ 34 | # Clean up 35 | && apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/* /tmp/library-scripts/ 36 | 37 | ENV JAVA_HOME="/jdk-11.0.11+9/" 38 | ENV PATH="${PATH}:/apache-maven-3.8.6/bin:/jdk-11.0.11+9/bin" 39 | 40 | VOLUME [ "/var/lib/docker" ] 41 | 42 | # Setting the ENTRYPOINT to docker-init.sh will start up the Docker Engine 43 | # inside the container "overrideCommand": false is set in devcontainer.json. 44 | # The script will also execute CMD if you need to alter startup behaviors. 45 | ENTRYPOINT [ "/usr/local/share/docker-init.sh" ] 46 | CMD [ "sleep", "infinity" ] 47 | 48 | # [Optional] Uncomment this section to install additional OS packages. 49 | # RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ 50 | # && apt-get -y install --no-install-recommends -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | // For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: 2 | // https://github.com/microsoft/vscode-dev-containers/tree/v0.202.3/containers/alpine 3 | { 4 | "name": "MyDaprDemos", 5 | "image": "darquewarrior/daprdevcontainer:0.0.11", 6 | //"dockerFile": "./Dockerfile", 7 | "remoteEnv": { 8 | "PATH": "${containerEnv:PATH}:/home/codespace/.dapr/bin" 9 | }, 10 | // Set *default* container specific settings.json values on container create. 11 | "settings": { 12 | "editor.minimap.enabled": false, 13 | "workbench.startupEditor": "none", 14 | "terminal.integrated.defaultProfile.linux": "pwsh" 15 | }, 16 | // Add the IDs of extensions you want installed when the container is created. 17 | // Note that some extensions may not work in Alpine Linux. See https://aka.ms/vscode-remote/linux. 18 | "extensions": [ 19 | "doggy8088.netcore-snippets", 20 | "ms-azuretools.vscode-dapr", 21 | "GitHub.vscode-pull-request-github", 22 | "ms-azuretools.vscode-docker", 23 | "humao.rest-client", 24 | "ms-azuretools.vscode-bicep", 25 | "ms-vscode.PowerShell", 26 | "cweijan.vscode-redis-client", 27 | "ms-dotnettools.csharp", 28 | "hookyqr.beautify", 29 | "simonsiefke.prettier-vscode", 30 | "streetsidesoftware.code-spell-checker", 31 | "ms-azuretools.vscode-tye", 32 | "ms-kubernetes-tools.vscode-kubernetes-tools", 33 | "HashiCorp.terraform", 34 | "vscjava.vscode-java-pack", 35 | "ms-python.python", 36 | "mindaro.mindaro" 37 | ], 38 | // Use 'forwardPorts' to make a list of ports inside the container available locally. 39 | "forwardPorts": [ 40 | 8000, 41 | 9411, 42 | 30000, 43 | 30001 44 | ], 45 | // add labels 46 | "portsAttributes": { 47 | "6379": { 48 | "label": "dapr_Redis" 49 | }, 50 | "6443": { 51 | "label": "k3d_Api" 52 | }, 53 | "8000": { 54 | "label": "Tye" 55 | }, 56 | "9411": { 57 | "label": "dapr_Zipkin" 58 | }, 59 | "30000": { 60 | "label": "k3d-Demo" 61 | }, 62 | "30001": { 63 | "label": "k3d-Zipkin" 64 | }, 65 | "50005": { 66 | "label": "dapr_Placement" 67 | } 68 | }, 69 | // Use 'postCreateCommand' to run commands after the container is created. 70 | // "postCreateCommand": "uname -a", 71 | // Replace when using a ptrace-based debugger like C++, Go, and Rust 72 | // "runArgs": [ "--init", "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined" ], 73 | "runArgs": [ 74 | "--init", 75 | "--privileged" 76 | ], 77 | "mounts": [ 78 | "source=dind-var-lib-docker,target=/var/lib/docker,type=volume" 79 | ], 80 | "overrideCommand": false, 81 | // Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. 82 | "remoteUser": "vscode", 83 | // Use 'onCreateCommand' to run commands as part of container creation. 84 | "onCreateCommand": "/bin/bash -c .devcontainer/on-create.sh", 85 | } -------------------------------------------------------------------------------- /.devcontainer/library-scripts/cloud-clis-debian.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Install AZ CLI 4 | curl -sL https://aka.ms/InstallAzureCLIDeb | /bin/bash 5 | 6 | # Install aws CLI 7 | curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" 8 | unzip awscliv2.zip 9 | ./aws/install 10 | rm -f awscliv2.zip 11 | 12 | # Install gcloud CLI 13 | echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] http://packages.cloud.google.com/apt cloud-sdk main" | tee -a /etc/apt/sources.list.d/google-cloud-sdk.list 14 | curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key --keyring /usr/share/keyrings/cloud.google.gpg add - 15 | 16 | apt-get update 17 | 18 | apt-get install google-cloud-sdk -y 19 | -------------------------------------------------------------------------------- /.devcontainer/library-scripts/dev-tools-debian.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | wget https://packages.microsoft.com/config/ubuntu/22.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb 4 | sudo dpkg -i packages-microsoft-prod.deb 5 | rm packages-microsoft-prod.deb 6 | 7 | apt-get update 8 | 9 | # Install .net 6 10 | apt-get install -y software-properties-common apt-transport-https gnupg2 dotnet-sdk-6.0 11 | 12 | dotnet tool install --tool-path /bin Microsoft.Tye --version "0.11.0-alpha.22111.1" 13 | 14 | # Install Dapr CLI 15 | wget -q https://raw.githubusercontent.com/dapr/cli/master/install/install.sh -O - | /bin/bash 16 | 17 | # Install K3d CLI 18 | wget -q https://raw.githubusercontent.com/rancher/k3d/main/install.sh -O - | /bin/bash 19 | 20 | curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - 21 | echo "deb https://apt.kubernetes.io/ kubernetes-xenial main" | tee -a /etc/apt/sources.list.d/kubernetes.list 22 | curl -fsSL https://apt.releases.hashicorp.com/gpg | apt-key add - 23 | apt-add-repository "deb [arch=$(dpkg --print-architecture)] https://apt.releases.hashicorp.com $(lsb_release -cs) main" 24 | apt-get update 25 | 26 | # Install kubectl 27 | apt-get install -y kubectl 28 | 29 | # Install Helm 30 | wget -q https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 -O - | /bin/bash 31 | 32 | # Install terraform 33 | apt-get install -y terraform 34 | 35 | # Install Microsoft Open SDK 36 | wget https://aka.ms/download-jdk/microsoft-jdk-11.0.11.9.1-linux-x64.tar.gz -O msopenjdk11.tar.gz && \ 37 | tar zxvf msopenjdk11.tar.gz && \ 38 | rm -rf msopenjdk11.tar.gz /var/lib/apt/lists/* 39 | 40 | # Install Maven 41 | wget https://dlcdn.apache.org/maven/maven-3/3.8.6/binaries/apache-maven-3.8.6-bin.tar.gz -O maven.tar.gz && \ 42 | tar zxvf maven.tar.gz && \ 43 | rm -rf maven.tar.gz /var/lib/apt/lists/* 44 | 45 | # Install PIP3 46 | apt-get update 47 | apt-get install -y python3-pip -------------------------------------------------------------------------------- /.devcontainer/library-scripts/powershell-debian.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | wget https://github.com/PowerShell/PowerShell/releases/download/v7.2.6/powershell-lts_7.2.6-1.deb_amd64.deb 4 | 5 | dpkg -i powershell-lts_7.2.6-1.deb_amd64.deb 6 | 7 | rm ./powershell-lts_7.2.6-1.deb_amd64.deb -------------------------------------------------------------------------------- /.devcontainer/on-create.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "on-create start" >> ~/status 4 | 5 | # create local registry 6 | docker network create k3d 7 | k3d registry create registry.localhost --port 5500 8 | docker network connect k3d k3d-registry.localhost 9 | 10 | # create cluster using network and registry 11 | k3d cluster create demo-cluster --registry-use k3d-registry.localhost:5500 --network k3d --api-port 6443 -p 30000-30001:30000-30001@server:0 12 | 13 | # initialize dapr 14 | dapr init 15 | 16 | # initialize dapr in K8s 17 | dapr init -k 18 | 19 | ### Azure 20 | # log into azure cli 21 | az login --service-principal -t $AZURE_TENANT -u $AZURE_APP_ID -p $AZURE_PASSWORD 22 | 23 | # set the subscription 24 | az account set -s $AZURE_SUB_ID 25 | 26 | # set defaults 27 | az config set core.output=table 28 | 29 | ### AWS 30 | # set output to table 31 | aws configure set output table 32 | 33 | # install PowerShell modules 34 | pwsh -Command "& {Install-Module -Name Trackyon.Utils, powershell-yaml -Force}" 35 | 36 | echo "on-create complete" >> ~/status -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/*.env 2 | **/local_secrets.json 3 | **/tempfiles/* 4 | **/local.yaml 5 | **/.terraform 6 | **/terraform.tfvars 7 | **/terraform.tfstate 8 | **/terraform.tfstate.backup 9 | **/.terraform.lock.hcl 10 | **/terraform.tfstate 11 | -------------------------------------------------------------------------------- /.images/ActionsSecrets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarqueWarrior/MyDaprDemos/f84b38eba203c23075eac2037b3994ab9c9928b1/.images/ActionsSecrets.png -------------------------------------------------------------------------------- /.images/CodespaceSecrets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarqueWarrior/MyDaprDemos/f84b38eba203c23075eac2037b3994ab9c9928b1/.images/CodespaceSecrets.png -------------------------------------------------------------------------------- /.images/DebugPane.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarqueWarrior/MyDaprDemos/f84b38eba203c23075eac2037b3994ab9c9928b1/.images/DebugPane.png -------------------------------------------------------------------------------- /.images/DevOpsAppOverview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarqueWarrior/MyDaprDemos/f84b38eba203c23075eac2037b3994ab9c9928b1/.images/DevOpsAppOverview.png -------------------------------------------------------------------------------- /.images/OpenWorkspace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarqueWarrior/MyDaprDemos/f84b38eba203c23075eac2037b3994ab9c9928b1/.images/OpenWorkspace.png -------------------------------------------------------------------------------- /.images/OpenWorkspaceFileMenu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarqueWarrior/MyDaprDemos/f84b38eba203c23075eac2037b3994ab9c9928b1/.images/OpenWorkspaceFileMenu.png -------------------------------------------------------------------------------- /.images/RunWorkflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarqueWarrior/MyDaprDemos/f84b38eba203c23075eac2037b3994ab9c9928b1/.images/RunWorkflow.png -------------------------------------------------------------------------------- /.images/SendRequest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarqueWarrior/MyDaprDemos/f84b38eba203c23075eac2037b3994ab9c9928b1/.images/SendRequest.png -------------------------------------------------------------------------------- /.images/Services.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarqueWarrior/MyDaprDemos/f84b38eba203c23075eac2037b3994ab9c9928b1/.images/Services.png -------------------------------------------------------------------------------- /.images/Zipkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarqueWarrior/MyDaprDemos/f84b38eba203c23075eac2037b3994ab9c9928b1/.images/Zipkin.png -------------------------------------------------------------------------------- /.scripts/cleanUpAll.ps1: -------------------------------------------------------------------------------- 1 | # This will call cleanUp of every demo. 2 | 3 | [CmdletBinding()] 4 | param ( 5 | [switch] 6 | $Force 7 | ) 8 | 9 | . ./demos.ps1 10 | 11 | foreach ($demo in $demos) { 12 | Write-Host "*******************************************" 13 | Write-Host "Cleaning up $demo" 14 | Write-Host "*******************************************" 15 | 16 | Push-Location "../$demo" 17 | ./cleanUp.ps1 -force:$Force 18 | Pop-Location 19 | } -------------------------------------------------------------------------------- /.scripts/demos.ps1: -------------------------------------------------------------------------------- 1 | $demos = @('Binding', 'Observability', 'PubSub', 'Secrets', 'StateStore', 'MyApp', 'DevOps') -------------------------------------------------------------------------------- /.scripts/deployAll.ps1: -------------------------------------------------------------------------------- 1 | # This will call setup of every demo. 2 | 3 | [CmdletBinding()] 4 | param () 5 | 6 | . ./demos.ps1 7 | 8 | foreach ($demo in $demos) { 9 | Write-Host "*******************************************" 10 | Write-Host "Setting up $demo" 11 | Write-Host "*******************************************" 12 | 13 | Push-Location "../$demo" 14 | ./demo.ps1 -deployOnly 15 | Pop-Location 16 | } -------------------------------------------------------------------------------- /Binding/.scripts/Deploy-AWSInfrastructure.ps1: -------------------------------------------------------------------------------- 1 | function Deploy-AWSInfrastructure { 2 | [CmdletBinding()] 3 | param () 4 | 5 | begin { 6 | Push-Location -Path './deploy/aws' 7 | } 8 | 9 | process { 10 | Deploy-AWS 11 | } 12 | 13 | end { 14 | Pop-Location 15 | } 16 | } -------------------------------------------------------------------------------- /Binding/.scripts/Deploy-AzureInfrastructure.ps1: -------------------------------------------------------------------------------- 1 | # This function will run an bicep deployment to deploy all the required 2 | # resources into Azure. All the keys, tokens and endpoints will be 3 | # automatically retreived and written to ./components/azure/local_secrets.json. 4 | # PowerShell Core 7 (runs on macOS, Linux and Windows) 5 | # Azure CLI (log in, runs on macOS, Linux and Windows) 6 | function Deploy-AzureInfrastructure { 7 | [CmdletBinding()] 8 | param ( 9 | [Parameter( 10 | Position = 0, 11 | HelpMessage = "The name of the resource group to be created. All resources will be place in the resource group and start with name." 12 | )] 13 | [string] 14 | $rgName, 15 | 16 | [Parameter( 17 | Position = 1, 18 | HelpMessage = "The location to store the meta data for the deployment." 19 | )] 20 | [string] 21 | $location 22 | ) 23 | 24 | begin { 25 | Push-Location -Path './deploy' 26 | } 27 | 28 | process { 29 | Write-Output 'Deploying the infrastructure' 30 | $deployment = $(az deployment sub create --name $rgName ` 31 | --location $location ` 32 | --template-file ./azure/main.bicep ` 33 | --parameters location=$location ` 34 | --parameters rgName=$rgName ` 35 | --output json) | ConvertFrom-Json 36 | 37 | # Store the outputs from the deployment to create 38 | # ./components/azure/local_secrets.json 39 | $storageAccountName = $deployment.properties.outputs.storageAccountName.value 40 | 41 | $storageAccountKey = $(az storage account keys list ` 42 | --account-name $storageAccountName ` 43 | --query [0].value ` 44 | --output tsv) 45 | 46 | Write-Verbose "storageAccountKey = $storageAccountKey" 47 | Write-Verbose "storageAccountName = $storageAccountName" 48 | 49 | # Creating components/azure/local_secrets.json 50 | $secrets = [PSCustomObject]@{ 51 | key = $storageAccountKey 52 | acct = $storageAccountName 53 | } 54 | 55 | Write-Output 'Saving ./components/azure/local_secrets.json for local secret store' 56 | $secrets | ConvertTo-Json | Set-Content ../components/azure/local_secrets.json 57 | } 58 | 59 | end { 60 | Pop-Location 61 | } 62 | } -------------------------------------------------------------------------------- /Binding/README.md: -------------------------------------------------------------------------------- 1 | # Binding demo 2 | 3 | The purpose of this demo is to show the use of [binding components](https://docs.dapr.io/developing-applications/building-blocks/bindings/) locally and in the cloud. 4 | 5 | Open the _demo_binding.code-workspace_ file and click the **Open Workspace** button in the lower right corner. This will reload your Codespace and scope your **Explorer** to just the folders needed for this demo. 6 | 7 | To provision the infrastructure before the demo execute the following command in the terminal. 8 | 9 | ``` 10 | ./demo.ps1 -env azure -deployOnly 11 | ``` 12 | 13 | This code is automatically run by the _demo.ps1_ script if the `-env azure` parameter is passed and *./components/azure/local_secrets.json* file is not found. 14 | 15 | The workspace consists of one top level folder _Binding_. This folder contains the _components_, _deploy_, and _tempfiles_ folders. The _components_ folder contains an _azure_ and _local_ folder so you can show the difference between a local component and a component configured for the cloud. The component in the _components/azure_ folder is configured to use [Azure Blob Storage](https://docs.dapr.io/reference/components-reference/supported-bindings/blobstorage/). In the _components/aws_ folder the component is configured to use AWS S3 and the local component is configured to use local file storage. The point to make comparing the files is that as long as the name of the component (in our demo "files") does not change the code will work no matter what backing service is used. 16 | 17 | The core of the demo is in the _sampleRequests.http_ file. **Do not change this file.** To run the demos use the _demo.ps1_ file. It will update the _sampleRequests.http_ for running locally or in the cloud for you. At the top of the file are three _demo.ps1_ commands. One for running the requests against local resources and two for running against the cloud resources. Copy the desired command and run it in the terminal. This will start Dapr pointing to the appropriate components for the demo. The Dapr run command issued is output if you want to explain during the demo. 18 | 19 | Running local 20 | ``` 21 | ./demo.ps1 22 | ``` 23 | 24 | Running in Azure 25 | ``` 26 | ./demo.ps1 -env azure 27 | ``` 28 | 29 | Running in AWS 30 | ``` 31 | ./demo.ps1 -env aws 32 | ``` 33 | 34 | Click the Send Request button above each of the requests to execute them. 35 | 36 | ![send requests](../.images/SendRequest.png) 37 | 38 | When running locally you can expand the _tempfiles_ folder to show the data being stored and deleted. When running in the cloud use the portal to show the data being stored and deleted. 39 | 40 | When you are done with the demo you can clean up the cloud resources by running the _cleanUp.ps1_ script using the following commands: 41 | 42 | ``` 43 | ./cleanUp.ps1 44 | ``` -------------------------------------------------------------------------------- /Binding/cleanUp.ps1: -------------------------------------------------------------------------------- 1 | # This will start the deletion of a resource group but not wait. 2 | 3 | [CmdletBinding()] 4 | param ( 5 | [Parameter( 6 | Position = 0, 7 | HelpMessage = "The name of the resource group to be created. All resources will be place in the resource group and start with name." 8 | )] 9 | [string] 10 | $rgName = "dapr_binding_demo", 11 | 12 | [Parameter( 13 | HelpMessage = "Set to the location of the resources to use." 14 | )] 15 | [ValidateSet("all", "local", "azure", "aws")] 16 | [string] 17 | $env = "all", 18 | 19 | [switch] 20 | $force 21 | ) 22 | 23 | . "../.scripts/common.ps1" 24 | 25 | # Put the sampleRequests.http file back the way it was 26 | git restore ./sampleRequests.http 27 | 28 | if ($env -eq 'all' -or $env -eq 'local') { 29 | # Remove the myTestFile.txt 30 | Remove-Item ./tempfiles/myTestFile.txt -ErrorAction SilentlyContinue 31 | } 32 | 33 | if ($env -eq 'all' -or $env -eq 'azure') { 34 | # Remove local_secrets.json 35 | Remove-Item ./components/azure/local_secrets.json -ErrorAction SilentlyContinue 36 | 37 | Remove-ResourceGroup -name $rgName -force:$force -nowait 38 | } 39 | 40 | if ($env -eq 'all' -or $env -eq 'aws') { 41 | ### AWS 42 | Remove-AWS 43 | } -------------------------------------------------------------------------------- /Binding/components/aws/binding.aws.s3.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: files 5 | auth: 6 | secretStore: strongbox 7 | spec: 8 | type: bindings.aws.s3 9 | version: v1 10 | metadata: 11 | - name: bucket 12 | value: dapr-bucket 13 | - name: region 14 | value: us-east-2 15 | - name: accessKey 16 | secretKeyRef: 17 | key: accessKey 18 | name: accessKey 19 | - name: secretKey 20 | secretKeyRef: 21 | key: secretKey 22 | name: secretKey 23 | -------------------------------------------------------------------------------- /Binding/components/aws/secretstore.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: strongbox 5 | spec: 6 | type: secretstores.local.file 7 | version: v1 8 | metadata: 9 | - name: secretsFile 10 | value: "./components/aws/local_secrets.json" -------------------------------------------------------------------------------- /Binding/components/azure/azurestorage.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: files 5 | auth: 6 | secretStore: strongbox 7 | spec: 8 | type: bindings.azure.blobstorage 9 | version: v1 10 | metadata: 11 | - name: storageAccount 12 | secretKeyRef: 13 | key: acct 14 | name: acct 15 | - name: storageAccessKey 16 | secretKeyRef: 17 | key: key 18 | name: key 19 | - name: container 20 | value: container1 21 | - name: decodeBase64 22 | value: false 23 | - name: getBlobRetryCount 24 | value: 3 -------------------------------------------------------------------------------- /Binding/components/azure/secretstore.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: strongbox 5 | spec: 6 | type: secretstores.local.file 7 | version: v1 8 | metadata: 9 | - name: secretsFile 10 | value: "./components/azure/local_secrets.json" -------------------------------------------------------------------------------- /Binding/components/local/localstorage.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: files 5 | spec: 6 | type: bindings.localstorage 7 | version: v1 8 | metadata: 9 | - name: rootPath 10 | value: "./tempfiles/" -------------------------------------------------------------------------------- /Binding/deploy/aws/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = var.region 3 | access_key = var.access_key 4 | secret_key = var.secret_key 5 | } 6 | 7 | resource "aws_s3_bucket" "dapr_binding" { 8 | bucket = var.bucket_name 9 | 10 | tags = { 11 | Name = "Dapr Binding Bucket" 12 | environment = "${var.environment}" 13 | } 14 | } 15 | 16 | resource "aws_s3_bucket_acl" "private_acl" { 17 | bucket = aws_s3_bucket.dapr_binding.id 18 | acl = "private" 19 | } 20 | -------------------------------------------------------------------------------- /Binding/deploy/aws/variables.tf: -------------------------------------------------------------------------------- 1 | 2 | variable "access_key" { 3 | description = "Access key to AWS console" 4 | } 5 | 6 | variable "secret_key" { 7 | description = "Secret key to AWS console" 8 | } 9 | 10 | variable "region" { 11 | description = "The region to use to create the resource" 12 | default = "us-east-2" 13 | } 14 | 15 | variable "bucket_name" { 16 | description = "S3 bucket name (space is not allowed)" 17 | default = "dapr-bucket" 18 | } 19 | 20 | variable "environment" { 21 | description = "Name of environment" 22 | default = "codespace" 23 | } 24 | -------------------------------------------------------------------------------- /Binding/deploy/azure/binding.bicep: -------------------------------------------------------------------------------- 1 | param location string 2 | 3 | resource stg 'Microsoft.Storage/storageAccounts@2019-06-01' = { 4 | name: toLower('stg${uniqueString(resourceGroup().id)}') // must be globally unique 5 | location: location 6 | kind: 'Storage' 7 | sku: { 8 | name: 'Standard_LRS' 9 | } 10 | } 11 | 12 | output storageAccountName string = stg.name 13 | -------------------------------------------------------------------------------- /Binding/deploy/azure/main.bicep: -------------------------------------------------------------------------------- 1 | targetScope = 'subscription' 2 | 3 | param location string = 'eastus' 4 | param rgName string = 'dapr_binding_demo' 5 | 6 | resource rg 'Microsoft.Resources/resourceGroups@2021-04-01' = { 7 | name: rgName 8 | location: location 9 | } 10 | 11 | module binding './binding.bicep' = { 12 | name: 'binding' 13 | scope: resourceGroup(rg.name) 14 | params: { 15 | location: location 16 | } 17 | } 18 | 19 | output storageAccountName string = binding.outputs.storageAccountName 20 | -------------------------------------------------------------------------------- /Binding/sampleRequests.http: -------------------------------------------------------------------------------- 1 | # Use this command to run local 2 | # Use fileName for item name 3 | # ./demo.ps1 4 | @itemName = fileName 5 | 6 | # Use this command to run in azure 7 | # Use blobName for item name 8 | # ./demo.ps1 -env azure 9 | # @itemName = blobName 10 | 11 | # Use this command to run in aws 12 | # Use key for item name 13 | # ./demo.ps1 -env aws 14 | # @itemName = key 15 | 16 | POST http://localhost:3500/v1.0/bindings/files 17 | 18 | { 19 | "operation": "create", 20 | "data": "Hello World", 21 | "metadata": { 22 | "{{itemName}}": "myTestFile.txt" 23 | } 24 | } 25 | 26 | ### 27 | 28 | POST http://localhost:3500/v1.0/bindings/files 29 | 30 | { 31 | "operation": "list" 32 | } 33 | 34 | ### 35 | 36 | POST http://localhost:3500/v1.0/bindings/files 37 | 38 | { 39 | "operation": "get", 40 | "metadata": { 41 | "{{itemName}}": "myTestFile.txt" 42 | } 43 | } 44 | 45 | ### 46 | 47 | POST http://localhost:3500/v1.0/bindings/files/ 48 | 49 | { 50 | "operation": "delete", 51 | "metadata": { 52 | "{{itemName}}": "myTestFile.txt" 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Binding/tempfiles/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarqueWarrior/MyDaprDemos/f84b38eba203c23075eac2037b3994ab9c9928b1/Binding/tempfiles/.gitkeep -------------------------------------------------------------------------------- /DevOps/README.md: -------------------------------------------------------------------------------- 1 | # DevOps demo 2 | 3 | The purpose of this demo is to show: 4 | - how to deploy a Daprized application to a cloud based Kubernetes Service, using the [Dapr tool installer](https://github.com/marketplace/actions/dapr-tool-installer) GitHub Action 5 | - using Dapr with C#, Java, and Python 6 | - how to debug all three microservices at the same time across languages 7 | 8 | Open the _demo_devops.code-workspace_ file and click the **Open Workspace** button in the lower right corner. This will reload your Codespace and scope your Explorer to just the folders needed for this demo. 9 | 10 | To provision the infrastructure before the demo execute the following command in the terminal. This code is automatically run by the _demo.ps1_ script if the `-env` parameter is passed and *./components/local/local_secrets.json* file is not found. 11 | 12 | ``` 13 | ./demo.ps1 -deployOnly 14 | ``` 15 | 16 | The project is deployed to Kubernetes using Helm. Each service defines its own chart which is referenced in the Helm Chart defined in the top level _charts_ folder. When deployed to Kubernetes only the C# version of the services are deployed. 17 | 18 | ## Set Actions secrets 19 | 20 | For the GitHub Actions workflow to succeed you must configure the following secrets. These are **not** the CodeSpaces secrets you set earlier. These are set as _Repository secrets_. Review [Configure Azure credentials as GitHub Secret](https://github.com/marketplace/actions/azure-cli-action#configure-azure-credentials-as-github-secret) to set your **AZURE_CREDENTIALS** secret. 21 | 22 | ![codespace secrets](../.images/ActionsSecrets.png) 23 | 24 | Running this demo will deploy the application to a Kubernetes cluster or run locally using [Project Tye](https://github.com/dotnet/tye). To show the demo running use the _PORTS_ tab to Open port **5000** with running local or **k3d-Demo (30000)** when running with k8s in a browser. 25 | 26 | ## Running local 27 | ``` 28 | ./demo.ps1 -env K8s 29 | ``` 30 | 31 | ## Running in cloud 32 | 33 | From the GitHub repo navigate to the Actions tab and use the **Run workflow** button to trigger the workflow. This will deploy all the required infrastructure into Azure and deploy the app. 34 | 35 | ![codespace secrets](../.images/RunWorkflow.png) 36 | 37 | ## Debugging 38 | 39 | The _Multi_ launch configuration builds and runs the Java Viewer, Python Provider and CSharp Processor. You can set breakpoints in all three projects and debug all three at the same time. 40 | 41 | ## Clean Up 42 | When you are done with the demo you can clean up the cloud resources by running the _cleanUp.ps1_ script using the following commands: 43 | 44 | ``` 45 | ./cleanUp.ps1 46 | ``` -------------------------------------------------------------------------------- /DevOps/charts/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: twittersentimentprocessor 3 | description: Main chart for twitter sentiment processor demo 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. They're included as 11 | # a dependency of application charts to inject those utilities and functions into the rendering 12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 13 | type: application 14 | 15 | # This is the chart version. This version number should be incremented each time you make changes 16 | # to the chart and its templates, including the app version. 17 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 18 | version: 0.1.0 19 | 20 | # This is the version number of the application being deployed. This version number should be 21 | # incremented each time you make changes to the application. Versions are not expected to 22 | # follow Semantic Versioning. They should reflect the version the application is using. 23 | # It is recommended to use it with quotes. 24 | appVersion: "0.1.0" 25 | 26 | dependencies: 27 | - name: components 28 | version: 0.1.0 29 | repository: "file://../components/charts/components" 30 | - name: zipkin 31 | version: 0.1.0 32 | condition: enableZipkin 33 | repository: "file://../components/charts/zipkin" 34 | - name: appinsights 35 | version: 0.1.0 36 | condition: enableAppInsights 37 | repository: "file://../components/charts/appinsights" 38 | - name: processor 39 | version: 0.1.0 40 | repository: "file://../src/csharp_processor/charts/processor" 41 | - name: provider 42 | version: 0.1.0 43 | repository: "file://../src/csharp_provider/charts/provider" 44 | - name: viewer 45 | version: 0.1.0 46 | repository: "file://../src/csharp_viewer/charts/viewer" -------------------------------------------------------------------------------- /DevOps/charts/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | To end the demo run: 2 | 3 | helm uninstall {{ .Release.Name }} -------------------------------------------------------------------------------- /DevOps/charts/values.yaml: -------------------------------------------------------------------------------- 1 | components: 2 | serviceBus: 3 | connectionString: "" 4 | tableStorage: 5 | name: "" 6 | key: "" 7 | twitter: 8 | consumerKey: "" 9 | consumerSecret: "" 10 | accessToken: "" 11 | accessSecret: "" 12 | processor: 13 | cognitiveService: 14 | endpoint: "" 15 | 16 | enableZipkin: false 17 | enableAppInsights: false -------------------------------------------------------------------------------- /DevOps/cleanUp.ps1: -------------------------------------------------------------------------------- 1 | # This will start the deletion of a resource group but not wait. 2 | 3 | [CmdletBinding()] 4 | param ( 5 | [Parameter( 6 | Position = 0, 7 | HelpMessage = "The name of the resource group to be created. All resources will be place in the resource group and start with name." 8 | )] 9 | [string] 10 | $rgName = "dapr_devops_demo", 11 | 12 | [switch] 13 | $force 14 | ) 15 | 16 | . ../.scripts/common.ps1 17 | 18 | # Remove local_secrets.json 19 | Remove-Item ./charts/local.yaml -Force -ErrorAction SilentlyContinue 20 | Remove-Item ./charts/charts/ -Recurse -Force -ErrorAction SilentlyContinue 21 | Remove-Item ./components/local/local.env -Force -ErrorAction SilentlyContinue 22 | Remove-Item ./components/local/local_secrets.json -Force -ErrorAction SilentlyContinue 23 | 24 | Remove-ResourceGroup -name $rgName -force:$force 25 | 26 | Write-Output "Getting soft deleted cognitive services" 27 | $cs = $(az cognitiveservices account list-deleted --subscription $env:AZURE_SUB_ID --query [].name --output tsv) 28 | $loc = $(az cognitiveservices account list-deleted --subscription $env:AZURE_SUB_ID --query [].location --output tsv) 29 | 30 | if ($null -ne $cs) { 31 | Write-Output "Purging cognitive services $cs" 32 | az cognitiveservices account purge --subscription $env:AZURE_SUB_ID --name $cs --resource-group $rgName --location $loc 33 | } -------------------------------------------------------------------------------- /DevOps/components/charts/appinsights/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /DevOps/components/charts/appinsights/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: appinsights 3 | description: A Helm chart for Kubernetes that deploys a AppInsights for Twitter Sentiment Demo. 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. They're included as 11 | # a dependency of application charts to inject those utilities and functions into the rendering 12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 13 | type: application 14 | 15 | # This is the chart version. This version number should be incremented each time you make changes 16 | # to the chart and its templates, including the app version. 17 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 18 | version: 0.1.0 19 | 20 | # This is the version number of the application being deployed. This version number should be 21 | # incremented each time you make changes to the application. Versions are not expected to 22 | # follow Semantic Versioning. They should reflect the version the application is using. 23 | # It is recommended to use it with quotes. 24 | appVersion: "0.1.0" 25 | -------------------------------------------------------------------------------- /DevOps/components/charts/appinsights/templates/tracing.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Configuration 3 | metadata: 4 | name: tracing 5 | namespace: default 6 | spec: 7 | tracing: 8 | samplingRate: "1" 9 | zipkin: 10 | endpointAddress: {{ .Values.tracing.endpointAddress | quote }} -------------------------------------------------------------------------------- /DevOps/components/charts/appinsights/values.yaml: -------------------------------------------------------------------------------- 1 | tracing: 2 | endpointAddress: "http://otel-collector.default.svc.cluster.local:9411/api/v2/spans" 3 | 4 | zipkin: 5 | externalPort: 9411 6 | nodePort: 30001 7 | 8 | applicationInsights: 9 | instrumentationKey: "" -------------------------------------------------------------------------------- /DevOps/components/charts/components/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /DevOps/components/charts/components/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: components 3 | description: A Helm chart for Kubernetes that deploys a Dapr components for Twitter Sentiment Demo. 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. They're included as 11 | # a dependency of application charts to inject those utilities and functions into the rendering 12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 13 | type: application 14 | 15 | # This is the chart version. This version number should be incremented each time you make changes 16 | # to the chart and its templates, including the app version. 17 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 18 | version: 0.1.0 19 | 20 | # This is the version number of the application being deployed. This version number should be 21 | # incremented each time you make changes to the application. Versions are not expected to 22 | # follow Semantic Versioning. They should reflect the version the application is using. 23 | # It is recommended to use it with quotes. 24 | appVersion: "0.1.0" 25 | -------------------------------------------------------------------------------- /DevOps/components/charts/components/templates/demo-bus-secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: demo-bus-secret 5 | type: Opaque 6 | data: 7 | connection-string: {{ .Values.serviceBus.connectionString | b64enc }} -------------------------------------------------------------------------------- /DevOps/components/charts/components/templates/demo-processor-secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: demo-processor-secret 5 | type: Opaque 6 | data: 7 | token: {{ .Values.cognitiveService.token | b64enc }} 8 | endpoint: {{ .Values.cognitiveService.endpoint | b64enc }} -------------------------------------------------------------------------------- /DevOps/components/charts/components/templates/demo-state-secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: demo-state-secret 5 | type: Opaque 6 | data: 7 | account-key: {{ .Values.tableStorage.key | b64enc }} 8 | account-name: {{ .Values.tableStorage.name | b64enc }} -------------------------------------------------------------------------------- /DevOps/components/charts/components/templates/demo-twitter-secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: demo-twitter-secret 5 | type: Opaque 6 | data: 7 | consumerKey: {{ .Values.twitter.consumerKey | b64enc }} 8 | consumerSecret: {{ .Values.twitter.consumerSecret | b64enc }} 9 | accessToken: {{ .Values.twitter.accessToken | b64enc }} 10 | accessSecret: {{ .Values.twitter.accessSecret | b64enc }} -------------------------------------------------------------------------------- /DevOps/components/charts/components/templates/pubsub.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: pubsub 5 | spec: 6 | type: pubsub.azure.servicebus 7 | version: v1 8 | metadata: 9 | - name: connectionString 10 | secretKeyRef: 11 | name: demo-bus-secret 12 | key: connection-string -------------------------------------------------------------------------------- /DevOps/components/charts/components/templates/statestore.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: statestore 5 | spec: 6 | type: state.azure.tablestorage 7 | version: v1 8 | metadata: 9 | - name: accountName 10 | secretKeyRef: 11 | name: demo-state-secret 12 | key: account-name 13 | - name: accountKey 14 | secretKeyRef: 15 | name: demo-state-secret 16 | key: account-key 17 | - name: tableName 18 | value: DemoScoredTweets -------------------------------------------------------------------------------- /DevOps/components/charts/components/templates/twitter.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: tweets 5 | spec: 6 | type: bindings.twitter 7 | version: v1 8 | metadata: 9 | - name: consumerKey 10 | secretKeyRef: 11 | name: demo-twitter-secret 12 | key: consumerKey 13 | - name: consumerSecret 14 | secretKeyRef: 15 | name: demo-twitter-secret 16 | key: consumerSecret 17 | - name: accessToken 18 | secretKeyRef: 19 | name: demo-twitter-secret 20 | key: accessToken 21 | - name: accessSecret 22 | secretKeyRef: 23 | name: demo-twitter-secret 24 | key: accessSecret 25 | - name: query 26 | value: {{ .Values.twitter.query | quote }} -------------------------------------------------------------------------------- /DevOps/components/charts/components/values.yaml: -------------------------------------------------------------------------------- 1 | # Default values for components chart. 2 | # This is a YAML-formatted file. 3 | # Declare variables to be passed into your templates. 4 | demoName: "twitterSentimentProcessor" 5 | 6 | dapr: 7 | port: 3500 8 | 9 | serviceBus: 10 | connectionString: "" 11 | 12 | cognitiveService: 13 | token: "" 14 | endpoint: "" 15 | 16 | tableStorage: 17 | key: "" 18 | name: "" 19 | 20 | twitter: 21 | consumerKey: "" 22 | accessToken: "" 23 | accessSecret: "" 24 | consumerSecret: "" 25 | query: "Microsoft" 26 | -------------------------------------------------------------------------------- /DevOps/components/charts/zipkin/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /DevOps/components/charts/zipkin/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: zipkin 3 | description: A Helm chart for Kubernetes that deploys a zipkin for Twitter Sentiment Demo. 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. They're included as 11 | # a dependency of application charts to inject those utilities and functions into the rendering 12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 13 | type: application 14 | 15 | # This is the chart version. This version number should be incremented each time you make changes 16 | # to the chart and its templates, including the app version. 17 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 18 | version: 0.1.0 19 | 20 | # This is the version number of the application being deployed. This version number should be 21 | # incremented each time you make changes to the application. Versions are not expected to 22 | # follow Semantic Versioning. They should reflect the version the application is using. 23 | # It is recommended to use it with quotes. 24 | appVersion: "0.1.0" 25 | -------------------------------------------------------------------------------- /DevOps/components/charts/zipkin/templates/tracing.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Configuration 3 | metadata: 4 | name: tracing 5 | namespace: default 6 | spec: 7 | tracing: 8 | samplingRate: "1" 9 | zipkin: 10 | endpointAddress: {{ .Values.tracing.endpointAddress | quote }} -------------------------------------------------------------------------------- /DevOps/components/charts/zipkin/templates/zipkin.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: zipkin 5 | labels: 6 | app: zipkin 7 | spec: 8 | replicas: 1 9 | selector: 10 | matchLabels: 11 | app: zipkin 12 | template: 13 | metadata: 14 | labels: 15 | app: zipkin 16 | spec: 17 | containers: 18 | - image: openzipkin/zipkin 19 | name: zipkin 20 | --- 21 | apiVersion: v1 22 | kind: Service 23 | metadata: 24 | name: publiczipkin 25 | labels: 26 | app: zipkin 27 | spec: 28 | ports: 29 | - port: {{ .Values.zipkin.externalPort }} 30 | protocol: TCP 31 | targetPort: 9411 32 | nodePort: {{ .Values.zipkin.nodePort }} 33 | selector: 34 | app: zipkin 35 | type: LoadBalancer 36 | --- 37 | apiVersion: v1 38 | kind: Service 39 | metadata: 40 | name: zipkin 41 | labels: 42 | app: zipkin 43 | spec: 44 | ports: 45 | - port: 9411 46 | protocol: TCP 47 | targetPort: 9411 48 | selector: 49 | app: zipkin 50 | type: ClusterIP -------------------------------------------------------------------------------- /DevOps/components/charts/zipkin/values.yaml: -------------------------------------------------------------------------------- 1 | # Default values for components chart. 2 | # This is a YAML-formatted file. 3 | # Declare variables to be passed into your templates. 4 | tracing: 5 | endpointAddress: "http://zipkin.default.svc.cluster.local:9411/api/v2/spans" 6 | 7 | zipkin: 8 | externalPort: 8411 9 | nodePort: 30001 10 | -------------------------------------------------------------------------------- /DevOps/components/local/pubsub.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: pubsub 5 | spec: 6 | type: pubsub.redis 7 | version: v1 8 | metadata: 9 | - name: redisHost 10 | value: localhost:6379 11 | - name: redisPassword 12 | value: "" 13 | -------------------------------------------------------------------------------- /DevOps/components/local/secretstore.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: strongbox 5 | spec: 6 | type: secretstores.local.file 7 | version: v1 8 | metadata: 9 | - name: secretsFile 10 | value: "./components/local/local_secrets.json" -------------------------------------------------------------------------------- /DevOps/components/local/statestore.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: statestore 5 | spec: 6 | type: state.redis 7 | version: v1 8 | metadata: 9 | - name: redisHost 10 | value: localhost:6379 11 | - name: redisPassword 12 | value: "" 13 | - name: actorStateStore 14 | value: "true" 15 | -------------------------------------------------------------------------------- /DevOps/components/local/twitter.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: tweets 5 | auth: 6 | secretStore: strongbox 7 | spec: 8 | type: bindings.twitter 9 | version: v1 10 | metadata: 11 | - name: consumerKey 12 | secretKeyRef: 13 | key: apiKey 14 | name: apiKey 15 | - name: consumerSecret 16 | secretKeyRef: 17 | key: apiKeySecret 18 | name: apiKeySecret 19 | - name: accessToken 20 | secretKeyRef: 21 | key: accessToken 22 | name: accessToken 23 | - name: accessSecret 24 | secretKeyRef: 25 | key: accessTokenSecret 26 | name: accessTokenSecret 27 | - name: query 28 | value: "microsoft" -------------------------------------------------------------------------------- /DevOps/deploy/azure/main.bicep: -------------------------------------------------------------------------------- 1 | targetScope = 'subscription' 2 | 3 | param location string = 'eastus' 4 | param k8sversion string = '1.21.2' 5 | param rgName string = 'dapr_devops_demo' 6 | 7 | resource rg 'Microsoft.Resources/resourceGroups@2021-04-01' = { 8 | name: rgName 9 | location: location 10 | } 11 | 12 | module devops './devops.bicep' = { 13 | name: 'devops' 14 | scope: resourceGroup(rg.name) 15 | params: { 16 | location: location 17 | k8sversion: k8sversion 18 | } 19 | } 20 | 21 | output aksName string = devops.outputs.clusterName 22 | 23 | output storageAccountName string = devops.outputs.storageAccountName 24 | 25 | output serviceBusAuthRule string = devops.outputs.serviceBusAuthRule 26 | output serviceBusNamespace string = devops.outputs.serviceBusNamespace 27 | 28 | output cognitiveServiceName string = devops.outputs.cognitiveServiceName 29 | output cognitiveServiceEndpoint string = devops.outputs.cognitiveServiceEndpoint 30 | 31 | output instrumentationKey string = devops.outputs.instrumentationKey 32 | -------------------------------------------------------------------------------- /DevOps/deploy/local/devops.bicep: -------------------------------------------------------------------------------- 1 | param location string 2 | 3 | var csName = 'cs${uniqueString(resourceGroup().id)}' 4 | 5 | resource cs 'Microsoft.CognitiveServices/accounts@2017-04-18' = { 6 | name: csName 7 | kind: 'CognitiveServices' 8 | location: location 9 | sku: { 10 | name: 'S0' 11 | } 12 | properties: { 13 | customSubDomainName: csName 14 | } 15 | } 16 | 17 | resource stg 'Microsoft.Storage/storageAccounts@2019-06-01' = { 18 | name: toLower('stg${uniqueString(resourceGroup().id)}') // must be globally unique 19 | location: location 20 | kind: 'Storage' 21 | sku: { 22 | name: 'Standard_LRS' 23 | } 24 | } 25 | 26 | resource sb 'Microsoft.ServiceBus/namespaces@2021-06-01-preview' = { 27 | name: 'sb${uniqueString(resourceGroup().id)}' 28 | location: location 29 | sku: { 30 | name: 'Standard' 31 | tier: 'Standard' 32 | } 33 | properties: {} 34 | } 35 | 36 | resource sbAuthRule 'Microsoft.ServiceBus/namespaces/AuthorizationRules@2021-06-01-preview' existing = { 37 | parent: sb 38 | name: 'RootManageSharedAccessKey' 39 | } 40 | 41 | resource workspace 'Microsoft.OperationalInsights/workspaces@2020-10-01' = { 42 | name: 'ws${uniqueString(resourceGroup().id)}' 43 | location: location 44 | } 45 | 46 | resource appInsights 'Microsoft.Insights/components@2020-02-02-preview' = { 47 | name: 'appi${uniqueString(resourceGroup().id)}' 48 | kind: 'web' 49 | location: location 50 | properties: { 51 | Application_Type: 'web' 52 | WorkspaceResourceId: workspace.id 53 | publicNetworkAccessForQuery: 'Enabled' 54 | publicNetworkAccessForIngestion: 'Enabled' 55 | } 56 | } 57 | 58 | output storageAccountName string = stg.name 59 | 60 | output cognitiveServiceName string = cs.name 61 | output cognitiveServiceEndpoint string = reference(cs.name).endpoint 62 | 63 | output serviceBusNamespace string = sb.name 64 | output serviceBusAuthRule string = sbAuthRule.name 65 | 66 | output instrumentationKey string = appInsights.properties.InstrumentationKey 67 | -------------------------------------------------------------------------------- /DevOps/deploy/local/main.bicep: -------------------------------------------------------------------------------- 1 | targetScope = 'subscription' 2 | 3 | param location string = 'eastus' 4 | param rgName string = 'dapr_devops_demo' 5 | 6 | resource rg 'Microsoft.Resources/resourceGroups@2021-04-01' = { 7 | name: rgName 8 | location: location 9 | } 10 | 11 | module devops './devops.bicep' = { 12 | name: 'devops' 13 | scope: resourceGroup(rg.name) 14 | params: { 15 | location: location 16 | } 17 | } 18 | 19 | output storageAccountName string = devops.outputs.storageAccountName 20 | 21 | output serviceBusAuthRule string = devops.outputs.serviceBusAuthRule 22 | output serviceBusNamespace string = devops.outputs.serviceBusNamespace 23 | 24 | output cognitiveServiceName string = devops.outputs.cognitiveServiceName 25 | output cognitiveServiceEndpoint string = devops.outputs.cognitiveServiceEndpoint 26 | 27 | output instrumentationKey string = devops.outputs.instrumentationKey 28 | -------------------------------------------------------------------------------- /DevOps/src/csharp_processor/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/dotnet/sdk:6.0 as SDK 2 | 3 | WORKDIR /src 4 | COPY . . 5 | RUN dotnet publish -c Release -o /out 6 | 7 | FROM mcr.microsoft.com/dotnet/aspnet:6.0 as RUNTIME 8 | 9 | WORKDIR /app 10 | COPY --from=SDK /out /app 11 | ENTRYPOINT ["dotnet", "/app/processor.dll"] -------------------------------------------------------------------------------- /DevOps/src/csharp_processor/Program.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | var app = WebApplication.Create(args); 4 | 5 | if (app.Environment.IsDevelopment()) 6 | { 7 | app.UseDeveloperExceptionPage(); 8 | } 9 | 10 | string API_TOKEN = app.Configuration.GetValue("AZURE_CS_TOKEN", ""); 11 | string ENDPOINT = app.Configuration.GetValue("AZURE_CS_ENDPOINT", ""); 12 | 13 | // The full URL to the sentiment service 14 | var apiURL = $"{ENDPOINT}text/analytics/v2.1/sentiment"; 15 | 16 | app.MapPost("/score", async (Tweet t) => 17 | { 18 | app.Logger.LogInformation($"processing tweet: {t.Author.Name}, {t.Language}, {t.Text}"); 19 | 20 | // this allows the demo to run locally with no cloud resources provisioned. 21 | if (string.IsNullOrEmpty(ENDPOINT)) 22 | { 23 | return new AnalyzedTweet(t, 0.0f); 24 | } 25 | 26 | var request = new HttpRequestMessage(HttpMethod.Post, new Uri(apiURL)); 27 | request.Headers.Add("Ocp-Apim-Subscription-Key", API_TOKEN); 28 | request.Content = new StringContent($"{{documents: [{{id: \"1\", language: \"{t.Language}\", text: \"{t.Text}\"}},],}}"); 29 | request.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json"); 30 | 31 | var result = await new HttpClient().SendAsync(request); 32 | var scores = await result.Content.ReadFromJsonAsync(); 33 | 34 | if (scores == null) 35 | { 36 | app.Logger.LogTrace($"scores is null"); 37 | return null; 38 | } 39 | 40 | if (scores.Documents == null) 41 | { 42 | app.Logger.LogTrace($"scores.Documents is null"); 43 | return null; 44 | } 45 | 46 | if (scores.Documents.Length == 0) 47 | { 48 | app.Logger.LogTrace($"scores.Documents is empty"); 49 | return null; 50 | } 51 | 52 | app.Logger.LogInformation($"tweet score: {scores.Documents[0].score}"); 53 | 54 | // Score it 55 | var data = new AnalyzedTweet(t, scores.Documents[0].score); 56 | 57 | app.Logger.LogInformation($"tweet: {data}"); 58 | 59 | return data; 60 | }); 61 | 62 | await app.RunAsync(); 63 | 64 | public record TwitterUser([property: JsonPropertyName("screen_name")] string ScreenName, 65 | [property: JsonPropertyName("profile_image_url_https")] string Picture, 66 | string Name); 67 | 68 | public record Tweet([property: JsonPropertyName("id_str")] string Id, 69 | [property: JsonPropertyName("lang")] string Language, 70 | [property: JsonPropertyName("user")] TwitterUser Author, 71 | [property: JsonPropertyName("full_text")] string FullText, 72 | string Text); 73 | 74 | public record AnalyzedTweet(Tweet Tweet, 75 | float score); 76 | 77 | public record ScoreResult(Document[] Documents); 78 | public record Document(int id, float score); -------------------------------------------------------------------------------- /DevOps/src/csharp_processor/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:33666", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "processor": { 12 | "commandName": "Project", 13 | "dotnetRunMessages": true, 14 | "launchBrowser": true, 15 | "applicationUrl": "http://localhost:5000", 16 | "environmentVariables": { 17 | "ASPNETCORE_ENVIRONMENT": "Development" 18 | } 19 | }, 20 | "IIS Express": { 21 | "commandName": "IISExpress", 22 | "launchBrowser": true, 23 | "environmentVariables": { 24 | "ASPNETCORE_ENVIRONMENT": "Development" 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /DevOps/src/csharp_processor/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /DevOps/src/csharp_processor/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "AllowedHosts": "*" 10 | } 11 | -------------------------------------------------------------------------------- /DevOps/src/csharp_processor/charts/processor/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /DevOps/src/csharp_processor/charts/processor/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: processor 3 | description: A Helm chart for processor 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. They're included as 11 | # a dependency of application charts to inject those utilities and functions into the rendering 12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 13 | type: application 14 | 15 | # This is the chart version. This version number should be incremented each time you make changes 16 | # to the chart and its templates, including the app version. 17 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 18 | version: 0.1.0 19 | 20 | # This is the version number of the application being deployed. This version number should be 21 | # incremented each time you make changes to the application. Versions are not expected to 22 | # follow Semantic Versioning. They should reflect the version the application is using. 23 | # It is recommended to use it with quotes. 24 | appVersion: "0.1.0" 25 | -------------------------------------------------------------------------------- /DevOps/src/csharp_processor/charts/processor/templates/processor.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: processor 5 | labels: 6 | app: processor 7 | spec: 8 | replicas: 1 9 | selector: 10 | matchLabels: 11 | app: processor 12 | template: 13 | metadata: 14 | labels: 15 | app: processor 16 | demo: {{ .Values.demoName }} 17 | annotations: 18 | dapr.io/enabled: "true" 19 | dapr.io/config: "tracing" 20 | dapr.io/app-id: "processor" 21 | dapr.io/log-as-json: "true" 22 | dapr.io/app-port: {{ .Values.processor.port | quote }} 23 | dapr.io/log-level: {{ .Values.dapr.loglevel | quote }} 24 | spec: 25 | containers: 26 | - name: processor 27 | image: "{{ .Values.processor.image }}:{{.Values.image.tag}}" 28 | imagePullPolicy: {{ .Values.image.imagePullPolicy }} 29 | ports: 30 | - containerPort: {{ .Values.processor.port }} 31 | env: 32 | - name: PORT 33 | value: {{ .Values.processor.port | quote }} 34 | - name: DAPR_HTTP_PORT 35 | value: {{ .Values.dapr.port | quote}} 36 | - name: SECRET_STORE 37 | value: "kubernetes" 38 | - name: SECRET_KEY 39 | value: "demo-processor-secret" 40 | - name: SECRET_STORE_NAMESPACE 41 | value: "default" 42 | - name: AZURE_CS_ENDPOINT 43 | valueFrom: 44 | secretKeyRef: 45 | name: demo-processor-secret 46 | key: endpoint 47 | - name: AZURE_CS_TOKEN 48 | valueFrom: 49 | secretKeyRef: 50 | name: demo-processor-secret 51 | key: token -------------------------------------------------------------------------------- /DevOps/src/csharp_processor/charts/processor/values.yaml: -------------------------------------------------------------------------------- 1 | # Default values for demo chart. 2 | # This is a YAML-formatted file. 3 | # Declare variables to be passed into your templates. 4 | demoName: "twitterSentimentProcessor" 5 | 6 | dapr: 7 | port: 3500 8 | # Sets the log level for the Dapr sidecar. Allowed values are debug, info, warn, error. 9 | loglevel: "info" 10 | 11 | image: 12 | tag: "local" 13 | imagePullPolicy: "Always" 14 | 15 | processor: 16 | port: 80 17 | image: "k3d-registry.localhost:5500/csharpprocessor" -------------------------------------------------------------------------------- /DevOps/src/csharp_processor/processor.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /DevOps/src/csharp_provider/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/dotnet/sdk:6.0 as SDK 2 | 3 | WORKDIR /src 4 | COPY . . 5 | RUN dotnet publish -c Release -o /out 6 | 7 | FROM mcr.microsoft.com/dotnet/aspnet:6.0 as RUNTIME 8 | 9 | WORKDIR /app 10 | COPY --from=SDK /out /app 11 | ENTRYPOINT ["dotnet", "/app/provider.dll"] -------------------------------------------------------------------------------- /DevOps/src/csharp_provider/Program.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | var builder = WebApplication.CreateBuilder(args); 4 | builder.Services.AddControllers().AddDapr(); 5 | 6 | // Configure and enable middlewares 7 | var app = builder.Build(); 8 | 9 | if (app.Environment.IsDevelopment()) 10 | { 11 | app.UseDeveloperExceptionPage(); 12 | } 13 | 14 | app.MapPost("/tweets", async (Tweet t, Dapr.Client.DaprClient client) => 15 | { 16 | app.Logger.LogInformation("/tweets invoked..."); 17 | var scoredTweet = await client.InvokeMethodAsync("processor", "score", t); 18 | 19 | app.Logger.LogInformation("/tweet scored, saving to state store"); 20 | await client.SaveStateAsync("statestore", t.Id, scoredTweet); 21 | 22 | app.Logger.LogInformation("/tweet saved, posting to pubsub"); 23 | await client.PublishEventAsync("pubsub", "scored", scoredTweet); 24 | 25 | app.Logger.LogInformation("/tweet processed"); 26 | }); 27 | 28 | await app.RunAsync(); 29 | 30 | public record TwitterUser([property: JsonPropertyName("screen_name")] string ScreenName, 31 | [property: JsonPropertyName("profile_image_url_https")] string Picture, 32 | string Name); 33 | 34 | public record Tweet([property: JsonPropertyName("id_str")] string Id, 35 | [property: JsonPropertyName("lang")] string Language, 36 | [property: JsonPropertyName("user")] TwitterUser Author, 37 | [property: JsonPropertyName("full_text")] string FullText, 38 | string Text); 39 | 40 | public record AnalyzedTweet(Tweet Tweet, 41 | float score); -------------------------------------------------------------------------------- /DevOps/src/csharp_provider/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:24898", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "provider": { 12 | "commandName": "Project", 13 | "dotnetRunMessages": true, 14 | "launchBrowser": true, 15 | "applicationUrl": "http://localhost:5000", 16 | "environmentVariables": { 17 | "ASPNETCORE_ENVIRONMENT": "Development" 18 | } 19 | }, 20 | "IIS Express": { 21 | "commandName": "IISExpress", 22 | "launchBrowser": true, 23 | "environmentVariables": { 24 | "ASPNETCORE_ENVIRONMENT": "Development" 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /DevOps/src/csharp_provider/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /DevOps/src/csharp_provider/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "AllowedHosts": "*" 10 | } 11 | -------------------------------------------------------------------------------- /DevOps/src/csharp_provider/charts/provider/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: provider 3 | description: A Helm chart for provider 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. They're included as 11 | # a dependency of application charts to inject those utilities and functions into the rendering 12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 13 | type: application 14 | 15 | # This is the chart version. This version number should be incremented each time you make changes 16 | # to the chart and its templates, including the app version. 17 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 18 | version: 0.1.0 19 | 20 | # This is the version number of the application being deployed. This version number should be 21 | # incremented each time you make changes to the application. Versions are not expected to 22 | # follow Semantic Versioning. They should reflect the version the application is using. 23 | # It is recommended to use it with quotes. 24 | appVersion: "0.1.0" 25 | -------------------------------------------------------------------------------- /DevOps/src/csharp_provider/charts/provider/templates/provider.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: provider 5 | labels: 6 | app: provider 7 | spec: 8 | replicas: 1 9 | selector: 10 | matchLabels: 11 | app: provider 12 | template: 13 | metadata: 14 | labels: 15 | app: provider 16 | demo: {{ .Values.demoName }} 17 | annotations: 18 | dapr.io/enabled: "true" 19 | dapr.io/config: "tracing" 20 | dapr.io/app-id: "provider" 21 | dapr.io/log-as-json: "true" 22 | dapr.io/app-port: {{ .Values.provider.port | quote }} 23 | dapr.io/log-level: {{ .Values.dapr.loglevel | quote }} 24 | spec: 25 | containers: 26 | - name: provider 27 | image: "{{ .Values.provider.image }}:{{.Values.image.tag}}" 28 | imagePullPolicy: {{ .Values.image.imagePullPolicy }} 29 | ports: 30 | - containerPort: {{ .Values.provider.port }} 31 | env: 32 | - name: PORT 33 | value: {{ .Values.provider.port | quote }} 34 | - name: DAPR_HTTP_PORT 35 | value: {{ .Values.dapr.port | quote}} -------------------------------------------------------------------------------- /DevOps/src/csharp_provider/charts/provider/values.yaml: -------------------------------------------------------------------------------- 1 | # Default values for demo chart. 2 | # This is a YAML-formatted file. 3 | # Declare variables to be passed into your templates. 4 | demoName: "twitterSentimentProcessor" 5 | 6 | dapr: 7 | port: 3500 8 | # Sets the log level for the Dapr sidecar. Allowed values are debug, info, warn, error. 9 | loglevel: "info" 10 | 11 | image: 12 | tag: "local" 13 | imagePullPolicy: "Always" 14 | 15 | provider: 16 | port: 80 17 | image: "k3d-registry.localhost:5500/csharpprovider" -------------------------------------------------------------------------------- /DevOps/src/csharp_provider/provider.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /DevOps/src/csharp_viewer/Controllers/TweetController.cs: -------------------------------------------------------------------------------- 1 | using viewer.Hubs; 2 | using Microsoft.AspNetCore.Mvc; 3 | using Microsoft.AspNetCore.SignalR; 4 | 5 | namespace viewer.Controllers; 6 | 7 | [ApiController] 8 | [Route("[controller]")] 9 | public class TweetController : ControllerBase 10 | { 11 | private readonly IHubContext _hub; 12 | private readonly ILogger _logger; 13 | 14 | public TweetController(ILogger logger, IHubContext hub) 15 | { 16 | _hub = hub; 17 | _logger = logger; 18 | } 19 | 20 | [HttpPost] 21 | [Dapr.Topic("pubsub", "scored")] 22 | public async void PostTweet(object tweet) 23 | { 24 | this._logger.LogInformation("Viewer received tweet"); 25 | await this._hub.Clients.All.SendAsync("ReceiveTweet", tweet); 26 | } 27 | } -------------------------------------------------------------------------------- /DevOps/src/csharp_viewer/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/dotnet/sdk:6.0 as SDK 2 | 3 | WORKDIR /src 4 | COPY . . 5 | RUN dotnet publish -c Release -o /out 6 | 7 | FROM mcr.microsoft.com/dotnet/aspnet:6.0 as RUNTIME 8 | 9 | WORKDIR /app 10 | COPY --from=SDK /out /app 11 | ENTRYPOINT ["dotnet", "/app/viewer.dll"] -------------------------------------------------------------------------------- /DevOps/src/csharp_viewer/Hubs/TweetHub.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.SignalR; 2 | 3 | namespace viewer.Hubs 4 | { 5 | public class TweetHub : Hub { } 6 | } -------------------------------------------------------------------------------- /DevOps/src/csharp_viewer/Pages/Error.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model ErrorModel 3 | @{ 4 | ViewData["Title"] = "Error"; 5 | } 6 | 7 |

Error.

8 |

An error occurred while processing your request.

9 | 10 | @if (Model.ShowRequestId) 11 | { 12 |

13 | Request ID: @Model.RequestId 14 |

15 | } 16 | 17 |

Development Mode

18 |

19 | Swapping to the Development environment displays detailed information about the error that occurred. 20 |

21 |

22 | The Development environment shouldn't be enabled for deployed applications. 23 | It can result in displaying sensitive information from exceptions to end users. 24 | For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development 25 | and restarting the app. 26 |

27 | -------------------------------------------------------------------------------- /DevOps/src/csharp_viewer/Pages/Error.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using Microsoft.AspNetCore.Mvc; 3 | using Microsoft.AspNetCore.Mvc.RazorPages; 4 | 5 | namespace viewer.Pages; 6 | 7 | [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] 8 | [IgnoreAntiforgeryToken] 9 | public class ErrorModel : PageModel 10 | { 11 | public string? RequestId { get; set; } 12 | 13 | public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); 14 | 15 | private readonly ILogger _logger; 16 | 17 | public ErrorModel(ILogger logger) 18 | { 19 | _logger = logger; 20 | } 21 | 22 | public void OnGet() 23 | { 24 | RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier; 25 | } 26 | } 27 | 28 | -------------------------------------------------------------------------------- /DevOps/src/csharp_viewer/Pages/Index.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model IndexModel 3 | @{ 4 | ViewData["Title"] = "Dapr Tweet Viewer"; 5 | } 6 |
7 | 8 | -------------------------------------------------------------------------------- /DevOps/src/csharp_viewer/Pages/Index.cshtml.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using Microsoft.AspNetCore.Mvc.RazorPages; 3 | 4 | namespace viewer.Pages; 5 | 6 | public class IndexModel : PageModel 7 | { 8 | private readonly ILogger _logger; 9 | 10 | public IndexModel(ILogger logger) 11 | { 12 | _logger = logger; 13 | } 14 | 15 | public void OnGet() 16 | { 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /DevOps/src/csharp_viewer/Pages/Privacy.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model PrivacyModel 3 | @{ 4 | ViewData["Title"] = "Privacy Policy"; 5 | } 6 |

@ViewData["Title"]

7 | 8 |

Use this page to detail your site's privacy policy.

9 | -------------------------------------------------------------------------------- /DevOps/src/csharp_viewer/Pages/Privacy.cshtml.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using Microsoft.AspNetCore.Mvc.RazorPages; 3 | 4 | namespace viewer.Pages; 5 | 6 | public class PrivacyModel : PageModel 7 | { 8 | private readonly ILogger _logger; 9 | 10 | public PrivacyModel(ILogger logger) 11 | { 12 | _logger = logger; 13 | } 14 | 15 | public void OnGet() 16 | { 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /DevOps/src/csharp_viewer/Pages/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | @ViewData["Title"] 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 23 | 24 |
25 | @RenderBody() 26 |
27 |
28 | 29 | 30 | 31 | 32 | 33 | @await RenderSectionAsync("Scripts", required: false) 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /DevOps/src/csharp_viewer/Pages/Shared/_ValidationScriptsPartial.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | -------------------------------------------------------------------------------- /DevOps/src/csharp_viewer/Pages/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using viewer 2 | @namespace viewer.Pages 3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 4 | -------------------------------------------------------------------------------- /DevOps/src/csharp_viewer/Pages/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /DevOps/src/csharp_viewer/Program.cs: -------------------------------------------------------------------------------- 1 | var builder = WebApplication.CreateBuilder(args); 2 | 3 | // Add services to the container. 4 | 5 | builder.Services.AddControllers().AddDapr(); 6 | builder.Services.AddSwaggerGen(c => 7 | { 8 | c.SwaggerDoc("v1", new() { Title = "temp", Version = "v1" }); 9 | }); 10 | 11 | // Add services to the container. 12 | builder.Services.AddRazorPages(); 13 | builder.Services.AddSignalR(); 14 | 15 | var app = builder.Build(); 16 | 17 | // Configure the HTTP request pipeline. 18 | if (app.Environment.IsDevelopment()) 19 | { 20 | app.UseDeveloperExceptionPage(); 21 | app.UseSwagger(); 22 | app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "temp v1")); 23 | } 24 | else 25 | { 26 | app.UseExceptionHandler("/Error"); 27 | } 28 | 29 | app.UseStaticFiles(); 30 | app.UseCloudEvents(); 31 | app.UseRouting(); 32 | app.UseAuthorization(); 33 | app.UseEndpoints(endpoints => 34 | { 35 | endpoints.MapSubscribeHandler(); 36 | endpoints.MapHub("/tweetHub"); 37 | }); 38 | 39 | app.MapControllers(); 40 | 41 | app.MapRazorPages(); 42 | 43 | app.Run(); -------------------------------------------------------------------------------- /DevOps/src/csharp_viewer/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:40661", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "viewer": { 12 | "commandName": "Project", 13 | "dotnetRunMessages": true, 14 | "launchBrowser": true, 15 | "applicationUrl": "http://localhost:5000", 16 | "environmentVariables": { 17 | "ASPNETCORE_ENVIRONMENT": "Development" 18 | } 19 | }, 20 | "IIS Express": { 21 | "commandName": "IISExpress", 22 | "launchBrowser": true, 23 | "environmentVariables": { 24 | "ASPNETCORE_ENVIRONMENT": "Development" 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /DevOps/src/csharp_viewer/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "DetailedErrors": true, 3 | "Logging": { 4 | "LogLevel": { 5 | "Default": "Information", 6 | "Microsoft": "Warning", 7 | "Microsoft.Hosting.Lifetime": "Information" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /DevOps/src/csharp_viewer/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "AllowedHosts": "*" 10 | } 11 | -------------------------------------------------------------------------------- /DevOps/src/csharp_viewer/charts/viewer/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /DevOps/src/csharp_viewer/charts/viewer/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: viewer 3 | description: A Helm chart for Kubernetes 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. They're included as 11 | # a dependency of application charts to inject those utilities and functions into the rendering 12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 13 | type: application 14 | 15 | # This is the chart version. This version number should be incremented each time you make changes 16 | # to the chart and its templates, including the app version. 17 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 18 | version: 0.1.0 19 | 20 | # This is the version number of the application being deployed. This version number should be 21 | # incremented each time you make changes to the application. Versions are not expected to 22 | # follow Semantic Versioning. They should reflect the version the application is using. 23 | # It is recommended to use it with quotes. 24 | appVersion: "1.16.0" 25 | -------------------------------------------------------------------------------- /DevOps/src/csharp_viewer/charts/viewer/templates/viewer.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: viewer 5 | labels: 6 | app: viewer 7 | spec: 8 | replicas: 1 9 | selector: 10 | matchLabels: 11 | app: viewer 12 | template: 13 | metadata: 14 | labels: 15 | app: viewer 16 | demo: {{ .Values.demoName }} 17 | annotations: 18 | dapr.io/enabled: "true" 19 | dapr.io/app-id: "viewer" 20 | dapr.io/config: "tracing" 21 | dapr.io/log-as-json: "true" 22 | dapr.io/app-port: {{ .Values.viewer.port | quote }} 23 | dapr.io/log-level: {{ .Values.dapr.loglevel | quote }} 24 | spec: 25 | containers: 26 | - name: viewer 27 | image: "{{ .Values.viewer.image }}:{{.Values.image.tag}}" 28 | imagePullPolicy: {{ .Values.image.imagePullPolicy }} 29 | ports: 30 | - containerPort: {{ .Values.viewer.port }} 31 | env: 32 | - name: PORT 33 | value: {{ .Values.viewer.port | quote }} 34 | - name: DAPR_HTTP_PORT 35 | value: {{ .Values.dapr.port | quote}} 36 | --- 37 | apiVersion: v1 38 | kind: Service 39 | metadata: 40 | name: viewer 41 | spec: 42 | ports: 43 | - port: {{ .Values.viewer.externalPort }} 44 | protocol: TCP 45 | targetPort: {{ .Values.viewer.port }} 46 | {{- if gt .Values.viewer.nodePort 0 }} 47 | nodePort: {{ .Values.viewer.nodePort }} 48 | {{- end }} 49 | selector: 50 | app: viewer 51 | type: LoadBalancer -------------------------------------------------------------------------------- /DevOps/src/csharp_viewer/charts/viewer/values.yaml: -------------------------------------------------------------------------------- 1 | # Default values for demo chart. 2 | # This is a YAML-formatted file. 3 | # Declare variables to be passed into your templates. 4 | demoName: "twitterSentimentProcessor" 5 | 6 | dapr: 7 | port: 3500 8 | # Sets the log level for the Dapr sidecar. Allowed values are debug, info, warn, error. 9 | loglevel: "info" 10 | 11 | image: 12 | tag: "local" 13 | imagePullPolicy: "Always" 14 | 15 | viewer: 16 | port: 80 17 | externalPort: 8080 18 | nodePort: 30000 19 | image: "k3d-registry.localhost:5500/csharpviewer" -------------------------------------------------------------------------------- /DevOps/src/csharp_viewer/libman.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0", 3 | "defaultProvider": "unpkg", 4 | "libraries": [ 5 | { 6 | "library": "@microsoft/signalr@latest", 7 | "destination": "wwwroot/js/signalr", 8 | "files": [ 9 | "dist/browser/signalr.js", 10 | "dist/browser/signalr.min.js" 11 | ] 12 | } 13 | ] 14 | } -------------------------------------------------------------------------------- /DevOps/src/csharp_viewer/viewer.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /DevOps/src/csharp_viewer/wwwroot/css/site.css: -------------------------------------------------------------------------------- 1 | /* 2 | Knative colors 3 | Dark Blue: #0865ad 4 | Light Blue: #6695ca 5 | 6 | */ 7 | 8 | html, 9 | body { 10 | height: 100%; 11 | margin: 0; 12 | padding: 0; 13 | background-color: #fff; 14 | } 15 | 16 | #wrapper { 17 | padding: 0; 18 | margin: 0; 19 | height: 100%; 20 | text-align: center; 21 | widows: 100%; 22 | } 23 | 24 | #page-header { 25 | padding: 0; 26 | margin: 10px 0 0 0; 27 | clear: both; 28 | break-after: always; 29 | height: 100px; 30 | } 31 | 32 | #page-header-image { 33 | border: 0; 34 | margin-left: 25px; 35 | } 36 | 37 | #page-header-image img { 38 | width: 100px; 39 | height: 100px; 40 | float: left; 41 | } 42 | 43 | #connection { 44 | float: right; 45 | margin: 10px; 46 | font-family: Geneva, Verdana, sans-serif; 47 | font-size: 1em; 48 | } 49 | 50 | #middle-section { 51 | margin: 0; 52 | padding: 10px; 53 | height: 700px; 54 | overflow: auto; 55 | } 56 | 57 | #middle-section div { 58 | margin: 5px; 59 | } 60 | 61 | #page-footer { 62 | widows: 80%; 63 | margin: 30px 0 0 0; 64 | font-family: Geneva, Verdana, sans-serif; 65 | font-size: 1em; 66 | } 67 | 68 | #tweets { 69 | background-color: #20329b; 70 | padding: 0; 71 | margin: 5px; 72 | height: 690px; 73 | overflow: auto; 74 | } 75 | 76 | img.profile-pic { 77 | width: 72px; 78 | height: 72px; 79 | margin: 0 5px 5px 0; 80 | float: left; 81 | } 82 | 83 | div.item-text { 84 | margin-left: 10px; 85 | padding-left: 10px; 86 | } 87 | 88 | #tweets b { 89 | font-family: Geneva, Verdana, sans-serif; 90 | font-size: 1em; 91 | color: #20329b; 92 | margin: 0; 93 | } 94 | 95 | #tweets i { 96 | font-family: Geneva, Verdana, sans-serif; 97 | font-size: 0.8em; 98 | font-style: normal; 99 | } 100 | 101 | #tweets i.small { 102 | font-size: 0.7em; 103 | color: #666666; 104 | } 105 | 106 | img.sentiment { 107 | width: 18px; 108 | height: 18px; 109 | margin: 0 3px 0 0; 110 | vertical-align: baseline; 111 | } 112 | 113 | img.tweet-link { 114 | width: 25px; 115 | height: 25px; 116 | margin: 0 0 0 3px; 117 | vertical-align: baseline; 118 | } 119 | 120 | .error { 121 | color: red; 122 | } 123 | 124 | .item { 125 | clear: both; 126 | padding: 5px; 127 | text-align: left; 128 | background-color: #fff; 129 | overflow: auto; 130 | } -------------------------------------------------------------------------------- /DevOps/src/csharp_viewer/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarqueWarrior/MyDaprDemos/f84b38eba203c23075eac2037b3994ab9c9928b1/DevOps/src/csharp_viewer/wwwroot/favicon.ico -------------------------------------------------------------------------------- /DevOps/src/csharp_viewer/wwwroot/img/negative.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /DevOps/src/csharp_viewer/wwwroot/img/neutral.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /DevOps/src/csharp_viewer/wwwroot/img/positive.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /DevOps/src/csharp_viewer/wwwroot/img/tw.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /DevOps/src/csharp_viewer/wwwroot/img/unknown.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /DevOps/src/csharp_viewer/wwwroot/js/site.js: -------------------------------------------------------------------------------- 1 | // Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification 2 | // for details on configuring this project to bundle and minify static web assets. 3 | 4 | // Write your JavaScript code. 5 | -------------------------------------------------------------------------------- /DevOps/src/csharp_viewer/wwwroot/js/tweet.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var connection = new signalR.HubConnectionBuilder().withUrl("/tweetHub").build(); 4 | 5 | connection.on("ReceiveTweet", function (t) { 6 | var log = document.getElementById("tweets"); 7 | 8 | function appendLog(item) { 9 | var doScroll = log.scrollTop > log.scrollHeight - log.clientHeight - 1; 10 | log.appendChild(item); 11 | if (doScroll) { 12 | log.scrollTop = log.scrollHeight - log.clientHeight; 13 | } 14 | } 15 | 16 | var scoreStr = "unknown"; 17 | var score = parseFloat(t.score) 18 | if (score <= parseFloat(0.3)) { 19 | scoreStr = "negative" 20 | } else if (score >= parseFloat(0.6)) { 21 | scoreStr = "positive" 22 | } else { 23 | scoreStr = "neutral" 24 | } 25 | 26 | var scoreAlt = `${scoreStr}: ${t.score}`; 27 | 28 | var tweetText = t.tweet.text; 29 | if (t.tweet.fullText != null) { 30 | tweetText = t.tweet.full_text; 31 | } 32 | 33 | var item = document.createElement("div"); 34 | item.className = "item"; 35 | 36 | var postURL = t.tweet.user.name; 37 | if (t.tweet.user.screen_name) { 38 | postURL = ` 39 | ${t.tweet.user.screen_name} 40 | 41 | `; 42 | } 43 | 44 | var tweetMsg = ` 45 | 46 |
47 | ${postURL}
${tweetText} 48 |
49 | `; 50 | 51 | item.innerHTML = tweetMsg; 52 | appendLog(item); 53 | }); 54 | 55 | connection.start().then(function () { 56 | var connDiv = document.getElementById("connection-status"); 57 | connDiv.innerText = "open"; 58 | }).catch(function (err) { 59 | return console.error(err.toString()); 60 | }); -------------------------------------------------------------------------------- /DevOps/src/csharp_viewer/wwwroot/lib/bootstrap/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2011-2018 Twitter, Inc. 4 | Copyright (c) 2011-2018 The Bootstrap Authors 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /DevOps/src/csharp_viewer/wwwroot/lib/jquery-validation-unobtrusive/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) .NET Foundation. All rights reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use 4 | these files except in compliance with the License. You may obtain a copy of the 5 | License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software distributed 10 | under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 11 | CONDITIONS OF ANY KIND, either express or implied. See the License for the 12 | specific language governing permissions and limitations under the License. 13 | -------------------------------------------------------------------------------- /DevOps/src/csharp_viewer/wwwroot/lib/jquery-validation/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | ===================== 3 | 4 | Copyright Jörn Zaefferer 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /DevOps/src/csharp_viewer/wwwroot/lib/jquery/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright JS Foundation and other contributors, https://js.foundation/ 2 | 3 | This software consists of voluntary contributions made by many 4 | individuals. For exact contribution history, see the revision history 5 | available at https://github.com/jquery/jquery 6 | 7 | The following license applies to all parts of this software except as 8 | documented below: 9 | 10 | ==== 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining 13 | a copy of this software and associated documentation files (the 14 | "Software"), to deal in the Software without restriction, including 15 | without limitation the rights to use, copy, modify, merge, publish, 16 | distribute, sublicense, and/or sell copies of the Software, and to 17 | permit persons to whom the Software is furnished to do so, subject to 18 | the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be 21 | included in all copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 27 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 28 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 29 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | 31 | ==== 32 | 33 | All files located in the node_modules and external directories are 34 | externally maintained libraries used by this software which have their 35 | own licenses; we recommend you read them, as their terms may differ from 36 | the terms above. 37 | -------------------------------------------------------------------------------- /DevOps/src/java_viewer/.gitignore: -------------------------------------------------------------------------------- 1 | **/secrets.json 2 | **/.classpath 3 | **/.settings 4 | **/.DS_Store 5 | **/target 6 | **/.factorypath 7 | **/.project 8 | -------------------------------------------------------------------------------- /DevOps/src/java_viewer/Dockerfile: -------------------------------------------------------------------------------- 1 | # Build stage build the jar with all our resources 2 | FROM maven:3-openjdk-11 as build 3 | 4 | WORKDIR /build 5 | COPY pom.xml ./ 6 | ADD src /build/src 7 | RUN mvn package 8 | 9 | # Base Image 10 | FROM ubuntu:20.04 11 | 12 | # Download and Extract the Microsoft Build of OpenJDK from the Microsoft OpenJDK website 13 | RUN apt-get update && \ 14 | apt-get install -y wget && \ 15 | wget https://aka.ms/download-jdk/microsoft-jdk-11.0.11.9.1-linux-x64.tar.gz -O msopenjdk11.tar.gz && \ 16 | tar zxvf msopenjdk11.tar.gz && \ 17 | rm -rf msopenjdk11.tar.gz /var/lib/apt/lists/* 18 | 19 | # Create a smaller Java runtime, and delete the JDK 20 | RUN /jdk-11.0.11+9/bin/jlink \ 21 | --add-modules java.se,jdk.httpserver,jdk.unsupported,jdk.jfr \ 22 | --strip-debug \ 23 | --no-man-pages \ 24 | --no-header-files \ 25 | --compress=2 \ 26 | --output /javaruntime && \ 27 | rm -rf /jdk-11.0.11+9/ 28 | 29 | ARG JAR_FILE 30 | COPY --from=build /build/target/app.jar /opt/app.jar 31 | WORKDIR /opt/ 32 | 33 | EXPOSE 3000 34 | CMD [ "/javaruntime/bin/java", "-jar", "app.jar", "--server.port=3000" ] 35 | -------------------------------------------------------------------------------- /DevOps/src/java_viewer/src/main/java/io/dapr/apps/twitter/viewer/Application.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft Corporation. 3 | * Licensed under the MIT License. 4 | */ 5 | 6 | package io.dapr.apps.twitter.viewer; 7 | 8 | import org.springframework.boot.SpringApplication; 9 | import org.springframework.boot.autoconfigure.SpringBootApplication; 10 | 11 | import static java.lang.System.out; 12 | 13 | @SpringBootApplication(scanBasePackages = { "io.dapr.apps.twitter.viewer", "io.dapr.springboot" }) 14 | public class Application { 15 | 16 | public static void main(String[] args) { 17 | printJavaVersion(); 18 | SpringApplication.run(Application.class, args); 19 | } 20 | 21 | private static final void printJavaVersion() { 22 | var runtime = System.getProperty("java.runtime.name"); 23 | var vendor = System.getProperty("java.vendor.version"); 24 | var build = System.getProperty("java.vm.version"); 25 | out.printf("\n%s %s (build %s)", runtime, vendor, build); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /DevOps/src/java_viewer/src/main/java/io/dapr/apps/twitter/viewer/ApplicationController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft Corporation. 3 | * Licensed under the MIT License. 4 | */ 5 | 6 | package io.dapr.apps.twitter.viewer; 7 | 8 | import java.io.IOException; 9 | 10 | import org.springframework.http.HttpStatus; 11 | import org.springframework.web.bind.annotation.GetMapping; 12 | import org.springframework.web.bind.annotation.PostMapping; 13 | import org.springframework.web.bind.annotation.RequestBody; 14 | import org.springframework.web.bind.annotation.ResponseBody; 15 | import org.springframework.web.bind.annotation.ResponseStatus; 16 | import org.springframework.web.bind.annotation.RestController; 17 | 18 | import com.fasterxml.jackson.databind.ObjectMapper; 19 | 20 | import io.dapr.Topic; 21 | import io.dapr.client.domain.CloudEvent; 22 | import reactor.core.publisher.Mono; 23 | 24 | @RestController 25 | public class ApplicationController { 26 | private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); 27 | 28 | private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ApplicationController.class); 29 | 30 | private static final String PUBSUB = "pubsub"; 31 | 32 | @Topic(name = "scored", pubsubName = PUBSUB) 33 | @PostMapping(value = "/tweets") 34 | @ResponseStatus(HttpStatus.OK) 35 | @ResponseBody 36 | public void tweet(@RequestBody(required = false) CloudEvent event) throws IOException { 37 | String data = OBJECT_MAPPER.writeValueAsString(event.getData()); 38 | log.info("Received cloud event: " + data); 39 | WebSocketPubSub.INSTANCE.send(data); 40 | } 41 | 42 | @GetMapping(path = "/health") 43 | public Mono health() { 44 | return Mono.empty(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /DevOps/src/java_viewer/src/main/java/io/dapr/apps/twitter/viewer/SocketTextHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft Corporation. 3 | * Licensed under the MIT License. 4 | */ 5 | 6 | package io.dapr.apps.twitter.viewer; 7 | 8 | import java.io.IOException; 9 | 10 | import org.springframework.web.socket.CloseStatus; 11 | import org.springframework.web.socket.TextMessage; 12 | import org.springframework.web.socket.WebSocketSession; 13 | import org.springframework.web.socket.handler.TextWebSocketHandler; 14 | 15 | public class SocketTextHandler extends TextWebSocketHandler { 16 | 17 | private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(SocketTextHandler.class); 18 | 19 | @Override 20 | public void afterConnectionEstablished(WebSocketSession session) throws Exception { 21 | WebSocketPubSub.INSTANCE.registerSession(session); 22 | } 23 | 24 | @Override 25 | public void handleTextMessage(WebSocketSession session, TextMessage message) throws IOException { 26 | log.info("Sending message: " + message.getPayload()); 27 | session.sendMessage(message); 28 | } 29 | 30 | @Override 31 | public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { 32 | WebSocketPubSub.INSTANCE.unregisterSession(session); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /DevOps/src/java_viewer/src/main/java/io/dapr/apps/twitter/viewer/WebSocketConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft Corporation. 3 | * Licensed under the MIT License. 4 | */ 5 | 6 | package io.dapr.apps.twitter.viewer; 7 | 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.web.socket.config.annotation.EnableWebSocket; 10 | import org.springframework.web.socket.config.annotation.WebSocketConfigurer; 11 | import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; 12 | 13 | @Configuration 14 | @EnableWebSocket 15 | public class WebSocketConfig implements WebSocketConfigurer { 16 | 17 | public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { 18 | registry.addHandler(new SocketTextHandler(), "/ws"); 19 | } 20 | 21 | } -------------------------------------------------------------------------------- /DevOps/src/java_viewer/src/main/java/io/dapr/apps/twitter/viewer/WebSocketPubSub.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft Corporation. 3 | * Licensed under the MIT License. 4 | */ 5 | 6 | package io.dapr.apps.twitter.viewer; 7 | 8 | import java.io.IOException; 9 | import java.util.Collections; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | 13 | import org.springframework.web.socket.TextMessage; 14 | import org.springframework.web.socket.WebSocketSession; 15 | 16 | public class WebSocketPubSub { 17 | 18 | private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(WebSocketPubSub.class); 19 | 20 | private final Map sessions = Collections.synchronizedMap(new HashMap<>()); 21 | 22 | public static final WebSocketPubSub INSTANCE = new WebSocketPubSub(); 23 | 24 | private WebSocketPubSub() {} 25 | 26 | public void registerSession(WebSocketSession session) { 27 | log.info("Registering new websocketsession: " + session.getId()); 28 | sessions.put(session.getId(), session); 29 | } 30 | 31 | public void unregisterSession(WebSocketSession session) { 32 | log.info("unregistering new websocketsession: " + session.getId()); 33 | sessions.remove(session.getId()); 34 | } 35 | 36 | public void send(String content) { 37 | sessions.values().forEach(socket -> { 38 | try { 39 | socket.sendMessage(new TextMessage(content)); 40 | } catch (IOException e) { 41 | log.error("Could not send message to websocket.", e); 42 | } 43 | }); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /DevOps/src/java_viewer/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | logging.level.root=INFO 2 | spring.application.name=TwitterViewer 3 | server.port=8088 -------------------------------------------------------------------------------- /DevOps/src/java_viewer/src/main/resources/static/css/app.css: -------------------------------------------------------------------------------- 1 | /* 2 | Knative colors 3 | Dark Blue: #0865ad 4 | Light Blue: #6695ca 5 | 6 | */ 7 | 8 | 9 | html, 10 | body { 11 | height: 100%; 12 | margin: 0; 13 | padding: 0; 14 | background-color: #fff; 15 | } 16 | 17 | #wrapper { 18 | padding: 0; 19 | margin: 0; 20 | height: 100%; 21 | text-align: center; 22 | widows: 100%; 23 | } 24 | 25 | #page-header { 26 | padding: 0; 27 | margin: 10px 0 0 0; 28 | clear: both; 29 | break-after: always; 30 | height: 100px; 31 | } 32 | 33 | #page-header-image { 34 | border: 0; 35 | margin-left: 25px; 36 | } 37 | 38 | #page-header-image img { 39 | width: 100px; 40 | height: 100px; 41 | float: left; 42 | } 43 | 44 | #connection { 45 | float: right; 46 | margin: 10px; 47 | font-family: Geneva, Verdana, sans-serif; 48 | font-size: 1em; 49 | } 50 | 51 | #middle-section { 52 | margin: 0; 53 | padding: 10px; 54 | height: 700px; 55 | overflow: auto; 56 | } 57 | 58 | #middle-section div { 59 | margin: 5px; 60 | } 61 | 62 | #page-footer { 63 | widows: 80%; 64 | margin: 30px 0 0 0; 65 | font-family: Geneva, Verdana, sans-serif; 66 | font-size: 1em; 67 | } 68 | 69 | #tweets { 70 | background-color: #20329b; 71 | padding: 0; 72 | margin: 5px; 73 | height: 690px; 74 | overflow: auto; 75 | } 76 | 77 | img.profile-pic { 78 | width: 72px; 79 | height: 72px; 80 | margin: 0 5px 5px 0; 81 | float: left; 82 | } 83 | 84 | div.item-text { 85 | margin-left: 10px; 86 | padding-left: 10px; 87 | } 88 | 89 | #tweets b { 90 | font-family: Geneva, Verdana, sans-serif; 91 | font-size: 1em; 92 | color: #20329b; 93 | margin: 0; 94 | } 95 | 96 | #tweets i { 97 | font-family: Geneva, Verdana, sans-serif; 98 | font-size: 0.8em; 99 | font-style: normal; 100 | } 101 | 102 | #tweets i.small { 103 | font-size: 0.7em; 104 | color: #666666; 105 | } 106 | 107 | img.sentiment { 108 | width: 18px; 109 | height: 18px; 110 | margin: 0 3px 0 0; 111 | vertical-align: baseline; 112 | } 113 | 114 | img.tweet-link { 115 | width: 25px; 116 | height: 25px; 117 | margin: 0 0 0 3px; 118 | vertical-align: baseline; 119 | } 120 | 121 | .error { 122 | color: red; 123 | } 124 | 125 | .item { 126 | clear:both; 127 | padding: 5px; 128 | text-align: left; 129 | background-color: #fff; 130 | overflow: auto; 131 | } -------------------------------------------------------------------------------- /DevOps/src/java_viewer/src/main/resources/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarqueWarrior/MyDaprDemos/f84b38eba203c23075eac2037b3994ab9c9928b1/DevOps/src/java_viewer/src/main/resources/static/img/favicon.ico -------------------------------------------------------------------------------- /DevOps/src/java_viewer/src/main/resources/static/img/negative.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /DevOps/src/java_viewer/src/main/resources/static/img/neutral.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /DevOps/src/java_viewer/src/main/resources/static/img/positive.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /DevOps/src/java_viewer/src/main/resources/static/img/tw.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /DevOps/src/java_viewer/src/main/resources/static/img/unknown.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /DevOps/src/java_viewer/src/main/resources/static/index.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | Dapr Tweet Viewer 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 29 | 30 |
31 |
32 |
33 | 34 | 35 | 39 |
40 | 41 | -------------------------------------------------------------------------------- /DevOps/src/python_provider/provider.py: -------------------------------------------------------------------------------- 1 | import os 2 | import json 3 | import logging 4 | 5 | from dapr.clients import DaprClient 6 | from dapr.ext.grpc import App, BindingRequest 7 | 8 | APP_PORT = os.getenv("APP_PORT", "5040") 9 | 10 | app = App() 11 | 12 | 13 | @app.binding('tweets') 14 | def binding(request: BindingRequest): 15 | payload = request.text() 16 | m = json.loads(payload) 17 | 18 | logging.info(m) 19 | 20 | with DaprClient() as d: 21 | logging.info('/tweets invoked...') 22 | d.save_state('statestore', m['id_str'], payload) 23 | 24 | logging.info('/tweet scored, saving to state store') 25 | resp = d.invoke_method('processor', 'score', payload, http_verb='POST') 26 | scoredTweet = json.loads(resp.data) 27 | 28 | logging.info('/tweet saved, posting to pubsub') 29 | d.publish_event("pubsub", "scored", json.dumps( 30 | scoredTweet), data_content_type='application/json') 31 | 32 | logging.info('/tweet processed') 33 | 34 | 35 | def main(): 36 | app.run(APP_PORT) 37 | 38 | 39 | if __name__ == "__main__": 40 | logging.basicConfig(format='%(asctime)s %(message)s', level=logging.INFO) 41 | 42 | main() 43 | -------------------------------------------------------------------------------- /DevOps/src/python_provider/requirements.txt: -------------------------------------------------------------------------------- 1 | dapr-ext-grpc == 1.6.0 2 | dapr == 1.6.0 3 | -------------------------------------------------------------------------------- /DevOps/src/twitter.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30114.105 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "provider", "csharp_provider\provider.csproj", "{02EAB257-5E55-4502-B0BB-8CAB7A3FCE60}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "processor", "csharp_processor\processor.csproj", "{189A7892-2265-42A1-AB56-E05ACF104131}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "viewer", "csharp_viewer\viewer.csproj", "{75DA92D0-1B5F-4D85-BF6A-EF3D32C5EB84}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 21 | {02EAB257-5E55-4502-B0BB-8CAB7A3FCE60}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 22 | {02EAB257-5E55-4502-B0BB-8CAB7A3FCE60}.Debug|Any CPU.Build.0 = Debug|Any CPU 23 | {02EAB257-5E55-4502-B0BB-8CAB7A3FCE60}.Release|Any CPU.ActiveCfg = Release|Any CPU 24 | {02EAB257-5E55-4502-B0BB-8CAB7A3FCE60}.Release|Any CPU.Build.0 = Release|Any CPU 25 | {189A7892-2265-42A1-AB56-E05ACF104131}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 26 | {189A7892-2265-42A1-AB56-E05ACF104131}.Debug|Any CPU.Build.0 = Debug|Any CPU 27 | {189A7892-2265-42A1-AB56-E05ACF104131}.Release|Any CPU.ActiveCfg = Release|Any CPU 28 | {189A7892-2265-42A1-AB56-E05ACF104131}.Release|Any CPU.Build.0 = Release|Any CPU 29 | {75DA92D0-1B5F-4D85-BF6A-EF3D32C5EB84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 30 | {75DA92D0-1B5F-4D85-BF6A-EF3D32C5EB84}.Debug|Any CPU.Build.0 = Debug|Any CPU 31 | {75DA92D0-1B5F-4D85-BF6A-EF3D32C5EB84}.Release|Any CPU.ActiveCfg = Release|Any CPU 32 | {75DA92D0-1B5F-4D85-BF6A-EF3D32C5EB84}.Release|Any CPU.Build.0 = Release|Any CPU 33 | EndGlobalSection 34 | EndGlobal 35 | -------------------------------------------------------------------------------- /DevOps/src/tye_cloud.yaml: -------------------------------------------------------------------------------- 1 | name: observability 2 | 3 | services: 4 | - name: serviceA 5 | executable: dapr 6 | args: run -a serviceA -p 5000 -H 3500 -- dotnet run --project ./src/serviceA/serviceA.csproj --urls "http://localhost:5000" 7 | 8 | - name: serviceB 9 | executable: dapr 10 | args: run -a serviceB -p 5010 -- dotnet run --project ./src/serviceB/serviceB.csproj --urls "http://localhost:5010" 11 | 12 | - name: serviceC 13 | executable: dapr 14 | args: run -a serviceC -p 5020 -- dotnet run --project ./src/serviceC/serviceC.csproj --urls "http://localhost:5020" 15 | 16 | - name: openTelemetry 17 | image: otel/opentelemetry-collector-contrib-dev 18 | bindings: 19 | - port: 9411 20 | volumes: 21 | - source: ../config/azure/otel-local-config.yaml 22 | target: /etc/otel/config.yaml -------------------------------------------------------------------------------- /DevOps/src/tye_local.yaml: -------------------------------------------------------------------------------- 1 | name: observability 2 | 3 | services: 4 | - name: viewer 5 | executable: dapr 6 | args: run --app-id viewer --app-port 5000 --components-path ./components/local -- dotnet run --project ./src/csharp_viewer/viewer.csproj --urls "http://localhost:5000" 7 | 8 | - name: processor 9 | executable: dapr 10 | args: run --app-id processor --app-port 5030 --components-path ./components/local -- dotnet run --project ./src/csharp_processor/processor.csproj --urls "http://localhost:5030" 11 | env_file: 12 | - ../components/local/local.env 13 | 14 | - name: provider 15 | executable: dapr 16 | args: run --app-id provider --app-port 5040 --components-path ./components/local -- dotnet run --project ./src/csharp_provider/provider.csproj --urls "http://localhost:5040" -------------------------------------------------------------------------------- /DevOps/src/tye_multi.yaml: -------------------------------------------------------------------------------- 1 | name: observability 2 | 3 | services: 4 | - name: viewer 5 | executable: dapr 6 | args: run --app-id viewer --app-port 8088 --components-path ./components/local -- java -jar ./src/java_viewer/target/app.jar 7 | 8 | - name: processor 9 | executable: dapr 10 | args: run --app-id processor --app-port 5030 --components-path ./components/local -- dotnet run --project ./src/csharp_processor/processor.csproj --urls "http://localhost:5030" 11 | env_file: 12 | - ../components/local/local.env 13 | 14 | - name: provider 15 | executable: dapr 16 | args: run --app-id provider --app-port 5040 --app-protocol grpc --components-path ./components/local -- python3 ./src/python_provider/provider.py -------------------------------------------------------------------------------- /MyApp/.scripts/Deploy-AWSInfrastructure.ps1: -------------------------------------------------------------------------------- 1 | function Deploy-AWSInfrastructure { 2 | [CmdletBinding()] 3 | param () 4 | 5 | begin { 6 | Push-Location -Path './deploy/aws' 7 | } 8 | 9 | process { 10 | Deploy-AWS 11 | } 12 | 13 | end { 14 | Pop-Location 15 | } 16 | } -------------------------------------------------------------------------------- /MyApp/cleanUp.ps1: -------------------------------------------------------------------------------- 1 | # This will start the deletion of a resource group but not wait. 2 | 3 | [CmdletBinding()] 4 | param ( 5 | [Parameter( 6 | Position = 0, 7 | HelpMessage = "The name of the resource group to be created. All resources will be place in the resource group and start with name." 8 | )] 9 | [string] 10 | $rgName = "dapr_myapp_demo", 11 | 12 | [Parameter( 13 | HelpMessage = "Set to the location of the resources to use." 14 | )] 15 | [ValidateSet("all", "local", "azure", "aws")] 16 | [string] 17 | $env = "all", 18 | 19 | [switch] 20 | $force 21 | ) 22 | 23 | . "../.scripts/common.ps1" 24 | 25 | # Put the sampleRequests.http file back the way it was 26 | git restore ./sampleRequests.http 27 | 28 | if ($env -eq 'all' -or $env -eq 'local') { 29 | # Remove the myTestFile.txt 30 | Remove-Item ./src -Force -Recurse -ErrorAction SilentlyContinue 31 | Remove-Item ./.vscode -Force -Recurse -ErrorAction SilentlyContinue 32 | } 33 | 34 | if ($env -eq 'all' -or $env -eq 'azure') { 35 | # Remove local_secrets.json 36 | Remove-Item ./components/azure/local_secrets.json -ErrorAction SilentlyContinue 37 | 38 | Remove-ResourceGroup -name $rgName -force:$force -nowait 39 | } 40 | 41 | if ($env -eq 'all' -or $env -eq 'aws') { 42 | ### AWS 43 | Remove-AWS 44 | } -------------------------------------------------------------------------------- /MyApp/components/aws/pubsub.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: pubsub 5 | auth: 6 | secretStore: strongbox 7 | spec: 8 | type: pubsub.snssqs 9 | version: v1 10 | metadata: 11 | - name: region 12 | value: us-east-2 13 | - name: accessKey 14 | secretKeyRef: 15 | key: accessKey 16 | name: accessKey 17 | - name: secretKey 18 | secretKeyRef: 19 | key: secretKey 20 | name: secretKey 21 | -------------------------------------------------------------------------------- /MyApp/components/aws/pubsub_subscription.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Subscription 3 | metadata: 4 | name: servicebus-subscription 5 | spec: 6 | topic: new 7 | route: /new 8 | pubsubname: pubsub 9 | scopes: 10 | - myapp 11 | -------------------------------------------------------------------------------- /MyApp/components/aws/secretstore.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: strongbox 5 | spec: 6 | type: secretstores.local.file 7 | version: v1 8 | metadata: 9 | - name: secretsFile 10 | value: "./components/aws/local_secrets.json" -------------------------------------------------------------------------------- /MyApp/components/aws/state.aws.dynamodb.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: statestore 5 | spec: 6 | type: state.aws.dynamodb 7 | version: v1 8 | metadata: 9 | - name: table 10 | value: myapp_statestore 11 | - name: region 12 | value: us-east-2 -------------------------------------------------------------------------------- /MyApp/components/azure/secretstore.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: strongbox 5 | spec: 6 | type: secretstores.local.file 7 | version: v1 8 | metadata: 9 | - name: secretsFile 10 | value: "./components/azure/local_secrets.json" -------------------------------------------------------------------------------- /MyApp/components/azure/servicebus.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: pubsub 5 | auth: 6 | secretStore: strongbox 7 | spec: 8 | type: pubsub.azure.servicebus 9 | version: v1 10 | metadata: 11 | - name: connectionString 12 | secretKeyRef: 13 | key: serviceBusEndpoint 14 | name: serviceBusEndpoint 15 | -------------------------------------------------------------------------------- /MyApp/components/azure/servicebus_subscription.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Subscription 3 | metadata: 4 | name: servicebus-subscription 5 | spec: 6 | topic: new 7 | route: /new 8 | pubsubname: pubsub 9 | scopes: 10 | - myapp 11 | -------------------------------------------------------------------------------- /MyApp/components/azure/statestore.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: statestore 5 | auth: 6 | secretStore: strongbox 7 | spec: 8 | type: state.azure.tablestorage 9 | version: v1 10 | metadata: 11 | - name: accountName 12 | secretKeyRef: 13 | key: storageAccountName 14 | name: storageAccountName 15 | - name: accountKey 16 | secretKeyRef: 17 | key: storageAccountKey 18 | name: storageAccountKey 19 | - name: tableName 20 | value: weatherforecasts 21 | - name: cosmosDbMode 22 | value: false 23 | -------------------------------------------------------------------------------- /MyApp/components/local/pubsub.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: pubsub 5 | spec: 6 | type: pubsub.redis 7 | version: v1 8 | metadata: 9 | - name: redisHost 10 | value: localhost:6379 11 | - name: redisPassword 12 | value: "" 13 | -------------------------------------------------------------------------------- /MyApp/components/local/statestore.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: statestore 5 | spec: 6 | type: state.redis 7 | version: v1 8 | metadata: 9 | - name: redisHost 10 | value: localhost:6379 11 | - name: redisPassword 12 | value: "" 13 | - name: actorStateStore 14 | value: "true" 15 | -------------------------------------------------------------------------------- /MyApp/demo.ps1: -------------------------------------------------------------------------------- 1 | # This script issues and displays the correct dapr run command for running with 2 | # local or cloud resources. To run in the clould add the -env azure parameter. 3 | # If the script determines the infrastructure has not been deployed it will 4 | # call the setup script first. 5 | [CmdletBinding()] 6 | param ( 7 | [Parameter( 8 | Position = 0, 9 | HelpMessage = "The name of the resource group to be created. All resources will be place in the resource group and start with name." 10 | )] 11 | [string] 12 | $rgName = "dapr_myapp_demo", 13 | 14 | [Parameter( 15 | Position = 1, 16 | HelpMessage = "The location to store the meta data for the deployment." 17 | )] 18 | [string] 19 | $location = "eastus", 20 | 21 | [Parameter( 22 | HelpMessage = "Set to the location of the resources to use." 23 | )] 24 | [ValidateSet("local", "azure", "aws")] 25 | [string] 26 | $env = "local", 27 | 28 | [Parameter( 29 | HelpMessage = "When provided deploys the cloud infrastructure without running the demo." 30 | )] 31 | [switch] 32 | $deployOnly 33 | ) 34 | 35 | . "../.scripts/common.ps1" 36 | . "./.scripts/Deploy-AWSInfrastructure.ps1" 37 | . "./.scripts/Deploy-AzureInfrastructure.ps1" 38 | 39 | # This will deploy the infrastructure without running the demo. You can use 40 | # this flag to set everything up before you run the demos to save time. Some 41 | # infrastucture can take some time to deploy. 42 | if ($deployOnly.IsPresent) { 43 | Deploy-AWSInfrastructure 44 | Deploy-AzureInfrastructure -rgName $rgName -location $location 45 | 46 | return 47 | } 48 | 49 | # Load the sample requests file for the demo 50 | code ./sampleRequests.http 51 | 52 | if ($env -eq "azure") { 53 | Write-Output "Running demo with Azure resources" 54 | 55 | # If you don't find the ./components/azure/local_secrets.json deploy infrastucture 56 | if ($(Test-Path -Path './components/azure/local_secrets.json') -eq $false) { 57 | Write-Output "Could not find ./components/azure/local_secrets.json" 58 | Deploy-AzureInfrastructure -rgName $rgName -location $location 59 | } 60 | } 61 | elseif ($env -eq "aws") { 62 | # If you don't find the ./deploy/aws/terraform.tfvars deploy infrastucture 63 | if ($(Test-Path -Path './deploy/aws/terraform.tfvars') -eq $false) { 64 | Write-Output "Could not find ./deploy/aws/terraform.tfvars" 65 | Deploy-AWSInfrastructure 66 | } 67 | } 68 | 69 | Write-Output "Running demo with $env resources" 70 | Write-Output "dapr run --app-id myapp --app-port 5000 --dapr-http-port 3500 --components-path ./components/$env -- dotnet run --project ./src/myapp/ --urls http://*:5000 `n" 71 | dapr run --app-id myapp --app-port 5000 --dapr-http-port 3500 --components-path ./components/$env -- dotnet run --project ./src/myapp/ --urls http://*:5000 -------------------------------------------------------------------------------- /MyApp/deploy/aws/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | access_key = var.access_key 3 | secret_key = var.secret_key 4 | region = var.region 5 | } 6 | 7 | resource "aws_sns_topic" "dapr_pubsub" { 8 | name = var.sns_name 9 | tags = { 10 | dapr-topic-name = "${var.sns_name}" 11 | } 12 | } 13 | 14 | resource "aws_sqs_queue" "dapr_pubsub_queue" { 15 | name = var.sqs_name 16 | tags = { 17 | dapr-queue-name = "${var.sqs_name}" 18 | } 19 | } 20 | 21 | resource "aws_sns_topic_subscription" "dapr_pubsub_sqs_target" { 22 | topic_arn = aws_sns_topic.dapr_pubsub.arn 23 | protocol = "sqs" 24 | endpoint = aws_sqs_queue.dapr_pubsub_queue.arn 25 | } 26 | 27 | resource "aws_dynamodb_table" "dapr_state_store" { 28 | name = var.table_name 29 | billing_mode = var.table_billing_mode 30 | hash_key = "key" 31 | attribute { 32 | name = "key" 33 | type = "S" 34 | } 35 | tags = { 36 | environment = "${var.environment}" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /MyApp/deploy/aws/variables.tf: -------------------------------------------------------------------------------- 1 | variable "access_key" { 2 | description = "Access key to AWS console" 3 | } 4 | 5 | variable "secret_key" { 6 | description = "Secret key to AWS console" 7 | } 8 | 9 | variable "region" { 10 | description = "The region to use to create the resource" 11 | default = "us-east-2" 12 | } 13 | 14 | variable "sqs_name" { 15 | description = "SQS name (A queue name is case-sensitive and can have up to 80 characters. You can use alphanumeric characters, hyphens (-), and underscores ( _ ).)" 16 | default = "myapp" 17 | } 18 | 19 | variable "sns_name" { 20 | description = "SNS name (space is not allowed)" 21 | default = "new" 22 | } 23 | 24 | variable "table_name" { 25 | description = "Dynamodb table name (space is not allowed)" 26 | default = "myapp_statestore" 27 | } 28 | 29 | variable "table_billing_mode" { 30 | description = "Controls how you are charged for read and write throughput and how you manage capacity." 31 | default = "PAY_PER_REQUEST" 32 | } 33 | 34 | variable "environment" { 35 | description = "Name of environment" 36 | default = "codespace" 37 | } 38 | -------------------------------------------------------------------------------- /MyApp/deploy/azure/main.bicep: -------------------------------------------------------------------------------- 1 | targetScope = 'subscription' 2 | 3 | param location string = 'eastus' 4 | param rgName string = 'dapr_myapp_demo' 5 | 6 | resource rg 'Microsoft.Resources/resourceGroups@2021-04-01' = { 7 | name: rgName 8 | location: location 9 | } 10 | 11 | module myapp './myapp.bicep' = { 12 | name: 'myapp' 13 | scope: resourceGroup(rg.name) 14 | params: { 15 | location: location 16 | } 17 | } 18 | 19 | output storageAccountName string = myapp.outputs.storageAccountName 20 | 21 | output serviceBusAuthRule string = myapp.outputs.serviceBusAuthRule 22 | output serviceBusNamespace string = myapp.outputs.serviceBusNamespace 23 | -------------------------------------------------------------------------------- /MyApp/deploy/azure/myapp.bicep: -------------------------------------------------------------------------------- 1 | param location string 2 | 3 | // PubSub backed by Azure Service Bus 4 | resource sb 'Microsoft.ServiceBus/namespaces@2021-06-01-preview' = { 5 | name: 'sb${uniqueString(resourceGroup().id)}' 6 | location: location 7 | sku: { 8 | name: 'Standard' 9 | tier: 'Standard' 10 | } 11 | properties: {} 12 | } 13 | 14 | resource sbAuthRule 'Microsoft.ServiceBus/namespaces/AuthorizationRules@2021-06-01-preview' existing = { 15 | parent: sb 16 | name: 'RootManageSharedAccessKey' 17 | } 18 | 19 | // State Store using Azure Table Storage 20 | resource stg 'Microsoft.Storage/storageAccounts@2019-06-01' = { 21 | name: toLower('stg${uniqueString(resourceGroup().id)}') // must be globally unique 22 | location: location 23 | kind: 'Storage' 24 | sku: { 25 | name: 'Standard_LRS' 26 | } 27 | } 28 | 29 | output storageAccountName string = stg.name 30 | 31 | output serviceBusNamespace string = sb.name 32 | output serviceBusAuthRule string = sbAuthRule.name 33 | -------------------------------------------------------------------------------- /MyApp/sampleRequests.http: -------------------------------------------------------------------------------- 1 | POST http://localhost:3500/v1.0/publish/pubsub/new 2 | Content-Type: application/json 3 | 4 | { 5 | "Summary": "hot", 6 | "Location": "77379", 7 | "TemperatureC": "46" 8 | } 9 | 10 | ### 11 | 12 | GET http://localhost:3500/v1.0/invoke/myapp/method/weatherforecast/77379 -------------------------------------------------------------------------------- /Observability/.scripts/Deploy-AzureInfrastructure.ps1: -------------------------------------------------------------------------------- 1 | # This function will run an bicep deployment to deploy all the required 2 | # resources into Azure. All the keys, tokens and endpoints will be 3 | # automatically retreived and written to ./components/azure/local_secrets.json. 4 | # PowerShell Core 7 (runs on macOS, Linux and Windows) 5 | # Azure CLI (log in, runs on macOS, Linux and Windows) 6 | function Deploy-AzureInfrastructure { 7 | [CmdletBinding()] 8 | param ( 9 | [Parameter( 10 | Position = 0, 11 | HelpMessage = "The name of the resource group to be created. All resources will be place in the resource group and start with name." 12 | )] 13 | [string] 14 | $rgName, 15 | 16 | [Parameter( 17 | Position = 1, 18 | HelpMessage = "The location to store the meta data for the deployment." 19 | )] 20 | [string] 21 | $location 22 | ) 23 | 24 | begin { 25 | Push-Location -Path './deploy' 26 | } 27 | 28 | process { 29 | Write-Output 'Deploying the infrastructure' 30 | $deployment = $(az deployment sub create --name $rgName ` 31 | --location $location ` 32 | --template-file ./azure/main.bicep ` 33 | --parameters location=$location ` 34 | --parameters rgName=$rgName ` 35 | --output json) | ConvertFrom-Json 36 | 37 | # Store the outputs from the deployment to create 38 | # config/azure/otel-local-config.yaml 39 | $instrumentationKey = $deployment.properties.outputs.instrumentationKey.value 40 | 41 | Write-Verbose "instrumentationKey = $instrumentationKey" 42 | 43 | # Populating config/azure/otel-local-config.yaml 44 | $config = $(Get-Content ../config/azure/otel-local-config.yaml | Convertfrom-Yaml) 45 | $config.exporters.azuremonitor.instrumentation_key = $instrumentationKey 46 | 47 | Write-Output 'Saving ./config/azure/otel-local-config.yaml' 48 | $config | ConvertTo-Yaml | Set-Content ../config/azure/otel-local-config.yaml 49 | } 50 | 51 | end { 52 | Pop-Location 53 | } 54 | } -------------------------------------------------------------------------------- /Observability/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "compounds": [ 7 | // For more information, visit: https://code.visualstudio.com/docs/editor/debugging#_compound-launch-configurations 8 | { 9 | "name": "All Services", 10 | "preLaunchTask": "build", 11 | "configurations": [ 12 | "ServiceA", 13 | "ServiceB", 14 | "ServiceC" 15 | ], 16 | "stopAll": true 17 | } 18 | ], 19 | "configurations": [ 20 | { 21 | "name": "ServiceA", 22 | "type": "coreclr", 23 | "request": "launch", 24 | "preLaunchTask": "run_ServiceA", 25 | "program": "${workspaceFolder}/src/serviceA/bin/Debug/net6.0/serviceA.dll", 26 | "args": [], 27 | "cwd": "${workspaceFolder}/src/serviceA", 28 | "stopAtEntry": false, 29 | "env": { 30 | "ASPNETCORE_ENVIRONMENT": "Development", 31 | "ASPNETCORE_URLS": "http://localhost:5000" 32 | }, 33 | "postDebugTask": "stop_ServiceA" 34 | }, 35 | { 36 | "name": "ServiceB", 37 | "type": "coreclr", 38 | "request": "launch", 39 | "preLaunchTask": "run_ServiceB", 40 | "program": "${workspaceFolder}/src/serviceB/bin/Debug/net6.0/serviceB.dll", 41 | "args": [], 42 | "cwd": "${workspaceFolder}/src/serviceB", 43 | "stopAtEntry": false, 44 | "env": { 45 | "ASPNETCORE_ENVIRONMENT": "Development", 46 | "ASPNETCORE_URLS": "http://localhost:5010" 47 | }, 48 | "postDebugTask": "stop_ServiceB" 49 | }, 50 | { 51 | "name": "ServiceC", 52 | "type": "coreclr", 53 | "request": "launch", 54 | "preLaunchTask": "run_ServiceC", 55 | "program": "${workspaceFolder}/src/serviceC/bin/Debug/net6.0/serviceC.dll", 56 | "args": [], 57 | "cwd": "${workspaceFolder}/src/serviceC", 58 | "stopAtEntry": false, 59 | "env": { 60 | "ASPNETCORE_ENVIRONMENT": "Development", 61 | "ASPNETCORE_URLS": "http://localhost:5020" 62 | }, 63 | "postDebugTask": "stop_ServiceC" 64 | } 65 | ] 66 | } -------------------------------------------------------------------------------- /Observability/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "label": "build", 6 | "command": "dotnet", 7 | "type": "process", 8 | "args": [ 9 | "build", 10 | "${workspaceFolder}/src/services.sln", 11 | "/property:GenerateFullPaths=true", 12 | "/consoleloggerparameters:NoSummary" 13 | ], 14 | "problemMatcher": "$msCompile" 15 | }, 16 | { 17 | "label": "run_ServiceA", 18 | "appId": "serviceA", 19 | "appPort": 5000, 20 | "httpPort": 3500, 21 | "grpcPort": 50001, 22 | "type": "dapr" 23 | }, 24 | { 25 | "label": "stop_ServiceA", 26 | "appId": "serviceA", 27 | "type": "daprd-down" 28 | }, 29 | { 30 | "label": "run_ServiceB", 31 | "appId": "serviceB", 32 | "appPort": 5010, 33 | "grpcPort": 50002, 34 | "type": "dapr" 35 | }, 36 | { 37 | "label": "stop_ServiceB", 38 | "appId": "serviceB", 39 | "type": "daprd-down" 40 | }, 41 | { 42 | "label": "run_ServiceC", 43 | "appId": "serviceC", 44 | "appPort": 5020, 45 | "grpcPort": 50003, 46 | "type": "dapr" 47 | }, 48 | { 49 | "label": "stop_ServiceC", 50 | "appId": "serviceC", 51 | "type": "daprd-down" 52 | } 53 | ] 54 | } -------------------------------------------------------------------------------- /Observability/README.md: -------------------------------------------------------------------------------- 1 | # Observability demo 2 | 3 | The purpose of this demo is to show the configuration of [observability](https://docs.dapr.io/developing-applications/building-blocks/observability/) locally and in the cloud. 4 | 5 | Open the _demo_observability.code-workspace_ file and click the **Open Workspace** button in the lower right corner. 6 | 7 | ![open workspace](../.images/OpenWorkspace.png) 8 | 9 | This will reload your Codespace and scope your Explorer to just the folders needed for this demo. 10 | 11 | To provision the infrastructure before the demo execute the following command in the terminal. 12 | 13 | ``` 14 | ./demo.ps1 -deployOnly 15 | ``` 16 | 17 | This code is automatically run by the _demo.ps1_ script if the `-env` parameter is passed and *./azureConfig/otel-local-config.yaml* file is missing the Azure Application Insights instrumentation key. 18 | 19 | The workspace consists of one top level folder _Observability_. This folder holds the _azureConfig_, _deploy_, and _src_ folders. The _azureConfig_ folder holds the _otel-local-config.yaml_ file that contains the configuration for the [Open Telemetry Collector used to send the data to Application Insights](https://docs.dapr.io/operations/monitoring/tracing/open-telemetry-collector-appinsights/). The Open Telemetry Collector is run in a local container. 20 | 21 | The core of the demo is in the _src_ folder. This folder holds three services, Service A, B, and C. Service A subscribes to the **PubSub** component. When a new order is received (1) Service A calls Service B using service to service invocation (2). When Service A gets a response from Service B, Service A stores the processed order using the **StateStore** component (3). Finally, Service A publishes the order to the **PubSub** component where Service C reads it (4). 22 | 23 | ![services architecture](../.images/Services.png) 24 | 25 | To start this demo open the _sampleRequests.http_ file. At the top of the file are two _demo.ps1_ commands. One for running the requests with a local configuration and one for running with the cloud configuration. Copy the desired command and run it in the terminal. This will start all three services with the appropriate configuration for the demo. The Dapr run commands issued are output if you want to explain during the demo. 26 | 27 | Running local 28 | ``` 29 | ./demo.ps1 30 | ``` 31 | 32 | Running in cloud 33 | ``` 34 | ./demo.ps1 -env azure 35 | ``` 36 | 37 | Click the Send Request button above of the request to post a new order to Service A to start the demo. After clicking the link a few times you can view the tracing information. 38 | 39 | When running locally you can expand the _tempfiles_ folder to show the data being stored and deleted. 40 | 41 | When you are done with the demo you can clean up the cloud resources by running the _cleanUp.ps1_ script using the following commands: 42 | 43 | ``` 44 | ./cleanUp.ps1 45 | ``` -------------------------------------------------------------------------------- /Observability/cleanUp.ps1: -------------------------------------------------------------------------------- 1 | # This will start the deletion of a resource group but not wait. 2 | 3 | [CmdletBinding()] 4 | param ( 5 | [Parameter( 6 | Position = 0, 7 | HelpMessage = "The name of the resource group to be created. All resources will be place in the resource group and start with name." 8 | )] 9 | [string] 10 | $rgName = "dapr_observability_demo", 11 | 12 | [switch] 13 | $force 14 | ) 15 | 16 | . ../.scripts/common.ps1 17 | 18 | # Put the otel-local-config.yaml file back the way it was 19 | git restore ./config/azure/otel-local-config.yaml 20 | 21 | Remove-ResourceGroup -name $rgName -force:$force -nowait -------------------------------------------------------------------------------- /Observability/config/azure/otel-local-config.yaml: -------------------------------------------------------------------------------- 1 | extensions: 2 | pprof: 3 | endpoint: :1888 4 | zpages: 5 | endpoint: :55679 6 | health_check: 7 | service: 8 | pipelines: 9 | traces: 10 | exporters: 11 | - azuremonitor 12 | - logging 13 | receivers: 14 | - zipkin 15 | extensions: 16 | - pprof 17 | - zpages 18 | - health_check 19 | receivers: 20 | zipkin: 21 | exporters: 22 | logging: 23 | loglevel: debug 24 | azuremonitor: 25 | maxbatchinterval: 5s 26 | instrumentation_key: '' 27 | maxbatchsize: 5 28 | 29 | -------------------------------------------------------------------------------- /Observability/deploy/azure/main.bicep: -------------------------------------------------------------------------------- 1 | targetScope = 'subscription' 2 | 3 | param location string = 'eastus' 4 | param rgName string = 'dapr_observability_demo' 5 | 6 | resource rg 'Microsoft.Resources/resourceGroups@2021-04-01' = { 7 | name: rgName 8 | location: location 9 | } 10 | 11 | module observability './observability.bicep' = { 12 | name: 'observability' 13 | scope: resourceGroup(rg.name) 14 | params: { 15 | location: location 16 | } 17 | } 18 | 19 | output instrumentationKey string = observability.outputs.instrumentationKey 20 | -------------------------------------------------------------------------------- /Observability/deploy/azure/observability.bicep: -------------------------------------------------------------------------------- 1 | param location string 2 | 3 | resource workspace 'Microsoft.OperationalInsights/workspaces@2020-10-01' = { 4 | name: 'ws${uniqueString(resourceGroup().id)}' 5 | location: location 6 | } 7 | 8 | resource appInsights 'Microsoft.Insights/components@2020-02-02-preview' = { 9 | name: 'appi${uniqueString(resourceGroup().id)}' 10 | kind: 'web' 11 | location: location 12 | properties: { 13 | Application_Type: 'web' 14 | WorkspaceResourceId: workspace.id 15 | publicNetworkAccessForQuery: 'Enabled' 16 | publicNetworkAccessForIngestion: 'Enabled' 17 | } 18 | } 19 | 20 | output instrumentationKey string = appInsights.properties.InstrumentationKey 21 | -------------------------------------------------------------------------------- /Observability/sampleRequests.http: -------------------------------------------------------------------------------- 1 | # Use this command to run local 2 | # ./demo.ps1 3 | 4 | # Use this command to run in the cloud 5 | # ./demo.ps1 -env azure 6 | 7 | POST http://localhost:3500/v1.0/publish/pubsub/incomingorders 8 | Content-Type: application/json 9 | 10 | {"orderId":"43"} -------------------------------------------------------------------------------- /Observability/src/serviceA/Program.cs: -------------------------------------------------------------------------------- 1 | var builder = WebApplication.CreateBuilder(args); 2 | builder.Services.AddControllers().AddDapr(); 3 | 4 | // Configure and enable middlewares 5 | var app = builder.Build(); 6 | app.UseCloudEvents(); 7 | app.UseRouting(); 8 | app.UseEndpoints(endpoints => endpoints.MapSubscribeHandler()); 9 | 10 | app.MapPost("/incomingorders", async (Order o, Dapr.Client.DaprClient client) => 11 | { 12 | app.Logger.LogInformation("order received"); 13 | app.Logger.LogInformation("calling serviceB"); 14 | var processedOrder = await client.InvokeMethodAsync("serviceB", "process", o); 15 | app.Logger.LogInformation("saving to state store"); 16 | await client.SaveStateAsync("statestore", "orders", processedOrder); 17 | app.Logger.LogInformation("publish to processedorders"); 18 | await client.PublishEventAsync("pubsub", "processedorders", processedOrder); 19 | }).WithTopic("pubsub", "incomingorders"); 20 | 21 | app.Run(); 22 | 23 | public record Order(string OrderId, string State); -------------------------------------------------------------------------------- /Observability/src/serviceA/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Observability/src/serviceA/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "AllowedHosts": "*" 10 | } 11 | -------------------------------------------------------------------------------- /Observability/src/serviceA/serviceA.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Observability/src/serviceB/Program.cs: -------------------------------------------------------------------------------- 1 | var app = WebApplication.Create(args); 2 | 3 | app.MapPost("/process", (Order o) => 4 | { 5 | app.Logger.LogInformation("processing order"); 6 | return new Order(o.OrderId, $"Processed at {DateTime.UtcNow}"); 7 | }); 8 | 9 | await app.RunAsync(); 10 | 11 | public record Order(string OrderId, string State); -------------------------------------------------------------------------------- /Observability/src/serviceB/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Observability/src/serviceB/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "AllowedHosts": "*" 10 | } 11 | -------------------------------------------------------------------------------- /Observability/src/serviceB/serviceB.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Observability/src/serviceC/Program.cs: -------------------------------------------------------------------------------- 1 | var builder = WebApplication.CreateBuilder(args); 2 | builder.Services.AddControllers().AddDapr(); 3 | 4 | // Configure and enable middlewares 5 | var app = builder.Build(); 6 | app.UseCloudEvents(); 7 | app.UseRouting(); 8 | app.UseEndpoints(endpoints => endpoints.MapSubscribeHandler()); 9 | 10 | app.MapPost("/revieworder", (Order order) => 11 | { 12 | app.Logger.LogInformation($"Reviewing order {order.OrderId} that was processed at {order.State}"); 13 | }).WithTopic("pubsub", "processedorders"); 14 | 15 | app.Run(); 16 | 17 | public record Order(string OrderId, string State); -------------------------------------------------------------------------------- /Observability/src/serviceC/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Observability/src/serviceC/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "AllowedHosts": "*" 10 | } 11 | -------------------------------------------------------------------------------- /Observability/src/serviceC/serviceC.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Observability/src/services.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30114.105 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "serviceA", "serviceA\serviceA.csproj", "{D96728D2-E312-496A-8563-51E7C8324CD9}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "serviceB", "serviceB\serviceB.csproj", "{C983819F-DFD5-4B8B-80BB-F9C3FEC4562D}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "serviceC", "serviceC\serviceC.csproj", "{F0709A7D-C512-4465-856A-F145E73B55EB}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 21 | {D96728D2-E312-496A-8563-51E7C8324CD9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 22 | {D96728D2-E312-496A-8563-51E7C8324CD9}.Debug|Any CPU.Build.0 = Debug|Any CPU 23 | {D96728D2-E312-496A-8563-51E7C8324CD9}.Release|Any CPU.ActiveCfg = Release|Any CPU 24 | {D96728D2-E312-496A-8563-51E7C8324CD9}.Release|Any CPU.Build.0 = Release|Any CPU 25 | {C983819F-DFD5-4B8B-80BB-F9C3FEC4562D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 26 | {C983819F-DFD5-4B8B-80BB-F9C3FEC4562D}.Debug|Any CPU.Build.0 = Debug|Any CPU 27 | {C983819F-DFD5-4B8B-80BB-F9C3FEC4562D}.Release|Any CPU.ActiveCfg = Release|Any CPU 28 | {C983819F-DFD5-4B8B-80BB-F9C3FEC4562D}.Release|Any CPU.Build.0 = Release|Any CPU 29 | {F0709A7D-C512-4465-856A-F145E73B55EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 30 | {F0709A7D-C512-4465-856A-F145E73B55EB}.Debug|Any CPU.Build.0 = Debug|Any CPU 31 | {F0709A7D-C512-4465-856A-F145E73B55EB}.Release|Any CPU.ActiveCfg = Release|Any CPU 32 | {F0709A7D-C512-4465-856A-F145E73B55EB}.Release|Any CPU.Build.0 = Release|Any CPU 33 | EndGlobalSection 34 | EndGlobal 35 | -------------------------------------------------------------------------------- /Observability/src/tye_cloud.yaml: -------------------------------------------------------------------------------- 1 | name: observability 2 | 3 | services: 4 | - name: serviceA 5 | executable: dapr 6 | args: run -a serviceA -p 5000 -H 3500 -- dotnet run --project ./src/serviceA/serviceA.csproj --urls "http://localhost:5000" 7 | 8 | - name: serviceB 9 | executable: dapr 10 | args: run -a serviceB -p 5010 -- dotnet run --project ./src/serviceB/serviceB.csproj --urls "http://localhost:5010" 11 | 12 | - name: serviceC 13 | executable: dapr 14 | args: run -a serviceC -p 5020 -- dotnet run --project ./src/serviceC/serviceC.csproj --urls "http://localhost:5020" 15 | 16 | - name: openTelemetry 17 | image: otel/opentelemetry-collector-contrib-dev 18 | bindings: 19 | - port: 9411 20 | volumes: 21 | - source: ../config/azure/otel-local-config.yaml 22 | target: /etc/otel/config.yaml -------------------------------------------------------------------------------- /Observability/src/tye_local.yaml: -------------------------------------------------------------------------------- 1 | name: observability 2 | 3 | services: 4 | - name: serviceA 5 | executable: dapr 6 | args: run -a serviceA -p 5000 -H 3500 -- dotnet run --project ./src/serviceA/serviceA.csproj --urls "http://localhost:5000" 7 | 8 | - name: serviceB 9 | executable: dapr 10 | args: run -a serviceB -p 5010 -- dotnet run --project ./src/serviceB/serviceB.csproj --urls "http://localhost:5010" 11 | 12 | - name: serviceC 13 | executable: dapr 14 | args: run -a serviceC -p 5020 -- dotnet run --project ./src/serviceC/serviceC.csproj --urls "http://localhost:5020" 15 | -------------------------------------------------------------------------------- /PubSub/.scripts/Deploy-AWSInfrastructure.ps1: -------------------------------------------------------------------------------- 1 | function Deploy-AWSInfrastructure { 2 | [CmdletBinding()] 3 | param () 4 | 5 | begin { 6 | Push-Location -Path './deploy/aws' 7 | } 8 | 9 | process { 10 | Deploy-AWS 11 | } 12 | 13 | end { 14 | Pop-Location 15 | } 16 | } -------------------------------------------------------------------------------- /PubSub/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Dapr Local", 6 | "type": "coreclr", 7 | "request": "launch", 8 | "preLaunchTask": "daprd-local-debug", 9 | "program": "${workspaceFolder}/src/bin/Debug/net6.0/src.dll", 10 | "args": [], 11 | "cwd": "${workspaceFolder}/src", 12 | "stopAtEntry": false, 13 | "env": { 14 | "ASPNETCORE_ENVIRONMENT": "Development" 15 | }, 16 | "postDebugTask": "daprd-down" 17 | }, 18 | { 19 | "name": "Dapr Azure", 20 | "type": "coreclr", 21 | "request": "launch", 22 | "preLaunchTask": "daprd-azure-debug", 23 | "program": "${workspaceFolder}/src/bin/Debug/net6.0/src.dll", 24 | "args": [], 25 | "cwd": "${workspaceFolder}/src", 26 | "stopAtEntry": false, 27 | "env": { 28 | "ASPNETCORE_ENVIRONMENT": "Development" 29 | }, 30 | "postDebugTask": "daprd-down" 31 | }, 32 | { 33 | "name": "Dapr AWS", 34 | "type": "coreclr", 35 | "request": "launch", 36 | "preLaunchTask": "daprd-aws-debug", 37 | "program": "${workspaceFolder}/src/bin/Debug/net6.0/src.dll", 38 | "args": [], 39 | "cwd": "${workspaceFolder}/src", 40 | "stopAtEntry": false, 41 | "env": { 42 | "ASPNETCORE_ENVIRONMENT": "Development" 43 | }, 44 | "postDebugTask": "daprd-down" 45 | } 46 | ] 47 | } -------------------------------------------------------------------------------- /PubSub/cleanUp.ps1: -------------------------------------------------------------------------------- 1 | # This will start the deletion of a resource group but not wait. 2 | 3 | [CmdletBinding()] 4 | param ( 5 | [Parameter( 6 | Position = 0, 7 | HelpMessage = "The name of the resource group to be created. All resources will be place in the resource group and start with name." 8 | )] 9 | [string] 10 | $rgName = "dapr_pubsub_demo", 11 | 12 | [Parameter( 13 | HelpMessage = "Set to the location of the resources to use." 14 | )] 15 | [ValidateSet("all", "azure", "aws")] 16 | [string] 17 | $env = "all", 18 | 19 | [switch] 20 | $force 21 | ) 22 | 23 | . ../.scripts/common.ps1 24 | 25 | if ($env -eq 'all' -or $env -eq 'azure') { 26 | # Remove local_secrets.json 27 | Remove-Item ./components/azure/local_secrets.json -ErrorAction SilentlyContinue 28 | 29 | Remove-ResourceGroup -name $rgName -force:$force -nowait 30 | } 31 | 32 | if ($env -eq 'all' -or $env -eq 'aws') { 33 | ### AWS 34 | Remove-AWS 35 | } -------------------------------------------------------------------------------- /PubSub/components/aws/pubsub1.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: pubsub1 5 | auth: 6 | secretStore: strongbox 7 | spec: 8 | type: pubsub.snssqs 9 | version: v1 10 | metadata: 11 | - name: region 12 | value: us-east-2 13 | - name: accessKey 14 | secretKeyRef: 15 | key: accessKey 16 | name: accessKey 17 | - name: secretKey 18 | secretKeyRef: 19 | key: secretKey 20 | name: secretKey 21 | -------------------------------------------------------------------------------- /PubSub/components/aws/pubsub1_subscription.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Subscription 3 | metadata: 4 | name: servicebus-subscription 5 | spec: 6 | topic: neworder 7 | route: /neworder 8 | pubsubname: pubsub1 9 | scopes: 10 | - app1 11 | -------------------------------------------------------------------------------- /PubSub/components/aws/pubsub2.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: pubsub2 5 | auth: 6 | secretStore: strongbox 7 | spec: 8 | type: pubsub.snssqs 9 | version: v1 10 | metadata: 11 | - name: region 12 | value: us-east-2 13 | - name: accessKey 14 | secretKeyRef: 15 | key: accessKey 16 | name: accessKey 17 | - name: secretKey 18 | secretKeyRef: 19 | key: secretKey 20 | name: secretKey 21 | -------------------------------------------------------------------------------- /PubSub/components/aws/pubsub2_subscription.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Subscription 3 | metadata: 4 | name: eventhubs-subscription 5 | spec: 6 | topic: neworder 7 | route: /neworder 8 | pubsubname: pubsub2 9 | scopes: 10 | - app1 11 | -------------------------------------------------------------------------------- /PubSub/components/aws/secretstore.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: strongbox 5 | spec: 6 | type: secretstores.local.file 7 | version: v1 8 | metadata: 9 | - name: secretsFile 10 | value: "./components/aws/local_secrets.json" -------------------------------------------------------------------------------- /PubSub/components/aws/state.aws.dynamodb.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: statestore 5 | spec: 6 | type: state.aws.dynamodb 7 | version: v1 8 | metadata: 9 | - name: table 10 | value: pubsub_statestore 11 | - name: region 12 | value: us-east-2 -------------------------------------------------------------------------------- /PubSub/components/azure/eventhubs.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: pubsub2 5 | auth: 6 | secretStore: strongbox 7 | spec: 8 | type: pubsub.azure.eventhubs 9 | version: v1 10 | metadata: 11 | - name: connectionString 12 | secretKeyRef: 13 | key: eventHubsEndpoint 14 | name: eventHubsEndpoint 15 | - name: storageAccountName 16 | secretKeyRef: 17 | key: storageAccountName 18 | name: storageAccountName 19 | - name: storageAccountKey 20 | secretKeyRef: 21 | key: storageAccountKey 22 | name: storageAccountKey 23 | - name: storageContainerName 24 | value: "neworder" 25 | -------------------------------------------------------------------------------- /PubSub/components/azure/eventhubs_subscription.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Subscription 3 | metadata: 4 | name: eventhubs-subscription 5 | spec: 6 | topic: neworder 7 | route: /neworder 8 | pubsubname: pubsub2 9 | scopes: 10 | - app1 11 | -------------------------------------------------------------------------------- /PubSub/components/azure/secretstore.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: strongbox 5 | spec: 6 | type: secretstores.local.file 7 | version: v1 8 | metadata: 9 | - name: secretsFile 10 | value: "./components/azure/local_secrets.json" -------------------------------------------------------------------------------- /PubSub/components/azure/servicebus.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: pubsub1 5 | auth: 6 | secretStore: strongbox 7 | spec: 8 | type: pubsub.azure.servicebus 9 | version: v1 10 | metadata: 11 | - name: connectionString 12 | secretKeyRef: 13 | key: serviceBusEndpoint 14 | name: serviceBusEndpoint 15 | -------------------------------------------------------------------------------- /PubSub/components/azure/servicebus_subscription.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Subscription 3 | metadata: 4 | name: servicebus-subscription 5 | spec: 6 | topic: neworder 7 | route: /neworder 8 | pubsubname: pubsub1 9 | scopes: 10 | - app1 11 | -------------------------------------------------------------------------------- /PubSub/components/azure/statestore.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: statestore 5 | auth: 6 | secretStore: strongbox 7 | spec: 8 | type: state.sqlserver 9 | version: v1 10 | metadata: 11 | - name: connectionString 12 | secretKeyRef: 13 | key: sqlConnectionString 14 | name: sqlConnectionString 15 | -------------------------------------------------------------------------------- /PubSub/components/local/pubsub1.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: pubsub1 5 | spec: 6 | type: pubsub.redis 7 | version: v1 8 | metadata: 9 | - name: redisHost 10 | value: localhost:6379 11 | - name: redisPassword 12 | value: "" 13 | -------------------------------------------------------------------------------- /PubSub/components/local/pubsub1_subscription.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Subscription 3 | metadata: 4 | name: myevent-subscription 5 | spec: 6 | topic: neworder 7 | route: /neworder 8 | pubsubname: pubsub1 9 | scopes: 10 | - app1 11 | -------------------------------------------------------------------------------- /PubSub/components/local/pubsub2.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: pubsub2 5 | spec: 6 | type: pubsub.redis 7 | version: v1 8 | metadata: 9 | - name: redisHost 10 | value: localhost:6379 11 | - name: redisPassword 12 | value: "" 13 | -------------------------------------------------------------------------------- /PubSub/components/local/pubsub2_subscription.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Subscription 3 | metadata: 4 | name: myevent-subscription 5 | spec: 6 | topic: neworder 7 | route: /neworder 8 | pubsubname: pubsub2 9 | scopes: 10 | - app1 11 | -------------------------------------------------------------------------------- /PubSub/components/local/statestore.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: statestore 5 | spec: 6 | type: state.redis 7 | version: v1 8 | metadata: 9 | - name: redisHost 10 | value: localhost:6379 11 | - name: redisPassword 12 | value: "" 13 | - name: actorStateStore 14 | value: "true" 15 | -------------------------------------------------------------------------------- /PubSub/deploy/aws/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | access_key = var.access_key 3 | secret_key = var.secret_key 4 | region = var.region 5 | } 6 | 7 | resource "aws_sns_topic" "dapr_pubsub" { 8 | name = var.sns_name 9 | tags = { 10 | dapr-topic-name = "${var.sns_name}" 11 | } 12 | } 13 | 14 | resource "aws_sqs_queue" "dapr_pubsub_queue" { 15 | name = var.sqs_name 16 | tags = { 17 | dapr-queue-name = "${var.sqs_name}" 18 | } 19 | } 20 | 21 | resource "aws_sns_topic_subscription" "dapr_pubsub_sqs_target" { 22 | topic_arn = aws_sns_topic.dapr_pubsub.arn 23 | protocol = "sqs" 24 | endpoint = aws_sqs_queue.dapr_pubsub_queue.arn 25 | } 26 | 27 | resource "aws_dynamodb_table" "dapr_state_store" { 28 | name = var.table_name 29 | billing_mode = var.table_billing_mode 30 | hash_key = "key" 31 | attribute { 32 | name = "key" 33 | type = "S" 34 | } 35 | tags = { 36 | environment = "${var.environment}" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /PubSub/deploy/aws/variables.tf: -------------------------------------------------------------------------------- 1 | variable "access_key" { 2 | description = "Access key to AWS console" 3 | } 4 | 5 | variable "secret_key" { 6 | description = "Secret key to AWS console" 7 | } 8 | 9 | variable "region" { 10 | description = "The region to use to create the resource" 11 | default = "us-east-2" 12 | } 13 | 14 | variable "sqs_name" { 15 | description = "SQS name (A queue name is case-sensitive and can have up to 80 characters. You can use alphanumeric characters, hyphens (-), and underscores ( _ ).)" 16 | default = "app1" 17 | } 18 | 19 | variable "sns_name" { 20 | description = "SNS name (space is not allowed)" 21 | default = "neworder" 22 | } 23 | 24 | variable "table_name" { 25 | description = "Dynamodb table name (space is not allowed)" 26 | default = "pubsub_statestore" 27 | } 28 | 29 | variable "table_billing_mode" { 30 | description = "Controls how you are charged for read and write throughput and how you manage capacity." 31 | default = "PAY_PER_REQUEST" 32 | } 33 | 34 | variable "environment" { 35 | description = "Name of environment" 36 | default = "codespace" 37 | } 38 | -------------------------------------------------------------------------------- /PubSub/deploy/azure/main.bicep: -------------------------------------------------------------------------------- 1 | targetScope = 'subscription' 2 | 3 | param ipAddress string 4 | @secure() 5 | param adminPassword string 6 | param location string = 'eastus' 7 | param serviceName string = 'app1' 8 | param topicName string = 'neworder' 9 | param rgName string = 'dapr_pubsub_demo' 10 | 11 | resource rg 'Microsoft.Resources/resourceGroups@2021-04-01' = { 12 | name: rgName 13 | location: location 14 | } 15 | 16 | module pubsub './pubsub.bicep' = { 17 | name: 'pubsub' 18 | scope: resourceGroup(rg.name) 19 | params: { 20 | location: location 21 | ipAddress: ipAddress 22 | topicName: topicName 23 | serviceName: serviceName 24 | adminPassword: adminPassword 25 | } 26 | } 27 | 28 | output storageAccountName string = pubsub.outputs.storageAccountName 29 | 30 | output serviceBusAuthRule string = pubsub.outputs.serviceBusAuthRule 31 | output serviceBusNamespace string = pubsub.outputs.serviceBusNamespace 32 | 33 | output eventHubName string = pubsub.outputs.eventHubName 34 | output eventHubAuthRule string = pubsub.outputs.eventHubAuthRule 35 | output eventHubsNamespace string = pubsub.outputs.eventHubsNamespace 36 | 37 | output databaseName string = pubsub.outputs.databaseName 38 | output administratorLogin string = pubsub.outputs.administratorLogin 39 | output fullyQualifiedDomainName string = pubsub.outputs.fullyQualifiedDomainName 40 | -------------------------------------------------------------------------------- /PubSub/sampleRequests.http: -------------------------------------------------------------------------------- 1 | # Use this command to run local 2 | # ./demo.ps1 3 | 4 | # Use this command to run in Azure 5 | # ./demo.ps1 -env azure 6 | 7 | # Use this command to run in AWS 8 | # ./demo.ps1 -env aws 9 | 10 | POST http://localhost:3500/v1.0/publish/pubsub1/neworder 11 | Content-Type: application/json 12 | 13 | {"orderId":"45"} 14 | 15 | ### 16 | 17 | POST http://localhost:3500/v1.0/publish/pubsub2/neworder 18 | Content-Type: application/json 19 | 20 | {"orderId":"46"} 21 | 22 | ### 23 | 24 | GET http://localhost:3500/v1.0/invoke/app1/method/order -------------------------------------------------------------------------------- /PubSub/src/Program.cs: -------------------------------------------------------------------------------- 1 | var builder = WebApplication.CreateBuilder(args); 2 | builder.Services.AddControllers().AddDapr(); 3 | 4 | // Configure and enable middlewares 5 | var app = builder.Build(); 6 | app.UseCloudEvents(); 7 | 8 | app.MapGet("/order", async (Dapr.Client.DaprClient client) => 9 | await client.GetStateAsync("statestore", "orders")); 10 | 11 | app.MapPost("/neworder", async (Order o, Dapr.Client.DaprClient client) => 12 | { 13 | await client.SaveStateAsync("statestore", "orders", o); 14 | return Results.Ok(); 15 | }); 16 | 17 | 18 | app.Run(); 19 | 20 | public record Order(string OrderId); -------------------------------------------------------------------------------- /PubSub/src/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:38073", 7 | "sslPort": 44339 8 | } 9 | }, 10 | "profiles": { 11 | "src": { 12 | "commandName": "Project", 13 | "dotnetRunMessages": true, 14 | "launchBrowser": true, 15 | "applicationUrl": "https://localhost:7065;http://localhost:5013", 16 | "environmentVariables": { 17 | "ASPNETCORE_ENVIRONMENT": "Development" 18 | } 19 | }, 20 | "IIS Express": { 21 | "commandName": "IISExpress", 22 | "launchBrowser": true, 23 | "environmentVariables": { 24 | "ASPNETCORE_ENVIRONMENT": "Development" 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /PubSub/src/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /PubSub/src/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*" 9 | } 10 | -------------------------------------------------------------------------------- /PubSub/src/src.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Secrets/.scripts/Deploy-AWSInfrastructure.ps1: -------------------------------------------------------------------------------- 1 | function Deploy-AWSInfrastructure { 2 | [CmdletBinding()] 3 | param () 4 | 5 | begin { 6 | Push-Location -Path './deploy/aws' 7 | } 8 | 9 | process { 10 | Deploy-AWS 11 | } 12 | 13 | end { 14 | Pop-Location 15 | } 16 | } -------------------------------------------------------------------------------- /Secrets/.scripts/Deploy-AzureInfrastructure.ps1: -------------------------------------------------------------------------------- 1 | # This function will run an bicep deployment to deploy all the required 2 | # resources into Azure. All the keys, tokens and endpoints will be 3 | # automatically retreived and written to ./components/azure/local_secrets.json. 4 | # PowerShell Core 7 (runs on macOS, Linux and Windows) 5 | # Azure CLI (log in, runs on macOS, Linux and Windows) 6 | function Deploy-AzureInfrastructure { 7 | [CmdletBinding()] 8 | param ( 9 | [Parameter( 10 | Position = 0, 11 | HelpMessage = "The name of the resource group to be created. All resources will be place in the resource group and start with name." 12 | )] 13 | [string] 14 | $rgName, 15 | 16 | [Parameter( 17 | Position = 1, 18 | HelpMessage = "The location to store the meta data for the deployment." 19 | )] 20 | [string] 21 | $location 22 | ) 23 | 24 | begin { 25 | Push-Location -Path './deploy' 26 | } 27 | 28 | process { 29 | # We need to get the object id for the service principal 30 | $objectId = $(az ad sp show ` 31 | --id $env:AZURE_APP_ID ` 32 | --query id ` 33 | --output tsv) 34 | 35 | Write-Verbose "ObjectID = $objectId" 36 | 37 | Write-Output 'Deploying the infrastructure' 38 | $deployment = $(az deployment sub create --name $rgName ` 39 | --location $location ` 40 | --parameters rgName=$rgName ` 41 | --parameters objectId=$objectId ` 42 | --parameters location=$location ` 43 | --parameters tenantId=$env:AZURE_TENANT ` 44 | --template-file ./azure/main.bicep ` 45 | --output json) | ConvertFrom-Json 46 | 47 | if(-not $deployment) { 48 | Pop-Location 49 | throw "Deployment failed" 50 | } 51 | 52 | $keyvaultName = $deployment.properties.outputs.keyvaultName.value 53 | 54 | Write-Verbose "keyvaultName = $keyvaultName" 55 | 56 | Write-Output 'Setting AZURE_KEY_VAULT_NAME environment variable' 57 | $env:AZURE_KEY_VAULT_NAME = $keyvaultName 58 | } 59 | 60 | end { 61 | Pop-Location 62 | } 63 | } -------------------------------------------------------------------------------- /Secrets/README.md: -------------------------------------------------------------------------------- 1 | # Secrets demo 2 | 3 | The purpose of this demo is to show the use of [secrets components](https://docs.dapr.io/developing-applications/building-blocks/secrets/) locally and in the cloud. 4 | 5 | Open the _demo_secrets.code-workspace_ file and click the **Open Workspace** button in the lower right corner. This will reload your Codespace and scope your Explorer to just the folders needed for this demo. 6 | 7 | To provision the infrastructure before the demo execute the following command in the terminal. This code is automatically run by the _demo.ps1_ script if the `-env` parameter is passed and *AZURE_KEY_VAULT_NAME* environment variable is not found. 8 | 9 | ``` 10 | ./demo.ps1 -deployOnly 11 | ``` 12 | 13 | The workspace consists of one top level folder _Secrets_. This folder holds the _components/azure_, _components_, and _deploy_ folders. The _components/azure_ and _components_ folders are in the workspace so you can show the difference between a local component and a component configured for the cloud. The component in the _components/azure_ folder is configured to use [Azure Key Vault](https://docs.dapr.io/reference/components-reference/supported-secret-stores/azure-keyvault/). In the _components/aws_ folder the component is configured to use AWS Secrets Manager and the local component is configured to use [local file](https://docs.dapr.io/reference/components-reference/supported-secret-stores/file-secret-store/). The point to make comparing the files is that as long as the name of the component does not change the code will work no matter what backing service is used. 14 | 15 | The core of the demo is in the _sampleRequests.http_ file. At the top of the file are two _demo.ps1_ commands. One for running the requests against local resources and one for running against the cloud resources. Copy the desired command and run it in the terminal. This will start Dapr pointing to the appropriate components for the demo. The Dapr run command issued is output if you want to explain during the demo. 16 | 17 | Running local 18 | ``` 19 | dapr run --app-id local --dapr-http-port 3500 --components-path ./components 20 | ``` 21 | 22 | Running in Azure 23 | ``` 24 | dapr run --app-id azure --dapr-http-port 3500 --components-path ./components/azure 25 | ``` 26 | 27 | Running in AWS 28 | ``` 29 | dapr run --app-id aws --dapr-http-port 3500 --components-path ./components/aws 30 | ``` 31 | 32 | Click the Send Request button above each of the requests to execute them. 33 | 34 | When you are done with the demo you can clean up the cloud resources by running the _cleanUp.ps1_ script using the following commands: 35 | 36 | ``` 37 | ./cleanUp.ps1 38 | ``` -------------------------------------------------------------------------------- /Secrets/cleanUp.ps1: -------------------------------------------------------------------------------- 1 | # This will start the deletion of a resource group but not wait. 2 | 3 | [CmdletBinding()] 4 | param ( 5 | [Parameter( 6 | Position = 0, 7 | HelpMessage = "The name of the resource group to be created. All resources will be place in the resource group and start with name." 8 | )] 9 | [string] 10 | $rgName = "dapr_secrets_demo", 11 | 12 | [Parameter( 13 | HelpMessage = "Set to the location of the resources to use." 14 | )] 15 | [ValidateSet("all", "azure", "aws")] 16 | [string] 17 | $env = "all", 18 | 19 | [switch] 20 | $force 21 | ) 22 | 23 | . ../.scripts/common.ps1 24 | 25 | if ($env -eq 'all' -or $env -eq 'azure') { 26 | # Remove clear out the vault name environment variable 27 | $env:AZURE_KEY_VAULT_NAME = $null 28 | 29 | Write-Output "Waiting for resource group to be deleted so the keyvault can be purged" 30 | Remove-ResourceGroup -name $rgName -force:$force 31 | 32 | Write-Output "Getting soft deleted key vaults" 33 | $vault = $(az keyvault list-deleted --subscription $env:AZURE_SUB_ID --resource-type vault --query [].name --output tsv) 34 | 35 | if ($null -ne $vault) { 36 | Write-Output "Purging key vault $vault" 37 | az keyvault purge --subscription $env:AZURE_SUB_ID --name $vault 38 | } 39 | } 40 | 41 | if ($env -eq 'all' -or $env -eq 'aws') { 42 | ### AWS 43 | Remove-AWS 44 | 45 | # When you delete a secret, Secrets Manager doesn't immediately delete the 46 | # secret. Secrets Manager schedules the secret for deletion after a 47 | # recovery window of a minimum of seven days. This means that you can't 48 | # recreate a secret using the same name using the AWS Management Console 49 | # until the recovery window ends. You can permanently delete a secret 50 | # without any recovery window using the AWS Command Line Interface (AWS CLI) 51 | Write-Output "Purging secret my-secret" 52 | aws secretsmanager delete-secret --secret-id my-secret --force-delete-without-recovery --region $env:AWS_DEFAULT_REGION 53 | } -------------------------------------------------------------------------------- /Secrets/components/aws/secret.aws.secrets.manager.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: my-secrets-store 5 | auth: 6 | secretStore: strongbox 7 | spec: 8 | type: secretstores.aws.secretmanager 9 | version: v1 10 | metadata: 11 | - name: region 12 | value: us-east-2 13 | - name: accessKey 14 | secretKeyRef: 15 | key: accessKey 16 | name: accessKey 17 | - name: secretKey 18 | secretKeyRef: 19 | key: secretKey 20 | name: secretKey 21 | -------------------------------------------------------------------------------- /Secrets/components/aws/secretstore.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: strongbox 5 | spec: 6 | type: secretstores.local.file 7 | version: v1 8 | metadata: 9 | - name: secretsFile 10 | value: "./components/aws/local_secrets.json" -------------------------------------------------------------------------------- /Secrets/components/azure/secretstore.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: my-secrets-store 5 | auth: 6 | secretStore: strongbox 7 | spec: 8 | type: secretstores.azure.keyvault 9 | version: v1 10 | metadata: 11 | - name: vaultName 12 | secretKeyRef: 13 | key: AZURE_KEY_VAULT_NAME 14 | name: AZURE_KEY_VAULT_NAME 15 | - name: azureTenantId 16 | secretKeyRef: 17 | key: AZURE_TENANT 18 | name: AZURE_TENANT 19 | - name: azureClientId 20 | secretKeyRef: 21 | key: AZURE_APP_ID 22 | name: AZURE_APP_ID 23 | - name: azureClientSecret 24 | secretKeyRef: 25 | key: AZURE_PASSWORD 26 | name: AZURE_PASSWORD -------------------------------------------------------------------------------- /Secrets/components/azure/strongbox.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: strongbox 5 | spec: 6 | type: secretstores.local.env 7 | version: v1 8 | metadata: [] 9 | -------------------------------------------------------------------------------- /Secrets/components/local/local_secrets.json: -------------------------------------------------------------------------------- 1 | { 2 | "my-secret": "My_Secret_From_Local_File" 3 | } -------------------------------------------------------------------------------- /Secrets/components/local/secretstore.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: my-secrets-store 5 | namespace: default 6 | spec: 7 | type: secretstores.local.file 8 | version: v1 9 | metadata: 10 | - name: secretsFile 11 | value: "./components/local/local_secrets.json" -------------------------------------------------------------------------------- /Secrets/deploy/aws/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = var.region 3 | access_key = var.access_key 4 | secret_key = var.secret_key 5 | } 6 | 7 | resource "aws_secretsmanager_secret" "dapr_secrets" { 8 | name = var.secrets_manager_name 9 | 10 | tags = { 11 | Name = "Dapr Secrets Manager" 12 | environment = "${var.environment}" 13 | } 14 | } 15 | 16 | resource "aws_secretsmanager_secret_version" "my_secret" { 17 | secret_id = aws_secretsmanager_secret.dapr_secrets.id 18 | secret_string = "My_Secret_From_AWS_Secrets_Manager" 19 | } -------------------------------------------------------------------------------- /Secrets/deploy/aws/variables.tf: -------------------------------------------------------------------------------- 1 | 2 | variable "access_key" { 3 | description = "Access key to AWS console" 4 | } 5 | 6 | variable "secret_key" { 7 | description = "Secret key to AWS console" 8 | } 9 | 10 | variable "region" { 11 | description = "The region to use to create the resource" 12 | default = "us-east-2" 13 | } 14 | 15 | variable "secrets_manager_name" { 16 | description = "Secrets Manager name (space is not allowed)" 17 | default = "my-secret" 18 | } 19 | 20 | variable "environment" { 21 | description = "Name of environment" 22 | default = "codespace" 23 | } 24 | -------------------------------------------------------------------------------- /Secrets/deploy/azure/main.bicep: -------------------------------------------------------------------------------- 1 | targetScope = 'subscription' 2 | 3 | param tenantId string 4 | param objectId string 5 | param location string = 'eastus' 6 | param rgName string = 'dapr_secrets_demo' 7 | 8 | resource rg 'Microsoft.Resources/resourceGroups@2021-04-01' = { 9 | name: rgName 10 | location: location 11 | } 12 | 13 | module secrets './secrets.bicep' = { 14 | name: 'secrets' 15 | scope: resourceGroup(rg.name) 16 | params: { 17 | tenantId: tenantId 18 | objectId: objectId 19 | location: location 20 | } 21 | } 22 | 23 | output keyvaultName string = secrets.outputs.keyvaultName 24 | -------------------------------------------------------------------------------- /Secrets/deploy/azure/secrets.bicep: -------------------------------------------------------------------------------- 1 | param tenantId string 2 | param objectId string 3 | param location string 4 | 5 | var kvName = 'kv${uniqueString(resourceGroup().id)}' 6 | 7 | resource keyVault 'Microsoft.KeyVault/vaults@2019-09-01' = { 8 | name: kvName 9 | location: location 10 | properties: { 11 | enabledForDeployment: true 12 | enabledForTemplateDeployment: true 13 | enabledForDiskEncryption: true 14 | enableSoftDelete: false 15 | tenantId: tenantId 16 | accessPolicies: [ 17 | { 18 | tenantId: tenantId 19 | objectId: objectId 20 | permissions: { 21 | keys: [ 22 | 'get' 23 | ] 24 | secrets: [ 25 | 'list' 26 | 'get' 27 | 'set' 28 | ] 29 | } 30 | } 31 | ] 32 | sku: { 33 | name: 'standard' 34 | family: 'A' 35 | } 36 | } 37 | } 38 | 39 | resource keyVaultSecret 'Microsoft.KeyVault/vaults/secrets@2019-09-01' = { 40 | name: '${kvName}/my-secret' 41 | properties: { 42 | value: 'My_Secret_From_Azure_KeyVault' 43 | } 44 | dependsOn: [ 45 | keyVault 46 | ] 47 | } 48 | 49 | output keyvaultName string = kvName 50 | -------------------------------------------------------------------------------- /Secrets/sampleRequests.http: -------------------------------------------------------------------------------- 1 | # Use this command to run local 2 | # ./demo.ps1 3 | 4 | # Use this command to run in Azure 5 | # ./demo.ps1 -env azure 6 | 7 | # Use this command to run in AWS 8 | # ./demo.ps1 -env aws 9 | 10 | http://localhost:3500/v1.0/secrets/my-secrets-store/my-secret 11 | -------------------------------------------------------------------------------- /StateStore/.scripts/Deploy-AWSInfrastructure.ps1: -------------------------------------------------------------------------------- 1 | function Deploy-AWSInfrastructure { 2 | [CmdletBinding()] 3 | param () 4 | 5 | begin { 6 | Push-Location -Path './deploy/aws' 7 | } 8 | 9 | process { 10 | Deploy-AWS -skipSecrets 11 | } 12 | 13 | end { 14 | Pop-Location 15 | } 16 | } -------------------------------------------------------------------------------- /StateStore/.scripts/Deploy-AzureInfrastructure.ps1: -------------------------------------------------------------------------------- 1 | # This function will run an bicep deployment to deploy all the required 2 | # resources into Azure. All the keys, tokens and endpoints will be 3 | # automatically retreived and written to ./components/azure/local_secrets.json. 4 | # PowerShell Core 7 (runs on macOS, Linux and Windows) 5 | # Azure CLI (log in, runs on macOS, Linux and Windows) 6 | function Deploy-AzureInfrastructure { 7 | [CmdletBinding()] 8 | param ( 9 | [Parameter( 10 | Position = 0, 11 | HelpMessage = "The name of the resource group to be created. All resources will be place in the resource group and start with name." 12 | )] 13 | [string] 14 | $rgName, 15 | 16 | [Parameter( 17 | Position = 1, 18 | HelpMessage = "The location to store the meta data for the deployment." 19 | )] 20 | [string] 21 | $location 22 | ) 23 | 24 | begin { 25 | Push-Location -Path './deploy' 26 | } 27 | 28 | process { 29 | Write-Output 'Deploying the Azure infrastructure' 30 | $deployment = $(az deployment sub create --name $rgName ` 31 | --location $location ` 32 | --template-file ./azure/main.bicep ` 33 | --parameters location=$location ` 34 | --parameters rgName=$rgName ` 35 | --output json) | ConvertFrom-Json 36 | 37 | # Store the outputs from the deployment to create 38 | # ./components/azure/local_secrets.json 39 | $cosmosDbName = $deployment.properties.outputs.cosmosDbName.value 40 | $cosmosDbEndpoint = $deployment.properties.outputs.cosmosDbEndpoint.value 41 | 42 | $cosmosDbKey = $(az cosmosdb keys list ` 43 | --name $cosmosDbName ` 44 | --resource-group $rgName ` 45 | --query primaryMasterKey ` 46 | --output tsv) 47 | 48 | Write-Verbose "cosmosDbKey = $cosmosDbKey" 49 | Write-Verbose "cosmosDbEndpoint = $cosmosDbEndpoint" 50 | 51 | # Creating components/azure/local_secrets.json 52 | $secrets = [PSCustomObject]@{ 53 | url = $cosmosDbEndpoint 54 | key = $cosmosDbKey 55 | } 56 | 57 | Write-Output 'Saving ./components/azure/local_secrets.json for local secret store' 58 | $secrets | ConvertTo-Json | Set-Content ../components/azure/local_secrets.json 59 | } 60 | 61 | end { 62 | Pop-Location 63 | } 64 | } -------------------------------------------------------------------------------- /StateStore/README.md: -------------------------------------------------------------------------------- 1 | # State management demo 2 | 3 | The purpose of this demo is to show the use of [state store components](https://docs.dapr.io/developing-applications/building-blocks/state-management/) locally and in the cloud. 4 | 5 | Open the _demo_statestore.code-workspace_ file and click the **Open Workspace** button in the lower right corner. This will reload your Codespace and scope your Explorer to just the folders needed for this demo. 6 | 7 | To provision the infrastructure before the demo execute the following command in the terminal. This code is automatically run by the _demo.ps1_ script if the `-env` parameter is passed and *./components/azure/local_secrets.json* file is not found. 8 | 9 | ``` 10 | ./demo.ps1 -deployOnly 11 | ``` 12 | 13 | The workspace consists of one top level folder _StateStore_. The components sub folder contains components for local, Azure, and AWS. These folders allow you to show the difference between that default components (local) and the components in the other folders. The point to make comparing the files is that as long as the name of the component does not change the code will work no matter what backing service is used. 14 | 15 | The core of the demo is in the _sampleRequests.http_ file. At the top of the file are _demo.ps1_ commands. One for running the requests against local resources and two for running against the cloud resources. Copy the desired command and run it in the terminal. This will start Dapr pointing to the appropriate components for the demo. The Dapr run command issued is output if you want to explain during the demo. 16 | 17 | Running local 18 | ``` 19 | dapr run --app-id local --dapr-http-port 3500 --components-path ./components/local 20 | ``` 21 | 22 | Running in Azure 23 | ``` 24 | dapr run --app-id azure --dapr-http-port 3500 --components-path ./components/azure 25 | ``` 26 | 27 | Running in AWS 28 | ``` 29 | dapr run --app-id aws --dapr-http-port 3500 --components-path ./components/aws 30 | ``` 31 | 32 | Click the Send Request button above each of the requests to execute them. 33 | 34 | When running locally against Redis you can use the Redis Visual Studio Code extension installed in the Codespace to see the state being stored there. 35 | 36 | When you are done with the demo you can clean up the cloud resources by running the _cleanUp.ps1_ script using the following commands: 37 | 38 | ``` 39 | ./cleanUp.ps1 40 | ``` -------------------------------------------------------------------------------- /StateStore/cleanUp.ps1: -------------------------------------------------------------------------------- 1 | # This will start the deletion of a resource group but not wait. 2 | 3 | [CmdletBinding()] 4 | param ( 5 | [Parameter( 6 | Position = 0, 7 | HelpMessage = "The name of the resource group to be created. All resources will be place in the resource group and start with name." 8 | )] 9 | [string] 10 | $rgName = "dapr_statestore_demo", 11 | 12 | [Parameter( 13 | HelpMessage = "Set to the location of the resources to use." 14 | )] 15 | [ValidateSet("all", "azure", "aws")] 16 | [string] 17 | $env = "all", 18 | 19 | [switch] 20 | $force 21 | ) 22 | 23 | . "../.scripts/common.ps1" 24 | 25 | if ($env -eq 'all' -or $env -eq 'azure') { 26 | ### Azure 27 | # Remove local_secrets.json 28 | Remove-Item ./components/azure/local_secrets.json -ErrorAction SilentlyContinue 29 | 30 | Remove-ResourceGroup -name $rgName -force:$force -nowait 31 | } 32 | 33 | if ($env -eq 'all' -or $env -eq 'aws') { 34 | ### AWS 35 | Remove-AWS 36 | } -------------------------------------------------------------------------------- /StateStore/components/aws/state.aws.dynamodb.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: statestore 5 | spec: 6 | type: state.aws.dynamodb 7 | version: v1 8 | metadata: 9 | - name: table 10 | value: dapr_store 11 | - name: region 12 | value: us-east-2 -------------------------------------------------------------------------------- /StateStore/components/azure/secretstores.local.file.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: strongbox 5 | spec: 6 | type: secretstores.local.file 7 | version: v1 8 | metadata: 9 | - name: secretsFile 10 | value: "./components/azure/local_secrets.json" -------------------------------------------------------------------------------- /StateStore/components/azure/state.azure.cosmosdb.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: statestore 5 | auth: 6 | secretStore: strongbox 7 | spec: 8 | type: state.azure.cosmosdb 9 | version: v1 10 | metadata: 11 | - name: url 12 | secretKeyRef: 13 | key: url 14 | name: url 15 | - name: masterKey 16 | secretKeyRef: 17 | key: key 18 | name: key 19 | - name: database 20 | value: StateStore 21 | - name: collection 22 | value: StateStoreValues 23 | -------------------------------------------------------------------------------- /StateStore/components/local/state.redis.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dapr.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: statestore 5 | spec: 6 | type: state.redis 7 | version: v1 8 | metadata: 9 | - name: redisHost 10 | value: localhost:6379 11 | - name: redisPassword 12 | value: "" 13 | - name: actorStateStore 14 | value: "true" 15 | -------------------------------------------------------------------------------- /StateStore/demo.ps1: -------------------------------------------------------------------------------- 1 | # This script issues and displays the correct dapr run command for running with 2 | # local or cloud resources. To run in the clould add -env azure parameter. If the 3 | # script determines the infrastructure has not been deployed it will call the 4 | # setup script first. 5 | [CmdletBinding()] 6 | param ( 7 | [Parameter( 8 | Position = 0, 9 | HelpMessage = "The name of the resource group to be created. All resources will be place in the resource group and start with name." 10 | )] 11 | [string] 12 | $rgName = "dapr_statestore_demo", 13 | 14 | [Parameter( 15 | Position = 1, 16 | HelpMessage = "The location to store the meta data for the deployment." 17 | )] 18 | [string] 19 | $location = "eastus", 20 | 21 | [Parameter( 22 | HelpMessage = "Set to the location of the resources to use." 23 | )] 24 | [ValidateSet("local", "azure", "aws")] 25 | [string] 26 | $env = "local", 27 | 28 | [Parameter( 29 | HelpMessage = "When provided deploys the cloud infrastructure without running the demo" 30 | )] 31 | [switch] 32 | $deployOnly 33 | ) 34 | 35 | . "../.scripts/common.ps1" 36 | . "./.scripts/Deploy-AWSInfrastructure.ps1" 37 | . "./.scripts/Deploy-AzureInfrastructure.ps1" 38 | 39 | # This will deploy the infrastructure without running the demo. You can use 40 | # this flag to set everything up before you run the demos to save time. Some 41 | # infrastucture can take some time to deploy. 42 | if ($deployOnly.IsPresent) { 43 | Deploy-AWSInfrastructure 44 | Deploy-AzureInfrastructure -rgName $rgName -location $location 45 | 46 | return 47 | } 48 | 49 | # Load the sample requests file for the demo 50 | code ./sampleRequests.http 51 | 52 | if ($env -eq "azure") { 53 | # If you don't find the ./components/azure/local_secrets.json deploy infrastucture 54 | if ($(Test-Path -Path './components/azure/local_secrets.json') -eq $false) { 55 | Write-Output "Could not find ./components/azure/local_secrets.json" 56 | Deploy-AzureInfrastructure -rgName $rgName -location $location 57 | } 58 | } 59 | elseif ($env -eq "aws") { 60 | # If you don't find the ./deploy/aws/terraform.tfvars deploy infrastucture 61 | if ($(Test-Path -Path './deploy/aws/terraform.tfvars') -eq $false) { 62 | Write-Output "Could not find ./deploy/aws/terraform.tfvars" 63 | Deploy-AWSInfrastructure 64 | } 65 | } 66 | 67 | Write-Output "Running demo with $env resources" 68 | Write-Output "dapr run --app-id $env --dapr-http-port 3500 --components-path ./components/$env `n" 69 | dapr run --app-id $env --dapr-http-port 3500 --components-path ./components/$env -------------------------------------------------------------------------------- /StateStore/deploy/aws/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | access_key = var.access_key 3 | secret_key = var.secret_key 4 | region = var.region 5 | } 6 | 7 | resource "aws_dynamodb_table" "dapr_state_store" { 8 | name = var.table_name 9 | billing_mode = var.table_billing_mode 10 | hash_key = "key" 11 | attribute { 12 | name = "key" 13 | type = "S" 14 | } 15 | tags = { 16 | environment = "${var.environment}" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /StateStore/deploy/aws/variables.tf: -------------------------------------------------------------------------------- 1 | variable "access_key" { 2 | description = "Access key to AWS console" 3 | } 4 | 5 | variable "secret_key" { 6 | description = "Secret key to AWS console" 7 | } 8 | 9 | variable "region" { 10 | description = "The region to use to create the resource" 11 | default = "us-east-2" 12 | } 13 | 14 | variable "table_name" { 15 | description = "Dynamodb table name (space is not allowed)" 16 | default = "dapr_store" 17 | } 18 | 19 | variable "table_billing_mode" { 20 | description = "Controls how you are charged for read and write throughput and how you manage capacity." 21 | default = "PAY_PER_REQUEST" 22 | } 23 | 24 | variable "environment" { 25 | description = "Name of environment" 26 | default = "codespace" 27 | } 28 | -------------------------------------------------------------------------------- /StateStore/deploy/azure/main.bicep: -------------------------------------------------------------------------------- 1 | targetScope = 'subscription' 2 | 3 | param location string = 'eastus' 4 | param rgName string = 'dapr_statestore_demo' 5 | 6 | resource rg 'Microsoft.Resources/resourceGroups@2021-04-01' = { 7 | name: rgName 8 | location: location 9 | } 10 | 11 | module stateStore './stateStore.bicep' = { 12 | name: 'stateStore' 13 | scope: resourceGroup(rg.name) 14 | params: { 15 | location: location 16 | } 17 | } 18 | 19 | output cosmosDbName string = stateStore.outputs.cosmosDbName 20 | output cosmosDbEndpoint string = stateStore.outputs.cosmosDbEndpoint 21 | -------------------------------------------------------------------------------- /StateStore/deploy/azure/stateStore.bicep: -------------------------------------------------------------------------------- 1 | var dbName = 'StateStore' 2 | var containerName = 'StateStoreValues' 3 | 4 | param location string 5 | 6 | resource cdb 'Microsoft.DocumentDB/databaseAccounts@2021-06-15' = { 7 | name: 'cdb${uniqueString(resourceGroup().id)}' 8 | location: location 9 | kind: 'GlobalDocumentDB' 10 | properties: { 11 | consistencyPolicy: { 12 | defaultConsistencyLevel: 'Session' 13 | } 14 | locations: [ 15 | { 16 | locationName: location 17 | failoverPriority: 0 18 | isZoneRedundant: false 19 | } 20 | ] 21 | capabilities: [ 22 | { 23 | name: 'EnableServerless' 24 | } 25 | ] 26 | databaseAccountOfferType: 'Standard' 27 | } 28 | } 29 | 30 | resource db 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases@2021-06-15' = { 31 | name: dbName 32 | parent: cdb 33 | properties: { 34 | resource: { 35 | id: dbName 36 | } 37 | } 38 | } 39 | 40 | resource dbContiner 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers@2021-06-15' = { 41 | name: containerName 42 | parent: db 43 | properties: { 44 | resource: { 45 | id: containerName 46 | partitionKey: { 47 | paths: [ 48 | '/id' 49 | ] 50 | } 51 | } 52 | } 53 | } 54 | 55 | output cosmosDbName string = cdb.name 56 | output cosmosDbEndpoint string = cdb.properties.documentEndpoint 57 | -------------------------------------------------------------------------------- /StateStore/sampleRequests.http: -------------------------------------------------------------------------------- 1 | # Use this command to run local 2 | # ./demo.ps1 3 | 4 | # Use this command to run in azure 5 | # ./demo.ps1 -env azure 6 | 7 | # Use this command to run in aws 8 | # ./demo.ps1 -env aws 9 | # aws dynamodb get-item --table-name dapr_store --key '{""key"": {""S"": ""aws||Dog""}}' --output json 10 | 11 | POST http://localhost:3500/v1.0/state/statestore 12 | 13 | [ 14 | { 15 | "key": "Dog", 16 | "value": "Hybrid" 17 | } 18 | ] 19 | 20 | ### 21 | GET http://localhost:3500/v1.0/state/statestore/Dog 22 | 23 | ### 24 | DELETE http://localhost:3500/v1.0/state/statestore/Dog -------------------------------------------------------------------------------- /default.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "." 5 | } 6 | ], 7 | "settings": { 8 | "files.exclude": { 9 | ".gitignore": true, 10 | "**/.devcontainer": true, 11 | "**/.images": true, 12 | "default.code-workspace": true 13 | }, 14 | "editor.minimap.enabled": false, 15 | "cSpell.words": [ 16 | "Codespace", 17 | "codespaces", 18 | "Dapr", 19 | "devcontainer", 20 | "pwsh", 21 | "secretstores", 22 | "statestore", 23 | "tempfiles" 24 | ] 25 | } 26 | } -------------------------------------------------------------------------------- /demo_binding.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "./Binding" 5 | }, 6 | { 7 | "path": "./.images" 8 | } 9 | ], 10 | "settings": { 11 | "files.exclude": { 12 | "**/.devcontainer": true, 13 | "**/.images": true, 14 | "**/.scripts": true, 15 | "**/.vscode": true, 16 | "demo_binding.code-workspace": true 17 | }, 18 | "editor.minimap.enabled": false, 19 | "cSpell.words": [ 20 | "Codespace", 21 | "Dapr", 22 | "pwsh", 23 | "tempfiles" 24 | ], 25 | "powershell.cwd": "/workspaces/MyDaprDemos/Binding" 26 | } 27 | } -------------------------------------------------------------------------------- /demo_devops.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "./DevOps" 5 | }, 6 | { 7 | "path": "./.images" 8 | } 9 | ], 10 | "settings": { 11 | "files.exclude": { 12 | "**/.devcontainer": true, 13 | "**/.images": true, 14 | "**/.scripts": true, 15 | "**/bin": true, 16 | "**/obj": true, 17 | "demo_devops.code-workspace": true 18 | }, 19 | "editor.minimap.enabled": false, 20 | "cSpell.words": [ 21 | "Codespace", 22 | "Dapr", 23 | "pwsh", 24 | "tempfiles" 25 | ], 26 | "powershell.cwd": "/workspaces/MyDaprDemos/DevOps" 27 | } 28 | } -------------------------------------------------------------------------------- /demo_myapp.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "./MyApp" 5 | }, 6 | { 7 | "path": "./.images" 8 | } 9 | ], 10 | "settings": { 11 | "files.exclude": { 12 | ".gitignore": true, 13 | "**/.devcontainer": true, 14 | "**/.images": true, 15 | "**/bin": true, 16 | "**/obj": true, 17 | "demo_observability.code-workspace": true 18 | }, 19 | "editor.minimap.enabled": false, 20 | "cSpell.words": [ 21 | "azuremonitor", 22 | "Codespace", 23 | "Dapr", 24 | "loglevel", 25 | "maxbatchinterval", 26 | "maxbatchsize", 27 | "pprof", 28 | "pwsh", 29 | "zipkin", 30 | "zpages" 31 | ], 32 | "powershell.cwd": "/workspaces/MyDaprDemos/MyApp" 33 | } 34 | } -------------------------------------------------------------------------------- /demo_observability.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "./Observability" 5 | }, 6 | { 7 | "path": "./.images" 8 | }, 9 | { 10 | "path": "./../../home/vscode/.dapr/" 11 | } 12 | ], 13 | "settings": { 14 | "files.exclude": { 15 | ".gitignore": true, 16 | "**/.devcontainer": true, 17 | "**/.images": true, 18 | "**/.vscode": true, 19 | "**/bin": true, 20 | "**/components": true, 21 | "**/obj": true, 22 | "demo_observability.code-workspace": true 23 | }, 24 | "editor.minimap.enabled": false, 25 | "cSpell.words": [ 26 | "azuremonitor", 27 | "Codespace", 28 | "Dapr", 29 | "loglevel", 30 | "maxbatchinterval", 31 | "maxbatchsize", 32 | "pprof", 33 | "pwsh", 34 | "zipkin", 35 | "zpages" 36 | ], 37 | "powershell.cwd": "/workspaces/MyDaprDemos/Observability" 38 | } 39 | } -------------------------------------------------------------------------------- /demo_pubsub.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "./PubSub" 5 | }, 6 | { 7 | "path": "./.images" 8 | } 9 | ], 10 | "settings": { 11 | "files.exclude": { 12 | "**/.devcontainer": true, 13 | "**/bin": true, 14 | "**/.images": true, 15 | "**/obj": true, 16 | "**/.vscode": true, 17 | ".gitignore": true, 18 | "demo_pubsub.code-workspace": true 19 | }, 20 | "editor.minimap.enabled": false, 21 | "cSpell.words": [ 22 | "Codespace", 23 | "Dapr", 24 | "pwsh" 25 | ] 26 | } 27 | } -------------------------------------------------------------------------------- /demo_secrets.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "./Secrets" 5 | }, 6 | { 7 | "path": "./.images" 8 | } 9 | ], 10 | "settings": { 11 | "files.exclude": { 12 | "**/.devcontainer": true, 13 | "**/.images": true, 14 | "demo_secrets.code-workspace": true 15 | }, 16 | "editor.minimap.enabled": false, 17 | "cSpell.words": [ 18 | "Codespace", 19 | "Dapr", 20 | "pwsh" 21 | ] 22 | } 23 | } -------------------------------------------------------------------------------- /demo_statestore.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "./StateStore" 5 | }, 6 | { 7 | "path": "./.images" 8 | } 9 | ], 10 | "settings": { 11 | "files.exclude": { 12 | "**/.devcontainer": true, 13 | "**/.images": true, 14 | "**/.scripts": true, 15 | "**/.vscode": true, 16 | "demo_statestore.code-workspace": true 17 | }, 18 | "editor.minimap.enabled": false, 19 | "cSpell.words": [ 20 | "Codespace", 21 | "Dapr", 22 | "pwsh", 23 | "statestore" 24 | ] 25 | } 26 | } --------------------------------------------------------------------------------