blob: c8789bf816132bc2c2f7a783af23886c53cf0fad [file] [log] [blame]
Sean Daguee263c822014-12-05 14:25:28 -05001#!/bin/bash
2#
Dean Troyerbf2ad702015-03-09 15:16:10 -05003# **lib/meta-config** - Configuration file manipulation functions
4#
5# Support for DevStack's local.conf meta-config sections
6#
Dean Troyer893e6632013-09-13 15:05:51 -05007# These functions have no external dependencies and the following side-effects:
8#
9# CONFIG_AWK_CMD is defined, default is ``awk``
10
11# Meta-config files contain multiple INI-style configuration files
12# using a specific new section header to delimit them:
13#
14# [[group-name|file-name]]
15#
16# group-name refers to the group of configuration file changes to be processed
Sean Dague537d4022013-10-22 07:43:22 -040017# at a particular time. These are called phases in ``stack.sh`` but
Dean Troyer893e6632013-09-13 15:05:51 -050018# group here as these functions are not DevStack-specific.
19#
20# file-name is the destination of the config file
21
22# Save trace setting
Dean Troyerbf2ad702015-03-09 15:16:10 -050023INC_META_XTRACE=$(set +o | grep xtrace)
Dean Troyer893e6632013-09-13 15:05:51 -050024set +o xtrace
25
26
27# Allow the awk command to be overridden on legacy platforms
28CONFIG_AWK_CMD=${CONFIG_AWK_CMD:-awk}
29
30# Get the section for the specific group and config file
31# get_meta_section infile group configfile
Ian Wienandaee18c72014-02-21 15:35:08 +110032function get_meta_section {
Dean Troyer893e6632013-09-13 15:05:51 -050033 local file=$1
34 local matchgroup=$2
35 local configfile=$3
36
37 [[ -r $file ]] || return 0
38 [[ -z $configfile ]] && return 0
39
40 $CONFIG_AWK_CMD -v matchgroup=$matchgroup -v configfile=$configfile '
41 BEGIN { group = "" }
Isaku Yamahatabff00142013-12-20 11:55:08 +090042 /^\[\[.+\|.*\]\]/ {
Dean Troyer893e6632013-09-13 15:05:51 -050043 if (group == "") {
44 gsub("[][]", "", $1);
45 split($1, a, "|");
46 if (a[1] == matchgroup && a[2] == configfile) {
47 group=a[1]
48 }
49 } else {
50 group=""
51 }
52 next
53 }
54 {
55 if (group != "")
56 print $0
57 }
58 ' $file
59}
60
61
62# Get a list of config files for a specific group
63# get_meta_section_files infile group
Ian Wienandaee18c72014-02-21 15:35:08 +110064function get_meta_section_files {
Dean Troyer893e6632013-09-13 15:05:51 -050065 local file=$1
66 local matchgroup=$2
67
68 [[ -r $file ]] || return 0
69
70 $CONFIG_AWK_CMD -v matchgroup=$matchgroup '
Sean Dague537d4022013-10-22 07:43:22 -040071 /^\[\[.+\|.*\]\]/ {
72 gsub("[][]", "", $1);
73 split($1, a, "|");
74 if (a[1] == matchgroup)
75 print a[2]
76 }
Dean Troyer893e6632013-09-13 15:05:51 -050077 ' $file
78}
79
80
81# Merge the contents of a meta-config file into its destination config file
82# If configfile does not exist it will be created.
83# merge_config_file infile group configfile
Ian Wienandaee18c72014-02-21 15:35:08 +110084function merge_config_file {
Dean Troyer893e6632013-09-13 15:05:51 -050085 local file=$1
86 local matchgroup=$2
87 local configfile=$3
88
Dean Troyer893e6632013-09-13 15:05:51 -050089 get_meta_section $file $matchgroup $configfile | \
90 $CONFIG_AWK_CMD -v configfile=$configfile '
Robert Li751ad1a2014-10-15 21:40:53 -040091 BEGIN {
92 section = ""
93 last_section = ""
94 section_count = 0
95 }
Dean Troyer893e6632013-09-13 15:05:51 -050096 /^\[.+\]/ {
97 gsub("[][]", "", $1);
98 section=$1
99 next
100 }
101 /^ *\#/ {
102 next
103 }
Dean Troyer2ac8b3f2013-12-04 17:20:28 -0600104 /^[^ \t]+/ {
Fergal Mc Carthycc87c282014-10-09 16:16:42 -0400105 # get offset of first '=' in $0
106 eq_idx = index($0, "=")
107 # extract attr & value from $0
108 attr = substr($0, 1, eq_idx - 1)
109 value = substr($0, eq_idx + 1)
110 # only need to strip trailing whitespace from attr
111 sub(/[ \t]*$/, "", attr)
112 # need to strip leading & trailing whitespace from value
113 sub(/^[ \t]*/, "", value)
114 sub(/[ \t]*$/, "", value)
Robert Li751ad1a2014-10-15 21:40:53 -0400115
116 # cfg_attr_count: number of config lines per [section, attr]
117 # cfg_attr: three dimensional array to keep all the config lines per [section, attr]
118 # cfg_section: keep the section names in the same order as they appear in local.conf
119 # cfg_sec_attr_name: keep the attr names in the same order as they appear in local.conf
120 if (! (section, attr) in cfg_attr_count) {
121 if (section != last_section) {
122 cfg_section[section_count++] = section
123 last_section = section
124 }
125 attr_count = cfg_sec_attr_count[section_count - 1]++
126 cfg_sec_attr_name[section_count - 1, attr_count] = attr
127
128 cfg_attr[section, attr, 0] = value
129 cfg_attr_count[section, attr] = 1
130 } else {
131 lno = cfg_attr_count[section, attr]++
132 cfg_attr[section, attr, lno] = value
133 }
134 }
135 END {
136 # Process each section in order
137 for (sno = 0; sno < section_count; sno++) {
138 section = cfg_section[sno]
139 # The ini routines simply append a config item immediately
140 # after the section header. To keep the same order as defined
141 # in local.conf, invoke the ini routines in the reverse order
142 for (attr_no = cfg_sec_attr_count[sno] - 1; attr_no >=0; attr_no--) {
143 attr = cfg_sec_attr_name[sno, attr_no]
144 if (cfg_attr_count[section, attr] == 1)
Ian Wienandf3bf8b62014-10-29 21:53:56 +1100145 print "iniset " configfile " " section " " attr " \"" cfg_attr[section, attr, 0] "\""
Robert Li751ad1a2014-10-15 21:40:53 -0400146 else {
147 # For multiline, invoke the ini routines in the reverse order
148 count = cfg_attr_count[section, attr]
Doug Wiegley1f65fd62014-12-13 11:56:16 -0700149 print "inidelete " configfile " " section " " attr
Ian Wienandf3bf8b62014-10-29 21:53:56 +1100150 print "iniset " configfile " " section " " attr " \"" cfg_attr[section, attr, count - 1] "\""
Robert Li751ad1a2014-10-15 21:40:53 -0400151 for (l = count -2; l >= 0; l--)
Ian Wienandf3bf8b62014-10-29 21:53:56 +1100152 print "iniadd_literal " configfile " " section " " attr " \"" cfg_attr[section, attr, l] "\""
Robert Li751ad1a2014-10-15 21:40:53 -0400153 }
154 }
155 }
Dean Troyer893e6632013-09-13 15:05:51 -0500156 }
157 ' | while read a; do eval "$a"; done
Dean Troyer893e6632013-09-13 15:05:51 -0500158}
159
160
161# Merge all of the files specified by group
162# merge_config_group infile group [group ...]
Ian Wienandaee18c72014-02-21 15:35:08 +1100163function merge_config_group {
Dean Troyer893e6632013-09-13 15:05:51 -0500164 local localfile=$1; shift
165 local matchgroups=$@
166
167 [[ -r $localfile ]] || return 0
168
Dean Troyerb1e3d0f2014-07-25 14:57:54 -0500169 local configfile group
Dean Troyer893e6632013-09-13 15:05:51 -0500170 for group in $matchgroups; do
171 for configfile in $(get_meta_section_files $localfile $group); do
Ryota MIBU410f5c02014-04-04 02:00:31 +0900172 if [[ -d $(dirname $(eval "echo $configfile")) ]]; then
Dean Troyer893e6632013-09-13 15:05:51 -0500173 merge_config_file $localfile $group $configfile
174 fi
175 done
176 done
177}
178
179
180# Restore xtrace
Dean Troyerbf2ad702015-03-09 15:16:10 -0500181$INC_META_XTRACE
Dean Troyer893e6632013-09-13 15:05:51 -0500182
183# Local variables:
184# mode: shell-script
185# End: