Créer un script Azure CLI pour Bash
À peu près toutes les tâches que vous pouvez effectuer dans le portail Azure, vous pouvez effectuer à l’aide des commandes de référence Azure CLI . L’utilisation du portail Azure pour en savoir plus sur Azure est un excellent point de départ. Toutefois, nous vous recommandons d’utiliser Azure CLI ou Azure PowerShell pour gérer les ressources Azure à grande échelle.
Envisagez le scénario dans lequel vous gérez Azure pour une société mondiale. Vous recevez plusieurs demandes quotidiennes pour les nouveaux groupes de ressources, Azure Logic Apps, les comptes de stockage, les pipelines Azure Data Factory et lesbases de données Azure SQL. Toutes vos équipes travaillent dans des environnements de développement, de préproduction et de production. Pour chaque demande, vous devez créer trois ressources Azure similaires qui suivent les normes d’affectation de noms et les stratégies de sécurité de votre entreprise. Il est temps d’utiliser des scripts Azure CLI !
Présentation des scripts Azure CLI
Les scripts Azure CLI permettent l’automatisation des tâches répétitives et du déploiement d’infrastructure à grande échelle. Les scripts fournissent une cohérence, réduisent les erreurs humaines et activent les pratiques d’infrastructure en tant que code (IaC). Que vous gériez des environnements de développement, de préproduction ou de production, le script Azure CLI simplifie l’approvisionnement et la gestion des ressources.
Notions de base de la structure de script
Un script Azure CLI bien structuré inclut généralement les éléments suivants :
-
Shebang (
#!/bin/bashou#!/usr/bin/env bash) : spécifie l’interpréteur pour l’exécution du script. - Variables: Stockez des valeurs réutilisables telles que les noms de ressources, les emplacements et les configurations de référence SKU.
- Commentaires: Documentez la logique de script et les paramètres pour la maintenance.
- Gestion des erreurs : Implémentez des vérifications pour gérer correctement les défaillances.
- Boucles et conditions : Créez plusieurs ressources ou appliquez une logique basée sur des conditions.
- Mise en forme de sortie : Afficher les résultats dans des formats lisibles pour la validation.
Créer un script de déploiement de ressources
Examinons un script Bash pratique qui crée plusieurs comptes de stockage Azure de manière cohérente et reproductible.
#!/bin/bash
# Script: Create multiple Azure storage accounts
# Description: Automates storage account creation with consistent naming and configuration
# Define deployment parameters
resourceGroupName="rg-storage-prod-eastus"
saCount=3
saLocation="eastus"
saNamePrefix="stprod"
saSku="Standard_GRS"
saKind="StorageV2"
# Validate Azure CLI is installed and authenticated
if ! command -v az &> /dev/null; then
echo "Error: Azure CLI is not installed. Please install Azure CLI first."
exit 1
fi
if ! az account show &> /dev/null; then
echo "Error: Not authenticated to Azure. Please run 'az login' first."
exit 1
fi
echo "Starting storage account deployment..."
echo "Resource Group: $resourceGroupName"
echo "Location: $saLocation"
echo "Count: $saCount"
echo ""
# Create resource group if it doesn't exist
if ! az group show --name $resourceGroupName &> /dev/null; then
echo "Creating resource group $resourceGroupName..."
az group create --name $resourceGroupName --location $saLocation
else
echo "Resource group $resourceGroupName already exists."
fi
# Loop to create multiple storage accounts
for i in $(seq 1 $saCount)
do
# Generate unique identifier using timestamp and random number
timestamp=$(date +%s)
let "randomIdentifier=$RANDOM"
saName="${saNamePrefix}${timestamp}${randomIdentifier}"
# Ensure name is lowercase and within 24 character limit
saName=$(echo $saName | tr '[:upper:]' '[:lower:]' | cut -c1-24)
echo "Creating storage account $saName..."
# Create storage account with error handling
if az storage account create \
--name $saName \
--resource-group $resourceGroupName \
--location $saLocation \
--sku $saSku \
--kind $saKind \
--tags Environment=Production ManagedBy=AzureCLI \
--output none; then
echo "✓ Successfully created storage account $saName"
else
echo "✗ Failed to create storage account $saName"
fi
done
echo ""
echo "Deployment complete. Verifying results..."
echo ""
# Verify results with formatted output
az storage account list \
--resource-group $resourceGroupName \
--query "[].{Name:name, Location:location, SKU:sku.name, Status:statusOfPrimary}" \
--output table
Répartition des scripts
Examinons les composants clés :
Validation de l’authentification :
if ! az account show &> /dev/null; then
echo "Error: Not authenticated to Azure. Please run 'az login' first."
exit 1
fi
Garantit que l’utilisateur est authentifié avant d’exécuter des opérations de ressources, ce qui empêche les échecs de script.
Création du groupe de ressources avec vérification de l'existence :
if ! az group show --name $resourceGroupName &> /dev/null; then
az group create --name $resourceGroupName --location $saLocation
fi
Crée le groupe de ressources uniquement s’il n’existe pas déjà, ce qui rend le script idempotent.
Génération de nom unique :
timestamp=$(date +%s)
let "randomIdentifier=$RANDOM"
saName="${saNamePrefix}${timestamp}${randomIdentifier}"
saName=$(echo $saName | tr '[:upper:]' '[:lower:]' | cut -c1-24)
Combine l’horodatage et le nombre aléatoire pour générer des noms de compte de stockage uniques, les convertir en minuscules et les limiter à 24 caractères conformément aux règles de nommage Azure.
Gestion des erreurs :
if az storage account create ...; then
echo "✓ Successfully created storage account $saName"
else
echo "✗ Failed to create storage account $saName"
fi
Valide chaque création de compte de stockage et fournit des commentaires clairs sur la réussite/l’échec.
Créer un script paramétrable
Les scripts de production doivent accepter des paramètres pour la flexibilité entre les environnements :
#!/bin/bash
# Script: create-storage-accounts.sh
# Usage: ./create-storage-accounts.sh <resource-group> <location> <count> <environment>
# Accept command-line parameters
resourceGroupName=$1
saLocation=$2
saCount=$3
environment=$4
# Validate parameters
if [ -z "$resourceGroupName" ] || [ -z "$saLocation" ] || [ -z "$saCount" ] || [ -z "$environment" ]; then
echo "Usage: $0 <resource-group> <location> <count> <environment>"
echo "Example: $0 rg-storage-dev eastus 3 Development"
exit 1
fi
# Validate count is a number
if ! [[ "$saCount" =~ ^[0-9]+$ ]]; then
echo "Error: Count must be a number"
exit 1
fi
echo "Parameters received:"
echo " Resource Group: $resourceGroupName"
echo " Location: $saLocation"
echo " Count: $saCount"
echo " Environment: $environment"
echo ""
# Set environment-specific configurations
case $environment in
Development)
saSku="Standard_LRS"
saKind="StorageV2"
;;
Staging)
saSku="Standard_GRS"
saKind="StorageV2"
;;
Production)
saSku="Standard_RAGRS"
saKind="StorageV2"
;;
*)
echo "Error: Environment must be Development, Staging, or Production"
exit 1
;;
esac
echo "Using SKU: $saSku for $environment environment"
echo ""
# Continue with resource creation...
Exécuter le script paramétrable
# Make script executable
chmod +x create-storage-accounts.sh
# Execute with parameters
./create-storage-accounts.sh rg-storage-dev eastus 3 Development
Créer un script piloté par la configuration
Pour les déploiements complexes, utilisez des fichiers de configuration externes :
config.json:
{
"resourceGroup": {
"name": "rg-app-prod-eastus",
"location": "eastus"
},
"storageAccounts": [
{
"namePrefix": "stappdata",
"sku": "Standard_RAGRS",
"kind": "StorageV2",
"count": 2
},
{
"namePrefix": "stappbackup",
"sku": "Standard_GRS",
"kind": "StorageV2",
"count": 1
}
],
"tags": {
"Environment": "Production",
"CostCenter": "Engineering",
"ManagedBy": "AzureCLI"
}
}
deploy-from-config.sh :
#!/bin/bash
# Load configuration file
configFile="config.json"
if [ ! -f "$configFile" ]; then
echo "Error: Configuration file $configFile not found"
exit 1
fi
# Parse configuration using jq (JSON processor)
resourceGroupName=$(jq -r '.resourceGroup.name' $configFile)
resourceGroupLocation=$(jq -r '.resourceGroup.location' $configFile)
tagsJson=$(jq -r '.tags | to_entries | map("\(.key)=\(.value)") | join(" ")' $configFile)
echo "Deploying resources from configuration file..."
echo "Resource Group: $resourceGroupName"
echo "Location: $resourceGroupLocation"
echo ""
# Create resource group
az group create --name $resourceGroupName --location $resourceGroupLocation
# Read storage account configurations
storageConfigCount=$(jq '.storageAccounts | length' $configFile)
for i in $(seq 0 $(($storageConfigCount - 1)))
do
namePrefix=$(jq -r ".storageAccounts[$i].namePrefix" $configFile)
sku=$(jq -r ".storageAccounts[$i].sku" $configFile)
kind=$(jq -r ".storageAccounts[$i].kind" $configFile)
count=$(jq -r ".storageAccounts[$i].count" $configFile)
echo "Creating $count storage account(s) with prefix: $namePrefix"
for j in $(seq 1 $count)
do
timestamp=$(date +%s)
saName="${namePrefix}${timestamp}${RANDOM}"
saName=$(echo $saName | tr '[:upper:]' '[:lower:]' | cut -c1-24)
az storage account create \
--name $saName \
--resource-group $resourceGroupName \
--location $resourceGroupLocation \
--sku $sku \
--kind $kind \
--tags $tagsJson \
--output none
echo " ✓ Created: $saName"
done
done
echo ""
echo "Deployment complete."
Avantages pilotés par la configuration
- Séparation des préoccupations : Configuration distincte de la logique de déploiement.
- Promotion de l’environnement : Même script avec différents fichiers de configuration pour le développement, la préproduction, la production.
- Contrôle de version : Suivez les modifications de configuration en même temps que le code.
- Validation: Validez la structure de configuration avant le déploiement.
Supprimer des ressources Azure avec des scripts
Lors de la création et du test de scripts, n’oubliez pas de supprimer les ressources de test pour éviter les coûts inutiles. L'utilisation de scripts avec Azure CLI permet de nettoyer les ressources de manière sécurisée et cohérente.
Supprimer des comptes de stockage par date de création
Supprimez tous les comptes de stockage créés à ou après une date et une heure spécifiques :
#!/bin/bash
# Define cleanup parameters
cutoffDate="2025-10-08T00:00:00.000000+00:00"
resourceGroup="rg-storage-dev-eastus"
echo "Finding storage accounts created on or after $cutoffDate..."
# Get list of storage accounts matching criteria
saList=$(az storage account list \
--resource-group $resourceGroup \
--query "[?creationTime >='$cutoffDate'].{Name:name, Created:creationTime}" \
--output table)
echo "$saList"
echo ""
# Confirm deletion
read -p "Delete these storage accounts? (yes/no): " confirm
if [ "$confirm" == "yes" ]; then
for saId in $(az storage account list \
--resource-group $resourceGroup \
--query "[?creationTime >='$cutoffDate'].id" \
--output tsv); do
echo "Deleting storage account: $saId"
az storage account delete --ids $saId --yes
done
echo "Cleanup complete."
else
echo "Deletion cancelled."
fi
Supprimer des groupes de ressources avec la fonctionnalité de journalisation
Supprimez des groupes de ressources correspondant à un modèle d’affectation de noms avec une journalisation complète :
#!/bin/bash
# Define cleanup parameters
namePattern="rg-dev-*"
logFileLocation="cleanup-$(date +%Y%m%d-%H%M%S).log"
echo "Resource Group Cleanup" > $logFileLocation
echo "Started: $(date)" >> $logFileLocation
echo "Pattern: $namePattern" >> $logFileLocation
echo "----------------------------------------" >> $logFileLocation
# Find matching resource groups
echo "Finding resource groups matching pattern: $namePattern"
matchingGroups=$(az group list \
--query "[?starts_with(name, 'rg-dev-')].name" \
--output tsv)
if [ -z "$matchingGroups" ]; then
echo "No resource groups found matching pattern: $namePattern"
echo "No resource groups found" >> $logFileLocation
exit 0
fi
# Display matches
echo "Found resource groups:"
echo "$matchingGroups"
echo ""
# Log matches
echo "Resource groups found:" >> $logFileLocation
echo "$matchingGroups" >> $logFileLocation
echo "" >> $logFileLocation
# Confirm deletion
read -p "Delete these resource groups? (yes/no): " confirm
if [ "$confirm" == "yes" ]; then
echo "Starting deletion..." >> $logFileLocation
for rgName in $matchingGroups
do
echo "Deleting resource group: $rgName"
echo "$(date): Deleting $rgName" >> $logFileLocation
# Delete with --no-wait for background execution
if az group delete --name $rgName --yes --no-wait; then
echo " ✓ Deletion initiated for $rgName"
echo "$(date): ✓ Deletion initiated for $rgName" >> $logFileLocation
else
echo " ✗ Failed to initiate deletion for $rgName"
echo "$(date): ✗ Failed to delete $rgName" >> $logFileLocation
fi
done
echo ""
echo "Deletion operations initiated. Resources will be removed in the background."
echo "Check deletion status with: az group list --query \"[?starts_with(name, 'rg-dev-')].name\""
echo "" >> $logFileLocation
echo "Completed: $(date)" >> $logFileLocation
echo "Log saved to: $logFileLocation"
# Display log
echo ""
echo "=== Cleanup Log ==="
cat $logFileLocation
else
echo "Deletion cancelled by user" >> $logFileLocation
echo "Deletion cancelled."
fi
Pratiques de suppression sécurisée
Implémentez des vérifications de sécurité avant la suppression :
#!/bin/bash
# Delete resources safely with multiple confirmations
resourceGroup="rg-storage-test-eastus"
# Check if resource group exists
if ! az group show --name $resourceGroup &> /dev/null; then
echo "Error: Resource group '$resourceGroup' not found"
exit 1
fi
# Display resources that will be deleted
echo "Resources in resource group '$resourceGroup':"
az resource list --resource-group $resourceGroup \
--query "[].{Name:name, Type:type, Location:location}" \
--output table
echo ""
echo "⚠️ WARNING: This will delete ALL resources in '$resourceGroup'"
echo ""
# First confirmation
read -p "Are you sure you want to delete '$resourceGroup'? (yes/no): " confirm1
if [ "$confirm1" != "yes" ]; then
echo "Deletion cancelled."
exit 0
fi
# Second confirmation with exact name
read -p "Type the resource group name to confirm: " confirm2
if [ "$confirm2" != "$resourceGroup" ]; then
echo "Resource group name does not match. Deletion cancelled."
exit 1
fi
# Final countdown
echo "Deleting in 5 seconds. Press Ctrl+C to cancel."
sleep 5
echo "Deleting resource group '$resourceGroup'..."
az group delete --name $resourceGroup --yes
echo "Resource group deleted successfully."
Avertissement
Vérifiez toujours les ressources avant la suppression. La suppression d’un groupe de ressources supprime définitivement toutes les ressources qu’elle contient. Cette opération est irréversible.
Meilleures pratiques pour les scripts de production
Les scripts Azure CLI prêts pour la production nécessitent une planification et une implémentation minutieuses. Les scripts fournis dans cette unité illustrent des concepts fondamentaux, mais les environnements de production exigent des considérations supplémentaires.
Composants de script de production essentiels
Un script Azure CLI robuste pour les environnements de production doit inclure :
1. Authentification et autorisation :
#!/bin/bash
# Authenticate with service principal (for automation)
if [ -n "$AZURE_CLIENT_ID" ] && [ -n "$AZURE_CLIENT_SECRET" ] && [ -n "$AZURE_TENANT_ID" ]; then
echo "Authenticating with service principal..."
az login --service-principal \
--username $AZURE_CLIENT_ID \
--password $AZURE_CLIENT_SECRET \
--tenant $AZURE_TENANT_ID
else
echo "Error: Service principal credentials not found"
exit 1
fi
# Set subscription
az account set --subscription $AZURE_SUBSCRIPTION_ID
# Verify authentication
if ! az account show &> /dev/null; then
echo "Error: Authentication failed"
exit 1
fi
2. Gestion complète des erreurs :
#!/bin/bash
# Exit immediately if command fails
set -e
# Trap errors and perform cleanup
trap 'cleanup_on_error' ERR
cleanup_on_error() {
echo "Error occurred on line $1"
echo "Performing cleanup..."
# Add cleanup logic here
exit 1
}
# Enable error trapping with line numbers
trap 'cleanup_on_error $LINENO' ERR
3. Vérifications de l’Idempotency :
#!/bin/bash
# Check if resource group exists before creation
create_resource_group() {
local rgName=$1
local location=$2
if az group show --name $rgName &> /dev/null; then
echo "Resource group $rgName already exists. Skipping creation."
else
echo "Creating resource group $rgName..."
az group create --name $rgName --location $location
fi
}
# Check if storage account exists
create_storage_account() {
local saName=$1
local rgName=$2
if az storage account show --name $saName --resource-group $rgName &> /dev/null; then
echo "Storage account $saName already exists. Skipping creation."
return 0
else
echo "Creating storage account $saName..."
az storage account create --name $saName --resource-group $rgName --location eastus
fi
}
4. Journalisation structurée :
#!/bin/bash
# Define log file with timestamp
logFile="deployment-$(date +%Y%m%d-%H%M%S).log"
errorLog="errors-$(date +%Y%m%d-%H%M%S).log"
# Logging function
log() {
local level=$1
shift
local message="$@"
local timestamp=$(date "+%Y-%m-%d %H:%M:%S")
echo "[$timestamp] [$level] $message" | tee -a $logFile
if [ "$level" == "ERROR" ]; then
echo "[$timestamp] $message" >> $errorLog
fi
}
# Usage
log "INFO" "Starting deployment..."
log "ERROR" "Failed to create resource"
log "SUCCESS" "Deployment complete"
5. Validation de la configuration :
#!/bin/bash
# Validate required configuration
validate_config() {
local errors=0
if [ -z "$RESOURCE_GROUP" ]; then
echo "Error: RESOURCE_GROUP not defined"
((errors++))
fi
if [ -z "$LOCATION" ]; then
echo "Error: LOCATION not defined"
((errors++))
fi
# Validate location exists
if ! az account list-locations --query "[?name=='$LOCATION']" | grep -q "$LOCATION"; then
echo "Error: Invalid location: $LOCATION"
((errors++))
fi
if [ $errors -gt 0 ]; then
echo "Configuration validation failed with $errors error(s)"
exit 1
fi
echo "Configuration validation passed"
}
6. Stratégie d’étiquetage :
#!/bin/bash
# Define standard tags
environment=$1 # Development, Staging, Production
costCenter=$2
owner=$3
# Create tags string
tags="Environment=$environment CostCenter=$costCenter Owner=$owner \
CreatedBy=AzureCLI CreatedDate=$(date +%Y-%m-%d) \
ManagedBy=Infrastructure-Team Project=WebApp"
# Apply tags to resources
az group create \
--name $resourceGroup \
--location $location \
--tags $tags
az storage account create \
--name $saName \
--resource-group $resourceGroup \
--location $location \
--tags $tags
7. Fonctionnalité de restauration :
#!/bin/bash
# Track created resources for rollback
createdResources=()
create_with_tracking() {
local resourceType=$1
local resourceName=$2
# Attempt resource creation
if create_resource "$resourceType" "$resourceName"; then
createdResources+=("$resourceType:$resourceName")
echo "✓ Created: $resourceType - $resourceName"
return 0
else
echo "✗ Failed: $resourceType - $resourceName"
return 1
fi
}
rollback() {
echo "Rolling back created resources..."
for resource in "${createdResources[@]}"; do
IFS=':' read -r type name <<< "$resource"
echo "Deleting $type: $name"
delete_resource "$type" "$name"
done
echo "Rollback complete"
}
# Use trap to rollback on error
trap rollback ERR
Structure de l’organisation de script
Organisez des scripts en modules logiques :
azure-infrastructure/
├── config/
│ ├── dev.json
│ ├── staging.json
│ └── prod.json
├── scripts/
│ ├── deploy-infrastructure.sh
│ ├── deploy-storage.sh
│ └── cleanup.sh
├── lib/
│ ├── common-functions.sh
│ ├── logging.sh
│ └── validation.sh
├── logs/
└── README.md
Bibliothèque de fonctions réutilisables
common-functions.sh :
#!/bin/bash
# Load this file in other scripts: source ./lib/common-functions.sh
# Check if Azure CLI is installed
check_azure_cli() {
if ! command -v az &> /dev/null; then
echo "Error: Azure CLI not installed"
exit 1
fi
}
# Wait for resource to be ready
wait_for_resource() {
local resourceId=$1
local maxAttempts=30
local attempt=1
echo "Waiting for resource to be ready..."
while [ $attempt -le $maxAttempts ]; do
if az resource show --ids $resourceId &> /dev/null; then
echo "Resource is ready"
return 0
fi
echo "Attempt $attempt/$maxAttempts - waiting..."
sleep 10
((attempt++))
done
echo "Timeout waiting for resource"
return 1
}
# Generate unique name
generate_unique_name() {
local prefix=$1
local timestamp=$(date +%s)
local random=$RANDOM
echo "${prefix}${timestamp}${random}" | tr '[:upper:]' '[:lower:]' | cut -c1-24
}
Tester des scripts en toute sécurité
Tester des scripts dans des environnements isolés :
#!/bin/bash
# Test mode flag
TEST_MODE=${TEST_MODE:-false}
execute_command() {
local command=$1
if [ "$TEST_MODE" == "true" ]; then
echo "[TEST MODE] Would execute: $command"
else
echo "Executing: $command"
eval $command
fi
}
# Usage
execute_command "az group create --name rg-test --location eastus"
Exécutez en mode test :
TEST_MODE=true ./deploy-infrastructure.sh
Ressources supplémentaires
- Référentiel d’exemples Azure CLI :github.com/Azure-Samples/azure-cli-samples.
- Guide de script Azure CLI :learn.microsoft.com/cli/azure/azure-cli-vm-tutorial.
Bonnes pratiques de script Bash : www.gnu.org/software/bash/manual/ .
Les scripts de cette unité illustrent les fonctionnalités d’Azure CLI lors de la combinaison de variables, de boucles, de conditions et de gestion des erreurs avec des commandes Azure CLI . Ces modèles s’étendent de la gestion de quelques ressources à l’orchestration de déploiements d’infrastructure d’entreprise complexes.