Setting the file. One moment.
Validate Deployment · Azure Validate · microsoft/azure-skills · Skills Docs
ContentsBack to the top of the page 28.8
Errors · azd
(opens in a new tab)
references/recipes/scripts/ validate-deployment.sh
Shell · 184 lines · 6 KB
# ./validate-deployment.sh --scope sub --location <location> [options]
16 # ./validate-deployment.sh --scope group --resource-group <rg-name> [options]
17 #
18 # Options:
19 # --scope <sub|group> Deployment scope (required)
20 # --location <location> Location (required when --scope sub)
21 # --resource-group <name> Resource group (required when --scope group)
22 # --template <path> Bicep template (default: ./infra/main.bicep)
23 # --parameters <path> Parameters file (default: ./infra/main.parameters.json;
24 # skipped automatically if the file does not exist)
25 # --subscription <id> Subscription to target (optional)
26 #
27 # Examples:
28 # ./validate-deployment.sh --scope sub --location eastus
29 # ./validate-deployment.sh --scope group --resource-group my-rg \
30 # --template ./infra/main.bicep --parameters ./infra/main.parameters.json
31 #
32 # Exit codes:
33 # 0 - every validation step passed
34 # 1 - a validation step failed
35 # 2 - usage / argument error (unknown or valueless option, missing required flag)
36
37 set -uo pipefail
38
39 # Ensure an option that consumes a value actually has one ($@ = remaining args).
40 need_val () {
41 [ " $# " -ge 2 ] || { echo "ERROR: $1 requires a value." >&2 ; exit 2 ; }
42 }
43
44 SCOPE = ""
45 LOCATION = ""
46 RESOURCE_GROUP = ""
47 TEMPLATE = "./infra/main.bicep"
48 PARAMETERS = "./infra/main.parameters.json"
49 SUBSCRIPTION = ""
50
51 while [ $# -gt 0 ]; do
52 case " $1 " in
53 --scope ) need_val " $@ " ; SCOPE = " $2 " ; shift 2 ;;
54 --location ) need_val " $@ " ; LOCATION = " $2 " ; shift 2 ;;
55 --resource-group ) need_val " $@ " ; RESOURCE_GROUP = " $2 " ; shift 2 ;;
56 --template ) need_val " $@ " ; TEMPLATE = " $2 " ; shift 2 ;;
57 --parameters ) need_val " $@ " ; PARAMETERS = " $2 " ; shift 2 ;;
58 --subscription ) need_val " $@ " ; SUBSCRIPTION = " $2 " ; shift 2 ;;
59 -h | --help )
60 grep '^#' " $0 " | grep -v '^#!' | sed 's/^# \{0,1\}//'
61 exit 0 ;;
62 *)
63 echo "Unknown argument: $1 " >&2
64 exit 2 ;;
65 esac
66 done
67
68 # Validate arguments
69 if [ " $SCOPE " != "sub" ] && [ " $SCOPE " != "group" ]; then
70 echo "ERROR: --scope must be 'sub' or 'group'." >&2
71 exit 2
72 fi
73 if [ " $SCOPE " = "sub" ] && [ -z " $LOCATION " ]; then
74 echo "ERROR: --location is required when --scope is 'sub'." >&2
75 exit 2
76 fi
77 if [ " $SCOPE " = "group" ] && [ -z " $RESOURCE_GROUP " ]; then
78 echo "ERROR: --resource-group is required when --scope is 'group'." >&2
79 exit 2
80 fi
81
82 # Build shared argument arrays
83 SUB_ARGS = ()
84 [ -n " $SUBSCRIPTION " ] && SUB_ARGS = ( --subscription " $SUBSCRIPTION " )
85
86 PARAM_ARGS = ()
87 if [ -f " $PARAMETERS " ]; then
88 PARAM_ARGS = ( --parameters " $PARAMETERS " )
89 else
90 echo "NOTE: parameters file ' $PARAMETERS ' not found; validating without --parameters."
91 fi
92
93 if [ " $SCOPE " = "sub" ]; then
94 SCOPE_TARGET_ARGS = ( --location " $LOCATION " )
95 SCOPE_DESC = "subscription (location: $LOCATION )"
96 else
97 SCOPE_TARGET_ARGS = ( --resource-group " $RESOURCE_GROUP " )
98 SCOPE_DESC = "resource group ' $RESOURCE_GROUP '"
99 fi
100
101 # Track overall result (0 = all passed, 1 = at least one failure).
102 OVERALL = 0
103
104 echo "=== Azure deployment validation ==="
105 echo "Template: $TEMPLATE "
106 echo "Scope: $SCOPE_DESC "
107 echo ""
108
109 # Step 1: Azure CLI installed
110 echo "--- Step 1: Azure CLI installed (az version) ---"
111 if az version > /dev/null 2>&1 ; then
112 echo "PASS: Azure CLI is installed."
113 else
114 echo "FAIL: Azure CLI not found. Install it, then re-run."
115 # Nothing else can run without the CLI.
116 echo ""
117 echo "OVERALL: FAIL"
118 exit 1
119 fi
120 echo ""
121
122 # Step 2: Authenticated
123 echo "--- Step 2: Authenticated (az account show) ---"
124 if ACCOUNT_NAME = $( az account show "${ SUB_ARGS [ @ ]}" --query name -o tsv 2> /dev/null ); then
125 echo "PASS: Authenticated (subscription: ${ ACCOUNT_NAME :- unknown })."
126 else
127 echo "FAIL: Not logged in. Run 'az login' (and 'az account set --subscription <id>')."
128 OVERALL = 1
129 fi
130 echo ""
131
132 # Step 3: Bicep compilation
133 echo "--- Step 3: Bicep compilation (az bicep build) ---"
134 BUILD_OUTPUT = $( az bicep build --file " $TEMPLATE " 2>&1 )
135 BUILD_RC = $?
136 if [ $BUILD_RC -eq 0 ]; then
137 echo "PASS: Template compiles cleanly."
138 else
139 echo "FAIL: Bicep compilation errors:"
140 echo " $BUILD_OUTPUT "
141 OVERALL = 1
142 fi
143 echo ""
144
145 # Step 4: Template validation
146 echo "--- Step 4: Template validation (az deployment $SCOPE validate) ---"
147 VALIDATE_OUTPUT = $( az deployment " $SCOPE " validate "${ SCOPE_TARGET_ARGS [ @ ]}" \
148 --template-file " $TEMPLATE " \
149 "${ PARAM_ARGS [ @ ]}" "${ SUB_ARGS [ @ ]}" 2>&1 )
150 VALIDATE_RC = $?
151 if [ $VALIDATE_RC -eq 0 ]; then
152 echo "PASS: Template validated against the target scope."
153 else
154 echo "FAIL: Template validation errors:"
155 echo " $VALIDATE_OUTPUT "
156 OVERALL = 1
157 fi
158 echo ""
159
160 # Step 5: What-if preview
161 echo "--- Step 5: What-if preview (az deployment $SCOPE what-if) ---"
162 WHATIF_OUTPUT = $( az deployment " $SCOPE " what-if "${ SCOPE_TARGET_ARGS [ @ ]}" \
163 --template-file " $TEMPLATE " \
164 "${ PARAM_ARGS [ @ ]}" "${ SUB_ARGS [ @ ]}" 2>&1 )
165 WHATIF_RC = $?
166 if [ $WHATIF_RC -eq 0 ]; then
167 CREATE_COUNT = $( echo " $WHATIF_OUTPUT " | grep -c '^[[:space:]]*+ ' )
168 MODIFY_COUNT = $( echo " $WHATIF_OUTPUT " | grep -c '^[[:space:]]*~ ' )
169 DELETE_COUNT = $( echo " $WHATIF_OUTPUT " | grep -c '^[[:space:]]*- ' )
170 echo "PASS: What-if completed. Changes -> Create: $CREATE_COUNT , Modify: $MODIFY_COUNT , Delete: $DELETE_COUNT "
171 else
172 echo "FAIL: What-if errors:"
173 echo " $WHATIF_OUTPUT "
174 OVERALL = 1
175 fi
176 echo ""
177
178 # Overall result
179 if [ $OVERALL -eq 0 ]; then
180 echo "OVERALL: PASS"
181 else
182 echo "OVERALL: FAIL"
183 fi
184 exit $OVERALL