-
Notifications
You must be signed in to change notification settings - Fork 5
/
entrypoint.sh
executable file
·208 lines (166 loc) · 6.42 KB
/
entrypoint.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
#!/bin/bash
#get our container ID, used if we add this container to networks to try and connect to labeled containers
containerID=$(basename $(cat /proc/1/cpuset))
if [ $containerID = "/" ]
then
containerID=$(cat /etc/hostname)
fi
echo "$(date -u +'%Y-%m-%dT%H:%M:%SZ') SUBWAY Container ID ${containerID}"
#lower case it!
SERVICES="${SERVICES,,}"
#figure out our services (default if not set is just cloudflare!)
if [[ "$SERVICES" == *"caddy"* ]]
then
caddy=1
echo "$(date -u +'%Y-%m-%dT%H:%M:%SZ') SUBWAY setting up service: caddy"
. ./services/caddy.sh
fi
if [[ "$SERVICES" == *"cloudflare"* || -z "$SERVICES" ]]
then
cloudflare=1
echo "$(date -u +'%Y-%m-%dT%H:%M:%SZ') SUBWAY setting up service: cloudflare"
. ./services/cloudflare.sh
fi
##call this like hostname=test.example.com service=10.0.0.x:80 addContainer
#will add the container the appropriate service
addContainer() {
[[ -n $cloudflare ]] && hostname=$hostname service=$service cloudflaredAddContainer
[[ -n $caddy ]] && hostname=$hostname service=$service caddyAddContainer
}
##call this like hostname=test.example.com removeContainer
#will add the container from the appropriate service
removeContainer() {
[[ -n $cloudflare ]] && hostname=$hostname cloudflaredRemoveContainer
[[ -n $caddy ]] && hostname=$hostname service=$service caddyRemoveContainer
}
#will start/restart our services on initial load and on changes being detected!
restartServices() {
[[ -n $cloudflare ]] && cloudflaredRestart
[[ -n $caddy ]] && caddyRestart
}
##call this like action=start|stop id=containerID checkContainer
#Get the container config, and if we have labels for subway
checkContainer() {
#fetch docker config in json
inspect=`docker inspect $id`
#get the hostname and config from our labels from the container!
read hostname name network ports labels< <(echo $(echo ${inspect} | jq --raw-output '.[0] | .Name as $name | .NetworkSettings as $network | .Config.ExposedPorts as $ports | .Config.Labels | . as $labels | to_entries[] | select(.key == "subway.hostname") | "\(.value) \($name) \($network) \($ports) \($labels)"') | sed -r 's/\\"/\\\\"/g')
if [[ $hostname ]]
then
echo "$(date -u +'%Y-%m-%dT%H:%M:%SZ') SUBWAY Container ${name:1} found with status ${action} and subway.hostname ${hostname}..."
#if we are stopping we can just check if it exists and delete it if it does!
if [ $action = "stop" ]
then
hostname=$hostname removeContainer
return 1
fi
port=''
#loop through the labels, getting ones start with subway. and not subway.hostname!
while read -r key value; do
#port is special, grab it out!
if [ $key == 'subway.port' ]
then
port=$value
fi
#Todo grab other labels, and store them to allow additional configuration!
done< <(echo ${labels} | jq --raw-output 'to_entries[] | select(.key != "subway.hostname") | select(.key | contains("subway.")) | "\(.key) \(.value)"' )
#if we did not find a port, see if it only has one exposed in docker, if so use that, otherwise ignore!
if [[ ! $port ]]
then
if [[ $(echo ${ports} | jq length) -eq "1" ]]
then
#Container has a single port, we can use it!
portString=$(echo ${ports} | jq --raw-output 'to_entries[0] | .key')
#gets the port up to the / format is 8080/tcp so this drops the /tcp
port=${portString%/*}
echo " - subway.port not specified, using single port container exposes: ${port}"
else
echo " - subway.port not specified, multiple ports exposed on container, specify the port using the label subway.port, ignorning"
return 0
fi
else
echo " - subway.port specified: ${port}"
fi
service="" #set up our scopped variable!
if [[ $port != '' ]]
then
network=$network checkContainerAccess
if [[ $service == "" && $CONNECT_NETWORKS ]]
then
#it was empty, but we are allowed to connect networks
echo " - Failed to connect, connecting to container networks and trying again"
while read -r netID; do
echo " - Connecting to network ${netID}"
docker network connect $netID $containerID
done< <(echo ${network} | jq --raw-output '.Networks | .[].NetworkID' )
#try again
network=$network checkContainerAccess
fi
fi
#if we connected, we can then setup a tunnel for it, so add it to the hostnames!
if [[ $service != "" ]]
then
hostname=$hostname service=$service addContainer
return 1
else
echo " - Failed to connect, ignoring"
fi
fi
return 0
}
##call this like network={docker json network spec} checkContainerAccess
#Will try and access the container via any of the networks and if successfull return the service url
checkContainerAccess() {
#get each of the networks IP's and see if we can connect to any of them via the port!
while read -r ip; do
echo -n " - Checking connection to ${ip}:${port}."
#loop and sleep to see if it comes up, important since the container could have just started so services might not be ready in time!
counter=0
while [ $counter -lt 10 ]; do
#check and wait 2 seconds for a response, store response or error
result=`nc -zvw2 ${ip} ${port} 2>&1`
#if we got a zero exit, we found it, stop!
if [ $? == 0 ]
then
break
fi
#sleep and try again!
echo -n "."
sleep 1
counter=$((counter+1))
done
#echo our last result, it will be success or fail!
echo " ${result}"
#if counter is not 10, we found it!
if [ $counter != 10 ]
then
#todo fix this to figure out http or https properly!
service="http://${ip}:${port}"
return
fi
done< <(echo ${network} | jq --raw-output '.Networks | .[].IPAddress' )
}
echo "$(date -u +'%Y-%m-%dT%H:%M:%SZ') SUBWAY Checking existing containers..."
#Get all currently running container IDs
docker ps -q | while read line ; do
#$line is now the container ID
#call the update routine to add it (incase it's missed)
action="start" id=$line checkContainer
done
#Restart them as we have changed now
restartServices
echo "$(date -u +'%Y-%m-%dT%H:%M:%SZ') SUBWAY Watching for container events... $(date)"
docker events --filter 'event=start' --filter 'event=stop' --format '{{json .}}' | while read event
do
#grab the ID and status from the event json
containerID=`echo $event | jq -r '.id'`
status=`echo $event | jq -r '.status'`
#Check the container for labels
action=$status id=$containerID checkContainer
valResult=$? # '$?' is the return value of the previous command
#if we had a change made, restarted cloudflared
if [[ $valResult -eq 1 ]]
then
restartServices
fi
done