Skip to content

Commit 8fcae81

Browse files
committed
make use of nginx cli extension for config updates
1 parent 8465b1d commit 8fcae81

File tree

2 files changed

+214
-60
lines changed

2 files changed

+214
-60
lines changed

action.yml

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,19 @@ inputs:
2424
default: "nginx.conf"
2525
transformed-nginx-config-directory-path:
2626
description: >
27-
'The transformed absolute path of the NGINX configuration directory in NGINXaaS for Azure deployment, example: "/etc/nginx/".
28-
If the "include" directive in the NGINX configuration files uses absolute paths, the path transformation
29-
can be used to overwrite the file paths when the action synchronizes the files to the NGINXaaS for Azure deployment.'
27+
'The absolute directory path in the NGINXaaS for Azure deployment where your configuration files will be placed.
28+
All files found in the nginx-config-directory-path will be copied to this location in the deployment.
29+
For example, use "/etc/nginx/" to match the standard NGINX directory structure on Azure.
30+
If your NGINX configuration files use absolute paths in "include" directives, this setting ensures those paths are correctly mapped in the deployment by prepending the specified directory.'
3031
required: false
3132
default: ""
3233
nginx-certificates:
3334
description: 'An array of JSON objects each with keys nginx_cert_name, keyvault_secret, certificate_virtual_path and key_virtual_path. Example: [{"certificateName": "server1", "keyvaultSecret": "https://...", "certificateVirtualPath": "/etc/ssl/certs/server1.crt", "keyVirtualPath": "/etc/ssl/certs/server1.key" }, {"name": "server2", "keyvaultSecret": "https://...", "certificateVirtualPath": "/etc/ssl/certs/server2.crt", "keyVirtualPath": "/etc/ssl/certs/server2.key" }] '
3435
required: false
36+
protected-files:
37+
description: "Comma-separated list of file paths relative to nginx-config-directory-path that should be marked as protected. Example: 'ssl/private.key,conf.d/secrets.conf'"
38+
required: false
39+
default: ""
3540
debug:
3641
description: "Enable/Disable debug output."
3742
required: false
@@ -40,10 +45,10 @@ runs:
4045
using: "composite"
4146
steps:
4247
- name: "Synchronize NGINX certificate(s) from the Git repository to an NGINXaaS for Azure deployment"
43-
run: ${{github.action_path}}/src/deploy-certificate.sh --subscription_id=${{ inputs.subscription-id }} --resource_group_name=${{ inputs.resource-group-name }} --nginx_deployment_name=${{ inputs.nginx-deployment-name }} --nginx_resource_location=${{ inputs.nginx-deployment-location }} --certificates=${{ toJSON(inputs.nginx-certificates) }} --debug=${{ inputs.debug }}
48+
run: ${{github.action_path}}/src/deploy-certificate.sh --subscription-id=${{ inputs.subscription-id }} --resource-group-name=${{ inputs.resource-group-name }} --nginx-deployment-name=${{ inputs.nginx-deployment-name }} --nginx-resource-location=${{ inputs.nginx-deployment-location }} --certificates=${{ toJSON(inputs.nginx-certificates) }} --debug=${{ inputs.debug }}
4449
if: ${{ inputs.nginx-deployment-location != '' && inputs.nginx-certificates != '' }}
4550
shell: bash
4651
- name: "Synchronize NGINX configuration from the Git repository to an NGINXaaS for Azure deployment"
47-
run: ${{github.action_path}}/src/deploy-config.sh --subscription_id=${{ inputs.subscription-id }} --resource_group_name=${{ inputs.resource-group-name }} --nginx_deployment_name=${{ inputs.nginx-deployment-name }} --config_dir_path=${{ inputs.nginx-config-directory-path }} --root_config_file=${{ inputs.nginx-root-config-file }} --transformed_config_dir_path=${{ inputs.transformed-nginx-config-directory-path }} --debug=${{ inputs.debug }}
52+
run: ${{github.action_path}}/src/deploy-config.sh --subscription-id=${{ inputs.subscription-id }} --resource-group-name=${{ inputs.resource-group-name }} --nginx-deployment-name=${{ inputs.nginx-deployment-name }} --nginx-config-directory-path=${{ inputs.nginx-config-directory-path }} --nginx-root-config-file=${{ inputs.nginx-root-config-file }} --transformed-nginx-config-directory-path=${{ inputs.transformed-nginx-config-directory-path }} --protected-files=${{ inputs.protected-files }} --debug=${{ inputs.debug }}
4853
if: ${{ inputs.nginx-config-directory-path != '' }}
4954
shell: bash

