Skip to content
Open
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
f51bdee
Add HOME so the script can be run in any folder
petetian Mar 7, 2025
4891990
Merge branch 'Azure-Samples:main' into main
petetian Mar 7, 2025
74c3136
Updated azure-resource.profile and create-azure-resource.sh with new …
petetian Mar 7, 2025
8d42816
Add bash scripts for lab-2
petetian Mar 8, 2025
b406e13
add create.mysql.sh
petetian Mar 9, 2025
6212a30
Remove the dependencies of external parameters
petetian Mar 9, 2025
6aeeeba
new module creation
petetian Mar 9, 2025
c2fe648
create new module
petetian Mar 9, 2025
3249751
Remove unused variable
petetian Mar 10, 2025
29df268
Update azd json with steps in lab2
petetian Mar 10, 2025
fa60784
create docker images for microservices
petetian Mar 10, 2025
7afe183
refactory
petetian Mar 11, 2025
5cf4a91
Refactory
petetian Mar 11, 2025
ae3fac9
Refactor: move azure-resource.profile to ../config sharing with other…
petetian Mar 11, 2025
4f8ab79
Refactor: source the config file created by the previous step. Add ap…
petetian Mar 11, 2025
188d693
Refactor
petetian Mar 11, 2025
94ff0ef
Refactor: use common config file
petetian Mar 11, 2025
27b345a
Write created components to config file
petetian Mar 12, 2025
766ca0a
add new module
petetian Mar 12, 2025
901cf04
update .gitignore
petetian Mar 12, 2025
1dfd416
update .gitignore
petetian Mar 12, 2025
87d939a
export LOCATION
petetian Mar 12, 2025
7e2780b
add lab-3
petetian Mar 13, 2025
d923a1d
Merge remote-tracking branch 'upstream'
petetian Mar 13, 2025
dc6a7ed
create main script as entry point
petetian Mar 13, 2025
058f350
add script for lab 3
petetian Mar 13, 2025
f575923
add lab-3; refactor lab-2
petetian Mar 13, 2025
b210c9f
bug fixing
petetian Mar 13, 2025
fa209e0
bug fixing
petetian Mar 13, 2025
a71b2a3
bug fixing
petetian Mar 13, 2025
678f85a
clean up
petetian Mar 13, 2025
5c65673
clean up
petetian Mar 13, 2025
7366333
create lab-3
petetian Mar 14, 2025
293b48b
bug fixing
petetian Mar 15, 2025
77c96eb
add java modules
petetian Mar 18, 2025
d2b4001
fix bugs in Java modules
petetian Mar 18, 2025
9e43a81
lab-3 fully working version
petetian Mar 18, 2025
77e68cb
add main script for lab-3
petetian Mar 18, 2025
6b03acf
update chat joke url
petetian Mar 18, 2025
55f730d
create scripts in lab-4
petetian Mar 19, 2025
710a35b
more for lab-4
petetian Mar 19, 2025
b891f6f
merge from upstream
petetian Apr 7, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions tools/azd-extension/java-on-ai-azd.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"$schema": "https://aka.ms/azd-extension-schema",
"name": "java-on-ai-extension",
"version": "1.1.0",
"description": "Java on AI AZD extension with bash",
"publisher": "Pete Tian",
"commands": [
{
"name": "collecte user information",
"description": "Before performing any additional actions, you’ll need to store your user info as an environment variable that you can use in subsequent steps.",
"entryPoint": "./lab2/collect-user-info.sh"
},
{
"name": "Create an Azure Container Apps environment",
"description": "With your user information stored in environment variables, you’re ready to begin the first step in the deployment: creating an Azure Container Apps instance.",
"entryPoint": "./lab-2/create-aca-env.sh"
},
{
"name": "Create an Azure Database for MySQL instance",
"description": " create an Azure Database for MySQL - Flexible Server–hosted database.",
"entryPoint": "./lab-2/create-mysql.sh"
},
{
"name": "Set up a configuration repository",
"description": "set up the application configuration settings that allow your Spring Boot application to connect with the database.",
"entryPoint": "./lab-2/create-container-registry.sh"
},
{
"name": "Create the Java components",
"description": "configure the config, discovery, and admin applications.",
"entryPoint": "./lab-2/create-java-components.sh"
},
{
"name": "Deploy the component applications to Azure Container Apps",
"description": "deploy the workload’s component applications to Azure.",
"entryPoint": "./lab-2/deploy-component-apps.sh"
}
]
}

9 changes: 9 additions & 0 deletions tools/azd-extension/lab-2/collect-user-info.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/bin/bash
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in some environment like Github codespace, we may fail to get the AAD_USER_ID, we should check if the AAD_USER_ID is valid before continue

