Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
15 changes: 15 additions & 0 deletions .github/workflows/run-samples.yml
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,21 @@ jobs:
unzip -o -q -j "$RUNNER_TEMP/sqlcmd.zip" sqlcmd.exe -d "$RUNNER_TEMP/bin"
sqlcmd --version

- name: Install mongosh
# The Azure Cosmos DB for MongoDB sample seeds its collection with mongosh, which the Linux runner image
# does not ship (the Windows runner image does). The release and its SHA-256 are pinned.
if: matrix.os == 'linux' && matrix.sample == 'web-app-cosmosdb-mongodb-api'
env:
MONGOSH_VERSION: 2.14.1
MONGOSH_SHA256: 8d24940ebe3675959b518fd41ea16b4e2182d6a75c09777db09cfa64e18834a1
run: |
curl --silent --show-error --fail --location --retry 3 --output "$RUNNER_TEMP/mongosh.tgz" \
"https://github.com/mongodb-js/mongosh/releases/download/v${MONGOSH_VERSION}/mongosh-${MONGOSH_VERSION}-linux-x64.tgz"
echo "${MONGOSH_SHA256} $RUNNER_TEMP/mongosh.tgz" | sha256sum --check
tar -xzf "$RUNNER_TEMP/mongosh.tgz" -C "$RUNNER_TEMP"
echo "$RUNNER_TEMP/mongosh-${MONGOSH_VERSION}-linux-x64/bin" >> "$GITHUB_PATH"
"$RUNNER_TEMP/mongosh-${MONGOSH_VERSION}-linux-x64/bin/mongosh" --version

- name: Create the SSH key the cluster script provisions the node pools with
run: ssh-keygen -t rsa -b 4096 -N '' -f ~/.ssh/id_rsa -q

