diff --git a/build.gradle b/build.gradle index be49411..543d917 100644 --- a/build.gradle +++ b/build.gradle @@ -37,7 +37,7 @@ dependencies { } task wrapper(type: Wrapper) { - gradleVersion = '3.5' + gradleVersion = '4.1' } task sourcesJar(type: Jar) { diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 159a5f5..7a3265e 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 72f8495..f16d266 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ -#Sun Aug 27 10:44:11 CEST 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-bin.zip diff --git a/gradlew b/gradlew index 4453cce..cccdd3d 100755 --- a/gradlew +++ b/gradlew @@ -33,11 +33,11 @@ DEFAULT_JVM_OPTS="" # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" -warn ( ) { +warn () { echo "$*" } -die ( ) { +die () { echo echo "$*" echo @@ -155,7 +155,7 @@ if $cygwin ; then fi # Escape application args -save ( ) { +save () { for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done echo " " } diff --git a/src/main/groovy/com/avast/gradle/dockercompose/NoOpLogger.groovy b/src/main/groovy/com/avast/gradle/dockercompose/NoOpLogger.groovy new file mode 100644 index 0000000..7e38077 --- /dev/null +++ b/src/main/groovy/com/avast/gradle/dockercompose/NoOpLogger.groovy @@ -0,0 +1,375 @@ +package com.avast.gradle.dockercompose + +import org.gradle.api.logging.LogLevel +import org.gradle.api.logging.Logger +import org.slf4j.Marker + +class NoOpLogger implements Logger { + + static Logger INSTANCE = new NoOpLogger() + + @Override + boolean isLifecycleEnabled() { + return false + } + + @Override + String getName() { + return null + } + + @Override + boolean isTraceEnabled() { + return false + } + + @Override + void trace(String s) { + + } + + @Override + void trace(String s, Object o) { + + } + + @Override + void trace(String s, Object o, Object o1) { + + } + + @Override + void trace(String s, Object... objects) { + + } + + @Override + void trace(String s, Throwable throwable) { + + } + + @Override + boolean isTraceEnabled(Marker marker) { + return false + } + + @Override + void trace(Marker marker, String s) { + + } + + @Override + void trace(Marker marker, String s, Object o) { + + } + + @Override + void trace(Marker marker, String s, Object o, Object o1) { + + } + + @Override + void trace(Marker marker, String s, Object... objects) { + + } + + @Override + void trace(Marker marker, String s, Throwable throwable) { + + } + + @Override + boolean isDebugEnabled() { + return false + } + + @Override + void debug(String s) { + + } + + @Override + void debug(String s, Object o) { + + } + + @Override + void debug(String s, Object o, Object o1) { + + } + + @Override + void debug(String s, Object... objects) { + + } + + @Override + void debug(String s, Throwable throwable) { + + } + + @Override + boolean isDebugEnabled(Marker marker) { + return false + } + + @Override + void debug(Marker marker, String s) { + + } + + @Override + void debug(Marker marker, String s, Object o) { + + } + + @Override + void debug(Marker marker, String s, Object o, Object o1) { + + } + + @Override + void debug(Marker marker, String s, Object... objects) { + + } + + @Override + void debug(Marker marker, String s, Throwable throwable) { + + } + + @Override + boolean isInfoEnabled() { + return false + } + + @Override + void info(String s) { + + } + + @Override + void info(String s, Object o) { + + } + + @Override + void info(String s, Object o, Object o1) { + + } + + @Override + void lifecycle(String s) { + + } + + @Override + void lifecycle(String s, Object... objects) { + + } + + @Override + void lifecycle(String s, Throwable throwable) { + + } + + @Override + boolean isQuietEnabled() { + return false + } + + @Override + void quiet(String s) { + + } + + @Override + void quiet(String s, Object... objects) { + + } + + @Override + void info(String s, Object... objects) { + + } + + @Override + void info(String s, Throwable throwable) { + + } + + @Override + boolean isInfoEnabled(Marker marker) { + return false + } + + @Override + void info(Marker marker, String s) { + + } + + @Override + void info(Marker marker, String s, Object o) { + + } + + @Override + void info(Marker marker, String s, Object o, Object o1) { + + } + + @Override + void info(Marker marker, String s, Object... objects) { + + } + + @Override + void info(Marker marker, String s, Throwable throwable) { + + } + + @Override + boolean isWarnEnabled() { + return false + } + + @Override + void warn(String s) { + + } + + @Override + void warn(String s, Object o) { + + } + + @Override + void warn(String s, Object... objects) { + + } + + @Override + void warn(String s, Object o, Object o1) { + + } + + @Override + void warn(String s, Throwable throwable) { + + } + + @Override + boolean isWarnEnabled(Marker marker) { + return false + } + + @Override + void warn(Marker marker, String s) { + + } + + @Override + void warn(Marker marker, String s, Object o) { + + } + + @Override + void warn(Marker marker, String s, Object o, Object o1) { + + } + + @Override + void warn(Marker marker, String s, Object... objects) { + + } + + @Override + void warn(Marker marker, String s, Throwable throwable) { + + } + + @Override + boolean isErrorEnabled() { + return false + } + + @Override + void error(String s) { + + } + + @Override + void error(String s, Object o) { + + } + + @Override + void error(String s, Object o, Object o1) { + + } + + @Override + void error(String s, Object... objects) { + + } + + @Override + void error(String s, Throwable throwable) { + + } + + @Override + boolean isErrorEnabled(Marker marker) { + return false + } + + @Override + void error(Marker marker, String s) { + + } + + @Override + void error(Marker marker, String s, Object o) { + + } + + @Override + void error(Marker marker, String s, Object o, Object o1) { + + } + + @Override + void error(Marker marker, String s, Object... objects) { + + } + + @Override + void error(Marker marker, String s, Throwable throwable) { + + } + + @Override + void quiet(String s, Throwable throwable) { + + } + + @Override + boolean isEnabled(LogLevel logLevel) { + return false + } + + @Override + void log(LogLevel logLevel, String s) { + + } + + @Override + void log(LogLevel logLevel, String s, Object... objects) { + + } + + @Override + void log(LogLevel logLevel, String s, Throwable throwable) { + + } +} diff --git a/src/main/groovy/com/avast/gradle/dockercompose/ServiceHost.groovy b/src/main/groovy/com/avast/gradle/dockercompose/ServiceHost.groovy index a1e0fb4..ef871e5 100644 --- a/src/main/groovy/com/avast/gradle/dockercompose/ServiceHost.groovy +++ b/src/main/groovy/com/avast/gradle/dockercompose/ServiceHost.groovy @@ -11,5 +11,6 @@ class ServiceHost { enum ServiceHostType { NetworkGateway, RemoteDockerHost, - LocalHost + LocalHost, + Host } diff --git a/src/main/groovy/com/avast/gradle/dockercompose/tasks/ComposeUp.groovy b/src/main/groovy/com/avast/gradle/dockercompose/tasks/ComposeUp.groovy index 7db8e30..d1ca333 100644 --- a/src/main/groovy/com/avast/gradle/dockercompose/tasks/ComposeUp.groovy +++ b/src/main/groovy/com/avast/gradle/dockercompose/tasks/ComposeUp.groovy @@ -1,11 +1,13 @@ package com.avast.gradle.dockercompose.tasks import com.avast.gradle.dockercompose.ComposeExtension +import com.avast.gradle.dockercompose.NoOpLogger import com.avast.gradle.dockercompose.ServiceHost import com.avast.gradle.dockercompose.ServiceHostType import com.avast.gradle.dockercompose.ServiceInfo import com.avast.gradle.dockercompose.ContainerInfo import org.gradle.api.DefaultTask +import org.gradle.api.logging.Logger import org.gradle.api.tasks.TaskAction import org.gradle.process.ExecSpec import org.gradle.util.VersionNumber @@ -126,7 +128,7 @@ class ComposeUp extends DefaultTask { Map createContainerInfos(Iterable containerIds, String serviceName) { containerIds.collectEntries { String containerId -> logger.info("Container ID of service $serviceName is $containerId") - def inspection = getDockerInspection(containerId) + def inspection = getValidDockerInspection(serviceName, containerId, 10) ServiceHost host = getServiceHost(serviceName, inspection) logger.info("Will use $host as host of service $serviceName") def tcpPorts = getTcpPortsMapping(serviceName, inspection, host) @@ -211,6 +213,44 @@ class ComposeUp extends DefaultTask { } } + Map getValidDockerInspection(String serviceName, String containerId, int remainingRetries) { + def dockerInspection = getDockerInspection(containerId) + def validationError = getDockerInspectionValidationError(serviceName, dockerInspection) + if (validationError.empty) { + dockerInspection + } else { + def msg = "Docker inspection of container $containerId (service $serviceName) is not valid: '$validationError'\n${dockerInspection.toString()}" + if (remainingRetries <= 0) { + throw new RuntimeException(msg) + } + logger.lifecycle("$msg Sleeping and trying again") + Thread.sleep(10000) + getValidDockerInspection(serviceName, containerId, remainingRetries - 1) + } + } + + private String getDockerInspectionValidationError(String serviceName, Map inspection) { + ServiceHost serviceHost + try { + serviceHost = getServiceHost(serviceName, inspection, NoOpLogger.INSTANCE) + } catch (Exception e) { + def msg = "Error when getting service host of service $serviceName: ${e.message}" + logger.warn(msg, e) + return msg + } + if (serviceHost.type != ServiceHostType.Host) { + Map portsFromConfig = inspection.Config.ExposedPorts ?: [:] + Map portsFromNetwork = inspection.NetworkSettings.Ports + def missingPorts = portsFromConfig.keySet().findAll { !portsFromNetwork.containsKey(it) } + if (!missingPorts.empty) { + def msg = "There ports of service $serviceName are declared as exposed but cannot be found in NetworkSetting: ${missingPorts.join(', ')}" + logger.warn(msg) + return msg + } + } + return "" + } + Map getNetworkInspection(String networkName) { new ByteArrayOutputStream().withStream { os -> project.exec { ExecSpec e -> @@ -238,7 +278,8 @@ class ComposeUp extends DefaultTask { null } - ServiceHost getServiceHost(String serviceName, Map inspection) { + + ServiceHost getServiceHost(String serviceName, Map inspection, Logger logger = this.logger) { String servicesHost = extension.environment['SERVICES_HOST'] ?: System.getenv('SERVICES_HOST') if (servicesHost) { logger.lifecycle("SERVICES_HOST environment variable detected - will be used as hostname of service $serviceName ($servicesHost)'") @@ -260,6 +301,7 @@ class ComposeUp extends DefaultTask { if (networks && networks.every { it.key.toLowerCase().equals("host") }) { gateway = 'localhost' logger.lifecycle("Will use $gateway as host of $serviceName because it is using HOST network") + return new ServiceHost(host: 'localhost', type: ServiceHostType.Host) } else if (networks && networks.size() > 0) { Map.Entry firstNetworkPair = networks.find() gateway = firstNetworkPair.value.Gateway @@ -302,6 +344,10 @@ class ComposeUp extends DefaultTask { logger.info("Exposed TCP port on service '$serviceName:$exposedPort' will be available as $forwardedPort") ports.put(exposedPort, forwardedPort) break + case ServiceHostType.Host: + logger.info("Exposed TCP port on service '$serviceName:$exposedPort' will be available as $exposedPort because it uses HOST network") + ports.put(exposedPort, exposedPort) + break; default: throw new IllegalArgumentException("Unknown ServiceHostType '${host.type}' for service '$serviceName'") break