# Before performing any additional actions, store user info as an environment variable that
# can be used in subsequent steps.

export USER_NAME=$(az account show --query user.name --output tsv)
echo "Current user:" $USER_NAME

export AAD_USER_ID=$(az ad signed-in-user show --query id --output tsv)
echo "Object ID:" $AAD_USER_ID
69 changes: 69 additions & 0 deletions tools/azd-extension/lab-2/create-aca-env.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#!/bin/bash
# This script creates an Azure Container Apps environment with a dedicated plan and a virtual network.
# It also creates a resource group and a virtual network with a subnet for the Azure Container Apps environment.
# The script uses the Azure CLI to create the resources and requires the user to be logged in to their Azure account.
# The script also requires the user to have the Azure CLI installed and configured on their machine.
# The script uses the `az` command to create the resources and requires the user to have the necessary permissions to create resources in their Azure account.
# The script uses the `openssl` command to generate a random unique ID for the resource group and virtual network names.
# The script uses the `az configure` command to set the default resource group for the Azure CLI commands.

#source ../../azure-resource.profile

UNIQUEID=$(openssl rand -hex 3)
APPNAME=petclinic
RESOURCE_GROUP=$(az group list --query "[?contains(name, 'petclinic')].{Name:name}[0]" -o tsv)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when multiple members share the same subscription, this would cause some conflicts on same resource group.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same for the acr, aca environment list & check


if [ -z "$RESOURCE_GROUP" ]; then
RESOURCE_GROUP=rg-$APPNAME-$UNIQUEID
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we will have user to set the UNIQUEID in profile and import those settings first.
we run "export RESOURCE_GROUP=rg-$APPNAME-$UNIQUEID" at the beginning.

In the current process,

  1. there will be conflict on resource group name
  2. we make sure we can rerun the script

LOCATION=$(random_element australiaeast brazilsouth eastasia eastus2 japaneast southindia swedencentral westus)
echo "Creating resource group [$RESOURCE_GROUP] in region [$LOCATION]..."
az group create -g $RESOURCE_GROUP -l $LOCATION
else
LOCATION=$(az group show --name $RESOURCE_GROUP --query "location" -o tsv)
echo "Provisioning in resource group [$RESOURCE_GROUP]..."
fi

az configure --default group=$RESOURCE_GROUP
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we may ask user to input the subscription.

az account set -s SUB

or az configure --default subscription=xxx


#
# Create VNET for Azure Container Apps Environment
#
VIRTUAL_NETWORK_NAME=vnet-$APPNAME-$UNIQUEID
az network vnet create \
--resource-group $RESOURCE_GROUP \
--name $VIRTUAL_NETWORK_NAME \
--location $LOCATION \
--address-prefix 10.1.0.0/16

ACA_SUBNET_CIDR=10.1.0.0/27
az network vnet subnet create \
--resource-group $RESOURCE_GROUP \
--vnet-name $VIRTUAL_NETWORK_NAME \
--address-prefixes $ACA_SUBNET_CIDR \
--name aca-subnet \
--delegations Microsoft.App/environments

SUBNET_ID="$(az network vnet subnet show --resource-group $RESOURCE_GROUP --vnet-name $VIRTUAL_NETWORK_NAME --name aca-subnet --query "id" -o tsv)"
echo "Subnet ID: [$SUBNET_ID]"

#
# Creating the service on an Azure Container Apps Dedicated plan using the workload profiles option.
# This plan gives you more advanced features than the alternative Azure Container Apps Consumption plan type
#
ACA_ENVIRONMENT=acalab-env-$APPNAME-$UNIQUEID

# winty is to accomodate git bash on Windows
# Otherwise, SUBNET_ID will be appended with local drive path
# NO_PATHCOW is for git bash on Windows
export MSYS_NO_PATHCONV=1

az containerapp env create \
-n $ACA_ENVIRONMENT \
-g $RESOURCE_GROUP \
--location $LOCATION \
--enable-workload-profiles true \
--infrastructure-subnet-resource-id "$SUBNET_ID" \
--logs-destination none

ACA_ENVIRONMENT_ID=$(az containerapp env show -n $ACA_ENVIRONMENT -g $RESOURCE_GROUP --query id -o tsv)

56 changes: 56 additions & 0 deletions tools/azd-extension/lab-2/create-container-registry.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#!/bin/bash
#
# Before deploying applications to the Azure Container Apps environment, you’ll need an Azure Container Registry instance that allows you to build and save your application container images.
# You’ll also need to allow your Container Apps environment to pull images from this new container registry.
#
# To give the Container Apps environment secure access to the container registry, we’ll create a user managed identity and assign it the required privileges to use the images stored in your Azure Container Registry.

