1
+ #! /bin/bash
2
+
3
+ # Color codes
4
+ RED=' \033[0;31m'
5
+ GREEN=' \033[0;32m'
6
+ YELLOW=' \033[0;33m'
7
+ BLUE=' \033[0;34m'
8
+ NC=' \033[0m' # No Color
9
+
10
+ # Logging function
11
+ log () {
12
+ local color=$1
13
+ local message=$2
14
+ echo -e " ${color}${message}${NC} "
15
+ }
16
+
17
+ # Default configuration options
18
+ DOCKER_IMAGE=" ${DOCKER_IMAGE:- tungbq/ devops-toolkit: latest} "
19
+ CONFIG_MOUNT_PATH=" ${CONFIG_MOUNT_PATH:- $HOME / .dtc} "
20
+ CONTAINER_NAME=" ${CONTAINER_NAME:- devops_toolkit} "
21
+ CONTAINER_SHELL=" ${CONTAINER_SHELL:-/ bin/ bash} "
22
+ RUN_MODE=" ${RUN_MODE:- run} "
23
+ NETWORK=" ${NETWORK:- --net=host} "
24
+
25
+ if [ -z " $CONTAINER_NAME " ]; then
26
+ log $RED " No CONTAINER_NAME provided"
27
+ exit 1
28
+ fi
29
+
30
+ # Function to check if local image is up-to-date with DockerHub
31
+ is_image_up_to_date () {
32
+ local image=" $1 "
33
+ local repo=" ${image%:* } "
34
+ local tag=" ${image#*: } "
35
+
36
+ local local_digest=$( docker image inspect --format=' {{index .RepoDigests 0}}' " $image " 2> /dev/null | cut -d' @' -f2)
37
+ local remote_digest=$( docker pull -q " $image " > /dev/null 2>&1 && docker image inspect --format=' {{index .RepoDigests 0}}' " $image " | cut -d' @' -f2)
38
+
39
+ [ " $local_digest " = " $remote_digest " ]
40
+ }
41
+
42
+ pull_image () {
43
+ local image=" $1 "
44
+
45
+ if [[ " $image " != " sha256:" * ]]; then
46
+ if docker image inspect " $image " > /dev/null 2>&1 ; then
47
+ if is_image_up_to_date " $image " ; then
48
+ log $YELLOW " Image $image is up-to-date. Skipping pull."
49
+ else
50
+ log $BLUE " Local image $image is outdated. Pulling latest version..."
51
+ docker pull " $image " || { log $RED " Failed to pull image $image " ; exit 1; }
52
+ fi
53
+ else
54
+ log $BLUE " Pulling image $image ..."
55
+ docker pull " $image " || { log $RED " Failed to pull image $image " ; exit 1; }
56
+ fi
57
+ fi
58
+ }
59
+
60
+ start_container () {
61
+ local image=" $1 "
62
+ if ! docker inspect --type=container " $CONTAINER_NAME " > /dev/null 2>&1 ; then
63
+ log $BLUE " Starting new container with image $image ..."
64
+ docker run -d --name " $CONTAINER_NAME " \
65
+ --volume " $PWD :$PWD " \
66
+ --volume " $CONFIG_MOUNT_PATH :/dtc" \
67
+ --volume " $HOME /.ssh:/root/.ssh" \
68
+ --workdir " $PWD " \
69
+ --init \
70
+ --entrypoint tail \
71
+ $NETWORK \
72
+ $DOCKER_ARGS \
73
+ " $image " -f /dev/null > /dev/null || { log $RED " Failed to start container" ; exit 1; }
74
+ log $GREEN " Container started successfully"
75
+ else
76
+ log $YELLOW " Container $CONTAINER_NAME already exists"
77
+ fi
78
+ }
79
+
80
+ exec_in_container () {
81
+ local command=" $1 "
82
+
83
+ local RUN_CMD=$CONTAINER_SHELL
84
+
85
+ if [ -n " $command " ]; then
86
+ RUN_CMD+=" -c $command "
87
+ fi
88
+
89
+ log $BLUE " Executing command in container $CONTAINER_NAME ..."
90
+ docker exec -it " $CONTAINER_NAME " $RUN_CMD || {
91
+ log $RED " Failed to execute command in container $CONTAINER_NAME " ; exit 1;
92
+ }
93
+ }
94
+
95
+ cleanup () {
96
+ log $BLUE " Cleaning up..."
97
+ if docker inspect --type=container " $CONTAINER_NAME " > /dev/null 2>&1 ; then
98
+ docker stop " $CONTAINER_NAME " > /dev/null
99
+ docker rm " $CONTAINER_NAME " > /dev/null
100
+ log $GREEN " Container $CONTAINER_NAME has been removed."
101
+ else
102
+ log $YELLOW " Container $CONTAINER_NAME does not exist."
103
+ fi
104
+ }
105
+
106
+ update () {
107
+ local version=" $1 "
108
+ local new_image
109
+
110
+ if [ -z " $version " ]; then
111
+ new_image=" ${DOCKER_IMAGE%:* } :latest"
112
+ log $BLUE " Updating to the latest version..."
113
+ else
114
+ new_image=" ${DOCKER_IMAGE%:* } :$version "
115
+ log $BLUE " Updating to version $version ..."
116
+ fi
117
+
118
+ if [ " $new_image " == " $DOCKER_IMAGE " ]; then
119
+ if is_image_up_to_date " $new_image " ; then
120
+ log $YELLOW " The specified image ($new_image ) is already in use and up-to-date. No update needed."
121
+ return
122
+ else
123
+ log $BLUE " The specified image ($new_image ) is in use but outdated. Updating..."
124
+ fi
125
+ fi
126
+
127
+ pull_image " $new_image "
128
+ cleanup
129
+ DOCKER_IMAGE=" $new_image "
130
+ start_container " $DOCKER_IMAGE "
131
+ log $GREEN " Update completed successfully. New image: $DOCKER_IMAGE "
132
+ }
133
+
134
+ version () {
135
+ log $BLUE " DevOps Toolkit Version Information:"
136
+ log $GREEN " Current Docker Image: $DOCKER_IMAGE "
137
+ if docker inspect --type=container " $CONTAINER_NAME " > /dev/null 2>&1 ; then
138
+ local container_image=$( docker inspect --format=' {{.Config.Image}}' " $CONTAINER_NAME " )
139
+ log $GREEN " Running Container Image: $container_image "
140
+ else
141
+ log $YELLOW " No running container found."
142
+ fi
143
+ }
144
+
145
+ list_versions () {
146
+ log $BLUE " Available versions of DevOps Toolkit:"
147
+ local repo=" ${DOCKER_IMAGE%:* } "
148
+ curl -s " https://registry.hub.docker.com/v2/repositories/${repo} /tags?page_size=100" | \
149
+ jq -r ' .results[].name' | sort -V
150
+ }
151
+
152
+ health_check () {
153
+ if docker inspect --type=container " $CONTAINER_NAME " > /dev/null 2>&1 ; then
154
+ local status=$( docker inspect --format=' {{.State.Status}}' " $CONTAINER_NAME " )
155
+ local health=$( docker inspect --format=' {{.State.Health.Status}}' " $CONTAINER_NAME " )
156
+ log $GREEN " Container Status: $status "
157
+ log $GREEN " Container Health: ${health:- N/ A} "
158
+ else
159
+ log $RED " Container $CONTAINER_NAME does not exist."
160
+ fi
161
+ }
162
+
163
+ show_logs () {
164
+ if docker inspect --type=container " $CONTAINER_NAME " > /dev/null 2>&1 ; then
165
+ docker logs " $CONTAINER_NAME "
166
+ else
167
+ log $RED " Container $CONTAINER_NAME does not exist."
168
+ fi
169
+ }
170
+
171
+ shell_access () {
172
+ if docker inspect --type=container " $CONTAINER_NAME " > /dev/null 2>&1 ; then
173
+ log $BLUE " Accessing shell in container $CONTAINER_NAME ..."
174
+ docker exec -it " $CONTAINER_NAME " $CONTAINER_SHELL
175
+ else
176
+ log $RED " Container $CONTAINER_NAME does not exist."
177
+ fi
178
+ }
179
+
180
+ usage () {
181
+ log $BLUE " Usage: $0 [command] [options]"
182
+ echo " Commands:"
183
+ echo " run [command]: Start a new container and run a command"
184
+ echo " exec [command]: Execute a command in an existing container"
185
+ echo " cleanup: Remove the container"
186
+ echo " update [version]: Update the container image. If version is omitted, updates to latest."
187
+ echo " version: Display version information"
188
+ echo " list-versions: List available versions of the DevOps toolkit"
189
+ echo " health: Perform a health check on the running container"
190
+ echo " logs: View the logs of the running container"
191
+ echo " shell: Get a shell inside the running container"
192
+ }
193
+
194
+ case " $1 " in
195
+ run)
196
+ RUN_MODE=" run"
197
+ shift
198
+ log $BLUE " Running in 'run' mode..."
199
+ pull_image " $DOCKER_IMAGE "
200
+ start_container " $DOCKER_IMAGE "
201
+ exec_in_container " $@ "
202
+ ;;
203
+ exec)
204
+ RUN_MODE=" exec"
205
+ shift
206
+ log $BLUE " Running in 'exec' mode..."
207
+ exec_in_container " $@ "
208
+ ;;
209
+ cleanup)
210
+ cleanup
211
+ ;;
212
+ update)
213
+ shift
214
+ update " $1 "
215
+ ;;
216
+ version)
217
+ version
218
+ ;;
219
+ list-versions)
220
+ list_versions
221
+ ;;
222
+ health)
223
+ health_check
224
+ ;;
225
+ logs)
226
+ show_logs
227
+ ;;
228
+ shell)
229
+ shell_access
230
+ ;;
231
+ help)
232
+ usage
233
+ exit 0
234
+ ;;
235
+ * )
236
+ log $RED " Invalid command: $1 "
237
+ usage
238
+ exit 1
239
+ ;;
240
+ esac
0 commit comments