Expand Down
2 changes: 1 addition & 1 deletion samples/web-app-cosmosdb-mongodb-api/dotnet/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ cd scripts
| File | Description |
| ---- | ----------- |
| [`00-variables.sh`](scripts/00-variables.sh) | Defines the variables shared across the other scripts (resource names, image tag, Cosmos DB account/database/collection, Kubernetes namespace, …). The other scripts load these values by sourcing this file. |
| [`01-deploy-resources.sh`](scripts/01-deploy-resources.sh) | Deploys the Azure resources used by this sample: the resource group, the [Azure Container Registry (ACR)](https://learn.microsoft.com/en-us/azure/container-registry/container-registry-intro), the [Azure Cosmos DB for MongoDB](https://learn.microsoft.com/en-us/azure/cosmos-db/mongodb/overview) account, the `sampledb` database, and the `activities` collection (with its shard key and indexes). |
| [`01-deploy-resources.sh`](scripts/01-deploy-resources.sh) | Deploys the Azure resources used by this sample: the resource group, the [Azure Container Registry (ACR)](https://learn.microsoft.com/en-us/azure/container-registry/container-registry-intro), the [Azure Cosmos DB for MongoDB](https://learn.microsoft.com/en-us/azure/cosmos-db/mongodb/overview) account, the `sampledb` database, and the `activities` collection (with its shard key and indexes), which it also seeds with sample data. Requires `mongosh` on the host. The script also sets the account's MongoDB server version (`MONGODB_API_VERSION`) itself, because `az cosmosdb create --server-version` does not apply it and the account would otherwise run version 3.6, which the app's MongoDB driver refuses. |
| [`02-build-docker-image.sh`](scripts/02-build-docker-image.sh) | Builds the Docker image for the web app from the [`src/`](src/) folder. |
| [`03-run-docker-container.sh`](scripts/03-run-docker-container.sh) | Runs the web app in a local Docker container (no Kubernetes) to validate that it starts and connects to the database as expected. |
| [`04-push-docker-image.sh`](scripts/04-push-docker-image.sh) | Tags and pushes the Docker image to the Azure Container Registry, on Azure or in the LocalStack emulator. |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,83 @@ else
echo "Cosmos DB account [$COSMOSDB_ACCOUNT_NAME] already exists in the [$RESOURCE_GROUP_NAME] resource group"
fi

# Make sure the account runs the MongoDB server version the sample asks for. The Azure CLI sends the
# --server-version of az cosmosdb create and az cosmosdb update as a ServerVersion property, which the service
# ignores, so the account keeps the default server version, 3.6, which the MongoDB drivers of the app and of
# mongosh refuse. The script sets the serverVersion property itself, with the API version the Azure CLI uses,
# and waits for the upgrade, which takes about a minute.
echo "Retrieving the MongoDB server version of Cosmos DB account [$COSMOSDB_ACCOUNT_NAME]..."
SERVER_VERSION=$(az cosmosdb show \
--name "$COSMOSDB_ACCOUNT_NAME" \
--resource-group "$RESOURCE_GROUP_NAME" \
--query "apiProperties.serverVersion" \
--output tsv \
--only-show-errors)

if [[ -n $SERVER_VERSION ]]; then
echo "Cosmos DB account [$COSMOSDB_ACCOUNT_NAME] runs MongoDB server version [$SERVER_VERSION]"
else
echo "Failed to retrieve the MongoDB server version of Cosmos DB account [$COSMOSDB_ACCOUNT_NAME]"
exit 1
fi

if [[ "$SERVER_VERSION" != "$MONGODB_API_VERSION" ]]; then
echo "Retrieving the resource id of Cosmos DB account [$COSMOSDB_ACCOUNT_NAME]..."
COSMOSDB_ACCOUNT_ID=$(az cosmosdb show \
--name "$COSMOSDB_ACCOUNT_NAME" \
--resource-group "$RESOURCE_GROUP_NAME" \
--query "id" \
--output tsv \
--only-show-errors)

if [[ -n $COSMOSDB_ACCOUNT_ID ]]; then
echo "Resource id of Cosmos DB account [$COSMOSDB_ACCOUNT_NAME] retrieved successfully"
else
echo "Failed to retrieve the resource id of Cosmos DB account [$COSMOSDB_ACCOUNT_NAME]"
exit 1
fi

echo "Upgrading Cosmos DB account [$COSMOSDB_ACCOUNT_NAME] to MongoDB server version [$MONGODB_API_VERSION]..."
az rest \
--method patch \
--url "${COSMOSDB_ACCOUNT_ID}?api-version=2026-03-15" \
--body "{\"properties\": {\"apiProperties\": {\"serverVersion\": \"$MONGODB_API_VERSION\"}}}" \
--only-show-errors 1>/dev/null

if [[ $? != 0 ]]; then
echo "Failed to upgrade Cosmos DB account [$COSMOSDB_ACCOUNT_NAME] to MongoDB server version [$MONGODB_API_VERSION]"
exit 1
fi

for ATTEMPT in $(seq 1 60); do
SERVER_VERSION=$(az cosmosdb show \
--name "$COSMOSDB_ACCOUNT_NAME" \
--resource-group "$RESOURCE_GROUP_NAME" \
--query "apiProperties.serverVersion" \
--output tsv \
--only-show-errors)
PROVISIONING_STATE=$(az cosmosdb show \
--name "$COSMOSDB_ACCOUNT_NAME" \
--resource-group "$RESOURCE_GROUP_NAME" \
--query "provisioningState" \
--output tsv \
--only-show-errors)

if [[ "$SERVER_VERSION" == "$MONGODB_API_VERSION" && "$PROVISIONING_STATE" == "Succeeded" ]]; then
break
fi
echo "Waiting for the upgrade of Cosmos DB account [$COSMOSDB_ACCOUNT_NAME] (attempt $ATTEMPT of 60)..."
sleep 10
done

if [[ "$SERVER_VERSION" == "$MONGODB_API_VERSION" && "$PROVISIONING_STATE" == "Succeeded" ]]; then
echo "Cosmos DB account [$COSMOSDB_ACCOUNT_NAME] successfully upgraded to MongoDB server version [$MONGODB_API_VERSION]"
else
echo "Failed to upgrade Cosmos DB account [$COSMOSDB_ACCOUNT_NAME]: it still runs MongoDB server version [$SERVER_VERSION]"
exit 1
fi
fi

# Create the MongoDB database
echo "Checking if MongoDB database [$COSMOSDB_DATABASE_NAME] exists in account [$COSMOSDB_ACCOUNT_NAME]..."
az cosmosdb mongodb database show \
Expand Down Expand Up @@ -159,4 +236,106 @@ else
exit 1
fi

# Insert the sample activities, so the app does not start with an empty list. Each activity is a document
# {_id, username, activity, timestamp} of the user the app shows, the shape the app itself reads and writes; these
# are the activities the SQL Database, MySQL and PostgreSQL samples seed. A document id is the MD5 of the user and
# a fixed name, and each upsert sets the fields only when it creates the document, so a re-run inserts only the
# missing activities and leaves the others as they are. The filter of each upsert holds the shard key (username),
# which an update of a sharded collection requires.
# mongosh must be available on the host machine.
if ! command -v mongosh &>/dev/null; then
echo "mongosh is not installed on the host. Install the MongoDB Shell (mongosh) and re-run."
exit 1
fi

# After an upgrade, the MongoDB endpoint of the account can go on serving the old server version for several
# minutes after Azure Resource Manager reports the new one, and mongosh refuses a server older than 4.2. Wait until
# mongosh connects; each attempt that fails takes about 30 seconds, the time mongosh looks for a suitable server.
echo "Checking that the MongoDB endpoint of Cosmos DB account [$COSMOSDB_ACCOUNT_NAME] accepts mongosh connections..."
MONGOSH_CONNECTED=false
for ATTEMPT in $(seq 1 30); do
CONNECTION_ERROR=$(mongosh "$COSMOSDB_CONNECTION_STRING" --quiet --eval 'db.hello().ok' 2>&1 1>/dev/null)

if [[ $? == 0 ]]; then
MONGOSH_CONNECTED=true
break
fi
echo "The MongoDB endpoint does not accept mongosh connections yet (attempt $ATTEMPT of 30): $CONNECTION_ERROR"
sleep 10
done

if [[ $MONGOSH_CONNECTED == true ]]; then
echo "The MongoDB endpoint of Cosmos DB account [$COSMOSDB_ACCOUNT_NAME] accepts mongosh connections"
else
echo "Failed to connect to the MongoDB endpoint of Cosmos DB account [$COSMOSDB_ACCOUNT_NAME] with mongosh"
exit 1
fi

SAMPLE_ACTIVITIES=(
"pisa|Visit the Leaning Tower in Pisa"
"volterra|Explore Etruscan walls in Volterra"
"san_gimignano|Climb Torre Grossa in San Gimignano"
"siena|Walk across Piazza del Campo in Siena"
"montalcino|Taste Brunello wine in Montalcino"
"pienza|Sample Pecorino cheese in Pienza"
"florence|Admire Michelangelo's David in Florence"
"viareggio_beach|Relax by the beach in Viareggio"
"viareggio_promenade|Stroll along the Viareggio promenade"
)

# mongosh reads the values from its environment, so no activity needs quoting in the script
echo "Inserting the sample activities of [$LOGIN_NAME] into collection [$COSMOSDB_COLLECTION_NAME]..."
SEED_DATABASE="$COSMOSDB_DATABASE_NAME" \
SEED_COLLECTION="$COSMOSDB_COLLECTION_NAME" \
SEED_USERNAME="$LOGIN_NAME" \
SEED_TIMESTAMP="$(date '+%Y-%m-%dT%H:%M:%S.000000')" \
SEED_ACTIVITIES="$(printf '%s\n' "${SAMPLE_ACTIVITIES[@]}")" \
mongosh "$COSMOSDB_CONNECTION_STRING" --quiet --eval '
const crypto = require("crypto");
const env = process.env;
const collection = db.getSiblingDB(env.SEED_DATABASE).getCollection(env.SEED_COLLECTION);
const operations = env.SEED_ACTIVITIES.trim().split("\n").map((line) => {
const separator = line.indexOf("|");
const name = line.slice(0, separator);
const activity = line.slice(separator + 1);
const id = crypto.createHash("md5").update(`${env.SEED_USERNAME}_${name}_seed`).digest("hex");
return {
updateOne: {
filter: { _id: id, username: env.SEED_USERNAME },
update: { $setOnInsert: { activity: activity, timestamp: env.SEED_TIMESTAMP } },
upsert: true
}
};
});
const result = collection.bulkWrite(operations, { ordered: false });
print(`${result.upsertedCount} activities inserted, ${result.matchedCount} already present`);
'

if [ $? -eq 0 ]; then
echo "Sample activities inserted successfully into collection [$COSMOSDB_COLLECTION_NAME]."
else
echo "Failed to insert the sample activities into collection [$COSMOSDB_COLLECTION_NAME]."
exit 1
fi

# Query the activities of the user back
echo "Querying the activities of [$LOGIN_NAME] from collection [$COSMOSDB_COLLECTION_NAME]..."
SEED_DATABASE="$COSMOSDB_DATABASE_NAME" \
SEED_COLLECTION="$COSMOSDB_COLLECTION_NAME" \
SEED_USERNAME="$LOGIN_NAME" \
mongosh "$COSMOSDB_CONNECTION_STRING" --quiet --eval '
const env = process.env;
db.getSiblingDB(env.SEED_DATABASE)
.getCollection(env.SEED_COLLECTION)
.find({ username: env.SEED_USERNAME }, { _id: 0, activity: 1 })
.forEach((document) => print(` - ${document.activity}`));
'

if [ $? -eq 0 ]; then
echo "Activities of [$LOGIN_NAME] queried successfully."
else
echo "Failed to query the activities of [$LOGIN_NAME]."
exit 1
fi

export COSMOSDB_CONNECTION_STRING
2 changes: 1 addition & 1 deletion samples/web-app-cosmosdb-mongodb-api/python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ cd scripts
| File | Description |
| ---- | ----------- |
| [`00-variables.sh`](scripts/00-variables.sh) | Defines the variables shared across the other scripts (resource names, image tag, Cosmos DB account/database/collection, Kubernetes namespace, …). The other scripts load these values by sourcing this file. |
| [`01-deploy-resources.sh`](scripts/01-deploy-resources.sh) | Deploys the Azure resources used by this sample: the resource group, the [Azure Container Registry (ACR)](https://learn.microsoft.com/en-us/azure/container-registry/container-registry-intro), the [Azure Cosmos DB for MongoDB](https://learn.microsoft.com/en-us/azure/cosmos-db/mongodb/overview) account, the `sampledb` database, and the `activities` collection (with its shard key and indexes). |
| [`01-deploy-resources.sh`](scripts/01-deploy-resources.sh) | Deploys the Azure resources used by this sample: the resource group, the [Azure Container Registry (ACR)](https://learn.microsoft.com/en-us/azure/container-registry/container-registry-intro), the [Azure Cosmos DB for MongoDB](https://learn.microsoft.com/en-us/azure/cosmos-db/mongodb/overview) account, the `sampledb` database, and the `activities` collection (with its shard key and indexes), which it also seeds with sample data. Requires `mongosh` on the host. The script also sets the account's MongoDB server version (`MONGODB_API_VERSION`) itself, because `az cosmosdb create --server-version` does not apply it and the account would otherwise run version 3.6, which the app's MongoDB driver refuses. |
| [`02-build-docker-image.sh`](scripts/02-build-docker-image.sh) | Builds the Docker image for the web app from the [`src/`](src/) folder. |
| [`03-run-docker-container.sh`](scripts/03-run-docker-container.sh) | Runs the web app in a local Docker container (no Kubernetes) to validate that it starts and connects to the database as expected. |
| [`04-push-docker-image.sh`](scripts/04-push-docker-image.sh) | Tags and pushes the Docker image to the Azure Container Registry, on Azure or in the LocalStack emulator. |
Expand Down
Loading
Loading