@@ -27,6 +27,12 @@ PARAMS_ENV_PATH="manifests/base/params.env"
2727# images we want to have in the `params.env` file.
2828EXPECTED_NUM_RECORDS=21
2929
30+ # Size change tresholds:
31+ # Max percentual change
32+ SIZE_PERCENTUAL_TRESHOLD=10
33+ # Max absolute change in MB
34+ SIZE_ABSOLUTE_TRESHOLD=100
35+
3036# ---------------------------- DEFINED FUNCTIONS ----------------------------- #
3137
3238function check_variables_uniq() {
@@ -80,95 +86,114 @@ function check_variables_uniq() {
8086 return " ${ret_code} "
8187}
8288
83- function check_image_variable_matches_name_and_commitref () {
89+ function check_image_variable_matches_name_and_commitref_and_size () {
8490 local image_variable=" ${1} "
8591 local image_name=" ${2} "
8692 local image_commitref=" ${3} "
8793 local openshift_build_name=" ${4} "
94+ local actual_img_size=" ${5} "
8895
8996 local expected_name
9097 local expected_commitref
91- local expected_build_name # Why some of the images has `-amd64` suffix and others not?
98+ local expected_build_name
99+ local expected_img_size
100+
92101 case " ${image_variable} " in
93102 odh-minimal-notebook-image-n)
94103 expected_name=" odh-notebook-jupyter-minimal-ubi9-python-3.11"
95104 expected_commitref=" 2024b"
96105 expected_build_name=" jupyter-minimal-ubi9-python-3.11-amd64"
106+ expected_img_size=520
97107 ;;
98108 odh-minimal-notebook-image-n-1)
99109 expected_name=" odh-notebook-jupyter-minimal-ubi9-python-3.9"
100110 expected_commitref=" 2024a"
101111 expected_build_name=" jupyter-minimal-ubi9-python-3.9-amd64"
112+ expected_img_size=503
102113 ;;
103114 odh-minimal-gpu-notebook-image-n)
104115 expected_name=" odh-notebook-jupyter-minimal-ubi9-python-3.11"
105116 expected_commitref=" 2024b"
106117 expected_build_name=" cuda-jupyter-minimal-ubi9-python-3.11-amd64"
118+ expected_img_size=5157
107119 ;;
108120 odh-minimal-gpu-notebook-image-n-1)
109121 expected_name=" odh-notebook-jupyter-minimal-ubi9-python-3.9"
110122 expected_commitref=" 2024a"
111123 expected_build_name=" cuda-jupyter-minimal-ubi9-python-3.9-amd64"
124+ expected_img_size=5718
112125 ;;
113126 odh-pytorch-gpu-notebook-image-n)
114127 expected_name=" odh-notebook-jupyter-pytorch-ubi9-python-3.11"
115128 expected_commitref=" 2024b"
116129 expected_build_name=" jupyter-pytorch-ubi9-python-3.11-amd64"
130+ expected_img_size=8571
117131 ;;
118132 odh-pytorch-gpu-notebook-image-n-1)
119133 expected_name=" odh-notebook-jupyter-pytorch-ubi9-python-3.9"
120134 expected_commitref=" 2024a"
121135 expected_build_name=" jupyter-pytorch-ubi9-python-3.9-amd64"
136+ expected_img_size=9037
122137 ;;
123138 odh-generic-data-science-notebook-image-n)
124139 expected_name=" odh-notebook-jupyter-datascience-ubi9-python-3.11"
125140 expected_commitref=" 2024b"
126141 expected_build_name=" jupyter-datascience-ubi9-python-3.11-amd64"
142+ expected_img_size=961
127143 ;;
128144 odh-generic-data-science-notebook-image-n-1)
129145 expected_name=" odh-notebook-jupyter-datascience-ubi9-python-3.9"
130146 expected_commitref=" 2024a"
131147 expected_build_name=" jupyter-datascience-ubi9-python-3.9-amd64"
148+ expected_img_size=904
132149 ;;
133150 odh-tensorflow-gpu-notebook-image-n)
134151 expected_name=" odh-notebook-cuda-jupyter-tensorflow-ubi9-python-3.11"
135152 expected_commitref=" 2024b"
136153 expected_build_name=" cuda-jupyter-tensorflow-ubi9-python-3.11-amd64"
154+ expected_img_size=8211
137155 ;;
138156 odh-tensorflow-gpu-notebook-image-n-1)
139157 expected_name=" odh-notebook-cuda-jupyter-tensorflow-ubi9-python-3.9"
140158 expected_commitref=" 2024a"
141159 expected_build_name=" cuda-jupyter-tensorflow-ubi9-python-3.9-amd64"
160+ expected_img_size=6667
142161 ;;
143162 odh-trustyai-notebook-image-n)
144163 expected_name=" odh-notebook-jupyter-trustyai-ubi9-python-3.11"
145164 expected_commitref=" 2024b"
146165 expected_build_name=" jupyter-trustyai-ubi9-python-3.11-amd64"
166+ expected_img_size=4197
147167 ;;
148168 odh-trustyai-notebook-image-n-1)
149169 expected_name=" odh-notebook-jupyter-trustyai-ubi9-python-3.9"
150170 expected_commitref=" 2024a"
151171 expected_build_name=" jupyter-trustyai-ubi9-python-3.9-amd64"
172+ expected_img_size=1158
152173 ;;
153174 odh-codeserver-notebook-image-n)
154175 expected_name=" odh-notebook-code-server-ubi9-python-3.11"
155176 expected_commitref=" 2024b"
156177 expected_build_name=" codeserver-ubi9-python-3.11-amd64"
178+ expected_img_size=893
157179 ;;
158180 odh-codeserver-notebook-image-n-1)
159181 expected_name=" odh-notebook-code-server-ubi9-python-3.9"
160182 expected_commitref=" 2024a"
161183 expected_build_name=" codeserver-ubi9-python-3.9-amd64"
184+ expected_img_size=850
162185 ;;
163186 odh-rstudio-notebook-image-n)
164187 expected_name=" odh-notebook-rstudio-server-c9s-python-3.11"
165188 expected_commitref=" 2024b"
166189 expected_build_name=" rstudio-c9s-python-3.11-amd64"
190+ expected_img_size=1242
167191 ;;
168192 odh-rstudio-notebook-image-n-1)
169193 expected_name=" odh-notebook-rstudio-server-c9s-python-3.9"
170194 expected_commitref=" 2024a"
171195 expected_build_name=" rstudio-c9s-python-3.9-amd64"
196+ expected_img_size=1208
172197 ;;
173198 # For both RStudio GPU workbenches - the final name labels are identical to plain RStudio ones
174199 # This is because the very same RStudio Dockerfile is used but different base images in both cases
@@ -177,26 +202,31 @@ function check_image_variable_matches_name_and_commitref() {
177202 expected_name=" odh-notebook-rstudio-server-c9s-python-3.11"
178203 expected_commitref=" 2024b"
179204 expected_build_name=" cuda-rstudio-c9s-python-3.11-amd64"
205+ expected_img_size=7184
180206 ;;
181207 odh-rstudio-gpu-notebook-image-n-1)
182208 expected_name=" odh-notebook-rstudio-server-c9s-python-3.9"
183209 expected_commitref=" 2024a"
184210 expected_build_name=" cuda-rstudio-c9s-python-3.9-amd64"
211+ expected_img_size=7129
185212 ;;
186213 odh-rocm-minimal-notebook-image-n)
187214 expected_name=" odh-notebook-jupyter-minimal-ubi9-python-3.11"
188215 expected_commitref=" 2024b"
189216 expected_build_name=" rocm-jupyter-minimal-ubi9-python-3.11-amd64"
217+ expected_img_size=4830
190218 ;;
191219 odh-rocm-pytorch-notebook-image-n)
192220 expected_name=" odh-notebook-jupyter-rocm-pytorch-ubi9-python-3.11"
193221 expected_commitref=" 2024b"
194222 expected_build_name=" rocm-jupyter-pytorch-ubi9-python-3.11-amd64"
223+ expected_img_size=6571
195224 ;;
196225 odh-rocm-tensorflow-notebook-image-n)
197226 expected_name=" odh-notebook-jupyter-rocm-tensorflow-ubi9-python-3.11"
198227 expected_commitref=" 2024b"
199228 expected_build_name=" rocm-jupyter-tensorflow-ubi9-python-3.11-amd64"
229+ expected_img_size=5782
200230 ;;
201231 * )
202232 echo " Unimplemented variable name: '${image_variable} '"
@@ -217,6 +247,20 @@ function check_image_variable_matches_name_and_commitref() {
217247 echo " Image URL points to an incorrect image: expected OPENSHIFT_BUILD_NAME '${expected_build_name} '; actual '${openshift_build_name} '"
218248 return 1
219249 }
250+
251+ # Check the size change constraints now
252+ # 1. Percentual size change
253+ percent_change=$(( 100 * actual_img_size / expected_img_size - 100 ))
254+ test ${percent_change} -le ${SIZE_PERCENTUAL_TRESHOLD} || {
255+ echo " Image size changed by ${percent_change} % (expected: ${expected_img_size} MB; actual: ${actual_img_size} MB; treshold: ${SIZE_PERCENTUAL_TRESHOLD} %)."
256+ return 1
257+ }
258+ # 2. Absolute size change
259+ size_difference=$(( actual_img_size - expected_img_size))
260+ test ${size_difference} -le ${SIZE_ABSOLUTE_TRESHOLD} || {
261+ echo " Image size changed by ${size_difference} MB (expected: ${expected_img_size} MB; actual: ${actual_img_size} MB; treshold: ${SIZE_ABSOLUTE_TRESHOLD} MB)."
262+ return 1
263+ }
220264}
221265
222266function check_image_commit_id_matches_metadata() {
@@ -249,29 +293,29 @@ function check_image() {
249293
250294 echo " Checking metadata for image '${image_variable} ' with URL '${image_url} '"
251295
252- local image_metadata
296+ local image_metadata_config
253297 local image_name
254298 local image_commit_id
255299 local image_commitref
256300 local image_created
257301
258- image_metadata =" $( skopeo inspect --config " docker://${image_url} " ) " || {
259- echo " Couldn't download image metadata with skopeo tool!"
302+ image_metadata_config =" $( skopeo inspect --config " docker://${image_url} " ) " || {
303+ echo " Couldn't download image config metadata with skopeo tool!"
260304 return 1
261305 }
262- image_name=$( echo " ${image_metadata } " | jq --raw-output ' .config.Labels.name' ) || {
306+ image_name=$( echo " ${image_metadata_config } " | jq --raw-output ' .config.Labels.name' ) || {
263307 echo " Couldn't parse '.config.Labels.name' from image metadata!"
264308 return 1
265309 }
266- image_commit_id=$( echo " ${image_metadata } " | jq --raw-output ' .config.Labels."io.openshift.build.commit.id"' ) || {
310+ image_commit_id=$( echo " ${image_metadata_config } " | jq --raw-output ' .config.Labels."io.openshift.build.commit.id"' ) || {
267311 echo " Couldn't parse '.config.Labels." io.openshift.build.commit.id" ' from image metadata!"
268312 return 1
269313 }
270- image_commitref=$( echo " ${image_metadata } " | jq --raw-output ' .config.Labels."io.openshift.build.commit.ref"' ) || {
314+ image_commitref=$( echo " ${image_metadata_config } " | jq --raw-output ' .config.Labels."io.openshift.build.commit.ref"' ) || {
271315 echo " Couldn't parse '.config.Labels." io.openshift.build.commit.ref" ' from image metadata!"
272316 return 1
273317 }
274- image_created=$( echo " ${image_metadata } " | jq --raw-output ' .created' ) || {
318+ image_created=$( echo " ${image_metadata_config } " | jq --raw-output ' .created' ) || {
275319 echo " Couldn't parse '.created' from image metadata!"
276320 return 1
277321 }
@@ -280,7 +324,7 @@ function check_image() {
280324 local build_name_raw
281325 local openshift_build_name
282326
283- config_env=$( echo " ${image_metadata } " | jq --raw-output ' .config.Env' ) || {
327+ config_env=$( echo " ${image_metadata_config } " | jq --raw-output ' .config.Env' ) || {
284328 echo " Couldn't parse '.config.Env' from image metadata!"
285329 return 1
286330 }
@@ -293,15 +337,38 @@ function check_image() {
293337 return 1
294338 }
295339
340+ local image_metadata
341+ local image_size
342+ local image_size_mb
343+
344+ image_metadata=" $( skopeo inspect --raw " docker://${image_url} " ) " || {
345+ echo " Couldn't download image metadata with skopeo tool!"
346+ return 1
347+ }
348+ # Here we get the image size as a compressed image. This differs to what we gather in
349+ # 'tests/containers/base_image_test.py#test_image_size_change' where we check against the extracted image size.
350+ # There is no actual reason to compare these different sizes except that in this case we want to do check the
351+ # image remotely, whereas in the othe test, we have the image present locally on the machine.
352+ image_size=$( echo " ${image_metadata} " | jq ' [ .layers[].size ] | add' ) || {
353+ echo " Couldn't count image size from image metadata!"
354+ return 1
355+ }
356+ image_size_mb=$(( image_size / 1024 / 1024 )) || {
357+ echo " Couldn't count image size from image metadata!"
358+ return 1
359+ }
360+
296361 test -n " ${image_name} " || {
297362 echo " Couldn't retrieve the name of the image - got empty value!"
298363 return 1
299364 }
300365
301366 echo " Image name retrieved: '${image_name} '"
302367 echo " Image created: '${image_created} '"
368+ echo " Image size: ${image_size_mb} MB"
303369
304- check_image_variable_matches_name_and_commitref " ${image_variable} " " ${image_name} " " ${image_commitref} " " ${openshift_build_name} " || return 1
370+ check_image_variable_matches_name_and_commitref_and_size " ${image_variable} " " ${image_name} " " ${image_commitref} " \
371+ " ${openshift_build_name} " " ${image_size_mb} " || return 1
305372
306373 check_image_commit_id_matches_metadata " ${image_variable} " " ${image_commit_id} " || return 1
307374
374441 echo " The '${PARAMS_ENV_PATH} ' file isn't valid, please check above!"
375442fi
376443
377- exit " ${ret_code} "
444+ exit " ${ret_code} "
0 commit comments