diff --git a/.markdownlint.json b/.markdownlint.json index 48e1c358..f1c90e87 100644 --- a/.markdownlint.json +++ b/.markdownlint.json @@ -9,6 +9,10 @@ "MD031": false, "MD038": false, "MD041": false, - "MD044": false, + "MD044": { + "code_blocks": false, + "html_elements": false, + "names": ["Application Insights", "Azure", "Azure Container Apps", "Azure Cosmos DB", "Azure Service Bus", "Cosmos", "dapr", "Dapr", "KEDA", "Log Analytics", "Log Analytics workspace"] + }, "MD046": false } \ No newline at end of file diff --git a/docs/aca/00-workshop-intro/1-aca-core-components.md b/docs/aca/00-workshop-intro/1-aca-core-components.md index 9e4c03df..c9e81df8 100644 --- a/docs/aca/00-workshop-intro/1-aca-core-components.md +++ b/docs/aca/00-workshop-intro/1-aca-core-components.md @@ -11,7 +11,7 @@ The main components of Azure Container Apps are: 1. **Environments** The Container App Environment is a secure boundary around several Container Apps. It contains one or more container apps. All container apps within an environment are deployed into a dedicated Azure Virtual Network, which makes it possible for these different container apps to communicate securely. In addition, all the logs produced from all container apps in the environment are sent to a dedicated Log Analytics workspace. -1. **Log Analytics Workspace** +1. **Log Analytics workspace** Used to provide monitoring and observability functionality. Each environment will have its own Log Analytics workspace and will be shared among all container apps within the environment. 1. **Container Apps** diff --git a/docs/aca/01-deploy-api-to-aca/index.md b/docs/aca/01-deploy-api-to-aca/index.md index fa36075a..922c52be 100644 --- a/docs/aca/01-deploy-api-to-aca/index.md +++ b/docs/aca/01-deploy-api-to-aca/index.md @@ -65,7 +65,7 @@ In this module, we will accomplish three objectives: --8<-- "docs/aca/01-deploy-api-to-aca/TaskModel.cs" ``` -- In the project root create a new folder named **Services** and add the two files below. Ensure to create it as a sibling to the *Models* folder. Add the Fake Tasks Manager service. This will be the interface of Tasks Manager service. In this module we will work with data in memory. Later on, we will implement a data store. +- In the project root create a new folder named **Services** and add the two files below. Ensure to create it as a sibling to the *Models* folder. Add the Fake Tasks Manager service. This will be the interface of Tasks Manager service. In this module we will work with data in memory. Later on, we will implement a data store. === "ITasksManager.cs" ```csharp @@ -204,24 +204,24 @@ We will be using Azure CLI to deploy the Web API Backend to ACA as shown in the --output tsv) ``` -#### 2.3 Create Log Analytics Workspace & Application Insights +#### 2.3 Create Log Analytics workspace & Application Insights -- Create an Azure Log Analytics Workspace which will provide a common place to store the system and application log data from all container apps running in the environment. Each environment should have its own Log Analytics Workspace. +- Create an Azure Log Analytics workspace which will provide a common place to store the system and application log data from all container apps running in the environment. Each environment should have its own Log Analytics workspace. ```shell - # Create the Log Analytics Workspace + # Create the Log Analytics workspace az monitor log-analytics workspace create ` --resource-group $RESOURCE_GROUP ` --workspace-name $WORKSPACE_NAME - # Retrieve the Log Analytics Workspace ID + # Retrieve the Log Analytics workspace ID $WORKSPACE_ID=az monitor log-analytics workspace show ` --resource-group $RESOURCE_GROUP ` --workspace-name $WORKSPACE_NAME ` --query customerId ` --output tsv - # Retrieve the Log Analytics Workspace secret + # Retrieve the Log Analytics workspace secret $WORKSPACE_SECRET=az monitor log-analytics workspace get-shared-keys ` --resource-group $RESOURCE_GROUP ` --workspace-name $WORKSPACE_NAME ` @@ -280,9 +280,9 @@ We will be using Azure CLI to deploy the Web API Backend to ACA as shown in the While this is not advised in a production workload, it is suitable for the workshop to keep the architecture confined to Azure Container Apps. ??? tip "Want to learn what above command does?" - - It creates an ACA environment and associates it with the Log Analytics Workspace created in the previous step. + - It creates an ACA environment and associates it with the Log Analytics workspace created in the previous step. - We are setting the `--dapr-instrumentation-key` value to the instrumentation key of the Application Insights instance. This will come handy when we introduce Dapr in later modules and show how the distributed tracing between microservices/container apps are captured and visualized in Application Insights. - > **_NOTE:_** + > ***NOTE:*** You can set the `--dapr-instrumentation-key` after you create the ACA environment but this is not possible via the AZ CLI right now. There is an [open issue](https://github.com/microsoft/azure-container-apps/issues/293){target=_blank} which is being tracked by the product group. ### 3. Deploy Web API Backend Project to ACA @@ -341,7 +341,7 @@ We will be using Azure CLI to deploy the Web API Backend to ACA as shown in the Note that the specific query string matters as you may otherwise get an empty result back. !!! tip - You can find your azure container app application url on the [Azure portal](https://portal.azure.com){target=_blank} overview tab. + You can find your Azure container app application url on the [Azure portal](https://portal.azure.com){target=_blank} overview tab. ![Web API Response](../../assets/images/01-deploy-api-to-aca/Response.jpg) diff --git a/docs/aca/02-aca-comm/index.md b/docs/aca/02-aca-comm/index.md index 237f6ee4..46c866e7 100644 --- a/docs/aca/02-aca-comm/index.md +++ b/docs/aca/02-aca-comm/index.md @@ -8,6 +8,7 @@ canonical_url: https://bitoftech.net/2022/08/25/communication-microservices-azur 60 minutes ## Objective + In this module, we will accomplish three objectives: 1. Create a web app named `{{ apps.frontend }}`, which is the UI to interact with `{{ apps.backend }}`. @@ -64,7 +65,7 @@ By looking at the cshtml content notice that the page is expecting a query strin ```csharp --8<-- "docs/aca/02-aca-comm/Create.cshtml.cs" ``` - + !!! tip "What does this code do?" The code is self-explanatory here. We just injected the type HttpClientFactory in order to issue a POST request and create a new task. @@ -77,7 +78,7 @@ By looking at the cshtml content notice that the page is expecting a query strin ```csharp --8<-- "docs/aca/02-aca-comm/Edit.cshtml.cs" ``` - + !!! tip "What does this code do?" The code added is similar to the create operation. The Edit page accepts the TaskId as a Guid, loads the task, and then updates the task by sending an HTTP PUT operation. @@ -224,6 +225,7 @@ So far the Frontend App is sending HTTP requests to the publicly exposed Web API --8<-- "snippets/update-variables.md" ## Review + In this module, we have accomplished three objectives: 1. Created a web app named `{{ apps.frontend }}`, which is the UI to interact with `{{ apps.backend }}`. diff --git a/docs/aca/03-aca-dapr-integration/index.md b/docs/aca/03-aca-dapr-integration/index.md index 94857d83..4819c94e 100644 --- a/docs/aca/03-aca-dapr-integration/index.md +++ b/docs/aca/03-aca-dapr-integration/index.md @@ -216,7 +216,7 @@ You are now ready to run the applications locally using the Dapr sidecar in a se #### 2.4 Run `{{ apps.frontend }}` and `{{ apps.backend }}` Locally Using Dapr -We are ready now to verify the changes on the Frontend Web App and test locally. Therefore, we need to run the Frontend Web App along with the Backend Web API to ensure the Dapr Sidecar containers are working as expected. +We are ready now to verify the changes on the Frontend Web App and test locally. Therefore, we need to run the Frontend Web App along with the Backend Web API to ensure the Dapr Sidecar containers are working as expected. - Open another terminal inside VS Code, so that we can run the two commands shown below (ensure that you are on the right project directory when running each command). diff --git a/docs/aca/04-aca-dapr-stateapi/index.md b/docs/aca/04-aca-dapr-stateapi/index.md index 8d489b85..dd4f5f3c 100644 --- a/docs/aca/04-aca-dapr-stateapi/index.md +++ b/docs/aca/04-aca-dapr-stateapi/index.md @@ -82,7 +82,7 @@ What we've done here is the following: - The value `statestore` in the endpoint should match the `name` value in the global component file `statestore.yaml` - We have sent a request to store 3 entries of books, you can put any JSON representation in the value property -#### 1.2 Local Redis Cache +#### 1.2 Local Redis Cache To see the results visually, you can install a VS Code extension to connect to Redis DB and see the results. There are several Redis extensions available for VS Code. For this workshop we will use an extension named ["Redis Xplorer"](https://marketplace.visualstudio.com/items?itemName=davidsekar.redis-xplorer){target=_blank}. @@ -264,7 +264,7 @@ echo "Cosmos DB Primary Master Key:" echo $COSMOS_DB_PRIMARY_MASTER_KEY ``` -#### 3.2. Create a Component File for State Store Management +#### 3.2. Create a Component File for State Store Management Dapr uses a modular design where functionality is delivered as a component. Each component has an interface definition. All the components are pluggable so that you can swap out one component with the same interface for another. @@ -284,7 +284,7 @@ To add the component file state store, add a new folder named **components** und !!! info You need to replace the **masterKey** value with your Cosmos Account key. Remember this is only needed for local development debugging, we will not be using the masterKey when we deploy to ACA. - Replace the **url** value with the URI value of your cosmos database account. You can get that from the [Azure portal](https://portal.azure.com){target=_blank} by navigating to the cosmos database account overview page and get the uri value from there. + Replace the **url** value with the URI value of your Azure Cosmos DB account. You can get that from the [Azure portal](https://portal.azure.com){target=_blank} by navigating to the Azure Cosmos DB account overview page and get the uri value from there. Basically the uri should have the following structure. [https://COSMOS_DB_ACCOUNT.documents.azure.com:443/](https://COSMOS_DB_ACCOUNT.documents.azure.com:443/). === "dapr-statestore-cosmos.yaml" @@ -304,7 +304,7 @@ To add the component file state store, add a new folder named **components** und Now you should be ready to launch both applications and start doing CRUD operations from the Frontend Web App including querying the store. All your data will be stored in Cosmos DB Database you just provisioned. -If you have been running the different microservices using the [debug and launch Dapr applications in VSCode](../13-appendix/01-run-debug-dapr-app-vscode.md) then remember to uncomment the following line inside tasks.json file. +If you have been running the different microservices using the [debug and launch Dapr applications in VSCode](../13-appendix/01-run-debug-dapr-app-vscode.md) then remember to uncomment the following line inside tasks.json file. This will instruct dapr to load the local projects components located at **./components** instead of the global components' folder. ```json hl_lines="2" @@ -326,7 +326,7 @@ If you have been using the dapr cli commands instead of the aforementioned debug !!! note "Deprecation Warning" components-path is being deprecated in favor of --resources-path. At the time of producing this workshop the --resources-path was not supported yet by the VS code extension. Hence, you will notice the use of the property "componentsPath": "./components" in the tasks.json file. Check the extension documentation in case that has changed. -After creating a new record you can navigate to the Data explorer on the [Azure portal](https://portal.azure.com){target=_blank} for the azure cosmos database account. It should look like the image below: +After creating a new record you can navigate to the Data explorer on the [Azure portal](https://portal.azure.com){target=_blank} for the Azure Cosmos DB account. It should look like the image below: ![cosmos-db-dapr-state-store](../../assets/images/04-aca-dapr-stateapi/cosmos-db-dapr-state-store.jpg) @@ -421,7 +421,7 @@ Here it is recommended to separate the component files that will be used when de Create a new folder named **aca-components** under the directory **TasksTracker.ContainerApps**, then add a new file as shown below: !!! info - Remember to replace the url value with the URI value of your cosmos database account. You can get that from the [Azure portal](https://portal.azure.com){target=_blank} by navigating to the cosmos database account overview page and get the uri value from there. + Remember to replace the url value with the URI value of your cosmos database account. You can get that from the [Azure portal](https://portal.azure.com){target=_blank} by navigating to the Azure Cosmos DB account overview page and get the uri value from there. Basically the uri should have the following structure `https://COSMOS_DB_ACCOUNT.documents.azure.com:443/` === "containerapps-statestore-cosmos.yaml" diff --git a/docs/aca/05-aca-dapr-pubsubapi/index.md b/docs/aca/05-aca-dapr-pubsubapi/index.md index eae73ca7..2a42dcc4 100644 --- a/docs/aca/05-aca-dapr-pubsubapi/index.md +++ b/docs/aca/05-aca-dapr-pubsubapi/index.md @@ -388,7 +388,7 @@ We need to add a new [Dapr Azure Service Bus Topic component](https://docs.dapr. ``` !!! note - We used the name `dapr-pubsub-servicebus` which should match the name of Pub/Sub component we've used earlier in the [TasksNotifierController.cs](#4-create-an-api-endpoint-for-the-consumer-to-subscribe-to-the-topic) controller on the action method with the attribute `Topic`. + We used the name `dapr-pubsub-servicebus` which should match the name of Pub/Sub component we've used earlier in the `TasksNotifierController.cs` controller on the action method with the attribute `Topic`. We set the metadata (key/value) to allow us to connect to Azure Service Bus topic. The metadata `consumerID` value should match the topic subscription name `sbts-tasks-processor`. diff --git a/docs/aca/06-aca-dapr-bindingsapi/index.md b/docs/aca/06-aca-dapr-bindingsapi/index.md index 2863e489..ed7f2bbf 100644 --- a/docs/aca/06-aca-dapr-bindingsapi/index.md +++ b/docs/aca/06-aca-dapr-bindingsapi/index.md @@ -24,8 +24,7 @@ In this module, we will accomplish four objectives: To achieve interfacing with an external system in a simple way, we will utilize [Dapr Input and Output Bindings](https://docs.dapr.io/developing-applications/building-blocks/bindings/bindings-overview/){target=_blank}. -The external system owns an Azure Storage Queue which the Tasks Tracker microservice application **reacts** to through an event handler (aka **Input Binding**). This event handler receives and processes the message coming to the storage queue. Once the processing of the message completes and stores the task into Cosmos DB, the system will **trigger** an event (aka **Output binding**) that invokes the external service. This service, in turn, stores the content of the message into an Azure Blob Storage container. -It is important to emphasize that both the Azure Storage Queue and the Azure Storage Blob belong to the *external* system. +The external system owns an Azure Storage Queue which the Tasks Tracker microservice application **reacts** to through an event handler (aka **Input Binding**). This event handler receives and processes the message coming to the storage queue. Once the processing of the message completes and stores the task into Cosmos DB, the system will **trigger** an event (aka **Output binding**) that invokes the external service. This service, in turn, stores the content of the message into an Azure Blob Storage container. It is important to emphasize that both the Azure Storage Queue and the Azure Storage Blob belong to the *external* system. The rest of this module will implement the three scenarios mentioned below: diff --git a/docs/aca/07-aca-cron-bindings/index.md b/docs/aca/07-aca-cron-bindings/index.md index 9df6cf62..8a47a0b5 100644 --- a/docs/aca/07-aca-cron-bindings/index.md +++ b/docs/aca/07-aca-cron-bindings/index.md @@ -207,4 +207,4 @@ In this module, we have accomplished three objectives: 1. Learned how the Cron binding can trigger actions. 1. Added a Cron binding to the Backend Background Processor. -1. Deployed updated Background Processor and API projects to Azure. \ No newline at end of file +1. Deployed updated Background Processor and API projects to Azure. diff --git a/docs/aca/08-aca-monitoring/index.md b/docs/aca/08-aca-monitoring/index.md index 75cd4a0a..05c4411a 100644 --- a/docs/aca/08-aca-monitoring/index.md +++ b/docs/aca/08-aca-monitoring/index.md @@ -250,7 +250,7 @@ az acr build ` We need to update all three container apps with new revisions so that our code changes are available for end users. !!! tip - Notice how we used the property `--set-env-vars` to set new environment variable named `ApplicationInsights__InstrumentationKey`. Its value is a secret reference obtained from the secret `appinsights-key` we added in [step 1](#1-add-application-insights-instrumentation-key-as-a-secret). + Notice how we used the property `--set-env-vars` to set new environment variable named `ApplicationInsights__InstrumentationKey`. Its value is a secret reference obtained from the secret `appinsights-key` we added in step 1. ```shell # Update Backend API App container app and create a new revision diff --git a/docs/aca/10-aca-iac-bicep/ci-cd-azdo.md b/docs/aca/10-aca-iac-bicep/ci-cd-azdo.md index b54bab11..c23e2059 100644 --- a/docs/aca/10-aca-iac-bicep/ci-cd-azdo.md +++ b/docs/aca/10-aca-iac-bicep/ci-cd-azdo.md @@ -37,7 +37,7 @@ to create service connection for GitHub. #### Create Service Connection for Azure Subscription -Create a new service connection to your azure subscription by following the steps at this [link](https://docs.microsoft.com/en-us/azure/devops/pipelines/library/service-endpoints?view=azure-devops&tabs=yaml#create-a-service-connection){target=_blank}. +Create a new service connection to your Azure subscription by following the steps at this [link](https://docs.microsoft.com/en-us/azure/devops/pipelines/library/service-endpoints?view=azure-devops&tabs=yaml#create-a-service-connection){target=_blank}. !!! note Update the created service connection role to have **[User Access Administrator](https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles#user-access-administrator){target=_blank}** role. This is required for pipeline to be able to perform role assignments in the infrastructure components deployed. To update the role of a service connection in Azure DevOps to have the User Access Administrator role, you can follow these steps: diff --git a/docs/aca/10-aca-iac-bicep/ci-cd-git-action.md b/docs/aca/10-aca-iac-bicep/ci-cd-git-action.md index 1587f797..a2fdbc57 100644 --- a/docs/aca/10-aca-iac-bicep/ci-cd-git-action.md +++ b/docs/aca/10-aca-iac-bicep/ci-cd-git-action.md @@ -26,7 +26,7 @@ The Azure login action supports two different ways of authenticating with Azure: - [Service principal with secrets](https://learn.microsoft.com/en-us/azure/developer/github/connect-from-azure?tabs=azure-portal%2Clinux#use-the-azure-login-action-with-a-service-principal-secret){target=_blank} - [OpenID Connect (OIDC) with a Azure service principal using a Federated Identity Credential](https://learn.microsoft.com/en-us/azure/developer/github/connect-from-azure?tabs=azure-portal%2Clinux#use-the-azure-login-action-with-openid-connect){target=_blank} -In this workshop, we will use the OIDC authentication method. Assuming you are already logged in using azure cli locally, follow the steps below to configure the repository for OIDC authentication with Azure AD either using powershell or bash/wsl: +In this workshop, we will use the OIDC authentication method. Assuming you are already logged in using Azure cli locally, follow the steps below to configure the repository for OIDC authentication with Azure AD either using powershell or bash/wsl: === "PowerShell" @@ -119,7 +119,7 @@ echo $APP_ID Configure repository variables in GitHub repo as described here in [create GitHub variables](https://docs.github.com/en/actions/learn-github-actions/variables). Use below values mapped to relevant variables in GitHub. -```bash +```bash # LOCATION: Azure region where resources will be deployed LOCATION= diff --git a/docs/aca/10-aca-iac-bicep/iac-bicep.md b/docs/aca/10-aca-iac-bicep/iac-bicep.md index 94c4f7dd..5f04862d 100644 --- a/docs/aca/10-aca-iac-bicep/iac-bicep.md +++ b/docs/aca/10-aca-iac-bicep/iac-bicep.md @@ -38,7 +38,7 @@ Add a new folder named `bicep` on the root project directory, then add another f - The parameters `prefix` and `suffix` could be used if you want to add a prefix or suffix to the resource names. - The parameter `tag` is used to tag the created resources. Tags are key-value pairs that help you identify resources based on settings that are relevant to your organization and deployment. - The parameters `containerAppsEnvironmentName`, `logAnalyticsWorkspaceName`, and `applicationInsightName` have default values of resource names using the helper function named `uniqueString`. This function performs a 64-bit hash of the provided strings to create a unique string. This function is helpful when you need to create a unique name for a resource. We are passing the `resourceGroup().id` to this function to ensure that if we executed this module on two different resource groups, the generated string will be a global unique name. - - This module will create two resources. It will start by creating a `logAnalyticsWorkspace`, then an `applicationInsights` resource. Notice how we are setting the `logAnalyticsWorkspace.id` as an application insights `WorkspaceResourceId`. + - This module will create two resources. It will start by creating a `logAnalyticsWorkspace`, then an `applicationInsights` resource. Notice how we are setting the `logAnalyticsWorkspace.id` as an Application Insights `WorkspaceResourceId`. - Lastly we are creating the `containerAppsEnvironment`. Notice how we are setting the `daprAIInstrumentationKey` by using the Application Insights `InstrumentationKey` and then setting `logAnalyticsConfiguration.customerId` and `logAnalyticsConfiguration.sharedKey`. - The output of this module are a is parameter named `applicationInsightsName`. This output is needed as an input for a subsequent module. diff --git a/docs/aca/10-aca-iac-bicep/index.md b/docs/aca/10-aca-iac-bicep/index.md index 907e7e53..ef912c67 100644 --- a/docs/aca/10-aca-iac-bicep/index.md +++ b/docs/aca/10-aca-iac-bicep/index.md @@ -11,7 +11,7 @@ Once we have this in place, IaC deployments will benefit us in key ways such as: 1. By ensuring consistency and reducing human errors in resource provisioning, deployments can be made with greater confidence and consistency. 2. Avoid configuration drifts as IaC is an idempotent operation, which means it provides the same result each time it's run. 3. With Infrastructure as Code (IaC) in place, recreating an identical environment to the production one becomes a simple task of executing the scripts. This can be particularly useful during the application's lifecycle when short-term isolation is needed for tasks such as penetration testing or load testing. -4. The [Azure portal](https://portal.azure.com){target=_blank} abstracts several processes when you provision resources. For instance, when you create an Azure Container Apps Environment from the portal, it automatically creates a log analytics workspace and associates it with the environment without your direct involvement. However, using Infrastructure as Code (IaC) can provide you with a deeper understanding of Azure and help you troubleshoot any issues that may arise more effectively. +4. The [Azure portal](https://portal.azure.com){target=_blank} abstracts several processes when you provision resources. For instance, when you create an Azure Container Apps Environment from the portal, it automatically creates a Log Analytics workspace and associates it with the environment without your direct involvement. However, using Infrastructure as Code (IaC) can provide you with a deeper understanding of Azure and help you troubleshoot any issues that may arise more effectively. ### ARM Templates in Azure diff --git a/docs/aca/13-appendix/03-variables.md b/docs/aca/13-appendix/03-variables.md index 3fe303f0..8abf365e 100644 --- a/docs/aca/13-appendix/03-variables.md +++ b/docs/aca/13-appendix/03-variables.md @@ -2,7 +2,6 @@ We declare numerous variables throughout this workshop. As these modules are lengthy, you will likely complete them over multiple sessions. However, as sessions are additive, they require previously-set variables. - !!! info "Shell Support" Presently, this supports PowerShell only, and we would like to see community contributions for shell scripts, please. Please see [GitHub Issue #111](https://github.com/Azure/aca-dotnet-workshop/issues/111){target=_blank}.