@@ -7,30 +7,38 @@ import com.cosmotech.api.exceptions.CsmClientException
77import io.mockk.every
88import io.mockk.impl.annotations.SpyK
99import io.mockk.mockk
10+ import java.net.URI
1011import kotlin.test.BeforeTest
1112import kotlin.test.Test
13+ import kotlin.test.assertEquals
14+ import kotlin.test.assertNull
1215import org.json.JSONArray
1316import org.json.JSONObject
1417import org.junit.jupiter.api.assertThrows
1518import org.springframework.http.HttpHeaders
1619import org.springframework.http.HttpStatus
20+ import org.springframework.http.ResponseEntity
1721import org.springframework.test.util.ReflectionTestUtils
22+ import org.springframework.util.MultiValueMap
1823import org.springframework.web.client.HttpClientErrorException
1924import org.springframework.web.client.HttpServerErrorException
2025import org.springframework.web.client.RestClient
2126import org.springframework.web.client.RestClient.ResponseSpec
27+ import org.springframework.web.client.RestClientException
2228
2329class ContainerRegistryServiceTest {
2430
2531 private var csmPlatformProperties: CsmPlatformProperties = mockk(relaxed = true )
2632 private var restClient: RestClient = mockk(relaxed = true )
33+ private var noRedirectClient: RestClient = mockk(relaxed = true )
2734
2835 @SpyK lateinit var containerRegistryService: ContainerRegistryService
2936
3037 @BeforeTest
3138 fun beforeTest () {
3239 containerRegistryService = ContainerRegistryService (csmPlatformProperties)
3340 ReflectionTestUtils .setField(containerRegistryService, " restClient" , restClient)
41+ ReflectionTestUtils .setField(containerRegistryService, " noRedirectClient" , noRedirectClient)
3442 every { csmPlatformProperties.containerRegistry.scheme } answers { " http" }
3543 every { csmPlatformProperties.containerRegistry.host } answers { " localhost:5000" }
3644 }
@@ -113,4 +121,98 @@ class ContainerRegistryServiceTest {
113121
114122 containerRegistryService.checkSolutionImage(" my-repository" , " latest" )
115123 }
124+
125+ @Test
126+ fun `getImageLabel, existing label` () {
127+ every {
128+ restClient
129+ .get()
130+ .uri(" /v2/myimage/manifests/mytag" )
131+ .header(HttpHeaders .AUTHORIZATION , any())
132+ .header(HttpHeaders .ACCEPT , " application/vnd.docker.distribution.manifest.v2+json" )
133+ .retrieve()
134+ .body(String ::class .java)
135+ } returns """ {"config":{"digest":"mydigest"}}"""
136+
137+ every {
138+ noRedirectClient
139+ .get()
140+ .uri(" /v2/myimage/blobs/mydigest" )
141+ .header(HttpHeaders .AUTHORIZATION , any())
142+ .retrieve()
143+ .toEntity(String ::class .java)
144+ } returns ResponseEntity (""" {"config":{"Labels":{"mylabel":"myvalue"}}}""" , HttpStatus .OK )
145+
146+ assertEquals(" myvalue" , containerRegistryService.getImageLabel(" myimage" , " mytag" , " mylabel" ))
147+ }
148+
149+ @Test
150+ fun `getImageLabel, with redirect` () {
151+ every {
152+ restClient
153+ .get()
154+ .uri(" /v2/myimage/manifests/mytag" )
155+ .header(HttpHeaders .AUTHORIZATION , any())
156+ .header(HttpHeaders .ACCEPT , " application/vnd.docker.distribution.manifest.v2+json" )
157+ .retrieve()
158+ .body(String ::class .java)
159+ } returns """ {"config":{"digest":"mydigest"}}"""
160+
161+ val response =
162+ ResponseEntity <String >(
163+ MultiValueMap .fromSingleValue(mapOf (HttpHeaders .LOCATION to String ())),
164+ HttpStatus .TEMPORARY_REDIRECT )
165+ every {
166+ noRedirectClient
167+ .get()
168+ .uri(" /v2/myimage/blobs/mydigest" )
169+ .header(HttpHeaders .AUTHORIZATION , any())
170+ .retrieve()
171+ .toEntity(String ::class .java)
172+ } returns response
173+
174+ every { restClient.get().uri(any<URI >()).retrieve().body(String ::class .java) } returns
175+ """ {"config":{"Labels":{"mylabel":"myvalue"}}}"""
176+
177+ assertEquals(" myvalue" , containerRegistryService.getImageLabel(" myimage" , " mytag" , " mylabel" ))
178+ }
179+
180+ @Test
181+ fun `getImageLabel, empty labels` () {
182+ every {
183+ restClient
184+ .get()
185+ .uri(" /v2/myimage/manifests/mytag" )
186+ .header(HttpHeaders .AUTHORIZATION , any())
187+ .header(HttpHeaders .ACCEPT , " application/vnd.docker.distribution.manifest.v2+json" )
188+ .retrieve()
189+ .body(String ::class .java)
190+ } returns """ {"config":{"digest":"mydigest"}}"""
191+
192+ every {
193+ noRedirectClient
194+ .get()
195+ .uri(" /v2/myimage/blobs/mydigest" )
196+ .header(HttpHeaders .AUTHORIZATION , any())
197+ .retrieve()
198+ .toEntity(String ::class .java)
199+ } returns ResponseEntity (""" {"config":{"Labels":null}}""" , HttpStatus .OK )
200+
201+ assertNull(containerRegistryService.getImageLabel(" myimage" , " mytag" , " mylabel" ))
202+ }
203+
204+ @Test
205+ fun `getImageLabel, invalid image` () {
206+ every {
207+ restClient
208+ .get()
209+ .uri(" /v2/wrong/manifests/wrong" )
210+ .header(HttpHeaders .AUTHORIZATION , any())
211+ .header(HttpHeaders .ACCEPT , " application/vnd.docker.distribution.manifest.v2+json" )
212+ .retrieve()
213+ .body(String ::class .java)
214+ } throws RestClientException (" " )
215+
216+ assertNull(containerRegistryService.getImageLabel(" wrong" , " wrong" , " mylabel" ))
217+ }
116218}
0 commit comments