APPNAME=petclinic
RESOURCE_GROUP=$(az group list --query "[?contains(name, 'petclinic')].{Name:name}[0]" -o tsv)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'petclinic' -> '$APPNAME'

echo "Resource group: $RESOURCE_GROUP"
if [ -z "$RESOURCE_GROUP" ]; then
echo "Error: Resource group not found."
exit 1
fi

# Check if a container registry containing the string $APPNAME already exists
EXISTING_ACR=$(az acr list --resource-group $RESOURCE_GROUP --query "[?contains(name, '$APPNAME')].{Name:name}[0]" -o tsv)

UNIQUEID=$(openssl rand -hex 3)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

renew the UNIQUEID will cause mismatch in the later steps.

if [ -n "$EXISTING_ACR" ]; then
echo "Container registry [$EXISTING_ACR] already exists. Skipping creation."
MYACR=$EXISTING_ACR
else
MYACR=acr$APPNAME$UNIQUEID
az acr create \
-n $MYACR \
-g $RESOURCE_GROUP \
--sku Basic \
--admin-enabled true
fi

# Check if ACA environment name containing string "acalab-env" exists
ACA_ENVIRONMENT=$(az containerapp env list --resource-group $RESOURCE_GROUP --query "[?contains(name, 'acalab-env')].{Name:name}[0]" -o tsv)

if [ -z "$ACA_ENVIRONMENT" ]; then
echo "Error: ACA environment containing 'acalab-env' not found."
exit 1
fi

# Disable path conversion for MSYS (Git Bash)
export MSYS_NO_PATHCONV=1

# Create the identity that your container apps will use.
APPS_IDENTITY=uid-petclinic-$UNIQUEID
az identity create --resource-group $RESOURCE_GROUP --name $APPS_IDENTITY --output json

APPS_IDENTITY_ID=$(az identity show --resource-group $RESOURCE_GROUP --name $APPS_IDENTITY --query id --output tsv)
APPS_IDENTITY_SP_ID=$(az identity show --resource-group $RESOURCE_GROUP --name $APPS_IDENTITY --query principalId --output tsv)

echo "Assign the user identity to your Azure Container Apps environment."
az containerapp env identity assign -g $RESOURCE_GROUP -n $ACA_ENVIRONMENT --user-assigned $APPS_IDENTITY_ID

# Grant the identity with the necessary privileges to pull images from the container registry.
ACR_ID=$(az acr show -n $MYACR -g $RESOURCE_GROUP --query id -o tsv)
az role assignment create --assignee $APPS_IDENTITY_SP_ID --scope $ACR_ID --role acrpull

62 changes: 62 additions & 0 deletions tools/azd-extension/lab-2/create-java-components.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#!/bin/bash
#
# Configure the config, discovery, and admin applications. These are available as built-in components of Azure Container Apps.

APPNAME=petclinic
RESOURCE_GROUP=$(az group list --query "[?contains(name, 'petclinic')].{Name:name}[0]" -o tsv)
echo "Resource group: $RESOURCE_GROUP"
if [ -z "$RESOURCE_GROUP" ]; then
echo "Error: Resource group not found."
exit 1
fi

# Create the Spring Cloud Config Server Java component. You’ll need to pass the Git repo information you defined back
# in the Config repo step to correctly load your configuration information.
GIT_URI="https://github.com/Azure-Samples/java-on-aca.git"
SEARCH_PATH="config"
LABEL=main

# Check if ACA environment name containing string "acalab-env" exists
ACA_ENVIRONMENT=$(az containerapp env list --resource-group $RESOURCE_GROUP --query "[?contains(name, 'acalab-env')].{Name:name}[0]" -o tsv)

if [ -z "$ACA_ENVIRONMENT" ]; then
echo "Error: ACA environment containing 'acalab-env' not found."
exit 1
fi

JAVA_CONFIG_COMP_NAME=configserver
az containerapp env java-component config-server-for-spring create \
--environment $ACA_ENVIRONMENT \
--resource-group $RESOURCE_GROUP \
--name $JAVA_CONFIG_COMP_NAME \
--set-configuration spring.cloud.config.server.git.uri=$GIT_URI spring.cloud.config.server.git.search-paths=$SEARCH_PATH spring.cloud.config.server.git.default-label=$LABEL