src/deploy-config.sh

Lines changed: 204 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,72 @@
11
#!/bin/bash
2-
set -euo pipefail
2+
set -eo pipefail
33
IFS=$'\n\t'
44

55
transformed_config_dir_path=''
66
for i in "$@"
77
do
88
case $i in
9-
--subscription_id=*)
9+
--subscription-id=*)
1010
subscription_id="${i#*=}"
1111
shift
1212
;;
13-
--resource_group_name=*)
13+
--resource-group-name=*)
1414
resource_group_name="${i#*=}"
1515
shift
1616
;;
17-
--nginx_deployment_name=*)
17+
--nginx-deployment-name=*)
1818
nginx_deployment_name="${i#*=}"
1919
shift
2020
;;
21-
--config_dir_path=*)
21+
--nginx-config-directory-path=*)
2222
config_dir_path="${i#*=}"
2323
shift
2424
;;
25-
--root_config_file=*)
25+
--nginx-root-config-file=*)
2626
root_config_file="${i#*=}"
2727
shift
2828
;;
29-
--transformed_config_dir_path=*)
29+
--transformed-nginx-config-directory-path=*)
3030
transformed_config_dir_path="${i#*=}"
3131
shift
3232
;;
3333
--debug=*)
3434
debug="${i#*=}"
3535
shift
3636
;;
37+
--protected-files=*)
38+
protected_files="${i#*=}"
39+
shift
40+
;;
3741
*)
38-
echo "Not matched option '${i#*=}' passed in."
42+
echo "Unknown option '${i}' passed in."
3943
exit 1
4044
;;
4145
esac
4246
done
4347

