-
Notifications
You must be signed in to change notification settings - Fork 99
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Generate stable state for cache #470
base: main
Are you sure you want to change the base?
Generate stable state for cache #470
Conversation
src/main/groovy/com/avast/gradle/dockercompose/tasks/ComposeUp.groovy
Outdated
Show resolved
Hide resolved
Thank you! Are you please sure that the |
The result of I can't give assurance that I covered all cases with this piece of code, while it solved the problem with the order of published ports that I had. There are certainly a great many cases controlled here that could force a restart of the service stack. It would be useful for someone else to test this at their site, because as far as I can see, there is a lack of automated testing for a piece of code? |
a433fd8
to
ac87a6c
Compare
Thanks for the explanation 👍 Regarding the tests, there is no direct test, but there are these two tests for the reconnecting feature (the state-cache is used under-the-hood). |
@augi So what do we do with this PR next? |
I would like to see a real value for the cache - grab it manually or even better create a new test for it. The reason for this is that I'm afraid that this change could be even worse than the current state because there could be more volatile field in the I personally don't have time for this now (~this month), so if you are willing to do it, it would be great 🙏 |
@augi I wrote a script in Groovy that should illuminate whether our concerns about the stability of the results of the foo@bar:~$ docker ps -aq | xargs ./script.groovy In my case, all tests on 18 containers in various states were successful. When I turned off sorting in the code, quite quickly the tests were terminated with an error, due to differences between states. #!/usr/bin/env groovy
import groovy.cli.commons.CliBuilder
import groovy.cli.Option
import groovy.cli.Unparsed
import groovy.json.JsonGenerator
import groovy.json.JsonOutput
import groovy.json.JsonSlurper
String firstState, nextState
CliBuilder cli = new CliBuilder(usage: 'groovy script.groovy [OPTIONS] NAME|ID [NAME|ID...]')
Options options = []
cli.parseFromInstance(options, args)
if (options.help || !options.containersIds) {
cli.usage()
System.exit(options.help ? 0 : 1)
}
firstState = getStateForCache(options.containersIds)
for (long i = 0; i < options.numberOfTests; i++) {
print("Test #$i: ")
nextState = getStateForCache(options.containersIds)
assert firstState == nextState : 'Unexpected differences between two states detected'
println('SUCCESS')
sleep(options.waitForNextTest)
}
static def getStateForCache(String... containersIds) {
def state = []
try {
def containersInfos = new JsonSlurper().parseText(
['docker', 'inspect', *containersIds].execute().text
)
def jsonGenerator = new JsonGenerator.Options()
.excludeFieldsByName('Log')
.addConverter(List) { items, key ->
// Prevent sorting of objects in the root list and list
// items in the "Args" key (usually command arguments)
if (key in [null, 'Args']) {
return items
}
// Sort the elements of all other lists
return items.sort()
}
.build()
state += JsonOutput.prettyPrint(
jsonGenerator.toJson(containersInfos)
)
} catch (Throwable t) {
throw new RuntimeException(
'Cannot generate inspections for containers, for this reason the state will be incomplete',
t
)
}
return state.join('\n')
}
class Options {
@Option(shortName = 'h', longName = 'help', description = 'Show usage information')
boolean help
@Option(shortName = 't', longName = 'tests', description = 'Number of comparison tests to be performed')
long numberOfTests = 100
@Option(shortName = 'w', longName = 'wait', description = 'Waiting time for next comparison test in ms')
long waitForNextTest = 0
@Unparsed(description = 'Names or IDs of containers')
String[] containersIds
} |
I did a test of 100 trials, which lasted for almost 2 minutes. foo@bar:~$ docker ps -aq | time xargs ./script.groovy -t 100 -w 1000
Test #0: SUCCESS
Test #1: SUCCESS
[...]
Test #98: SUCCESS
Test #99: SUCCESS
6.93user 1.39system 1:43.88elapsed 8%CPU (0avgtext+0avgdata 992608maxresident)k
0inputs+0outputs (0major+637858minor)pagefaults 0swaps
xargs ./script.groovy -t 100 -w 1000 6,94s user 1,40s system 8% cpu 1:43,89 total |
Wouldn't it be possible to convert it to a new test? To have it reproducible, and also to be able to test it easily in different environments (Docker versions, OSs) 🙏 |
@augi I could do this if I knew how to perform these tests on my machine. Unfortunately, a simple |
Relates to: #431
Rather than relying on the output of the
docker-compose ps
command, where the output from different versions may vary, I suggest for this command to limit itself to only retrieving a list of container IDs. The ID list thus obtained is then passed to thedocker inspect
command, whose output format has always been JSON. Then on the results of thedocker inspect
command build the state for the cache.I think there is nothing to go further in parsing the results of the
docker-compose ps
command. A recent fix was made by @tom-wozniakowski-tw in #468, but that didn't ultimately solve the state stability problem either.