# Check the Spring Cloud Config Server Java component to confirm that it was successfully created.
CONFIG_SERVER_EXISTS=$(az containerapp env java-component config-server-for-spring show \
--environment $ACA_ENVIRONMENT \
--resource-group $RESOURCE_GROUP \
--name $JAVA_CONFIG_COMP_NAME --query "name" -o tsv)

if [ -z "$CONFIG_SERVER_EXISTS" ]; then
echo "Error: Config server was not successfully created."
exit 1
fi

# Create the Spring Cloud Eureka Server Java component. This will create a standard Eureka endpoint within
# the Container Apps environment. The Spring Petclinic workload will use this for discovery services.
JAVA_EUREKA_COMP_NAME=eureka
az containerapp env java-component eureka-server-for-spring create \
--environment $ACA_ENVIRONMENT \
--resource-group $RESOURCE_GROUP \
--name $JAVA_EUREKA_COMP_NAME \
--set-configuration eureka.server.response-cache-update-interval-ms=10000

# Create a new Spring Boot Admin application and bind it to the Eureka Server
JAVA_SBA_COMP_NAME=springbootadmin
az containerapp env java-component admin-for-spring create \
--environment $ACA_ENVIRONMENT \
--resource-group $RESOURCE_GROUP \
--name $JAVA_SBA_COMP_NAME \
--bind $JAVA_EUREKA_COMP_NAME \
--min-replicas 1 \
--max-replicas 1
33 changes: 33 additions & 0 deletions tools/azd-extension/lab-2/create-mysql.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/bin/bash

UNIQUEID=$(openssl rand -hex 3)
APPNAME=petclinic

RESOURCE_GROUP=$(az group list --query "[?contains(name, 'petclinic')].{Name:name}[0]" -o tsv)

# This script creates an Azure MySQL server and an Azure Container Registry (ACR) in a specified resource group.
MYSQL_SERVER_NAME=mysql-$APPNAME-$UNIQUEID
MYSQL_ADMIN_USERNAME=sqladmin
MYSQL_ADMIN_PASSWORD="5qVYxsoyaV9qJN"
DATABASE_NAME=petclinic

az mysql flexible-server create \
--admin-user "$MYSQL_ADMIN_USERNAME" \
--admin-password "$MYSQL_ADMIN_PASSWORD" \
--name "$MYSQL_SERVER_NAME" \
--resource-group "$RESOURCE_GROUP" \
--public-access none \
--yes
az mysql flexible-server db create \
--server-name $MYSQL_SERVER_NAME \
--resource-group $RESOURCE_GROUP \
-d $DATABASE_NAME

#
# Allow public access to the MySQL server
#
az mysql flexible-server firewall-rule create \
--rule-name allAzureIPs \
--name $MYSQL_SERVER_NAME \
--resource-group $RESOURCE_GROUP \
--start-ip-address 0.0.0.0 --end-ip-address 0.0.0.0
22 changes: 22 additions & 0 deletions tools/azd-extension/lab-2/deploy-component-apps.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/bin/bash

# Get the application code from public upstream repo, and then build the applications.
cd ../../../spring-petclinic-microservices
git submodule update --init
mvn clean package -DskipTests

# Build the Docker image using the Dockerfile

DOCKERFILE="../tools/Dockerfile"
if [ ! -f $DOCKERFILE ]; then
echo "Dockerfile not found at $DOCKERFILE"
exit 1
fi

docker build -t petclinic-admin-server:latest -f $DOCKERFILE ./spring-petclinic-admin-server
docker build -t petclinic-api-gateway:latest -f $DOCKERFILE ./spring-petclinic-api-gateway
docker build -t petclinic-config-server:latest -f $DOCKERFILE ./spring-petclinic-config-server
docker build -t petclinic-customers-service:latest -f $DOCKERFILE ./spring-petclinic-customers-service
docker build -t petclinic-discovery-server:latest -f $DOCKERFILE ./spring-petclinic-discovery-server
docker build -t petclinic-vets-service:latest -f $DOCKERFILE ./spring-petclinic-vets-service
docker build -t petclinic-visits-service:latest -f $DOCKERFILE ./spring-petclinic-visits-service
4 changes: 2 additions & 2 deletions tools/azure-resource.profile
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@

# Set all the variables with <> and keep the others unchanged

# This part is for lab 2 & Lab 3

# Pay attention to this, use command 'openssl rand -hex 3' to generate a unique id and put value here, don't put command here
UNIQUEID=<unique-id>

# To extract the subscription ID, use the following Azure CLI command:
# az account show --query id --output tsv
SUBSCRIPTION=<subscription-id>
LOCATION=<region>

