Popular New Releases in UUID Generator
No Popular Releases are available at this moment for UUID Generator
Popular Libraries in UUID Generator
by furkankahvecii php
3
Pure PHP UUID generator
by sanikapanika java
2
Generate uuids by just typing uuid to terminal
Trending New libraries in UUID Generator
by furkankahvecii php
3
Pure PHP UUID generator
by sanikapanika java
2
Generate uuids by just typing uuid to terminal
Top Authors in UUID Generator
1
1 Libraries
2
2
1 Libraries
3
1
1 Libraries
2
2
1 Libraries
3
Trending Kits in UUID Generator
No Trending Kits are available at this moment for UUID Generator
Trending Discussions on UUID Generator
MySQL + Kubernetes statefulset with defined env variables
How to convert a UUID to a number with less than 40 digits?
Save Variable from a Pre-request script to use in a new Request
YAML/YQ - remove sections that have sub-sections containing a particular attribute match
How can I reference an array when I don't know the name of it?
React Context API context API issues , when adding and removing an items from UI
BLE: How to get correct service UUID and characteristic UUID?
Syntax to manually insert a UUID value in Postgres
QUESTION
MySQL + Kubernetes statefulset with defined env variables
Asked 2022-Mar-08 at 14:56I'm following Kubernetes's MySQL as a StatefulSet from here. What the tutorial did not cover is how do I specify other environmental variables, like MYSQL_ROOT_PASSWORD
, MYSQL_USER
and such. I tried doing it myself, but didn't work. Here's the code:
1apiVersion: apps/v1
2kind: StatefulSet
3metadata:
4 name: mysql
5spec:
6 selector:
7 matchLabels:
8 app: mysql
9 serviceName: mysql
10 replicas: 3
11 template:
12 metadata:
13 labels:
14 app: mysql
15 spec:
16 initContainers:
17 - name: init-mysql
18 image: mysql:5.7
19 env:
20 - name: MYSQL_ROOT_PASSWORD
21 valueFrom:
22 secretKeyRef:
23 name: mysql-secret
24 key: mysql-root-password
25 command:
26 - bash
27 - "-c"
28 - |
29 set -ex
30 # Generate mysql server-id from pod ordinal index.
31 [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
32 ordinal=${BASH_REMATCH[1]}
33 echo [mysqld] > /mnt/conf.d/server-id.cnf
34 # Add an offset to avoid reserved server-id=0 value.
35 echo server-id=$((100 + $ordinal)) >> /mnt/conf.d/server-id.cnf
36 # Copy appropriate conf.d files from config-map to emptyDir.
37 if [[ $ordinal -eq 0 ]]; then
38 cp /mnt/config-map/primary.cnf /mnt/conf.d/
39 else
40 cp /mnt/config-map/replica.cnf /mnt/conf.d/
41 fi
42 volumeMounts:
43 - name: conf
44 mountPath: /mnt/conf.d
45 - name: config-map
46 mountPath: /mnt/config-map
47 - name: clone-mysql
48 image: gcr.io/google-samples/xtrabackup:1.0
49 command:
50 - bash
51 - "-c"
52 - |
53 set -ex
54 # Skip the clone if data already exists.
55 [[ -d /var/lib/mysql/mysql ]] && exit 0
56 # Skip the clone on primary (ordinal index 0).
57 [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
58 ordinal=${BASH_REMATCH[1]}
59 [[ $ordinal -eq 0 ]] && exit 0
60 # Clone data from previous peer.
61 ncat --recv-only mysql-$(($ordinal-1)).mysql 3307 | xbstream -x -C /var/lib/mysql
62 # Prepare the backup.
63 xtrabackup --prepare --target-dir=/var/lib/mysql
64 volumeMounts:
65 - name: data
66 mountPath: /var/lib/mysql
67 subPath: mysql
68 - name: conf
69 mountPath: /etc/mysql/conf.d
70 containers:
71 - name: mysql
72 image: mysql:5.7
73 env:
74 - name: MYSQL_ROOT_PASSWORD
75 valueFrom:
76 secretKeyRef:
77 name: mysql-secret
78 key: mysql-root-password
79 ports:
80 - name: mysql
81 containerPort: 3306
82 volumeMounts:
83 - name: data
84 mountPath: /var/lib/mysql
85 subPath: mysql
86 - name: conf
87 mountPath: /etc/mysql/conf.d
88 resources:
89 requests:
90 cpu: 100m
91 memory: 500Mi
92 - name: xtrabackup
93 image: gcr.io/google-samples/xtrabackup:1.0
94 env:
95 - name: MYSQL_ROOT_PASSWORD
96 valueFrom:
97 secretKeyRef:
98 name: mysql-secret
99 key: mysql-root-password
100 ports:
101 - name: xtrabackup
102 containerPort: 3307
103 command:
104 - bash
105 - "-c"
106 - |
107 set -ex
108 cd /var/lib/mysql
109
110 # Determine binlog position of cloned data, if any.
111 if [[ -f xtrabackup_slave_info && "x$(<xtrabackup_slave_info)" != "x" ]]; then
112 # XtraBackup already generated a partial "CHANGE MASTER TO" query
113 # because we're cloning from an existing replica. (Need to remove the tailing semicolon!)
114 cat xtrabackup_slave_info | sed -E 's/;$//g' > change_master_to.sql.in
115 # Ignore xtrabackup_binlog_info in this case (it's useless).
116 rm -f xtrabackup_slave_info xtrabackup_binlog_info
117 elif [[ -f xtrabackup_binlog_info ]]; then
118 # We're cloning directly from primary. Parse binlog position.
119 [[ `cat xtrabackup_binlog_info` =~ ^(.*?)[[:space:]]+(.*?)$ ]] || exit 1
120 rm -f xtrabackup_binlog_info xtrabackup_slave_info
121 echo "CHANGE MASTER TO MASTER_LOG_FILE='${BASH_REMATCH[1]}',\
122 MASTER_LOG_POS=${BASH_REMATCH[2]}" > change_master_to.sql.in
123 fi
124
125 # Check if we need to complete a clone by starting replication.
126 if [[ -f change_master_to.sql.in ]]; then
127 echo "Waiting for mysqld to be ready (accepting connections)"
128 until mysql -h 127.0.0.1 -uroot -p$MYSQL_ROOT_PASSWORD -e "SELECT 1"; do sleep 1; done
129
130 echo "Initializing replication from clone position"
131 mysql -h 127.0.0.1 \
132 -e "$(<change_master_to.sql.in), \
133 MASTER_HOST='mysql-0.mysql', \
134 MASTER_USER='root', \
135 MASTER_PASSWORD=$MYSQL_ROOT_PASSWORD, \
136 MASTER_CONNECT_RETRY=10; \
137 START SLAVE USER='root' PASSWORD=$MYSQL_ROOT_PASSWORD;" || exit 1
138 # In case of container restart, attempt this at-most-once.
139 mv change_master_to.sql.in change_master_to.sql.orig
140 fi
141
142 # Start a server to send backups when requested by peers.
143 exec ncat --listen --keep-open --send-only --max-conns=1 3307 -c \
144 "xtrabackup --backup --slave-info --stream=xbstream --host=127.0.0.1 --user=root --password=$MYSQL_ROOT_PASSWORD"
145 volumeMounts:
146 - name: data
147 mountPath: /var/lib/mysql
148 subPath: mysql
149 - name: conf
150 mountPath: /etc/mysql/conf.d
151 resources:
152 requests:
153 cpu: 50m
154 memory: 50Mi
155 volumes:
156 - name: conf
157 emptyDir: {}
158 - name: config-map
159 configMap:
160 name: mysql
161 volumeClaimTemplates:
162 - metadata:
163 name: data
164 spec:
165 accessModes: ["ReadWriteOnce"]
166 resources:
167 requests:
168 storage: 10Gi
169
and here is my kubectl get all,secret,configmap
's result:
1apiVersion: apps/v1
2kind: StatefulSet
3metadata:
4 name: mysql
5spec:
6 selector:
7 matchLabels:
8 app: mysql
9 serviceName: mysql
10 replicas: 3
11 template:
12 metadata:
13 labels:
14 app: mysql
15 spec:
16 initContainers:
17 - name: init-mysql
18 image: mysql:5.7
19 env:
20 - name: MYSQL_ROOT_PASSWORD
21 valueFrom:
22 secretKeyRef:
23 name: mysql-secret
24 key: mysql-root-password
25 command:
26 - bash
27 - "-c"
28 - |
29 set -ex
30 # Generate mysql server-id from pod ordinal index.
31 [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
32 ordinal=${BASH_REMATCH[1]}
33 echo [mysqld] > /mnt/conf.d/server-id.cnf
34 # Add an offset to avoid reserved server-id=0 value.
35 echo server-id=$((100 + $ordinal)) >> /mnt/conf.d/server-id.cnf
36 # Copy appropriate conf.d files from config-map to emptyDir.
37 if [[ $ordinal -eq 0 ]]; then
38 cp /mnt/config-map/primary.cnf /mnt/conf.d/
39 else
40 cp /mnt/config-map/replica.cnf /mnt/conf.d/
41 fi
42 volumeMounts:
43 - name: conf
44 mountPath: /mnt/conf.d
45 - name: config-map
46 mountPath: /mnt/config-map
47 - name: clone-mysql
48 image: gcr.io/google-samples/xtrabackup:1.0
49 command:
50 - bash
51 - "-c"
52 - |
53 set -ex
54 # Skip the clone if data already exists.
55 [[ -d /var/lib/mysql/mysql ]] && exit 0
56 # Skip the clone on primary (ordinal index 0).
57 [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
58 ordinal=${BASH_REMATCH[1]}
59 [[ $ordinal -eq 0 ]] && exit 0
60 # Clone data from previous peer.
61 ncat --recv-only mysql-$(($ordinal-1)).mysql 3307 | xbstream -x -C /var/lib/mysql
62 # Prepare the backup.
63 xtrabackup --prepare --target-dir=/var/lib/mysql
64 volumeMounts:
65 - name: data
66 mountPath: /var/lib/mysql
67 subPath: mysql
68 - name: conf
69 mountPath: /etc/mysql/conf.d
70 containers:
71 - name: mysql
72 image: mysql:5.7
73 env:
74 - name: MYSQL_ROOT_PASSWORD
75 valueFrom:
76 secretKeyRef:
77 name: mysql-secret
78 key: mysql-root-password
79 ports:
80 - name: mysql
81 containerPort: 3306
82 volumeMounts:
83 - name: data
84 mountPath: /var/lib/mysql
85 subPath: mysql
86 - name: conf
87 mountPath: /etc/mysql/conf.d
88 resources:
89 requests:
90 cpu: 100m
91 memory: 500Mi
92 - name: xtrabackup
93 image: gcr.io/google-samples/xtrabackup:1.0
94 env:
95 - name: MYSQL_ROOT_PASSWORD
96 valueFrom:
97 secretKeyRef:
98 name: mysql-secret
99 key: mysql-root-password
100 ports:
101 - name: xtrabackup
102 containerPort: 3307
103 command:
104 - bash
105 - "-c"
106 - |
107 set -ex
108 cd /var/lib/mysql
109
110 # Determine binlog position of cloned data, if any.
111 if [[ -f xtrabackup_slave_info && "x$(<xtrabackup_slave_info)" != "x" ]]; then
112 # XtraBackup already generated a partial "CHANGE MASTER TO" query
113 # because we're cloning from an existing replica. (Need to remove the tailing semicolon!)
114 cat xtrabackup_slave_info | sed -E 's/;$//g' > change_master_to.sql.in
115 # Ignore xtrabackup_binlog_info in this case (it's useless).
116 rm -f xtrabackup_slave_info xtrabackup_binlog_info
117 elif [[ -f xtrabackup_binlog_info ]]; then
118 # We're cloning directly from primary. Parse binlog position.
119 [[ `cat xtrabackup_binlog_info` =~ ^(.*?)[[:space:]]+(.*?)$ ]] || exit 1
120 rm -f xtrabackup_binlog_info xtrabackup_slave_info
121 echo "CHANGE MASTER TO MASTER_LOG_FILE='${BASH_REMATCH[1]}',\
122 MASTER_LOG_POS=${BASH_REMATCH[2]}" > change_master_to.sql.in
123 fi
124
125 # Check if we need to complete a clone by starting replication.
126 if [[ -f change_master_to.sql.in ]]; then
127 echo "Waiting for mysqld to be ready (accepting connections)"
128 until mysql -h 127.0.0.1 -uroot -p$MYSQL_ROOT_PASSWORD -e "SELECT 1"; do sleep 1; done
129
130 echo "Initializing replication from clone position"
131 mysql -h 127.0.0.1 \
132 -e "$(<change_master_to.sql.in), \
133 MASTER_HOST='mysql-0.mysql', \
134 MASTER_USER='root', \
135 MASTER_PASSWORD=$MYSQL_ROOT_PASSWORD, \
136 MASTER_CONNECT_RETRY=10; \
137 START SLAVE USER='root' PASSWORD=$MYSQL_ROOT_PASSWORD;" || exit 1
138 # In case of container restart, attempt this at-most-once.
139 mv change_master_to.sql.in change_master_to.sql.orig
140 fi
141
142 # Start a server to send backups when requested by peers.
143 exec ncat --listen --keep-open --send-only --max-conns=1 3307 -c \
144 "xtrabackup --backup --slave-info --stream=xbstream --host=127.0.0.1 --user=root --password=$MYSQL_ROOT_PASSWORD"
145 volumeMounts:
146 - name: data
147 mountPath: /var/lib/mysql
148 subPath: mysql
149 - name: conf
150 mountPath: /etc/mysql/conf.d
151 resources:
152 requests:
153 cpu: 50m
154 memory: 50Mi
155 volumes:
156 - name: conf
157 emptyDir: {}
158 - name: config-map
159 configMap:
160 name: mysql
161 volumeClaimTemplates:
162 - metadata:
163 name: data
164 spec:
165 accessModes: ["ReadWriteOnce"]
166 resources:
167 requests:
168 storage: 10Gi
169NAME READY STATUS RESTARTS AGE
170pod/mysql-0 2/2 Running 0 11m
171pod/mysql-1 1/2 Error 7 11m
172pod/mysql-2 0/2 Init:CrashLoopBackOff 6 10m
173
174NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
175service/kubernetes ClusterIP 10.245.0.1 <none> 443/TCP 2d23h
176service/mysql ClusterIP None <none> 3306/TCP 43h
177service/mysql-read ClusterIP 10.245.81.173 <none> 3306/TCP 43h
178
179NAME READY UP-TO-DATE AVAILABLE AGE
180deployment.apps/phpmyadmin 1/1 1 1 2d18h
181
182NAME DESIRED CURRENT READY AGE
183replicaset.apps/phpmyadmin-6c57fd98bf 1 1 1 2d18h
184
185NAME READY AGE
186statefulset.apps/mysql 1/3 11m
187
188NAME TYPE DATA AGE
189secret/mysql-pass Opaque 1 46h
190secret/mysql-secret Opaque 3 2d18h
191
192NAME DATA AGE
193configmap/mysql 4 2d18h
194
When I tried to describe the mysql-1
pod, it said that:
1apiVersion: apps/v1
2kind: StatefulSet
3metadata:
4 name: mysql
5spec:
6 selector:
7 matchLabels:
8 app: mysql
9 serviceName: mysql
10 replicas: 3
11 template:
12 metadata:
13 labels:
14 app: mysql
15 spec:
16 initContainers:
17 - name: init-mysql
18 image: mysql:5.7
19 env:
20 - name: MYSQL_ROOT_PASSWORD
21 valueFrom:
22 secretKeyRef:
23 name: mysql-secret
24 key: mysql-root-password
25 command:
26 - bash
27 - "-c"
28 - |
29 set -ex
30 # Generate mysql server-id from pod ordinal index.
31 [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
32 ordinal=${BASH_REMATCH[1]}
33 echo [mysqld] > /mnt/conf.d/server-id.cnf
34 # Add an offset to avoid reserved server-id=0 value.
35 echo server-id=$((100 + $ordinal)) >> /mnt/conf.d/server-id.cnf
36 # Copy appropriate conf.d files from config-map to emptyDir.
37 if [[ $ordinal -eq 0 ]]; then
38 cp /mnt/config-map/primary.cnf /mnt/conf.d/
39 else
40 cp /mnt/config-map/replica.cnf /mnt/conf.d/
41 fi
42 volumeMounts:
43 - name: conf
44 mountPath: /mnt/conf.d
45 - name: config-map
46 mountPath: /mnt/config-map
47 - name: clone-mysql
48 image: gcr.io/google-samples/xtrabackup:1.0
49 command:
50 - bash
51 - "-c"
52 - |
53 set -ex
54 # Skip the clone if data already exists.
55 [[ -d /var/lib/mysql/mysql ]] && exit 0
56 # Skip the clone on primary (ordinal index 0).
57 [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
58 ordinal=${BASH_REMATCH[1]}
59 [[ $ordinal -eq 0 ]] && exit 0
60 # Clone data from previous peer.
61 ncat --recv-only mysql-$(($ordinal-1)).mysql 3307 | xbstream -x -C /var/lib/mysql
62 # Prepare the backup.
63 xtrabackup --prepare --target-dir=/var/lib/mysql
64 volumeMounts:
65 - name: data
66 mountPath: /var/lib/mysql
67 subPath: mysql
68 - name: conf
69 mountPath: /etc/mysql/conf.d
70 containers:
71 - name: mysql
72 image: mysql:5.7
73 env:
74 - name: MYSQL_ROOT_PASSWORD
75 valueFrom:
76 secretKeyRef:
77 name: mysql-secret
78 key: mysql-root-password
79 ports:
80 - name: mysql
81 containerPort: 3306
82 volumeMounts:
83 - name: data
84 mountPath: /var/lib/mysql
85 subPath: mysql
86 - name: conf
87 mountPath: /etc/mysql/conf.d
88 resources:
89 requests:
90 cpu: 100m
91 memory: 500Mi
92 - name: xtrabackup
93 image: gcr.io/google-samples/xtrabackup:1.0
94 env:
95 - name: MYSQL_ROOT_PASSWORD
96 valueFrom:
97 secretKeyRef:
98 name: mysql-secret
99 key: mysql-root-password
100 ports:
101 - name: xtrabackup
102 containerPort: 3307
103 command:
104 - bash
105 - "-c"
106 - |
107 set -ex
108 cd /var/lib/mysql
109
110 # Determine binlog position of cloned data, if any.
111 if [[ -f xtrabackup_slave_info && "x$(<xtrabackup_slave_info)" != "x" ]]; then
112 # XtraBackup already generated a partial "CHANGE MASTER TO" query
113 # because we're cloning from an existing replica. (Need to remove the tailing semicolon!)
114 cat xtrabackup_slave_info | sed -E 's/;$//g' > change_master_to.sql.in
115 # Ignore xtrabackup_binlog_info in this case (it's useless).
116 rm -f xtrabackup_slave_info xtrabackup_binlog_info
117 elif [[ -f xtrabackup_binlog_info ]]; then
118 # We're cloning directly from primary. Parse binlog position.
119 [[ `cat xtrabackup_binlog_info` =~ ^(.*?)[[:space:]]+(.*?)$ ]] || exit 1
120 rm -f xtrabackup_binlog_info xtrabackup_slave_info
121 echo "CHANGE MASTER TO MASTER_LOG_FILE='${BASH_REMATCH[1]}',\
122 MASTER_LOG_POS=${BASH_REMATCH[2]}" > change_master_to.sql.in
123 fi
124
125 # Check if we need to complete a clone by starting replication.
126 if [[ -f change_master_to.sql.in ]]; then
127 echo "Waiting for mysqld to be ready (accepting connections)"
128 until mysql -h 127.0.0.1 -uroot -p$MYSQL_ROOT_PASSWORD -e "SELECT 1"; do sleep 1; done
129
130 echo "Initializing replication from clone position"
131 mysql -h 127.0.0.1 \
132 -e "$(<change_master_to.sql.in), \
133 MASTER_HOST='mysql-0.mysql', \
134 MASTER_USER='root', \
135 MASTER_PASSWORD=$MYSQL_ROOT_PASSWORD, \
136 MASTER_CONNECT_RETRY=10; \
137 START SLAVE USER='root' PASSWORD=$MYSQL_ROOT_PASSWORD;" || exit 1
138 # In case of container restart, attempt this at-most-once.
139 mv change_master_to.sql.in change_master_to.sql.orig
140 fi
141
142 # Start a server to send backups when requested by peers.
143 exec ncat --listen --keep-open --send-only --max-conns=1 3307 -c \
144 "xtrabackup --backup --slave-info --stream=xbstream --host=127.0.0.1 --user=root --password=$MYSQL_ROOT_PASSWORD"
145 volumeMounts:
146 - name: data
147 mountPath: /var/lib/mysql
148 subPath: mysql
149 - name: conf
150 mountPath: /etc/mysql/conf.d
151 resources:
152 requests:
153 cpu: 50m
154 memory: 50Mi
155 volumes:
156 - name: conf
157 emptyDir: {}
158 - name: config-map
159 configMap:
160 name: mysql
161 volumeClaimTemplates:
162 - metadata:
163 name: data
164 spec:
165 accessModes: ["ReadWriteOnce"]
166 resources:
167 requests:
168 storage: 10Gi
169NAME READY STATUS RESTARTS AGE
170pod/mysql-0 2/2 Running 0 11m
171pod/mysql-1 1/2 Error 7 11m
172pod/mysql-2 0/2 Init:CrashLoopBackOff 6 10m
173
174NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
175service/kubernetes ClusterIP 10.245.0.1 <none> 443/TCP 2d23h
176service/mysql ClusterIP None <none> 3306/TCP 43h
177service/mysql-read ClusterIP 10.245.81.173 <none> 3306/TCP 43h
178
179NAME READY UP-TO-DATE AVAILABLE AGE
180deployment.apps/phpmyadmin 1/1 1 1 2d18h
181
182NAME DESIRED CURRENT READY AGE
183replicaset.apps/phpmyadmin-6c57fd98bf 1 1 1 2d18h
184
185NAME READY AGE
186statefulset.apps/mysql 1/3 11m
187
188NAME TYPE DATA AGE
189secret/mysql-pass Opaque 1 46h
190secret/mysql-secret Opaque 3 2d18h
191
192NAME DATA AGE
193configmap/mysql 4 2d18h
194ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)
195
But when I tried logging in using my defined root password on mysql-0
pod, it works. I have also tried looking a duplicated question here, but the past's tutorial code has changed (FYI, I also tried it too despite the change), so it did not really help. Any help will do! Thanks in advance!
UPDATE I tried adding this:
1apiVersion: apps/v1
2kind: StatefulSet
3metadata:
4 name: mysql
5spec:
6 selector:
7 matchLabels:
8 app: mysql
9 serviceName: mysql
10 replicas: 3
11 template:
12 metadata:
13 labels:
14 app: mysql
15 spec:
16 initContainers:
17 - name: init-mysql
18 image: mysql:5.7
19 env:
20 - name: MYSQL_ROOT_PASSWORD
21 valueFrom:
22 secretKeyRef:
23 name: mysql-secret
24 key: mysql-root-password
25 command:
26 - bash
27 - "-c"
28 - |
29 set -ex
30 # Generate mysql server-id from pod ordinal index.
31 [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
32 ordinal=${BASH_REMATCH[1]}
33 echo [mysqld] > /mnt/conf.d/server-id.cnf
34 # Add an offset to avoid reserved server-id=0 value.
35 echo server-id=$((100 + $ordinal)) >> /mnt/conf.d/server-id.cnf
36 # Copy appropriate conf.d files from config-map to emptyDir.
37 if [[ $ordinal -eq 0 ]]; then
38 cp /mnt/config-map/primary.cnf /mnt/conf.d/
39 else
40 cp /mnt/config-map/replica.cnf /mnt/conf.d/
41 fi
42 volumeMounts:
43 - name: conf
44 mountPath: /mnt/conf.d
45 - name: config-map
46 mountPath: /mnt/config-map
47 - name: clone-mysql
48 image: gcr.io/google-samples/xtrabackup:1.0
49 command:
50 - bash
51 - "-c"
52 - |
53 set -ex
54 # Skip the clone if data already exists.
55 [[ -d /var/lib/mysql/mysql ]] && exit 0
56 # Skip the clone on primary (ordinal index 0).
57 [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
58 ordinal=${BASH_REMATCH[1]}
59 [[ $ordinal -eq 0 ]] && exit 0
60 # Clone data from previous peer.
61 ncat --recv-only mysql-$(($ordinal-1)).mysql 3307 | xbstream -x -C /var/lib/mysql
62 # Prepare the backup.
63 xtrabackup --prepare --target-dir=/var/lib/mysql
64 volumeMounts:
65 - name: data
66 mountPath: /var/lib/mysql
67 subPath: mysql
68 - name: conf
69 mountPath: /etc/mysql/conf.d
70 containers:
71 - name: mysql
72 image: mysql:5.7
73 env:
74 - name: MYSQL_ROOT_PASSWORD
75 valueFrom:
76 secretKeyRef:
77 name: mysql-secret
78 key: mysql-root-password
79 ports:
80 - name: mysql
81 containerPort: 3306
82 volumeMounts:
83 - name: data
84 mountPath: /var/lib/mysql
85 subPath: mysql
86 - name: conf
87 mountPath: /etc/mysql/conf.d
88 resources:
89 requests:
90 cpu: 100m
91 memory: 500Mi
92 - name: xtrabackup
93 image: gcr.io/google-samples/xtrabackup:1.0
94 env:
95 - name: MYSQL_ROOT_PASSWORD
96 valueFrom:
97 secretKeyRef:
98 name: mysql-secret
99 key: mysql-root-password
100 ports:
101 - name: xtrabackup
102 containerPort: 3307
103 command:
104 - bash
105 - "-c"
106 - |
107 set -ex
108 cd /var/lib/mysql
109
110 # Determine binlog position of cloned data, if any.
111 if [[ -f xtrabackup_slave_info && "x$(<xtrabackup_slave_info)" != "x" ]]; then
112 # XtraBackup already generated a partial "CHANGE MASTER TO" query
113 # because we're cloning from an existing replica. (Need to remove the tailing semicolon!)
114 cat xtrabackup_slave_info | sed -E 's/;$//g' > change_master_to.sql.in
115 # Ignore xtrabackup_binlog_info in this case (it's useless).
116 rm -f xtrabackup_slave_info xtrabackup_binlog_info
117 elif [[ -f xtrabackup_binlog_info ]]; then
118 # We're cloning directly from primary. Parse binlog position.
119 [[ `cat xtrabackup_binlog_info` =~ ^(.*?)[[:space:]]+(.*?)$ ]] || exit 1
120 rm -f xtrabackup_binlog_info xtrabackup_slave_info
121 echo "CHANGE MASTER TO MASTER_LOG_FILE='${BASH_REMATCH[1]}',\
122 MASTER_LOG_POS=${BASH_REMATCH[2]}" > change_master_to.sql.in
123 fi
124
125 # Check if we need to complete a clone by starting replication.
126 if [[ -f change_master_to.sql.in ]]; then
127 echo "Waiting for mysqld to be ready (accepting connections)"
128 until mysql -h 127.0.0.1 -uroot -p$MYSQL_ROOT_PASSWORD -e "SELECT 1"; do sleep 1; done
129
130 echo "Initializing replication from clone position"
131 mysql -h 127.0.0.1 \
132 -e "$(<change_master_to.sql.in), \
133 MASTER_HOST='mysql-0.mysql', \
134 MASTER_USER='root', \
135 MASTER_PASSWORD=$MYSQL_ROOT_PASSWORD, \
136 MASTER_CONNECT_RETRY=10; \
137 START SLAVE USER='root' PASSWORD=$MYSQL_ROOT_PASSWORD;" || exit 1
138 # In case of container restart, attempt this at-most-once.
139 mv change_master_to.sql.in change_master_to.sql.orig
140 fi
141
142 # Start a server to send backups when requested by peers.
143 exec ncat --listen --keep-open --send-only --max-conns=1 3307 -c \
144 "xtrabackup --backup --slave-info --stream=xbstream --host=127.0.0.1 --user=root --password=$MYSQL_ROOT_PASSWORD"
145 volumeMounts:
146 - name: data
147 mountPath: /var/lib/mysql
148 subPath: mysql
149 - name: conf
150 mountPath: /etc/mysql/conf.d
151 resources:
152 requests:
153 cpu: 50m
154 memory: 50Mi
155 volumes:
156 - name: conf
157 emptyDir: {}
158 - name: config-map
159 configMap:
160 name: mysql
161 volumeClaimTemplates:
162 - metadata:
163 name: data
164 spec:
165 accessModes: ["ReadWriteOnce"]
166 resources:
167 requests:
168 storage: 10Gi
169NAME READY STATUS RESTARTS AGE
170pod/mysql-0 2/2 Running 0 11m
171pod/mysql-1 1/2 Error 7 11m
172pod/mysql-2 0/2 Init:CrashLoopBackOff 6 10m
173
174NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
175service/kubernetes ClusterIP 10.245.0.1 <none> 443/TCP 2d23h
176service/mysql ClusterIP None <none> 3306/TCP 43h
177service/mysql-read ClusterIP 10.245.81.173 <none> 3306/TCP 43h
178
179NAME READY UP-TO-DATE AVAILABLE AGE
180deployment.apps/phpmyadmin 1/1 1 1 2d18h
181
182NAME DESIRED CURRENT READY AGE
183replicaset.apps/phpmyadmin-6c57fd98bf 1 1 1 2d18h
184
185NAME READY AGE
186statefulset.apps/mysql 1/3 11m
187
188NAME TYPE DATA AGE
189secret/mysql-pass Opaque 1 46h
190secret/mysql-secret Opaque 3 2d18h
191
192NAME DATA AGE
193configmap/mysql 4 2d18h
194ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)
195 - name: MYSQL_ROOT_HOST
196 value: "%"
197
on my mysql
and xtrabackup
containers, also didn't work, here's the get pods --watch
return:
1apiVersion: apps/v1
2kind: StatefulSet
3metadata:
4 name: mysql
5spec:
6 selector:
7 matchLabels:
8 app: mysql
9 serviceName: mysql
10 replicas: 3
11 template:
12 metadata:
13 labels:
14 app: mysql
15 spec:
16 initContainers:
17 - name: init-mysql
18 image: mysql:5.7
19 env:
20 - name: MYSQL_ROOT_PASSWORD
21 valueFrom:
22 secretKeyRef:
23 name: mysql-secret
24 key: mysql-root-password
25 command:
26 - bash
27 - "-c"
28 - |
29 set -ex
30 # Generate mysql server-id from pod ordinal index.
31 [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
32 ordinal=${BASH_REMATCH[1]}
33 echo [mysqld] > /mnt/conf.d/server-id.cnf
34 # Add an offset to avoid reserved server-id=0 value.
35 echo server-id=$((100 + $ordinal)) >> /mnt/conf.d/server-id.cnf
36 # Copy appropriate conf.d files from config-map to emptyDir.
37 if [[ $ordinal -eq 0 ]]; then
38 cp /mnt/config-map/primary.cnf /mnt/conf.d/
39 else
40 cp /mnt/config-map/replica.cnf /mnt/conf.d/
41 fi
42 volumeMounts:
43 - name: conf
44 mountPath: /mnt/conf.d
45 - name: config-map
46 mountPath: /mnt/config-map
47 - name: clone-mysql
48 image: gcr.io/google-samples/xtrabackup:1.0
49 command:
50 - bash
51 - "-c"
52 - |
53 set -ex
54 # Skip the clone if data already exists.
55 [[ -d /var/lib/mysql/mysql ]] && exit 0
56 # Skip the clone on primary (ordinal index 0).
57 [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
58 ordinal=${BASH_REMATCH[1]}
59 [[ $ordinal -eq 0 ]] && exit 0
60 # Clone data from previous peer.
61 ncat --recv-only mysql-$(($ordinal-1)).mysql 3307 | xbstream -x -C /var/lib/mysql
62 # Prepare the backup.
63 xtrabackup --prepare --target-dir=/var/lib/mysql
64 volumeMounts:
65 - name: data
66 mountPath: /var/lib/mysql
67 subPath: mysql
68 - name: conf
69 mountPath: /etc/mysql/conf.d
70 containers:
71 - name: mysql
72 image: mysql:5.7
73 env:
74 - name: MYSQL_ROOT_PASSWORD
75 valueFrom:
76 secretKeyRef:
77 name: mysql-secret
78 key: mysql-root-password
79 ports:
80 - name: mysql
81 containerPort: 3306
82 volumeMounts:
83 - name: data
84 mountPath: /var/lib/mysql
85 subPath: mysql
86 - name: conf
87 mountPath: /etc/mysql/conf.d
88 resources:
89 requests:
90 cpu: 100m
91 memory: 500Mi
92 - name: xtrabackup
93 image: gcr.io/google-samples/xtrabackup:1.0
94 env:
95 - name: MYSQL_ROOT_PASSWORD
96 valueFrom:
97 secretKeyRef:
98 name: mysql-secret
99 key: mysql-root-password
100 ports:
101 - name: xtrabackup
102 containerPort: 3307
103 command:
104 - bash
105 - "-c"
106 - |
107 set -ex
108 cd /var/lib/mysql
109
110 # Determine binlog position of cloned data, if any.
111 if [[ -f xtrabackup_slave_info && "x$(<xtrabackup_slave_info)" != "x" ]]; then
112 # XtraBackup already generated a partial "CHANGE MASTER TO" query
113 # because we're cloning from an existing replica. (Need to remove the tailing semicolon!)
114 cat xtrabackup_slave_info | sed -E 's/;$//g' > change_master_to.sql.in
115 # Ignore xtrabackup_binlog_info in this case (it's useless).
116 rm -f xtrabackup_slave_info xtrabackup_binlog_info
117 elif [[ -f xtrabackup_binlog_info ]]; then
118 # We're cloning directly from primary. Parse binlog position.
119 [[ `cat xtrabackup_binlog_info` =~ ^(.*?)[[:space:]]+(.*?)$ ]] || exit 1
120 rm -f xtrabackup_binlog_info xtrabackup_slave_info
121 echo "CHANGE MASTER TO MASTER_LOG_FILE='${BASH_REMATCH[1]}',\
122 MASTER_LOG_POS=${BASH_REMATCH[2]}" > change_master_to.sql.in
123 fi
124
125 # Check if we need to complete a clone by starting replication.
126 if [[ -f change_master_to.sql.in ]]; then
127 echo "Waiting for mysqld to be ready (accepting connections)"
128 until mysql -h 127.0.0.1 -uroot -p$MYSQL_ROOT_PASSWORD -e "SELECT 1"; do sleep 1; done
129
130 echo "Initializing replication from clone position"
131 mysql -h 127.0.0.1 \
132 -e "$(<change_master_to.sql.in), \
133 MASTER_HOST='mysql-0.mysql', \
134 MASTER_USER='root', \
135 MASTER_PASSWORD=$MYSQL_ROOT_PASSWORD, \
136 MASTER_CONNECT_RETRY=10; \
137 START SLAVE USER='root' PASSWORD=$MYSQL_ROOT_PASSWORD;" || exit 1
138 # In case of container restart, attempt this at-most-once.
139 mv change_master_to.sql.in change_master_to.sql.orig
140 fi
141
142 # Start a server to send backups when requested by peers.
143 exec ncat --listen --keep-open --send-only --max-conns=1 3307 -c \
144 "xtrabackup --backup --slave-info --stream=xbstream --host=127.0.0.1 --user=root --password=$MYSQL_ROOT_PASSWORD"
145 volumeMounts:
146 - name: data
147 mountPath: /var/lib/mysql
148 subPath: mysql
149 - name: conf
150 mountPath: /etc/mysql/conf.d
151 resources:
152 requests:
153 cpu: 50m
154 memory: 50Mi
155 volumes:
156 - name: conf
157 emptyDir: {}
158 - name: config-map
159 configMap:
160 name: mysql
161 volumeClaimTemplates:
162 - metadata:
163 name: data
164 spec:
165 accessModes: ["ReadWriteOnce"]
166 resources:
167 requests:
168 storage: 10Gi
169NAME READY STATUS RESTARTS AGE
170pod/mysql-0 2/2 Running 0 11m
171pod/mysql-1 1/2 Error 7 11m
172pod/mysql-2 0/2 Init:CrashLoopBackOff 6 10m
173
174NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
175service/kubernetes ClusterIP 10.245.0.1 <none> 443/TCP 2d23h
176service/mysql ClusterIP None <none> 3306/TCP 43h
177service/mysql-read ClusterIP 10.245.81.173 <none> 3306/TCP 43h
178
179NAME READY UP-TO-DATE AVAILABLE AGE
180deployment.apps/phpmyadmin 1/1 1 1 2d18h
181
182NAME DESIRED CURRENT READY AGE
183replicaset.apps/phpmyadmin-6c57fd98bf 1 1 1 2d18h
184
185NAME READY AGE
186statefulset.apps/mysql 1/3 11m
187
188NAME TYPE DATA AGE
189secret/mysql-pass Opaque 1 46h
190secret/mysql-secret Opaque 3 2d18h
191
192NAME DATA AGE
193configmap/mysql 4 2d18h
194ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)
195 - name: MYSQL_ROOT_HOST
196 value: "%"
197NAME READY STATUS RESTARTS AGE
198mysql-0 0/2 Init:0/2 0 7s
199mysql-0 0/2 Init:1/2 0 18s
200mysql-0 0/2 PodInitializing 0 19s
201mysql-0 2/2 Running 0 20s
202mysql-1 0/2 Pending 0 0s
203mysql-1 0/2 Pending 0 0s
204mysql-1 0/2 Pending 0 8s
205mysql-1 0/2 Init:0/2 0 8s
206mysql-1 0/2 Init:1/2 0 26s
207mysql-1 0/2 Init:1/2 0 27s
208mysql-1 0/2 PodInitializing 0 34s
209mysql-1 2/2 Running 0 35s
210mysql-2 0/2 Pending 0 0s
211mysql-2 0/2 Pending 0 0s
212mysql-1 1/2 Error 0 37s
213mysql-1 1/2 Error 1 38s
214mysql-2 0/2 Pending 0 3s
215mysql-2 0/2 Init:0/2 0 3s
216mysql-1 1/2 CrashLoopBackOff 1 53s
217mysql-1 1/2 Error 2 54s
218mysql-2 0/2 Init:1/2 0 21s
219mysql-2 0/2 Init:Error 0 22s
220mysql-2 0/2 Init:Error 1 23s
221mysql-2 0/2 Init:CrashLoopBackOff 1 24s
222mysql-1 1/2 CrashLoopBackOff 2 64s
223mysql-2 0/2 Init:Error 2 38s
224mysql-1 1/2 Error 3 79s
225mysql-2 0/2 Init:CrashLoopBackOff 2 50s
226mysql-1 1/2 CrashLoopBackOff 3 92s
227mysql-2 0/2 Init:Error 3 62s
228mysql-2 0/2 Init:CrashLoopBackOff 3 74s
229mysql-1 1/2 Error 4 2m1s
230mysql-1 1/2 CrashLoopBackOff 4 2m11s
231mysql-2 0/2 Init:Error 4 113s
232mysql-2 0/2 Init:CrashLoopBackOff 4 2m6s
233mysql-1 1/2 Error 5 3m29s
234mysql-1 1/2 CrashLoopBackOff 5 3m41s
235mysql-2 0/2 Init:Error 5 3m23s
236mysql-2 0/2 Init:CrashLoopBackOff 5 3m34s
237
For some reason mysql-1
ran for a while, then stopped.
Logs from mysql-1
pod :
1apiVersion: apps/v1
2kind: StatefulSet
3metadata:
4 name: mysql
5spec:
6 selector:
7 matchLabels:
8 app: mysql
9 serviceName: mysql
10 replicas: 3
11 template:
12 metadata:
13 labels:
14 app: mysql
15 spec:
16 initContainers:
17 - name: init-mysql
18 image: mysql:5.7
19 env:
20 - name: MYSQL_ROOT_PASSWORD
21 valueFrom:
22 secretKeyRef:
23 name: mysql-secret
24 key: mysql-root-password
25 command:
26 - bash
27 - "-c"
28 - |
29 set -ex
30 # Generate mysql server-id from pod ordinal index.
31 [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
32 ordinal=${BASH_REMATCH[1]}
33 echo [mysqld] > /mnt/conf.d/server-id.cnf
34 # Add an offset to avoid reserved server-id=0 value.
35 echo server-id=$((100 + $ordinal)) >> /mnt/conf.d/server-id.cnf
36 # Copy appropriate conf.d files from config-map to emptyDir.
37 if [[ $ordinal -eq 0 ]]; then
38 cp /mnt/config-map/primary.cnf /mnt/conf.d/
39 else
40 cp /mnt/config-map/replica.cnf /mnt/conf.d/
41 fi
42 volumeMounts:
43 - name: conf
44 mountPath: /mnt/conf.d
45 - name: config-map
46 mountPath: /mnt/config-map
47 - name: clone-mysql
48 image: gcr.io/google-samples/xtrabackup:1.0
49 command:
50 - bash
51 - "-c"
52 - |
53 set -ex
54 # Skip the clone if data already exists.
55 [[ -d /var/lib/mysql/mysql ]] && exit 0
56 # Skip the clone on primary (ordinal index 0).
57 [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
58 ordinal=${BASH_REMATCH[1]}
59 [[ $ordinal -eq 0 ]] && exit 0
60 # Clone data from previous peer.
61 ncat --recv-only mysql-$(($ordinal-1)).mysql 3307 | xbstream -x -C /var/lib/mysql
62 # Prepare the backup.
63 xtrabackup --prepare --target-dir=/var/lib/mysql
64 volumeMounts:
65 - name: data
66 mountPath: /var/lib/mysql
67 subPath: mysql
68 - name: conf
69 mountPath: /etc/mysql/conf.d
70 containers:
71 - name: mysql
72 image: mysql:5.7
73 env:
74 - name: MYSQL_ROOT_PASSWORD
75 valueFrom:
76 secretKeyRef:
77 name: mysql-secret
78 key: mysql-root-password
79 ports:
80 - name: mysql
81 containerPort: 3306
82 volumeMounts:
83 - name: data
84 mountPath: /var/lib/mysql
85 subPath: mysql
86 - name: conf
87 mountPath: /etc/mysql/conf.d
88 resources:
89 requests:
90 cpu: 100m
91 memory: 500Mi
92 - name: xtrabackup
93 image: gcr.io/google-samples/xtrabackup:1.0
94 env:
95 - name: MYSQL_ROOT_PASSWORD
96 valueFrom:
97 secretKeyRef:
98 name: mysql-secret
99 key: mysql-root-password
100 ports:
101 - name: xtrabackup
102 containerPort: 3307
103 command:
104 - bash
105 - "-c"
106 - |
107 set -ex
108 cd /var/lib/mysql
109
110 # Determine binlog position of cloned data, if any.
111 if [[ -f xtrabackup_slave_info && "x$(<xtrabackup_slave_info)" != "x" ]]; then
112 # XtraBackup already generated a partial "CHANGE MASTER TO" query
113 # because we're cloning from an existing replica. (Need to remove the tailing semicolon!)
114 cat xtrabackup_slave_info | sed -E 's/;$//g' > change_master_to.sql.in
115 # Ignore xtrabackup_binlog_info in this case (it's useless).
116 rm -f xtrabackup_slave_info xtrabackup_binlog_info
117 elif [[ -f xtrabackup_binlog_info ]]; then
118 # We're cloning directly from primary. Parse binlog position.
119 [[ `cat xtrabackup_binlog_info` =~ ^(.*?)[[:space:]]+(.*?)$ ]] || exit 1
120 rm -f xtrabackup_binlog_info xtrabackup_slave_info
121 echo "CHANGE MASTER TO MASTER_LOG_FILE='${BASH_REMATCH[1]}',\
122 MASTER_LOG_POS=${BASH_REMATCH[2]}" > change_master_to.sql.in
123 fi
124
125 # Check if we need to complete a clone by starting replication.
126 if [[ -f change_master_to.sql.in ]]; then
127 echo "Waiting for mysqld to be ready (accepting connections)"
128 until mysql -h 127.0.0.1 -uroot -p$MYSQL_ROOT_PASSWORD -e "SELECT 1"; do sleep 1; done
129
130 echo "Initializing replication from clone position"
131 mysql -h 127.0.0.1 \
132 -e "$(<change_master_to.sql.in), \
133 MASTER_HOST='mysql-0.mysql', \
134 MASTER_USER='root', \
135 MASTER_PASSWORD=$MYSQL_ROOT_PASSWORD, \
136 MASTER_CONNECT_RETRY=10; \
137 START SLAVE USER='root' PASSWORD=$MYSQL_ROOT_PASSWORD;" || exit 1
138 # In case of container restart, attempt this at-most-once.
139 mv change_master_to.sql.in change_master_to.sql.orig
140 fi
141
142 # Start a server to send backups when requested by peers.
143 exec ncat --listen --keep-open --send-only --max-conns=1 3307 -c \
144 "xtrabackup --backup --slave-info --stream=xbstream --host=127.0.0.1 --user=root --password=$MYSQL_ROOT_PASSWORD"
145 volumeMounts:
146 - name: data
147 mountPath: /var/lib/mysql
148 subPath: mysql
149 - name: conf
150 mountPath: /etc/mysql/conf.d
151 resources:
152 requests:
153 cpu: 50m
154 memory: 50Mi
155 volumes:
156 - name: conf
157 emptyDir: {}
158 - name: config-map
159 configMap:
160 name: mysql
161 volumeClaimTemplates:
162 - metadata:
163 name: data
164 spec:
165 accessModes: ["ReadWriteOnce"]
166 resources:
167 requests:
168 storage: 10Gi
169NAME READY STATUS RESTARTS AGE
170pod/mysql-0 2/2 Running 0 11m
171pod/mysql-1 1/2 Error 7 11m
172pod/mysql-2 0/2 Init:CrashLoopBackOff 6 10m
173
174NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
175service/kubernetes ClusterIP 10.245.0.1 <none> 443/TCP 2d23h
176service/mysql ClusterIP None <none> 3306/TCP 43h
177service/mysql-read ClusterIP 10.245.81.173 <none> 3306/TCP 43h
178
179NAME READY UP-TO-DATE AVAILABLE AGE
180deployment.apps/phpmyadmin 1/1 1 1 2d18h
181
182NAME DESIRED CURRENT READY AGE
183replicaset.apps/phpmyadmin-6c57fd98bf 1 1 1 2d18h
184
185NAME READY AGE
186statefulset.apps/mysql 1/3 11m
187
188NAME TYPE DATA AGE
189secret/mysql-pass Opaque 1 46h
190secret/mysql-secret Opaque 3 2d18h
191
192NAME DATA AGE
193configmap/mysql 4 2d18h
194ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)
195 - name: MYSQL_ROOT_HOST
196 value: "%"
197NAME READY STATUS RESTARTS AGE
198mysql-0 0/2 Init:0/2 0 7s
199mysql-0 0/2 Init:1/2 0 18s
200mysql-0 0/2 PodInitializing 0 19s
201mysql-0 2/2 Running 0 20s
202mysql-1 0/2 Pending 0 0s
203mysql-1 0/2 Pending 0 0s
204mysql-1 0/2 Pending 0 8s
205mysql-1 0/2 Init:0/2 0 8s
206mysql-1 0/2 Init:1/2 0 26s
207mysql-1 0/2 Init:1/2 0 27s
208mysql-1 0/2 PodInitializing 0 34s
209mysql-1 2/2 Running 0 35s
210mysql-2 0/2 Pending 0 0s
211mysql-2 0/2 Pending 0 0s
212mysql-1 1/2 Error 0 37s
213mysql-1 1/2 Error 1 38s
214mysql-2 0/2 Pending 0 3s
215mysql-2 0/2 Init:0/2 0 3s
216mysql-1 1/2 CrashLoopBackOff 1 53s
217mysql-1 1/2 Error 2 54s
218mysql-2 0/2 Init:1/2 0 21s
219mysql-2 0/2 Init:Error 0 22s
220mysql-2 0/2 Init:Error 1 23s
221mysql-2 0/2 Init:CrashLoopBackOff 1 24s
222mysql-1 1/2 CrashLoopBackOff 2 64s
223mysql-2 0/2 Init:Error 2 38s
224mysql-1 1/2 Error 3 79s
225mysql-2 0/2 Init:CrashLoopBackOff 2 50s
226mysql-1 1/2 CrashLoopBackOff 3 92s
227mysql-2 0/2 Init:Error 3 62s
228mysql-2 0/2 Init:CrashLoopBackOff 3 74s
229mysql-1 1/2 Error 4 2m1s
230mysql-1 1/2 CrashLoopBackOff 4 2m11s
231mysql-2 0/2 Init:Error 4 113s
232mysql-2 0/2 Init:CrashLoopBackOff 4 2m6s
233mysql-1 1/2 Error 5 3m29s
234mysql-1 1/2 CrashLoopBackOff 5 3m41s
235mysql-2 0/2 Init:Error 5 3m23s
236mysql-2 0/2 Init:CrashLoopBackOff 5 3m34s
2372021-10-25 03:16:36+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.36-1debian10 started.
2382021-10-25 03:16:36+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
2392021-10-25 03:16:36+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.36-1debian10 started.
2402021-10-25T03:16:37.231906Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
2412021-10-25T03:16:37.234015Z 0 [Note] mysqld (mysqld 5.7.36) starting as process 1 ...
2422021-10-25T03:16:37.237044Z 0 [Note] InnoDB: PUNCH HOLE support available
2432021-10-25T03:16:37.237196Z 0 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
2442021-10-25T03:16:37.237263Z 0 [Note] InnoDB: Uses event mutexes
2452021-10-25T03:16:37.237345Z 0 [Note] InnoDB: GCC builtin __atomic_thread_fence() is used for memory barrier
2462021-10-25T03:16:37.237416Z 0 [Note] InnoDB: Compressed tables use zlib 1.2.11
2472021-10-25T03:16:37.237489Z 0 [Note] InnoDB: Using Linux native AIO
2482021-10-25T03:16:37.237792Z 0 [Note] InnoDB: Number of pools: 1
2492021-10-25T03:16:37.238102Z 0 [Note] InnoDB: Using CPU crc32 instructions
2502021-10-25T03:16:37.240179Z 0 [Note] InnoDB: Initializing buffer pool, total size = 128M, instances = 1, chunk size = 128M
2512021-10-25T03:16:37.248111Z 0 [Note] InnoDB: Completed initialization of buffer pool
2522021-10-25T03:16:37.251017Z 0 [Note] InnoDB: If the mysqld execution user is authorized, page cleaner thread priority can be changed. See the man page of setpriority().
2532021-10-25T03:16:37.263519Z 0 [Note] InnoDB: Highest supported file format is Barracuda.
2542021-10-25T03:16:37.307064Z 0 [Note] InnoDB: Removed temporary tablespace data file: "ibtmp1"
2552021-10-25T03:16:37.307319Z 0 [Note] InnoDB: Creating shared tablespace for temporary tables
2562021-10-25T03:16:37.307466Z 0 [Note] InnoDB: Setting file './ibtmp1' size to 12 MB. Physically writing the file full; Please wait ...
2572021-10-25T03:16:37.353707Z 0 [Note] InnoDB: File './ibtmp1' size is now 12 MB.
2582021-10-25T03:16:37.354244Z 0 [Note] InnoDB: 96 redo rollback segment(s) found. 96 redo rollback segment(s) are active.
2592021-10-25T03:16:37.354256Z 0 [Note] InnoDB: 32 non-redo rollback segment(s) are active.
2602021-10-25T03:16:37.355048Z 0 [Note] InnoDB: Waiting for purge to start
2612021-10-25T03:16:37.406335Z 0 [Note] InnoDB: 5.7.36 started; log sequence number 12660776
2622021-10-25T03:16:37.406850Z 0 [Note] Plugin 'FEDERATED' is disabled.
2632021-10-25T03:16:37.413880Z 0 [Note] InnoDB: Loading buffer pool(s) from /var/lib/mysql/ib_buffer_pool
2642021-10-25T03:16:37.426491Z 0 [Note] InnoDB: Buffer pool(s) load completed at 211025 3:16:37
2652021-10-25T03:16:37.427210Z 0 [Note] Salting uuid generator variables, current_pid: 1, server_start_time: 1635131797, bytes_sent: 0,
2662021-10-25T03:16:37.427438Z 0 [Note] Generated uuid: 'f6f89137-3541-11ec-84bc-f29710c93c86', server_start_time: 281476611842454, bytes_sent: 94355589700272
2672021-10-25T03:16:37.427554Z 0 [Warning] No existing UUID has been found, so we assume that this is the first time that this server has been started. Generating a new UUID: f6f89137-3541-11ec-84bc-f29710c93c86.
2682021-10-25T03:16:38.109098Z 0 [Note] Auto generated SSL certificates are placed in data directory.
2692021-10-25T03:16:38.109327Z 0 [Warning] A deprecated TLS version TLSv1 is enabled. Please use TLSv1.2 or higher.
2702021-10-25T03:16:38.109395Z 0 [Warning] A deprecated TLS version TLSv1.1 is enabled. Please use TLSv1.2 or higher.
2712021-10-25T03:16:38.109907Z 0 [Warning] CA certificate ca.pem is self signed.
2722021-10-25T03:16:38.354105Z 0 [Note] Auto generated RSA key files are placed in data directory.
2732021-10-25T03:16:38.354795Z 0 [Note] Server hostname (bind-address): '*'; port: 3306
2742021-10-25T03:16:38.354968Z 0 [Note] IPv6 is available.
2752021-10-25T03:16:38.355039Z 0 [Note] - '::' resolves to '::';
2762021-10-25T03:16:38.355125Z 0 [Note] Server socket created on IP: '::'.
2772021-10-25T03:16:38.357907Z 0 [Warning] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory.
2782021-10-25T03:16:38.361720Z 0 [Note] Failed to start slave threads for channel ''
2792021-10-25T03:16:38.366691Z 0 [Note] Event Scheduler: Loaded 0 events
2802021-10-25T03:16:38.367135Z 0 [Note] mysqld: ready for connections.
281Version: '5.7.36' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server (GPL)
2822021-10-25T03:16:39.011694Z 3 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2832021-10-25T03:16:39.759020Z 5 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2842021-10-25T03:16:56.006754Z 7 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2852021-10-25T03:17:21.016988Z 9 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2862021-10-25T03:18:03.010443Z 11 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2872021-10-25T03:19:30.984929Z 13 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2882021-10-25T03:22:25.011291Z 15 [Note] Access denied for user 'root'@'localhost' (using password: NO)
289
UPDATE
What I have tried again is stripping down a lot of optional code(I think...), and here is the result:
1apiVersion: apps/v1
2kind: StatefulSet
3metadata:
4 name: mysql
5spec:
6 selector:
7 matchLabels:
8 app: mysql
9 serviceName: mysql
10 replicas: 3
11 template:
12 metadata:
13 labels:
14 app: mysql
15 spec:
16 initContainers:
17 - name: init-mysql
18 image: mysql:5.7
19 env:
20 - name: MYSQL_ROOT_PASSWORD
21 valueFrom:
22 secretKeyRef:
23 name: mysql-secret
24 key: mysql-root-password
25 command:
26 - bash
27 - "-c"
28 - |
29 set -ex
30 # Generate mysql server-id from pod ordinal index.
31 [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
32 ordinal=${BASH_REMATCH[1]}
33 echo [mysqld] > /mnt/conf.d/server-id.cnf
34 # Add an offset to avoid reserved server-id=0 value.
35 echo server-id=$((100 + $ordinal)) >> /mnt/conf.d/server-id.cnf
36 # Copy appropriate conf.d files from config-map to emptyDir.
37 if [[ $ordinal -eq 0 ]]; then
38 cp /mnt/config-map/primary.cnf /mnt/conf.d/
39 else
40 cp /mnt/config-map/replica.cnf /mnt/conf.d/
41 fi
42 volumeMounts:
43 - name: conf
44 mountPath: /mnt/conf.d
45 - name: config-map
46 mountPath: /mnt/config-map
47 - name: clone-mysql
48 image: gcr.io/google-samples/xtrabackup:1.0
49 command:
50 - bash
51 - "-c"
52 - |
53 set -ex
54 # Skip the clone if data already exists.
55 [[ -d /var/lib/mysql/mysql ]] && exit 0
56 # Skip the clone on primary (ordinal index 0).
57 [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
58 ordinal=${BASH_REMATCH[1]}
59 [[ $ordinal -eq 0 ]] && exit 0
60 # Clone data from previous peer.
61 ncat --recv-only mysql-$(($ordinal-1)).mysql 3307 | xbstream -x -C /var/lib/mysql
62 # Prepare the backup.
63 xtrabackup --prepare --target-dir=/var/lib/mysql
64 volumeMounts:
65 - name: data
66 mountPath: /var/lib/mysql
67 subPath: mysql
68 - name: conf
69 mountPath: /etc/mysql/conf.d
70 containers:
71 - name: mysql
72 image: mysql:5.7
73 env:
74 - name: MYSQL_ROOT_PASSWORD
75 valueFrom:
76 secretKeyRef:
77 name: mysql-secret
78 key: mysql-root-password
79 ports:
80 - name: mysql
81 containerPort: 3306
82 volumeMounts:
83 - name: data
84 mountPath: /var/lib/mysql
85 subPath: mysql
86 - name: conf
87 mountPath: /etc/mysql/conf.d
88 resources:
89 requests:
90 cpu: 100m
91 memory: 500Mi
92 - name: xtrabackup
93 image: gcr.io/google-samples/xtrabackup:1.0
94 env:
95 - name: MYSQL_ROOT_PASSWORD
96 valueFrom:
97 secretKeyRef:
98 name: mysql-secret
99 key: mysql-root-password
100 ports:
101 - name: xtrabackup
102 containerPort: 3307
103 command:
104 - bash
105 - "-c"
106 - |
107 set -ex
108 cd /var/lib/mysql
109
110 # Determine binlog position of cloned data, if any.
111 if [[ -f xtrabackup_slave_info && "x$(<xtrabackup_slave_info)" != "x" ]]; then
112 # XtraBackup already generated a partial "CHANGE MASTER TO" query
113 # because we're cloning from an existing replica. (Need to remove the tailing semicolon!)
114 cat xtrabackup_slave_info | sed -E 's/;$//g' > change_master_to.sql.in
115 # Ignore xtrabackup_binlog_info in this case (it's useless).
116 rm -f xtrabackup_slave_info xtrabackup_binlog_info
117 elif [[ -f xtrabackup_binlog_info ]]; then
118 # We're cloning directly from primary. Parse binlog position.
119 [[ `cat xtrabackup_binlog_info` =~ ^(.*?)[[:space:]]+(.*?)$ ]] || exit 1
120 rm -f xtrabackup_binlog_info xtrabackup_slave_info
121 echo "CHANGE MASTER TO MASTER_LOG_FILE='${BASH_REMATCH[1]}',\
122 MASTER_LOG_POS=${BASH_REMATCH[2]}" > change_master_to.sql.in
123 fi
124
125 # Check if we need to complete a clone by starting replication.
126 if [[ -f change_master_to.sql.in ]]; then
127 echo "Waiting for mysqld to be ready (accepting connections)"
128 until mysql -h 127.0.0.1 -uroot -p$MYSQL_ROOT_PASSWORD -e "SELECT 1"; do sleep 1; done
129
130 echo "Initializing replication from clone position"
131 mysql -h 127.0.0.1 \
132 -e "$(<change_master_to.sql.in), \
133 MASTER_HOST='mysql-0.mysql', \
134 MASTER_USER='root', \
135 MASTER_PASSWORD=$MYSQL_ROOT_PASSWORD, \
136 MASTER_CONNECT_RETRY=10; \
137 START SLAVE USER='root' PASSWORD=$MYSQL_ROOT_PASSWORD;" || exit 1
138 # In case of container restart, attempt this at-most-once.
139 mv change_master_to.sql.in change_master_to.sql.orig
140 fi
141
142 # Start a server to send backups when requested by peers.
143 exec ncat --listen --keep-open --send-only --max-conns=1 3307 -c \
144 "xtrabackup --backup --slave-info --stream=xbstream --host=127.0.0.1 --user=root --password=$MYSQL_ROOT_PASSWORD"
145 volumeMounts:
146 - name: data
147 mountPath: /var/lib/mysql
148 subPath: mysql
149 - name: conf
150 mountPath: /etc/mysql/conf.d
151 resources:
152 requests:
153 cpu: 50m
154 memory: 50Mi
155 volumes:
156 - name: conf
157 emptyDir: {}
158 - name: config-map
159 configMap:
160 name: mysql
161 volumeClaimTemplates:
162 - metadata:
163 name: data
164 spec:
165 accessModes: ["ReadWriteOnce"]
166 resources:
167 requests:
168 storage: 10Gi
169NAME READY STATUS RESTARTS AGE
170pod/mysql-0 2/2 Running 0 11m
171pod/mysql-1 1/2 Error 7 11m
172pod/mysql-2 0/2 Init:CrashLoopBackOff 6 10m
173
174NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
175service/kubernetes ClusterIP 10.245.0.1 <none> 443/TCP 2d23h
176service/mysql ClusterIP None <none> 3306/TCP 43h
177service/mysql-read ClusterIP 10.245.81.173 <none> 3306/TCP 43h
178
179NAME READY UP-TO-DATE AVAILABLE AGE
180deployment.apps/phpmyadmin 1/1 1 1 2d18h
181
182NAME DESIRED CURRENT READY AGE
183replicaset.apps/phpmyadmin-6c57fd98bf 1 1 1 2d18h
184
185NAME READY AGE
186statefulset.apps/mysql 1/3 11m
187
188NAME TYPE DATA AGE
189secret/mysql-pass Opaque 1 46h
190secret/mysql-secret Opaque 3 2d18h
191
192NAME DATA AGE
193configmap/mysql 4 2d18h
194ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)
195 - name: MYSQL_ROOT_HOST
196 value: "%"
197NAME READY STATUS RESTARTS AGE
198mysql-0 0/2 Init:0/2 0 7s
199mysql-0 0/2 Init:1/2 0 18s
200mysql-0 0/2 PodInitializing 0 19s
201mysql-0 2/2 Running 0 20s
202mysql-1 0/2 Pending 0 0s
203mysql-1 0/2 Pending 0 0s
204mysql-1 0/2 Pending 0 8s
205mysql-1 0/2 Init:0/2 0 8s
206mysql-1 0/2 Init:1/2 0 26s
207mysql-1 0/2 Init:1/2 0 27s
208mysql-1 0/2 PodInitializing 0 34s
209mysql-1 2/2 Running 0 35s
210mysql-2 0/2 Pending 0 0s
211mysql-2 0/2 Pending 0 0s
212mysql-1 1/2 Error 0 37s
213mysql-1 1/2 Error 1 38s
214mysql-2 0/2 Pending 0 3s
215mysql-2 0/2 Init:0/2 0 3s
216mysql-1 1/2 CrashLoopBackOff 1 53s
217mysql-1 1/2 Error 2 54s
218mysql-2 0/2 Init:1/2 0 21s
219mysql-2 0/2 Init:Error 0 22s
220mysql-2 0/2 Init:Error 1 23s
221mysql-2 0/2 Init:CrashLoopBackOff 1 24s
222mysql-1 1/2 CrashLoopBackOff 2 64s
223mysql-2 0/2 Init:Error 2 38s
224mysql-1 1/2 Error 3 79s
225mysql-2 0/2 Init:CrashLoopBackOff 2 50s
226mysql-1 1/2 CrashLoopBackOff 3 92s
227mysql-2 0/2 Init:Error 3 62s
228mysql-2 0/2 Init:CrashLoopBackOff 3 74s
229mysql-1 1/2 Error 4 2m1s
230mysql-1 1/2 CrashLoopBackOff 4 2m11s
231mysql-2 0/2 Init:Error 4 113s
232mysql-2 0/2 Init:CrashLoopBackOff 4 2m6s
233mysql-1 1/2 Error 5 3m29s
234mysql-1 1/2 CrashLoopBackOff 5 3m41s
235mysql-2 0/2 Init:Error 5 3m23s
236mysql-2 0/2 Init:CrashLoopBackOff 5 3m34s
2372021-10-25 03:16:36+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.36-1debian10 started.
2382021-10-25 03:16:36+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
2392021-10-25 03:16:36+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.36-1debian10 started.
2402021-10-25T03:16:37.231906Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
2412021-10-25T03:16:37.234015Z 0 [Note] mysqld (mysqld 5.7.36) starting as process 1 ...
2422021-10-25T03:16:37.237044Z 0 [Note] InnoDB: PUNCH HOLE support available
2432021-10-25T03:16:37.237196Z 0 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
2442021-10-25T03:16:37.237263Z 0 [Note] InnoDB: Uses event mutexes
2452021-10-25T03:16:37.237345Z 0 [Note] InnoDB: GCC builtin __atomic_thread_fence() is used for memory barrier
2462021-10-25T03:16:37.237416Z 0 [Note] InnoDB: Compressed tables use zlib 1.2.11
2472021-10-25T03:16:37.237489Z 0 [Note] InnoDB: Using Linux native AIO
2482021-10-25T03:16:37.237792Z 0 [Note] InnoDB: Number of pools: 1
2492021-10-25T03:16:37.238102Z 0 [Note] InnoDB: Using CPU crc32 instructions
2502021-10-25T03:16:37.240179Z 0 [Note] InnoDB: Initializing buffer pool, total size = 128M, instances = 1, chunk size = 128M
2512021-10-25T03:16:37.248111Z 0 [Note] InnoDB: Completed initialization of buffer pool
2522021-10-25T03:16:37.251017Z 0 [Note] InnoDB: If the mysqld execution user is authorized, page cleaner thread priority can be changed. See the man page of setpriority().
2532021-10-25T03:16:37.263519Z 0 [Note] InnoDB: Highest supported file format is Barracuda.
2542021-10-25T03:16:37.307064Z 0 [Note] InnoDB: Removed temporary tablespace data file: "ibtmp1"
2552021-10-25T03:16:37.307319Z 0 [Note] InnoDB: Creating shared tablespace for temporary tables
2562021-10-25T03:16:37.307466Z 0 [Note] InnoDB: Setting file './ibtmp1' size to 12 MB. Physically writing the file full; Please wait ...
2572021-10-25T03:16:37.353707Z 0 [Note] InnoDB: File './ibtmp1' size is now 12 MB.
2582021-10-25T03:16:37.354244Z 0 [Note] InnoDB: 96 redo rollback segment(s) found. 96 redo rollback segment(s) are active.
2592021-10-25T03:16:37.354256Z 0 [Note] InnoDB: 32 non-redo rollback segment(s) are active.
2602021-10-25T03:16:37.355048Z 0 [Note] InnoDB: Waiting for purge to start
2612021-10-25T03:16:37.406335Z 0 [Note] InnoDB: 5.7.36 started; log sequence number 12660776
2622021-10-25T03:16:37.406850Z 0 [Note] Plugin 'FEDERATED' is disabled.
2632021-10-25T03:16:37.413880Z 0 [Note] InnoDB: Loading buffer pool(s) from /var/lib/mysql/ib_buffer_pool
2642021-10-25T03:16:37.426491Z 0 [Note] InnoDB: Buffer pool(s) load completed at 211025 3:16:37
2652021-10-25T03:16:37.427210Z 0 [Note] Salting uuid generator variables, current_pid: 1, server_start_time: 1635131797, bytes_sent: 0,
2662021-10-25T03:16:37.427438Z 0 [Note] Generated uuid: 'f6f89137-3541-11ec-84bc-f29710c93c86', server_start_time: 281476611842454, bytes_sent: 94355589700272
2672021-10-25T03:16:37.427554Z 0 [Warning] No existing UUID has been found, so we assume that this is the first time that this server has been started. Generating a new UUID: f6f89137-3541-11ec-84bc-f29710c93c86.
2682021-10-25T03:16:38.109098Z 0 [Note] Auto generated SSL certificates are placed in data directory.
2692021-10-25T03:16:38.109327Z 0 [Warning] A deprecated TLS version TLSv1 is enabled. Please use TLSv1.2 or higher.
2702021-10-25T03:16:38.109395Z 0 [Warning] A deprecated TLS version TLSv1.1 is enabled. Please use TLSv1.2 or higher.
2712021-10-25T03:16:38.109907Z 0 [Warning] CA certificate ca.pem is self signed.
2722021-10-25T03:16:38.354105Z 0 [Note] Auto generated RSA key files are placed in data directory.
2732021-10-25T03:16:38.354795Z 0 [Note] Server hostname (bind-address): '*'; port: 3306
2742021-10-25T03:16:38.354968Z 0 [Note] IPv6 is available.
2752021-10-25T03:16:38.355039Z 0 [Note] - '::' resolves to '::';
2762021-10-25T03:16:38.355125Z 0 [Note] Server socket created on IP: '::'.
2772021-10-25T03:16:38.357907Z 0 [Warning] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory.
2782021-10-25T03:16:38.361720Z 0 [Note] Failed to start slave threads for channel ''
2792021-10-25T03:16:38.366691Z 0 [Note] Event Scheduler: Loaded 0 events
2802021-10-25T03:16:38.367135Z 0 [Note] mysqld: ready for connections.
281Version: '5.7.36' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server (GPL)
2822021-10-25T03:16:39.011694Z 3 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2832021-10-25T03:16:39.759020Z 5 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2842021-10-25T03:16:56.006754Z 7 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2852021-10-25T03:17:21.016988Z 9 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2862021-10-25T03:18:03.010443Z 11 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2872021-10-25T03:19:30.984929Z 13 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2882021-10-25T03:22:25.011291Z 15 [Note] Access denied for user 'root'@'localhost' (using password: NO)
289apiVersion: apps/v1
290kind: StatefulSet
291metadata:
292 name: mysql
293spec:
294 selector:
295 matchLabels:
296 app: mysql
297 serviceName: mysql
298 replicas: 3
299 template:
300 metadata:
301 labels:
302 app: mysql
303 spec:
304 initContainers:
305 - name: init-mysql
306 image: mysql:5.7
307 env:
308 - name: MYSQL_ROOT_PASSWORD
309 value: admin123
310 command:
311 - bash
312 - "-c"
313 - |
314 set -ex
315 # Generate mysql server-id from pod ordinal index.
316 [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
317 ordinal=${BASH_REMATCH[1]}
318 echo [mysqld] > /mnt/conf.d/server-id.cnf
319 # Add an offset to avoid reserved server-id=0 value.
320 echo server-id=$((100 + $ordinal)) >> /mnt/conf.d/server-id.cnf
321 # Copy appropriate conf.d files from config-map to emptyDir.
322 if [[ $ordinal -eq 0 ]]; then
323 cp /mnt/config-map/primary.cnf /mnt/conf.d/
324 else
325 cp /mnt/config-map/replica.cnf /mnt/conf.d/
326 fi
327 volumeMounts:
328 - name: conf
329 mountPath: /mnt/conf.d
330 - name: config-map
331 mountPath: /mnt/config-map
332 containers:
333 - name: mysql
334 image: mysql:5.7
335 env:
336 - name: MYSQL_ROOT_PASSWORD
337 value: admin123
338 ports:
339 - name: mysql
340 containerPort: 3306
341 volumeMounts:
342 - name: data
343 mountPath: /var/lib/mysql
344 subPath: mysql
345 - name: conf
346 mountPath: /etc/mysql/conf.d
347 resources:
348 requests:
349 cpu: 100m
350 memory: 500Mi
351 volumes:
352 - name: conf
353 emptyDir: {}
354 - name: config-map
355 configMap:
356 name: mysql
357 volumeClaimTemplates:
358 - metadata:
359 name: data
360 spec:
361 accessModes: ["ReadWriteOnce"]
362 resources:
363 requests:
364 storage: 10Gi
365
From the yaml above, the master pod is running without a problem, but for the slave pods, the process is pretty normal until it ran for a while, then they encountered an error. After that, the state went back to running again. I checked the error from the logs and turned out that they could not authenticate mysql using the user root and the root password that I've set, so they tried authenticating mysql using the user root with no password specified and succeeded. That's weird because I've set the env variables MYSQL_ROOT_PASSWORD
already inside the initContainers
and the containers
themselves, so I tried to exec
each of the slave pods. I ran echo $MYSQL_ROOT_PASSWORD
and the result is the same as I have specified. So the problem now from the yaml above is the env variable that I've set on the yaml file did not penetrate through the mysql application, but only through the container's environmental system.
ANSWER
Answered 2021-Oct-28 at 03:33I have solved the problem. Turns out I tweaked some of my first uploaded code because there was a syntax error and typos:
1apiVersion: apps/v1
2kind: StatefulSet
3metadata:
4 name: mysql
5spec:
6 selector:
7 matchLabels:
8 app: mysql
9 serviceName: mysql
10 replicas: 3
11 template:
12 metadata:
13 labels:
14 app: mysql
15 spec:
16 initContainers:
17 - name: init-mysql
18 image: mysql:5.7
19 env:
20 - name: MYSQL_ROOT_PASSWORD
21 valueFrom:
22 secretKeyRef:
23 name: mysql-secret
24 key: mysql-root-password
25 command:
26 - bash
27 - "-c"
28 - |
29 set -ex
30 # Generate mysql server-id from pod ordinal index.
31 [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
32 ordinal=${BASH_REMATCH[1]}
33 echo [mysqld] > /mnt/conf.d/server-id.cnf
34 # Add an offset to avoid reserved server-id=0 value.
35 echo server-id=$((100 + $ordinal)) >> /mnt/conf.d/server-id.cnf
36 # Copy appropriate conf.d files from config-map to emptyDir.
37 if [[ $ordinal -eq 0 ]]; then
38 cp /mnt/config-map/primary.cnf /mnt/conf.d/
39 else
40 cp /mnt/config-map/replica.cnf /mnt/conf.d/
41 fi
42 volumeMounts:
43 - name: conf
44 mountPath: /mnt/conf.d
45 - name: config-map
46 mountPath: /mnt/config-map
47 - name: clone-mysql
48 image: gcr.io/google-samples/xtrabackup:1.0
49 command:
50 - bash
51 - "-c"
52 - |
53 set -ex
54 # Skip the clone if data already exists.
55 [[ -d /var/lib/mysql/mysql ]] && exit 0
56 # Skip the clone on primary (ordinal index 0).
57 [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
58 ordinal=${BASH_REMATCH[1]}
59 [[ $ordinal -eq 0 ]] && exit 0
60 # Clone data from previous peer.
61 ncat --recv-only mysql-$(($ordinal-1)).mysql 3307 | xbstream -x -C /var/lib/mysql
62 # Prepare the backup.
63 xtrabackup --prepare --target-dir=/var/lib/mysql
64 volumeMounts:
65 - name: data
66 mountPath: /var/lib/mysql
67 subPath: mysql
68 - name: conf
69 mountPath: /etc/mysql/conf.d
70 containers:
71 - name: mysql
72 image: mysql:5.7
73 env:
74 - name: MYSQL_ROOT_PASSWORD
75 valueFrom:
76 secretKeyRef:
77 name: mysql-secret
78 key: mysql-root-password
79 ports:
80 - name: mysql
81 containerPort: 3306
82 volumeMounts:
83 - name: data
84 mountPath: /var/lib/mysql
85 subPath: mysql
86 - name: conf
87 mountPath: /etc/mysql/conf.d
88 resources:
89 requests:
90 cpu: 100m
91 memory: 500Mi
92 - name: xtrabackup
93 image: gcr.io/google-samples/xtrabackup:1.0
94 env:
95 - name: MYSQL_ROOT_PASSWORD
96 valueFrom:
97 secretKeyRef:
98 name: mysql-secret
99 key: mysql-root-password
100 ports:
101 - name: xtrabackup
102 containerPort: 3307
103 command:
104 - bash
105 - "-c"
106 - |
107 set -ex
108 cd /var/lib/mysql
109
110 # Determine binlog position of cloned data, if any.
111 if [[ -f xtrabackup_slave_info && "x$(<xtrabackup_slave_info)" != "x" ]]; then
112 # XtraBackup already generated a partial "CHANGE MASTER TO" query
113 # because we're cloning from an existing replica. (Need to remove the tailing semicolon!)
114 cat xtrabackup_slave_info | sed -E 's/;$//g' > change_master_to.sql.in
115 # Ignore xtrabackup_binlog_info in this case (it's useless).
116 rm -f xtrabackup_slave_info xtrabackup_binlog_info
117 elif [[ -f xtrabackup_binlog_info ]]; then
118 # We're cloning directly from primary. Parse binlog position.
119 [[ `cat xtrabackup_binlog_info` =~ ^(.*?)[[:space:]]+(.*?)$ ]] || exit 1
120 rm -f xtrabackup_binlog_info xtrabackup_slave_info
121 echo "CHANGE MASTER TO MASTER_LOG_FILE='${BASH_REMATCH[1]}',\
122 MASTER_LOG_POS=${BASH_REMATCH[2]}" > change_master_to.sql.in
123 fi
124
125 # Check if we need to complete a clone by starting replication.
126 if [[ -f change_master_to.sql.in ]]; then
127 echo "Waiting for mysqld to be ready (accepting connections)"
128 until mysql -h 127.0.0.1 -uroot -p$MYSQL_ROOT_PASSWORD -e "SELECT 1"; do sleep 1; done
129
130 echo "Initializing replication from clone position"
131 mysql -h 127.0.0.1 \
132 -e "$(<change_master_to.sql.in), \
133 MASTER_HOST='mysql-0.mysql', \
134 MASTER_USER='root', \
135 MASTER_PASSWORD=$MYSQL_ROOT_PASSWORD, \
136 MASTER_CONNECT_RETRY=10; \
137 START SLAVE USER='root' PASSWORD=$MYSQL_ROOT_PASSWORD;" || exit 1
138 # In case of container restart, attempt this at-most-once.
139 mv change_master_to.sql.in change_master_to.sql.orig
140 fi
141
142 # Start a server to send backups when requested by peers.
143 exec ncat --listen --keep-open --send-only --max-conns=1 3307 -c \
144 "xtrabackup --backup --slave-info --stream=xbstream --host=127.0.0.1 --user=root --password=$MYSQL_ROOT_PASSWORD"
145 volumeMounts:
146 - name: data
147 mountPath: /var/lib/mysql
148 subPath: mysql
149 - name: conf
150 mountPath: /etc/mysql/conf.d
151 resources:
152 requests:
153 cpu: 50m
154 memory: 50Mi
155 volumes:
156 - name: conf
157 emptyDir: {}
158 - name: config-map
159 configMap:
160 name: mysql
161 volumeClaimTemplates:
162 - metadata:
163 name: data
164 spec:
165 accessModes: ["ReadWriteOnce"]
166 resources:
167 requests:
168 storage: 10Gi
169NAME READY STATUS RESTARTS AGE
170pod/mysql-0 2/2 Running 0 11m
171pod/mysql-1 1/2 Error 7 11m
172pod/mysql-2 0/2 Init:CrashLoopBackOff 6 10m
173
174NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
175service/kubernetes ClusterIP 10.245.0.1 <none> 443/TCP 2d23h
176service/mysql ClusterIP None <none> 3306/TCP 43h
177service/mysql-read ClusterIP 10.245.81.173 <none> 3306/TCP 43h
178
179NAME READY UP-TO-DATE AVAILABLE AGE
180deployment.apps/phpmyadmin 1/1 1 1 2d18h
181
182NAME DESIRED CURRENT READY AGE
183replicaset.apps/phpmyadmin-6c57fd98bf 1 1 1 2d18h
184
185NAME READY AGE
186statefulset.apps/mysql 1/3 11m
187
188NAME TYPE DATA AGE
189secret/mysql-pass Opaque 1 46h
190secret/mysql-secret Opaque 3 2d18h
191
192NAME DATA AGE
193configmap/mysql 4 2d18h
194ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)
195 - name: MYSQL_ROOT_HOST
196 value: "%"
197NAME READY STATUS RESTARTS AGE
198mysql-0 0/2 Init:0/2 0 7s
199mysql-0 0/2 Init:1/2 0 18s
200mysql-0 0/2 PodInitializing 0 19s
201mysql-0 2/2 Running 0 20s
202mysql-1 0/2 Pending 0 0s
203mysql-1 0/2 Pending 0 0s
204mysql-1 0/2 Pending 0 8s
205mysql-1 0/2 Init:0/2 0 8s
206mysql-1 0/2 Init:1/2 0 26s
207mysql-1 0/2 Init:1/2 0 27s
208mysql-1 0/2 PodInitializing 0 34s
209mysql-1 2/2 Running 0 35s
210mysql-2 0/2 Pending 0 0s
211mysql-2 0/2 Pending 0 0s
212mysql-1 1/2 Error 0 37s
213mysql-1 1/2 Error 1 38s
214mysql-2 0/2 Pending 0 3s
215mysql-2 0/2 Init:0/2 0 3s
216mysql-1 1/2 CrashLoopBackOff 1 53s
217mysql-1 1/2 Error 2 54s
218mysql-2 0/2 Init:1/2 0 21s
219mysql-2 0/2 Init:Error 0 22s
220mysql-2 0/2 Init:Error 1 23s
221mysql-2 0/2 Init:CrashLoopBackOff 1 24s
222mysql-1 1/2 CrashLoopBackOff 2 64s
223mysql-2 0/2 Init:Error 2 38s
224mysql-1 1/2 Error 3 79s
225mysql-2 0/2 Init:CrashLoopBackOff 2 50s
226mysql-1 1/2 CrashLoopBackOff 3 92s
227mysql-2 0/2 Init:Error 3 62s
228mysql-2 0/2 Init:CrashLoopBackOff 3 74s
229mysql-1 1/2 Error 4 2m1s
230mysql-1 1/2 CrashLoopBackOff 4 2m11s
231mysql-2 0/2 Init:Error 4 113s
232mysql-2 0/2 Init:CrashLoopBackOff 4 2m6s
233mysql-1 1/2 Error 5 3m29s
234mysql-1 1/2 CrashLoopBackOff 5 3m41s
235mysql-2 0/2 Init:Error 5 3m23s
236mysql-2 0/2 Init:CrashLoopBackOff 5 3m34s
2372021-10-25 03:16:36+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.36-1debian10 started.
2382021-10-25 03:16:36+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
2392021-10-25 03:16:36+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.36-1debian10 started.
2402021-10-25T03:16:37.231906Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
2412021-10-25T03:16:37.234015Z 0 [Note] mysqld (mysqld 5.7.36) starting as process 1 ...
2422021-10-25T03:16:37.237044Z 0 [Note] InnoDB: PUNCH HOLE support available
2432021-10-25T03:16:37.237196Z 0 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
2442021-10-25T03:16:37.237263Z 0 [Note] InnoDB: Uses event mutexes
2452021-10-25T03:16:37.237345Z 0 [Note] InnoDB: GCC builtin __atomic_thread_fence() is used for memory barrier
2462021-10-25T03:16:37.237416Z 0 [Note] InnoDB: Compressed tables use zlib 1.2.11
2472021-10-25T03:16:37.237489Z 0 [Note] InnoDB: Using Linux native AIO
2482021-10-25T03:16:37.237792Z 0 [Note] InnoDB: Number of pools: 1
2492021-10-25T03:16:37.238102Z 0 [Note] InnoDB: Using CPU crc32 instructions
2502021-10-25T03:16:37.240179Z 0 [Note] InnoDB: Initializing buffer pool, total size = 128M, instances = 1, chunk size = 128M
2512021-10-25T03:16:37.248111Z 0 [Note] InnoDB: Completed initialization of buffer pool
2522021-10-25T03:16:37.251017Z 0 [Note] InnoDB: If the mysqld execution user is authorized, page cleaner thread priority can be changed. See the man page of setpriority().
2532021-10-25T03:16:37.263519Z 0 [Note] InnoDB: Highest supported file format is Barracuda.
2542021-10-25T03:16:37.307064Z 0 [Note] InnoDB: Removed temporary tablespace data file: "ibtmp1"
2552021-10-25T03:16:37.307319Z 0 [Note] InnoDB: Creating shared tablespace for temporary tables
2562021-10-25T03:16:37.307466Z 0 [Note] InnoDB: Setting file './ibtmp1' size to 12 MB. Physically writing the file full; Please wait ...
2572021-10-25T03:16:37.353707Z 0 [Note] InnoDB: File './ibtmp1' size is now 12 MB.
2582021-10-25T03:16:37.354244Z 0 [Note] InnoDB: 96 redo rollback segment(s) found. 96 redo rollback segment(s) are active.
2592021-10-25T03:16:37.354256Z 0 [Note] InnoDB: 32 non-redo rollback segment(s) are active.
2602021-10-25T03:16:37.355048Z 0 [Note] InnoDB: Waiting for purge to start
2612021-10-25T03:16:37.406335Z 0 [Note] InnoDB: 5.7.36 started; log sequence number 12660776
2622021-10-25T03:16:37.406850Z 0 [Note] Plugin 'FEDERATED' is disabled.
2632021-10-25T03:16:37.413880Z 0 [Note] InnoDB: Loading buffer pool(s) from /var/lib/mysql/ib_buffer_pool
2642021-10-25T03:16:37.426491Z 0 [Note] InnoDB: Buffer pool(s) load completed at 211025 3:16:37
2652021-10-25T03:16:37.427210Z 0 [Note] Salting uuid generator variables, current_pid: 1, server_start_time: 1635131797, bytes_sent: 0,
2662021-10-25T03:16:37.427438Z 0 [Note] Generated uuid: 'f6f89137-3541-11ec-84bc-f29710c93c86', server_start_time: 281476611842454, bytes_sent: 94355589700272
2672021-10-25T03:16:37.427554Z 0 [Warning] No existing UUID has been found, so we assume that this is the first time that this server has been started. Generating a new UUID: f6f89137-3541-11ec-84bc-f29710c93c86.
2682021-10-25T03:16:38.109098Z 0 [Note] Auto generated SSL certificates are placed in data directory.
2692021-10-25T03:16:38.109327Z 0 [Warning] A deprecated TLS version TLSv1 is enabled. Please use TLSv1.2 or higher.
2702021-10-25T03:16:38.109395Z 0 [Warning] A deprecated TLS version TLSv1.1 is enabled. Please use TLSv1.2 or higher.
2712021-10-25T03:16:38.109907Z 0 [Warning] CA certificate ca.pem is self signed.
2722021-10-25T03:16:38.354105Z 0 [Note] Auto generated RSA key files are placed in data directory.
2732021-10-25T03:16:38.354795Z 0 [Note] Server hostname (bind-address): '*'; port: 3306
2742021-10-25T03:16:38.354968Z 0 [Note] IPv6 is available.
2752021-10-25T03:16:38.355039Z 0 [Note] - '::' resolves to '::';
2762021-10-25T03:16:38.355125Z 0 [Note] Server socket created on IP: '::'.
2772021-10-25T03:16:38.357907Z 0 [Warning] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory.
2782021-10-25T03:16:38.361720Z 0 [Note] Failed to start slave threads for channel ''
2792021-10-25T03:16:38.366691Z 0 [Note] Event Scheduler: Loaded 0 events
2802021-10-25T03:16:38.367135Z 0 [Note] mysqld: ready for connections.
281Version: '5.7.36' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server (GPL)
2822021-10-25T03:16:39.011694Z 3 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2832021-10-25T03:16:39.759020Z 5 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2842021-10-25T03:16:56.006754Z 7 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2852021-10-25T03:17:21.016988Z 9 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2862021-10-25T03:18:03.010443Z 11 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2872021-10-25T03:19:30.984929Z 13 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2882021-10-25T03:22:25.011291Z 15 [Note] Access denied for user 'root'@'localhost' (using password: NO)
289apiVersion: apps/v1
290kind: StatefulSet
291metadata:
292 name: mysql
293spec:
294 selector:
295 matchLabels:
296 app: mysql
297 serviceName: mysql
298 replicas: 3
299 template:
300 metadata:
301 labels:
302 app: mysql
303 spec:
304 initContainers:
305 - name: init-mysql
306 image: mysql:5.7
307 env:
308 - name: MYSQL_ROOT_PASSWORD
309 value: admin123
310 command:
311 - bash
312 - "-c"
313 - |
314 set -ex
315 # Generate mysql server-id from pod ordinal index.
316 [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
317 ordinal=${BASH_REMATCH[1]}
318 echo [mysqld] > /mnt/conf.d/server-id.cnf
319 # Add an offset to avoid reserved server-id=0 value.
320 echo server-id=$((100 + $ordinal)) >> /mnt/conf.d/server-id.cnf
321 # Copy appropriate conf.d files from config-map to emptyDir.
322 if [[ $ordinal -eq 0 ]]; then
323 cp /mnt/config-map/primary.cnf /mnt/conf.d/
324 else
325 cp /mnt/config-map/replica.cnf /mnt/conf.d/
326 fi
327 volumeMounts:
328 - name: conf
329 mountPath: /mnt/conf.d
330 - name: config-map
331 mountPath: /mnt/config-map
332 containers:
333 - name: mysql
334 image: mysql:5.7
335 env:
336 - name: MYSQL_ROOT_PASSWORD
337 value: admin123
338 ports:
339 - name: mysql
340 containerPort: 3306
341 volumeMounts:
342 - name: data
343 mountPath: /var/lib/mysql
344 subPath: mysql
345 - name: conf
346 mountPath: /etc/mysql/conf.d
347 resources:
348 requests:
349 cpu: 100m
350 memory: 500Mi
351 volumes:
352 - name: conf
353 emptyDir: {}
354 - name: config-map
355 configMap:
356 name: mysql
357 volumeClaimTemplates:
358 - metadata:
359 name: data
360 spec:
361 accessModes: ["ReadWriteOnce"]
362 resources:
363 requests:
364 storage: 10Gi
365$MYSQL_ROOT_PASSWORD ==> $(MYSQL_ROOT_PASSWORD)
366#when calling env var inside command, you have to add the brackets
367
1apiVersion: apps/v1
2kind: StatefulSet
3metadata:
4 name: mysql
5spec:
6 selector:
7 matchLabels:
8 app: mysql
9 serviceName: mysql
10 replicas: 3
11 template:
12 metadata:
13 labels:
14 app: mysql
15 spec:
16 initContainers:
17 - name: init-mysql
18 image: mysql:5.7
19 env:
20 - name: MYSQL_ROOT_PASSWORD
21 valueFrom:
22 secretKeyRef:
23 name: mysql-secret
24 key: mysql-root-password
25 command:
26 - bash
27 - "-c"
28 - |
29 set -ex
30 # Generate mysql server-id from pod ordinal index.
31 [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
32 ordinal=${BASH_REMATCH[1]}
33 echo [mysqld] > /mnt/conf.d/server-id.cnf
34 # Add an offset to avoid reserved server-id=0 value.
35 echo server-id=$((100 + $ordinal)) >> /mnt/conf.d/server-id.cnf
36 # Copy appropriate conf.d files from config-map to emptyDir.
37 if [[ $ordinal -eq 0 ]]; then
38 cp /mnt/config-map/primary.cnf /mnt/conf.d/
39 else
40 cp /mnt/config-map/replica.cnf /mnt/conf.d/
41 fi
42 volumeMounts:
43 - name: conf
44 mountPath: /mnt/conf.d
45 - name: config-map
46 mountPath: /mnt/config-map
47 - name: clone-mysql
48 image: gcr.io/google-samples/xtrabackup:1.0
49 command:
50 - bash
51 - "-c"
52 - |
53 set -ex
54 # Skip the clone if data already exists.
55 [[ -d /var/lib/mysql/mysql ]] && exit 0
56 # Skip the clone on primary (ordinal index 0).
57 [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
58 ordinal=${BASH_REMATCH[1]}
59 [[ $ordinal -eq 0 ]] && exit 0
60 # Clone data from previous peer.
61 ncat --recv-only mysql-$(($ordinal-1)).mysql 3307 | xbstream -x -C /var/lib/mysql
62 # Prepare the backup.
63 xtrabackup --prepare --target-dir=/var/lib/mysql
64 volumeMounts:
65 - name: data
66 mountPath: /var/lib/mysql
67 subPath: mysql
68 - name: conf
69 mountPath: /etc/mysql/conf.d
70 containers:
71 - name: mysql
72 image: mysql:5.7
73 env:
74 - name: MYSQL_ROOT_PASSWORD
75 valueFrom:
76 secretKeyRef:
77 name: mysql-secret
78 key: mysql-root-password
79 ports:
80 - name: mysql
81 containerPort: 3306
82 volumeMounts:
83 - name: data
84 mountPath: /var/lib/mysql
85 subPath: mysql
86 - name: conf
87 mountPath: /etc/mysql/conf.d
88 resources:
89 requests:
90 cpu: 100m
91 memory: 500Mi
92 - name: xtrabackup
93 image: gcr.io/google-samples/xtrabackup:1.0
94 env:
95 - name: MYSQL_ROOT_PASSWORD
96 valueFrom:
97 secretKeyRef:
98 name: mysql-secret
99 key: mysql-root-password
100 ports:
101 - name: xtrabackup
102 containerPort: 3307
103 command:
104 - bash
105 - "-c"
106 - |
107 set -ex
108 cd /var/lib/mysql
109
110 # Determine binlog position of cloned data, if any.
111 if [[ -f xtrabackup_slave_info && "x$(<xtrabackup_slave_info)" != "x" ]]; then
112 # XtraBackup already generated a partial "CHANGE MASTER TO" query
113 # because we're cloning from an existing replica. (Need to remove the tailing semicolon!)
114 cat xtrabackup_slave_info | sed -E 's/;$//g' > change_master_to.sql.in
115 # Ignore xtrabackup_binlog_info in this case (it's useless).
116 rm -f xtrabackup_slave_info xtrabackup_binlog_info
117 elif [[ -f xtrabackup_binlog_info ]]; then
118 # We're cloning directly from primary. Parse binlog position.
119 [[ `cat xtrabackup_binlog_info` =~ ^(.*?)[[:space:]]+(.*?)$ ]] || exit 1
120 rm -f xtrabackup_binlog_info xtrabackup_slave_info
121 echo "CHANGE MASTER TO MASTER_LOG_FILE='${BASH_REMATCH[1]}',\
122 MASTER_LOG_POS=${BASH_REMATCH[2]}" > change_master_to.sql.in
123 fi
124
125 # Check if we need to complete a clone by starting replication.
126 if [[ -f change_master_to.sql.in ]]; then
127 echo "Waiting for mysqld to be ready (accepting connections)"
128 until mysql -h 127.0.0.1 -uroot -p$MYSQL_ROOT_PASSWORD -e "SELECT 1"; do sleep 1; done
129
130 echo "Initializing replication from clone position"
131 mysql -h 127.0.0.1 \
132 -e "$(<change_master_to.sql.in), \
133 MASTER_HOST='mysql-0.mysql', \
134 MASTER_USER='root', \
135 MASTER_PASSWORD=$MYSQL_ROOT_PASSWORD, \
136 MASTER_CONNECT_RETRY=10; \
137 START SLAVE USER='root' PASSWORD=$MYSQL_ROOT_PASSWORD;" || exit 1
138 # In case of container restart, attempt this at-most-once.
139 mv change_master_to.sql.in change_master_to.sql.orig
140 fi
141
142 # Start a server to send backups when requested by peers.
143 exec ncat --listen --keep-open --send-only --max-conns=1 3307 -c \
144 "xtrabackup --backup --slave-info --stream=xbstream --host=127.0.0.1 --user=root --password=$MYSQL_ROOT_PASSWORD"
145 volumeMounts:
146 - name: data
147 mountPath: /var/lib/mysql
148 subPath: mysql
149 - name: conf
150 mountPath: /etc/mysql/conf.d
151 resources:
152 requests:
153 cpu: 50m
154 memory: 50Mi
155 volumes:
156 - name: conf
157 emptyDir: {}
158 - name: config-map
159 configMap:
160 name: mysql
161 volumeClaimTemplates:
162 - metadata:
163 name: data
164 spec:
165 accessModes: ["ReadWriteOnce"]
166 resources:
167 requests:
168 storage: 10Gi
169NAME READY STATUS RESTARTS AGE
170pod/mysql-0 2/2 Running 0 11m
171pod/mysql-1 1/2 Error 7 11m
172pod/mysql-2 0/2 Init:CrashLoopBackOff 6 10m
173
174NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
175service/kubernetes ClusterIP 10.245.0.1 <none> 443/TCP 2d23h
176service/mysql ClusterIP None <none> 3306/TCP 43h
177service/mysql-read ClusterIP 10.245.81.173 <none> 3306/TCP 43h
178
179NAME READY UP-TO-DATE AVAILABLE AGE
180deployment.apps/phpmyadmin 1/1 1 1 2d18h
181
182NAME DESIRED CURRENT READY AGE
183replicaset.apps/phpmyadmin-6c57fd98bf 1 1 1 2d18h
184
185NAME READY AGE
186statefulset.apps/mysql 1/3 11m
187
188NAME TYPE DATA AGE
189secret/mysql-pass Opaque 1 46h
190secret/mysql-secret Opaque 3 2d18h
191
192NAME DATA AGE
193configmap/mysql 4 2d18h
194ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)
195 - name: MYSQL_ROOT_HOST
196 value: "%"
197NAME READY STATUS RESTARTS AGE
198mysql-0 0/2 Init:0/2 0 7s
199mysql-0 0/2 Init:1/2 0 18s
200mysql-0 0/2 PodInitializing 0 19s
201mysql-0 2/2 Running 0 20s
202mysql-1 0/2 Pending 0 0s
203mysql-1 0/2 Pending 0 0s
204mysql-1 0/2 Pending 0 8s
205mysql-1 0/2 Init:0/2 0 8s
206mysql-1 0/2 Init:1/2 0 26s
207mysql-1 0/2 Init:1/2 0 27s
208mysql-1 0/2 PodInitializing 0 34s
209mysql-1 2/2 Running 0 35s
210mysql-2 0/2 Pending 0 0s
211mysql-2 0/2 Pending 0 0s
212mysql-1 1/2 Error 0 37s
213mysql-1 1/2 Error 1 38s
214mysql-2 0/2 Pending 0 3s
215mysql-2 0/2 Init:0/2 0 3s
216mysql-1 1/2 CrashLoopBackOff 1 53s
217mysql-1 1/2 Error 2 54s
218mysql-2 0/2 Init:1/2 0 21s
219mysql-2 0/2 Init:Error 0 22s
220mysql-2 0/2 Init:Error 1 23s
221mysql-2 0/2 Init:CrashLoopBackOff 1 24s
222mysql-1 1/2 CrashLoopBackOff 2 64s
223mysql-2 0/2 Init:Error 2 38s
224mysql-1 1/2 Error 3 79s
225mysql-2 0/2 Init:CrashLoopBackOff 2 50s
226mysql-1 1/2 CrashLoopBackOff 3 92s
227mysql-2 0/2 Init:Error 3 62s
228mysql-2 0/2 Init:CrashLoopBackOff 3 74s
229mysql-1 1/2 Error 4 2m1s
230mysql-1 1/2 CrashLoopBackOff 4 2m11s
231mysql-2 0/2 Init:Error 4 113s
232mysql-2 0/2 Init:CrashLoopBackOff 4 2m6s
233mysql-1 1/2 Error 5 3m29s
234mysql-1 1/2 CrashLoopBackOff 5 3m41s
235mysql-2 0/2 Init:Error 5 3m23s
236mysql-2 0/2 Init:CrashLoopBackOff 5 3m34s
2372021-10-25 03:16:36+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.36-1debian10 started.
2382021-10-25 03:16:36+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
2392021-10-25 03:16:36+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.36-1debian10 started.
2402021-10-25T03:16:37.231906Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
2412021-10-25T03:16:37.234015Z 0 [Note] mysqld (mysqld 5.7.36) starting as process 1 ...
2422021-10-25T03:16:37.237044Z 0 [Note] InnoDB: PUNCH HOLE support available
2432021-10-25T03:16:37.237196Z 0 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
2442021-10-25T03:16:37.237263Z 0 [Note] InnoDB: Uses event mutexes
2452021-10-25T03:16:37.237345Z 0 [Note] InnoDB: GCC builtin __atomic_thread_fence() is used for memory barrier
2462021-10-25T03:16:37.237416Z 0 [Note] InnoDB: Compressed tables use zlib 1.2.11
2472021-10-25T03:16:37.237489Z 0 [Note] InnoDB: Using Linux native AIO
2482021-10-25T03:16:37.237792Z 0 [Note] InnoDB: Number of pools: 1
2492021-10-25T03:16:37.238102Z 0 [Note] InnoDB: Using CPU crc32 instructions
2502021-10-25T03:16:37.240179Z 0 [Note] InnoDB: Initializing buffer pool, total size = 128M, instances = 1, chunk size = 128M
2512021-10-25T03:16:37.248111Z 0 [Note] InnoDB: Completed initialization of buffer pool
2522021-10-25T03:16:37.251017Z 0 [Note] InnoDB: If the mysqld execution user is authorized, page cleaner thread priority can be changed. See the man page of setpriority().
2532021-10-25T03:16:37.263519Z 0 [Note] InnoDB: Highest supported file format is Barracuda.
2542021-10-25T03:16:37.307064Z 0 [Note] InnoDB: Removed temporary tablespace data file: "ibtmp1"
2552021-10-25T03:16:37.307319Z 0 [Note] InnoDB: Creating shared tablespace for temporary tables
2562021-10-25T03:16:37.307466Z 0 [Note] InnoDB: Setting file './ibtmp1' size to 12 MB. Physically writing the file full; Please wait ...
2572021-10-25T03:16:37.353707Z 0 [Note] InnoDB: File './ibtmp1' size is now 12 MB.
2582021-10-25T03:16:37.354244Z 0 [Note] InnoDB: 96 redo rollback segment(s) found. 96 redo rollback segment(s) are active.
2592021-10-25T03:16:37.354256Z 0 [Note] InnoDB: 32 non-redo rollback segment(s) are active.
2602021-10-25T03:16:37.355048Z 0 [Note] InnoDB: Waiting for purge to start
2612021-10-25T03:16:37.406335Z 0 [Note] InnoDB: 5.7.36 started; log sequence number 12660776
2622021-10-25T03:16:37.406850Z 0 [Note] Plugin 'FEDERATED' is disabled.
2632021-10-25T03:16:37.413880Z 0 [Note] InnoDB: Loading buffer pool(s) from /var/lib/mysql/ib_buffer_pool
2642021-10-25T03:16:37.426491Z 0 [Note] InnoDB: Buffer pool(s) load completed at 211025 3:16:37
2652021-10-25T03:16:37.427210Z 0 [Note] Salting uuid generator variables, current_pid: 1, server_start_time: 1635131797, bytes_sent: 0,
2662021-10-25T03:16:37.427438Z 0 [Note] Generated uuid: 'f6f89137-3541-11ec-84bc-f29710c93c86', server_start_time: 281476611842454, bytes_sent: 94355589700272
2672021-10-25T03:16:37.427554Z 0 [Warning] No existing UUID has been found, so we assume that this is the first time that this server has been started. Generating a new UUID: f6f89137-3541-11ec-84bc-f29710c93c86.
2682021-10-25T03:16:38.109098Z 0 [Note] Auto generated SSL certificates are placed in data directory.
2692021-10-25T03:16:38.109327Z 0 [Warning] A deprecated TLS version TLSv1 is enabled. Please use TLSv1.2 or higher.
2702021-10-25T03:16:38.109395Z 0 [Warning] A deprecated TLS version TLSv1.1 is enabled. Please use TLSv1.2 or higher.
2712021-10-25T03:16:38.109907Z 0 [Warning] CA certificate ca.pem is self signed.
2722021-10-25T03:16:38.354105Z 0 [Note] Auto generated RSA key files are placed in data directory.
2732021-10-25T03:16:38.354795Z 0 [Note] Server hostname (bind-address): '*'; port: 3306
2742021-10-25T03:16:38.354968Z 0 [Note] IPv6 is available.
2752021-10-25T03:16:38.355039Z 0 [Note] - '::' resolves to '::';
2762021-10-25T03:16:38.355125Z 0 [Note] Server socket created on IP: '::'.
2772021-10-25T03:16:38.357907Z 0 [Warning] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory.
2782021-10-25T03:16:38.361720Z 0 [Note] Failed to start slave threads for channel ''
2792021-10-25T03:16:38.366691Z 0 [Note] Event Scheduler: Loaded 0 events
2802021-10-25T03:16:38.367135Z 0 [Note] mysqld: ready for connections.
281Version: '5.7.36' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server (GPL)
2822021-10-25T03:16:39.011694Z 3 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2832021-10-25T03:16:39.759020Z 5 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2842021-10-25T03:16:56.006754Z 7 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2852021-10-25T03:17:21.016988Z 9 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2862021-10-25T03:18:03.010443Z 11 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2872021-10-25T03:19:30.984929Z 13 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2882021-10-25T03:22:25.011291Z 15 [Note] Access denied for user 'root'@'localhost' (using password: NO)
289apiVersion: apps/v1
290kind: StatefulSet
291metadata:
292 name: mysql
293spec:
294 selector:
295 matchLabels:
296 app: mysql
297 serviceName: mysql
298 replicas: 3
299 template:
300 metadata:
301 labels:
302 app: mysql
303 spec:
304 initContainers:
305 - name: init-mysql
306 image: mysql:5.7
307 env:
308 - name: MYSQL_ROOT_PASSWORD
309 value: admin123
310 command:
311 - bash
312 - "-c"
313 - |
314 set -ex
315 # Generate mysql server-id from pod ordinal index.
316 [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
317 ordinal=${BASH_REMATCH[1]}
318 echo [mysqld] > /mnt/conf.d/server-id.cnf
319 # Add an offset to avoid reserved server-id=0 value.
320 echo server-id=$((100 + $ordinal)) >> /mnt/conf.d/server-id.cnf
321 # Copy appropriate conf.d files from config-map to emptyDir.
322 if [[ $ordinal -eq 0 ]]; then
323 cp /mnt/config-map/primary.cnf /mnt/conf.d/
324 else
325 cp /mnt/config-map/replica.cnf /mnt/conf.d/
326 fi
327 volumeMounts:
328 - name: conf
329 mountPath: /mnt/conf.d
330 - name: config-map
331 mountPath: /mnt/config-map
332 containers:
333 - name: mysql
334 image: mysql:5.7
335 env:
336 - name: MYSQL_ROOT_PASSWORD
337 value: admin123
338 ports:
339 - name: mysql
340 containerPort: 3306
341 volumeMounts:
342 - name: data
343 mountPath: /var/lib/mysql
344 subPath: mysql
345 - name: conf
346 mountPath: /etc/mysql/conf.d
347 resources:
348 requests:
349 cpu: 100m
350 memory: 500Mi
351 volumes:
352 - name: conf
353 emptyDir: {}
354 - name: config-map
355 configMap:
356 name: mysql
357 volumeClaimTemplates:
358 - metadata:
359 name: data
360 spec:
361 accessModes: ["ReadWriteOnce"]
362 resources:
363 requests:
364 storage: 10Gi
365$MYSQL_ROOT_PASSWORD ==> $(MYSQL_ROOT_PASSWORD)
366#when calling env var inside command, you have to add the brackets
367-uroot -p$MYQSL_ROOT_PASSWORD ==> -u root --password=$(MYSQL_ROOT_PASSWORD)
368
1apiVersion: apps/v1
2kind: StatefulSet
3metadata:
4 name: mysql
5spec:
6 selector:
7 matchLabels:
8 app: mysql
9 serviceName: mysql
10 replicas: 3
11 template:
12 metadata:
13 labels:
14 app: mysql
15 spec:
16 initContainers:
17 - name: init-mysql
18 image: mysql:5.7
19 env:
20 - name: MYSQL_ROOT_PASSWORD
21 valueFrom:
22 secretKeyRef:
23 name: mysql-secret
24 key: mysql-root-password
25 command:
26 - bash
27 - "-c"
28 - |
29 set -ex
30 # Generate mysql server-id from pod ordinal index.
31 [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
32 ordinal=${BASH_REMATCH[1]}
33 echo [mysqld] > /mnt/conf.d/server-id.cnf
34 # Add an offset to avoid reserved server-id=0 value.
35 echo server-id=$((100 + $ordinal)) >> /mnt/conf.d/server-id.cnf
36 # Copy appropriate conf.d files from config-map to emptyDir.
37 if [[ $ordinal -eq 0 ]]; then
38 cp /mnt/config-map/primary.cnf /mnt/conf.d/
39 else
40 cp /mnt/config-map/replica.cnf /mnt/conf.d/
41 fi
42 volumeMounts:
43 - name: conf
44 mountPath: /mnt/conf.d
45 - name: config-map
46 mountPath: /mnt/config-map
47 - name: clone-mysql
48 image: gcr.io/google-samples/xtrabackup:1.0
49 command:
50 - bash
51 - "-c"
52 - |
53 set -ex
54 # Skip the clone if data already exists.
55 [[ -d /var/lib/mysql/mysql ]] && exit 0
56 # Skip the clone on primary (ordinal index 0).
57 [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
58 ordinal=${BASH_REMATCH[1]}
59 [[ $ordinal -eq 0 ]] && exit 0
60 # Clone data from previous peer.
61 ncat --recv-only mysql-$(($ordinal-1)).mysql 3307 | xbstream -x -C /var/lib/mysql
62 # Prepare the backup.
63 xtrabackup --prepare --target-dir=/var/lib/mysql
64 volumeMounts:
65 - name: data
66 mountPath: /var/lib/mysql
67 subPath: mysql
68 - name: conf
69 mountPath: /etc/mysql/conf.d
70 containers:
71 - name: mysql
72 image: mysql:5.7
73 env:
74 - name: MYSQL_ROOT_PASSWORD
75 valueFrom:
76 secretKeyRef:
77 name: mysql-secret
78 key: mysql-root-password
79 ports:
80 - name: mysql
81 containerPort: 3306
82 volumeMounts:
83 - name: data
84 mountPath: /var/lib/mysql
85 subPath: mysql
86 - name: conf
87 mountPath: /etc/mysql/conf.d
88 resources:
89 requests:
90 cpu: 100m
91 memory: 500Mi
92 - name: xtrabackup
93 image: gcr.io/google-samples/xtrabackup:1.0
94 env:
95 - name: MYSQL_ROOT_PASSWORD
96 valueFrom:
97 secretKeyRef:
98 name: mysql-secret
99 key: mysql-root-password
100 ports:
101 - name: xtrabackup
102 containerPort: 3307
103 command:
104 - bash
105 - "-c"
106 - |
107 set -ex
108 cd /var/lib/mysql
109
110 # Determine binlog position of cloned data, if any.
111 if [[ -f xtrabackup_slave_info && "x$(<xtrabackup_slave_info)" != "x" ]]; then
112 # XtraBackup already generated a partial "CHANGE MASTER TO" query
113 # because we're cloning from an existing replica. (Need to remove the tailing semicolon!)
114 cat xtrabackup_slave_info | sed -E 's/;$//g' > change_master_to.sql.in
115 # Ignore xtrabackup_binlog_info in this case (it's useless).
116 rm -f xtrabackup_slave_info xtrabackup_binlog_info
117 elif [[ -f xtrabackup_binlog_info ]]; then
118 # We're cloning directly from primary. Parse binlog position.
119 [[ `cat xtrabackup_binlog_info` =~ ^(.*?)[[:space:]]+(.*?)$ ]] || exit 1
120 rm -f xtrabackup_binlog_info xtrabackup_slave_info
121 echo "CHANGE MASTER TO MASTER_LOG_FILE='${BASH_REMATCH[1]}',\
122 MASTER_LOG_POS=${BASH_REMATCH[2]}" > change_master_to.sql.in
123 fi
124
125 # Check if we need to complete a clone by starting replication.
126 if [[ -f change_master_to.sql.in ]]; then
127 echo "Waiting for mysqld to be ready (accepting connections)"
128 until mysql -h 127.0.0.1 -uroot -p$MYSQL_ROOT_PASSWORD -e "SELECT 1"; do sleep 1; done
129
130 echo "Initializing replication from clone position"
131 mysql -h 127.0.0.1 \
132 -e "$(<change_master_to.sql.in), \
133 MASTER_HOST='mysql-0.mysql', \
134 MASTER_USER='root', \
135 MASTER_PASSWORD=$MYSQL_ROOT_PASSWORD, \
136 MASTER_CONNECT_RETRY=10; \
137 START SLAVE USER='root' PASSWORD=$MYSQL_ROOT_PASSWORD;" || exit 1
138 # In case of container restart, attempt this at-most-once.
139 mv change_master_to.sql.in change_master_to.sql.orig
140 fi
141
142 # Start a server to send backups when requested by peers.
143 exec ncat --listen --keep-open --send-only --max-conns=1 3307 -c \
144 "xtrabackup --backup --slave-info --stream=xbstream --host=127.0.0.1 --user=root --password=$MYSQL_ROOT_PASSWORD"
145 volumeMounts:
146 - name: data
147 mountPath: /var/lib/mysql
148 subPath: mysql
149 - name: conf
150 mountPath: /etc/mysql/conf.d
151 resources:
152 requests:
153 cpu: 50m
154 memory: 50Mi
155 volumes:
156 - name: conf
157 emptyDir: {}
158 - name: config-map
159 configMap:
160 name: mysql
161 volumeClaimTemplates:
162 - metadata:
163 name: data
164 spec:
165 accessModes: ["ReadWriteOnce"]
166 resources:
167 requests:
168 storage: 10Gi
169NAME READY STATUS RESTARTS AGE
170pod/mysql-0 2/2 Running 0 11m
171pod/mysql-1 1/2 Error 7 11m
172pod/mysql-2 0/2 Init:CrashLoopBackOff 6 10m
173
174NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
175service/kubernetes ClusterIP 10.245.0.1 <none> 443/TCP 2d23h
176service/mysql ClusterIP None <none> 3306/TCP 43h
177service/mysql-read ClusterIP 10.245.81.173 <none> 3306/TCP 43h
178
179NAME READY UP-TO-DATE AVAILABLE AGE
180deployment.apps/phpmyadmin 1/1 1 1 2d18h
181
182NAME DESIRED CURRENT READY AGE
183replicaset.apps/phpmyadmin-6c57fd98bf 1 1 1 2d18h
184
185NAME READY AGE
186statefulset.apps/mysql 1/3 11m
187
188NAME TYPE DATA AGE
189secret/mysql-pass Opaque 1 46h
190secret/mysql-secret Opaque 3 2d18h
191
192NAME DATA AGE
193configmap/mysql 4 2d18h
194ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)
195 - name: MYSQL_ROOT_HOST
196 value: "%"
197NAME READY STATUS RESTARTS AGE
198mysql-0 0/2 Init:0/2 0 7s
199mysql-0 0/2 Init:1/2 0 18s
200mysql-0 0/2 PodInitializing 0 19s
201mysql-0 2/2 Running 0 20s
202mysql-1 0/2 Pending 0 0s
203mysql-1 0/2 Pending 0 0s
204mysql-1 0/2 Pending 0 8s
205mysql-1 0/2 Init:0/2 0 8s
206mysql-1 0/2 Init:1/2 0 26s
207mysql-1 0/2 Init:1/2 0 27s
208mysql-1 0/2 PodInitializing 0 34s
209mysql-1 2/2 Running 0 35s
210mysql-2 0/2 Pending 0 0s
211mysql-2 0/2 Pending 0 0s
212mysql-1 1/2 Error 0 37s
213mysql-1 1/2 Error 1 38s
214mysql-2 0/2 Pending 0 3s
215mysql-2 0/2 Init:0/2 0 3s
216mysql-1 1/2 CrashLoopBackOff 1 53s
217mysql-1 1/2 Error 2 54s
218mysql-2 0/2 Init:1/2 0 21s
219mysql-2 0/2 Init:Error 0 22s
220mysql-2 0/2 Init:Error 1 23s
221mysql-2 0/2 Init:CrashLoopBackOff 1 24s
222mysql-1 1/2 CrashLoopBackOff 2 64s
223mysql-2 0/2 Init:Error 2 38s
224mysql-1 1/2 Error 3 79s
225mysql-2 0/2 Init:CrashLoopBackOff 2 50s
226mysql-1 1/2 CrashLoopBackOff 3 92s
227mysql-2 0/2 Init:Error 3 62s
228mysql-2 0/2 Init:CrashLoopBackOff 3 74s
229mysql-1 1/2 Error 4 2m1s
230mysql-1 1/2 CrashLoopBackOff 4 2m11s
231mysql-2 0/2 Init:Error 4 113s
232mysql-2 0/2 Init:CrashLoopBackOff 4 2m6s
233mysql-1 1/2 Error 5 3m29s
234mysql-1 1/2 CrashLoopBackOff 5 3m41s
235mysql-2 0/2 Init:Error 5 3m23s
236mysql-2 0/2 Init:CrashLoopBackOff 5 3m34s
2372021-10-25 03:16:36+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.36-1debian10 started.
2382021-10-25 03:16:36+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
2392021-10-25 03:16:36+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.36-1debian10 started.
2402021-10-25T03:16:37.231906Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
2412021-10-25T03:16:37.234015Z 0 [Note] mysqld (mysqld 5.7.36) starting as process 1 ...
2422021-10-25T03:16:37.237044Z 0 [Note] InnoDB: PUNCH HOLE support available
2432021-10-25T03:16:37.237196Z 0 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
2442021-10-25T03:16:37.237263Z 0 [Note] InnoDB: Uses event mutexes
2452021-10-25T03:16:37.237345Z 0 [Note] InnoDB: GCC builtin __atomic_thread_fence() is used for memory barrier
2462021-10-25T03:16:37.237416Z 0 [Note] InnoDB: Compressed tables use zlib 1.2.11
2472021-10-25T03:16:37.237489Z 0 [Note] InnoDB: Using Linux native AIO
2482021-10-25T03:16:37.237792Z 0 [Note] InnoDB: Number of pools: 1
2492021-10-25T03:16:37.238102Z 0 [Note] InnoDB: Using CPU crc32 instructions
2502021-10-25T03:16:37.240179Z 0 [Note] InnoDB: Initializing buffer pool, total size = 128M, instances = 1, chunk size = 128M
2512021-10-25T03:16:37.248111Z 0 [Note] InnoDB: Completed initialization of buffer pool
2522021-10-25T03:16:37.251017Z 0 [Note] InnoDB: If the mysqld execution user is authorized, page cleaner thread priority can be changed. See the man page of setpriority().
2532021-10-25T03:16:37.263519Z 0 [Note] InnoDB: Highest supported file format is Barracuda.
2542021-10-25T03:16:37.307064Z 0 [Note] InnoDB: Removed temporary tablespace data file: "ibtmp1"
2552021-10-25T03:16:37.307319Z 0 [Note] InnoDB: Creating shared tablespace for temporary tables
2562021-10-25T03:16:37.307466Z 0 [Note] InnoDB: Setting file './ibtmp1' size to 12 MB. Physically writing the file full; Please wait ...
2572021-10-25T03:16:37.353707Z 0 [Note] InnoDB: File './ibtmp1' size is now 12 MB.
2582021-10-25T03:16:37.354244Z 0 [Note] InnoDB: 96 redo rollback segment(s) found. 96 redo rollback segment(s) are active.
2592021-10-25T03:16:37.354256Z 0 [Note] InnoDB: 32 non-redo rollback segment(s) are active.
2602021-10-25T03:16:37.355048Z 0 [Note] InnoDB: Waiting for purge to start
2612021-10-25T03:16:37.406335Z 0 [Note] InnoDB: 5.7.36 started; log sequence number 12660776
2622021-10-25T03:16:37.406850Z 0 [Note] Plugin 'FEDERATED' is disabled.
2632021-10-25T03:16:37.413880Z 0 [Note] InnoDB: Loading buffer pool(s) from /var/lib/mysql/ib_buffer_pool
2642021-10-25T03:16:37.426491Z 0 [Note] InnoDB: Buffer pool(s) load completed at 211025 3:16:37
2652021-10-25T03:16:37.427210Z 0 [Note] Salting uuid generator variables, current_pid: 1, server_start_time: 1635131797, bytes_sent: 0,
2662021-10-25T03:16:37.427438Z 0 [Note] Generated uuid: 'f6f89137-3541-11ec-84bc-f29710c93c86', server_start_time: 281476611842454, bytes_sent: 94355589700272
2672021-10-25T03:16:37.427554Z 0 [Warning] No existing UUID has been found, so we assume that this is the first time that this server has been started. Generating a new UUID: f6f89137-3541-11ec-84bc-f29710c93c86.
2682021-10-25T03:16:38.109098Z 0 [Note] Auto generated SSL certificates are placed in data directory.
2692021-10-25T03:16:38.109327Z 0 [Warning] A deprecated TLS version TLSv1 is enabled. Please use TLSv1.2 or higher.
2702021-10-25T03:16:38.109395Z 0 [Warning] A deprecated TLS version TLSv1.1 is enabled. Please use TLSv1.2 or higher.
2712021-10-25T03:16:38.109907Z 0 [Warning] CA certificate ca.pem is self signed.
2722021-10-25T03:16:38.354105Z 0 [Note] Auto generated RSA key files are placed in data directory.
2732021-10-25T03:16:38.354795Z 0 [Note] Server hostname (bind-address): '*'; port: 3306
2742021-10-25T03:16:38.354968Z 0 [Note] IPv6 is available.
2752021-10-25T03:16:38.355039Z 0 [Note] - '::' resolves to '::';
2762021-10-25T03:16:38.355125Z 0 [Note] Server socket created on IP: '::'.
2772021-10-25T03:16:38.357907Z 0 [Warning] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory.
2782021-10-25T03:16:38.361720Z 0 [Note] Failed to start slave threads for channel ''
2792021-10-25T03:16:38.366691Z 0 [Note] Event Scheduler: Loaded 0 events
2802021-10-25T03:16:38.367135Z 0 [Note] mysqld: ready for connections.
281Version: '5.7.36' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server (GPL)
2822021-10-25T03:16:39.011694Z 3 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2832021-10-25T03:16:39.759020Z 5 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2842021-10-25T03:16:56.006754Z 7 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2852021-10-25T03:17:21.016988Z 9 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2862021-10-25T03:18:03.010443Z 11 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2872021-10-25T03:19:30.984929Z 13 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2882021-10-25T03:22:25.011291Z 15 [Note] Access denied for user 'root'@'localhost' (using password: NO)
289apiVersion: apps/v1
290kind: StatefulSet
291metadata:
292 name: mysql
293spec:
294 selector:
295 matchLabels:
296 app: mysql
297 serviceName: mysql
298 replicas: 3
299 template:
300 metadata:
301 labels:
302 app: mysql
303 spec:
304 initContainers:
305 - name: init-mysql
306 image: mysql:5.7
307 env:
308 - name: MYSQL_ROOT_PASSWORD
309 value: admin123
310 command:
311 - bash
312 - "-c"
313 - |
314 set -ex
315 # Generate mysql server-id from pod ordinal index.
316 [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
317 ordinal=${BASH_REMATCH[1]}
318 echo [mysqld] > /mnt/conf.d/server-id.cnf
319 # Add an offset to avoid reserved server-id=0 value.
320 echo server-id=$((100 + $ordinal)) >> /mnt/conf.d/server-id.cnf
321 # Copy appropriate conf.d files from config-map to emptyDir.
322 if [[ $ordinal -eq 0 ]]; then
323 cp /mnt/config-map/primary.cnf /mnt/conf.d/
324 else
325 cp /mnt/config-map/replica.cnf /mnt/conf.d/
326 fi
327 volumeMounts:
328 - name: conf
329 mountPath: /mnt/conf.d
330 - name: config-map
331 mountPath: /mnt/config-map
332 containers:
333 - name: mysql
334 image: mysql:5.7
335 env:
336 - name: MYSQL_ROOT_PASSWORD
337 value: admin123
338 ports:
339 - name: mysql
340 containerPort: 3306
341 volumeMounts:
342 - name: data
343 mountPath: /var/lib/mysql
344 subPath: mysql
345 - name: conf
346 mountPath: /etc/mysql/conf.d
347 resources:
348 requests:
349 cpu: 100m
350 memory: 500Mi
351 volumes:
352 - name: conf
353 emptyDir: {}
354 - name: config-map
355 configMap:
356 name: mysql
357 volumeClaimTemplates:
358 - metadata:
359 name: data
360 spec:
361 accessModes: ["ReadWriteOnce"]
362 resources:
363 requests:
364 storage: 10Gi
365$MYSQL_ROOT_PASSWORD ==> $(MYSQL_ROOT_PASSWORD)
366#when calling env var inside command, you have to add the brackets
367-uroot -p$MYQSL_ROOT_PASSWORD ==> -u root --password=$(MYSQL_ROOT_PASSWORD)
368START SLAVE USER='root' PASSWORD=$(MYSQL_ROOT_PASSWORD);" || exit 1 ==> START SLAVE;" || exit 1
369
and
1apiVersion: apps/v1
2kind: StatefulSet
3metadata:
4 name: mysql
5spec:
6 selector:
7 matchLabels:
8 app: mysql
9 serviceName: mysql
10 replicas: 3
11 template:
12 metadata:
13 labels:
14 app: mysql
15 spec:
16 initContainers:
17 - name: init-mysql
18 image: mysql:5.7
19 env:
20 - name: MYSQL_ROOT_PASSWORD
21 valueFrom:
22 secretKeyRef:
23 name: mysql-secret
24 key: mysql-root-password
25 command:
26 - bash
27 - "-c"
28 - |
29 set -ex
30 # Generate mysql server-id from pod ordinal index.
31 [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
32 ordinal=${BASH_REMATCH[1]}
33 echo [mysqld] > /mnt/conf.d/server-id.cnf
34 # Add an offset to avoid reserved server-id=0 value.
35 echo server-id=$((100 + $ordinal)) >> /mnt/conf.d/server-id.cnf
36 # Copy appropriate conf.d files from config-map to emptyDir.
37 if [[ $ordinal -eq 0 ]]; then
38 cp /mnt/config-map/primary.cnf /mnt/conf.d/
39 else
40 cp /mnt/config-map/replica.cnf /mnt/conf.d/
41 fi
42 volumeMounts:
43 - name: conf
44 mountPath: /mnt/conf.d
45 - name: config-map
46 mountPath: /mnt/config-map
47 - name: clone-mysql
48 image: gcr.io/google-samples/xtrabackup:1.0
49 command:
50 - bash
51 - "-c"
52 - |
53 set -ex
54 # Skip the clone if data already exists.
55 [[ -d /var/lib/mysql/mysql ]] && exit 0
56 # Skip the clone on primary (ordinal index 0).
57 [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
58 ordinal=${BASH_REMATCH[1]}
59 [[ $ordinal -eq 0 ]] && exit 0
60 # Clone data from previous peer.
61 ncat --recv-only mysql-$(($ordinal-1)).mysql 3307 | xbstream -x -C /var/lib/mysql
62 # Prepare the backup.
63 xtrabackup --prepare --target-dir=/var/lib/mysql
64 volumeMounts:
65 - name: data
66 mountPath: /var/lib/mysql
67 subPath: mysql
68 - name: conf
69 mountPath: /etc/mysql/conf.d
70 containers:
71 - name: mysql
72 image: mysql:5.7
73 env:
74 - name: MYSQL_ROOT_PASSWORD
75 valueFrom:
76 secretKeyRef:
77 name: mysql-secret
78 key: mysql-root-password
79 ports:
80 - name: mysql
81 containerPort: 3306
82 volumeMounts:
83 - name: data
84 mountPath: /var/lib/mysql
85 subPath: mysql
86 - name: conf
87 mountPath: /etc/mysql/conf.d
88 resources:
89 requests:
90 cpu: 100m
91 memory: 500Mi
92 - name: xtrabackup
93 image: gcr.io/google-samples/xtrabackup:1.0
94 env:
95 - name: MYSQL_ROOT_PASSWORD
96 valueFrom:
97 secretKeyRef:
98 name: mysql-secret
99 key: mysql-root-password
100 ports:
101 - name: xtrabackup
102 containerPort: 3307
103 command:
104 - bash
105 - "-c"
106 - |
107 set -ex
108 cd /var/lib/mysql
109
110 # Determine binlog position of cloned data, if any.
111 if [[ -f xtrabackup_slave_info && "x$(<xtrabackup_slave_info)" != "x" ]]; then
112 # XtraBackup already generated a partial "CHANGE MASTER TO" query
113 # because we're cloning from an existing replica. (Need to remove the tailing semicolon!)
114 cat xtrabackup_slave_info | sed -E 's/;$//g' > change_master_to.sql.in
115 # Ignore xtrabackup_binlog_info in this case (it's useless).
116 rm -f xtrabackup_slave_info xtrabackup_binlog_info
117 elif [[ -f xtrabackup_binlog_info ]]; then
118 # We're cloning directly from primary. Parse binlog position.
119 [[ `cat xtrabackup_binlog_info` =~ ^(.*?)[[:space:]]+(.*?)$ ]] || exit 1
120 rm -f xtrabackup_binlog_info xtrabackup_slave_info
121 echo "CHANGE MASTER TO MASTER_LOG_FILE='${BASH_REMATCH[1]}',\
122 MASTER_LOG_POS=${BASH_REMATCH[2]}" > change_master_to.sql.in
123 fi
124
125 # Check if we need to complete a clone by starting replication.
126 if [[ -f change_master_to.sql.in ]]; then
127 echo "Waiting for mysqld to be ready (accepting connections)"
128 until mysql -h 127.0.0.1 -uroot -p$MYSQL_ROOT_PASSWORD -e "SELECT 1"; do sleep 1; done
129
130 echo "Initializing replication from clone position"
131 mysql -h 127.0.0.1 \
132 -e "$(<change_master_to.sql.in), \
133 MASTER_HOST='mysql-0.mysql', \
134 MASTER_USER='root', \
135 MASTER_PASSWORD=$MYSQL_ROOT_PASSWORD, \
136 MASTER_CONNECT_RETRY=10; \
137 START SLAVE USER='root' PASSWORD=$MYSQL_ROOT_PASSWORD;" || exit 1
138 # In case of container restart, attempt this at-most-once.
139 mv change_master_to.sql.in change_master_to.sql.orig
140 fi
141
142 # Start a server to send backups when requested by peers.
143 exec ncat --listen --keep-open --send-only --max-conns=1 3307 -c \
144 "xtrabackup --backup --slave-info --stream=xbstream --host=127.0.0.1 --user=root --password=$MYSQL_ROOT_PASSWORD"
145 volumeMounts:
146 - name: data
147 mountPath: /var/lib/mysql
148 subPath: mysql
149 - name: conf
150 mountPath: /etc/mysql/conf.d
151 resources:
152 requests:
153 cpu: 50m
154 memory: 50Mi
155 volumes:
156 - name: conf
157 emptyDir: {}
158 - name: config-map
159 configMap:
160 name: mysql
161 volumeClaimTemplates:
162 - metadata:
163 name: data
164 spec:
165 accessModes: ["ReadWriteOnce"]
166 resources:
167 requests:
168 storage: 10Gi
169NAME READY STATUS RESTARTS AGE
170pod/mysql-0 2/2 Running 0 11m
171pod/mysql-1 1/2 Error 7 11m
172pod/mysql-2 0/2 Init:CrashLoopBackOff 6 10m
173
174NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
175service/kubernetes ClusterIP 10.245.0.1 <none> 443/TCP 2d23h
176service/mysql ClusterIP None <none> 3306/TCP 43h
177service/mysql-read ClusterIP 10.245.81.173 <none> 3306/TCP 43h
178
179NAME READY UP-TO-DATE AVAILABLE AGE
180deployment.apps/phpmyadmin 1/1 1 1 2d18h
181
182NAME DESIRED CURRENT READY AGE
183replicaset.apps/phpmyadmin-6c57fd98bf 1 1 1 2d18h
184
185NAME READY AGE
186statefulset.apps/mysql 1/3 11m
187
188NAME TYPE DATA AGE
189secret/mysql-pass Opaque 1 46h
190secret/mysql-secret Opaque 3 2d18h
191
192NAME DATA AGE
193configmap/mysql 4 2d18h
194ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)
195 - name: MYSQL_ROOT_HOST
196 value: "%"
197NAME READY STATUS RESTARTS AGE
198mysql-0 0/2 Init:0/2 0 7s
199mysql-0 0/2 Init:1/2 0 18s
200mysql-0 0/2 PodInitializing 0 19s
201mysql-0 2/2 Running 0 20s
202mysql-1 0/2 Pending 0 0s
203mysql-1 0/2 Pending 0 0s
204mysql-1 0/2 Pending 0 8s
205mysql-1 0/2 Init:0/2 0 8s
206mysql-1 0/2 Init:1/2 0 26s
207mysql-1 0/2 Init:1/2 0 27s
208mysql-1 0/2 PodInitializing 0 34s
209mysql-1 2/2 Running 0 35s
210mysql-2 0/2 Pending 0 0s
211mysql-2 0/2 Pending 0 0s
212mysql-1 1/2 Error 0 37s
213mysql-1 1/2 Error 1 38s
214mysql-2 0/2 Pending 0 3s
215mysql-2 0/2 Init:0/2 0 3s
216mysql-1 1/2 CrashLoopBackOff 1 53s
217mysql-1 1/2 Error 2 54s
218mysql-2 0/2 Init:1/2 0 21s
219mysql-2 0/2 Init:Error 0 22s
220mysql-2 0/2 Init:Error 1 23s
221mysql-2 0/2 Init:CrashLoopBackOff 1 24s
222mysql-1 1/2 CrashLoopBackOff 2 64s
223mysql-2 0/2 Init:Error 2 38s
224mysql-1 1/2 Error 3 79s
225mysql-2 0/2 Init:CrashLoopBackOff 2 50s
226mysql-1 1/2 CrashLoopBackOff 3 92s
227mysql-2 0/2 Init:Error 3 62s
228mysql-2 0/2 Init:CrashLoopBackOff 3 74s
229mysql-1 1/2 Error 4 2m1s
230mysql-1 1/2 CrashLoopBackOff 4 2m11s
231mysql-2 0/2 Init:Error 4 113s
232mysql-2 0/2 Init:CrashLoopBackOff 4 2m6s
233mysql-1 1/2 Error 5 3m29s
234mysql-1 1/2 CrashLoopBackOff 5 3m41s
235mysql-2 0/2 Init:Error 5 3m23s
236mysql-2 0/2 Init:CrashLoopBackOff 5 3m34s
2372021-10-25 03:16:36+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.36-1debian10 started.
2382021-10-25 03:16:36+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
2392021-10-25 03:16:36+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.36-1debian10 started.
2402021-10-25T03:16:37.231906Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
2412021-10-25T03:16:37.234015Z 0 [Note] mysqld (mysqld 5.7.36) starting as process 1 ...
2422021-10-25T03:16:37.237044Z 0 [Note] InnoDB: PUNCH HOLE support available
2432021-10-25T03:16:37.237196Z 0 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
2442021-10-25T03:16:37.237263Z 0 [Note] InnoDB: Uses event mutexes
2452021-10-25T03:16:37.237345Z 0 [Note] InnoDB: GCC builtin __atomic_thread_fence() is used for memory barrier
2462021-10-25T03:16:37.237416Z 0 [Note] InnoDB: Compressed tables use zlib 1.2.11
2472021-10-25T03:16:37.237489Z 0 [Note] InnoDB: Using Linux native AIO
2482021-10-25T03:16:37.237792Z 0 [Note] InnoDB: Number of pools: 1
2492021-10-25T03:16:37.238102Z 0 [Note] InnoDB: Using CPU crc32 instructions
2502021-10-25T03:16:37.240179Z 0 [Note] InnoDB: Initializing buffer pool, total size = 128M, instances = 1, chunk size = 128M
2512021-10-25T03:16:37.248111Z 0 [Note] InnoDB: Completed initialization of buffer pool
2522021-10-25T03:16:37.251017Z 0 [Note] InnoDB: If the mysqld execution user is authorized, page cleaner thread priority can be changed. See the man page of setpriority().
2532021-10-25T03:16:37.263519Z 0 [Note] InnoDB: Highest supported file format is Barracuda.
2542021-10-25T03:16:37.307064Z 0 [Note] InnoDB: Removed temporary tablespace data file: "ibtmp1"
2552021-10-25T03:16:37.307319Z 0 [Note] InnoDB: Creating shared tablespace for temporary tables
2562021-10-25T03:16:37.307466Z 0 [Note] InnoDB: Setting file './ibtmp1' size to 12 MB. Physically writing the file full; Please wait ...
2572021-10-25T03:16:37.353707Z 0 [Note] InnoDB: File './ibtmp1' size is now 12 MB.
2582021-10-25T03:16:37.354244Z 0 [Note] InnoDB: 96 redo rollback segment(s) found. 96 redo rollback segment(s) are active.
2592021-10-25T03:16:37.354256Z 0 [Note] InnoDB: 32 non-redo rollback segment(s) are active.
2602021-10-25T03:16:37.355048Z 0 [Note] InnoDB: Waiting for purge to start
2612021-10-25T03:16:37.406335Z 0 [Note] InnoDB: 5.7.36 started; log sequence number 12660776
2622021-10-25T03:16:37.406850Z 0 [Note] Plugin 'FEDERATED' is disabled.
2632021-10-25T03:16:37.413880Z 0 [Note] InnoDB: Loading buffer pool(s) from /var/lib/mysql/ib_buffer_pool
2642021-10-25T03:16:37.426491Z 0 [Note] InnoDB: Buffer pool(s) load completed at 211025 3:16:37
2652021-10-25T03:16:37.427210Z 0 [Note] Salting uuid generator variables, current_pid: 1, server_start_time: 1635131797, bytes_sent: 0,
2662021-10-25T03:16:37.427438Z 0 [Note] Generated uuid: 'f6f89137-3541-11ec-84bc-f29710c93c86', server_start_time: 281476611842454, bytes_sent: 94355589700272
2672021-10-25T03:16:37.427554Z 0 [Warning] No existing UUID has been found, so we assume that this is the first time that this server has been started. Generating a new UUID: f6f89137-3541-11ec-84bc-f29710c93c86.
2682021-10-25T03:16:38.109098Z 0 [Note] Auto generated SSL certificates are placed in data directory.
2692021-10-25T03:16:38.109327Z 0 [Warning] A deprecated TLS version TLSv1 is enabled. Please use TLSv1.2 or higher.
2702021-10-25T03:16:38.109395Z 0 [Warning] A deprecated TLS version TLSv1.1 is enabled. Please use TLSv1.2 or higher.
2712021-10-25T03:16:38.109907Z 0 [Warning] CA certificate ca.pem is self signed.
2722021-10-25T03:16:38.354105Z 0 [Note] Auto generated RSA key files are placed in data directory.
2732021-10-25T03:16:38.354795Z 0 [Note] Server hostname (bind-address): '*'; port: 3306
2742021-10-25T03:16:38.354968Z 0 [Note] IPv6 is available.
2752021-10-25T03:16:38.355039Z 0 [Note] - '::' resolves to '::';
2762021-10-25T03:16:38.355125Z 0 [Note] Server socket created on IP: '::'.
2772021-10-25T03:16:38.357907Z 0 [Warning] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory.
2782021-10-25T03:16:38.361720Z 0 [Note] Failed to start slave threads for channel ''
2792021-10-25T03:16:38.366691Z 0 [Note] Event Scheduler: Loaded 0 events
2802021-10-25T03:16:38.367135Z 0 [Note] mysqld: ready for connections.
281Version: '5.7.36' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server (GPL)
2822021-10-25T03:16:39.011694Z 3 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2832021-10-25T03:16:39.759020Z 5 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2842021-10-25T03:16:56.006754Z 7 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2852021-10-25T03:17:21.016988Z 9 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2862021-10-25T03:18:03.010443Z 11 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2872021-10-25T03:19:30.984929Z 13 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2882021-10-25T03:22:25.011291Z 15 [Note] Access denied for user 'root'@'localhost' (using password: NO)
289apiVersion: apps/v1
290kind: StatefulSet
291metadata:
292 name: mysql
293spec:
294 selector:
295 matchLabels:
296 app: mysql
297 serviceName: mysql
298 replicas: 3
299 template:
300 metadata:
301 labels:
302 app: mysql
303 spec:
304 initContainers:
305 - name: init-mysql
306 image: mysql:5.7
307 env:
308 - name: MYSQL_ROOT_PASSWORD
309 value: admin123
310 command:
311 - bash
312 - "-c"
313 - |
314 set -ex
315 # Generate mysql server-id from pod ordinal index.
316 [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
317 ordinal=${BASH_REMATCH[1]}
318 echo [mysqld] > /mnt/conf.d/server-id.cnf
319 # Add an offset to avoid reserved server-id=0 value.
320 echo server-id=$((100 + $ordinal)) >> /mnt/conf.d/server-id.cnf
321 # Copy appropriate conf.d files from config-map to emptyDir.
322 if [[ $ordinal -eq 0 ]]; then
323 cp /mnt/config-map/primary.cnf /mnt/conf.d/
324 else
325 cp /mnt/config-map/replica.cnf /mnt/conf.d/
326 fi
327 volumeMounts:
328 - name: conf
329 mountPath: /mnt/conf.d
330 - name: config-map
331 mountPath: /mnt/config-map
332 containers:
333 - name: mysql
334 image: mysql:5.7
335 env:
336 - name: MYSQL_ROOT_PASSWORD
337 value: admin123
338 ports:
339 - name: mysql
340 containerPort: 3306
341 volumeMounts:
342 - name: data
343 mountPath: /var/lib/mysql
344 subPath: mysql
345 - name: conf
346 mountPath: /etc/mysql/conf.d
347 resources:
348 requests:
349 cpu: 100m
350 memory: 500Mi
351 volumes:
352 - name: conf
353 emptyDir: {}
354 - name: config-map
355 configMap:
356 name: mysql
357 volumeClaimTemplates:
358 - metadata:
359 name: data
360 spec:
361 accessModes: ["ReadWriteOnce"]
362 resources:
363 requests:
364 storage: 10Gi
365$MYSQL_ROOT_PASSWORD ==> $(MYSQL_ROOT_PASSWORD)
366#when calling env var inside command, you have to add the brackets
367-uroot -p$MYQSL_ROOT_PASSWORD ==> -u root --password=$(MYSQL_ROOT_PASSWORD)
368START SLAVE USER='root' PASSWORD=$(MYSQL_ROOT_PASSWORD);" || exit 1 ==> START SLAVE;" || exit 1
369MASTER_PASSWORD=$(MYSQL_ROOT_PASSWORD), \ ==> MASTER_PASSWORD='$(MYSQL_ROOT_PASSWORD)', \
370# have to put ' before and after getting the env value
371
Also, I noticed that the code from mine only works if you removed the livenessProbe
and readinessProbe
. Somehow, both of them is called before the env var gets loaded, that's why when readinessProbe
executes this command:
1apiVersion: apps/v1
2kind: StatefulSet
3metadata:
4 name: mysql
5spec:
6 selector:
7 matchLabels:
8 app: mysql
9 serviceName: mysql
10 replicas: 3
11 template:
12 metadata:
13 labels:
14 app: mysql
15 spec:
16 initContainers:
17 - name: init-mysql
18 image: mysql:5.7
19 env:
20 - name: MYSQL_ROOT_PASSWORD
21 valueFrom:
22 secretKeyRef:
23 name: mysql-secret
24 key: mysql-root-password
25 command:
26 - bash
27 - "-c"
28 - |
29 set -ex
30 # Generate mysql server-id from pod ordinal index.
31 [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
32 ordinal=${BASH_REMATCH[1]}
33 echo [mysqld] > /mnt/conf.d/server-id.cnf
34 # Add an offset to avoid reserved server-id=0 value.
35 echo server-id=$((100 + $ordinal)) >> /mnt/conf.d/server-id.cnf
36 # Copy appropriate conf.d files from config-map to emptyDir.
37 if [[ $ordinal -eq 0 ]]; then
38 cp /mnt/config-map/primary.cnf /mnt/conf.d/
39 else
40 cp /mnt/config-map/replica.cnf /mnt/conf.d/
41 fi
42 volumeMounts:
43 - name: conf
44 mountPath: /mnt/conf.d
45 - name: config-map
46 mountPath: /mnt/config-map
47 - name: clone-mysql
48 image: gcr.io/google-samples/xtrabackup:1.0
49 command:
50 - bash
51 - "-c"
52 - |
53 set -ex
54 # Skip the clone if data already exists.
55 [[ -d /var/lib/mysql/mysql ]] && exit 0
56 # Skip the clone on primary (ordinal index 0).
57 [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
58 ordinal=${BASH_REMATCH[1]}
59 [[ $ordinal -eq 0 ]] && exit 0
60 # Clone data from previous peer.
61 ncat --recv-only mysql-$(($ordinal-1)).mysql 3307 | xbstream -x -C /var/lib/mysql
62 # Prepare the backup.
63 xtrabackup --prepare --target-dir=/var/lib/mysql
64 volumeMounts:
65 - name: data
66 mountPath: /var/lib/mysql
67 subPath: mysql
68 - name: conf
69 mountPath: /etc/mysql/conf.d
70 containers:
71 - name: mysql
72 image: mysql:5.7
73 env:
74 - name: MYSQL_ROOT_PASSWORD
75 valueFrom:
76 secretKeyRef:
77 name: mysql-secret
78 key: mysql-root-password
79 ports:
80 - name: mysql
81 containerPort: 3306
82 volumeMounts:
83 - name: data
84 mountPath: /var/lib/mysql
85 subPath: mysql
86 - name: conf
87 mountPath: /etc/mysql/conf.d
88 resources:
89 requests:
90 cpu: 100m
91 memory: 500Mi
92 - name: xtrabackup
93 image: gcr.io/google-samples/xtrabackup:1.0
94 env:
95 - name: MYSQL_ROOT_PASSWORD
96 valueFrom:
97 secretKeyRef:
98 name: mysql-secret
99 key: mysql-root-password
100 ports:
101 - name: xtrabackup
102 containerPort: 3307
103 command:
104 - bash
105 - "-c"
106 - |
107 set -ex
108 cd /var/lib/mysql
109
110 # Determine binlog position of cloned data, if any.
111 if [[ -f xtrabackup_slave_info && "x$(<xtrabackup_slave_info)" != "x" ]]; then
112 # XtraBackup already generated a partial "CHANGE MASTER TO" query
113 # because we're cloning from an existing replica. (Need to remove the tailing semicolon!)
114 cat xtrabackup_slave_info | sed -E 's/;$//g' > change_master_to.sql.in
115 # Ignore xtrabackup_binlog_info in this case (it's useless).
116 rm -f xtrabackup_slave_info xtrabackup_binlog_info
117 elif [[ -f xtrabackup_binlog_info ]]; then
118 # We're cloning directly from primary. Parse binlog position.
119 [[ `cat xtrabackup_binlog_info` =~ ^(.*?)[[:space:]]+(.*?)$ ]] || exit 1
120 rm -f xtrabackup_binlog_info xtrabackup_slave_info
121 echo "CHANGE MASTER TO MASTER_LOG_FILE='${BASH_REMATCH[1]}',\
122 MASTER_LOG_POS=${BASH_REMATCH[2]}" > change_master_to.sql.in
123 fi
124
125 # Check if we need to complete a clone by starting replication.
126 if [[ -f change_master_to.sql.in ]]; then
127 echo "Waiting for mysqld to be ready (accepting connections)"
128 until mysql -h 127.0.0.1 -uroot -p$MYSQL_ROOT_PASSWORD -e "SELECT 1"; do sleep 1; done
129
130 echo "Initializing replication from clone position"
131 mysql -h 127.0.0.1 \
132 -e "$(<change_master_to.sql.in), \
133 MASTER_HOST='mysql-0.mysql', \
134 MASTER_USER='root', \
135 MASTER_PASSWORD=$MYSQL_ROOT_PASSWORD, \
136 MASTER_CONNECT_RETRY=10; \
137 START SLAVE USER='root' PASSWORD=$MYSQL_ROOT_PASSWORD;" || exit 1
138 # In case of container restart, attempt this at-most-once.
139 mv change_master_to.sql.in change_master_to.sql.orig
140 fi
141
142 # Start a server to send backups when requested by peers.
143 exec ncat --listen --keep-open --send-only --max-conns=1 3307 -c \
144 "xtrabackup --backup --slave-info --stream=xbstream --host=127.0.0.1 --user=root --password=$MYSQL_ROOT_PASSWORD"
145 volumeMounts:
146 - name: data
147 mountPath: /var/lib/mysql
148 subPath: mysql
149 - name: conf
150 mountPath: /etc/mysql/conf.d
151 resources:
152 requests:
153 cpu: 50m
154 memory: 50Mi
155 volumes:
156 - name: conf
157 emptyDir: {}
158 - name: config-map
159 configMap:
160 name: mysql
161 volumeClaimTemplates:
162 - metadata:
163 name: data
164 spec:
165 accessModes: ["ReadWriteOnce"]
166 resources:
167 requests:
168 storage: 10Gi
169NAME READY STATUS RESTARTS AGE
170pod/mysql-0 2/2 Running 0 11m
171pod/mysql-1 1/2 Error 7 11m
172pod/mysql-2 0/2 Init:CrashLoopBackOff 6 10m
173
174NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
175service/kubernetes ClusterIP 10.245.0.1 <none> 443/TCP 2d23h
176service/mysql ClusterIP None <none> 3306/TCP 43h
177service/mysql-read ClusterIP 10.245.81.173 <none> 3306/TCP 43h
178
179NAME READY UP-TO-DATE AVAILABLE AGE
180deployment.apps/phpmyadmin 1/1 1 1 2d18h
181
182NAME DESIRED CURRENT READY AGE
183replicaset.apps/phpmyadmin-6c57fd98bf 1 1 1 2d18h
184
185NAME READY AGE
186statefulset.apps/mysql 1/3 11m
187
188NAME TYPE DATA AGE
189secret/mysql-pass Opaque 1 46h
190secret/mysql-secret Opaque 3 2d18h
191
192NAME DATA AGE
193configmap/mysql 4 2d18h
194ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)
195 - name: MYSQL_ROOT_HOST
196 value: "%"
197NAME READY STATUS RESTARTS AGE
198mysql-0 0/2 Init:0/2 0 7s
199mysql-0 0/2 Init:1/2 0 18s
200mysql-0 0/2 PodInitializing 0 19s
201mysql-0 2/2 Running 0 20s
202mysql-1 0/2 Pending 0 0s
203mysql-1 0/2 Pending 0 0s
204mysql-1 0/2 Pending 0 8s
205mysql-1 0/2 Init:0/2 0 8s
206mysql-1 0/2 Init:1/2 0 26s
207mysql-1 0/2 Init:1/2 0 27s
208mysql-1 0/2 PodInitializing 0 34s
209mysql-1 2/2 Running 0 35s
210mysql-2 0/2 Pending 0 0s
211mysql-2 0/2 Pending 0 0s
212mysql-1 1/2 Error 0 37s
213mysql-1 1/2 Error 1 38s
214mysql-2 0/2 Pending 0 3s
215mysql-2 0/2 Init:0/2 0 3s
216mysql-1 1/2 CrashLoopBackOff 1 53s
217mysql-1 1/2 Error 2 54s
218mysql-2 0/2 Init:1/2 0 21s
219mysql-2 0/2 Init:Error 0 22s
220mysql-2 0/2 Init:Error 1 23s
221mysql-2 0/2 Init:CrashLoopBackOff 1 24s
222mysql-1 1/2 CrashLoopBackOff 2 64s
223mysql-2 0/2 Init:Error 2 38s
224mysql-1 1/2 Error 3 79s
225mysql-2 0/2 Init:CrashLoopBackOff 2 50s
226mysql-1 1/2 CrashLoopBackOff 3 92s
227mysql-2 0/2 Init:Error 3 62s
228mysql-2 0/2 Init:CrashLoopBackOff 3 74s
229mysql-1 1/2 Error 4 2m1s
230mysql-1 1/2 CrashLoopBackOff 4 2m11s
231mysql-2 0/2 Init:Error 4 113s
232mysql-2 0/2 Init:CrashLoopBackOff 4 2m6s
233mysql-1 1/2 Error 5 3m29s
234mysql-1 1/2 CrashLoopBackOff 5 3m41s
235mysql-2 0/2 Init:Error 5 3m23s
236mysql-2 0/2 Init:CrashLoopBackOff 5 3m34s
2372021-10-25 03:16:36+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.36-1debian10 started.
2382021-10-25 03:16:36+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
2392021-10-25 03:16:36+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.36-1debian10 started.
2402021-10-25T03:16:37.231906Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
2412021-10-25T03:16:37.234015Z 0 [Note] mysqld (mysqld 5.7.36) starting as process 1 ...
2422021-10-25T03:16:37.237044Z 0 [Note] InnoDB: PUNCH HOLE support available
2432021-10-25T03:16:37.237196Z 0 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
2442021-10-25T03:16:37.237263Z 0 [Note] InnoDB: Uses event mutexes
2452021-10-25T03:16:37.237345Z 0 [Note] InnoDB: GCC builtin __atomic_thread_fence() is used for memory barrier
2462021-10-25T03:16:37.237416Z 0 [Note] InnoDB: Compressed tables use zlib 1.2.11
2472021-10-25T03:16:37.237489Z 0 [Note] InnoDB: Using Linux native AIO
2482021-10-25T03:16:37.237792Z 0 [Note] InnoDB: Number of pools: 1
2492021-10-25T03:16:37.238102Z 0 [Note] InnoDB: Using CPU crc32 instructions
2502021-10-25T03:16:37.240179Z 0 [Note] InnoDB: Initializing buffer pool, total size = 128M, instances = 1, chunk size = 128M
2512021-10-25T03:16:37.248111Z 0 [Note] InnoDB: Completed initialization of buffer pool
2522021-10-25T03:16:37.251017Z 0 [Note] InnoDB: If the mysqld execution user is authorized, page cleaner thread priority can be changed. See the man page of setpriority().
2532021-10-25T03:16:37.263519Z 0 [Note] InnoDB: Highest supported file format is Barracuda.
2542021-10-25T03:16:37.307064Z 0 [Note] InnoDB: Removed temporary tablespace data file: "ibtmp1"
2552021-10-25T03:16:37.307319Z 0 [Note] InnoDB: Creating shared tablespace for temporary tables
2562021-10-25T03:16:37.307466Z 0 [Note] InnoDB: Setting file './ibtmp1' size to 12 MB. Physically writing the file full; Please wait ...
2572021-10-25T03:16:37.353707Z 0 [Note] InnoDB: File './ibtmp1' size is now 12 MB.
2582021-10-25T03:16:37.354244Z 0 [Note] InnoDB: 96 redo rollback segment(s) found. 96 redo rollback segment(s) are active.
2592021-10-25T03:16:37.354256Z 0 [Note] InnoDB: 32 non-redo rollback segment(s) are active.
2602021-10-25T03:16:37.355048Z 0 [Note] InnoDB: Waiting for purge to start
2612021-10-25T03:16:37.406335Z 0 [Note] InnoDB: 5.7.36 started; log sequence number 12660776
2622021-10-25T03:16:37.406850Z 0 [Note] Plugin 'FEDERATED' is disabled.
2632021-10-25T03:16:37.413880Z 0 [Note] InnoDB: Loading buffer pool(s) from /var/lib/mysql/ib_buffer_pool
2642021-10-25T03:16:37.426491Z 0 [Note] InnoDB: Buffer pool(s) load completed at 211025 3:16:37
2652021-10-25T03:16:37.427210Z 0 [Note] Salting uuid generator variables, current_pid: 1, server_start_time: 1635131797, bytes_sent: 0,
2662021-10-25T03:16:37.427438Z 0 [Note] Generated uuid: 'f6f89137-3541-11ec-84bc-f29710c93c86', server_start_time: 281476611842454, bytes_sent: 94355589700272
2672021-10-25T03:16:37.427554Z 0 [Warning] No existing UUID has been found, so we assume that this is the first time that this server has been started. Generating a new UUID: f6f89137-3541-11ec-84bc-f29710c93c86.
2682021-10-25T03:16:38.109098Z 0 [Note] Auto generated SSL certificates are placed in data directory.
2692021-10-25T03:16:38.109327Z 0 [Warning] A deprecated TLS version TLSv1 is enabled. Please use TLSv1.2 or higher.
2702021-10-25T03:16:38.109395Z 0 [Warning] A deprecated TLS version TLSv1.1 is enabled. Please use TLSv1.2 or higher.
2712021-10-25T03:16:38.109907Z 0 [Warning] CA certificate ca.pem is self signed.
2722021-10-25T03:16:38.354105Z 0 [Note] Auto generated RSA key files are placed in data directory.
2732021-10-25T03:16:38.354795Z 0 [Note] Server hostname (bind-address): '*'; port: 3306
2742021-10-25T03:16:38.354968Z 0 [Note] IPv6 is available.
2752021-10-25T03:16:38.355039Z 0 [Note] - '::' resolves to '::';
2762021-10-25T03:16:38.355125Z 0 [Note] Server socket created on IP: '::'.
2772021-10-25T03:16:38.357907Z 0 [Warning] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory.
2782021-10-25T03:16:38.361720Z 0 [Note] Failed to start slave threads for channel ''
2792021-10-25T03:16:38.366691Z 0 [Note] Event Scheduler: Loaded 0 events
2802021-10-25T03:16:38.367135Z 0 [Note] mysqld: ready for connections.
281Version: '5.7.36' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server (GPL)
2822021-10-25T03:16:39.011694Z 3 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2832021-10-25T03:16:39.759020Z 5 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2842021-10-25T03:16:56.006754Z 7 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2852021-10-25T03:17:21.016988Z 9 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2862021-10-25T03:18:03.010443Z 11 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2872021-10-25T03:19:30.984929Z 13 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2882021-10-25T03:22:25.011291Z 15 [Note] Access denied for user 'root'@'localhost' (using password: NO)
289apiVersion: apps/v1
290kind: StatefulSet
291metadata:
292 name: mysql
293spec:
294 selector:
295 matchLabels:
296 app: mysql
297 serviceName: mysql
298 replicas: 3
299 template:
300 metadata:
301 labels:
302 app: mysql
303 spec:
304 initContainers:
305 - name: init-mysql
306 image: mysql:5.7
307 env:
308 - name: MYSQL_ROOT_PASSWORD
309 value: admin123
310 command:
311 - bash
312 - "-c"
313 - |
314 set -ex
315 # Generate mysql server-id from pod ordinal index.
316 [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
317 ordinal=${BASH_REMATCH[1]}
318 echo [mysqld] > /mnt/conf.d/server-id.cnf
319 # Add an offset to avoid reserved server-id=0 value.
320 echo server-id=$((100 + $ordinal)) >> /mnt/conf.d/server-id.cnf
321 # Copy appropriate conf.d files from config-map to emptyDir.
322 if [[ $ordinal -eq 0 ]]; then
323 cp /mnt/config-map/primary.cnf /mnt/conf.d/
324 else
325 cp /mnt/config-map/replica.cnf /mnt/conf.d/
326 fi
327 volumeMounts:
328 - name: conf
329 mountPath: /mnt/conf.d
330 - name: config-map
331 mountPath: /mnt/config-map
332 containers:
333 - name: mysql
334 image: mysql:5.7
335 env:
336 - name: MYSQL_ROOT_PASSWORD
337 value: admin123
338 ports:
339 - name: mysql
340 containerPort: 3306
341 volumeMounts:
342 - name: data
343 mountPath: /var/lib/mysql
344 subPath: mysql
345 - name: conf
346 mountPath: /etc/mysql/conf.d
347 resources:
348 requests:
349 cpu: 100m
350 memory: 500Mi
351 volumes:
352 - name: conf
353 emptyDir: {}
354 - name: config-map
355 configMap:
356 name: mysql
357 volumeClaimTemplates:
358 - metadata:
359 name: data
360 spec:
361 accessModes: ["ReadWriteOnce"]
362 resources:
363 requests:
364 storage: 10Gi
365$MYSQL_ROOT_PASSWORD ==> $(MYSQL_ROOT_PASSWORD)
366#when calling env var inside command, you have to add the brackets
367-uroot -p$MYQSL_ROOT_PASSWORD ==> -u root --password=$(MYSQL_ROOT_PASSWORD)
368START SLAVE USER='root' PASSWORD=$(MYSQL_ROOT_PASSWORD);" || exit 1 ==> START SLAVE;" || exit 1
369MASTER_PASSWORD=$(MYSQL_ROOT_PASSWORD), \ ==> MASTER_PASSWORD='$(MYSQL_ROOT_PASSWORD)', \
370# have to put ' before and after getting the env value
371command: ["mysql", "-h", "127.0.0.1", "-u", "root", "--password=$(MYSQL_ROOT_PASSWORD)", "-e", "SELECT 1"]
372
it failed because $(MYSQL_ROOT_PASSWORD)
's value was not found, therefore, resulting this error:
1apiVersion: apps/v1
2kind: StatefulSet
3metadata:
4 name: mysql
5spec:
6 selector:
7 matchLabels:
8 app: mysql
9 serviceName: mysql
10 replicas: 3
11 template:
12 metadata:
13 labels:
14 app: mysql
15 spec:
16 initContainers:
17 - name: init-mysql
18 image: mysql:5.7
19 env:
20 - name: MYSQL_ROOT_PASSWORD
21 valueFrom:
22 secretKeyRef:
23 name: mysql-secret
24 key: mysql-root-password
25 command:
26 - bash
27 - "-c"
28 - |
29 set -ex
30 # Generate mysql server-id from pod ordinal index.
31 [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
32 ordinal=${BASH_REMATCH[1]}
33 echo [mysqld] > /mnt/conf.d/server-id.cnf
34 # Add an offset to avoid reserved server-id=0 value.
35 echo server-id=$((100 + $ordinal)) >> /mnt/conf.d/server-id.cnf
36 # Copy appropriate conf.d files from config-map to emptyDir.
37 if [[ $ordinal -eq 0 ]]; then
38 cp /mnt/config-map/primary.cnf /mnt/conf.d/
39 else
40 cp /mnt/config-map/replica.cnf /mnt/conf.d/
41 fi
42 volumeMounts:
43 - name: conf
44 mountPath: /mnt/conf.d
45 - name: config-map
46 mountPath: /mnt/config-map
47 - name: clone-mysql
48 image: gcr.io/google-samples/xtrabackup:1.0
49 command:
50 - bash
51 - "-c"
52 - |
53 set -ex
54 # Skip the clone if data already exists.
55 [[ -d /var/lib/mysql/mysql ]] && exit 0
56 # Skip the clone on primary (ordinal index 0).
57 [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
58 ordinal=${BASH_REMATCH[1]}
59 [[ $ordinal -eq 0 ]] && exit 0
60 # Clone data from previous peer.
61 ncat --recv-only mysql-$(($ordinal-1)).mysql 3307 | xbstream -x -C /var/lib/mysql
62 # Prepare the backup.
63 xtrabackup --prepare --target-dir=/var/lib/mysql
64 volumeMounts:
65 - name: data
66 mountPath: /var/lib/mysql
67 subPath: mysql
68 - name: conf
69 mountPath: /etc/mysql/conf.d
70 containers:
71 - name: mysql
72 image: mysql:5.7
73 env:
74 - name: MYSQL_ROOT_PASSWORD
75 valueFrom:
76 secretKeyRef:
77 name: mysql-secret
78 key: mysql-root-password
79 ports:
80 - name: mysql
81 containerPort: 3306
82 volumeMounts:
83 - name: data
84 mountPath: /var/lib/mysql
85 subPath: mysql
86 - name: conf
87 mountPath: /etc/mysql/conf.d
88 resources:
89 requests:
90 cpu: 100m
91 memory: 500Mi
92 - name: xtrabackup
93 image: gcr.io/google-samples/xtrabackup:1.0
94 env:
95 - name: MYSQL_ROOT_PASSWORD
96 valueFrom:
97 secretKeyRef:
98 name: mysql-secret
99 key: mysql-root-password
100 ports:
101 - name: xtrabackup
102 containerPort: 3307
103 command:
104 - bash
105 - "-c"
106 - |
107 set -ex
108 cd /var/lib/mysql
109
110 # Determine binlog position of cloned data, if any.
111 if [[ -f xtrabackup_slave_info && "x$(<xtrabackup_slave_info)" != "x" ]]; then
112 # XtraBackup already generated a partial "CHANGE MASTER TO" query
113 # because we're cloning from an existing replica. (Need to remove the tailing semicolon!)
114 cat xtrabackup_slave_info | sed -E 's/;$//g' > change_master_to.sql.in
115 # Ignore xtrabackup_binlog_info in this case (it's useless).
116 rm -f xtrabackup_slave_info xtrabackup_binlog_info
117 elif [[ -f xtrabackup_binlog_info ]]; then
118 # We're cloning directly from primary. Parse binlog position.
119 [[ `cat xtrabackup_binlog_info` =~ ^(.*?)[[:space:]]+(.*?)$ ]] || exit 1
120 rm -f xtrabackup_binlog_info xtrabackup_slave_info
121 echo "CHANGE MASTER TO MASTER_LOG_FILE='${BASH_REMATCH[1]}',\
122 MASTER_LOG_POS=${BASH_REMATCH[2]}" > change_master_to.sql.in
123 fi
124
125 # Check if we need to complete a clone by starting replication.
126 if [[ -f change_master_to.sql.in ]]; then
127 echo "Waiting for mysqld to be ready (accepting connections)"
128 until mysql -h 127.0.0.1 -uroot -p$MYSQL_ROOT_PASSWORD -e "SELECT 1"; do sleep 1; done
129
130 echo "Initializing replication from clone position"
131 mysql -h 127.0.0.1 \
132 -e "$(<change_master_to.sql.in), \
133 MASTER_HOST='mysql-0.mysql', \
134 MASTER_USER='root', \
135 MASTER_PASSWORD=$MYSQL_ROOT_PASSWORD, \
136 MASTER_CONNECT_RETRY=10; \
137 START SLAVE USER='root' PASSWORD=$MYSQL_ROOT_PASSWORD;" || exit 1
138 # In case of container restart, attempt this at-most-once.
139 mv change_master_to.sql.in change_master_to.sql.orig
140 fi
141
142 # Start a server to send backups when requested by peers.
143 exec ncat --listen --keep-open --send-only --max-conns=1 3307 -c \
144 "xtrabackup --backup --slave-info --stream=xbstream --host=127.0.0.1 --user=root --password=$MYSQL_ROOT_PASSWORD"
145 volumeMounts:
146 - name: data
147 mountPath: /var/lib/mysql
148 subPath: mysql
149 - name: conf
150 mountPath: /etc/mysql/conf.d
151 resources:
152 requests:
153 cpu: 50m
154 memory: 50Mi
155 volumes:
156 - name: conf
157 emptyDir: {}
158 - name: config-map
159 configMap:
160 name: mysql
161 volumeClaimTemplates:
162 - metadata:
163 name: data
164 spec:
165 accessModes: ["ReadWriteOnce"]
166 resources:
167 requests:
168 storage: 10Gi
169NAME READY STATUS RESTARTS AGE
170pod/mysql-0 2/2 Running 0 11m
171pod/mysql-1 1/2 Error 7 11m
172pod/mysql-2 0/2 Init:CrashLoopBackOff 6 10m
173
174NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
175service/kubernetes ClusterIP 10.245.0.1 <none> 443/TCP 2d23h
176service/mysql ClusterIP None <none> 3306/TCP 43h
177service/mysql-read ClusterIP 10.245.81.173 <none> 3306/TCP 43h
178
179NAME READY UP-TO-DATE AVAILABLE AGE
180deployment.apps/phpmyadmin 1/1 1 1 2d18h
181
182NAME DESIRED CURRENT READY AGE
183replicaset.apps/phpmyadmin-6c57fd98bf 1 1 1 2d18h
184
185NAME READY AGE
186statefulset.apps/mysql 1/3 11m
187
188NAME TYPE DATA AGE
189secret/mysql-pass Opaque 1 46h
190secret/mysql-secret Opaque 3 2d18h
191
192NAME DATA AGE
193configmap/mysql 4 2d18h
194ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)
195 - name: MYSQL_ROOT_HOST
196 value: "%"
197NAME READY STATUS RESTARTS AGE
198mysql-0 0/2 Init:0/2 0 7s
199mysql-0 0/2 Init:1/2 0 18s
200mysql-0 0/2 PodInitializing 0 19s
201mysql-0 2/2 Running 0 20s
202mysql-1 0/2 Pending 0 0s
203mysql-1 0/2 Pending 0 0s
204mysql-1 0/2 Pending 0 8s
205mysql-1 0/2 Init:0/2 0 8s
206mysql-1 0/2 Init:1/2 0 26s
207mysql-1 0/2 Init:1/2 0 27s
208mysql-1 0/2 PodInitializing 0 34s
209mysql-1 2/2 Running 0 35s
210mysql-2 0/2 Pending 0 0s
211mysql-2 0/2 Pending 0 0s
212mysql-1 1/2 Error 0 37s
213mysql-1 1/2 Error 1 38s
214mysql-2 0/2 Pending 0 3s
215mysql-2 0/2 Init:0/2 0 3s
216mysql-1 1/2 CrashLoopBackOff 1 53s
217mysql-1 1/2 Error 2 54s
218mysql-2 0/2 Init:1/2 0 21s
219mysql-2 0/2 Init:Error 0 22s
220mysql-2 0/2 Init:Error 1 23s
221mysql-2 0/2 Init:CrashLoopBackOff 1 24s
222mysql-1 1/2 CrashLoopBackOff 2 64s
223mysql-2 0/2 Init:Error 2 38s
224mysql-1 1/2 Error 3 79s
225mysql-2 0/2 Init:CrashLoopBackOff 2 50s
226mysql-1 1/2 CrashLoopBackOff 3 92s
227mysql-2 0/2 Init:Error 3 62s
228mysql-2 0/2 Init:CrashLoopBackOff 3 74s
229mysql-1 1/2 Error 4 2m1s
230mysql-1 1/2 CrashLoopBackOff 4 2m11s
231mysql-2 0/2 Init:Error 4 113s
232mysql-2 0/2 Init:CrashLoopBackOff 4 2m6s
233mysql-1 1/2 Error 5 3m29s
234mysql-1 1/2 CrashLoopBackOff 5 3m41s
235mysql-2 0/2 Init:Error 5 3m23s
236mysql-2 0/2 Init:CrashLoopBackOff 5 3m34s
2372021-10-25 03:16:36+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.36-1debian10 started.
2382021-10-25 03:16:36+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
2392021-10-25 03:16:36+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.36-1debian10 started.
2402021-10-25T03:16:37.231906Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
2412021-10-25T03:16:37.234015Z 0 [Note] mysqld (mysqld 5.7.36) starting as process 1 ...
2422021-10-25T03:16:37.237044Z 0 [Note] InnoDB: PUNCH HOLE support available
2432021-10-25T03:16:37.237196Z 0 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
2442021-10-25T03:16:37.237263Z 0 [Note] InnoDB: Uses event mutexes
2452021-10-25T03:16:37.237345Z 0 [Note] InnoDB: GCC builtin __atomic_thread_fence() is used for memory barrier
2462021-10-25T03:16:37.237416Z 0 [Note] InnoDB: Compressed tables use zlib 1.2.11
2472021-10-25T03:16:37.237489Z 0 [Note] InnoDB: Using Linux native AIO
2482021-10-25T03:16:37.237792Z 0 [Note] InnoDB: Number of pools: 1
2492021-10-25T03:16:37.238102Z 0 [Note] InnoDB: Using CPU crc32 instructions
2502021-10-25T03:16:37.240179Z 0 [Note] InnoDB: Initializing buffer pool, total size = 128M, instances = 1, chunk size = 128M
2512021-10-25T03:16:37.248111Z 0 [Note] InnoDB: Completed initialization of buffer pool
2522021-10-25T03:16:37.251017Z 0 [Note] InnoDB: If the mysqld execution user is authorized, page cleaner thread priority can be changed. See the man page of setpriority().
2532021-10-25T03:16:37.263519Z 0 [Note] InnoDB: Highest supported file format is Barracuda.
2542021-10-25T03:16:37.307064Z 0 [Note] InnoDB: Removed temporary tablespace data file: "ibtmp1"
2552021-10-25T03:16:37.307319Z 0 [Note] InnoDB: Creating shared tablespace for temporary tables
2562021-10-25T03:16:37.307466Z 0 [Note] InnoDB: Setting file './ibtmp1' size to 12 MB. Physically writing the file full; Please wait ...
2572021-10-25T03:16:37.353707Z 0 [Note] InnoDB: File './ibtmp1' size is now 12 MB.
2582021-10-25T03:16:37.354244Z 0 [Note] InnoDB: 96 redo rollback segment(s) found. 96 redo rollback segment(s) are active.
2592021-10-25T03:16:37.354256Z 0 [Note] InnoDB: 32 non-redo rollback segment(s) are active.
2602021-10-25T03:16:37.355048Z 0 [Note] InnoDB: Waiting for purge to start
2612021-10-25T03:16:37.406335Z 0 [Note] InnoDB: 5.7.36 started; log sequence number 12660776
2622021-10-25T03:16:37.406850Z 0 [Note] Plugin 'FEDERATED' is disabled.
2632021-10-25T03:16:37.413880Z 0 [Note] InnoDB: Loading buffer pool(s) from /var/lib/mysql/ib_buffer_pool
2642021-10-25T03:16:37.426491Z 0 [Note] InnoDB: Buffer pool(s) load completed at 211025 3:16:37
2652021-10-25T03:16:37.427210Z 0 [Note] Salting uuid generator variables, current_pid: 1, server_start_time: 1635131797, bytes_sent: 0,
2662021-10-25T03:16:37.427438Z 0 [Note] Generated uuid: 'f6f89137-3541-11ec-84bc-f29710c93c86', server_start_time: 281476611842454, bytes_sent: 94355589700272
2672021-10-25T03:16:37.427554Z 0 [Warning] No existing UUID has been found, so we assume that this is the first time that this server has been started. Generating a new UUID: f6f89137-3541-11ec-84bc-f29710c93c86.
2682021-10-25T03:16:38.109098Z 0 [Note] Auto generated SSL certificates are placed in data directory.
2692021-10-25T03:16:38.109327Z 0 [Warning] A deprecated TLS version TLSv1 is enabled. Please use TLSv1.2 or higher.
2702021-10-25T03:16:38.109395Z 0 [Warning] A deprecated TLS version TLSv1.1 is enabled. Please use TLSv1.2 or higher.
2712021-10-25T03:16:38.109907Z 0 [Warning] CA certificate ca.pem is self signed.
2722021-10-25T03:16:38.354105Z 0 [Note] Auto generated RSA key files are placed in data directory.
2732021-10-25T03:16:38.354795Z 0 [Note] Server hostname (bind-address): '*'; port: 3306
2742021-10-25T03:16:38.354968Z 0 [Note] IPv6 is available.
2752021-10-25T03:16:38.355039Z 0 [Note] - '::' resolves to '::';
2762021-10-25T03:16:38.355125Z 0 [Note] Server socket created on IP: '::'.
2772021-10-25T03:16:38.357907Z 0 [Warning] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory.
2782021-10-25T03:16:38.361720Z 0 [Note] Failed to start slave threads for channel ''
2792021-10-25T03:16:38.366691Z 0 [Note] Event Scheduler: Loaded 0 events
2802021-10-25T03:16:38.367135Z 0 [Note] mysqld: ready for connections.
281Version: '5.7.36' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server (GPL)
2822021-10-25T03:16:39.011694Z 3 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2832021-10-25T03:16:39.759020Z 5 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2842021-10-25T03:16:56.006754Z 7 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2852021-10-25T03:17:21.016988Z 9 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2862021-10-25T03:18:03.010443Z 11 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2872021-10-25T03:19:30.984929Z 13 [Note] Access denied for user 'root'@'localhost' (using password: NO)
2882021-10-25T03:22:25.011291Z 15 [Note] Access denied for user 'root'@'localhost' (using password: NO)
289apiVersion: apps/v1
290kind: StatefulSet
291metadata:
292 name: mysql
293spec:
294 selector:
295 matchLabels:
296 app: mysql
297 serviceName: mysql
298 replicas: 3
299 template:
300 metadata:
301 labels:
302 app: mysql
303 spec:
304 initContainers:
305 - name: init-mysql
306 image: mysql:5.7
307 env:
308 - name: MYSQL_ROOT_PASSWORD
309 value: admin123
310 command:
311 - bash
312 - "-c"
313 - |
314 set -ex
315 # Generate mysql server-id from pod ordinal index.
316 [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
317 ordinal=${BASH_REMATCH[1]}
318 echo [mysqld] > /mnt/conf.d/server-id.cnf
319 # Add an offset to avoid reserved server-id=0 value.
320 echo server-id=$((100 + $ordinal)) >> /mnt/conf.d/server-id.cnf
321 # Copy appropriate conf.d files from config-map to emptyDir.
322 if [[ $ordinal -eq 0 ]]; then
323 cp /mnt/config-map/primary.cnf /mnt/conf.d/
324 else
325 cp /mnt/config-map/replica.cnf /mnt/conf.d/
326 fi
327 volumeMounts:
328 - name: conf
329 mountPath: /mnt/conf.d
330 - name: config-map
331 mountPath: /mnt/config-map
332 containers:
333 - name: mysql
334 image: mysql:5.7
335 env:
336 - name: MYSQL_ROOT_PASSWORD
337 value: admin123
338 ports:
339 - name: mysql
340 containerPort: 3306
341 volumeMounts:
342 - name: data
343 mountPath: /var/lib/mysql
344 subPath: mysql
345 - name: conf
346 mountPath: /etc/mysql/conf.d
347 resources:
348 requests:
349 cpu: 100m
350 memory: 500Mi
351 volumes:
352 - name: conf
353 emptyDir: {}
354 - name: config-map
355 configMap:
356 name: mysql
357 volumeClaimTemplates:
358 - metadata:
359 name: data
360 spec:
361 accessModes: ["ReadWriteOnce"]
362 resources:
363 requests:
364 storage: 10Gi
365$MYSQL_ROOT_PASSWORD ==> $(MYSQL_ROOT_PASSWORD)
366#when calling env var inside command, you have to add the brackets
367-uroot -p$MYQSL_ROOT_PASSWORD ==> -u root --password=$(MYSQL_ROOT_PASSWORD)
368START SLAVE USER='root' PASSWORD=$(MYSQL_ROOT_PASSWORD);" || exit 1 ==> START SLAVE;" || exit 1
369MASTER_PASSWORD=$(MYSQL_ROOT_PASSWORD), \ ==> MASTER_PASSWORD='$(MYSQL_ROOT_PASSWORD)', \
370# have to put ' before and after getting the env value
371command: ["mysql", "-h", "127.0.0.1", "-u", "root", "--password=$(MYSQL_ROOT_PASSWORD)", "-e", "SELECT 1"]
3722021-10-25T03:16:39.011694Z 3 [Note] Access denied for user 'root'@'localhost' (using password: NO)
373
If someone has any additional info between livenessProbe
, readinessProbe
, and env var, please let me know, because my theory might be wrong. CMIIW. :)
QUESTION
How to convert a UUID to a number with less than 40 digits?
Asked 2022-Feb-17 at 17:49I need to convert a UUID (like ffffffff-ffff-ffff-ffff-ffffffffffff
) to a number with as least digits as possible. These UUIDs are being generated by com.fasterxml.uuid.impl.TimeBasedGenerator.java.
1package com.fasterxml.uuid.impl;
2
3import java.util.UUID;
4
5import com.fasterxml.uuid.*;
6
7/**
8 * Implementation of UUID generator that uses time/location based generation
9 * method (variant 1).
10 *<p>
11 * As all JUG provided implementations, this generator is fully thread-safe.
12 * Additionally it can also be made externally synchronized with other
13 * instances (even ones running on other JVMs); to do this,
14 * use {@link com.fasterxml.uuid.ext.FileBasedTimestampSynchronizer}
15 * (or equivalent).
16 *
17 * @since 3.0
18 */
19public class TimeBasedGenerator extends NoArgGenerator
20{
21 /*
22 /**********************************************************************
23 /* Configuration
24 /**********************************************************************
25 */
26
27 protected final EthernetAddress _ethernetAddress;
28
29 /**
30 * Object used for synchronizing access to timestamps, to guarantee
31 * that timestamps produced by this generator are unique and monotonically increasings.
32 * Some implementations offer even stronger guarantees, for example that
33 * same guarantee holds between instances running on different JVMs (or
34 * with native code).
35 */
36 protected final UUIDTimer _timer;
37
38 /**
39 * Base values for the second long (last 8 bytes) of UUID to construct
40 */
41 protected final long _uuidL2;
42
43 /*
44 /**********************************************************************
45 /* Construction
46 /**********************************************************************
47 */
48
49 /**
50 * @param ethAddr Hardware address (802.1) to use for generating
51 * spatially unique part of UUID. If system has more than one NIC,
52 */
53
54 public TimeBasedGenerator(EthernetAddress ethAddr, UUIDTimer timer)
55 {
56 byte[] uuidBytes = new byte[16];
57 if (ethAddr == null) {
58 ethAddr = EthernetAddress.constructMulticastAddress();
59 }
60 // initialize baseline with MAC address info
61 _ethernetAddress = ethAddr;
62 _ethernetAddress.toByteArray(uuidBytes, 10);
63 // and add clock sequence
64 int clockSeq = timer.getClockSequence();
65 uuidBytes[UUIDUtil.BYTE_OFFSET_CLOCK_SEQUENCE] = (byte) (clockSeq >> 8);
66 uuidBytes[UUIDUtil.BYTE_OFFSET_CLOCK_SEQUENCE+1] = (byte) clockSeq;
67 long l2 = UUIDUtil.gatherLong(uuidBytes, 8);
68 _uuidL2 = UUIDUtil.initUUIDSecondLong(l2);
69 _timer = timer;
70 }
71
72 /*
73 /**********************************************************************
74 /* Access to config
75 /**********************************************************************
76 */
77
78 @Override
79 public UUIDType getType() { return UUIDType.TIME_BASED; }
80
81 public EthernetAddress getEthernetAddress() { return _ethernetAddress; }
82
83 /*
84 /**********************************************************************
85 /* UUID generation
86 /**********************************************************************
87 */
88
89 /* As timer is not synchronized (nor _uuidBytes), need to sync; but most
90 * importantly, synchronize on timer which may also be shared between
91 * multiple instances
92 */
93 @Override
94 public UUID generate()
95 {
96 final long rawTimestamp = _timer.getTimestamp();
97 // Time field components are kind of shuffled, need to slice:
98 int clockHi = (int) (rawTimestamp >>> 32);
99 int clockLo = (int) rawTimestamp;
100 // and dice
101 int midhi = (clockHi << 16) | (clockHi >>> 16);
102 // need to squeeze in type (4 MSBs in byte 6, clock hi)
103 midhi &= ~0xF000; // remove high nibble of 6th byte
104 midhi |= 0x1000; // type 1
105 long midhiL = (long) midhi;
106 midhiL = ((midhiL << 32) >>> 32); // to get rid of sign extension
107 // and reconstruct
108 long l1 = (((long) clockLo) << 32) | midhiL;
109 // last detail: must force 2 MSB to be '10'
110 return new UUID(l1, _uuidL2);
111 }
112}
113
I expect that every day at least 12 million UUIDs will be generated on a particular machine. I assume that TimeBasedGenerator
will be instatiated once when the program starts and thus will have a constant network address and a constant random generator seed time (value now
in the code snipped below).
1package com.fasterxml.uuid.impl;
2
3import java.util.UUID;
4
5import com.fasterxml.uuid.*;
6
7/**
8 * Implementation of UUID generator that uses time/location based generation
9 * method (variant 1).
10 *<p>
11 * As all JUG provided implementations, this generator is fully thread-safe.
12 * Additionally it can also be made externally synchronized with other
13 * instances (even ones running on other JVMs); to do this,
14 * use {@link com.fasterxml.uuid.ext.FileBasedTimestampSynchronizer}
15 * (or equivalent).
16 *
17 * @since 3.0
18 */
19public class TimeBasedGenerator extends NoArgGenerator
20{
21 /*
22 /**********************************************************************
23 /* Configuration
24 /**********************************************************************
25 */
26
27 protected final EthernetAddress _ethernetAddress;
28
29 /**
30 * Object used for synchronizing access to timestamps, to guarantee
31 * that timestamps produced by this generator are unique and monotonically increasings.
32 * Some implementations offer even stronger guarantees, for example that
33 * same guarantee holds between instances running on different JVMs (or
34 * with native code).
35 */
36 protected final UUIDTimer _timer;
37
38 /**
39 * Base values for the second long (last 8 bytes) of UUID to construct
40 */
41 protected final long _uuidL2;
42
43 /*
44 /**********************************************************************
45 /* Construction
46 /**********************************************************************
47 */
48
49 /**
50 * @param ethAddr Hardware address (802.1) to use for generating
51 * spatially unique part of UUID. If system has more than one NIC,
52 */
53
54 public TimeBasedGenerator(EthernetAddress ethAddr, UUIDTimer timer)
55 {
56 byte[] uuidBytes = new byte[16];
57 if (ethAddr == null) {
58 ethAddr = EthernetAddress.constructMulticastAddress();
59 }
60 // initialize baseline with MAC address info
61 _ethernetAddress = ethAddr;
62 _ethernetAddress.toByteArray(uuidBytes, 10);
63 // and add clock sequence
64 int clockSeq = timer.getClockSequence();
65 uuidBytes[UUIDUtil.BYTE_OFFSET_CLOCK_SEQUENCE] = (byte) (clockSeq >> 8);
66 uuidBytes[UUIDUtil.BYTE_OFFSET_CLOCK_SEQUENCE+1] = (byte) clockSeq;
67 long l2 = UUIDUtil.gatherLong(uuidBytes, 8);
68 _uuidL2 = UUIDUtil.initUUIDSecondLong(l2);
69 _timer = timer;
70 }
71
72 /*
73 /**********************************************************************
74 /* Access to config
75 /**********************************************************************
76 */
77
78 @Override
79 public UUIDType getType() { return UUIDType.TIME_BASED; }
80
81 public EthernetAddress getEthernetAddress() { return _ethernetAddress; }
82
83 /*
84 /**********************************************************************
85 /* UUID generation
86 /**********************************************************************
87 */
88
89 /* As timer is not synchronized (nor _uuidBytes), need to sync; but most
90 * importantly, synchronize on timer which may also be shared between
91 * multiple instances
92 */
93 @Override
94 public UUID generate()
95 {
96 final long rawTimestamp = _timer.getTimestamp();
97 // Time field components are kind of shuffled, need to slice:
98 int clockHi = (int) (rawTimestamp >>> 32);
99 int clockLo = (int) rawTimestamp;
100 // and dice
101 int midhi = (clockHi << 16) | (clockHi >>> 16);
102 // need to squeeze in type (4 MSBs in byte 6, clock hi)
103 midhi &= ~0xF000; // remove high nibble of 6th byte
104 midhi |= 0x1000; // type 1
105 long midhiL = (long) midhi;
106 midhiL = ((midhiL << 32) >>> 32); // to get rid of sign extension
107 // and reconstruct
108 long l1 = (((long) clockLo) << 32) | midhiL;
109 // last detail: must force 2 MSB to be '10'
110 return new UUID(l1, _uuidL2);
111 }
112}
113final long now = 1644575806478L;
114
115final TimeBasedGenerator sut = new TimeBasedGenerator(EthernetAddress.fromInterface(),
116 new UUIDTimer(new Random(now), null));
117
How can I turn a UUID into a number with
a) less than 40 digits and
b) so that duplicate UUIDs occur once in 6 months the earliest?
Failed attempt 1
The simplest way to convert a UUID to a number looks like this:
1package com.fasterxml.uuid.impl;
2
3import java.util.UUID;
4
5import com.fasterxml.uuid.*;
6
7/**
8 * Implementation of UUID generator that uses time/location based generation
9 * method (variant 1).
10 *<p>
11 * As all JUG provided implementations, this generator is fully thread-safe.
12 * Additionally it can also be made externally synchronized with other
13 * instances (even ones running on other JVMs); to do this,
14 * use {@link com.fasterxml.uuid.ext.FileBasedTimestampSynchronizer}
15 * (or equivalent).
16 *
17 * @since 3.0
18 */
19public class TimeBasedGenerator extends NoArgGenerator
20{
21 /*
22 /**********************************************************************
23 /* Configuration
24 /**********************************************************************
25 */
26
27 protected final EthernetAddress _ethernetAddress;
28
29 /**
30 * Object used for synchronizing access to timestamps, to guarantee
31 * that timestamps produced by this generator are unique and monotonically increasings.
32 * Some implementations offer even stronger guarantees, for example that
33 * same guarantee holds between instances running on different JVMs (or
34 * with native code).
35 */
36 protected final UUIDTimer _timer;
37
38 /**
39 * Base values for the second long (last 8 bytes) of UUID to construct
40 */
41 protected final long _uuidL2;
42
43 /*
44 /**********************************************************************
45 /* Construction
46 /**********************************************************************
47 */
48
49 /**
50 * @param ethAddr Hardware address (802.1) to use for generating
51 * spatially unique part of UUID. If system has more than one NIC,
52 */
53
54 public TimeBasedGenerator(EthernetAddress ethAddr, UUIDTimer timer)
55 {
56 byte[] uuidBytes = new byte[16];
57 if (ethAddr == null) {
58 ethAddr = EthernetAddress.constructMulticastAddress();
59 }
60 // initialize baseline with MAC address info
61 _ethernetAddress = ethAddr;
62 _ethernetAddress.toByteArray(uuidBytes, 10);
63 // and add clock sequence
64 int clockSeq = timer.getClockSequence();
65 uuidBytes[UUIDUtil.BYTE_OFFSET_CLOCK_SEQUENCE] = (byte) (clockSeq >> 8);
66 uuidBytes[UUIDUtil.BYTE_OFFSET_CLOCK_SEQUENCE+1] = (byte) clockSeq;
67 long l2 = UUIDUtil.gatherLong(uuidBytes, 8);
68 _uuidL2 = UUIDUtil.initUUIDSecondLong(l2);
69 _timer = timer;
70 }
71
72 /*
73 /**********************************************************************
74 /* Access to config
75 /**********************************************************************
76 */
77
78 @Override
79 public UUIDType getType() { return UUIDType.TIME_BASED; }
80
81 public EthernetAddress getEthernetAddress() { return _ethernetAddress; }
82
83 /*
84 /**********************************************************************
85 /* UUID generation
86 /**********************************************************************
87 */
88
89 /* As timer is not synchronized (nor _uuidBytes), need to sync; but most
90 * importantly, synchronize on timer which may also be shared between
91 * multiple instances
92 */
93 @Override
94 public UUID generate()
95 {
96 final long rawTimestamp = _timer.getTimestamp();
97 // Time field components are kind of shuffled, need to slice:
98 int clockHi = (int) (rawTimestamp >>> 32);
99 int clockLo = (int) rawTimestamp;
100 // and dice
101 int midhi = (clockHi << 16) | (clockHi >>> 16);
102 // need to squeeze in type (4 MSBs in byte 6, clock hi)
103 midhi &= ~0xF000; // remove high nibble of 6th byte
104 midhi |= 0x1000; // type 1
105 long midhiL = (long) midhi;
106 midhiL = ((midhiL << 32) >>> 32); // to get rid of sign extension
107 // and reconstruct
108 long l1 = (((long) clockLo) << 32) | midhiL;
109 // last detail: must force 2 MSB to be '10'
110 return new UUID(l1, _uuidL2);
111 }
112}
113final long now = 1644575806478L;
114
115final TimeBasedGenerator sut = new TimeBasedGenerator(EthernetAddress.fromInterface(),
116 new UUIDTimer(new Random(now), null));
117import java.math.BigInteger;
118import java.util.function.Function;
119
120public class OldUUIDConverter implements Function<String, BigInteger> {
121 @Override
122 public BigInteger apply(final String uuid) {
123 final String uuidWithoutDashes = uuid.replaceAll("-", "");
124 return new BigInteger(uuidWithoutDashes, 16);
125 }
126}
127
For the largest possible UUID (ffffffff-ffff-ffff-ffff-ffffffffffff
) it producees the number
1package com.fasterxml.uuid.impl;
2
3import java.util.UUID;
4
5import com.fasterxml.uuid.*;
6
7/**
8 * Implementation of UUID generator that uses time/location based generation
9 * method (variant 1).
10 *<p>
11 * As all JUG provided implementations, this generator is fully thread-safe.
12 * Additionally it can also be made externally synchronized with other
13 * instances (even ones running on other JVMs); to do this,
14 * use {@link com.fasterxml.uuid.ext.FileBasedTimestampSynchronizer}
15 * (or equivalent).
16 *
17 * @since 3.0
18 */
19public class TimeBasedGenerator extends NoArgGenerator
20{
21 /*
22 /**********************************************************************
23 /* Configuration
24 /**********************************************************************
25 */
26
27 protected final EthernetAddress _ethernetAddress;
28
29 /**
30 * Object used for synchronizing access to timestamps, to guarantee
31 * that timestamps produced by this generator are unique and monotonically increasings.
32 * Some implementations offer even stronger guarantees, for example that
33 * same guarantee holds between instances running on different JVMs (or
34 * with native code).
35 */
36 protected final UUIDTimer _timer;
37
38 /**
39 * Base values for the second long (last 8 bytes) of UUID to construct
40 */
41 protected final long _uuidL2;
42
43 /*
44 /**********************************************************************
45 /* Construction
46 /**********************************************************************
47 */
48
49 /**
50 * @param ethAddr Hardware address (802.1) to use for generating
51 * spatially unique part of UUID. If system has more than one NIC,
52 */
53
54 public TimeBasedGenerator(EthernetAddress ethAddr, UUIDTimer timer)
55 {
56 byte[] uuidBytes = new byte[16];
57 if (ethAddr == null) {
58 ethAddr = EthernetAddress.constructMulticastAddress();
59 }
60 // initialize baseline with MAC address info
61 _ethernetAddress = ethAddr;
62 _ethernetAddress.toByteArray(uuidBytes, 10);
63 // and add clock sequence
64 int clockSeq = timer.getClockSequence();
65 uuidBytes[UUIDUtil.BYTE_OFFSET_CLOCK_SEQUENCE] = (byte) (clockSeq >> 8);
66 uuidBytes[UUIDUtil.BYTE_OFFSET_CLOCK_SEQUENCE+1] = (byte) clockSeq;
67 long l2 = UUIDUtil.gatherLong(uuidBytes, 8);
68 _uuidL2 = UUIDUtil.initUUIDSecondLong(l2);
69 _timer = timer;
70 }
71
72 /*
73 /**********************************************************************
74 /* Access to config
75 /**********************************************************************
76 */
77
78 @Override
79 public UUIDType getType() { return UUIDType.TIME_BASED; }
80
81 public EthernetAddress getEthernetAddress() { return _ethernetAddress; }
82
83 /*
84 /**********************************************************************
85 /* UUID generation
86 /**********************************************************************
87 */
88
89 /* As timer is not synchronized (nor _uuidBytes), need to sync; but most
90 * importantly, synchronize on timer which may also be shared between
91 * multiple instances
92 */
93 @Override
94 public UUID generate()
95 {
96 final long rawTimestamp = _timer.getTimestamp();
97 // Time field components are kind of shuffled, need to slice:
98 int clockHi = (int) (rawTimestamp >>> 32);
99 int clockLo = (int) rawTimestamp;
100 // and dice
101 int midhi = (clockHi << 16) | (clockHi >>> 16);
102 // need to squeeze in type (4 MSBs in byte 6, clock hi)
103 midhi &= ~0xF000; // remove high nibble of 6th byte
104 midhi |= 0x1000; // type 1
105 long midhiL = (long) midhi;
106 midhiL = ((midhiL << 32) >>> 32); // to get rid of sign extension
107 // and reconstruct
108 long l1 = (((long) clockLo) << 32) | midhiL;
109 // last detail: must force 2 MSB to be '10'
110 return new UUID(l1, _uuidL2);
111 }
112}
113final long now = 1644575806478L;
114
115final TimeBasedGenerator sut = new TimeBasedGenerator(EthernetAddress.fromInterface(),
116 new UUIDTimer(new Random(now), null));
117import java.math.BigInteger;
118import java.util.function.Function;
119
120public class OldUUIDConverter implements Function<String, BigInteger> {
121 @Override
122 public BigInteger apply(final String uuid) {
123 final String uuidWithoutDashes = uuid.replaceAll("-", "");
124 return new BigInteger(uuidWithoutDashes, 16);
125 }
126}
127340282366920938463463374607431768211455
128^ ^ ^ ^ ^
129
Because we convert the UUID directly, it won't be repeated if the UUID generator does not produce duplicate UUIDs too frequently.
The criterion b) of the above requirement is satisfied. But criterion a) -- the length of the converted number -- is not.
Failed attempt 2
Someone proposed to only take the first 8 digits of the UUID. Thus the criterion a) will be satisfied.
However, the first 8 digits of the UUID repeat too frequently.
I wrote a simple test program:
1package com.fasterxml.uuid.impl;
2
3import java.util.UUID;
4
5import com.fasterxml.uuid.*;
6
7/**
8 * Implementation of UUID generator that uses time/location based generation
9 * method (variant 1).
10 *<p>
11 * As all JUG provided implementations, this generator is fully thread-safe.
12 * Additionally it can also be made externally synchronized with other
13 * instances (even ones running on other JVMs); to do this,
14 * use {@link com.fasterxml.uuid.ext.FileBasedTimestampSynchronizer}
15 * (or equivalent).
16 *
17 * @since 3.0
18 */
19public class TimeBasedGenerator extends NoArgGenerator
20{
21 /*
22 /**********************************************************************
23 /* Configuration
24 /**********************************************************************
25 */
26
27 protected final EthernetAddress _ethernetAddress;
28
29 /**
30 * Object used for synchronizing access to timestamps, to guarantee
31 * that timestamps produced by this generator are unique and monotonically increasings.
32 * Some implementations offer even stronger guarantees, for example that
33 * same guarantee holds between instances running on different JVMs (or
34 * with native code).
35 */
36 protected final UUIDTimer _timer;
37
38 /**
39 * Base values for the second long (last 8 bytes) of UUID to construct
40 */
41 protected final long _uuidL2;
42
43 /*
44 /**********************************************************************
45 /* Construction
46 /**********************************************************************
47 */
48
49 /**
50 * @param ethAddr Hardware address (802.1) to use for generating
51 * spatially unique part of UUID. If system has more than one NIC,
52 */
53
54 public TimeBasedGenerator(EthernetAddress ethAddr, UUIDTimer timer)
55 {
56 byte[] uuidBytes = new byte[16];
57 if (ethAddr == null) {
58 ethAddr = EthernetAddress.constructMulticastAddress();
59 }
60 // initialize baseline with MAC address info
61 _ethernetAddress = ethAddr;
62 _ethernetAddress.toByteArray(uuidBytes, 10);
63 // and add clock sequence
64 int clockSeq = timer.getClockSequence();
65 uuidBytes[UUIDUtil.BYTE_OFFSET_CLOCK_SEQUENCE] = (byte) (clockSeq >> 8);
66 uuidBytes[UUIDUtil.BYTE_OFFSET_CLOCK_SEQUENCE+1] = (byte) clockSeq;
67 long l2 = UUIDUtil.gatherLong(uuidBytes, 8);
68 _uuidL2 = UUIDUtil.initUUIDSecondLong(l2);
69 _timer = timer;
70 }
71
72 /*
73 /**********************************************************************
74 /* Access to config
75 /**********************************************************************
76 */
77
78 @Override
79 public UUIDType getType() { return UUIDType.TIME_BASED; }
80
81 public EthernetAddress getEthernetAddress() { return _ethernetAddress; }
82
83 /*
84 /**********************************************************************
85 /* UUID generation
86 /**********************************************************************
87 */
88
89 /* As timer is not synchronized (nor _uuidBytes), need to sync; but most
90 * importantly, synchronize on timer which may also be shared between
91 * multiple instances
92 */
93 @Override
94 public UUID generate()
95 {
96 final long rawTimestamp = _timer.getTimestamp();
97 // Time field components are kind of shuffled, need to slice:
98 int clockHi = (int) (rawTimestamp >>> 32);
99 int clockLo = (int) rawTimestamp;
100 // and dice
101 int midhi = (clockHi << 16) | (clockHi >>> 16);
102 // need to squeeze in type (4 MSBs in byte 6, clock hi)
103 midhi &= ~0xF000; // remove high nibble of 6th byte
104 midhi |= 0x1000; // type 1
105 long midhiL = (long) midhi;
106 midhiL = ((midhiL << 32) >>> 32); // to get rid of sign extension
107 // and reconstruct
108 long l1 = (((long) clockLo) << 32) | midhiL;
109 // last detail: must force 2 MSB to be '10'
110 return new UUID(l1, _uuidL2);
111 }
112}
113final long now = 1644575806478L;
114
115final TimeBasedGenerator sut = new TimeBasedGenerator(EthernetAddress.fromInterface(),
116 new UUIDTimer(new Random(now), null));
117import java.math.BigInteger;
118import java.util.function.Function;
119
120public class OldUUIDConverter implements Function<String, BigInteger> {
121 @Override
122 public BigInteger apply(final String uuid) {
123 final String uuidWithoutDashes = uuid.replaceAll("-", "");
124 return new BigInteger(uuidWithoutDashes, 16);
125 }
126}
127340282366920938463463374607431768211455
128^ ^ ^ ^ ^
129import com.fasterxml.uuid.EthernetAddress;
130import com.fasterxml.uuid.UUIDTimer;
131import com.fasterxml.uuid.impl.TimeBasedGenerator;
132import org.junit.Test;
133
134import java.io.IOException;
135import java.util.HashSet;
136import java.util.Random;
137import java.util.Set;
138
139public class UUIDShortenerTest {
140 @Test
141 public void test() throws IOException {
142 final Set<String> first8DigitsAsLong = new HashSet<>(73000000);
143
144 final long now = 1644575806478L;
145
146 final TimeBasedGenerator sut = new TimeBasedGenerator(EthernetAddress.fromInterface(), new UUIDTimer(new Random(now), null));
147
148 for (int i=0; i < Integer.MAX_VALUE; i++) {
149 final String curUuid = sut.generate().toString();
150 final String first8Digits = curUuid.substring(0, 8);
151 if ((i % 1000000L) == 0) {
152 System.out.println(String.format("Counter: %d", i));
153 }
154 if (!first8DigitsAsLong.add(first8Digits)) {
155 System.out.println("Duplicate!");
156 System.out.println(i);
157 break;
158 }
159 }
160 }
161}
162
I ran it 10 times. Every time I wrote down the number of UUID generations after which the first 8 digits are repeated.
Here are the results:
- Duplicate first 8 digits found after
74499376
UUID generations. - 44259478
- 45365652
- 45031094
- 45445463
- 46250299
- 45403800
- 44658612
- 46098250
- 43748051
Let's assume that the first 8 digits are repeated after I generate 75 million UUIDs.
If I generate 12 million UUIDs daily, this means that the first UUID with duplicate first 8 digits will be generated after 62-63 days (75000000/1200000=62.5 days).
These 62.5 days (around two months) are lower than the requirement of 6 months before UUID repetition.
Options I am aware of
There is a number of this I can do to fix the issue.
One would be to increase the number of first digits that I use until the frequency of UUID repetitions reaches the desired level. That is, I can try to use 9 first digits instead of 8 and see if it's good enough. If it doesn't, I can use 10 first digits etc.
Another would be to use the code from failed attempt #1 and encode the resulting number 340282366920938463463374607431768211455
in a numerical system with a greater basis.
Let's say I use numbers 0-9, Latin lowercase and uppercase letters, plus 14 special characters. This results in 10+26+26+14=76 numbers that each digit can have. I assume that the above number in a base 76 system will be shorter than the same number in decimal or hexadecimal system.
Are there any other, better options (e. g. hash functions with sufficient degree of diversity)?
ANSWER
Answered 2022-Feb-17 at 17:131package com.fasterxml.uuid.impl;
2
3import java.util.UUID;
4
5import com.fasterxml.uuid.*;
6
7/**
8 * Implementation of UUID generator that uses time/location based generation
9 * method (variant 1).
10 *<p>
11 * As all JUG provided implementations, this generator is fully thread-safe.
12 * Additionally it can also be made externally synchronized with other
13 * instances (even ones running on other JVMs); to do this,
14 * use {@link com.fasterxml.uuid.ext.FileBasedTimestampSynchronizer}
15 * (or equivalent).
16 *
17 * @since 3.0
18 */
19public class TimeBasedGenerator extends NoArgGenerator
20{
21 /*
22 /**********************************************************************
23 /* Configuration
24 /**********************************************************************
25 */
26
27 protected final EthernetAddress _ethernetAddress;
28
29 /**
30 * Object used for synchronizing access to timestamps, to guarantee
31 * that timestamps produced by this generator are unique and monotonically increasings.
32 * Some implementations offer even stronger guarantees, for example that
33 * same guarantee holds between instances running on different JVMs (or
34 * with native code).
35 */
36 protected final UUIDTimer _timer;
37
38 /**
39 * Base values for the second long (last 8 bytes) of UUID to construct
40 */
41 protected final long _uuidL2;
42
43 /*
44 /**********************************************************************
45 /* Construction
46 /**********************************************************************
47 */
48
49 /**
50 * @param ethAddr Hardware address (802.1) to use for generating
51 * spatially unique part of UUID. If system has more than one NIC,
52 */
53
54 public TimeBasedGenerator(EthernetAddress ethAddr, UUIDTimer timer)
55 {
56 byte[] uuidBytes = new byte[16];
57 if (ethAddr == null) {
58 ethAddr = EthernetAddress.constructMulticastAddress();
59 }
60 // initialize baseline with MAC address info
61 _ethernetAddress = ethAddr;
62 _ethernetAddress.toByteArray(uuidBytes, 10);
63 // and add clock sequence
64 int clockSeq = timer.getClockSequence();
65 uuidBytes[UUIDUtil.BYTE_OFFSET_CLOCK_SEQUENCE] = (byte) (clockSeq >> 8);
66 uuidBytes[UUIDUtil.BYTE_OFFSET_CLOCK_SEQUENCE+1] = (byte) clockSeq;
67 long l2 = UUIDUtil.gatherLong(uuidBytes, 8);
68 _uuidL2 = UUIDUtil.initUUIDSecondLong(l2);
69 _timer = timer;
70 }
71
72 /*
73 /**********************************************************************
74 /* Access to config
75 /**********************************************************************
76 */
77
78 @Override
79 public UUIDType getType() { return UUIDType.TIME_BASED; }
80
81 public EthernetAddress getEthernetAddress() { return _ethernetAddress; }
82
83 /*
84 /**********************************************************************
85 /* UUID generation
86 /**********************************************************************
87 */
88
89 /* As timer is not synchronized (nor _uuidBytes), need to sync; but most
90 * importantly, synchronize on timer which may also be shared between
91 * multiple instances
92 */
93 @Override
94 public UUID generate()
95 {
96 final long rawTimestamp = _timer.getTimestamp();
97 // Time field components are kind of shuffled, need to slice:
98 int clockHi = (int) (rawTimestamp >>> 32);
99 int clockLo = (int) rawTimestamp;
100 // and dice
101 int midhi = (clockHi << 16) | (clockHi >>> 16);
102 // need to squeeze in type (4 MSBs in byte 6, clock hi)
103 midhi &= ~0xF000; // remove high nibble of 6th byte
104 midhi |= 0x1000; // type 1
105 long midhiL = (long) midhi;
106 midhiL = ((midhiL << 32) >>> 32); // to get rid of sign extension
107 // and reconstruct
108 long l1 = (((long) clockLo) << 32) | midhiL;
109 // last detail: must force 2 MSB to be '10'
110 return new UUID(l1, _uuidL2);
111 }
112}
113final long now = 1644575806478L;
114
115final TimeBasedGenerator sut = new TimeBasedGenerator(EthernetAddress.fromInterface(),
116 new UUIDTimer(new Random(now), null));
117import java.math.BigInteger;
118import java.util.function.Function;
119
120public class OldUUIDConverter implements Function<String, BigInteger> {
121 @Override
122 public BigInteger apply(final String uuid) {
123 final String uuidWithoutDashes = uuid.replaceAll("-", "");
124 return new BigInteger(uuidWithoutDashes, 16);
125 }
126}
127340282366920938463463374607431768211455
128^ ^ ^ ^ ^
129import com.fasterxml.uuid.EthernetAddress;
130import com.fasterxml.uuid.UUIDTimer;
131import com.fasterxml.uuid.impl.TimeBasedGenerator;
132import org.junit.Test;
133
134import java.io.IOException;
135import java.util.HashSet;
136import java.util.Random;
137import java.util.Set;
138
139public class UUIDShortenerTest {
140 @Test
141 public void test() throws IOException {
142 final Set<String> first8DigitsAsLong = new HashSet<>(73000000);
143
144 final long now = 1644575806478L;
145
146 final TimeBasedGenerator sut = new TimeBasedGenerator(EthernetAddress.fromInterface(), new UUIDTimer(new Random(now), null));
147
148 for (int i=0; i < Integer.MAX_VALUE; i++) {
149 final String curUuid = sut.generate().toString();
150 final String first8Digits = curUuid.substring(0, 8);
151 if ((i % 1000000L) == 0) {
152 System.out.println(String.format("Counter: %d", i));
153 }
154 if (!first8DigitsAsLong.add(first8Digits)) {
155 System.out.println("Duplicate!");
156 System.out.println(i);
157 break;
158 }
159 }
160 }
161}
162new BigInteger(
163 "ffffffff-ffff-ffff-ffff-ffffffffffff" ,
164 16
165) // Parse the input as hexadecimal numbers. Returns a `BigInteger` object.
166.toString() // Generate text containing the digits of a decimal integer representation of this number.
167.codePoints() // Generate a stream of the Unicode code point number assigned to each of the characters in this string.
168.toArray() // Collect the streamed code point numbers into an array.
169.length // Get size of array.
170
340282366920938463463374607431768211455 is indeed under 40 digits39
Your statement:
But criterion a) -- the length of the converted number -- is not.
… is incorrect.
The resulting integer number has 39 digits. Thirty-nine meets your threshold of being under forty digits: 39 < 40.
Here is code to count the digits.
1package com.fasterxml.uuid.impl;
2
3import java.util.UUID;
4
5import com.fasterxml.uuid.*;
6
7/**
8 * Implementation of UUID generator that uses time/location based generation
9 * method (variant 1).
10 *<p>
11 * As all JUG provided implementations, this generator is fully thread-safe.
12 * Additionally it can also be made externally synchronized with other
13 * instances (even ones running on other JVMs); to do this,
14 * use {@link com.fasterxml.uuid.ext.FileBasedTimestampSynchronizer}
15 * (or equivalent).
16 *
17 * @since 3.0
18 */
19public class TimeBasedGenerator extends NoArgGenerator
20{
21 /*
22 /**********************************************************************
23 /* Configuration
24 /**********************************************************************
25 */
26
27 protected final EthernetAddress _ethernetAddress;
28
29 /**
30 * Object used for synchronizing access to timestamps, to guarantee
31 * that timestamps produced by this generator are unique and monotonically increasings.
32 * Some implementations offer even stronger guarantees, for example that
33 * same guarantee holds between instances running on different JVMs (or
34 * with native code).
35 */
36 protected final UUIDTimer _timer;
37
38 /**
39 * Base values for the second long (last 8 bytes) of UUID to construct
40 */
41 protected final long _uuidL2;
42
43 /*
44 /**********************************************************************
45 /* Construction
46 /**********************************************************************
47 */
48
49 /**
50 * @param ethAddr Hardware address (802.1) to use for generating
51 * spatially unique part of UUID. If system has more than one NIC,
52 */
53
54 public TimeBasedGenerator(EthernetAddress ethAddr, UUIDTimer timer)
55 {
56 byte[] uuidBytes = new byte[16];
57 if (ethAddr == null) {
58 ethAddr = EthernetAddress.constructMulticastAddress();
59 }
60 // initialize baseline with MAC address info
61 _ethernetAddress = ethAddr;
62 _ethernetAddress.toByteArray(uuidBytes, 10);
63 // and add clock sequence
64 int clockSeq = timer.getClockSequence();
65 uuidBytes[UUIDUtil.BYTE_OFFSET_CLOCK_SEQUENCE] = (byte) (clockSeq >> 8);
66 uuidBytes[UUIDUtil.BYTE_OFFSET_CLOCK_SEQUENCE+1] = (byte) clockSeq;
67 long l2 = UUIDUtil.gatherLong(uuidBytes, 8);
68 _uuidL2 = UUIDUtil.initUUIDSecondLong(l2);
69 _timer = timer;
70 }
71
72 /*
73 /**********************************************************************
74 /* Access to config
75 /**********************************************************************
76 */
77
78 @Override
79 public UUIDType getType() { return UUIDType.TIME_BASED; }
80
81 public EthernetAddress getEthernetAddress() { return _ethernetAddress; }
82
83 /*
84 /**********************************************************************
85 /* UUID generation
86 /**********************************************************************
87 */
88
89 /* As timer is not synchronized (nor _uuidBytes), need to sync; but most
90 * importantly, synchronize on timer which may also be shared between
91 * multiple instances
92 */
93 @Override
94 public UUID generate()
95 {
96 final long rawTimestamp = _timer.getTimestamp();
97 // Time field components are kind of shuffled, need to slice:
98 int clockHi = (int) (rawTimestamp >>> 32);
99 int clockLo = (int) rawTimestamp;
100 // and dice
101 int midhi = (clockHi << 16) | (clockHi >>> 16);
102 // need to squeeze in type (4 MSBs in byte 6, clock hi)
103 midhi &= ~0xF000; // remove high nibble of 6th byte
104 midhi |= 0x1000; // type 1
105 long midhiL = (long) midhi;
106 midhiL = ((midhiL << 32) >>> 32); // to get rid of sign extension
107 // and reconstruct
108 long l1 = (((long) clockLo) << 32) | midhiL;
109 // last detail: must force 2 MSB to be '10'
110 return new UUID(l1, _uuidL2);
111 }
112}
113final long now = 1644575806478L;
114
115final TimeBasedGenerator sut = new TimeBasedGenerator(EthernetAddress.fromInterface(),
116 new UUIDTimer(new Random(now), null));
117import java.math.BigInteger;
118import java.util.function.Function;
119
120public class OldUUIDConverter implements Function<String, BigInteger> {
121 @Override
122 public BigInteger apply(final String uuid) {
123 final String uuidWithoutDashes = uuid.replaceAll("-", "");
124 return new BigInteger(uuidWithoutDashes, 16);
125 }
126}
127340282366920938463463374607431768211455
128^ ^ ^ ^ ^
129import com.fasterxml.uuid.EthernetAddress;
130import com.fasterxml.uuid.UUIDTimer;
131import com.fasterxml.uuid.impl.TimeBasedGenerator;
132import org.junit.Test;
133
134import java.io.IOException;
135import java.util.HashSet;
136import java.util.Random;
137import java.util.Set;
138
139public class UUIDShortenerTest {
140 @Test
141 public void test() throws IOException {
142 final Set<String> first8DigitsAsLong = new HashSet<>(73000000);
143
144 final long now = 1644575806478L;
145
146 final TimeBasedGenerator sut = new TimeBasedGenerator(EthernetAddress.fromInterface(), new UUIDTimer(new Random(now), null));
147
148 for (int i=0; i < Integer.MAX_VALUE; i++) {
149 final String curUuid = sut.generate().toString();
150 final String first8Digits = curUuid.substring(0, 8);
151 if ((i % 1000000L) == 0) {
152 System.out.println(String.format("Counter: %d", i));
153 }
154 if (!first8DigitsAsLong.add(first8Digits)) {
155 System.out.println("Duplicate!");
156 System.out.println(i);
157 break;
158 }
159 }
160 }
161}
162new BigInteger(
163 "ffffffff-ffff-ffff-ffff-ffffffffffff" ,
164 16
165) // Parse the input as hexadecimal numbers. Returns a `BigInteger` object.
166.toString() // Generate text containing the digits of a decimal integer representation of this number.
167.codePoints() // Generate a stream of the Unicode code point number assigned to each of the characters in this string.
168.toArray() // Collect the streamed code point numbers into an array.
169.length // Get size of array.
170String input = "ffffffff-ffff-ffff-ffff-ffffffffffff" ;
171String uuidWithoutDashes = input.replaceAll( "-" , "" );
172BigInteger bi = new BigInteger( uuidWithoutDashes , 16 );
173String output = bi.toString() ;
174int digitCount = output.codePoints().toArray().length ;
175
176System.out.println( bi ) ;
177System.out.println( digitCount ) ;
178
See this code run live at IdeOne.com.
340282366920938463463374607431768211455
39
Or, manually count the digits. To facilitate that count, I added caret characters to mark 1, 11, 21, 31, 41.
1package com.fasterxml.uuid.impl;
2
3import java.util.UUID;
4
5import com.fasterxml.uuid.*;
6
7/**
8 * Implementation of UUID generator that uses time/location based generation
9 * method (variant 1).
10 *<p>
11 * As all JUG provided implementations, this generator is fully thread-safe.
12 * Additionally it can also be made externally synchronized with other
13 * instances (even ones running on other JVMs); to do this,
14 * use {@link com.fasterxml.uuid.ext.FileBasedTimestampSynchronizer}
15 * (or equivalent).
16 *
17 * @since 3.0
18 */
19public class TimeBasedGenerator extends NoArgGenerator
20{
21 /*
22 /**********************************************************************
23 /* Configuration
24 /**********************************************************************
25 */
26
27 protected final EthernetAddress _ethernetAddress;
28
29 /**
30 * Object used for synchronizing access to timestamps, to guarantee
31 * that timestamps produced by this generator are unique and monotonically increasings.
32 * Some implementations offer even stronger guarantees, for example that
33 * same guarantee holds between instances running on different JVMs (or
34 * with native code).
35 */
36 protected final UUIDTimer _timer;
37
38 /**
39 * Base values for the second long (last 8 bytes) of UUID to construct
40 */
41 protected final long _uuidL2;
42
43 /*
44 /**********************************************************************
45 /* Construction
46 /**********************************************************************
47 */
48
49 /**
50 * @param ethAddr Hardware address (802.1) to use for generating
51 * spatially unique part of UUID. If system has more than one NIC,
52 */
53
54 public TimeBasedGenerator(EthernetAddress ethAddr, UUIDTimer timer)
55 {
56 byte[] uuidBytes = new byte[16];
57 if (ethAddr == null) {
58 ethAddr = EthernetAddress.constructMulticastAddress();
59 }
60 // initialize baseline with MAC address info
61 _ethernetAddress = ethAddr;
62 _ethernetAddress.toByteArray(uuidBytes, 10);
63 // and add clock sequence
64 int clockSeq = timer.getClockSequence();
65 uuidBytes[UUIDUtil.BYTE_OFFSET_CLOCK_SEQUENCE] = (byte) (clockSeq >> 8);
66 uuidBytes[UUIDUtil.BYTE_OFFSET_CLOCK_SEQUENCE+1] = (byte) clockSeq;
67 long l2 = UUIDUtil.gatherLong(uuidBytes, 8);
68 _uuidL2 = UUIDUtil.initUUIDSecondLong(l2);
69 _timer = timer;
70 }
71
72 /*
73 /**********************************************************************
74 /* Access to config
75 /**********************************************************************
76 */
77
78 @Override
79 public UUIDType getType() { return UUIDType.TIME_BASED; }
80
81 public EthernetAddress getEthernetAddress() { return _ethernetAddress; }
82
83 /*
84 /**********************************************************************
85 /* UUID generation
86 /**********************************************************************
87 */
88
89 /* As timer is not synchronized (nor _uuidBytes), need to sync; but most
90 * importantly, synchronize on timer which may also be shared between
91 * multiple instances
92 */
93 @Override
94 public UUID generate()
95 {
96 final long rawTimestamp = _timer.getTimestamp();
97 // Time field components are kind of shuffled, need to slice:
98 int clockHi = (int) (rawTimestamp >>> 32);
99 int clockLo = (int) rawTimestamp;
100 // and dice
101 int midhi = (clockHi << 16) | (clockHi >>> 16);
102 // need to squeeze in type (4 MSBs in byte 6, clock hi)
103 midhi &= ~0xF000; // remove high nibble of 6th byte
104 midhi |= 0x1000; // type 1
105 long midhiL = (long) midhi;
106 midhiL = ((midhiL << 32) >>> 32); // to get rid of sign extension
107 // and reconstruct
108 long l1 = (((long) clockLo) << 32) | midhiL;
109 // last detail: must force 2 MSB to be '10'
110 return new UUID(l1, _uuidL2);
111 }
112}
113final long now = 1644575806478L;
114
115final TimeBasedGenerator sut = new TimeBasedGenerator(EthernetAddress.fromInterface(),
116 new UUIDTimer(new Random(now), null));
117import java.math.BigInteger;
118import java.util.function.Function;
119
120public class OldUUIDConverter implements Function<String, BigInteger> {
121 @Override
122 public BigInteger apply(final String uuid) {
123 final String uuidWithoutDashes = uuid.replaceAll("-", "");
124 return new BigInteger(uuidWithoutDashes, 16);
125 }
126}
127340282366920938463463374607431768211455
128^ ^ ^ ^ ^
129import com.fasterxml.uuid.EthernetAddress;
130import com.fasterxml.uuid.UUIDTimer;
131import com.fasterxml.uuid.impl.TimeBasedGenerator;
132import org.junit.Test;
133
134import java.io.IOException;
135import java.util.HashSet;
136import java.util.Random;
137import java.util.Set;
138
139public class UUIDShortenerTest {
140 @Test
141 public void test() throws IOException {
142 final Set<String> first8DigitsAsLong = new HashSet<>(73000000);
143
144 final long now = 1644575806478L;
145
146 final TimeBasedGenerator sut = new TimeBasedGenerator(EthernetAddress.fromInterface(), new UUIDTimer(new Random(now), null));
147
148 for (int i=0; i < Integer.MAX_VALUE; i++) {
149 final String curUuid = sut.generate().toString();
150 final String first8Digits = curUuid.substring(0, 8);
151 if ((i % 1000000L) == 0) {
152 System.out.println(String.format("Counter: %d", i));
153 }
154 if (!first8DigitsAsLong.add(first8Digits)) {
155 System.out.println("Duplicate!");
156 System.out.println(i);
157 break;
158 }
159 }
160 }
161}
162new BigInteger(
163 "ffffffff-ffff-ffff-ffff-ffffffffffff" ,
164 16
165) // Parse the input as hexadecimal numbers. Returns a `BigInteger` object.
166.toString() // Generate text containing the digits of a decimal integer representation of this number.
167.codePoints() // Generate a stream of the Unicode code point number assigned to each of the characters in this string.
168.toArray() // Collect the streamed code point numbers into an array.
169.length // Get size of array.
170String input = "ffffffff-ffff-ffff-ffff-ffffffffffff" ;
171String uuidWithoutDashes = input.replaceAll( "-" , "" );
172BigInteger bi = new BigInteger( uuidWithoutDashes , 16 );
173String output = bi.toString() ;
174int digitCount = output.codePoints().toArray().length ;
175
176System.out.println( bi ) ;
177System.out.println( digitCount ) ;
178340282366920938463463374607431768211455
179^ ^ ^ ^ ^
180
As for the bigger picture, I cannot imagine a worthy purpose to storing 39 digits extracted from a decimal representation of a UUID. Study the Comments suggesting you stick with a 128-bit binary representation.
I also wonder why you supply a fixed number as the seed to your Random
. Doing so produces identical numbers as outputs.
QUESTION
Save Variable from a Pre-request script to use in a new Request
Asked 2021-Oct-26 at 21:13I'd like to run a Pre-request script in POSTMAN that sends a request to a UUID generator API and saves the UUIDs as variables. Which I can call in the body of the request since they are required there.
Originally, I have two separate requests (1) a request to the UUID Generator API (2) and another to my private API. I'm able to set the 3 UUIDs as variables and call them to the body following request to my private API no problem and it works. Like so:
1GET https://www.uuidgenerator.net/api/version1/3
2
3pm.collectionVariables.set("UUID_1", pm.response.text().split(" ")[1])
4pm.collectionVariables.set("UUID_2", pm.response.text().split(" ")[2])
5pm.collectionVariables.set("UUID_3", pm.response.text().split(" ")[3])
6
7**Response:**
8
91. f3600940-3684-11ec-8d3d-0242ac130003
102. f3600b70-3684-11ec-8d3d-0242ac130003
113. f3600c6a-3684-11ec-8d3d-0242ac130003
12
13
14**Variables in body of next Request:**
15
16 "data": {
17 "uuid": "{{UUID_1}}",
18 "uuid2": "{{UUID_2}}",
19 "uuid3": "{{UUID_3}}",
20
Side note: The only way I figured out how to get individualized raw text data from a response is by using .split
and the line the data is one, pm.response.text().split(" ")[1])
HOWEVER, I'd like to simplify things and insert the UUID Generator Request in the Pre-Request section so I don't need two separate Requests to make this work. But when inserting the same information that works in the prior request above to set these variables, it doesn't work.
The Pre-request script I have so far gives an error (below):
1GET https://www.uuidgenerator.net/api/version1/3
2
3pm.collectionVariables.set("UUID_1", pm.response.text().split(" ")[1])
4pm.collectionVariables.set("UUID_2", pm.response.text().split(" ")[2])
5pm.collectionVariables.set("UUID_3", pm.response.text().split(" ")[3])
6
7**Response:**
8
91. f3600940-3684-11ec-8d3d-0242ac130003
102. f3600b70-3684-11ec-8d3d-0242ac130003
113. f3600c6a-3684-11ec-8d3d-0242ac130003
12
13
14**Variables in body of next Request:**
15
16 "data": {
17 "uuid": "{{UUID_1}}",
18 "uuid2": "{{UUID_2}}",
19 "uuid3": "{{UUID_3}}",
20 pm.sendRequest({
21 url: "https://www.uuidgenerator.net/api/version1/3",
22 method: 'GET'
23}, function (err, res) {
24pm.collectionVariables.set("UUID_1", pm.response.text().split(" ")[1])
25pm.collectionVariables.set("UUID_2", pm.response.text().split(" ")[2])
26pm.collectionVariables.set("UUID_3", pm.response.text().split(" ")[3])
27});
28
29POSTMAN Error:
30
31 There was an error in evaluating the Pre-request Script:Error: Cannot read property 'text' of undefined
32
Basically whichever different variations I try in collectionVariables.set
in the Pre-request script....
1GET https://www.uuidgenerator.net/api/version1/3
2
3pm.collectionVariables.set("UUID_1", pm.response.text().split(" ")[1])
4pm.collectionVariables.set("UUID_2", pm.response.text().split(" ")[2])
5pm.collectionVariables.set("UUID_3", pm.response.text().split(" ")[3])
6
7**Response:**
8
91. f3600940-3684-11ec-8d3d-0242ac130003
102. f3600b70-3684-11ec-8d3d-0242ac130003
113. f3600c6a-3684-11ec-8d3d-0242ac130003
12
13
14**Variables in body of next Request:**
15
16 "data": {
17 "uuid": "{{UUID_1}}",
18 "uuid2": "{{UUID_2}}",
19 "uuid3": "{{UUID_3}}",
20 pm.sendRequest({
21 url: "https://www.uuidgenerator.net/api/version1/3",
22 method: 'GET'
23}, function (err, res) {
24pm.collectionVariables.set("UUID_1", pm.response.text().split(" ")[1])
25pm.collectionVariables.set("UUID_2", pm.response.text().split(" ")[2])
26pm.collectionVariables.set("UUID_3", pm.response.text().split(" ")[3])
27});
28
29POSTMAN Error:
30
31 There was an error in evaluating the Pre-request Script:Error: Cannot read property 'text' of undefined
32pm.collectionVariables.set("UUID_1", pm.response.text().split(" ")[1])
33OR
34pm.collectionVariables.set("UUID_2", pm.response.split(" ")[2])
35OR
36pm.collectionVariables.set("UUID_3", pm.response.[3])
37
I receive errors that otherwise I wouldn't get if it was it's own Request (which works)
This leads me to believe it may be the inner workings of the Pre-Request Script I have.
ANSWER
Answered 2021-Oct-26 at 21:13You were nearly there. Array starts with [0] and you need to declare the response as res, as placed in the function:
1GET https://www.uuidgenerator.net/api/version1/3
2
3pm.collectionVariables.set("UUID_1", pm.response.text().split(" ")[1])
4pm.collectionVariables.set("UUID_2", pm.response.text().split(" ")[2])
5pm.collectionVariables.set("UUID_3", pm.response.text().split(" ")[3])
6
7**Response:**
8
91. f3600940-3684-11ec-8d3d-0242ac130003
102. f3600b70-3684-11ec-8d3d-0242ac130003
113. f3600c6a-3684-11ec-8d3d-0242ac130003
12
13
14**Variables in body of next Request:**
15
16 "data": {
17 "uuid": "{{UUID_1}}",
18 "uuid2": "{{UUID_2}}",
19 "uuid3": "{{UUID_3}}",
20 pm.sendRequest({
21 url: "https://www.uuidgenerator.net/api/version1/3",
22 method: 'GET'
23}, function (err, res) {
24pm.collectionVariables.set("UUID_1", pm.response.text().split(" ")[1])
25pm.collectionVariables.set("UUID_2", pm.response.text().split(" ")[2])
26pm.collectionVariables.set("UUID_3", pm.response.text().split(" ")[3])
27});
28
29POSTMAN Error:
30
31 There was an error in evaluating the Pre-request Script:Error: Cannot read property 'text' of undefined
32pm.collectionVariables.set("UUID_1", pm.response.text().split(" ")[1])
33OR
34pm.collectionVariables.set("UUID_2", pm.response.split(" ")[2])
35OR
36pm.collectionVariables.set("UUID_3", pm.response.[3])
37pm.sendRequest({
38 url: "https://www.uuidgenerator.net/api/version1/3",
39 method: 'GET'
40 }, function(err, res){
41pm.collectionVariables.set("UUID_1", res.text().split("\r\n")[0])
42pm.collectionVariables.set("UUID_2", res.text().split("\r\n")[1])
43pm.collectionVariables.set("UUID_3", res.text().split("\r\n")[2])
44});
45console.log(pm.response);
46
QUESTION
YAML/YQ - remove sections that have sub-sections containing a particular attribute match
Asked 2021-Oct-07 at 18:16I'm trying to use mikefarah's yq
to remote sections of a yaml
file that have a sub-section with a particular attribute match.
More specifically, let's say that we have the following OpenAPI file:
1openapi: 3.0.0
2protocol: https
3tags:
4 - description: Sample API
5 name: Sample Echo API
6info:
7 title: UUID generator based on httpbin.org
8 version: 1.0.3
9paths:
10 /uuid:
11 get:
12 responses:
13 "200":
14 description: A UUID4.
15 summary: Return a UUID4.
16 tags:
17 - UUID Ops
18 /uuid/{uuid}:
19 delete:
20 parameters:
21 - in: path
22 name: uuid
23 required: true
24 schema:
25 type: string
26 responses:
27 "200":
28 description: Deleted okay.
29 summary: This endpoint makes no sense.
30 tags:
31 - UUID Ops
32 - Experimental
33 /delay/{delay}:
34 get:
35 parameters:
36 - in: path
37 name: delay
38 required: true
39 schema:
40 type: integer
41 responses:
42 "200":
43 description: Returns a delayed response
44 summary: Returns a delayed response
45 tags:
46 - Delayed Response
47 - Experimental
48servers:
49 - url: https://httpbin.org/
50
I want to remove all API endpoints with a tag of "Experimental", so basically the resulting file would be:
1openapi: 3.0.0
2protocol: https
3tags:
4 - description: Sample API
5 name: Sample Echo API
6info:
7 title: UUID generator based on httpbin.org
8 version: 1.0.3
9paths:
10 /uuid:
11 get:
12 responses:
13 "200":
14 description: A UUID4.
15 summary: Return a UUID4.
16 tags:
17 - UUID Ops
18 /uuid/{uuid}:
19 delete:
20 parameters:
21 - in: path
22 name: uuid
23 required: true
24 schema:
25 type: string
26 responses:
27 "200":
28 description: Deleted okay.
29 summary: This endpoint makes no sense.
30 tags:
31 - UUID Ops
32 - Experimental
33 /delay/{delay}:
34 get:
35 parameters:
36 - in: path
37 name: delay
38 required: true
39 schema:
40 type: integer
41 responses:
42 "200":
43 description: Returns a delayed response
44 summary: Returns a delayed response
45 tags:
46 - Delayed Response
47 - Experimental
48servers:
49 - url: https://httpbin.org/
50openapi: 3.0.0
51protocol: https
52tags:
53 - description: Sample API
54 name: Sample Echo API
55info:
56 title: UUID generator based on httpbin.org
57 version: 1.0.3
58paths:
59 /uuid:
60 get:
61 responses:
62 "200":
63 description: A UUID4.
64 summary: Return a UUID4.
65 tags:
66 - UUID Ops
67servers:
68 - url: https://httpbin.org/
69
Where I'm struggling is to find the right 'level' for the yq
command to work in this way.
As in, I know that I can show all tags in a few different ways:
yq eval '.paths[]?[]?.tags?' openapi.yaml
or
yq eval '.. | select(. == "Experimental")' openapi.yaml
But when I try something like the following to delete the parent section (i.e. the actual API block) based on the tags:
yq eval '.paths | del(.. | select(. == "Experimental"))' openapi.yaml
or
yq eval '.paths |= with_entries(del(select(.. | select(. == "Experimental"))) )' openapi.yaml
All it does it delete the specific Experimental
tag, not the actual API block.
Any ideas what I'm doing wrong please?
ANSWER
Answered 2021-Oct-07 at 18:16With mikefarah/yq, this was a bit tricky, but you can use with_entries
and contains
methods to achieve your desired result
1openapi: 3.0.0
2protocol: https
3tags:
4 - description: Sample API
5 name: Sample Echo API
6info:
7 title: UUID generator based on httpbin.org
8 version: 1.0.3
9paths:
10 /uuid:
11 get:
12 responses:
13 "200":
14 description: A UUID4.
15 summary: Return a UUID4.
16 tags:
17 - UUID Ops
18 /uuid/{uuid}:
19 delete:
20 parameters:
21 - in: path
22 name: uuid
23 required: true
24 schema:
25 type: string
26 responses:
27 "200":
28 description: Deleted okay.
29 summary: This endpoint makes no sense.
30 tags:
31 - UUID Ops
32 - Experimental
33 /delay/{delay}:
34 get:
35 parameters:
36 - in: path
37 name: delay
38 required: true
39 schema:
40 type: integer
41 responses:
42 "200":
43 description: Returns a delayed response
44 summary: Returns a delayed response
45 tags:
46 - Delayed Response
47 - Experimental
48servers:
49 - url: https://httpbin.org/
50openapi: 3.0.0
51protocol: https
52tags:
53 - description: Sample API
54 name: Sample Echo API
55info:
56 title: UUID generator based on httpbin.org
57 version: 1.0.3
58paths:
59 /uuid:
60 get:
61 responses:
62 "200":
63 description: A UUID4.
64 summary: Return a UUID4.
65 tags:
66 - UUID Ops
67servers:
68 - url: https://httpbin.org/
69yq e '
70 .paths |=
71 with_entries( select( .value[].tags | contains(["Experimental"] ) | not ) )' yaml
72
Using with_entries, each of your map elements are converted to key/value pairs and by using a special notation as .value[]
, you bypass the top level keys - /uuid
, /uuid/{uuid}
and get to apply your filter directly on the tags
Using contains, we were able to filter only on the necessary object containing only "Experimental"
and negate that condition using not
to get your desired result.
QUESTION
How can I reference an array when I don't know the name of it?
Asked 2021-Aug-31 at 04:59In my Cloud Firestore I have a database comprised of several users, and on their structure there's an array called contacts
that has several nested arrays. The id (or name, if you will) from every single of one of those arrays is the id from another user. Like so
1"contacts": [
2 "UserAid": [
3 "value1",
4 "value2",
5 "value3"
6 ],
7 "UserBid": [
8 "value4",
9 "value5"
10 ]
11]
12
The thing is, I want to delete value2
from contacts
. However, the UserAid
is actually a value generated at random by an UUID generator. I know that deleting a value from an array is as simple as:
1"contacts": [
2 "UserAid": [
3 "value1",
4 "value2",
5 "value3"
6 ],
7 "UserBid": [
8 "value4",
9 "value5"
10 ]
11]
12firebase.firestore().collection('Users')
13 .doc(user.id)
14 .update({
15 array: firebase.firestore.FieldValue.arrayRemove(`${valueName}`)
16 })
17
However, because in this case "array" on the update function is a dynamic value (aka the uuid of another user), how can I reference "UserAid" on my function to delete de value?
ANSWER
Answered 2021-Aug-31 at 04:59You can use []
notation to use the value of a variable as the property name. So:
1"contacts": [
2 "UserAid": [
3 "value1",
4 "value2",
5 "value3"
6 ],
7 "UserBid": [
8 "value4",
9 "value5"
10 ]
11]
12firebase.firestore().collection('Users')
13 .doc(user.id)
14 .update({
15 array: firebase.firestore.FieldValue.arrayRemove(`${valueName}`)
16 })
17const fieldName = "theFieldNameThatYouWantToUpdate"
18firebase.firestore().collection('Users')
19 .doc(user.id)
20 .update({
21 [fieldName]: firebase.firestore.FieldValue.arrayRemove(`${valueName}`)
22 })
23
If you don't have the name of the field to update, you'll have to first load the document to determine that.
QUESTION
React Context API context API issues , when adding and removing an items from UI
Asked 2021-Aug-30 at 02:54I have this working code link, that have some issues with the following.
Adding itemsI have multi components called row.. I need to add a single item to each of them, problems is the items is getting added to every one of the rows, instead of the selected one? is the context API the issue or should I use redux, or some other solution for that ? react mind set is really different when it comes to state, any idea how to achieve adding an item to every single row separately?
Removing a single element..to say the truth I have no access to the id I tried to uses UUID generator, and pass the id down using props, which was a very stupid idea since it regenerate a different id each time, any idea how can I target the id of the parent element,
in the icon component so I can use the filter method on that state and remove the selected item from the items array ??
hiding an icon after click outside of the item …if you have noticed once you click on an item it shows an icon, what if I decided on not doing any thing and remove the icon ? I tried removing it from the item it self element by using onBlur event but it resulted in the icon (losing the a passed down functionality) so I wont be able to remove the item later on.. currently the icon will disappear but then icon functionality (remove the current element has gone down)
1// Context Module
2import React, { useReducer } from 'react'
3import appContext from './appContext'
4import AppReducer from './appReducer'
5import Item from '../../components/Item';
6// the action to chanhe the state !!!
7import {
8 ICONS,
9 ITEMS,
10 ADD_ITEM,
11 REMOVE_ITEM
12
13} from '../types'
14// Creating the state MUST BE A CAPITAL OTHER WISE IT WILL B^&% !! AND REFUSE TO COMPILE
15const AppState = (props) => {
16const initialState = {
17 Icons : false,
18 Items : [<Item/>],
19}
20
21const [state, dispatch] = useReducer(AppReducer, initialState)
22const Iconsshow = () => {
23 // show the icon
24 dispatch({
25 type: ICONS,
26 stabelIcons : true
27 })
28}
29
30const Iconshide = () => {
31 // show the icon
32 dispatch({
33 type: ICONS,
34 stabelIcons : false
35 })
36}
37
38const AddItem = ()=> {
39 dispatch({
40 type: ADD_ITEM,
41 Items : [...state.Items, initialState.Items]
42})
43}
44
45const RemoveItem = (e)=> {
46 dispatch({
47 type: REMOVE_ITEM,
48 Items : [[<Item/>]]
49})
50}
51
52return <appContext.Provider
53value={{
54 Icons : state.Icons,
55 Items : state.Items,
56 AddItem,
57 RemoveItem
58 }}>
59{props.children}
60</appContext.Provider>
61}
62
63export default AppState;
64
1// Context Module
2import React, { useReducer } from 'react'
3import appContext from './appContext'
4import AppReducer from './appReducer'
5import Item from '../../components/Item';
6// the action to chanhe the state !!!
7import {
8 ICONS,
9 ITEMS,
10 ADD_ITEM,
11 REMOVE_ITEM
12
13} from '../types'
14// Creating the state MUST BE A CAPITAL OTHER WISE IT WILL B^&% !! AND REFUSE TO COMPILE
15const AppState = (props) => {
16const initialState = {
17 Icons : false,
18 Items : [<Item/>],
19}
20
21const [state, dispatch] = useReducer(AppReducer, initialState)
22const Iconsshow = () => {
23 // show the icon
24 dispatch({
25 type: ICONS,
26 stabelIcons : true
27 })
28}
29
30const Iconshide = () => {
31 // show the icon
32 dispatch({
33 type: ICONS,
34 stabelIcons : false
35 })
36}
37
38const AddItem = ()=> {
39 dispatch({
40 type: ADD_ITEM,
41 Items : [...state.Items, initialState.Items]
42})
43}
44
45const RemoveItem = (e)=> {
46 dispatch({
47 type: REMOVE_ITEM,
48 Items : [[<Item/>]]
49})
50}
51
52return <appContext.Provider
53value={{
54 Icons : state.Icons,
55 Items : state.Items,
56 AddItem,
57 RemoveItem
58 }}>
59{props.children}
60</appContext.Provider>
61}
62
63export default AppState;
64// Reducer Module
65
66import {
67 ICONS_SHOW,
68 ICONS_HIDE,
69 ITEMS,
70 ADD_ITEM,
71 REMOVE_ITEM
72} from "../types"
73
74export default (state, action ) => {
75
76switch(action.type) {
77 case ICONS_SHOW:
78 return {
79 ...state,
80 Icons: true
81 }
82 case ICONS_HIDE:
83 return {
84 ...state,
85 Icons: false
86 }
87 case ITEMS:
88 return {
89 ...state,
90 Items: action.Items
91 }
92 case ADD_ITEM:
93 return {
94 ...state,
95 Items: [...state.Items, action.payload]
96
97 }
98 case REMOVE_ITEM:
99 return {
100 ...state,
101 Items: action.payload
102 }
103default:
104return state
105}
106}
code box dependencies
1// Context Module
2import React, { useReducer } from 'react'
3import appContext from './appContext'
4import AppReducer from './appReducer'
5import Item from '../../components/Item';
6// the action to chanhe the state !!!
7import {
8 ICONS,
9 ITEMS,
10 ADD_ITEM,
11 REMOVE_ITEM
12
13} from '../types'
14// Creating the state MUST BE A CAPITAL OTHER WISE IT WILL B^&% !! AND REFUSE TO COMPILE
15const AppState = (props) => {
16const initialState = {
17 Icons : false,
18 Items : [<Item/>],
19}
20
21const [state, dispatch] = useReducer(AppReducer, initialState)
22const Iconsshow = () => {
23 // show the icon
24 dispatch({
25 type: ICONS,
26 stabelIcons : true
27 })
28}
29
30const Iconshide = () => {
31 // show the icon
32 dispatch({
33 type: ICONS,
34 stabelIcons : false
35 })
36}
37
38const AddItem = ()=> {
39 dispatch({
40 type: ADD_ITEM,
41 Items : [...state.Items, initialState.Items]
42})
43}
44
45const RemoveItem = (e)=> {
46 dispatch({
47 type: REMOVE_ITEM,
48 Items : [[<Item/>]]
49})
50}
51
52return <appContext.Provider
53value={{
54 Icons : state.Icons,
55 Items : state.Items,
56 AddItem,
57 RemoveItem
58 }}>
59{props.children}
60</appContext.Provider>
61}
62
63export default AppState;
64// Reducer Module
65
66import {
67 ICONS_SHOW,
68 ICONS_HIDE,
69 ITEMS,
70 ADD_ITEM,
71 REMOVE_ITEM
72} from "../types"
73
74export default (state, action ) => {
75
76switch(action.type) {
77 case ICONS_SHOW:
78 return {
79 ...state,
80 Icons: true
81 }
82 case ICONS_HIDE:
83 return {
84 ...state,
85 Icons: false
86 }
87 case ITEMS:
88 return {
89 ...state,
90 Items: action.Items
91 }
92 case ADD_ITEM:
93 return {
94 ...state,
95 Items: [...state.Items, action.payload]
96
97 }
98 case REMOVE_ITEM:
99 return {
100 ...state,
101 Items: action.payload
102 }
103default:
104return state
105}
106}"dependencies": {
107 "@fortawesome/fontawesome-svg-core": "^1.2.36",
108 "@fortawesome/free-brands-svg-icons": "^5.15.4",
109 "@fortawesome/free-regular-svg-icons": "^5.15.4",
110 "@fortawesome/free-solid-svg-icons": "^5.15.4",
111 "@fortawesome/react-fontawesome": "^0.1.15",
112 "@testing-library/jest-dom": "^5.14.1",
113 "@testing-library/react": "^11.2.7",
114 "@testing-library/user-event": "^12.8.3",
115 "moment-timezone": "^0.5.33",
116 "node-sass": "^6.0.1",
117 "react": "^17.0.2",
118 "react-dom": "^17.0.2",
119 "react-live-clock": "^5.2.0",
120 "react-modal": "^3.14.3",
121 "react-moment": "^1.1.1",
122 "react-scripts": "4.0.3",
123 "uuid": "^8.3.2",
124 "web-vitals": "^1.1.2"
125 },
126
ANSWER
Answered 2021-Aug-26 at 06:43After a day or so tinkering around with your sandbox I decided it had enough going against it that it needed more of a rewrite. The biggest issue was the storing of <Item />
component JSX into the component state. Storing JSX into component state is anti-pattern in React.
Give each row component an id
that can be used to identify it in state. Pass the row id
with each dispatched action to add/remove items from that row's data.
appContext - Convert the items array to a rows
object
1// Context Module
2import React, { useReducer } from 'react'
3import appContext from './appContext'
4import AppReducer from './appReducer'
5import Item from '../../components/Item';
6// the action to chanhe the state !!!
7import {
8 ICONS,
9 ITEMS,
10 ADD_ITEM,
11 REMOVE_ITEM
12
13} from '../types'
14// Creating the state MUST BE A CAPITAL OTHER WISE IT WILL B^&% !! AND REFUSE TO COMPILE
15const AppState = (props) => {
16const initialState = {
17 Icons : false,
18 Items : [<Item/>],
19}
20
21const [state, dispatch] = useReducer(AppReducer, initialState)
22const Iconsshow = () => {
23 // show the icon
24 dispatch({
25 type: ICONS,
26 stabelIcons : true
27 })
28}
29
30const Iconshide = () => {
31 // show the icon
32 dispatch({
33 type: ICONS,
34 stabelIcons : false
35 })
36}
37
38const AddItem = ()=> {
39 dispatch({
40 type: ADD_ITEM,
41 Items : [...state.Items, initialState.Items]
42})
43}
44
45const RemoveItem = (e)=> {
46 dispatch({
47 type: REMOVE_ITEM,
48 Items : [[<Item/>]]
49})
50}
51
52return <appContext.Provider
53value={{
54 Icons : state.Icons,
55 Items : state.Items,
56 AddItem,
57 RemoveItem
58 }}>
59{props.children}
60</appContext.Provider>
61}
62
63export default AppState;
64// Reducer Module
65
66import {
67 ICONS_SHOW,
68 ICONS_HIDE,
69 ITEMS,
70 ADD_ITEM,
71 REMOVE_ITEM
72} from "../types"
73
74export default (state, action ) => {
75
76switch(action.type) {
77 case ICONS_SHOW:
78 return {
79 ...state,
80 Icons: true
81 }
82 case ICONS_HIDE:
83 return {
84 ...state,
85 Icons: false
86 }
87 case ITEMS:
88 return {
89 ...state,
90 Items: action.Items
91 }
92 case ADD_ITEM:
93 return {
94 ...state,
95 Items: [...state.Items, action.payload]
96
97 }
98 case REMOVE_ITEM:
99 return {
100 ...state,
101 Items: action.payload
102 }
103default:
104return state
105}
106}"dependencies": {
107 "@fortawesome/fontawesome-svg-core": "^1.2.36",
108 "@fortawesome/free-brands-svg-icons": "^5.15.4",
109 "@fortawesome/free-regular-svg-icons": "^5.15.4",
110 "@fortawesome/free-solid-svg-icons": "^5.15.4",
111 "@fortawesome/react-fontawesome": "^0.1.15",
112 "@testing-library/jest-dom": "^5.14.1",
113 "@testing-library/react": "^11.2.7",
114 "@testing-library/user-event": "^12.8.3",
115 "moment-timezone": "^0.5.33",
116 "node-sass": "^6.0.1",
117 "react": "^17.0.2",
118 "react-dom": "^17.0.2",
119 "react-live-clock": "^5.2.0",
120 "react-modal": "^3.14.3",
121 "react-moment": "^1.1.1",
122 "react-scripts": "4.0.3",
123 "uuid": "^8.3.2",
124 "web-vitals": "^1.1.2"
125 },
126const CentContext = createContext({
127 Icons: null,
128 rows: {},
129 addItem: () => {},
130 removeItem: () => {}
131});
132
appReducer - When adding items store only a new element id. When removing items used the passed element id to filter the row's data.
1// Context Module
2import React, { useReducer } from 'react'
3import appContext from './appContext'
4import AppReducer from './appReducer'
5import Item from '../../components/Item';
6// the action to chanhe the state !!!
7import {
8 ICONS,
9 ITEMS,
10 ADD_ITEM,
11 REMOVE_ITEM
12
13} from '../types'
14// Creating the state MUST BE A CAPITAL OTHER WISE IT WILL B^&% !! AND REFUSE TO COMPILE
15const AppState = (props) => {
16const initialState = {
17 Icons : false,
18 Items : [<Item/>],
19}
20
21const [state, dispatch] = useReducer(AppReducer, initialState)
22const Iconsshow = () => {
23 // show the icon
24 dispatch({
25 type: ICONS,
26 stabelIcons : true
27 })
28}
29
30const Iconshide = () => {
31 // show the icon
32 dispatch({
33 type: ICONS,
34 stabelIcons : false
35 })
36}
37
38const AddItem = ()=> {
39 dispatch({
40 type: ADD_ITEM,
41 Items : [...state.Items, initialState.Items]
42})
43}
44
45const RemoveItem = (e)=> {
46 dispatch({
47 type: REMOVE_ITEM,
48 Items : [[<Item/>]]
49})
50}
51
52return <appContext.Provider
53value={{
54 Icons : state.Icons,
55 Items : state.Items,
56 AddItem,
57 RemoveItem
58 }}>
59{props.children}
60</appContext.Provider>
61}
62
63export default AppState;
64// Reducer Module
65
66import {
67 ICONS_SHOW,
68 ICONS_HIDE,
69 ITEMS,
70 ADD_ITEM,
71 REMOVE_ITEM
72} from "../types"
73
74export default (state, action ) => {
75
76switch(action.type) {
77 case ICONS_SHOW:
78 return {
79 ...state,
80 Icons: true
81 }
82 case ICONS_HIDE:
83 return {
84 ...state,
85 Icons: false
86 }
87 case ITEMS:
88 return {
89 ...state,
90 Items: action.Items
91 }
92 case ADD_ITEM:
93 return {
94 ...state,
95 Items: [...state.Items, action.payload]
96
97 }
98 case REMOVE_ITEM:
99 return {
100 ...state,
101 Items: action.payload
102 }
103default:
104return state
105}
106}"dependencies": {
107 "@fortawesome/fontawesome-svg-core": "^1.2.36",
108 "@fortawesome/free-brands-svg-icons": "^5.15.4",
109 "@fortawesome/free-regular-svg-icons": "^5.15.4",
110 "@fortawesome/free-solid-svg-icons": "^5.15.4",
111 "@fortawesome/react-fontawesome": "^0.1.15",
112 "@testing-library/jest-dom": "^5.14.1",
113 "@testing-library/react": "^11.2.7",
114 "@testing-library/user-event": "^12.8.3",
115 "moment-timezone": "^0.5.33",
116 "node-sass": "^6.0.1",
117 "react": "^17.0.2",
118 "react-dom": "^17.0.2",
119 "react-live-clock": "^5.2.0",
120 "react-modal": "^3.14.3",
121 "react-moment": "^1.1.1",
122 "react-scripts": "4.0.3",
123 "uuid": "^8.3.2",
124 "web-vitals": "^1.1.2"
125 },
126const CentContext = createContext({
127 Icons: null,
128 rows: {},
129 addItem: () => {},
130 removeItem: () => {}
131});
132import { v4 as uuidV4 } from "uuid";
133
134...
135
136export default (state, action) => {
137 switch (action.type) {
138 ...
139
140 case ADD_ITEM:
141 console.log("add item");
142 return {
143 ...state,
144 rows: {
145 ...state.rows,
146 [action.rowId]: [
147 ...(state.rows[action.rowId] ?? []),
148 { id: uuidV4() }
149 ]
150 }
151 };
152
153 case REMOVE_ITEM:
154 return {
155 ...state,
156 rows: {
157 ...state.rows,
158 [action.rowId]: state.rows[action.rowId]?.filter(
159 (el) => el.id !== action.elementId
160 )
161 }
162 };
163
164 default:
165 return state;
166 }
167};
168
appState - Swap the items state for a rows
object state. Update the add/remove item action creators to consume the appropriate row and element ids. Pass the rows
state to the context provider.
1// Context Module
2import React, { useReducer } from 'react'
3import appContext from './appContext'
4import AppReducer from './appReducer'
5import Item from '../../components/Item';
6// the action to chanhe the state !!!
7import {
8 ICONS,
9 ITEMS,
10 ADD_ITEM,
11 REMOVE_ITEM
12
13} from '../types'
14// Creating the state MUST BE A CAPITAL OTHER WISE IT WILL B^&% !! AND REFUSE TO COMPILE
15const AppState = (props) => {
16const initialState = {
17 Icons : false,
18 Items : [<Item/>],
19}
20
21const [state, dispatch] = useReducer(AppReducer, initialState)
22const Iconsshow = () => {
23 // show the icon
24 dispatch({
25 type: ICONS,
26 stabelIcons : true
27 })
28}
29
30const Iconshide = () => {
31 // show the icon
32 dispatch({
33 type: ICONS,
34 stabelIcons : false
35 })
36}
37
38const AddItem = ()=> {
39 dispatch({
40 type: ADD_ITEM,
41 Items : [...state.Items, initialState.Items]
42})
43}
44
45const RemoveItem = (e)=> {
46 dispatch({
47 type: REMOVE_ITEM,
48 Items : [[<Item/>]]
49})
50}
51
52return <appContext.Provider
53value={{
54 Icons : state.Icons,
55 Items : state.Items,
56 AddItem,
57 RemoveItem
58 }}>
59{props.children}
60</appContext.Provider>
61}
62
63export default AppState;
64// Reducer Module
65
66import {
67 ICONS_SHOW,
68 ICONS_HIDE,
69 ITEMS,
70 ADD_ITEM,
71 REMOVE_ITEM
72} from "../types"
73
74export default (state, action ) => {
75
76switch(action.type) {
77 case ICONS_SHOW:
78 return {
79 ...state,
80 Icons: true
81 }
82 case ICONS_HIDE:
83 return {
84 ...state,
85 Icons: false
86 }
87 case ITEMS:
88 return {
89 ...state,
90 Items: action.Items
91 }
92 case ADD_ITEM:
93 return {
94 ...state,
95 Items: [...state.Items, action.payload]
96
97 }
98 case REMOVE_ITEM:
99 return {
100 ...state,
101 Items: action.payload
102 }
103default:
104return state
105}
106}"dependencies": {
107 "@fortawesome/fontawesome-svg-core": "^1.2.36",
108 "@fortawesome/free-brands-svg-icons": "^5.15.4",
109 "@fortawesome/free-regular-svg-icons": "^5.15.4",
110 "@fortawesome/free-solid-svg-icons": "^5.15.4",
111 "@fortawesome/react-fontawesome": "^0.1.15",
112 "@testing-library/jest-dom": "^5.14.1",
113 "@testing-library/react": "^11.2.7",
114 "@testing-library/user-event": "^12.8.3",
115 "moment-timezone": "^0.5.33",
116 "node-sass": "^6.0.1",
117 "react": "^17.0.2",
118 "react-dom": "^17.0.2",
119 "react-live-clock": "^5.2.0",
120 "react-modal": "^3.14.3",
121 "react-moment": "^1.1.1",
122 "react-scripts": "4.0.3",
123 "uuid": "^8.3.2",
124 "web-vitals": "^1.1.2"
125 },
126const CentContext = createContext({
127 Icons: null,
128 rows: {},
129 addItem: () => {},
130 removeItem: () => {}
131});
132import { v4 as uuidV4 } from "uuid";
133
134...
135
136export default (state, action) => {
137 switch (action.type) {
138 ...
139
140 case ADD_ITEM:
141 console.log("add item");
142 return {
143 ...state,
144 rows: {
145 ...state.rows,
146 [action.rowId]: [
147 ...(state.rows[action.rowId] ?? []),
148 { id: uuidV4() }
149 ]
150 }
151 };
152
153 case REMOVE_ITEM:
154 return {
155 ...state,
156 rows: {
157 ...state.rows,
158 [action.rowId]: state.rows[action.rowId]?.filter(
159 (el) => el.id !== action.elementId
160 )
161 }
162 };
163
164 default:
165 return state;
166 }
167};
168const AppState = (props) => {
169 const initialState = {
170 Icons: false,
171 rows: {}
172 };
173
174 const [state, dispatch] = useReducer(AppReducer, initialState);
175
176 ...
177
178 const addItem = (rowId) => {
179 dispatch({
180 type: ADD_ITEM,
181 rowId,
182 });
183 };
184
185 const removeItem = (rowId, elementId) => {
186 dispatch({
187 type: REMOVE_ITEM,
188 rowId,
189 elementId,
190 });
191 };
192
193 return (
194 <appContext.Provider
195 value={{
196 Icons: state.Icons,
197 Items: state.Items,
198 rows: state.rows,
199 addItem,
200 removeItem
201 }}
202 >
203 {props.children}
204 </appContext.Provider>
205 );
206};
207
App - Give each Row
component an id
prop to uniquely identify it.
1// Context Module
2import React, { useReducer } from 'react'
3import appContext from './appContext'
4import AppReducer from './appReducer'
5import Item from '../../components/Item';
6// the action to chanhe the state !!!
7import {
8 ICONS,
9 ITEMS,
10 ADD_ITEM,
11 REMOVE_ITEM
12
13} from '../types'
14// Creating the state MUST BE A CAPITAL OTHER WISE IT WILL B^&% !! AND REFUSE TO COMPILE
15const AppState = (props) => {
16const initialState = {
17 Icons : false,
18 Items : [<Item/>],
19}
20
21const [state, dispatch] = useReducer(AppReducer, initialState)
22const Iconsshow = () => {
23 // show the icon
24 dispatch({
25 type: ICONS,
26 stabelIcons : true
27 })
28}
29
30const Iconshide = () => {
31 // show the icon
32 dispatch({
33 type: ICONS,
34 stabelIcons : false
35 })
36}
37
38const AddItem = ()=> {
39 dispatch({
40 type: ADD_ITEM,
41 Items : [...state.Items, initialState.Items]
42})
43}
44
45const RemoveItem = (e)=> {
46 dispatch({
47 type: REMOVE_ITEM,
48 Items : [[<Item/>]]
49})
50}
51
52return <appContext.Provider
53value={{
54 Icons : state.Icons,
55 Items : state.Items,
56 AddItem,
57 RemoveItem
58 }}>
59{props.children}
60</appContext.Provider>
61}
62
63export default AppState;
64// Reducer Module
65
66import {
67 ICONS_SHOW,
68 ICONS_HIDE,
69 ITEMS,
70 ADD_ITEM,
71 REMOVE_ITEM
72} from "../types"
73
74export default (state, action ) => {
75
76switch(action.type) {
77 case ICONS_SHOW:
78 return {
79 ...state,
80 Icons: true
81 }
82 case ICONS_HIDE:
83 return {
84 ...state,
85 Icons: false
86 }
87 case ITEMS:
88 return {
89 ...state,
90 Items: action.Items
91 }
92 case ADD_ITEM:
93 return {
94 ...state,
95 Items: [...state.Items, action.payload]
96
97 }
98 case REMOVE_ITEM:
99 return {
100 ...state,
101 Items: action.payload
102 }
103default:
104return state
105}
106}"dependencies": {
107 "@fortawesome/fontawesome-svg-core": "^1.2.36",
108 "@fortawesome/free-brands-svg-icons": "^5.15.4",
109 "@fortawesome/free-regular-svg-icons": "^5.15.4",
110 "@fortawesome/free-solid-svg-icons": "^5.15.4",
111 "@fortawesome/react-fontawesome": "^0.1.15",
112 "@testing-library/jest-dom": "^5.14.1",
113 "@testing-library/react": "^11.2.7",
114 "@testing-library/user-event": "^12.8.3",
115 "moment-timezone": "^0.5.33",
116 "node-sass": "^6.0.1",
117 "react": "^17.0.2",
118 "react-dom": "^17.0.2",
119 "react-live-clock": "^5.2.0",
120 "react-modal": "^3.14.3",
121 "react-moment": "^1.1.1",
122 "react-scripts": "4.0.3",
123 "uuid": "^8.3.2",
124 "web-vitals": "^1.1.2"
125 },
126const CentContext = createContext({
127 Icons: null,
128 rows: {},
129 addItem: () => {},
130 removeItem: () => {}
131});
132import { v4 as uuidV4 } from "uuid";
133
134...
135
136export default (state, action) => {
137 switch (action.type) {
138 ...
139
140 case ADD_ITEM:
141 console.log("add item");
142 return {
143 ...state,
144 rows: {
145 ...state.rows,
146 [action.rowId]: [
147 ...(state.rows[action.rowId] ?? []),
148 { id: uuidV4() }
149 ]
150 }
151 };
152
153 case REMOVE_ITEM:
154 return {
155 ...state,
156 rows: {
157 ...state.rows,
158 [action.rowId]: state.rows[action.rowId]?.filter(
159 (el) => el.id !== action.elementId
160 )
161 }
162 };
163
164 default:
165 return state;
166 }
167};
168const AppState = (props) => {
169 const initialState = {
170 Icons: false,
171 rows: {}
172 };
173
174 const [state, dispatch] = useReducer(AppReducer, initialState);
175
176 ...
177
178 const addItem = (rowId) => {
179 dispatch({
180 type: ADD_ITEM,
181 rowId,
182 });
183 };
184
185 const removeItem = (rowId, elementId) => {
186 dispatch({
187 type: REMOVE_ITEM,
188 rowId,
189 elementId,
190 });
191 };
192
193 return (
194 <appContext.Provider
195 value={{
196 Icons: state.Icons,
197 Items: state.Items,
198 rows: state.rows,
199 addItem,
200 removeItem
201 }}
202 >
203 {props.children}
204 </appContext.Provider>
205 );
206};
207<AppState>
208 <Row id={1} />
209 <Row id={2} />
210 <Row id={3} />
211</AppState>
212
Row - Pass the rows id
prop to the addItem
handler. Map the rows
state to the Item
component.
1// Context Module
2import React, { useReducer } from 'react'
3import appContext from './appContext'
4import AppReducer from './appReducer'
5import Item from '../../components/Item';
6// the action to chanhe the state !!!
7import {
8 ICONS,
9 ITEMS,
10 ADD_ITEM,
11 REMOVE_ITEM
12
13} from '../types'
14// Creating the state MUST BE A CAPITAL OTHER WISE IT WILL B^&% !! AND REFUSE TO COMPILE
15const AppState = (props) => {
16const initialState = {
17 Icons : false,
18 Items : [<Item/>],
19}
20
21const [state, dispatch] = useReducer(AppReducer, initialState)
22const Iconsshow = () => {
23 // show the icon
24 dispatch({
25 type: ICONS,
26 stabelIcons : true
27 })
28}
29
30const Iconshide = () => {
31 // show the icon
32 dispatch({
33 type: ICONS,
34 stabelIcons : false
35 })
36}
37
38const AddItem = ()=> {
39 dispatch({
40 type: ADD_ITEM,
41 Items : [...state.Items, initialState.Items]
42})
43}
44
45const RemoveItem = (e)=> {
46 dispatch({
47 type: REMOVE_ITEM,
48 Items : [[<Item/>]]
49})
50}
51
52return <appContext.Provider
53value={{
54 Icons : state.Icons,
55 Items : state.Items,
56 AddItem,
57 RemoveItem
58 }}>
59{props.children}
60</appContext.Provider>
61}
62
63export default AppState;
64// Reducer Module
65
66import {
67 ICONS_SHOW,
68 ICONS_HIDE,
69 ITEMS,
70 ADD_ITEM,
71 REMOVE_ITEM
72} from "../types"
73
74export default (state, action ) => {
75
76switch(action.type) {
77 case ICONS_SHOW:
78 return {
79 ...state,
80 Icons: true
81 }
82 case ICONS_HIDE:
83 return {
84 ...state,
85 Icons: false
86 }
87 case ITEMS:
88 return {
89 ...state,
90 Items: action.Items
91 }
92 case ADD_ITEM:
93 return {
94 ...state,
95 Items: [...state.Items, action.payload]
96
97 }
98 case REMOVE_ITEM:
99 return {
100 ...state,
101 Items: action.payload
102 }
103default:
104return state
105}
106}"dependencies": {
107 "@fortawesome/fontawesome-svg-core": "^1.2.36",
108 "@fortawesome/free-brands-svg-icons": "^5.15.4",
109 "@fortawesome/free-regular-svg-icons": "^5.15.4",
110 "@fortawesome/free-solid-svg-icons": "^5.15.4",
111 "@fortawesome/react-fontawesome": "^0.1.15",
112 "@testing-library/jest-dom": "^5.14.1",
113 "@testing-library/react": "^11.2.7",
114 "@testing-library/user-event": "^12.8.3",
115 "moment-timezone": "^0.5.33",
116 "node-sass": "^6.0.1",
117 "react": "^17.0.2",
118 "react-dom": "^17.0.2",
119 "react-live-clock": "^5.2.0",
120 "react-modal": "^3.14.3",
121 "react-moment": "^1.1.1",
122 "react-scripts": "4.0.3",
123 "uuid": "^8.3.2",
124 "web-vitals": "^1.1.2"
125 },
126const CentContext = createContext({
127 Icons: null,
128 rows: {},
129 addItem: () => {},
130 removeItem: () => {}
131});
132import { v4 as uuidV4 } from "uuid";
133
134...
135
136export default (state, action) => {
137 switch (action.type) {
138 ...
139
140 case ADD_ITEM:
141 console.log("add item");
142 return {
143 ...state,
144 rows: {
145 ...state.rows,
146 [action.rowId]: [
147 ...(state.rows[action.rowId] ?? []),
148 { id: uuidV4() }
149 ]
150 }
151 };
152
153 case REMOVE_ITEM:
154 return {
155 ...state,
156 rows: {
157 ...state.rows,
158 [action.rowId]: state.rows[action.rowId]?.filter(
159 (el) => el.id !== action.elementId
160 )
161 }
162 };
163
164 default:
165 return state;
166 }
167};
168const AppState = (props) => {
169 const initialState = {
170 Icons: false,
171 rows: {}
172 };
173
174 const [state, dispatch] = useReducer(AppReducer, initialState);
175
176 ...
177
178 const addItem = (rowId) => {
179 dispatch({
180 type: ADD_ITEM,
181 rowId,
182 });
183 };
184
185 const removeItem = (rowId, elementId) => {
186 dispatch({
187 type: REMOVE_ITEM,
188 rowId,
189 elementId,
190 });
191 };
192
193 return (
194 <appContext.Provider
195 value={{
196 Icons: state.Icons,
197 Items: state.Items,
198 rows: state.rows,
199 addItem,
200 removeItem
201 }}
202 >
203 {props.children}
204 </appContext.Provider>
205 );
206};
207<AppState>
208 <Row id={1} />
209 <Row id={2} />
210 <Row id={3} />
211</AppState>
212function Row(props) {
213 // getting the context needed
214 const context = useContext(appContext);
215 return (
216 <li className="day-row check faderin">
217 <div className="income-outcome">
218 <div className="vl-changable"></div>
219 <ul className="global income dayIncome">
220 {context.rows[props.id]?.map((el) => (
221 <Item key={el.id} rowId={props.id} id={el.id} />
222 ))}
223 <FontAwesomeIcon
224 className="changable margin-left"
225 onClick={() => context.addItem(props.id)}
226 icon={["fas", "plus-circle"]}
227 size="lg"
228 />
229 </ul>
230 </div>
231 </li>
232 );
233}
234
Removing a single element from state was covered above, but you need to pass the correct row and element ids to the removeItem
handler.
1// Context Module
2import React, { useReducer } from 'react'
3import appContext from './appContext'
4import AppReducer from './appReducer'
5import Item from '../../components/Item';
6// the action to chanhe the state !!!
7import {
8 ICONS,
9 ITEMS,
10 ADD_ITEM,
11 REMOVE_ITEM
12
13} from '../types'
14// Creating the state MUST BE A CAPITAL OTHER WISE IT WILL B^&% !! AND REFUSE TO COMPILE
15const AppState = (props) => {
16const initialState = {
17 Icons : false,
18 Items : [<Item/>],
19}
20
21const [state, dispatch] = useReducer(AppReducer, initialState)
22const Iconsshow = () => {
23 // show the icon
24 dispatch({
25 type: ICONS,
26 stabelIcons : true
27 })
28}
29
30const Iconshide = () => {
31 // show the icon
32 dispatch({
33 type: ICONS,
34 stabelIcons : false
35 })
36}
37
38const AddItem = ()=> {
39 dispatch({
40 type: ADD_ITEM,
41 Items : [...state.Items, initialState.Items]
42})
43}
44
45const RemoveItem = (e)=> {
46 dispatch({
47 type: REMOVE_ITEM,
48 Items : [[<Item/>]]
49})
50}
51
52return <appContext.Provider
53value={{
54 Icons : state.Icons,
55 Items : state.Items,
56 AddItem,
57 RemoveItem
58 }}>
59{props.children}
60</appContext.Provider>
61}
62
63export default AppState;
64// Reducer Module
65
66import {
67 ICONS_SHOW,
68 ICONS_HIDE,
69 ITEMS,
70 ADD_ITEM,
71 REMOVE_ITEM
72} from "../types"
73
74export default (state, action ) => {
75
76switch(action.type) {
77 case ICONS_SHOW:
78 return {
79 ...state,
80 Icons: true
81 }
82 case ICONS_HIDE:
83 return {
84 ...state,
85 Icons: false
86 }
87 case ITEMS:
88 return {
89 ...state,
90 Items: action.Items
91 }
92 case ADD_ITEM:
93 return {
94 ...state,
95 Items: [...state.Items, action.payload]
96
97 }
98 case REMOVE_ITEM:
99 return {
100 ...state,
101 Items: action.payload
102 }
103default:
104return state
105}
106}"dependencies": {
107 "@fortawesome/fontawesome-svg-core": "^1.2.36",
108 "@fortawesome/free-brands-svg-icons": "^5.15.4",
109 "@fortawesome/free-regular-svg-icons": "^5.15.4",
110 "@fortawesome/free-solid-svg-icons": "^5.15.4",
111 "@fortawesome/react-fontawesome": "^0.1.15",
112 "@testing-library/jest-dom": "^5.14.1",
113 "@testing-library/react": "^11.2.7",
114 "@testing-library/user-event": "^12.8.3",
115 "moment-timezone": "^0.5.33",
116 "node-sass": "^6.0.1",
117 "react": "^17.0.2",
118 "react-dom": "^17.0.2",
119 "react-live-clock": "^5.2.0",
120 "react-modal": "^3.14.3",
121 "react-moment": "^1.1.1",
122 "react-scripts": "4.0.3",
123 "uuid": "^8.3.2",
124 "web-vitals": "^1.1.2"
125 },
126const CentContext = createContext({
127 Icons: null,
128 rows: {},
129 addItem: () => {},
130 removeItem: () => {}
131});
132import { v4 as uuidV4 } from "uuid";
133
134...
135
136export default (state, action) => {
137 switch (action.type) {
138 ...
139
140 case ADD_ITEM:
141 console.log("add item");
142 return {
143 ...state,
144 rows: {
145 ...state.rows,
146 [action.rowId]: [
147 ...(state.rows[action.rowId] ?? []),
148 { id: uuidV4() }
149 ]
150 }
151 };
152
153 case REMOVE_ITEM:
154 return {
155 ...state,
156 rows: {
157 ...state.rows,
158 [action.rowId]: state.rows[action.rowId]?.filter(
159 (el) => el.id !== action.elementId
160 )
161 }
162 };
163
164 default:
165 return state;
166 }
167};
168const AppState = (props) => {
169 const initialState = {
170 Icons: false,
171 rows: {}
172 };
173
174 const [state, dispatch] = useReducer(AppReducer, initialState);
175
176 ...
177
178 const addItem = (rowId) => {
179 dispatch({
180 type: ADD_ITEM,
181 rowId,
182 });
183 };
184
185 const removeItem = (rowId, elementId) => {
186 dispatch({
187 type: REMOVE_ITEM,
188 rowId,
189 elementId,
190 });
191 };
192
193 return (
194 <appContext.Provider
195 value={{
196 Icons: state.Icons,
197 Items: state.Items,
198 rows: state.rows,
199 addItem,
200 removeItem
201 }}
202 >
203 {props.children}
204 </appContext.Provider>
205 );
206};
207<AppState>
208 <Row id={1} />
209 <Row id={2} />
210 <Row id={3} />
211</AppState>
212function Row(props) {
213 // getting the context needed
214 const context = useContext(appContext);
215 return (
216 <li className="day-row check faderin">
217 <div className="income-outcome">
218 <div className="vl-changable"></div>
219 <ul className="global income dayIncome">
220 {context.rows[props.id]?.map((el) => (
221 <Item key={el.id} rowId={props.id} id={el.id} />
222 ))}
223 <FontAwesomeIcon
224 className="changable margin-left"
225 onClick={() => context.addItem(props.id)}
226 icon={["fas", "plus-circle"]}
227 size="lg"
228 />
229 </ul>
230 </div>
231 </li>
232 );
233}
234function ChangeablelItem(props) {
235 const { rowId, id } = props;
236 const context = useContext(appContext);
237 ...
238 return (
239 <li className="day-item">
240 ... editable div ...
241 <div className="icons">
242 {iconsVisble && (
243 <RemoveIcon
244 removeItem={() => context.removeItem(rowId, id)}
245 />
246 )}
247 </div>
248 </li>
249 );
250}
251
This was actually the easiest issue to resolve. Use onFocus
and onBlur
handlers to set the iconVisible
state to show the delete button. I used a setTimeout
on the blur handler to keep it the delete button mounted long enough when clicked to call the removeItem
handler.
1// Context Module
2import React, { useReducer } from 'react'
3import appContext from './appContext'
4import AppReducer from './appReducer'
5import Item from '../../components/Item';
6// the action to chanhe the state !!!
7import {
8 ICONS,
9 ITEMS,
10 ADD_ITEM,
11 REMOVE_ITEM
12
13} from '../types'
14// Creating the state MUST BE A CAPITAL OTHER WISE IT WILL B^&% !! AND REFUSE TO COMPILE
15const AppState = (props) => {
16const initialState = {
17 Icons : false,
18 Items : [<Item/>],
19}
20
21const [state, dispatch] = useReducer(AppReducer, initialState)
22const Iconsshow = () => {
23 // show the icon
24 dispatch({
25 type: ICONS,
26 stabelIcons : true
27 })
28}
29
30const Iconshide = () => {
31 // show the icon
32 dispatch({
33 type: ICONS,
34 stabelIcons : false
35 })
36}
37
38const AddItem = ()=> {
39 dispatch({
40 type: ADD_ITEM,
41 Items : [...state.Items, initialState.Items]
42})
43}
44
45const RemoveItem = (e)=> {
46 dispatch({
47 type: REMOVE_ITEM,
48 Items : [[<Item/>]]
49})
50}
51
52return <appContext.Provider
53value={{
54 Icons : state.Icons,
55 Items : state.Items,
56 AddItem,
57 RemoveItem
58 }}>
59{props.children}
60</appContext.Provider>
61}
62
63export default AppState;
64// Reducer Module
65
66import {
67 ICONS_SHOW,
68 ICONS_HIDE,
69 ITEMS,
70 ADD_ITEM,
71 REMOVE_ITEM
72} from "../types"
73
74export default (state, action ) => {
75
76switch(action.type) {
77 case ICONS_SHOW:
78 return {
79 ...state,
80 Icons: true
81 }
82 case ICONS_HIDE:
83 return {
84 ...state,
85 Icons: false
86 }
87 case ITEMS:
88 return {
89 ...state,
90 Items: action.Items
91 }
92 case ADD_ITEM:
93 return {
94 ...state,
95 Items: [...state.Items, action.payload]
96
97 }
98 case REMOVE_ITEM:
99 return {
100 ...state,
101 Items: action.payload
102 }
103default:
104return state
105}
106}"dependencies": {
107 "@fortawesome/fontawesome-svg-core": "^1.2.36",
108 "@fortawesome/free-brands-svg-icons": "^5.15.4",
109 "@fortawesome/free-regular-svg-icons": "^5.15.4",
110 "@fortawesome/free-solid-svg-icons": "^5.15.4",
111 "@fortawesome/react-fontawesome": "^0.1.15",
112 "@testing-library/jest-dom": "^5.14.1",
113 "@testing-library/react": "^11.2.7",
114 "@testing-library/user-event": "^12.8.3",
115 "moment-timezone": "^0.5.33",
116 "node-sass": "^6.0.1",
117 "react": "^17.0.2",
118 "react-dom": "^17.0.2",
119 "react-live-clock": "^5.2.0",
120 "react-modal": "^3.14.3",
121 "react-moment": "^1.1.1",
122 "react-scripts": "4.0.3",
123 "uuid": "^8.3.2",
124 "web-vitals": "^1.1.2"
125 },
126const CentContext = createContext({
127 Icons: null,
128 rows: {},
129 addItem: () => {},
130 removeItem: () => {}
131});
132import { v4 as uuidV4 } from "uuid";
133
134...
135
136export default (state, action) => {
137 switch (action.type) {
138 ...
139
140 case ADD_ITEM:
141 console.log("add item");
142 return {
143 ...state,
144 rows: {
145 ...state.rows,
146 [action.rowId]: [
147 ...(state.rows[action.rowId] ?? []),
148 { id: uuidV4() }
149 ]
150 }
151 };
152
153 case REMOVE_ITEM:
154 return {
155 ...state,
156 rows: {
157 ...state.rows,
158 [action.rowId]: state.rows[action.rowId]?.filter(
159 (el) => el.id !== action.elementId
160 )
161 }
162 };
163
164 default:
165 return state;
166 }
167};
168const AppState = (props) => {
169 const initialState = {
170 Icons: false,
171 rows: {}
172 };
173
174 const [state, dispatch] = useReducer(AppReducer, initialState);
175
176 ...
177
178 const addItem = (rowId) => {
179 dispatch({
180 type: ADD_ITEM,
181 rowId,
182 });
183 };
184
185 const removeItem = (rowId, elementId) => {
186 dispatch({
187 type: REMOVE_ITEM,
188 rowId,
189 elementId,
190 });
191 };
192
193 return (
194 <appContext.Provider
195 value={{
196 Icons: state.Icons,
197 Items: state.Items,
198 rows: state.rows,
199 addItem,
200 removeItem
201 }}
202 >
203 {props.children}
204 </appContext.Provider>
205 );
206};
207<AppState>
208 <Row id={1} />
209 <Row id={2} />
210 <Row id={3} />
211</AppState>
212function Row(props) {
213 // getting the context needed
214 const context = useContext(appContext);
215 return (
216 <li className="day-row check faderin">
217 <div className="income-outcome">
218 <div className="vl-changable"></div>
219 <ul className="global income dayIncome">
220 {context.rows[props.id]?.map((el) => (
221 <Item key={el.id} rowId={props.id} id={el.id} />
222 ))}
223 <FontAwesomeIcon
224 className="changable margin-left"
225 onClick={() => context.addItem(props.id)}
226 icon={["fas", "plus-circle"]}
227 size="lg"
228 />
229 </ul>
230 </div>
231 </li>
232 );
233}
234function ChangeablelItem(props) {
235 const { rowId, id } = props;
236 const context = useContext(appContext);
237 ...
238 return (
239 <li className="day-item">
240 ... editable div ...
241 <div className="icons">
242 {iconsVisble && (
243 <RemoveIcon
244 removeItem={() => context.removeItem(rowId, id)}
245 />
246 )}
247 </div>
248 </li>
249 );
250}
251// Icon State
252const [iconsVisble, setIconVisble] = useState(false);
253
254...
255
256<div
257 className="number amount"
258 onFocus={() => setIconVisble(true)}
259 onBlur={() => setTimeout(() => setIconVisble(false), 200)}
260 contentEditable="true"
261/>
262
QUESTION
BLE: How to get correct service UUID and characteristic UUID?
Asked 2021-Jan-08 at 06:18I am a new in Bluetooth connection and I want to add second device in my iOS project. I already have one device, and the new device is very similar with first one, but little bit deferent. I have one process for the two devices, and I did not change a lot of code, just created all value for the new device. My all devices have different name and identifier, first device is working fine.
For creating UUID values, I used UUID generator (https://www.guidgenerator.com/online-guid-generator.aspx).
1class BleConstants: NSObject {
2let deviceTwoServiceUUID = “59DE3994-6A63-4654-8FF0-F85C5163B2F5”
3let deviceTwoFirstCharacteristicUUID = “59DE3994-6A63-4654-8FF0-F85C5163B2F6”
4let deviceTwoSecondCharacteristicUUID = “59DE3994-6A63-4654-8FF0-F85C5163B2F7”
5let deviceOneServiceUUID = “A6AF4483-E210-457B-B9D6-B8A621513D1D”
6let deviceOneFirstCharacteristicUUID = “A6AF4483-E210-457B-B9D6-B8A621513D2D”
7let deviceOneSecondCharacteristicUUID = “A6AF4483-E210-457B-B9D6-B8A621513D2D”
8}
9
10class BleManager: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate {
11@objc private(set) static var sharedInstance = BleManager()
12var cbManager : CBCentralManager? = nil
13var currentPeripheral : CBPeripheral? = nil
14var secondService : CBService? = nil
15var firstService : CBService? = nil
16var secondFirstCharacteristic : CBCharacteristic!
17var secondSecondCharacteristic : CBCharacteristic!
18var firstFirstCharacteristic : CBCharacteristic!
19var firstSecondCharacteristic : CBCharacteristic!
20
21func initCentralManager() {
22 if cbManager == nil {
23 cbManager = CBCentralManager(delegate: self, queue: nil, options: [CBCentralManagerOptionRestoreIdentifierKey : “MyApp”, CBCentralManagerOptionShowPowerAlertKey: true])
24 }
25
26func deinitCentralManager() {
27 cbManager = nil
28}
29
30func isBluetoothAvailable() -> Bool {
31 return cbManager?.state == CBManagerState.poweredOn
32}
33
34func scan() {
35 if (cbManager != nil && (cbManager?.isScanning)!) {
36 return
37 }
38
39 discoveredPeripherals.removeAll()
40
41 let serviceUUIDs = [CBUUID(string: BleConstants.deviceTwoServiceUUID), CBUUID(string: BleConstants.deviceOneServiceUUID)]
42
43 cbManager?.scanForPeripherals(withServices: serviceUUIDs,
44 options: [CBCentralManagerScanOptionAllowDuplicatesKey : 1])
45}
46
47func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
48 if(!discoveredPeripherals.contains(peripheral)) {
49 discoveredPeripherals.append(peripheral)
50 }
51}
52
53func stopScan() {
54 if cbManager != nil && (cbManager?.isScanning)! {
55 cbManager?.stopScan()
56 }
57}
58
59func connect(peripheral: CBPeripheral) {
60 if cbManager?.state == CBManagerState.poweredOn {
61 if currentPeripheral == nil || currentPeripheral?.state != CBPeripheralState.connected {
62 cbManager?.connect(peripheral, options: nil)
63 } else {
64 cbManager?.cancelPeripheralConnection(peripheral)
65 }
66 }
67}
68
69func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
70Device.savePeripheralString(peripheral: peripheral.identifier.uuidString)
71 AutoConnect.stop()
72DeviceUpdate.updateProgress = .None
73Device.isDongleConnected = true
74currentPeripheral = peripheral
75currentPeripheral?.delegate = self
76currentPeripheral?.discoverServices(nil)
77disableSleep()
78}
79
80func disableSleep() {
81 UIApplication.shared.isIdleTimerDisabled = true
82}
83
84func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
85 if error != nil {
86 return
87 }
88
89 if let services = peripheral.services {
90
91 for service in services {
92 if service.uuid.uuidString == BleConstants.deviceTwoServiceUUID {
93 Device.dongleType = port.second
94 secondService = service
95 peripheral.discoverCharacteristics(nil, for: service)
96 }
97 if service.uuid.uuidString == BleConstants.deviceOneServiceUUID {
98 Device.dongleType = port.first
99 firstService = service
100 peripheral.discoverCharacteristics(nil, for: service)
101 } else {
102 Log.bt("didDiscoverServices for peripheral not found \(peripheral.identifier.uuidString)")
103 }
104 }
105 }
106}
107
108func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
109
110 for characteristic in service.characteristics! {
111 if characteristic.uuid.uuidString == BleConstants.deviceOneFirstCharacteristicUUID {
112 firstCharacteristic = characteristic
113 }
114 else if characteristic.uuid.uuidString == BleConstants.deviceOneSecondCharacteristicUUID {
115 firstSecondCharacteristic = characteristic
116 else if characteristic.uuid.uuidString == BleConstants.deviceTwoFirstCharacteristicUUID {
117 secondFirstCharacteristic = characteristic
118 } else if characteristic.uuid.uuidString == BleConstants.deviceTwoSecondCharacteristicUUID {
119 secondSecondCharacteristic = characteristic
120 } else {
121 Log.bt("didDiscoverCharacteristics not found \(characteristic.uuid.uuidString)")
122 }
123 }
124
125 if Device.dongleType == .deviceTwo {
126 openPortDeviceTwo()
127 } else {
128 openPortDeviceOne()
129 }
130}
131
}
Data from logs:
For first device:
- isBluetoothAvailable()
- scan()
- CentralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) (peripheral <CBPeripheral: 0x267hg5670, identifier = 98HG761CE-56C3-K767-26HJ-E51BA678Gh56, name = DeviceOne, state = disconnected)
- CentralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber)
- scan()
- CentralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) (peripheral <CBPeripheral: 0x267hg5670, identifier = FJ1478HJ-EH8J-6709-1FH0-1456HGJ0BC901, name = SecondDevice, state = disconnected>)
- stopScan()
- connect(peripheral: CBPeripheral) (currentPeripheral nil, currentPeripheral nil)
- CentralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral
- centralManager(_:didConnect:) - didConnectPeripheral FJ1478HJ-EH8J-6709-1FH0-1456HGJ0BC901 Second device
- savedPeripheralString FJ1478HJ-EH8J-6709-1FH0-1456HGJ0BC901 Second device
- Bluetooth stop() currentPeripheral Optional(<CBPeripheral: 0x2jk875fe0, identifier = FJ1478HJ-EH8J-6709-1FH0-1456HGJ0BC901, name = SecondDevice, state = connected>)
- disableSleep()
- peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?)
- peripheral(_:didDiscoverServices:) - didDiscoverServices for peripheral FJ1478HJ-EH8J-6709-1FH0-1456HGJ0BC901
- peripheral(_:didDiscoverServices:) - didDiscoverServices for peripheral.services Optional([<CBService: 0x2jkki2dc0, isPrimary = YES, UUID = 59DE3994-6A63-4654-8FF0-F85C5163B2F5>, <CBService: 0xhj67c240, isPrimary = YES, UUID = Device Information>]) [<CBService: 0x5678f2dc0, isPrimary = YES, UUID = 59DE3994-6A63-4654-8FF0-F85C5163B2F5>, <CBService: 0x28186c240, isPrimary = YES, UUID = Device Information>], peripheral.services is Optional([<CBService: 0xhjy62dc0, isPrimary = YES, UUID = 59DE3994-6A63-4654-8FF0-F85C5163B2F5>, <CBService: 0x2hju7240, isPrimary = YES, UUID = Device Information>])) service.uuid.uuidString is 59DE3994-6A63-4654-8FF0-F85C5163B2F5 and services is [<CBService: 0xhj7892dc0, isPrimary = YES, UUID = 59DE3994-6A63-4654-8FF0-F85C5163B2F5>, <CBService: 0xhjk678340, isPrimary = YES, UUID = Device Information>]
- peripheral(_:didDiscoverServices:) - didDiscoverServices SecondDevice 59DE3994-6A63-4654-8FF0-F85C5163B2F5
- peripheral(_:didDiscoverServices:) - didDiscoverServices for peripheral not found FJ1478HJ-EH8J-6709-1FH0-1456HGJ0BC901
For second device:
- isBluetoothAvailable()
- scan()
- CentralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) (peripheral <CBPeripheral: 0xh6789a40, identifier = 98HG761CE-56C3-K767-26HJ-E51BA678Gh56, name = DeviceOne, state = disconnected)
- scan()
- CentralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) (peripheral <CBPeripheral: 0x678jhs0, identifier = H56KIL35-7835-7JKL-2B11-HJKLIYTAA400, name = ThirdDevice, state = disconnected)
- CentralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber)
- stopScan()
- connect(peripheral: CBPeripheral) currentPeripheral nil, currentPeripheral nil
- CentralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral
- centralManager(_:didConnect:) - didConnectPeripheral H56KIL35-7835-7JKL-2B11-HJKLIYTAA400
- savedPeripheralString H56KIL35-7835-7JKL-2B11-HJKLIYTAA400
- Bluetooth stop() - currentPeripheral Optional(<CBPeripheral: 0x78jkl680, identifier = H56KIL35-7835-7JKL-2B11-HJKLIYTAA400, name = ThirdDevice, state = connected>)
- disableSleep()
- peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?)
- peripheral(_:didDiscoverServices:) - didDiscoverServices for peripheral H56KIL35-7835-7JKL-2B11-HJKLIYTAA400
- **peripheral(_:didDiscoverServices:) - didDiscoverServices for peripheral.services Optional([<CBService: 0xlki8901c0, isPrimary = YES, UUID = 59DE3994-6A63-4654-8FF0-F85C5163B2F5 - same like for secondDevice>, <CBService: 0x281111180, isPrimary = YES, UUID = Device Information>]) services is [<CBService: 0x2827444c0, isPrimary = YES, UUID = 59DE3994-6A63-4654-8FF0-F85C5163B2F5 - same like for secondDevice>, <CBService: 0x282744580, isPrimary = YES, UUID = Device Information>], peripheral.services is Optional([<CBService: 0xlki8901c0, isPrimary = YES, UUID = 59DE3994-6A63-4654-8FF0-F85C5163B2F5 - same like for secondDevice>, <CBService: 0x281111180, isPrimary = YES, UUID = Device Information>])) service.uuid.uuidString is 59DE3994-6A63-4654-8FF0-F85C5163B2F5 - same like for secondDeviceand services is [<CBService: 0x27893kdc0, isPrimary = YES, UUID = 59DE3994-6A63-4654-8FF0-F85C5163B2F5 - same like for secondDevice>, <CBService: 0x679kh8580, isPrimary = YES, UUID = Device Information>]
- peripheral(_:didDiscoverServices:) - didDiscoverServices ThirdDevice 59DE3994-6A63-4654-8FF0-F85C5163B2F5 - same like for secondDevice
- peripheral(_:didDiscoverServices:) - didDiscoverServices for peripheral not found H56KIL35-7835-7JKL-2B11-HJKLIYTAA400**
Based on logs information for second device in 16th step app connected to my first service UUID and first characteristic UUID, that is wrong!
Do you have idea, Did I create UUIDs correct?
P.S: Android app works fine with both devices.
Thanks a lot!
ANSWER
Answered 2021-Jan-08 at 06:18Receiving the same service and characteristic UUID for multiple BLE devices is perfectly normal and only means that all the devices offer exactly the same service.
For example: If you have two devices which measure the heart rate of a person, e.g. a smartwatch, both devices might offer the heart rate service with the same UUID.
If you want to differentiate between the device you can use the identifier which you received in step 3 of your provided log.
QUESTION
Syntax to manually insert a UUID value in Postgres
Asked 2020-Nov-19 at 15:41I have a table that was created as such:
1CREATE TABLE IF NOT EXISTS DIM_Jour (
2 jour_id uuid NOT NULL,
3 AAAA int,
4 MM int,
5 JJ int,
6 Jour_Semaine int,
7 Num_Semaine int,
8
9 PRIMARY KEY (jour_id)
10);
11
I'm trying to manually insert some value for testing purposes. I know that eventually I would need to use a UUID generator.
1CREATE TABLE IF NOT EXISTS DIM_Jour (
2 jour_id uuid NOT NULL,
3 AAAA int,
4 MM int,
5 JJ int,
6 Jour_Semaine int,
7 Num_Semaine int,
8
9 PRIMARY KEY (jour_id)
10);
11INSERT INTO DIM_Jour (jour_id, AAAA, MM, JJ, Jour_Semaine, Num_Semaine) VALUES (
12 292a485f-a56a-4938-8f1a-bbbbbbbbbbb1,
13 2020,
14 11,
15 19,
16 4,
17 47
18);
19
I get this error (or similar)
1CREATE TABLE IF NOT EXISTS DIM_Jour (
2 jour_id uuid NOT NULL,
3 AAAA int,
4 MM int,
5 JJ int,
6 Jour_Semaine int,
7 Num_Semaine int,
8
9 PRIMARY KEY (jour_id)
10);
11INSERT INTO DIM_Jour (jour_id, AAAA, MM, JJ, Jour_Semaine, Num_Semaine) VALUES (
12 292a485f-a56a-4938-8f1a-bbbbbbbbbbb1,
13 2020,
14 11,
15 19,
16 4,
17 47
18);
19ERROR: syntax error at or near "a485f"
20 LINE 3: 292a485f-a56a-4938-8f1a-bbbbbbbbbbb1,
21 ^
22
I've tried the different formats mentioned in the Postgres documentation, but it seems like it doesn't except any format. Is it a stupid syntax issue or am I missing something here? What is the correct syntax?
ANSWER
Answered 2020-Nov-19 at 15:40You could pass it as a string literal and have the database implicitly convert it to a UUID:
1CREATE TABLE IF NOT EXISTS DIM_Jour (
2 jour_id uuid NOT NULL,
3 AAAA int,
4 MM int,
5 JJ int,
6 Jour_Semaine int,
7 Num_Semaine int,
8
9 PRIMARY KEY (jour_id)
10);
11INSERT INTO DIM_Jour (jour_id, AAAA, MM, JJ, Jour_Semaine, Num_Semaine) VALUES (
12 292a485f-a56a-4938-8f1a-bbbbbbbbbbb1,
13 2020,
14 11,
15 19,
16 4,
17 47
18);
19ERROR: syntax error at or near "a485f"
20 LINE 3: 292a485f-a56a-4938-8f1a-bbbbbbbbbbb1,
21 ^
22INSERT INTO DIM_Jour (jour_id, AAAA, MM, JJ, Jour_Semaine, Num_Semaine) VALUES (
23 '292a485f-a56a-4938-8f1a-bbbbbbbbbbb1',
24 2020,
25 11,
26 19,
27 4,
28 47
29);
30
But it's probably a good practice to be explicit about it and perform the cast yourself
1CREATE TABLE IF NOT EXISTS DIM_Jour (
2 jour_id uuid NOT NULL,
3 AAAA int,
4 MM int,
5 JJ int,
6 Jour_Semaine int,
7 Num_Semaine int,
8
9 PRIMARY KEY (jour_id)
10);
11INSERT INTO DIM_Jour (jour_id, AAAA, MM, JJ, Jour_Semaine, Num_Semaine) VALUES (
12 292a485f-a56a-4938-8f1a-bbbbbbbbbbb1,
13 2020,
14 11,
15 19,
16 4,
17 47
18);
19ERROR: syntax error at or near "a485f"
20 LINE 3: 292a485f-a56a-4938-8f1a-bbbbbbbbbbb1,
21 ^
22INSERT INTO DIM_Jour (jour_id, AAAA, MM, JJ, Jour_Semaine, Num_Semaine) VALUES (
23 '292a485f-a56a-4938-8f1a-bbbbbbbbbbb1',
24 2020,
25 11,
26 19,
27 4,
28 47
29);
30INSERT INTO DIM_Jour (jour_id, AAAA, MM, JJ, Jour_Semaine, Num_Semaine) VALUES (
31 '292a485f-a56a-4938-8f1a-bbbbbbbbbbb1'::UUID,
32 2020,
33 11,
34 19,
35 4,
36 47
37);
38
Community Discussions contain sources that include Stack Exchange Network
Tutorials and Learning Resources in UUID Generator
Tutorials and Learning Resources are not available at this moment for UUID Generator