44-
if [[ ! -v subscription_id ]];
45-
then
46-
echo "Please set 'subscription-id' ..."
47-
exit 1
48+
# Validate Required Parameters
49+
missing_params=()
50+
if [ -z "$subscription_id" ]; then
51+
missing_params+=("subscription-id")
4852
fi
49-
if [[ ! -v resource_group_name ]];
50-
then
51-
echo "Please set 'resource-group-name' ..."
52-
exit 1
53+
if [ -z "$resource_group_name" ]; then
54+
missing_params+=("resource-group-name")
5355
fi
54-
if [[ ! -v nginx_deployment_name ]];
55-
then
56-
echo "Please set 'nginx-deployment-name' ..."
57-
exit 1
56+
if [ -z "$nginx_deployment_name" ]; then
57+
missing_params+=("nginx-deployment-name")
5858
fi
59-
if [[ ! -v config_dir_path ]];
60-
then
61-
echo "Please set 'nginx-config-directory-path' ..."
62-
exit 1
59+
if [ -z "$config_dir_path" ]; then
60+
missing_params+=("nginx-config-directory-path")
6361
fi
64-
if [[ ! -v root_config_file ]];
65-
then
66-
echo "Please set 'nginx-root-config-file' ..."
62+
if [ -z "$root_config_file" ]; then
63+
missing_params+=("nginx-root-config-file")
64+
fi
65+
66+
# Check and print if any required params are missing
67+
if [ ${#missing_params[@]} -gt 0 ]; then
68+
echo "Error: Missing required variables in the workflow:"
69+
echo "${missing_params[*]}"
6770
exit 1
6871
fi
6972

@@ -121,60 +124,206 @@ fi
121124
transformed_root_config_file_path="$transformed_config_dir_path$root_config_file"
122125
echo "The transformed root NGINX configuration file path is '$transformed_root_config_file_path'."
123126

124-
# Create a NGINX configuration tarball.
127+
# Common utility functions
128+
129+
# Function to trim whitespace from a string
130+
trim_whitespace() {
131+
local var="$1"
132+
# Trim leading whitespace from the file path (var)
133+
# ${var%%[![:space:]]*} starts at the file path's end
134+
# and finds the longest match of non-whitespace
135+
# characters leaving only leading whitespaces
136+
# ${var#"..." } removes the leading whitespace found
137+
var="${var#"${var%%[![:space:]]*}"}"
138+
# Remove trailing whitespace
139+
# See explanation above. The process is reversed here.
140+
var="${var%"${var##*[![:space:]]}"}"
141+
# Check if the file exists in the repository
142+
echo "$var"
143+
}
144+
145+
# Function to encode file content to base64
146+
encode_file_base64() {
147+
local file_path="$1"
148+
# Use base64 to encode the file content
149+
# -w 0 option is used to avoid line wrapping in the output
150+
base64 -w 0 "$file_path"
151+
}
125152

126-
config_tarball="nginx-config.tar.gz"
153+
# Function to build virtual path from relative path
154+
build_virtual_path() {
155+
local relative_path="$1"
156+
echo "${transformed_config_dir_path}${relative_path}"
157+
}
127158

128-
echo "Creating a tarball from the NGINX configuration directory."
129-
tar -cvzf "$config_tarball" -C "$config_dir_path" --xform s:'./':"$transformed_config_dir_path": .
130-
echo "Successfully created the tarball from the NGINX configuration directory."
159+
# Function to add a file entry to a JSON array
160+
# The add_file_to_json_array function uses indirect variable references
161+
# and global assignment to update JSON arrays and flags that track
162+
# which files have been processed. The variable names for the JSON array
163+
# and the "first file" flag are passed as arguments, allowing the
164+
# function to generically update different arrays
165+
# (for regular and protected files) without hardcoding their names.
166+
# The syntax ${!var} retrieves the value of the variable whose
167+
# name is stored in 'var', and declare -g ensures the updated
168+
# values are set globally, so changes persist outside the function.
169+
add_file_to_json_array() {
170+
local file_path="$1"
171+
local virtual_path="$2"
172+
local file_type="$3" # "regular" or "protected"
173+
local json_var_name="$4" # Variable name to modify
174+
local first_file_var_name="$5" # Variable name for first_file flag
175+
176+
if [ -f "$file_path" ]; then
177+
echo "Processing $file_type file: $file_path -> $virtual_path"
178+
179+
# Base64 encode the file content
180+
local file_content_b64
181+
file_content_b64=$(encode_file_base64 "$file_path")
182+
183+
# Get current values using indirect variable references
184+
local current_json="${!json_var_name}"
185+
local is_first_file="${!first_file_var_name}"
186+
187+
# Add comma separator if not the first file
188+
if [ "$is_first_file" = false ]; then
189+
current_json+=","
190+
fi
191+
192+
# Add the file entry to JSON array
193+
current_json+="{\"content\":\"$file_content_b64\",\"virtual-path\":\"$virtual_path\"}"
194+
195+
# Update the variables using indirect assignment
196+
declare -g "$json_var_name=$current_json"
197+
declare -g "$first_file_var_name=false"
198+
199+
if [[ "$debug" == true ]]; then
200+
echo "$file_type file virtual path: $virtual_path"
201+
echo "$file_type file content (base64): ${file_content_b64:0:50}..."
202+
fi
203+
else
204+
echo "Warning: $file_type file '$file_path' not found"
205+
fi
206+
}
207+
208+
# Process protected files first to build exclusion list
209+
protected_files_list=()
210+
if [ -n "$protected_files" ]; then
211+
IFS=',' read -ra files <<< "$protected_files"
212+
213+
for file in "${files[@]}"; do
214+
file=$(trim_whitespace "$file")
215+
if [ -n "$file" ]; then
216+
protected_files_list+=("$file")
217+
fi
218+
done
219+
fi
220+
221+
# Function to check if a file is in the protected files list
222+
is_protected_file() {
223+
local relative_path="$1"
224+
for protected_file in "${protected_files_list[@]}"; do
225+
if [ "$relative_path" = "$protected_file" ]; then
226+
return 0 # File is protected
227+
fi
228+
done
229+
return 1 # File is not protected
230+
}
131231

132-
echo "Listing the NGINX configuration file paths in the tarball."
133-
tar -tf "$config_tarball"
232+
# Process all configuration files individually (excluding protected files)
233+
234+
echo "Processing NGINX configuration files individually."
235+
236+
# Build the files JSON array
237+
files_json="["
238+
files_first_file=true
239+
240+
# Find all files in the config directory and process them (excluding protected files)
241+
while IFS= read -r -d '' file; do
242+
# Get relative path from config directory
243+
relative_path="${file#$config_dir_path}"
244+
245+
# Skip if this file is in the protected files list
246+
if is_protected_file "$relative_path"; then
247+
echo "Skipping protected file from regular files: $relative_path"
248+
continue
249+
fi
250+
251+
# Apply transformation to get virtual path
252+
virtual_path=$(build_virtual_path "$relative_path")
253+
254+
add_file_to_json_array "$file" "$virtual_path" "regular" "files_json" "files_first_file"
255+
done < <(find "$config_dir_path" -type f -print0)
134256

135-
encoded_config_tarball=$(base64 "$config_tarball")
257+
files_json+="]"
136258

137259
if [[ "$debug" == true ]]; then
138-
echo "The base64 encoded NGINX configuration tarball"
139-
echo "$encoded_config_tarball"
260+
echo "Regular files JSON: $files_json"
140261
fi
141-
echo ""
142262

143-
# Synchronize the NGINX configuration tarball to the NGINXaaS for Azure deployment.
263+
# Process protected files if specified
264+
protected_files_arg=""
265+
if [ -n "$protected_files" ]; then
266+
echo "Processing protected files: $protected_files"
267+
268+
# Build the protected files JSON array
269+
protected_files_json="["
270+
protected_first_file=true
271+
IFS=',' read -ra files <<< "$protected_files"
272+
273+
for file in "${files[@]}"; do
274+
file=$(trim_whitespace "$file")
275+
if [ -n "$file" ]; then
276+
repo_file_path="${config_dir_path}${file}"
277+
virtual_path=$(build_virtual_path "$file")
278+
279+
add_file_to_json_array "$repo_file_path" "$virtual_path" "protected" "protected_files_json" "protected_first_file"
280+
fi
281+
done
282+
283+
protected_files_json+="]"
284+
285+
if [ "$protected_first_file" = false ]; then
286+
protected_files_arg="--protected-files"
287+
if [[ "$debug" == true ]]; then
288+
echo "Protected files JSON: $protected_files_json"
289+
fi
290+
fi
291+
fi
144292

145-
uuid="$(cat /proc/sys/kernel/random/uuid)"
146-
template_file="template-$uuid.json"
147-
template_deployment_name="${nginx_deployment_name:0:20}-$uuid"
148293

149-
wget -O "$template_file" https://raw.githubusercontent.com/nginxinc/nginx-for-azure-deploy-action/487d1394d6115d4f42ece6200cbd20859595557d/src/nginx-for-azure-configuration-template.json
150-
echo "Downloaded the ARM template for synchronizing NGINX configuration."
151-
cat "$template_file"
152-
echo ""
294+
# Synchronize the NGINX configuration files to the NGINXaaS for Azure deployment.
153295

154296
echo "Synchronizing NGINX configuration"
155297
echo "Subscription ID: $subscription_id"
156298
echo "Resource group name: $resource_group_name"
157299
echo "NGINXaaS for Azure deployment name: $nginx_deployment_name"
158-
echo "ARM template deployment name: $template_deployment_name"
159300
echo ""
160301

161302
az account set -s "$subscription_id" --verbose
162303

304+
echo "Installing the az nginx extension if not already installed."
305+
az extension add --name nginx --allow-preview true
306+
163307
az_cmd=(
164308
"az"
309+
"nginx"
165310
"deployment"
166-
"group"
167-
"create"
168-
"--name" "$template_deployment_name"
311+
"configuration"
312+
"update"
313+
"--name" "default"
314+
"--deployment-name" "$nginx_deployment_name"
169315
"--resource-group" "$resource_group_name"
170-
"--template-file" "$template_file"
171-
"--parameters"
172-
"nginxDeploymentName=$nginx_deployment_name"
173-
"rootFile=$transformed_root_config_file_path"
174-
"tarball=$encoded_config_tarball"
316+
"--root-file" "$transformed_root_config_file_path"
317+
"--files" "$files_json"
175318
"--verbose"
176319
)
177320

321+
# Add protected files argument if present
322+
if [ -n "$protected_files_arg" ]; then
323+
az_cmd+=("$protected_files_arg")
324+
az_cmd+=("$protected_files_json")
325+
fi
326+
178327
if [[ "$debug" == true ]]; then
179328
az_cmd+=("--debug")
180329
echo "${az_cmd[@]}"

0 commit comments

Comments
 (0)