APPNAME=petclinic
RESOURCE_GROUP=rg-$APPNAME-$UNIQUEID
Expand Down
28 changes: 13 additions & 15 deletions tools/create-azure-resource.sh
Original file line number Diff line number Diff line change
@@ -1,31 +1,33 @@
#!/usr/bin/env bash

source ./azure-resource.profile
source ./funcs.sh
export HOME=/workspaces/java-on-aca

source ./tools/azure-resource.profile
source ./tools/funcs.sh

# Resource Group

# Random regions for MySQL server
LOCATION=$(random_element australiaeast brazilsouth eastasia eastus2 japaneast southindia swedencentral westus)
Copy link
Collaborator

@sonwan2020 sonwan2020 Mar 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here are the problems with these regions:

  1. OpenAI not supported in eastasia
  2. Managed Grafana not supported in southindia, prefer use centralindia
    See the differences between AI_LOCATION, SQL_LOCATION, GRAFANA_LOCATION

Copy link
Collaborator

@sonwan2020 sonwan2020 Mar 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW, I don't think the potential regional latency is matter in this lab environment


az group create -g $RESOURCE_GROUP -l $LOCATION -o table

az configure --default group=$RESOURCE_GROUP

# MySQL server

# Random regions for MySQL server
SQL_LOCATION=$(random_element australiaeast brazilsouth eastasia eastus2 japaneast southindia swedencentral westus)

SQL_ID=$(az mysql flexible-server show --resource-group $RESOURCE_GROUP --name $MYSQL_SERVER_NAME -o tsv --query id 2>/dev/null)
if [[ -n $SQL_ID ]]; then
echo -e "${GREEN}INFO:${NC} MySQL server $MYSQL_SERVER_NAME already exists"
else
echo -e "${YELLOW}INFO:${NC} Creating MySQL server $MYSQL_SERVER_NAME in region $SQL_LOCATION ..."
echo -e "${YELLOW}INFO:${NC} Creating MySQL server $MYSQL_SERVER_NAME in region $LOCATION ..."

az mysql flexible-server create \
--admin-user $MYSQL_ADMIN_USERNAME \
--admin-password $MYSQL_ADMIN_PASSWORD \
--name $MYSQL_SERVER_NAME \
--resource-group $RESOURCE_GROUP \
--location $SQL_LOCATION \
--location $LOCATION \
--public-access none \
--yes \
--output table
Expand All @@ -49,18 +51,16 @@ fi

# Azure OpenAI Service

AI_LOCATION=$(random_element australiaeast brazilsouth eastus2 japaneast southindia swedencentral westus)

AI_ID=$(az cognitiveservices account show --resource-group $RESOURCE_GROUP --name $OPEN_AI_SERVICE_NAME -o tsv --query id 2>/dev/null)
if [[ -n $ACR_ID ]]; then
echo -e "${GREEN}INFO:${NC} OpenAI instance $OPEN_AI_SERVICE_NAME already exists"
else
echo -e "${YELLOW}INFO:${NC} Creating OpenAI instance $OPEN_AI_SERVICE_NAME in region $AI_LOCATION ..."
echo -e "${YELLOW}INFO:${NC} Creating OpenAI instance $OPEN_AI_SERVICE_NAME in region $LOCATION ..."

az cognitiveservices account create \
--resource-group $RESOURCE_GROUP \
--name $OPEN_AI_SERVICE_NAME \
--location $AI_LOCATION \
--location $LOCATION \
--kind OpenAI \
--sku s0 \
--custom-domain $OPEN_AI_SERVICE_NAME \
Expand Down Expand Up @@ -122,18 +122,16 @@ fi

# Azure Managed Grafana

GRAFANA_LOCATION=$(random_element australiaeast brazilsouth centralindia eastasia eastus2 japaneast swedencentral westus)

GRAFANA_ID=$(az grafana show --name $GRAFANA_NAME --resource-group $RESOURCE_GROUP -o tsv --query id 2>/dev/null)
if [[ -n $GRAFANA_ID ]]; then
echo -e "${GREEN}INFO:${NC} Grafana instance $GRAFANA_NAME already exists"
else
echo -e "${YELLOW}INFO:${NC} Creating Grafana instance $GRAFANA_NAME in region $GRAFANA_LOCATION ..."
echo -e "${YELLOW}INFO:${NC} Creating Grafana instance $GRAFANA_NAME in region $LOCATION ..."

az deployment group create \
--resource-group $RESOURCE_GROUP \
--template-file ../infra/bicep/modules/grafana/grafana-dashboard.bicep \
--parameters grafanaName=$GRAFANA_NAME location=$GRAFANA_LOCATION \
--parameters grafanaName=$GRAFANA_NAME location=$LOCATION \
--output table
fi

Expand Down