@@ -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,22 @@ 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+ abs_percent_change=${percent_change# -* }
255+ test ${abs_percent_change} -le ${SIZE_PERCENTUAL_TRESHOLD} || {
256+ echo " Image size changed by ${abs_percent_change} % (expected: ${expected_img_size} MB; actual: ${actual_img_size} MB; treshold: ${SIZE_PERCENTUAL_TRESHOLD} %)."
257+ return 1
258+ }
259+ # 2. Absolute size change
260+ size_difference=$(( actual_img_size - expected_img_size))
261+ abs_size_difference=${size_difference# -* }
262+ test ${abs_size_difference} -le ${SIZE_ABSOLUTE_TRESHOLD} || {
263+ echo " Image size changed by ${abs_size_difference} MB (expected: ${expected_img_size} MB; actual: ${actual_img_size} MB; treshold: ${SIZE_ABSOLUTE_TRESHOLD} MB)."
264+ return 1
265+ }
220266}
221267
222268function check_image_commit_id_matches_metadata() {
@@ -249,29 +295,29 @@ function check_image() {
249295
250296 echo " Checking metadata for image '${image_variable} ' with URL '${image_url} '"
251297
252- local image_metadata
298+ local image_metadata_config
253299 local image_name
254300 local image_commit_id
255301 local image_commitref
256302 local image_created
257303
258- image_metadata =" $( skopeo inspect --config " docker://${image_url} " ) " || {
259- echo " Couldn't download image metadata with skopeo tool!"
304+ image_metadata_config =" $( skopeo inspect --config " docker://${image_url} " ) " || {
305+ echo " Couldn't download image config metadata with skopeo tool!"
260306 return 1
261307 }
262- image_name=$( echo " ${image_metadata } " | jq --raw-output ' .config.Labels.name' ) || {
308+ image_name=$( echo " ${image_metadata_config } " | jq --raw-output ' .config.Labels.name' ) || {
263309 echo " Couldn't parse '.config.Labels.name' from image metadata!"
264310 return 1
265311 }
266- image_commit_id=$( echo " ${image_metadata } " | jq --raw-output ' .config.Labels."io.openshift.build.commit.id"' ) || {
312+ image_commit_id=$( echo " ${image_metadata_config } " | jq --raw-output ' .config.Labels."io.openshift.build.commit.id"' ) || {
267313 echo " Couldn't parse '.config.Labels." io.openshift.build.commit.id" ' from image metadata!"
268314 return 1
269315 }
270- image_commitref=$( echo " ${image_metadata } " | jq --raw-output ' .config.Labels."io.openshift.build.commit.ref"' ) || {
316+ image_commitref=$( echo " ${image_metadata_config } " | jq --raw-output ' .config.Labels."io.openshift.build.commit.ref"' ) || {
271317 echo " Couldn't parse '.config.Labels." io.openshift.build.commit.ref" ' from image metadata!"
272318 return 1
273319 }
274- image_created=$( echo " ${image_metadata } " | jq --raw-output ' .created' ) || {
320+ image_created=$( echo " ${image_metadata_config } " | jq --raw-output ' .created' ) || {
275321 echo " Couldn't parse '.created' from image metadata!"
276322 return 1
277323 }
@@ -280,7 +326,7 @@ function check_image() {
280326 local build_name_raw
281327 local openshift_build_name
282328
283- config_env=$( echo " ${image_metadata } " | jq --raw-output ' .config.Env' ) || {
329+ config_env=$( echo " ${image_metadata_config } " | jq --raw-output ' .config.Env' ) || {
284330 echo " Couldn't parse '.config.Env' from image metadata!"
285331 return 1
286332 }
@@ -293,15 +339,38 @@ function check_image() {
293339 return 1
294340 }
295341
342+ local image_metadata
343+ local image_size
344+ local image_size_mb
345+
346+ image_metadata=" $( skopeo inspect --raw " docker://${image_url} " ) " || {
347+ echo " Couldn't download image metadata with skopeo tool!"
348+ return 1
349+ }
350+ # Here we get the image size as a compressed image. This differs to what we gather in
351+ # 'tests/containers/base_image_test.py#test_image_size_change' where we check against the extracted image size.
352+ # There is no actual reason to compare these different sizes except that in this case we want to do check the
353+ # image remotely, whereas in the othe test, we have the image present locally on the machine.
354+ image_size=$( echo " ${image_metadata} " | jq ' [ .layers[].size ] | add' ) || {
355+ echo " Couldn't count image size from image metadata!"
356+ return 1
357+ }
358+ image_size_mb=$(( image_size / 1024 / 1024 )) || {
359+ echo " Couldn't count image size from image metadata!"
360+ return 1
361+ }
362+
296363 test -n " ${image_name} " || {
297364 echo " Couldn't retrieve the name of the image - got empty value!"
298365 return 1
299366 }
300367
301368 echo " Image name retrieved: '${image_name} '"
302369 echo " Image created: '${image_created} '"
370+ echo " Image size: ${image_size_mb} MB"
303371
304- check_image_variable_matches_name_and_commitref " ${image_variable} " " ${image_name} " " ${image_commitref} " " ${openshift_build_name} " || return 1
372+ check_image_variable_matches_name_and_commitref_and_size " ${image_variable} " " ${image_name} " " ${image_commitref} " \
373+ " ${openshift_build_name} " " ${image_size_mb} " || return 1
305374
306375 check_image_commit_id_matches_metadata " ${image_variable} " " ${image_commit_id} " || return 1
307376
374443 echo " The '${PARAMS_ENV_PATH} ' file isn't valid, please check above!"
375444fi
376445
377- exit " ${ret_code} "
446+ exit " ${ret_code} "
0 commit comments