@@ -6,6 +6,8 @@ import com.avast.gradle.dockercompose.DockerExecutor
66import com.avast.gradle.dockercompose.ServiceHost
77import com.avast.gradle.dockercompose.ServiceInfo
88import com.avast.gradle.dockercompose.ServiceInfoCache
9+ import groovy.json.JsonGenerator
10+ import groovy.json.JsonOutput
911import groovy.json.JsonSlurper
1012import org.gradle.api.DefaultTask
1113import org.gradle.api.file.DirectoryProperty
@@ -209,45 +211,41 @@ abstract class ComposeUp extends DefaultTask {
209211 }
210212 }
211213
212- private static final VOLATILE_STATE_KEYS = [' RunningFor' ]
213- private static final UNSTABLE_ARRAY_STATE_KEYS = [' Mounts' , ' Ports' , ' Networks' , ' Labels' , ' Publishers' ]
214-
215214 @Internal
216215 protected def getStateForCache () {
217- String processesAsString = composeExecutor . get() . execute( ' ps ' , ' --format ' , ' json ' )
218- String processesState = processesAsString
216+ def state = []
217+
219218 try {
220- // Since Docker Compose 2.21.0, the output is not one JSON array but newline-separated JSONs.
221- Map<String , Object > [] processes
222- if (processesAsString. startsWith(' [' )) {
223- processes = new JsonSlurper (). parseText(processesAsString)
224- } else {
225- processes = processesAsString. split(' \\ R' ). findAll { it. trim() }. collect { new JsonSlurper (). parseText(it) }
226- }
227- List<Object > transformed = processes. collect {
228- // Status field contains something like "Up 8 seconds", so we have to strip the duration.
229- if (it. containsKey(' Status' ) && it.Status . startsWith(' Up ' )) it.Status = ' Up'
230- VOLATILE_STATE_KEYS . each { key -> it. remove(key) }
231- UNSTABLE_ARRAY_STATE_KEYS . each { key -> it[key] = parseAndSortStateArray(it[key]) }
232- it
233- }
234- processesState = transformed. join(' \t ' )
235- } catch (Exception e) {
236- logger. warn(" Cannot process JSON returned from 'docker compose ps --format json'" , e)
237- }
238- processesState + composeExecutor. get(). execute(' config' ) + startedServices. get(). join(' ,' )
239- }
219+ def containersIds = composeExecutor. get()
220+ .execute(' ps' , ' --quiet' , ' --all' )
221+ .readLines()
222+ def containersInfos = new JsonSlurper (). parseText(
223+ dockerExecutor. execute([' inspect' , * containersIds] as String [])
224+ )
225+ def jsonGenerator = new JsonGenerator.Options ()
226+ .excludeFieldsByName(' Log' )
227+ .addConverter(List ) { items , key ->
228+ if (key in [null , ' Args' ]) {
229+ return items
230+ }
240231
241- protected Object parseAndSortStateArray (Object list ) {
242- if (list instanceof List ) {
243- // Already provided as a List, no pre-parsing needed
244- return list. sort { (first , second ) -> first. toString() <=> second. toString() }
245- } else if (list instanceof String && list. contains(" ," )) {
246- // Not already a list, but a comma separated string
247- return list. split(' ,' ). collect { it. trim() }. sort()
248- } else {
249- return list
232+ return items. sort()
233+ }
234+ .build()
235+
236+ state + = JsonOutput . prettyPrint(
237+ jsonGenerator. toJson(containersInfos)
238+ )
239+ } catch (Throwable t) {
240+ logger. warn(
241+ ' Cannot generate inspections for containers, for this reason the state will be incomplete' , t
242+ )
250243 }
244+
245+ state + = composeExecutor. get(). execute(' config' )
246+ state + = startedServices. get(). join(' ,' )
247+
248+ return state. join(' \n ' )
251249 }
252250
253251 protected Iterable<ServiceInfo > loadServicesInfo (Iterable<String > servicesNames ) {
0 commit comments