1717package org .springframework .cloud .kubernetes .integration .tests .commons ;
1818
1919import java .io .File ;
20- import java .io .IOException ;
2120import java .io .InputStream ;
22- import java .io .UncheckedIOException ;
2321import java .nio .charset .StandardCharsets ;
24- import java .nio .file .Files ;
25- import java .nio .file .Path ;
2622import java .nio .file .Paths ;
27- import java .nio .file .StandardCopyOption ;
2823import java .time .Duration ;
2924import java .util .Arrays ;
3025import java .util .List ;
3328
3429import com .github .dockerjava .api .command .ListImagesCmd ;
3530import com .github .dockerjava .api .command .PullImageCmd ;
36- import com .github .dockerjava .api .command .SaveImageCmd ;
3731import com .github .dockerjava .api .model .Image ;
3832import org .apache .commons .logging .Log ;
3933import org .apache .commons .logging .LogFactory ;
5044import org .springframework .web .reactive .function .client .WebClient ;
5145
5246import static org .springframework .cloud .kubernetes .integration .tests .commons .Constants .KUBERNETES_VERSION_FILE ;
53- import static org .springframework .cloud .kubernetes .integration .tests .commons .Constants .TEMP_FOLDER ;
5447import static org .springframework .cloud .kubernetes .integration .tests .commons .Constants .TMP_IMAGES ;
5548import static org .springframework .cloud .kubernetes .integration .tests .commons .FixedPortsK3sContainer .CONTAINER ;
49+ import static org .springframework .cloud .kubernetes .integration .tests .commons .FixedPortsK3sContainer .REGISTRY_PORT ;
5650
5751/**
5852 * A few commons things that can be re-used across clients. This is meant to be used for
@@ -78,66 +72,64 @@ public static K3sContainer container() {
7872 return CONTAINER ;
7973 }
8074
81- public static void loadSpringCloudKubernetesImage (String project , K3sContainer container ) {
75+ public static void tagAndPushSpringCloudKubernetesImage (String imageName , K3sContainer container ) {
8276 try {
83- loadImage ("springcloud/" + project , pomVersion (), project , container );
77+ String springCloudImage = "springcloud/" + imageName + ":" + pomVersion ();
78+ tagAndPushImage (springCloudImage , container );
8479 }
8580 catch (Exception e ) {
8681 throw new RuntimeException (e );
8782 }
8883 }
8984
9085 /**
91- * create a tar, copy it in the running k3s and load this tar as an image .
86+ * tag image and push to local registry .
9287 */
93- public static void loadImage (String image , String tag , String tarName , K3sContainer container ) {
88+ public static void tagAndPushImage (String imageFromDeploymentWithTag , K3sContainer container ) {
9489
95- if (imageAlreadyInK3s (container , tarName )) {
90+ if (imageAlreadyInK3s (container , imageFromDeploymentWithTag )) {
9691 return ;
9792 }
9893
99- // save image
100- try (SaveImageCmd saveImageCmd = container .getDockerClient ().saveImageCmd (image )) {
101- InputStream imageStream = saveImageCmd .withTag (tag ).exec ();
102-
103- Path imagePath = Paths .get (TEMP_FOLDER + "/" + tarName + ".tar" );
104- try {
105- Files .copy (imageStream , imagePath , StandardCopyOption .REPLACE_EXISTING );
106- }
107- catch (IOException e ) {
108- throw new UncheckedIOException (e );
94+ try {
95+ int lastColon = imageFromDeploymentWithTag .lastIndexOf (':' );
96+ if (lastColon < 0 ) {
97+ throw new IllegalArgumentException ("image must include tag: " + imageFromDeploymentWithTag );
10998 }
110- // import image with ctr. this works because TEMP_FOLDER is mounted in the
111- // container
99+
100+ String imageWithoutTag = imageFromDeploymentWithTag .substring (0 , lastColon );
101+ String tag = imageFromDeploymentWithTag .substring (lastColon + 1 );
102+
103+ String targetRepository = "localhost:" + REGISTRY_PORT + "/" + imageWithoutTag ;
104+ String targetImageWithTag = targetRepository + ":" + tag ;
105+
106+ container .getDockerClient ().tagImageCmd (imageFromDeploymentWithTag , targetRepository , tag ).exec ();
107+
112108 Awaitilities .awaitUntil (120 , 1000 , () -> {
113- Container .ExecResult result ;
114109 try {
115- result = container .execInContainer ( "ctr" , "i" , "import" ,
116- Constants . TEMP_FOLDER + "/" + tarName + ".tar" ) ;
110+ container .getDockerClient (). pushImageCmd ( targetImageWithTag ). start (). awaitCompletion ();
111+ return true ;
117112 }
118113 catch (Exception e ) {
119- throw new RuntimeException (e );
114+ LOG .info ("failed to push image " + targetImageWithTag + " to local registry" , e );
115+ return false ;
120116 }
121- boolean noErrors = result .getStderr () == null || result .getStderr ().isEmpty ();
122- if (!noErrors ) {
123- LOG .info ("error is : " + result .getStderr ());
124- }
125- return noErrors ;
126117 });
127118 }
128-
119+ catch (Exception e ) {
120+ throw new RuntimeException (e );
121+ }
129122 }
130123
131124 /**
132- * Ensures a common external test image is available inside K3s/containerd.
133- * It first checks whether the image is already present in K3s.
134- * If not, it tries to load it as a tar under '/tmp/docker/images'.
135- * If no matching tar is found, it pulls the image directly inside K3s
136- * using 'ctr images pull'.
137- * This is meant for shared test images such as busybox, wiremock, kafka, etc.
125+ * Ensures a common external test image is available inside K3s/containerd. It first
126+ * checks whether the image is already present in K3s. If not, it tries to load it as
127+ * a tar under '/tmp/docker/images'. If no matching tar is found, it pulls the image
128+ * directly inside K3s using 'ctr images pull'. This is meant for shared test images
129+ * such as busybox, wiremock, kafka, etc.
138130 */
139- public static void loadOrPullCommonTestImages (K3sContainer container , String tarName ,
140- String imageNameForDownload , String imageVersion ) {
131+ public static void loadOrPullCommonTestImages (K3sContainer container , String tarName , String imageNameForDownload ,
132+ String imageVersion ) {
141133
142134 if (imageAlreadyInK3s (container , tarName )) {
143135 return ;
@@ -239,15 +231,14 @@ public static void validateImage(String image, K3sContainer container) {
239231 }
240232 }
241233
242- public static void pullImage (String image , String tag , String tarName , K3sContainer container )
243- throws InterruptedException {
234+ public static void pullImage (String imageFromDeployment , K3sContainer container ) throws InterruptedException {
244235
245- if (imageAlreadyInK3s (container , tarName )) {
236+ if (imageAlreadyInK3s (container , imageFromDeployment )) {
246237 return ;
247238 }
248239
249- try (PullImageCmd pullImageCmd = container .getDockerClient ().pullImageCmd (image )) {
250- pullImageCmd .withTag ( tag ). start ().awaitCompletion ();
240+ try (PullImageCmd pullImageCmd = container .getDockerClient ().pullImageCmd (imageFromDeployment )) {
241+ pullImageCmd .start ().awaitCompletion ();
251242 }
252243 }
253244
@@ -324,24 +315,19 @@ private static void loadImageFromPath(String tarName, K3sContainer container) {
324315 });
325316 }
326317
327- private static boolean imageAlreadyInK3s (K3sContainer container , String tarName ) {
318+ private static boolean imageAlreadyInK3s (K3sContainer container , String imageWithTag ) {
319+ try {
320+ String stdout = container .execInContainer ("ctr" , "-n" , "k8s.io" , "images" , "list" , "-q" ).getStdout ();
328321
329- if (tarName == null ) {
330- return false ;
331- }
322+ boolean present = Arrays .stream (stdout .split ("\\ R" )).map (String ::trim ).anyMatch (imageWithTag ::equals );
332323
333- try {
334- boolean present = container .execInContainer ("sh" , "-c" , "ctr images list | grep " + tarName )
335- .getStdout ()
336- .contains (tarName );
337324 if (present ) {
338- System .out .println ("image : " + tarName + " already in k3s, skipping" );
325+ System .out .println ("image : " + imageWithTag + " already in k3s, skipping" );
339326 return true ;
340327 }
341- else {
342- System .out .println ("image : " + tarName + " not in k3s" );
343- return false ;
344- }
328+
329+ System .out .println ("image : " + imageWithTag + " not in k3s" );
330+ return false ;
345331 }
346332 catch (Exception e ) {
347333 throw new RuntimeException (e );
0 commit comments