Merge "[AAI] Add model-loader tracing config"
[oom.git] / kubernetes / common / mongodb / templates / replicaset / scripts-configmap.yaml
1 {{- /*
2 Copyright VMware, Inc.
3 SPDX-License-Identifier: APACHE-2.0
4 */}}
5
6 {{- if eq .Values.architecture "replicaset" }}
7 apiVersion: v1
8 kind: ConfigMap
9 metadata:
10   name: {{ printf "%s-scripts" (include "mongodb.fullname" .) }}
11   namespace: {{ include "mongodb.namespace" . | quote }}
12   labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
13     app.kubernetes.io/component: mongodb
14   {{- if .Values.commonAnnotations }}
15   annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
16   {{- end }}
17 data:
18   {{- $fullname := include "mongodb.fullname" . }}
19   {{- $releaseNamespace := include "mongodb.namespace" . }}
20   {{- if and .Values.externalAccess.autoDiscovery.enabled (eq .Values.externalAccess.service.type "LoadBalancer") }}
21   auto-discovery.sh: |-
22     #!/bin/bash
23
24     SVC_NAME="${MY_POD_NAME}-external"
25
26     # Auxiliary functions
27     retry_while() {
28         local -r cmd="${1:?cmd is missing}"
29         local -r retries="${2:-12}"
30         local -r sleep_time="${3:-5}"
31         local return_value=1
32
33         read -r -a command <<< "$cmd"
34         for ((i = 1 ; i <= retries ; i+=1 )); do
35             "${command[@]}" && return_value=0 && break
36             sleep "$sleep_time"
37         done
38         return $return_value
39     }
40     k8s_svc_lb_ip() {
41         local namespace=${1:?namespace is missing}
42         local service=${2:?service is missing}
43         local service_ip=$(kubectl get svc "$service" -n "$namespace" -o jsonpath="{.status.loadBalancer.ingress[0].ip}")
44         local service_hostname=$(kubectl get svc "$service" -n "$namespace" -o jsonpath="{.status.loadBalancer.ingress[0].hostname}")
45
46         if [[ -n ${service_ip} ]]; then
47             echo "${service_ip}"
48         else
49             echo "${service_hostname}"
50         fi
51     }
52     k8s_svc_lb_ip_ready() {
53         local namespace=${1:?namespace is missing}
54         local service=${2:?service is missing}
55         [[ -n "$(k8s_svc_lb_ip "$namespace" "$service")" ]]
56     }
57     # Wait until LoadBalancer IP is ready
58     retry_while "k8s_svc_lb_ip_ready {{ $releaseNamespace }} $SVC_NAME" || exit 1
59     # Obtain LoadBalancer external IP
60     k8s_svc_lb_ip "{{ $releaseNamespace }}" "$SVC_NAME" | tee "$SHARED_FILE"
61   {{- end }}
62   setup.sh: |-
63     #!/bin/bash
64
65     . /opt/bitnami/scripts/mongodb-env.sh
66     . /opt/bitnami/scripts/libfs.sh
67     . /opt/bitnami/scripts/liblog.sh
68     . /opt/bitnami/scripts/libvalidations.sh
69
70     {{- if .Values.externalAccess.enabled }}
71     {{- if eq .Values.externalAccess.service.type "LoadBalancer" }}
72     {{- if .Values.externalAccess.autoDiscovery.enabled }}
73     export MONGODB_ADVERTISED_HOSTNAME="$(<${SHARED_FILE})"
74     {{- else }}
75     ID="${MY_POD_NAME#"{{ $fullname }}-"}"
76     export MONGODB_ADVERTISED_HOSTNAME=$(echo '{{ .Values.externalAccess.service.loadBalancerIPs }}' | tr -d '[]' | cut -d ' ' -f "$(($ID + 1))")
77     {{- end }}
78     {{- else if eq .Values.externalAccess.service.type "NodePort" }}
79     ID="${MY_POD_NAME#"{{ $fullname }}-"}"
80     if is_empty_value "$MONGODB_ADVERTISED_PORT_NUMBER"; then
81       export MONGODB_ADVERTISED_PORT_NUMBER=$(echo '{{ .Values.externalAccess.service.nodePorts }}' | tr -d '[]' | cut -d ' ' -f "$(($ID + 1))")
82     fi
83     {{- if .Values.externalAccess.service.domain }}
84     export MONGODB_ADVERTISED_HOSTNAME={{ .Values.externalAccess.service.domain }}
85     {{- else }}
86     export MONGODB_ADVERTISED_HOSTNAME=$MY_POD_HOST_IP
87     {{- end }}
88     {{- end }}
89     {{- end }}
90
91     {{- if .Values.replicaSetConfigurationSettings.enabled }}
92     # placed here before root password env is overwritten
93     # makes no assumption about starting state
94     # ensures that any stepDown or non-default starting state is handled
95     /scripts/replicaSetConfigurationSettings.sh &
96     {{- end }}
97
98     if is_empty_value "$MONGODB_ADVERTISED_PORT_NUMBER"; then
99       export MONGODB_ADVERTISED_PORT_NUMBER="$MONGODB_PORT_NUMBER"
100     fi
101
102     info "Advertised Hostname: $MONGODB_ADVERTISED_HOSTNAME"
103     info "Advertised Port: $MONGODB_ADVERTISED_PORT_NUMBER"
104
105     # Check for existing replica set in case there is no data in the PVC
106     # This is for cases where the PVC is lost or for MongoDB caches without
107     # persistence
108     current_primary=""
109     if is_dir_empty "${MONGODB_DATA_DIR}/db"; then
110       info "Data dir empty, checking if the replica set already exists"
111       {{- $replicaCount := int .Values.replicaCount }}
112       {{- $portNumber := int .Values.service.ports.mongodb }}
113       {{- $fullname := include "mongodb.fullname" . }}
114       {{- $releaseNamespace := include "mongodb.namespace" . }}
115       {{- $clusterDomain := .Values.clusterDomain }}
116       {{- $loadBalancerIPListLength := len .Values.externalAccess.service.loadBalancerIPs }}
117       {{- $mongoList := list }}
118       {{- range $e, $i := until $replicaCount }}
119       {{- $mongoList = append $mongoList (printf "%s-%d.%s-headless.%s.svc.%s:%d" $fullname $i $fullname $releaseNamespace $clusterDomain $portNumber) }}
120       {{- end }}
121
122       {{- if .Values.externalAccess.externalMaster.enabled }}
123         current_primary={{ printf "%s:%d" (.Values.externalAccess.externalMaster.host) ( int .Values.externalAccess.externalMaster.port) }}
124       {{- else }}
125         current_primary=$(mongosh admin --host "{{ join "," $mongoList }}" {{- if .Values.auth.enabled }} --authenticationDatabase admin -u $MONGODB_ROOT_USER -p $MONGODB_ROOT_PASSWORD{{- end }}{{- if .Values.tls.enabled}} --tls {{ if .Values.tls.mTLS.enabled }}--tlsCertificateKeyFile=/certs/mongodb.pem {{ end }}--tlsCAFile=/certs/mongodb-ca-cert{{- end }} --eval 'db.runCommand("ismaster")' | awk -F\' '/primary/ {print $2}')
126       {{- end }}
127       if ! is_empty_value "$current_primary"; then
128         info "Detected existing primary: ${current_primary}"
129       fi
130     fi
131
132     if ! is_empty_value "$current_primary" && [[ "$MONGODB_ADVERTISED_HOSTNAME:$MONGODB_ADVERTISED_PORT_NUMBER" == "$current_primary" ]]; then
133         info "Advertised name matches current primary, configuring node as a primary"
134         export MONGODB_REPLICA_SET_MODE="primary"
135     elif ! is_empty_value "$current_primary" && [[ "$MONGODB_ADVERTISED_HOSTNAME:$MONGODB_ADVERTISED_PORT_NUMBER" != "$current_primary" ]]; then
136         info "Current primary is different from this node. Configuring the node as replica of ${current_primary}"
137         export MONGODB_REPLICA_SET_MODE="secondary"
138         export MONGODB_INITIAL_PRIMARY_HOST="${current_primary%:*}"
139         export MONGODB_INITIAL_PRIMARY_PORT_NUMBER="${current_primary#*:}"
140         export MONGODB_SET_SECONDARY_OK="yes"
141     elif [[ "$MY_POD_NAME" = "{{ $fullname }}-0" ]]; then
142         info "Pod name matches initial primary pod name, configuring node as a primary"
143         export MONGODB_REPLICA_SET_MODE="primary"
144     else
145         info "Pod name doesn't match initial primary pod name, configuring node as a secondary"
146         export MONGODB_REPLICA_SET_MODE="secondary"
147         export MONGODB_INITIAL_PRIMARY_PORT_NUMBER="$MONGODB_PORT_NUMBER"
148     fi
149
150     if [[ "$MONGODB_REPLICA_SET_MODE" == "secondary" ]]; then
151         export MONGODB_INITIAL_PRIMARY_ROOT_USER="$MONGODB_ROOT_USER"
152         export MONGODB_INITIAL_PRIMARY_ROOT_PASSWORD="$MONGODB_ROOT_PASSWORD"
153         export MONGODB_ROOT_PASSWORD=""
154         export MONGODB_EXTRA_USERNAMES=""
155         export MONGODB_EXTRA_DATABASES=""
156         export MONGODB_EXTRA_PASSWORDS=""
157         export MONGODB_ROOT_PASSWORD_FILE=""
158         export MONGODB_EXTRA_USERNAMES_FILE=""
159         export MONGODB_EXTRA_DATABASES_FILE=""
160         export MONGODB_EXTRA_PASSWORDS_FILE=""
161     fi
162
163     exec /opt/bitnami/scripts/mongodb/entrypoint.sh /opt/bitnami/scripts/mongodb/run.sh
164   setup-hidden.sh: |-
165     #!/bin/bash
166
167     . /opt/bitnami/scripts/mongodb-env.sh
168
169     {{- if .Values.externalAccess.hidden.enabled }}
170     {{- if eq .Values.externalAccess.hidden.service.type "LoadBalancer" }}
171     {{- if .Values.externalAccess.autoDiscovery.enabled }}
172     export MONGODB_ADVERTISED_HOSTNAME="$(<${SHARED_FILE})"
173     {{- else }}
174     ID="${MY_POD_NAME#"{{ $fullname }}-hidden-"}"
175     export MONGODB_ADVERTISED_HOSTNAME=$(echo '{{ .Values.externalAccess.hidden.service.loadBalancerIPs }}' | tr -d '[]' | cut -d ' ' -f "$(($ID + 1))")
176     {{- end }}
177     {{- else if eq .Values.externalAccess.hidden.service.type "NodePort" }}
178     ID="${MY_POD_NAME#"{{ $fullname }}-hidden-"}"
179     if is_empty_value "$MONGODB_ADVERTISED_PORT_NUMBER"; then
180       export MONGODB_ADVERTISED_PORT_NUMBER=$(echo '{{ .Values.externalAccess.service.nodePorts }}' | tr -d '[]' | cut -d ' ' -f "$(($ID + 1))")
181     fi
182     {{- if .Values.externalAccess.hidden.service.domain }}
183     export MONGODB_ADVERTISED_HOSTNAME={{ .Values.externalAccess.hidden.service.domain }}
184     {{- else }}
185     export MONGODB_ADVERTISED_HOSTNAME=$MY_POD_HOST_IP
186     {{- end }}
187     {{- end }}
188     {{- end }}
189
190     {{- if .Values.replicaSetConfigurationSettings.enabled }}
191     # placed here before root password env is overwritten
192     # makes no assumption about starting state
193     # ensures that any stepDown or non-default starting state is handled
194     /scripts/replicaSetConfigurationSettings.sh &
195     {{- end }}
196
197     echo "Advertised Hostname: $MONGODB_ADVERTISED_HOSTNAME"
198     echo "Advertised Port: $MONGODB_ADVERTISED_PORT_NUMBER"
199     echo "Configuring node as a hidden node"
200     export MONGODB_REPLICA_SET_MODE="hidden"
201     export MONGODB_INITIAL_PRIMARY_ROOT_USER="$MONGODB_ROOT_USER"
202     export MONGODB_INITIAL_PRIMARY_ROOT_PASSWORD="$MONGODB_ROOT_PASSWORD"
203     export MONGODB_INITIAL_PRIMARY_PORT_NUMBER="$MONGODB_PORT_NUMBER"
204     export MONGODB_ROOT_PASSWORD=""
205     export MONGODB_EXTRA_USERNAMES=""
206     export MONGODB_EXTRA_DATABASES=""
207     export MONGODB_EXTRA_PASSWORDS=""
208     export MONGODB_ROOT_PASSWORD_FILE=""
209     export MONGODB_EXTRA_USERNAMES_FILE=""
210     export MONGODB_EXTRA_DATABASES_FILE=""
211     export MONGODB_EXTRA_PASSWORDS_FILE=""
212     exec /opt/bitnami/scripts/mongodb/entrypoint.sh /opt/bitnami/scripts/mongodb/run.sh
213   {{- if .Values.replicaSetConfigurationSettings.enabled }}
214   replicaSetConfigurationSettings.sh: |-
215     #!/bin/bash
216     # This script to be called when pod starts.
217     # This script sets rs settings which can not be applied via conf file
218
219     function logger ()
220     #$1 is the line to be logged
221     {
222       echo "replicaSetConfigurationSettings.sh -- ${1}" >&1
223     }
224
225     SLEEP_PERIOD=10
226
227     {{- if and .Values.auth.enabled .Values.auth.rootPassword }}
228     usernameAndPassword="{{- if .Values.tls.enabled}} --tls {{ if .Values.tls.mTLS.enabled }}--tlsCertificateKeyFile=/certs/mongodb.pem {{ end }}--tlsCAFile=/certs/mongodb-ca-cert{{- end }} -u ${MONGODB_ROOT_USER} -p ${MONGODB_ROOT_PASSWORD}"
229     {{- else }}
230     usernameAndPassword=""
231     {{- end }}
232
233     # load Values.replicaSetConfigurationSettings.configuration into associtive array which makes iterating and string manipulation easy
234     declare -A desiredRsConf
235     {{ range $setting, $value := .Values.replicaSetConfigurationSettings.configuration -}}
236     {{ printf "desiredRsConf[%s]='%v'" $setting $value }}
237     {{ end }}
238
239     rsConfWriteAttempts=0
240     rs_conf_configured_ok=unknown
241
242     while [[ "${rs_conf_configured_ok}" != "true" ]]; do
243
244       # give the rs setup a chance to succeed before attempting to read or configure
245       sleep ${SLEEP_PERIOD}
246
247       counter=0
248       while ! mongosh ${usernameAndPassword} --eval 'rs.conf()'; do
249         counter=$((${counter} +1))
250         logger "not yet able to read rs.conf settings from the currently running rs (after ${counter} attempts)"
251         sleep ${SLEEP_PERIOD}
252       done
253       counter=$((${counter} +1))
254       logger "rs.conf settings have been read from the currently running rs (after ${counter} attempts)"
255
256       # read rs.conf again and store it. settings format is '"<key>" : <value>,'
257       currentRsConf=$(mongosh ${usernameAndPassword} --eval 'rs.conf()')
258
259       desiredEqualsactual=unknown
260       settingsToConfigure=""
261       for key in ${!desiredRsConf[@]}; do
262         value=${desiredRsConf[$key]}
263         if ! $(echo "\"${currentRsConf}"\" | grep -q -e "${key}: ${value},"); then
264            if [[ $key =~ ^members\[[0-9]+\]\..+ ]]; then
265             memberIndex=$(echo $key | grep -o -E '[0-9]+')
266             nodeConfigKey=${key#*.}
267             settingsToConfigure="${settingsToConfigure}cfg.members[${memberIndex}].${nodeConfigKey} = ${value}; "
268           else
269             # General rs settings
270             settingsToConfigure="${settingsToConfigure}cfg.settings.${key} = ${value}; "
271           fi
272            desiredEqualsactual=false
273         else
274           logger "rs conf: ${key} is already at desired value: ${value}"
275         fi
276       done
277
278       if [[ "${desiredEqualsactual}" != "false" ]]; then
279         logger "replicaSetConfigurationSettings match the settings of the currently running rs"
280         desiredEqualsactual=true
281         rs_conf_configured_ok=true
282         logger "Current settings match desired settings (There have been ${rsConfWriteAttempts} attempts to write to mongoDB rs configuration)"
283         exit
284       fi
285
286       # apply the settings only if this member is currently the mongo replicaset PRIMARY
287       # it might take a little time before any pod is PRIMARY
288       isMaster=unknown
289       if ! mongosh ${usernameAndPassword} --eval 'rs.isMaster()' | grep -q "ismaster: true"; then
290         isMaster=false
291         logger "This node is not yet PRIMARY - replicaSetConfigurationSettings will only be set on the member that is currently PRIMARY"
292       else
293         isMaster=true
294         logger "This node is PRIMARY"
295       fi
296
297       if [[ "${isMaster}" == "true" ]]; then
298         logger "This node is currently PRIMARY - will apply rs.conf settings"
299
300         # avoiding tricky string substitution with single quotes by making the eval string a set of vars
301         rsconf="cfg = rs.conf();"
302         rsreconf="rs.reconfig(cfg);"
303         rsCommand="${rsconf} ${settingsToConfigure} ${rsreconf}"
304
305         mongosh ${usernameAndPassword} --eval "${rsCommand}"
306         if [ $? -ne 0 ]; then
307           logger "Failed to apply mongodb cfg.settings configuration"
308         else
309           logger "mongodb replicaset cfg.settings configuration applied"
310           logger "Will check rs conf"
311           # don't exit just yet - the settings will be checked in the next loop
312         fi
313         rsConfWriteAttempts=$((${rsConfWriteAttempts} + 1 ))
314       fi
315     done
316   {{- end }}
317 {{- end }}