nginx-conf-flatten 4.59 KB
Newer Older
Michał Woźniak's avatar
Michał Woźniak committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/bash

#
# flatten an nginx config
# 
# replaces all occurences of the `include` directive
# with the relevant included files
#
# assumptions:
# - include file paths do not contain spaces
#   (this seems compatible with how nginx handles includes)
# - no files are included from above the directory where the nginx config file
#   being processed resides in

Michał Woźniak's avatar
Michał Woźniak committed
15
16
17
18
function debug {
    echo "$@" >&2
}

Michał Woźniak's avatar
Michał Woźniak committed
19
20
21
22
23
24
25
ORIG_CWD="$PWD"

#
# TODO: reality checks
#

NGINX_CONFIG="$( realpath -eL "$1" )"
Michał Woźniak's avatar
Michał Woźniak committed
26
debug "+-- config file: '$NGINX_CONFIG'"
Michał Woźniak's avatar
Michał Woźniak committed
27
28

NGINX_CONFIG_DIR="$( dirname "$NGINX_CONFIG" )"
Michał Woźniak's avatar
Michał Woźniak committed
29
debug "    config directory: 'NGINX_CONFIG_DIR'"
Michał Woźniak's avatar
Michał Woźniak committed
30
31
32
33

cd "$NGINX_CONFIG_DIR"

TMP_WORKDIR="$( mktemp -d /tmp/nginx-conf-flatten.XXXX )"
Michał Woźniak's avatar
Michał Woźniak committed
34
debug "+-- TMP_WORKDIR: $TMP_WORKDIR"
Michał Woźniak's avatar
Michał Woźniak committed
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61

# the list of files whose includes we have not copied yet
NGINX_CONFIG_ELEMENTS=("$NGINX_CONFIG")

# 
# extract the include paths from an nginx config file
# 
# $1 - the file to work with
function nginx-extract-includes {
    # assumption: include path does not contain spaces
    egrep '^\s*include ' "$1" | sed -r -e "s/^\s*include\s*([^;]+).*$/\1/"
}

# 
# handle all includes of a file to the temporary workdir
# creating the directory structure in the process
# and adding them to the NGINX_CONFIG_FILES variable
# for further processing
# 
# $1 - the file to work with
function nginx-handle-includes {
    # get the included files
    # this will loop through actual globbed filenames
    # 
    # assumption: no files are included from directories above the directory
    # the main config file resides in
    for i in $( nginx-extract-includes "$1" ); do
Michał Woźniak's avatar
Michał Woźniak committed
62
        debug -n "        +-- found include: $i"
Michał Woźniak's avatar
Michał Woźniak committed
63
64
        # if the temporary copy of the file does not exist
        if [ ! -e "$TMP_WORKDIR/$i" ]; then
Michał Woźniak's avatar
Michał Woźniak committed
65
            debug " - copying!"
Michał Woźniak's avatar
Michał Woźniak committed
66
67
68
69
70
71
72
            # create the directory structure
            mkdir -p "$TMP_WORKDIR/$( dirname "$i" )"
            # copy the file
            cp "$NGINX_CONFIG_DIR/$i" "$TMP_WORKDIR/$i"
            # add to the list of files to proces
            NGINX_CONFIG_ELEMENTS+=("$i")
        else
Michał Woźniak's avatar
Michał Woźniak committed
73
            debug " - already copied."
Michał Woźniak's avatar
Michał Woźniak committed
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
        fi
    done
}


function nginx-clean-directory {
    # let's get the file in a temporary location
    # (we don't want to screw up the original!)
    cp "$NGINX_CONFIG" "$TMP_WORKDIR"/

    # go one by one over the NGINX_CONFIG_ELEMENTS array
    # but from the end
    while [[ ${#NGINX_CONFIG_ELEMENTS[@]} > 0 ]]; do
        CUR_INDEX=$(( ${#NGINX_CONFIG_ELEMENTS[@]} - 1 ))
        CUR_ELEMENT=${NGINX_CONFIG_ELEMENTS[$CUR_INDEX]}
Michał Woźniak's avatar
Michał Woźniak committed
89
90
        debug "    +-- working with index: $CUR_INDEX"
        debug "        $CUR_ELEMENT"
Michał Woźniak's avatar
Michał Woźniak committed
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
        unset "NGINX_CONFIG_ELEMENTS[$CUR_INDEX]"
        nginx-handle-includes "$CUR_ELEMENT";
    done
    # TODO: finish
}

# let's get the file in a temporary location
# (we don't want to screw up the original!)
cp "$NGINX_CONFIG" "$TMP_WORKDIR"/
NGINX_CONFIG_COPY="$TMP_WORKDIR/$( basename "$NGINX_CONFIG")"

OLDIFS="$IFS"
IFS=$'\n'
while CURRENT_INCLUDES="$( egrep -n '^\s*include\s*.+;.*$' "$NGINX_CONFIG_COPY" )"; do
    PREVIOUS_CI_LINE=0;
    for ci in $CURRENT_INCLUDES; do
        # get the actual file glob
        CI_FILE_GLOB="$( echo "$ci" | sed -r -e "s/^[0-9]+\:\s*include\s*([^;]+).*$/\1/" )"
        CI_LINE="$( echo "$ci" | cut -d ':' -f 1 )"
        DATE_EXT="$( date +%s%N )"
Michał Woźniak's avatar
Michał Woźniak committed
111
112
        #debug "    +-- previous line : $PREVIOUS_CI_LINE"
        #debug "        ci line       : $CI_LINE"
Michał Woźniak's avatar
Michał Woźniak committed
113
114
115
116
117
118
        tail -n "+$(( $PREVIOUS_CI_LINE + 1 ))" "$NGINX_CONFIG_COPY" | head -n $(( $CI_LINE - 1 - $PREVIOUS_CI_LINE )) > "$NGINX_CONFIG_COPY.$DATE_EXT"
        echo -e "\n############################################################\n### $ci \n############################################################" >> "$NGINX_CONFIG_COPY.$DATE_EXT"
        cat $CI_FILE_GLOB >> "$NGINX_CONFIG_COPY.$DATE_EXT"
        echo -e "\n############################################################\n### end $ci \n############################################################" >> "$NGINX_CONFIG_COPY.$DATE_EXT"
        PREVIOUS_CI_LINE="$CI_LINE"
    done
Michał Woźniak's avatar
Michał Woźniak committed
119
    #debug "pre-cat waiting..."
Michał Woźniak's avatar
Michał Woźniak committed
120
121
122
    #read
    cat $NGINX_CONFIG_COPY.* > "$NGINX_CONFIG_COPY"
    rm $NGINX_CONFIG_COPY.*
Michał Woźniak's avatar
Michał Woźniak committed
123
    #debug "post-rm waiting..."
Michał Woźniak's avatar
Michał Woźniak committed
124
125
126
127
128
129
130
131
132
    #read
done
IFS="$OLDIFS"

# get back to the original directory we've been running from
cd "$ORIG_CWD"

# check how we need to output the thing
if [ "$2" != "" ]; then
Michał Woźniak's avatar
Michał Woźniak committed
133
134
135
    debug "+-- moving the temporary output file to the output destination"
    debug "    src: $NGINX_CONFIG_COPY"
    debug "    dst: $2"
Michał Woźniak's avatar
Michał Woźniak committed
136
    mv "$NGINX_CONFIG_COPY" "$( basename $2 )"
Michał Woźniak's avatar
Michał Woźniak committed
137
    debug "+-- cleaning up the temporary output directory"
Michał Woźniak's avatar
Michał Woźniak committed
138
139
    rm -rf "$TMP_WORKDIR"
fi