From 4128ce935c7afb5407457eb96e58c96ce9856217 Mon Sep 17 00:00:00 2001 From: "tad.cordle@gmail.com" Date: Fri, 3 Jan 2020 15:26:54 -0500 Subject: [PATCH 01/36] Progress --- .../cloud/tools/jib/gradle/TaskCommon.java | 2 + .../cloud/tools/jib/maven/MojoCommon.java | 2 + .../common/PluginConfigurationProcessor.java | 6 +- .../jib/plugins/common/PropertyNames.java | 1 + .../jib/plugins/common/UpdateChecker.java | 135 ++++++++++++++++++ 5 files changed, 142 insertions(+), 4 deletions(-) create mode 100644 jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java diff --git a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/TaskCommon.java b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/TaskCommon.java index c9cb753796..140bd3ec94 100644 --- a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/TaskCommon.java +++ b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/TaskCommon.java @@ -36,6 +36,8 @@ /** Collection of common methods to share between Gradle tasks. */ class TaskCommon { + public static final String VERSION_URL = "https://storage.googleapis.com/jib-versions/jib-gradle"; + @Nullable static TaskProvider getWarTaskProvider(Project project) { if (project.getPlugins().hasPlugin(WarPlugin.class)) { diff --git a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/MojoCommon.java b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/MojoCommon.java index b333779828..d233c3a1f7 100644 --- a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/MojoCommon.java +++ b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/MojoCommon.java @@ -40,6 +40,8 @@ public class MojoCommon { @VisibleForTesting public static final String REQUIRED_VERSION_PROPERTY_NAME = "jib.requiredVersion"; + public static final String VERSION_URL = "https://storage.googleapis.com/jib-versions/jib-maven"; + /** * Gets the list of extra directory paths from a {@link JibPluginConfiguration}. Returns {@code * (project dir)/src/main/jib} by default if not configured. diff --git a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/PluginConfigurationProcessor.java b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/PluginConfigurationProcessor.java index 778a839fdd..e344298d17 100644 --- a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/PluginConfigurationProcessor.java +++ b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/PluginConfigurationProcessor.java @@ -166,10 +166,8 @@ public static JibBuildRunner createJibBuildRunnerForRegistryImage( rawConfiguration.getToCredHelper().orElse(null)); boolean alwaysCacheBaseImage = - Boolean.valueOf( - rawConfiguration - .getProperty(PropertyNames.ALWAYS_CACHE_BASE_IMAGE) - .orElse(Boolean.FALSE.toString())); + Boolean.parseBoolean( + rawConfiguration.getProperty(PropertyNames.ALWAYS_CACHE_BASE_IMAGE).orElse("false")); Containerizer containerizer = Containerizer.to(targetImage).setAlwaysCacheBaseImage(alwaysCacheBaseImage); diff --git a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/PropertyNames.java b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/PropertyNames.java index fd15d8f30e..3ba75d5c55 100644 --- a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/PropertyNames.java +++ b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/PropertyNames.java @@ -61,6 +61,7 @@ public class PropertyNames { public static final String CONSOLE = "jib.console"; public static final String CONTAINERIZE = "jib.containerize"; public static final String ALWAYS_CACHE_BASE_IMAGE = "jib.alwaysCacheBaseImage"; + public static final String DISABLE_UPDATE_CHECKS = "jib.disableUpdateChecks"; private PropertyNames() {} } diff --git a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java new file mode 100644 index 0000000000..77a176abdf --- /dev/null +++ b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java @@ -0,0 +1,135 @@ +/* + * Copyright 2019 Google LLC. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.cloud.tools.jib.plugins.common; + +import com.google.cloud.tools.jib.json.JsonTemplate; +import com.google.cloud.tools.jib.json.JsonTemplateMapper; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import java.net.URLConnection; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.attribute.FileTime; +import java.time.Duration; +import java.time.Instant; +import java.util.Optional; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; + +/** Checks if Jib is up-to-date. */ +public class UpdateChecker { + + /** JSON template for the configuration file used to enable/disable update checks. */ + private static class ConfigJsonTemplate implements JsonTemplate { + private boolean disableUpdateCheck; + } + + /** + * Begins checking for an update in a separate thread. + * + * @param currentVersion the current version of Jib in use + * @param versionUrl the location to check for the latest version + * @param executorService the {@link ExecutorService} + * @return a new {@link UpdateChecker} + */ + public static UpdateChecker checkForUpdate( + String currentVersion, String versionUrl, ExecutorService executorService) { + return new UpdateChecker( + executorService.submit(() -> performUpdateCheck(currentVersion, versionUrl, CONFIG_DIR))); + } + + private static Optional performUpdateCheck( + String currentVersion, String versionUrl, Path configDir) { + if (Boolean.getBoolean(PropertyNames.DISABLE_UPDATE_CHECKS)) { + return Optional.empty(); + } + + try { + Path configFile = configDir.resolve("config.json"); + if (Files.exists(configFile)) { + ConfigJsonTemplate config = + JsonTemplateMapper.readJsonFromFile(configFile, ConfigJsonTemplate.class); + if (config.disableUpdateCheck) { + return Optional.empty(); + } + } else { + ConfigJsonTemplate config = new ConfigJsonTemplate(); + config.disableUpdateCheck = true; + JsonTemplateMapper.writeTo(config, Files.newOutputStream(configFile)); + } + + Path lastUpdateCheck = configDir.resolve("lastUpdateCheck"); + if (Files.exists(lastUpdateCheck)) { + FileTime modifiedTime = Files.getLastModifiedTime(lastUpdateCheck); + if (modifiedTime.toInstant().plus(Duration.ofDays(1)).isAfter(Instant.now())) { + return Optional.empty(); + } + } + + URLConnection connection = new URL(versionUrl).openConnection(); + BufferedReader bufferedReader = + new BufferedReader(new InputStreamReader(connection.getInputStream())); + String latestVersion = bufferedReader.readLine(); + + Files.setLastModifiedTime(lastUpdateCheck, FileTime.from(Instant.now())); + if (currentVersion.equals(latestVersion)) { + return Optional.empty(); + } + + return Optional.of( + "A new version of Jib (" + + latestVersion + + ") is available (currently using " + + currentVersion + + "). Update your build configuration to use the latest features and fixes!"); + + } catch (IOException ignored) { + // Fail silently + } + + return Optional.empty(); + } + + private final Future> updateMessageFuture; + + private UpdateChecker(Future> updateMessageFuture) { + this.updateMessageFuture = updateMessageFuture; + } + + /** + * Returns a message indicating Jib should be upgraded if the check succeeded and the current + * version is outdated, or returns {@code Optional.empty()} if the check was interrupted or did + * not determine that a later version was available. + * + * @return the {@link Optional} message to upgrade Jib if a later version was found, else {@code + * Optional.empty()}. + */ + public Optional finishUpdateCheck() { + if (updateMessageFuture.isDone()) { + try { + return updateMessageFuture.get(); + } catch (InterruptedException | ExecutionException ignored) { + // Fail silently; + } + } + updateMessageFuture.cancel(true); + return Optional.empty(); + } +} From 76fb821a1ce25043cc0276edbdea5bc94a352cb0 Mon Sep 17 00:00:00 2001 From: "tad.cordle@gmail.com" Date: Fri, 3 Jan 2020 15:59:53 -0500 Subject: [PATCH 02/36] Add method for retrieving XDG config directory --- .../cloud/tools/jib/api/Containerizer.java | 4 +- ...UserCacheHome.java => XdgDirectories.java} | 73 +++++++++++++++++-- ...eHomeTest.java => XdgDirectoriesTest.java} | 60 +++++++++++++-- 3 files changed, 122 insertions(+), 15 deletions(-) rename jib-core/src/main/java/com/google/cloud/tools/jib/filesystem/{UserCacheHome.java => XdgDirectories.java} (55%) rename jib-core/src/test/java/com/google/cloud/tools/jib/filesystem/{UserCacheHomeTest.java => XdgDirectoriesTest.java} (54%) diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/api/Containerizer.java b/jib-core/src/main/java/com/google/cloud/tools/jib/api/Containerizer.java index cbd05e7318..cbe596bf68 100644 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/api/Containerizer.java +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/api/Containerizer.java @@ -22,7 +22,7 @@ import com.google.cloud.tools.jib.configuration.ImageConfiguration; import com.google.cloud.tools.jib.docker.DockerClient; import com.google.cloud.tools.jib.event.EventHandlers; -import com.google.cloud.tools.jib.filesystem.UserCacheHome; +import com.google.cloud.tools.jib.filesystem.XdgDirectories; import com.google.common.base.Preconditions; import java.io.IOException; import java.nio.file.Files; @@ -45,7 +45,7 @@ public class Containerizer { * home]/google-cloud-tools-java/jib}. */ public static final Path DEFAULT_BASE_CACHE_DIRECTORY = - UserCacheHome.getCacheHome().resolve("google-cloud-tools-java").resolve("jib"); + XdgDirectories.getCacheHome().resolve("google-cloud-tools-java").resolve("jib"); private static final String DEFAULT_TOOL_NAME = "jib-core"; diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/filesystem/UserCacheHome.java b/jib-core/src/main/java/com/google/cloud/tools/jib/filesystem/XdgDirectories.java similarity index 55% rename from jib-core/src/main/java/com/google/cloud/tools/jib/filesystem/UserCacheHome.java rename to jib-core/src/main/java/com/google/cloud/tools/jib/filesystem/XdgDirectories.java index 4547269154..5016dac3fa 100644 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/filesystem/UserCacheHome.java +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/filesystem/XdgDirectories.java @@ -26,27 +26,32 @@ import java.util.logging.Logger; /** - * Obtains an OS-specific user cache directory based on the XDG Base Directory Specification. + * Obtains an OS-specific directories based on the XDG Base Directory Specification. * *

Specifically, from the specification: * *

    - *
  • This directory is defined by the environment variable {@code $XDG_CACHE_HOME}. - *
  • If {@code $XDG_CACHE_HOME} is either not set or empty, a default equal to {@code - * $HOME/.cache} should be used. + *
  • These directories are defined by the environment variables {@code $XDG_CACHE_HOME} and + * {@code $XDG_CONFIG_HOME}. + *
  • If {@code $XDG_CACHE_HOME} / {@code $XDG_CONFIG_HOME} is either not set or empty, a default + * equal to {@code $HOME/.cache} / {@code $HOME/.config} should be used. *
* * @see https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html */ -public class UserCacheHome { +public class XdgDirectories { - private static final Logger logger = Logger.getLogger(UserCacheHome.class.getName()); + private static final Logger logger = Logger.getLogger(XdgDirectories.class.getName()); public static Path getCacheHome() { return getCacheHome(System.getProperties(), System.getenv()); } + public static Path getConfigHome() { + return getConfigHome(System.getProperties(), System.getenv()); + } + /** * Returns {@code $XDG_CACHE_HOME}, if available, or resolves the OS-specific user cache home * based. @@ -101,5 +106,59 @@ static Path getCacheHome(Properties properties, Map environment) throw new IllegalStateException("Unknown OS: " + rawOsName); } - private UserCacheHome() {} + /** + * Returns {@code $XDG_CONFIG_HOME}, if available, or resolves the OS-specific user config home + * based. + * + *

For Linux, this is {@code $HOME/.config/}. + * + *

For Windows, this is {@code %LOCALAPPDATA%}. + * + *

For macOS, this is {@code $HOME/Library/Preferences/}. + */ + @VisibleForTesting + static Path getConfigHome(Properties properties, Map environment) { + // Use environment variable $XDG_CONFIG_HOME if set and not empty. + String xdgConfigHome = environment.get("XDG_CONFIG_HOME"); + if (xdgConfigHome != null && !xdgConfigHome.trim().isEmpty()) { + return Paths.get(xdgConfigHome); + } + + String userHome = properties.getProperty("user.home"); + Path xdgPath = Paths.get(userHome, ".config"); + + String rawOsName = properties.getProperty("os.name"); + String osName = rawOsName.toLowerCase(Locale.ENGLISH); + + if (osName.contains("linux")) { + return xdgPath; + + } else if (osName.contains("windows")) { + // Use %LOCALAPPDATA% for Windows. + String localAppDataEnv = environment.get("LOCALAPPDATA"); + if (localAppDataEnv == null || localAppDataEnv.trim().isEmpty()) { + logger.warning("LOCALAPPDATA environment is invalid or missing"); + return xdgPath; + } + Path localAppData = Paths.get(localAppDataEnv); + if (!Files.exists(localAppData)) { + logger.warning(localAppData + " does not exist"); + return xdgPath; + } + return localAppData; + + } else if (osName.contains("mac") || osName.contains("darwin")) { + // Use '~/Library/Preferences/' for macOS. + Path applicationSupport = Paths.get(userHome, "Library", "Preferences"); + if (!Files.exists(applicationSupport)) { + logger.warning(applicationSupport + " does not exist"); + return xdgPath; + } + return applicationSupport; + } + + throw new IllegalStateException("Unknown OS: " + rawOsName); + } + + private XdgDirectories() {} } diff --git a/jib-core/src/test/java/com/google/cloud/tools/jib/filesystem/UserCacheHomeTest.java b/jib-core/src/test/java/com/google/cloud/tools/jib/filesystem/XdgDirectoriesTest.java similarity index 54% rename from jib-core/src/test/java/com/google/cloud/tools/jib/filesystem/UserCacheHomeTest.java rename to jib-core/src/test/java/com/google/cloud/tools/jib/filesystem/XdgDirectoriesTest.java index 4d5152fd7e..d8025b11fb 100644 --- a/jib-core/src/test/java/com/google/cloud/tools/jib/filesystem/UserCacheHomeTest.java +++ b/jib-core/src/test/java/com/google/cloud/tools/jib/filesystem/XdgDirectoriesTest.java @@ -31,16 +31,18 @@ import org.junit.rules.TemporaryFolder; import org.mockito.Mockito; -/** Tests for {@link UserCacheHome}. */ -public class UserCacheHomeTest { +/** Tests for {@link XdgDirectories}. */ +public class XdgDirectoriesTest { @Rule public TemporaryFolder temporaryFolder = new TemporaryFolder(); private String fakeCacheHome; + private String fakeConfigHome; @Before public void setUp() throws IOException { fakeCacheHome = temporaryFolder.newFolder().getPath(); + fakeConfigHome = temporaryFolder.newFolder().getPath(); } @Test @@ -49,7 +51,7 @@ public void testGetCacheHome_hasXdgCacheHome() { Assert.assertEquals( Paths.get(fakeCacheHome), - UserCacheHome.getCacheHome(Mockito.mock(Properties.class), fakeEnvironment)); + XdgDirectories.getCacheHome(Mockito.mock(Properties.class), fakeEnvironment)); } @Test @@ -60,7 +62,7 @@ public void testGetCacheHome_linux() { Assert.assertEquals( Paths.get(fakeCacheHome, ".cache"), - UserCacheHome.getCacheHome(fakeProperties, Collections.emptyMap())); + XdgDirectories.getCacheHome(fakeProperties, Collections.emptyMap())); } @Test @@ -72,7 +74,7 @@ public void testGetCacheHome_windows() { Map fakeEnvironment = ImmutableMap.of("LOCALAPPDATA", fakeCacheHome); Assert.assertEquals( - Paths.get(fakeCacheHome), UserCacheHome.getCacheHome(fakeProperties, fakeEnvironment)); + Paths.get(fakeCacheHome), XdgDirectories.getCacheHome(fakeProperties, fakeEnvironment)); } @Test @@ -86,6 +88,52 @@ public void testGetCacheHome_mac() throws IOException { Assert.assertEquals( libraryApplicationSupport, - UserCacheHome.getCacheHome(fakeProperties, Collections.emptyMap())); + XdgDirectories.getCacheHome(fakeProperties, Collections.emptyMap())); + } + + @Test + public void testGetConfigHome_hasXdgConfigHome() { + Map fakeEnvironment = ImmutableMap.of("XDG_CONFIG_HOME", fakeConfigHome); + + Assert.assertEquals( + Paths.get(fakeConfigHome), + XdgDirectories.getConfigHome(Mockito.mock(Properties.class), fakeEnvironment)); + } + + @Test + public void testGetConfigHome_linux() { + Properties fakeProperties = new Properties(); + fakeProperties.setProperty("user.home", fakeConfigHome); + fakeProperties.setProperty("os.name", "os is LiNuX"); + + Assert.assertEquals( + Paths.get(fakeConfigHome, ".config"), + XdgDirectories.getConfigHome(fakeProperties, Collections.emptyMap())); + } + + @Test + public void testGetConfigHome_windows() { + Properties fakeProperties = new Properties(); + fakeProperties.setProperty("user.home", "nonexistent"); + fakeProperties.setProperty("os.name", "os is WiNdOwS"); + + Map fakeEnvironment = ImmutableMap.of("LOCALAPPDATA", fakeConfigHome); + + Assert.assertEquals( + Paths.get(fakeConfigHome), XdgDirectories.getConfigHome(fakeProperties, fakeEnvironment)); + } + + @Test + public void testGetConfigHome_mac() throws IOException { + Path libraryApplicationSupport = Paths.get(fakeConfigHome, "Library", "Preferences"); + Files.createDirectories(libraryApplicationSupport); + + Properties fakeProperties = new Properties(); + fakeProperties.setProperty("user.home", fakeConfigHome); + fakeProperties.setProperty("os.name", "os is mAc or DaRwIn"); + + Assert.assertEquals( + libraryApplicationSupport, + XdgDirectories.getConfigHome(fakeProperties, Collections.emptyMap())); } } From 88a86b896463d85f9200fe4cfd5e5102972ca7ba Mon Sep 17 00:00:00 2001 From: "tad.cordle@gmail.com" Date: Fri, 3 Jan 2020 17:38:15 -0500 Subject: [PATCH 03/36] Progress --- .../tools/jib/gradle/BuildDockerTask.java | 9 ++++++++ .../tools/jib/gradle/BuildImageTask.java | 9 ++++++++ .../cloud/tools/jib/gradle/BuildTarTask.java | 9 ++++++++ .../tools/jib/maven/BuildDockerMojo.java | 9 ++++++++ .../cloud/tools/jib/maven/BuildImageMojo.java | 9 ++++++++ .../cloud/tools/jib/maven/BuildTarMojo.java | 9 ++++++++ .../jib/plugins/common/UpdateChecker.java | 23 ++++++++++++++----- 7 files changed, 71 insertions(+), 6 deletions(-) diff --git a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildDockerTask.java b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildDockerTask.java index 5d8f3a7ab9..03eb98c853 100644 --- a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildDockerTask.java +++ b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildDockerTask.java @@ -18,6 +18,7 @@ import com.google.cloud.tools.jib.api.CacheDirectoryCreationException; import com.google.cloud.tools.jib.api.InvalidImageReferenceException; +import com.google.cloud.tools.jib.api.LogEvent; import com.google.cloud.tools.jib.docker.DockerClient; import com.google.cloud.tools.jib.filesystem.TempDirectoryProvider; import com.google.cloud.tools.jib.plugins.common.BuildStepsExecutionException; @@ -31,9 +32,11 @@ import com.google.cloud.tools.jib.plugins.common.InvalidWorkingDirectoryException; import com.google.cloud.tools.jib.plugins.common.MainClassInferenceException; import com.google.cloud.tools.jib.plugins.common.PluginConfigurationProcessor; +import com.google.cloud.tools.jib.plugins.common.UpdateChecker; import com.google.common.base.Preconditions; import java.io.IOException; import java.nio.file.Path; +import java.util.concurrent.Executors; import javax.annotation.Nullable; import org.gradle.api.DefaultTask; import org.gradle.api.GradleException; @@ -92,6 +95,9 @@ public void buildDocker() GradleProjectProperties projectProperties = GradleProjectProperties.getForProject(getProject(), getLogger(), tempDirectoryProvider); + UpdateChecker updateChecker = + UpdateChecker.checkForUpdate( + projectProperties, TaskCommon.VERSION_URL, Executors.newSingleThreadExecutor()); try { PluginConfigurationProcessor.createJibBuildRunnerForDockerDaemonImage( new GradleRawConfiguration(jibExtension), @@ -145,6 +151,9 @@ public void buildDocker() } finally { tempDirectoryProvider.close(); + updateChecker + .finishUpdateCheck() + .ifPresent(s -> projectProperties.log(LogEvent.lifecycle(s))); projectProperties.waitForLoggingThread(); } } diff --git a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildImageTask.java b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildImageTask.java index 8927310deb..d2d3b963f7 100644 --- a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildImageTask.java +++ b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildImageTask.java @@ -18,6 +18,7 @@ import com.google.cloud.tools.jib.api.CacheDirectoryCreationException; import com.google.cloud.tools.jib.api.InvalidImageReferenceException; +import com.google.cloud.tools.jib.api.LogEvent; import com.google.cloud.tools.jib.filesystem.TempDirectoryProvider; import com.google.cloud.tools.jib.plugins.common.BuildStepsExecutionException; import com.google.cloud.tools.jib.plugins.common.HelpfulSuggestions; @@ -30,10 +31,12 @@ import com.google.cloud.tools.jib.plugins.common.InvalidWorkingDirectoryException; import com.google.cloud.tools.jib.plugins.common.MainClassInferenceException; import com.google.cloud.tools.jib.plugins.common.PluginConfigurationProcessor; +import com.google.cloud.tools.jib.plugins.common.UpdateChecker; import com.google.common.base.Preconditions; import com.google.common.base.Strings; import java.io.IOException; import java.util.Optional; +import java.util.concurrent.Executors; import javax.annotation.Nullable; import org.gradle.api.DefaultTask; import org.gradle.api.GradleException; @@ -81,6 +84,9 @@ public void buildImage() GradleProjectProperties projectProperties = GradleProjectProperties.getForProject(getProject(), getLogger(), tempDirectoryProvider); + UpdateChecker updateChecker = + UpdateChecker.checkForUpdate( + projectProperties, TaskCommon.VERSION_URL, Executors.newSingleThreadExecutor()); try { if (Strings.isNullOrEmpty(jibExtension.getTo().getImage())) { throw new GradleException( @@ -143,6 +149,9 @@ public void buildImage() } finally { tempDirectoryProvider.close(); + updateChecker + .finishUpdateCheck() + .ifPresent(s -> projectProperties.log(LogEvent.lifecycle(s))); projectProperties.waitForLoggingThread(); } } diff --git a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildTarTask.java b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildTarTask.java index 3a778b019f..0aed241a87 100644 --- a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildTarTask.java +++ b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildTarTask.java @@ -18,6 +18,7 @@ import com.google.cloud.tools.jib.api.CacheDirectoryCreationException; import com.google.cloud.tools.jib.api.InvalidImageReferenceException; +import com.google.cloud.tools.jib.api.LogEvent; import com.google.cloud.tools.jib.filesystem.TempDirectoryProvider; import com.google.cloud.tools.jib.plugins.common.BuildStepsExecutionException; import com.google.cloud.tools.jib.plugins.common.HelpfulSuggestions; @@ -30,11 +31,13 @@ import com.google.cloud.tools.jib.plugins.common.InvalidWorkingDirectoryException; import com.google.cloud.tools.jib.plugins.common.MainClassInferenceException; import com.google.cloud.tools.jib.plugins.common.PluginConfigurationProcessor; +import com.google.cloud.tools.jib.plugins.common.UpdateChecker; import com.google.common.base.Preconditions; import java.io.IOException; import java.nio.file.Path; import java.util.List; import java.util.Optional; +import java.util.concurrent.Executors; import javax.annotation.Nullable; import org.gradle.api.DefaultTask; import org.gradle.api.GradleException; @@ -106,6 +109,9 @@ public void buildTar() GradleProjectProperties projectProperties = GradleProjectProperties.getForProject(getProject(), getLogger(), tempDirectoryProvider); + UpdateChecker updateChecker = + UpdateChecker.checkForUpdate( + projectProperties, TaskCommon.VERSION_URL, Executors.newSingleThreadExecutor()); try { PluginConfigurationProcessor.createJibBuildRunnerForTarImage( new GradleRawConfiguration(jibExtension), @@ -159,6 +165,9 @@ public void buildTar() } finally { tempDirectoryProvider.close(); + updateChecker + .finishUpdateCheck() + .ifPresent(s -> projectProperties.log(LogEvent.lifecycle(s))); projectProperties.waitForLoggingThread(); } } diff --git a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildDockerMojo.java b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildDockerMojo.java index 08d37c6df3..bd69ed6de1 100644 --- a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildDockerMojo.java +++ b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildDockerMojo.java @@ -18,6 +18,7 @@ import com.google.cloud.tools.jib.api.CacheDirectoryCreationException; import com.google.cloud.tools.jib.api.InvalidImageReferenceException; +import com.google.cloud.tools.jib.api.LogEvent; import com.google.cloud.tools.jib.docker.DockerClient; import com.google.cloud.tools.jib.filesystem.TempDirectoryProvider; import com.google.cloud.tools.jib.plugins.common.BuildStepsExecutionException; @@ -31,9 +32,11 @@ import com.google.cloud.tools.jib.plugins.common.InvalidWorkingDirectoryException; import com.google.cloud.tools.jib.plugins.common.MainClassInferenceException; import com.google.cloud.tools.jib.plugins.common.PluginConfigurationProcessor; +import com.google.cloud.tools.jib.plugins.common.UpdateChecker; import com.google.common.annotations.VisibleForTesting; import java.io.IOException; import java.nio.file.Path; +import java.util.concurrent.Executors; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Mojo; @@ -73,6 +76,9 @@ public void execute() throws MojoExecutionException, MojoFailureException { MavenProjectProperties projectProperties = MavenProjectProperties.getForProject( getProject(), getSession(), getLog(), tempDirectoryProvider); + UpdateChecker updateChecker = + UpdateChecker.checkForUpdate( + projectProperties, MojoCommon.VERSION_URL, Executors.newSingleThreadExecutor()); try { PluginConfigurationProcessor.createJibBuildRunnerForDockerDaemonImage( new MavenRawConfiguration(this), @@ -134,6 +140,9 @@ public void execute() throws MojoExecutionException, MojoFailureException { } finally { tempDirectoryProvider.close(); + updateChecker + .finishUpdateCheck() + .ifPresent(s -> projectProperties.log(LogEvent.lifecycle(s))); projectProperties.waitForLoggingThread(); getLog().info(""); } diff --git a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildImageMojo.java b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildImageMojo.java index 98de714f51..deea9b4122 100644 --- a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildImageMojo.java +++ b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildImageMojo.java @@ -19,6 +19,7 @@ import com.google.cloud.tools.jib.api.CacheDirectoryCreationException; import com.google.cloud.tools.jib.api.ImageFormat; import com.google.cloud.tools.jib.api.InvalidImageReferenceException; +import com.google.cloud.tools.jib.api.LogEvent; import com.google.cloud.tools.jib.filesystem.TempDirectoryProvider; import com.google.cloud.tools.jib.plugins.common.BuildStepsExecutionException; import com.google.cloud.tools.jib.plugins.common.HelpfulSuggestions; @@ -31,10 +32,12 @@ import com.google.cloud.tools.jib.plugins.common.InvalidWorkingDirectoryException; import com.google.cloud.tools.jib.plugins.common.MainClassInferenceException; import com.google.cloud.tools.jib.plugins.common.PluginConfigurationProcessor; +import com.google.cloud.tools.jib.plugins.common.UpdateChecker; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Strings; import java.io.IOException; import java.util.Arrays; +import java.util.concurrent.Executors; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Mojo; @@ -87,6 +90,9 @@ public void execute() throws MojoExecutionException, MojoFailureException { MavenProjectProperties projectProperties = MavenProjectProperties.getForProject( getProject(), getSession(), getLog(), tempDirectoryProvider); + UpdateChecker updateChecker = + UpdateChecker.checkForUpdate( + projectProperties, MojoCommon.VERSION_URL, Executors.newSingleThreadExecutor()); try { PluginConfigurationProcessor.createJibBuildRunnerForRegistryImage( new MavenRawConfiguration(this), @@ -148,6 +154,9 @@ public void execute() throws MojoExecutionException, MojoFailureException { } finally { tempDirectoryProvider.close(); + updateChecker + .finishUpdateCheck() + .ifPresent(s -> projectProperties.log(LogEvent.lifecycle(s))); projectProperties.waitForLoggingThread(); getLog().info(""); } diff --git a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildTarMojo.java b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildTarMojo.java index 10ab15b691..562e64bde4 100644 --- a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildTarMojo.java +++ b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildTarMojo.java @@ -18,6 +18,7 @@ import com.google.cloud.tools.jib.api.CacheDirectoryCreationException; import com.google.cloud.tools.jib.api.InvalidImageReferenceException; +import com.google.cloud.tools.jib.api.LogEvent; import com.google.cloud.tools.jib.filesystem.TempDirectoryProvider; import com.google.cloud.tools.jib.plugins.common.BuildStepsExecutionException; import com.google.cloud.tools.jib.plugins.common.HelpfulSuggestions; @@ -30,8 +31,10 @@ import com.google.cloud.tools.jib.plugins.common.InvalidWorkingDirectoryException; import com.google.cloud.tools.jib.plugins.common.MainClassInferenceException; import com.google.cloud.tools.jib.plugins.common.PluginConfigurationProcessor; +import com.google.cloud.tools.jib.plugins.common.UpdateChecker; import com.google.common.annotations.VisibleForTesting; import java.io.IOException; +import java.util.concurrent.Executors; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Mojo; @@ -65,6 +68,9 @@ public void execute() throws MojoExecutionException, MojoFailureException { MavenProjectProperties projectProperties = MavenProjectProperties.getForProject( getProject(), getSession(), getLog(), tempDirectoryProvider); + UpdateChecker updateChecker = + UpdateChecker.checkForUpdate( + projectProperties, MojoCommon.VERSION_URL, Executors.newSingleThreadExecutor()); try { PluginConfigurationProcessor.createJibBuildRunnerForTarImage( new MavenRawConfiguration(this), @@ -126,6 +132,9 @@ public void execute() throws MojoExecutionException, MojoFailureException { } finally { tempDirectoryProvider.close(); + updateChecker + .finishUpdateCheck() + .ifPresent(s -> projectProperties.log(LogEvent.lifecycle(s))); projectProperties.waitForLoggingThread(); getLog().info(""); } diff --git a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java index 77a176abdf..f3ff6ab2ad 100644 --- a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java +++ b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java @@ -16,8 +16,10 @@ package com.google.cloud.tools.jib.plugins.common; +import com.google.cloud.tools.jib.filesystem.XdgDirectories; import com.google.cloud.tools.jib.json.JsonTemplate; import com.google.cloud.tools.jib.json.JsonTemplateMapper; +import com.google.common.annotations.VisibleForTesting; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; @@ -44,20 +46,28 @@ private static class ConfigJsonTemplate implements JsonTemplate { /** * Begins checking for an update in a separate thread. * - * @param currentVersion the current version of Jib in use + * @param projectProperties the {@link ProjectProperties} used to get the current version/check + * for offline mode * @param versionUrl the location to check for the latest version * @param executorService the {@link ExecutorService} * @return a new {@link UpdateChecker} */ public static UpdateChecker checkForUpdate( - String currentVersion, String versionUrl, ExecutorService executorService) { + ProjectProperties projectProperties, String versionUrl, ExecutorService executorService) { return new UpdateChecker( - executorService.submit(() -> performUpdateCheck(currentVersion, versionUrl, CONFIG_DIR))); + executorService.submit( + () -> + performUpdateCheck( + projectProperties.getVersion(), + versionUrl, + XdgDirectories.getConfigHome().resolve("com-google-cloud-tools").resolve("jib"), + projectProperties.isOffline()))); } - private static Optional performUpdateCheck( - String currentVersion, String versionUrl, Path configDir) { - if (Boolean.getBoolean(PropertyNames.DISABLE_UPDATE_CHECKS)) { + @VisibleForTesting + static Optional performUpdateCheck( + String currentVersion, String versionUrl, Path configDir, boolean offline) { + if (offline || Boolean.getBoolean(PropertyNames.DISABLE_UPDATE_CHECKS)) { return Optional.empty(); } @@ -72,6 +82,7 @@ private static Optional performUpdateCheck( } else { ConfigJsonTemplate config = new ConfigJsonTemplate(); config.disableUpdateCheck = true; + Files.createDirectories(configDir); JsonTemplateMapper.writeTo(config, Files.newOutputStream(configFile)); } From 0dbc81f758709cc77a64191b26170f8a31aa8df1 Mon Sep 17 00:00:00 2001 From: "tad.cordle@gmail.com" Date: Mon, 6 Jan 2020 15:31:56 -0500 Subject: [PATCH 04/36] Add unit tests --- .../tools/jib/gradle/BuildDockerTask.java | 5 +- .../tools/jib/gradle/BuildImageTask.java | 5 +- .../cloud/tools/jib/gradle/BuildTarTask.java | 5 +- .../tools/jib/maven/BuildDockerMojo.java | 5 +- .../cloud/tools/jib/maven/BuildImageMojo.java | 5 +- .../cloud/tools/jib/maven/BuildTarMojo.java | 5 +- .../jib/plugins/common/UpdateChecker.java | 45 ++-- .../jib/plugins/common/UpdateCheckerTest.java | 196 ++++++++++++++++++ 8 files changed, 250 insertions(+), 21 deletions(-) create mode 100644 jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java diff --git a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildDockerTask.java b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildDockerTask.java index 03eb98c853..808903a303 100644 --- a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildDockerTask.java +++ b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildDockerTask.java @@ -97,7 +97,10 @@ public void buildDocker() GradleProjectProperties.getForProject(getProject(), getLogger(), tempDirectoryProvider); UpdateChecker updateChecker = UpdateChecker.checkForUpdate( - projectProperties, TaskCommon.VERSION_URL, Executors.newSingleThreadExecutor()); + projectProperties.isOffline() || getLogger().isQuietEnabled(), + projectProperties.getVersion(), + TaskCommon.VERSION_URL, + Executors.newSingleThreadExecutor()); try { PluginConfigurationProcessor.createJibBuildRunnerForDockerDaemonImage( new GradleRawConfiguration(jibExtension), diff --git a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildImageTask.java b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildImageTask.java index d2d3b963f7..91aad78635 100644 --- a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildImageTask.java +++ b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildImageTask.java @@ -86,7 +86,10 @@ public void buildImage() GradleProjectProperties.getForProject(getProject(), getLogger(), tempDirectoryProvider); UpdateChecker updateChecker = UpdateChecker.checkForUpdate( - projectProperties, TaskCommon.VERSION_URL, Executors.newSingleThreadExecutor()); + projectProperties.isOffline() || getLogger().isQuietEnabled(), + projectProperties.getVersion(), + TaskCommon.VERSION_URL, + Executors.newSingleThreadExecutor()); try { if (Strings.isNullOrEmpty(jibExtension.getTo().getImage())) { throw new GradleException( diff --git a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildTarTask.java b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildTarTask.java index 0aed241a87..cfa821f618 100644 --- a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildTarTask.java +++ b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildTarTask.java @@ -111,7 +111,10 @@ public void buildTar() GradleProjectProperties.getForProject(getProject(), getLogger(), tempDirectoryProvider); UpdateChecker updateChecker = UpdateChecker.checkForUpdate( - projectProperties, TaskCommon.VERSION_URL, Executors.newSingleThreadExecutor()); + projectProperties.isOffline() || getLogger().isQuietEnabled(), + projectProperties.getVersion(), + TaskCommon.VERSION_URL, + Executors.newSingleThreadExecutor()); try { PluginConfigurationProcessor.createJibBuildRunnerForTarImage( new GradleRawConfiguration(jibExtension), diff --git a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildDockerMojo.java b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildDockerMojo.java index bd69ed6de1..744affbc7f 100644 --- a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildDockerMojo.java +++ b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildDockerMojo.java @@ -78,7 +78,10 @@ public void execute() throws MojoExecutionException, MojoFailureException { getProject(), getSession(), getLog(), tempDirectoryProvider); UpdateChecker updateChecker = UpdateChecker.checkForUpdate( - projectProperties, MojoCommon.VERSION_URL, Executors.newSingleThreadExecutor()); + projectProperties.isOffline() || !getLog().isInfoEnabled(), + projectProperties.getVersion(), + MojoCommon.VERSION_URL, + Executors.newSingleThreadExecutor()); try { PluginConfigurationProcessor.createJibBuildRunnerForDockerDaemonImage( new MavenRawConfiguration(this), diff --git a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildImageMojo.java b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildImageMojo.java index deea9b4122..8321b44f3d 100644 --- a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildImageMojo.java +++ b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildImageMojo.java @@ -92,7 +92,10 @@ public void execute() throws MojoExecutionException, MojoFailureException { getProject(), getSession(), getLog(), tempDirectoryProvider); UpdateChecker updateChecker = UpdateChecker.checkForUpdate( - projectProperties, MojoCommon.VERSION_URL, Executors.newSingleThreadExecutor()); + projectProperties.isOffline() || !getLog().isInfoEnabled(), + projectProperties.getVersion(), + MojoCommon.VERSION_URL, + Executors.newSingleThreadExecutor()); try { PluginConfigurationProcessor.createJibBuildRunnerForRegistryImage( new MavenRawConfiguration(this), diff --git a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildTarMojo.java b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildTarMojo.java index 562e64bde4..b2afd85063 100644 --- a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildTarMojo.java +++ b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildTarMojo.java @@ -70,7 +70,10 @@ public void execute() throws MojoExecutionException, MojoFailureException { getProject(), getSession(), getLog(), tempDirectoryProvider); UpdateChecker updateChecker = UpdateChecker.checkForUpdate( - projectProperties, MojoCommon.VERSION_URL, Executors.newSingleThreadExecutor()); + projectProperties.isOffline() || !getLog().isInfoEnabled(), + projectProperties.getVersion(), + MojoCommon.VERSION_URL, + Executors.newSingleThreadExecutor()); try { PluginConfigurationProcessor.createJibBuildRunnerForTarImage( new MavenRawConfiguration(this), diff --git a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java index f3ff6ab2ad..112eed361e 100644 --- a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java +++ b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java @@ -25,6 +25,7 @@ import java.io.InputStreamReader; import java.net.URL; import java.net.URLConnection; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.FileTime; @@ -39,71 +40,84 @@ public class UpdateChecker { /** JSON template for the configuration file used to enable/disable update checks. */ - private static class ConfigJsonTemplate implements JsonTemplate { + @VisibleForTesting + static class ConfigJsonTemplate implements JsonTemplate { private boolean disableUpdateCheck; + + @VisibleForTesting + void setDisableUpdateCheck(boolean disableUpdateCheck) { + this.disableUpdateCheck = disableUpdateCheck; + } } /** * Begins checking for an update in a separate thread. * - * @param projectProperties the {@link ProjectProperties} used to get the current version/check - * for offline mode + * @param skip if {@code true}, the update check itself will be skipped + * @param version the current version of Jib being used * @param versionUrl the location to check for the latest version * @param executorService the {@link ExecutorService} * @return a new {@link UpdateChecker} */ public static UpdateChecker checkForUpdate( - ProjectProperties projectProperties, String versionUrl, ExecutorService executorService) { + boolean skip, String version, String versionUrl, ExecutorService executorService) { return new UpdateChecker( executorService.submit( () -> performUpdateCheck( - projectProperties.getVersion(), + skip, + version, versionUrl, - XdgDirectories.getConfigHome().resolve("com-google-cloud-tools").resolve("jib"), - projectProperties.isOffline()))); + XdgDirectories.getConfigHome() + .resolve("com-google-cloud-tools") + .resolve("jib")))); } @VisibleForTesting static Optional performUpdateCheck( - String currentVersion, String versionUrl, Path configDir, boolean offline) { - if (offline || Boolean.getBoolean(PropertyNames.DISABLE_UPDATE_CHECKS)) { + boolean skip, String currentVersion, String versionUrl, Path configDir) { + // Abort if offline or update checks are disabled + if (skip || Boolean.getBoolean(PropertyNames.DISABLE_UPDATE_CHECKS)) { return Optional.empty(); } try { Path configFile = configDir.resolve("config.json"); if (Files.exists(configFile)) { + // Abort of update checks are disabled ConfigJsonTemplate config = JsonTemplateMapper.readJsonFromFile(configFile, ConfigJsonTemplate.class); if (config.disableUpdateCheck) { return Optional.empty(); } } else { + // Generate config file if it doesn't exist ConfigJsonTemplate config = new ConfigJsonTemplate(); - config.disableUpdateCheck = true; Files.createDirectories(configDir); JsonTemplateMapper.writeTo(config, Files.newOutputStream(configFile)); } + // Check time of last update check Path lastUpdateCheck = configDir.resolve("lastUpdateCheck"); if (Files.exists(lastUpdateCheck)) { FileTime modifiedTime = Files.getLastModifiedTime(lastUpdateCheck); if (modifiedTime.toInstant().plus(Duration.ofDays(1)).isAfter(Instant.now())) { return Optional.empty(); } + } else { + Files.createFile(lastUpdateCheck); } + // Check for update URLConnection connection = new URL(versionUrl).openConnection(); BufferedReader bufferedReader = - new BufferedReader(new InputStreamReader(connection.getInputStream())); - String latestVersion = bufferedReader.readLine(); - + new BufferedReader( + new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8)); + String latestVersion = bufferedReader.readLine().trim(); Files.setLastModifiedTime(lastUpdateCheck, FileTime.from(Instant.now())); if (currentVersion.equals(latestVersion)) { return Optional.empty(); } - return Optional.of( "A new version of Jib (" + latestVersion @@ -120,7 +134,8 @@ static Optional performUpdateCheck( private final Future> updateMessageFuture; - private UpdateChecker(Future> updateMessageFuture) { + @VisibleForTesting + UpdateChecker(Future> updateMessageFuture) { this.updateMessageFuture = updateMessageFuture; } diff --git a/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java b/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java new file mode 100644 index 0000000000..c9040be36d --- /dev/null +++ b/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java @@ -0,0 +1,196 @@ +/* + * Copyright 2019 Google LLC. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.cloud.tools.jib.plugins.common; + +import com.google.cloud.tools.jib.http.TestWebServer; +import com.google.cloud.tools.jib.json.JsonTemplateMapper; +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.attribute.FileTime; +import java.security.GeneralSecurityException; +import java.time.Duration; +import java.time.Instant; +import java.util.Collections; +import java.util.Optional; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.contrib.java.lang.system.RestoreSystemProperties; +import org.junit.rules.TemporaryFolder; + +/** Tests for {@link UpdateChecker} */ +public class UpdateCheckerTest { + + @Rule public final RestoreSystemProperties systemPropertyRestorer = new RestoreSystemProperties(); + @Rule public final TemporaryFolder temporaryFolder = new TemporaryFolder(); + + private TestWebServer testWebServer; + private Path configDir; + + @Before + public void setUp() + throws InterruptedException, GeneralSecurityException, URISyntaxException, IOException { + testWebServer = + new TestWebServer( + false, Collections.singletonList("HTTP/1.1 200 OK\nContent-Length:5\n\n2.0.0"), 1); + configDir = temporaryFolder.newFolder().toPath(); + } + + @After + public void tearDown() throws IOException { + testWebServer.close(); + } + + @Test + public void testPerformUpdateCheck_newVersionFound() throws IOException { + Instant before = Instant.now(); + setupConfigAndLastUpdateCheck(); + Optional message = + UpdateChecker.performUpdateCheck(false, "1.0.2", testWebServer.getEndpoint(), configDir); + Assert.assertTrue(message.isPresent()); + Assert.assertEquals( + "A new version of Jib (2.0.0) is available (currently using 1.0.2). Update your build " + + "configuration to use the latest features and fixes!", + message.get()); + Assert.assertTrue( + Files.getLastModifiedTime(configDir.resolve("lastUpdateCheck")) + .toInstant() + .isAfter(before)); + } + + @Test + public void testPerformUpdateCheck_onLatest() throws IOException { + Instant before = Instant.now(); + setupConfigAndLastUpdateCheck(); + Optional message = + UpdateChecker.performUpdateCheck(false, "2.0.0", testWebServer.getEndpoint(), configDir); + Assert.assertFalse(message.isPresent()); + Assert.assertTrue( + Files.getLastModifiedTime(configDir.resolve("lastUpdateCheck")) + .toInstant() + .isAfter(before)); + } + + @Test + public void testPerformUpdateCheck_noConfigOrLastUpdateCheck() throws IOException { + Instant before = Instant.now(); + Optional message = + UpdateChecker.performUpdateCheck(false, "1.0.2", testWebServer.getEndpoint(), configDir); + Assert.assertTrue(message.isPresent()); + Assert.assertEquals( + "A new version of Jib (2.0.0) is available (currently using 1.0.2). Update your build " + + "configuration to use the latest features and fixes!", + message.get()); + Assert.assertTrue( + Files.getLastModifiedTime(configDir.resolve("lastUpdateCheck")) + .toInstant() + .isAfter(before)); + } + + @Test + public void testPerformUpdateCheck_lastUpdateCheckTooSoon() throws IOException { + FileTime modifiedTime = FileTime.from(Instant.now().minusSeconds(12)); + setupConfigAndLastUpdateCheck(); + Files.setLastModifiedTime(configDir.resolve("lastUpdateCheck"), modifiedTime); + Optional message = + UpdateChecker.performUpdateCheck(false, "1.0.2", testWebServer.getEndpoint(), configDir); + Assert.assertFalse(message.isPresent()); + + // lastUpdateCheck should not have changed + Assert.assertEquals( + Files.getLastModifiedTime(configDir.resolve("lastUpdateCheck")), modifiedTime); + } + + @Test + public void testPerformUpdateCheck_skip() { + Optional message = + UpdateChecker.performUpdateCheck(true, "1.0.2", testWebServer.getEndpoint(), configDir); + Assert.assertFalse(message.isPresent()); + } + + @Test + public void testPerformUpdateCheck_systemProperty() { + System.setProperty(PropertyNames.DISABLE_UPDATE_CHECKS, "true"); + Optional message = + UpdateChecker.performUpdateCheck(true, "1.0.2", testWebServer.getEndpoint(), configDir); + Assert.assertFalse(message.isPresent()); + } + + @Test + public void testPerformUpdateCheck_configDisabled() throws IOException { + UpdateChecker.ConfigJsonTemplate config = new UpdateChecker.ConfigJsonTemplate(); + config.setDisableUpdateCheck(true); + JsonTemplateMapper.writeTo(config, Files.newOutputStream(configDir.resolve("config.json"))); + + Optional message = + UpdateChecker.performUpdateCheck(true, "1.0.2", testWebServer.getEndpoint(), configDir); + Assert.assertFalse(message.isPresent()); + } + + @Test + public void testPerformUpdateCheck_failSilently() + throws InterruptedException, GeneralSecurityException, URISyntaxException, IOException { + try (TestWebServer badServer = new TestWebServer(false, Collections.singletonList("bad"), 1)) { + Optional message = + UpdateChecker.performUpdateCheck(true, "1.0.2", badServer.getEndpoint(), configDir); + Assert.assertFalse(message.isPresent()); + } + } + + @Test + public void testFinishUpdateCheck_success() throws InterruptedException { + ExecutorService executorService = Executors.newSingleThreadExecutor(); + UpdateChecker updateChecker = + new UpdateChecker(executorService.submit(() -> Optional.of("Hello"))); + Thread.sleep(100); + Optional result = updateChecker.finishUpdateCheck(); + Assert.assertTrue(result.isPresent()); + Assert.assertEquals("Hello", result.get()); + } + + @Test + public void testFinishUpdateCheck_notDone() { + ExecutorService executorService = Executors.newSingleThreadExecutor(); + UpdateChecker updateChecker = + new UpdateChecker( + executorService.submit( + () -> { + try { + Thread.sleep(100); + } catch (InterruptedException ignored) { + } + return Optional.of("Hello"); + })); + Optional result = updateChecker.finishUpdateCheck(); + Assert.assertFalse(result.isPresent()); + } + + private void setupConfigAndLastUpdateCheck() throws IOException { + UpdateChecker.ConfigJsonTemplate config = new UpdateChecker.ConfigJsonTemplate(); + JsonTemplateMapper.writeTo(config, Files.newOutputStream(configDir.resolve("config.json"))); + Files.createFile(configDir.resolve("lastUpdateCheck")); + Files.setLastModifiedTime( + configDir.resolve("lastUpdateCheck"), + FileTime.from(Instant.now().minus(Duration.ofDays(2)))); + } +} From b80d27234d7254811042cde15e8b87835325619e Mon Sep 17 00:00:00 2001 From: "tad.cordle@gmail.com" Date: Mon, 6 Jan 2020 16:34:50 -0500 Subject: [PATCH 05/36] Travis? --- .../jib/plugins/common/UpdateChecker.java | 18 +++++---- .../jib/plugins/common/UpdateCheckerTest.java | 39 +++++++++++-------- 2 files changed, 33 insertions(+), 24 deletions(-) diff --git a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java index 112eed361e..20773a14c7 100644 --- a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java +++ b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java @@ -28,9 +28,9 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.attribute.FileTime; import java.time.Duration; import java.time.Instant; +import java.time.format.DateTimeParseException; import java.util.Optional; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; @@ -100,12 +100,16 @@ static Optional performUpdateCheck( // Check time of last update check Path lastUpdateCheck = configDir.resolve("lastUpdateCheck"); if (Files.exists(lastUpdateCheck)) { - FileTime modifiedTime = Files.getLastModifiedTime(lastUpdateCheck); - if (modifiedTime.toInstant().plus(Duration.ofDays(1)).isAfter(Instant.now())) { - return Optional.empty(); + String fileContents = + new String(Files.readAllBytes(lastUpdateCheck), StandardCharsets.UTF_8); + try { + Instant modifiedTime = Instant.parse(fileContents); + if (modifiedTime.plus(Duration.ofDays(1)).isAfter(Instant.now())) { + return Optional.empty(); + } + } catch (DateTimeParseException ex) { + // Ignore parse failure; assume update check hasn't been performed } - } else { - Files.createFile(lastUpdateCheck); } // Check for update @@ -114,7 +118,7 @@ static Optional performUpdateCheck( new BufferedReader( new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8)); String latestVersion = bufferedReader.readLine().trim(); - Files.setLastModifiedTime(lastUpdateCheck, FileTime.from(Instant.now())); + Files.write(lastUpdateCheck, Instant.now().toString().getBytes(StandardCharsets.UTF_8)); if (currentVersion.equals(latestVersion)) { return Optional.empty(); } diff --git a/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java b/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java index c9040be36d..4268c3c13d 100644 --- a/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java +++ b/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java @@ -20,6 +20,7 @@ import com.google.cloud.tools.jib.json.JsonTemplateMapper; import java.io.IOException; import java.net.URISyntaxException; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.FileTime; @@ -72,10 +73,10 @@ public void testPerformUpdateCheck_newVersionFound() throws IOException { "A new version of Jib (2.0.0) is available (currently using 1.0.2). Update your build " + "configuration to use the latest features and fixes!", message.get()); - Assert.assertTrue( - Files.getLastModifiedTime(configDir.resolve("lastUpdateCheck")) - .toInstant() - .isAfter(before)); + String modifiedTime = + new String( + Files.readAllBytes(configDir.resolve("lastUpdateCheck")), StandardCharsets.UTF_8); + Assert.assertTrue(Instant.parse(modifiedTime).isAfter(before)); } @Test @@ -85,10 +86,10 @@ public void testPerformUpdateCheck_onLatest() throws IOException { Optional message = UpdateChecker.performUpdateCheck(false, "2.0.0", testWebServer.getEndpoint(), configDir); Assert.assertFalse(message.isPresent()); - Assert.assertTrue( - Files.getLastModifiedTime(configDir.resolve("lastUpdateCheck")) - .toInstant() - .isAfter(before)); + String modifiedTime = + new String( + Files.readAllBytes(configDir.resolve("lastUpdateCheck")), StandardCharsets.UTF_8); + Assert.assertTrue(Instant.parse(modifiedTime).isAfter(before)); } @Test @@ -101,24 +102,29 @@ public void testPerformUpdateCheck_noConfigOrLastUpdateCheck() throws IOExceptio "A new version of Jib (2.0.0) is available (currently using 1.0.2). Update your build " + "configuration to use the latest features and fixes!", message.get()); - Assert.assertTrue( - Files.getLastModifiedTime(configDir.resolve("lastUpdateCheck")) - .toInstant() - .isAfter(before)); + String modifiedTime = + new String( + Files.readAllBytes(configDir.resolve("lastUpdateCheck")), StandardCharsets.UTF_8); + Assert.assertTrue(Instant.parse(modifiedTime).isAfter(before)); } @Test public void testPerformUpdateCheck_lastUpdateCheckTooSoon() throws IOException { FileTime modifiedTime = FileTime.from(Instant.now().minusSeconds(12)); setupConfigAndLastUpdateCheck(); + Files.write( + configDir.resolve("lastUpdateCheck"), + modifiedTime.toString().getBytes(StandardCharsets.UTF_8)); Files.setLastModifiedTime(configDir.resolve("lastUpdateCheck"), modifiedTime); Optional message = UpdateChecker.performUpdateCheck(false, "1.0.2", testWebServer.getEndpoint(), configDir); Assert.assertFalse(message.isPresent()); // lastUpdateCheck should not have changed - Assert.assertEquals( - Files.getLastModifiedTime(configDir.resolve("lastUpdateCheck")), modifiedTime); + String lastUpdateTime = + new String( + Files.readAllBytes(configDir.resolve("lastUpdateCheck")), StandardCharsets.UTF_8); + Assert.assertEquals(Instant.parse(lastUpdateTime), modifiedTime.toInstant()); } @Test @@ -188,9 +194,8 @@ public void testFinishUpdateCheck_notDone() { private void setupConfigAndLastUpdateCheck() throws IOException { UpdateChecker.ConfigJsonTemplate config = new UpdateChecker.ConfigJsonTemplate(); JsonTemplateMapper.writeTo(config, Files.newOutputStream(configDir.resolve("config.json"))); - Files.createFile(configDir.resolve("lastUpdateCheck")); - Files.setLastModifiedTime( + Files.write( configDir.resolve("lastUpdateCheck"), - FileTime.from(Instant.now().minus(Duration.ofDays(2)))); + Instant.now().minus(Duration.ofDays(2)).toString().getBytes(StandardCharsets.UTF_8)); } } From 6f93837068fcf97f28ea2cdea348624d313ef7f4 Mon Sep 17 00:00:00 2001 From: "tad.cordle@gmail.com" Date: Mon, 6 Jan 2020 17:46:01 -0500 Subject: [PATCH 06/36] Update comment --- .../google/cloud/tools/jib/filesystem/XdgDirectories.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/filesystem/XdgDirectories.java b/jib-core/src/main/java/com/google/cloud/tools/jib/filesystem/XdgDirectories.java index 5016dac3fa..ea5d96e940 100644 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/filesystem/XdgDirectories.java +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/filesystem/XdgDirectories.java @@ -33,8 +33,9 @@ *

    *
  • These directories are defined by the environment variables {@code $XDG_CACHE_HOME} and * {@code $XDG_CONFIG_HOME}. - *
  • If {@code $XDG_CACHE_HOME} / {@code $XDG_CONFIG_HOME} is either not set or empty, a default - * equal to {@code $HOME/.cache} / {@code $HOME/.config} should be used. + *
  • If {@code $XDG_CACHE_HOME} / {@code $XDG_CONFIG_HOME} is either not set or empty, a + * platform-specific equivalent of {@code $HOME/.cache} / {@code $HOME/.config} should be + * used. *
* * @see Date: Tue, 7 Jan 2020 13:17:23 -0500 Subject: [PATCH 07/36] Return full path --- .../tools/jib/filesystem/XdgDirectories.java | 55 +++++++++++-------- .../jib/filesystem/XdgDirectoriesTest.java | 24 ++++++-- 2 files changed, 51 insertions(+), 28 deletions(-) diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/filesystem/XdgDirectories.java b/jib-core/src/main/java/com/google/cloud/tools/jib/filesystem/XdgDirectories.java index ea5d96e940..2c0a96e22b 100644 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/filesystem/XdgDirectories.java +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/filesystem/XdgDirectories.java @@ -26,7 +26,7 @@ import java.util.logging.Logger; /** - * Obtains an OS-specific directories based on the XDG Base Directory Specification. + * Obtains OS-specific directories based on the XDG Base Directory Specification. * *

Specifically, from the specification: * @@ -43,7 +43,10 @@ */ public class XdgDirectories { - private static final Logger logger = Logger.getLogger(XdgDirectories.class.getName()); + private static final Logger LOGGER = Logger.getLogger(XdgDirectories.class.getName()); + private static final Path JIB_SUBDIRECTORY_LINUX = + Paths.get("google-cloud-tools-java").resolve("jib"); + private static final Path JIB_SUBDIRECTORY_OTHER = Paths.get("Google").resolve("Jib"); public static Path getCacheHome() { return getCacheHome(System.getProperties(), System.getenv()); @@ -84,12 +87,12 @@ static Path getCacheHome(Properties properties, Map environment) // Use %LOCALAPPDATA% for Windows. String localAppDataEnv = environment.get("LOCALAPPDATA"); if (localAppDataEnv == null || localAppDataEnv.trim().isEmpty()) { - logger.warning("LOCALAPPDATA environment is invalid or missing"); + LOGGER.warning("LOCALAPPDATA environment is invalid or missing"); return xdgPath; } Path localAppData = Paths.get(localAppDataEnv); if (!Files.exists(localAppData)) { - logger.warning(localAppData + " does not exist"); + LOGGER.warning(localAppData + " does not exist"); return xdgPath; } return localAppData; @@ -98,7 +101,7 @@ static Path getCacheHome(Properties properties, Map environment) // Use '~/Library/Application Support/' for macOS. Path applicationSupport = Paths.get(userHome, "Library", "Application Support"); if (!Files.exists(applicationSupport)) { - logger.warning(applicationSupport + " does not exist"); + LOGGER.warning(applicationSupport + " does not exist"); return xdgPath; } return applicationSupport; @@ -108,54 +111,60 @@ static Path getCacheHome(Properties properties, Map environment) } /** - * Returns {@code $XDG_CONFIG_HOME}, if available, or resolves the OS-specific user config home - * based. + * Returns config directory based on {@code $XDG_CONFIG_HOME}, if available, or resolves the + * OS-specific user config directory. * - *

For Linux, this is {@code $HOME/.config/}. + *

For Linux, this is {@code $HOME/.config/google-cloud-tools-java/jib/}. * - *

For Windows, this is {@code %LOCALAPPDATA%}. + *

For Windows, this is {@code %LOCALAPPDATA%/Google/Jib/}. * - *

For macOS, this is {@code $HOME/Library/Preferences/}. + *

For macOS, this is {@code $HOME/Library/Preferences/Google/Jib/}. */ @VisibleForTesting static Path getConfigHome(Properties properties, Map environment) { + Path windowsSubDirectory = JIB_SUBDIRECTORY_OTHER.resolve("Config"); + String rawOsName = properties.getProperty("os.name"); + String osName = rawOsName.toLowerCase(Locale.ENGLISH); + // Use environment variable $XDG_CONFIG_HOME if set and not empty. String xdgConfigHome = environment.get("XDG_CONFIG_HOME"); if (xdgConfigHome != null && !xdgConfigHome.trim().isEmpty()) { - return Paths.get(xdgConfigHome); + if (osName.contains("linux")) { + return Paths.get(xdgConfigHome).resolve(JIB_SUBDIRECTORY_LINUX); + } else if (osName.contains("windows")) { + return Paths.get(xdgConfigHome).resolve(windowsSubDirectory); + } + return Paths.get(xdgConfigHome).resolve(JIB_SUBDIRECTORY_OTHER); } String userHome = properties.getProperty("user.home"); Path xdgPath = Paths.get(userHome, ".config"); - String rawOsName = properties.getProperty("os.name"); - String osName = rawOsName.toLowerCase(Locale.ENGLISH); - if (osName.contains("linux")) { - return xdgPath; + return xdgPath.resolve(JIB_SUBDIRECTORY_LINUX); } else if (osName.contains("windows")) { // Use %LOCALAPPDATA% for Windows. String localAppDataEnv = environment.get("LOCALAPPDATA"); if (localAppDataEnv == null || localAppDataEnv.trim().isEmpty()) { - logger.warning("LOCALAPPDATA environment is invalid or missing"); - return xdgPath; + LOGGER.warning("LOCALAPPDATA environment is invalid or missing"); + return xdgPath.resolve(windowsSubDirectory); } Path localAppData = Paths.get(localAppDataEnv); if (!Files.exists(localAppData)) { - logger.warning(localAppData + " does not exist"); - return xdgPath; + LOGGER.warning(localAppData + " does not exist"); + return xdgPath.resolve(windowsSubDirectory); } - return localAppData; + return localAppData.resolve(windowsSubDirectory); } else if (osName.contains("mac") || osName.contains("darwin")) { // Use '~/Library/Preferences/' for macOS. Path applicationSupport = Paths.get(userHome, "Library", "Preferences"); if (!Files.exists(applicationSupport)) { - logger.warning(applicationSupport + " does not exist"); - return xdgPath; + LOGGER.warning(applicationSupport + " does not exist"); + return xdgPath.resolve(JIB_SUBDIRECTORY_OTHER); } - return applicationSupport; + return applicationSupport.resolve(JIB_SUBDIRECTORY_OTHER); } throw new IllegalStateException("Unknown OS: " + rawOsName); diff --git a/jib-core/src/test/java/com/google/cloud/tools/jib/filesystem/XdgDirectoriesTest.java b/jib-core/src/test/java/com/google/cloud/tools/jib/filesystem/XdgDirectoriesTest.java index d8025b11fb..b4449db737 100644 --- a/jib-core/src/test/java/com/google/cloud/tools/jib/filesystem/XdgDirectoriesTest.java +++ b/jib-core/src/test/java/com/google/cloud/tools/jib/filesystem/XdgDirectoriesTest.java @@ -93,11 +93,24 @@ public void testGetCacheHome_mac() throws IOException { @Test public void testGetConfigHome_hasXdgConfigHome() { + Properties fakeProperties = new Properties(); + fakeProperties.setProperty("user.home", fakeConfigHome); Map fakeEnvironment = ImmutableMap.of("XDG_CONFIG_HOME", fakeConfigHome); + fakeProperties.setProperty("os.name", "linux"); + Assert.assertEquals( + Paths.get(fakeConfigHome).resolve("google-cloud-tools-java").resolve("jib"), + XdgDirectories.getConfigHome(fakeProperties, fakeEnvironment)); + + fakeProperties.setProperty("os.name", "windows"); Assert.assertEquals( - Paths.get(fakeConfigHome), - XdgDirectories.getConfigHome(Mockito.mock(Properties.class), fakeEnvironment)); + Paths.get(fakeConfigHome).resolve("Google").resolve("Jib").resolve("Config"), + XdgDirectories.getConfigHome(fakeProperties, fakeEnvironment)); + + fakeProperties.setProperty("os.name", "mac"); + Assert.assertEquals( + Paths.get(fakeConfigHome).resolve("Google").resolve("Jib"), + XdgDirectories.getConfigHome(fakeProperties, fakeEnvironment)); } @Test @@ -107,7 +120,7 @@ public void testGetConfigHome_linux() { fakeProperties.setProperty("os.name", "os is LiNuX"); Assert.assertEquals( - Paths.get(fakeConfigHome, ".config"), + Paths.get(fakeConfigHome, ".config").resolve("google-cloud-tools-java").resolve("jib"), XdgDirectories.getConfigHome(fakeProperties, Collections.emptyMap())); } @@ -120,7 +133,8 @@ public void testGetConfigHome_windows() { Map fakeEnvironment = ImmutableMap.of("LOCALAPPDATA", fakeConfigHome); Assert.assertEquals( - Paths.get(fakeConfigHome), XdgDirectories.getConfigHome(fakeProperties, fakeEnvironment)); + Paths.get(fakeConfigHome).resolve("Google").resolve("Jib").resolve("Config"), + XdgDirectories.getConfigHome(fakeProperties, fakeEnvironment)); } @Test @@ -133,7 +147,7 @@ public void testGetConfigHome_mac() throws IOException { fakeProperties.setProperty("os.name", "os is mAc or DaRwIn"); Assert.assertEquals( - libraryApplicationSupport, + libraryApplicationSupport.resolve("Google").resolve("Jib"), XdgDirectories.getConfigHome(fakeProperties, Collections.emptyMap())); } } From fefc308ad9d9c4a7608cc5044c731e6eb49cac6e Mon Sep 17 00:00:00 2001 From: "tad.cordle@gmail.com" Date: Tue, 7 Jan 2020 13:19:51 -0500 Subject: [PATCH 08/36] Fix comment --- .../com/google/cloud/tools/jib/filesystem/XdgDirectories.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/filesystem/XdgDirectories.java b/jib-core/src/main/java/com/google/cloud/tools/jib/filesystem/XdgDirectories.java index 2c0a96e22b..ad52dd0d80 100644 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/filesystem/XdgDirectories.java +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/filesystem/XdgDirectories.java @@ -116,7 +116,7 @@ static Path getCacheHome(Properties properties, Map environment) * *

For Linux, this is {@code $HOME/.config/google-cloud-tools-java/jib/}. * - *

For Windows, this is {@code %LOCALAPPDATA%/Google/Jib/}. + *

For Windows, this is {@code %LOCALAPPDATA%\Google\Jib/}. * *

For macOS, this is {@code $HOME/Library/Preferences/Google/Jib/}. */ From 8c75b78fe4f0ad25eb7507ecf31d2f9bfc1ad6dd Mon Sep 17 00:00:00 2001 From: "tad.cordle@gmail.com" Date: Tue, 7 Jan 2020 13:22:48 -0500 Subject: [PATCH 09/36] Reduce diff --- .../cloud/tools/jib/filesystem/XdgDirectories.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/filesystem/XdgDirectories.java b/jib-core/src/main/java/com/google/cloud/tools/jib/filesystem/XdgDirectories.java index ad52dd0d80..86ed5f8632 100644 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/filesystem/XdgDirectories.java +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/filesystem/XdgDirectories.java @@ -43,7 +43,7 @@ */ public class XdgDirectories { - private static final Logger LOGGER = Logger.getLogger(XdgDirectories.class.getName()); + private static final Logger logger = Logger.getLogger(XdgDirectories.class.getName()); private static final Path JIB_SUBDIRECTORY_LINUX = Paths.get("google-cloud-tools-java").resolve("jib"); private static final Path JIB_SUBDIRECTORY_OTHER = Paths.get("Google").resolve("Jib"); @@ -87,12 +87,12 @@ static Path getCacheHome(Properties properties, Map environment) // Use %LOCALAPPDATA% for Windows. String localAppDataEnv = environment.get("LOCALAPPDATA"); if (localAppDataEnv == null || localAppDataEnv.trim().isEmpty()) { - LOGGER.warning("LOCALAPPDATA environment is invalid or missing"); + logger.warning("LOCALAPPDATA environment is invalid or missing"); return xdgPath; } Path localAppData = Paths.get(localAppDataEnv); if (!Files.exists(localAppData)) { - LOGGER.warning(localAppData + " does not exist"); + logger.warning(localAppData + " does not exist"); return xdgPath; } return localAppData; @@ -101,7 +101,7 @@ static Path getCacheHome(Properties properties, Map environment) // Use '~/Library/Application Support/' for macOS. Path applicationSupport = Paths.get(userHome, "Library", "Application Support"); if (!Files.exists(applicationSupport)) { - LOGGER.warning(applicationSupport + " does not exist"); + logger.warning(applicationSupport + " does not exist"); return xdgPath; } return applicationSupport; @@ -147,12 +147,12 @@ static Path getConfigHome(Properties properties, Map environment // Use %LOCALAPPDATA% for Windows. String localAppDataEnv = environment.get("LOCALAPPDATA"); if (localAppDataEnv == null || localAppDataEnv.trim().isEmpty()) { - LOGGER.warning("LOCALAPPDATA environment is invalid or missing"); + logger.warning("LOCALAPPDATA environment is invalid or missing"); return xdgPath.resolve(windowsSubDirectory); } Path localAppData = Paths.get(localAppDataEnv); if (!Files.exists(localAppData)) { - LOGGER.warning(localAppData + " does not exist"); + logger.warning(localAppData + " does not exist"); return xdgPath.resolve(windowsSubDirectory); } return localAppData.resolve(windowsSubDirectory); @@ -161,7 +161,7 @@ static Path getConfigHome(Properties properties, Map environment // Use '~/Library/Preferences/' for macOS. Path applicationSupport = Paths.get(userHome, "Library", "Preferences"); if (!Files.exists(applicationSupport)) { - LOGGER.warning(applicationSupport + " does not exist"); + logger.warning(applicationSupport + " does not exist"); return xdgPath.resolve(JIB_SUBDIRECTORY_OTHER); } return applicationSupport.resolve(JIB_SUBDIRECTORY_OTHER); From 0aed062c9771bd527f8f55476fbee03f68d4218b Mon Sep 17 00:00:00 2001 From: "tad.cordle@gmail.com" Date: Tue, 7 Jan 2020 13:23:54 -0500 Subject: [PATCH 10/36] Nevermind --- .../cloud/tools/jib/filesystem/XdgDirectories.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/filesystem/XdgDirectories.java b/jib-core/src/main/java/com/google/cloud/tools/jib/filesystem/XdgDirectories.java index 86ed5f8632..ad52dd0d80 100644 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/filesystem/XdgDirectories.java +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/filesystem/XdgDirectories.java @@ -43,7 +43,7 @@ */ public class XdgDirectories { - private static final Logger logger = Logger.getLogger(XdgDirectories.class.getName()); + private static final Logger LOGGER = Logger.getLogger(XdgDirectories.class.getName()); private static final Path JIB_SUBDIRECTORY_LINUX = Paths.get("google-cloud-tools-java").resolve("jib"); private static final Path JIB_SUBDIRECTORY_OTHER = Paths.get("Google").resolve("Jib"); @@ -87,12 +87,12 @@ static Path getCacheHome(Properties properties, Map environment) // Use %LOCALAPPDATA% for Windows. String localAppDataEnv = environment.get("LOCALAPPDATA"); if (localAppDataEnv == null || localAppDataEnv.trim().isEmpty()) { - logger.warning("LOCALAPPDATA environment is invalid or missing"); + LOGGER.warning("LOCALAPPDATA environment is invalid or missing"); return xdgPath; } Path localAppData = Paths.get(localAppDataEnv); if (!Files.exists(localAppData)) { - logger.warning(localAppData + " does not exist"); + LOGGER.warning(localAppData + " does not exist"); return xdgPath; } return localAppData; @@ -101,7 +101,7 @@ static Path getCacheHome(Properties properties, Map environment) // Use '~/Library/Application Support/' for macOS. Path applicationSupport = Paths.get(userHome, "Library", "Application Support"); if (!Files.exists(applicationSupport)) { - logger.warning(applicationSupport + " does not exist"); + LOGGER.warning(applicationSupport + " does not exist"); return xdgPath; } return applicationSupport; @@ -147,12 +147,12 @@ static Path getConfigHome(Properties properties, Map environment // Use %LOCALAPPDATA% for Windows. String localAppDataEnv = environment.get("LOCALAPPDATA"); if (localAppDataEnv == null || localAppDataEnv.trim().isEmpty()) { - logger.warning("LOCALAPPDATA environment is invalid or missing"); + LOGGER.warning("LOCALAPPDATA environment is invalid or missing"); return xdgPath.resolve(windowsSubDirectory); } Path localAppData = Paths.get(localAppDataEnv); if (!Files.exists(localAppData)) { - logger.warning(localAppData + " does not exist"); + LOGGER.warning(localAppData + " does not exist"); return xdgPath.resolve(windowsSubDirectory); } return localAppData.resolve(windowsSubDirectory); @@ -161,7 +161,7 @@ static Path getConfigHome(Properties properties, Map environment // Use '~/Library/Preferences/' for macOS. Path applicationSupport = Paths.get(userHome, "Library", "Preferences"); if (!Files.exists(applicationSupport)) { - logger.warning(applicationSupport + " does not exist"); + LOGGER.warning(applicationSupport + " does not exist"); return xdgPath.resolve(JIB_SUBDIRECTORY_OTHER); } return applicationSupport.resolve(JIB_SUBDIRECTORY_OTHER); From ef8ad1e852f9a92e4a69dca25d189895f7ab3a83 Mon Sep 17 00:00:00 2001 From: "tad.cordle@gmail.com" Date: Tue, 7 Jan 2020 14:57:08 -0500 Subject: [PATCH 11/36] Change base image cache directory --- .../cloud/tools/jib/api/Containerizer.java | 3 +-- .../tools/jib/filesystem/XdgDirectories.java | 26 ++++++++++++------- .../jib/filesystem/XdgDirectoriesTest.java | 25 +++++++++++++----- 3 files changed, 36 insertions(+), 18 deletions(-) diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/api/Containerizer.java b/jib-core/src/main/java/com/google/cloud/tools/jib/api/Containerizer.java index cbe596bf68..833295ed5d 100644 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/api/Containerizer.java +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/api/Containerizer.java @@ -44,8 +44,7 @@ public class Containerizer { * The default directory for caching the base image layers, in {@code [user cache * home]/google-cloud-tools-java/jib}. */ - public static final Path DEFAULT_BASE_CACHE_DIRECTORY = - XdgDirectories.getCacheHome().resolve("google-cloud-tools-java").resolve("jib"); + public static final Path DEFAULT_BASE_CACHE_DIRECTORY = XdgDirectories.getCacheHome(); private static final String DEFAULT_TOOL_NAME = "jib-core"; diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/filesystem/XdgDirectories.java b/jib-core/src/main/java/com/google/cloud/tools/jib/filesystem/XdgDirectories.java index ad52dd0d80..980cebb694 100644 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/filesystem/XdgDirectories.java +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/filesystem/XdgDirectories.java @@ -68,43 +68,49 @@ public static Path getConfigHome() { */ @VisibleForTesting static Path getCacheHome(Properties properties, Map environment) { + Path windowsSubDirectory = JIB_SUBDIRECTORY_OTHER.resolve("Cache"); + String rawOsName = properties.getProperty("os.name"); + String osName = rawOsName.toLowerCase(Locale.ENGLISH); + // Use environment variable $XDG_CACHE_HOME if set and not empty. String xdgCacheHome = environment.get("XDG_CACHE_HOME"); if (xdgCacheHome != null && !xdgCacheHome.trim().isEmpty()) { - return Paths.get(xdgCacheHome); + if (osName.contains("linux")) { + return Paths.get(xdgCacheHome).resolve(JIB_SUBDIRECTORY_LINUX); + } else if (osName.contains("windows")) { + return Paths.get(xdgCacheHome).resolve(windowsSubDirectory); + } + return Paths.get(xdgCacheHome).resolve(JIB_SUBDIRECTORY_OTHER); } String userHome = properties.getProperty("user.home"); Path xdgPath = Paths.get(userHome, ".cache"); - String rawOsName = properties.getProperty("os.name"); - String osName = rawOsName.toLowerCase(Locale.ENGLISH); - if (osName.contains("linux")) { - return xdgPath; + return xdgPath.resolve(JIB_SUBDIRECTORY_LINUX); } else if (osName.contains("windows")) { // Use %LOCALAPPDATA% for Windows. String localAppDataEnv = environment.get("LOCALAPPDATA"); if (localAppDataEnv == null || localAppDataEnv.trim().isEmpty()) { LOGGER.warning("LOCALAPPDATA environment is invalid or missing"); - return xdgPath; + return xdgPath.resolve(windowsSubDirectory); } Path localAppData = Paths.get(localAppDataEnv); if (!Files.exists(localAppData)) { LOGGER.warning(localAppData + " does not exist"); - return xdgPath; + return xdgPath.resolve(windowsSubDirectory); } - return localAppData; + return localAppData.resolve(windowsSubDirectory); } else if (osName.contains("mac") || osName.contains("darwin")) { // Use '~/Library/Application Support/' for macOS. Path applicationSupport = Paths.get(userHome, "Library", "Application Support"); if (!Files.exists(applicationSupport)) { LOGGER.warning(applicationSupport + " does not exist"); - return xdgPath; + return xdgPath.resolve(JIB_SUBDIRECTORY_OTHER); } - return applicationSupport; + return applicationSupport.resolve(JIB_SUBDIRECTORY_OTHER); } throw new IllegalStateException("Unknown OS: " + rawOsName); diff --git a/jib-core/src/test/java/com/google/cloud/tools/jib/filesystem/XdgDirectoriesTest.java b/jib-core/src/test/java/com/google/cloud/tools/jib/filesystem/XdgDirectoriesTest.java index b4449db737..e628b6c785 100644 --- a/jib-core/src/test/java/com/google/cloud/tools/jib/filesystem/XdgDirectoriesTest.java +++ b/jib-core/src/test/java/com/google/cloud/tools/jib/filesystem/XdgDirectoriesTest.java @@ -29,7 +29,6 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; -import org.mockito.Mockito; /** Tests for {@link XdgDirectories}. */ public class XdgDirectoriesTest { @@ -47,11 +46,24 @@ public void setUp() throws IOException { @Test public void testGetCacheHome_hasXdgCacheHome() { + Properties fakeProperties = new Properties(); + fakeProperties.setProperty("user.home", fakeCacheHome); Map fakeEnvironment = ImmutableMap.of("XDG_CACHE_HOME", fakeCacheHome); + fakeProperties.setProperty("os.name", "linux"); + Assert.assertEquals( + Paths.get(fakeCacheHome).resolve("google-cloud-tools-java").resolve("jib"), + XdgDirectories.getCacheHome(fakeProperties, fakeEnvironment)); + + fakeProperties.setProperty("os.name", "windows"); Assert.assertEquals( - Paths.get(fakeCacheHome), - XdgDirectories.getCacheHome(Mockito.mock(Properties.class), fakeEnvironment)); + Paths.get(fakeCacheHome).resolve("Google").resolve("Jib").resolve("Cache"), + XdgDirectories.getCacheHome(fakeProperties, fakeEnvironment)); + + fakeProperties.setProperty("os.name", "mac"); + Assert.assertEquals( + Paths.get(fakeCacheHome).resolve("Google").resolve("Jib"), + XdgDirectories.getCacheHome(fakeProperties, fakeEnvironment)); } @Test @@ -61,7 +73,7 @@ public void testGetCacheHome_linux() { fakeProperties.setProperty("os.name", "os is LiNuX"); Assert.assertEquals( - Paths.get(fakeCacheHome, ".cache"), + Paths.get(fakeCacheHome, ".cache").resolve("google-cloud-tools-java").resolve("jib"), XdgDirectories.getCacheHome(fakeProperties, Collections.emptyMap())); } @@ -74,7 +86,8 @@ public void testGetCacheHome_windows() { Map fakeEnvironment = ImmutableMap.of("LOCALAPPDATA", fakeCacheHome); Assert.assertEquals( - Paths.get(fakeCacheHome), XdgDirectories.getCacheHome(fakeProperties, fakeEnvironment)); + Paths.get(fakeCacheHome).resolve("Google").resolve("Jib").resolve("Cache"), + XdgDirectories.getCacheHome(fakeProperties, fakeEnvironment)); } @Test @@ -87,7 +100,7 @@ public void testGetCacheHome_mac() throws IOException { fakeProperties.setProperty("os.name", "os is mAc or DaRwIn"); Assert.assertEquals( - libraryApplicationSupport, + libraryApplicationSupport.resolve("Google").resolve("Jib"), XdgDirectories.getCacheHome(fakeProperties, Collections.emptyMap())); } From 7257f98911d5d41ff1b059c2e50f9d431e7b30fc Mon Sep 17 00:00:00 2001 From: "tad.cordle@gmail.com" Date: Tue, 7 Jan 2020 16:35:50 -0500 Subject: [PATCH 12/36] Share code --- .../tools/jib/filesystem/XdgDirectories.java | 111 ++++++++---------- 1 file changed, 46 insertions(+), 65 deletions(-) diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/filesystem/XdgDirectories.java b/jib-core/src/main/java/com/google/cloud/tools/jib/filesystem/XdgDirectories.java index 980cebb694..b537249867 100644 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/filesystem/XdgDirectories.java +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/filesystem/XdgDirectories.java @@ -60,60 +60,16 @@ public static Path getConfigHome() { * Returns {@code $XDG_CACHE_HOME}, if available, or resolves the OS-specific user cache home * based. * - *

For Linux, this is {@code $HOME/.cache/}. + *

For Linux, this is {@code $HOME/.cache/google-cloud-tools-java/jib/}. * - *

For Windows, this is {@code %LOCALAPPDATA%}. + *

For Windows, this is {@code %LOCALAPPDATA%\Google\Jib\Cache\}. * - *

For macOS, this is {@code $HOME/Library/Application Support/}. + *

For macOS, this is {@code $HOME/Library/Caches/Google/Jib/}. */ @VisibleForTesting static Path getCacheHome(Properties properties, Map environment) { - Path windowsSubDirectory = JIB_SUBDIRECTORY_OTHER.resolve("Cache"); - String rawOsName = properties.getProperty("os.name"); - String osName = rawOsName.toLowerCase(Locale.ENGLISH); - - // Use environment variable $XDG_CACHE_HOME if set and not empty. - String xdgCacheHome = environment.get("XDG_CACHE_HOME"); - if (xdgCacheHome != null && !xdgCacheHome.trim().isEmpty()) { - if (osName.contains("linux")) { - return Paths.get(xdgCacheHome).resolve(JIB_SUBDIRECTORY_LINUX); - } else if (osName.contains("windows")) { - return Paths.get(xdgCacheHome).resolve(windowsSubDirectory); - } - return Paths.get(xdgCacheHome).resolve(JIB_SUBDIRECTORY_OTHER); - } - - String userHome = properties.getProperty("user.home"); - Path xdgPath = Paths.get(userHome, ".cache"); - - if (osName.contains("linux")) { - return xdgPath.resolve(JIB_SUBDIRECTORY_LINUX); - - } else if (osName.contains("windows")) { - // Use %LOCALAPPDATA% for Windows. - String localAppDataEnv = environment.get("LOCALAPPDATA"); - if (localAppDataEnv == null || localAppDataEnv.trim().isEmpty()) { - LOGGER.warning("LOCALAPPDATA environment is invalid or missing"); - return xdgPath.resolve(windowsSubDirectory); - } - Path localAppData = Paths.get(localAppDataEnv); - if (!Files.exists(localAppData)) { - LOGGER.warning(localAppData + " does not exist"); - return xdgPath.resolve(windowsSubDirectory); - } - return localAppData.resolve(windowsSubDirectory); - - } else if (osName.contains("mac") || osName.contains("darwin")) { - // Use '~/Library/Application Support/' for macOS. - Path applicationSupport = Paths.get(userHome, "Library", "Application Support"); - if (!Files.exists(applicationSupport)) { - LOGGER.warning(applicationSupport + " does not exist"); - return xdgPath.resolve(JIB_SUBDIRECTORY_OTHER); - } - return applicationSupport.resolve(JIB_SUBDIRECTORY_OTHER); - } - - throw new IllegalStateException("Unknown OS: " + rawOsName); + return getOsSpecificDirectory( + properties, environment, "XDG_CACHE_HOME", ".cache", "Cache", "Caches"); } /** @@ -122,34 +78,54 @@ static Path getCacheHome(Properties properties, Map environment) * *

For Linux, this is {@code $HOME/.config/google-cloud-tools-java/jib/}. * - *

For Windows, this is {@code %LOCALAPPDATA%\Google\Jib/}. + *

For Windows, this is {@code %LOCALAPPDATA%\Google\Jib\Config\}. * *

For macOS, this is {@code $HOME/Library/Preferences/Google/Jib/}. */ @VisibleForTesting static Path getConfigHome(Properties properties, Map environment) { - Path windowsSubDirectory = JIB_SUBDIRECTORY_OTHER.resolve("Config"); + return getOsSpecificDirectory( + properties, environment, "XDG_CONFIG_HOME", ".config", "Config", "Preferences"); + } + + /** + * Helper method for resolving directories on different operating systems. + * + * @param xdgEnvVariable the name of the environment variable used to resolve the XDG base + * directory + * @param linuxFolder ".config" or ".cache" + * @param windowsFolder "Config" or "Cache" + * @param macFolder "Preferences" or "Caches" + * @return the full path constructed from the given parameters + */ + private static Path getOsSpecificDirectory( + Properties properties, + Map environment, + String xdgEnvVariable, + String linuxFolder, + String windowsFolder, + String macFolder) { + + Path windowsSubDirectory = JIB_SUBDIRECTORY_OTHER.resolve(windowsFolder); String rawOsName = properties.getProperty("os.name"); String osName = rawOsName.toLowerCase(Locale.ENGLISH); - - // Use environment variable $XDG_CONFIG_HOME if set and not empty. - String xdgConfigHome = environment.get("XDG_CONFIG_HOME"); - if (xdgConfigHome != null && !xdgConfigHome.trim().isEmpty()) { - if (osName.contains("linux")) { - return Paths.get(xdgConfigHome).resolve(JIB_SUBDIRECTORY_LINUX); - } else if (osName.contains("windows")) { - return Paths.get(xdgConfigHome).resolve(windowsSubDirectory); - } - return Paths.get(xdgConfigHome).resolve(JIB_SUBDIRECTORY_OTHER); - } - + String xdgConfigHome = environment.get(xdgEnvVariable); String userHome = properties.getProperty("user.home"); - Path xdgPath = Paths.get(userHome, ".config"); + Path xdgPath = Paths.get(userHome, linuxFolder); if (osName.contains("linux")) { + // Use environment variable $XDG_CONFIG_HOME if set and not empty. + if (xdgConfigHome != null && !xdgConfigHome.trim().isEmpty()) { + return Paths.get(xdgConfigHome).resolve(JIB_SUBDIRECTORY_LINUX); + } return xdgPath.resolve(JIB_SUBDIRECTORY_LINUX); } else if (osName.contains("windows")) { + // Use environment variable $XDG_CONFIG_HOME if set and not empty. + if (xdgConfigHome != null && !xdgConfigHome.trim().isEmpty()) { + return Paths.get(xdgConfigHome).resolve(windowsSubDirectory); + } + // Use %LOCALAPPDATA% for Windows. String localAppDataEnv = environment.get("LOCALAPPDATA"); if (localAppDataEnv == null || localAppDataEnv.trim().isEmpty()) { @@ -164,8 +140,13 @@ static Path getConfigHome(Properties properties, Map environment return localAppData.resolve(windowsSubDirectory); } else if (osName.contains("mac") || osName.contains("darwin")) { + // Use environment variable $XDG_CONFIG_HOME if set and not empty. + if (xdgConfigHome != null && !xdgConfigHome.trim().isEmpty()) { + return Paths.get(xdgConfigHome).resolve(JIB_SUBDIRECTORY_OTHER); + } + // Use '~/Library/Preferences/' for macOS. - Path applicationSupport = Paths.get(userHome, "Library", "Preferences"); + Path applicationSupport = Paths.get(userHome, "Library", macFolder); if (!Files.exists(applicationSupport)) { LOGGER.warning(applicationSupport + " does not exist"); return xdgPath.resolve(JIB_SUBDIRECTORY_OTHER); From 594bf738f518969d49c5e288efe9a60f974bde12 Mon Sep 17 00:00:00 2001 From: "tad.cordle@gmail.com" Date: Tue, 7 Jan 2020 16:43:57 -0500 Subject: [PATCH 13/36] Fix test --- .../google/cloud/tools/jib/filesystem/XdgDirectoriesTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jib-core/src/test/java/com/google/cloud/tools/jib/filesystem/XdgDirectoriesTest.java b/jib-core/src/test/java/com/google/cloud/tools/jib/filesystem/XdgDirectoriesTest.java index e628b6c785..a3e23a5b95 100644 --- a/jib-core/src/test/java/com/google/cloud/tools/jib/filesystem/XdgDirectoriesTest.java +++ b/jib-core/src/test/java/com/google/cloud/tools/jib/filesystem/XdgDirectoriesTest.java @@ -92,7 +92,7 @@ public void testGetCacheHome_windows() { @Test public void testGetCacheHome_mac() throws IOException { - Path libraryApplicationSupport = Paths.get(fakeCacheHome, "Library", "Application Support"); + Path libraryApplicationSupport = Paths.get(fakeCacheHome, "Library", "Caches"); Files.createDirectories(libraryApplicationSupport); Properties fakeProperties = new Properties(); From 4fd8727a326712cf5923fde7190c6dba7d97fe56 Mon Sep 17 00:00:00 2001 From: "tad.cordle@gmail.com" Date: Thu, 9 Jan 2020 11:48:02 -0500 Subject: [PATCH 14/36] Feedback --- .../jib/builder/steps/BuildImageStep.java | 2 +- .../tools/jib/filesystem/XdgDirectories.java | 36 +++++++++---------- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/BuildImageStep.java b/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/BuildImageStep.java index b16656917d..f40fb3a634 100644 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/BuildImageStep.java +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/BuildImageStep.java @@ -66,7 +66,7 @@ public Image call() throws LayerPropertyNotFoundException { ContainerConfiguration containerConfiguration = buildContext.getContainerConfiguration(); // Base image layers - baseImageLayers.stream().forEach(imageBuilder::addLayer); + baseImageLayers.forEach(imageBuilder::addLayer); // Passthrough config and count non-empty history entries int nonEmptyLayerCount = 0; diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/filesystem/XdgDirectories.java b/jib-core/src/main/java/com/google/cloud/tools/jib/filesystem/XdgDirectories.java index b537249867..e5267be7b8 100644 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/filesystem/XdgDirectories.java +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/filesystem/XdgDirectories.java @@ -57,8 +57,7 @@ public static Path getConfigHome() { } /** - * Returns {@code $XDG_CACHE_HOME}, if available, or resolves the OS-specific user cache home - * based. + * Returns the default OS-specific cache directory. * *

For Linux, this is {@code $HOME/.cache/google-cloud-tools-java/jib/}. * @@ -73,8 +72,7 @@ static Path getCacheHome(Properties properties, Map environment) } /** - * Returns config directory based on {@code $XDG_CONFIG_HOME}, if available, or resolves the - * OS-specific user config directory. + * Returns the default OS-specific config directory. * *

For Linux, this is {@code $HOME/.config/google-cloud-tools-java/jib/}. * @@ -109,21 +107,21 @@ private static Path getOsSpecificDirectory( Path windowsSubDirectory = JIB_SUBDIRECTORY_OTHER.resolve(windowsFolder); String rawOsName = properties.getProperty("os.name"); String osName = rawOsName.toLowerCase(Locale.ENGLISH); - String xdgConfigHome = environment.get(xdgEnvVariable); + String xdgHome = environment.get(xdgEnvVariable); String userHome = properties.getProperty("user.home"); Path xdgPath = Paths.get(userHome, linuxFolder); if (osName.contains("linux")) { - // Use environment variable $XDG_CONFIG_HOME if set and not empty. - if (xdgConfigHome != null && !xdgConfigHome.trim().isEmpty()) { - return Paths.get(xdgConfigHome).resolve(JIB_SUBDIRECTORY_LINUX); + // Use XDG environment variable if set and not empty. + if (xdgHome != null && !xdgHome.trim().isEmpty()) { + return Paths.get(xdgHome).resolve(JIB_SUBDIRECTORY_LINUX); } return xdgPath.resolve(JIB_SUBDIRECTORY_LINUX); } else if (osName.contains("windows")) { - // Use environment variable $XDG_CONFIG_HOME if set and not empty. - if (xdgConfigHome != null && !xdgConfigHome.trim().isEmpty()) { - return Paths.get(xdgConfigHome).resolve(windowsSubDirectory); + // Use XDG environment variable if set and not empty. + if (xdgHome != null && !xdgHome.trim().isEmpty()) { + return Paths.get(xdgHome).resolve(windowsSubDirectory); } // Use %LOCALAPPDATA% for Windows. @@ -140,18 +138,18 @@ private static Path getOsSpecificDirectory( return localAppData.resolve(windowsSubDirectory); } else if (osName.contains("mac") || osName.contains("darwin")) { - // Use environment variable $XDG_CONFIG_HOME if set and not empty. - if (xdgConfigHome != null && !xdgConfigHome.trim().isEmpty()) { - return Paths.get(xdgConfigHome).resolve(JIB_SUBDIRECTORY_OTHER); + // Use XDG environment variable if set and not empty. + if (xdgHome != null && !xdgHome.trim().isEmpty()) { + return Paths.get(xdgHome).resolve(JIB_SUBDIRECTORY_OTHER); } - // Use '~/Library/Preferences/' for macOS. - Path applicationSupport = Paths.get(userHome, "Library", macFolder); - if (!Files.exists(applicationSupport)) { - LOGGER.warning(applicationSupport + " does not exist"); + // Use '~/Library/...' for macOS. + Path macDirectory = Paths.get(userHome, "Library", macFolder); + if (!Files.exists(macDirectory)) { + LOGGER.warning(macDirectory + " does not exist"); return xdgPath.resolve(JIB_SUBDIRECTORY_OTHER); } - return applicationSupport.resolve(JIB_SUBDIRECTORY_OTHER); + return macDirectory.resolve(JIB_SUBDIRECTORY_OTHER); } throw new IllegalStateException("Unknown OS: " + rawOsName); From dfe86e9d2fdfadde2c786cc54dd2f88e566eb346 Mon Sep 17 00:00:00 2001 From: "tad.cordle@gmail.com" Date: Thu, 9 Jan 2020 12:59:37 -0500 Subject: [PATCH 15/36] Fix directory --- .../cloud/tools/jib/plugins/common/UpdateChecker.java | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java index 20773a14c7..d0f76b960c 100644 --- a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java +++ b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java @@ -63,14 +63,7 @@ public static UpdateChecker checkForUpdate( boolean skip, String version, String versionUrl, ExecutorService executorService) { return new UpdateChecker( executorService.submit( - () -> - performUpdateCheck( - skip, - version, - versionUrl, - XdgDirectories.getConfigHome() - .resolve("com-google-cloud-tools") - .resolve("jib")))); + () -> performUpdateCheck(skip, version, versionUrl, XdgDirectories.getConfigHome()))); } @VisibleForTesting From c7709af8eeb9523ff179bc72a0247599e5a4a495 Mon Sep 17 00:00:00 2001 From: "tad.cordle@gmail.com" Date: Thu, 9 Jan 2020 15:19:52 -0500 Subject: [PATCH 16/36] Add system property for config directory --- .../jib/plugins/common/PropertyNames.java | 1 + .../jib/plugins/common/UpdateChecker.java | 19 ++++++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/PropertyNames.java b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/PropertyNames.java index 3ba75d5c55..e13dd500d4 100644 --- a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/PropertyNames.java +++ b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/PropertyNames.java @@ -62,6 +62,7 @@ public class PropertyNames { public static final String CONTAINERIZE = "jib.containerize"; public static final String ALWAYS_CACHE_BASE_IMAGE = "jib.alwaysCacheBaseImage"; public static final String DISABLE_UPDATE_CHECKS = "jib.disableUpdateChecks"; + public static final String CONFIG_DIRECTORY = "jib.configDirectory"; private PropertyNames() {} } diff --git a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java index d0f76b960c..c750e279b7 100644 --- a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java +++ b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java @@ -20,6 +20,7 @@ import com.google.cloud.tools.jib.json.JsonTemplate; import com.google.cloud.tools.jib.json.JsonTemplateMapper; import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Strings; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; @@ -28,6 +29,7 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; import java.time.Duration; import java.time.Instant; import java.time.format.DateTimeParseException; @@ -63,7 +65,7 @@ public static UpdateChecker checkForUpdate( boolean skip, String version, String versionUrl, ExecutorService executorService) { return new UpdateChecker( executorService.submit( - () -> performUpdateCheck(skip, version, versionUrl, XdgDirectories.getConfigHome()))); + () -> performUpdateCheck(skip, version, versionUrl, getConfigDir()))); } @VisibleForTesting @@ -129,6 +131,21 @@ static Optional performUpdateCheck( return Optional.empty(); } + /** + * Returns the config directory set by {@link PropertyNames#CONFIG_DIRECTORY} if not null, + * otherwise returns the default config directory. + * + * @return the config directory set by {@link PropertyNames#CONFIG_DIRECTORY} if not null, + * otherwise returns the default config directory. + */ + private static Path getConfigDir() { + String configDirProperty = System.getProperty(PropertyNames.CONFIG_DIRECTORY); + if (!Strings.isNullOrEmpty(configDirProperty)) { + return Paths.get(configDirProperty); + } + return XdgDirectories.getConfigHome(); + } + private final Future> updateMessageFuture; @VisibleForTesting From 14fe3f5911e2c013d56529fa2e4d23f3c33f0e2f Mon Sep 17 00:00:00 2001 From: "tad.cordle@gmail.com" Date: Mon, 13 Jan 2020 15:37:26 -0500 Subject: [PATCH 17/36] Fixes and feedback --- .../tools/jib/gradle/BuildDockerTask.java | 10 ++--- .../tools/jib/gradle/BuildImageTask.java | 10 ++--- .../cloud/tools/jib/gradle/BuildTarTask.java | 10 ++--- .../tools/jib/maven/BuildDockerMojo.java | 9 ++-- .../cloud/tools/jib/maven/BuildImageMojo.java | 9 ++-- .../cloud/tools/jib/maven/BuildTarMojo.java | 9 ++-- .../jib/plugins/common/UpdateChecker.java | 38 +++++++++++----- .../jib/plugins/common/UpdateCheckerTest.java | 43 +++++++++---------- 8 files changed, 68 insertions(+), 70 deletions(-) diff --git a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildDockerTask.java b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildDockerTask.java index 808903a303..2b5449db62 100644 --- a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildDockerTask.java +++ b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildDockerTask.java @@ -36,7 +36,6 @@ import com.google.common.base.Preconditions; import java.io.IOException; import java.nio.file.Path; -import java.util.concurrent.Executors; import javax.annotation.Nullable; import org.gradle.api.DefaultTask; import org.gradle.api.GradleException; @@ -97,10 +96,8 @@ public void buildDocker() GradleProjectProperties.getForProject(getProject(), getLogger(), tempDirectoryProvider); UpdateChecker updateChecker = UpdateChecker.checkForUpdate( - projectProperties.isOffline() || getLogger().isQuietEnabled(), - projectProperties.getVersion(), - TaskCommon.VERSION_URL, - Executors.newSingleThreadExecutor()); + projectProperties.isOffline() || !getLogger().isLifecycleEnabled(), + TaskCommon.VERSION_URL); try { PluginConfigurationProcessor.createJibBuildRunnerForDockerDaemonImage( new GradleRawConfiguration(jibExtension), @@ -156,7 +153,8 @@ public void buildDocker() tempDirectoryProvider.close(); updateChecker .finishUpdateCheck() - .ifPresent(s -> projectProperties.log(LogEvent.lifecycle(s))); + .ifPresent( + s -> projectProperties.log(LogEvent.lifecycle("\n\u001B[33m" + s + "\u001B[0m\n"))); projectProperties.waitForLoggingThread(); } } diff --git a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildImageTask.java b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildImageTask.java index 91aad78635..db72f364f4 100644 --- a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildImageTask.java +++ b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildImageTask.java @@ -36,7 +36,6 @@ import com.google.common.base.Strings; import java.io.IOException; import java.util.Optional; -import java.util.concurrent.Executors; import javax.annotation.Nullable; import org.gradle.api.DefaultTask; import org.gradle.api.GradleException; @@ -86,10 +85,8 @@ public void buildImage() GradleProjectProperties.getForProject(getProject(), getLogger(), tempDirectoryProvider); UpdateChecker updateChecker = UpdateChecker.checkForUpdate( - projectProperties.isOffline() || getLogger().isQuietEnabled(), - projectProperties.getVersion(), - TaskCommon.VERSION_URL, - Executors.newSingleThreadExecutor()); + projectProperties.isOffline() || !getLogger().isLifecycleEnabled(), + TaskCommon.VERSION_URL); try { if (Strings.isNullOrEmpty(jibExtension.getTo().getImage())) { throw new GradleException( @@ -154,7 +151,8 @@ public void buildImage() tempDirectoryProvider.close(); updateChecker .finishUpdateCheck() - .ifPresent(s -> projectProperties.log(LogEvent.lifecycle(s))); + .ifPresent( + s -> projectProperties.log(LogEvent.lifecycle("\n\u001B[33m" + s + "\u001B[0m\n"))); projectProperties.waitForLoggingThread(); } } diff --git a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildTarTask.java b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildTarTask.java index cfa821f618..95dbec7a91 100644 --- a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildTarTask.java +++ b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildTarTask.java @@ -37,7 +37,6 @@ import java.nio.file.Path; import java.util.List; import java.util.Optional; -import java.util.concurrent.Executors; import javax.annotation.Nullable; import org.gradle.api.DefaultTask; import org.gradle.api.GradleException; @@ -111,10 +110,8 @@ public void buildTar() GradleProjectProperties.getForProject(getProject(), getLogger(), tempDirectoryProvider); UpdateChecker updateChecker = UpdateChecker.checkForUpdate( - projectProperties.isOffline() || getLogger().isQuietEnabled(), - projectProperties.getVersion(), - TaskCommon.VERSION_URL, - Executors.newSingleThreadExecutor()); + projectProperties.isOffline() || !getLogger().isLifecycleEnabled(), + TaskCommon.VERSION_URL); try { PluginConfigurationProcessor.createJibBuildRunnerForTarImage( new GradleRawConfiguration(jibExtension), @@ -170,7 +167,8 @@ public void buildTar() tempDirectoryProvider.close(); updateChecker .finishUpdateCheck() - .ifPresent(s -> projectProperties.log(LogEvent.lifecycle(s))); + .ifPresent( + s -> projectProperties.log(LogEvent.lifecycle("\n\u001B[33m" + s + "\u001B[0m\n"))); projectProperties.waitForLoggingThread(); } } diff --git a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildDockerMojo.java b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildDockerMojo.java index 744affbc7f..13772b35c0 100644 --- a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildDockerMojo.java +++ b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildDockerMojo.java @@ -36,7 +36,6 @@ import com.google.common.annotations.VisibleForTesting; import java.io.IOException; import java.nio.file.Path; -import java.util.concurrent.Executors; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Mojo; @@ -78,10 +77,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { getProject(), getSession(), getLog(), tempDirectoryProvider); UpdateChecker updateChecker = UpdateChecker.checkForUpdate( - projectProperties.isOffline() || !getLog().isInfoEnabled(), - projectProperties.getVersion(), - MojoCommon.VERSION_URL, - Executors.newSingleThreadExecutor()); + projectProperties.isOffline() || !getLog().isInfoEnabled(), MojoCommon.VERSION_URL); try { PluginConfigurationProcessor.createJibBuildRunnerForDockerDaemonImage( new MavenRawConfiguration(this), @@ -145,7 +141,8 @@ public void execute() throws MojoExecutionException, MojoFailureException { tempDirectoryProvider.close(); updateChecker .finishUpdateCheck() - .ifPresent(s -> projectProperties.log(LogEvent.lifecycle(s))); + .ifPresent( + s -> projectProperties.log(LogEvent.lifecycle("\n\u001B[33m" + s + "\u001B[0m\n"))); projectProperties.waitForLoggingThread(); getLog().info(""); } diff --git a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildImageMojo.java b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildImageMojo.java index 8321b44f3d..40cbf53f77 100644 --- a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildImageMojo.java +++ b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildImageMojo.java @@ -37,7 +37,6 @@ import com.google.common.base.Strings; import java.io.IOException; import java.util.Arrays; -import java.util.concurrent.Executors; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Mojo; @@ -92,10 +91,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { getProject(), getSession(), getLog(), tempDirectoryProvider); UpdateChecker updateChecker = UpdateChecker.checkForUpdate( - projectProperties.isOffline() || !getLog().isInfoEnabled(), - projectProperties.getVersion(), - MojoCommon.VERSION_URL, - Executors.newSingleThreadExecutor()); + projectProperties.isOffline() || !getLog().isInfoEnabled(), MojoCommon.VERSION_URL); try { PluginConfigurationProcessor.createJibBuildRunnerForRegistryImage( new MavenRawConfiguration(this), @@ -159,7 +155,8 @@ public void execute() throws MojoExecutionException, MojoFailureException { tempDirectoryProvider.close(); updateChecker .finishUpdateCheck() - .ifPresent(s -> projectProperties.log(LogEvent.lifecycle(s))); + .ifPresent( + s -> projectProperties.log(LogEvent.lifecycle("\n\u001B[33m" + s + "\u001B[0m\n"))); projectProperties.waitForLoggingThread(); getLog().info(""); } diff --git a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildTarMojo.java b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildTarMojo.java index b2afd85063..d603c0ce76 100644 --- a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildTarMojo.java +++ b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildTarMojo.java @@ -34,7 +34,6 @@ import com.google.cloud.tools.jib.plugins.common.UpdateChecker; import com.google.common.annotations.VisibleForTesting; import java.io.IOException; -import java.util.concurrent.Executors; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Mojo; @@ -70,10 +69,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { getProject(), getSession(), getLog(), tempDirectoryProvider); UpdateChecker updateChecker = UpdateChecker.checkForUpdate( - projectProperties.isOffline() || !getLog().isInfoEnabled(), - projectProperties.getVersion(), - MojoCommon.VERSION_URL, - Executors.newSingleThreadExecutor()); + projectProperties.isOffline() || !getLog().isInfoEnabled(), MojoCommon.VERSION_URL); try { PluginConfigurationProcessor.createJibBuildRunnerForTarImage( new MavenRawConfiguration(this), @@ -137,7 +133,8 @@ public void execute() throws MojoExecutionException, MojoFailureException { tempDirectoryProvider.close(); updateChecker .finishUpdateCheck() - .ifPresent(s -> projectProperties.log(LogEvent.lifecycle(s))); + .ifPresent( + s -> projectProperties.log(LogEvent.lifecycle("\n\u001B[33m" + s + "\u001B[0m\n"))); projectProperties.waitForLoggingThread(); getLog().info(""); } diff --git a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java index c750e279b7..77cfffda83 100644 --- a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java +++ b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java @@ -16,16 +16,18 @@ package com.google.cloud.tools.jib.plugins.common; +import com.google.cloud.tools.jib.ProjectInfo; import com.google.cloud.tools.jib.filesystem.XdgDirectories; import com.google.cloud.tools.jib.json.JsonTemplate; import com.google.cloud.tools.jib.json.JsonTemplateMapper; import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; import com.google.common.base.Strings; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; +import java.net.HttpURLConnection; import java.net.URL; -import java.net.URLConnection; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; @@ -36,6 +38,7 @@ import java.util.Optional; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import java.util.concurrent.Future; /** Checks if Jib is up-to-date. */ @@ -56,16 +59,21 @@ void setDisableUpdateCheck(boolean disableUpdateCheck) { * Begins checking for an update in a separate thread. * * @param skip if {@code true}, the update check itself will be skipped - * @param version the current version of Jib being used * @param versionUrl the location to check for the latest version - * @param executorService the {@link ExecutorService} * @return a new {@link UpdateChecker} */ - public static UpdateChecker checkForUpdate( - boolean skip, String version, String versionUrl, ExecutorService executorService) { - return new UpdateChecker( + public static UpdateChecker checkForUpdate(boolean skip, String versionUrl) { + ExecutorService executorService = Executors.newSingleThreadExecutor(); + Future> messageFuture = executorService.submit( - () -> performUpdateCheck(skip, version, versionUrl, getConfigDir()))); + () -> + performUpdateCheck( + skip, + Preconditions.checkNotNull(ProjectInfo.VERSION), + versionUrl, + getConfigDir())); + executorService.shutdown(); + return new UpdateChecker(messageFuture); } @VisibleForTesting @@ -79,7 +87,7 @@ static Optional performUpdateCheck( try { Path configFile = configDir.resolve("config.json"); if (Files.exists(configFile)) { - // Abort of update checks are disabled + // Abort if update checks are disabled ConfigJsonTemplate config = JsonTemplateMapper.readJsonFromFile(configFile, ConfigJsonTemplate.class); if (config.disableUpdateCheck) { @@ -108,11 +116,14 @@ static Optional performUpdateCheck( } // Check for update - URLConnection connection = new URL(versionUrl).openConnection(); + HttpURLConnection connection = (HttpURLConnection) new URL(versionUrl).openConnection(); + connection.setConnectTimeout(3000); BufferedReader bufferedReader = new BufferedReader( new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8)); String latestVersion = bufferedReader.readLine().trim(); + connection.disconnect(); + Files.write(lastUpdateCheck, Instant.now().toString().getBytes(StandardCharsets.UTF_8)); if (currentVersion.equals(latestVersion)) { return Optional.empty(); @@ -124,8 +135,13 @@ static Optional performUpdateCheck( + currentVersion + "). Update your build configuration to use the latest features and fixes!"); - } catch (IOException ignored) { - // Fail silently + } catch (IOException ex) { + try { + Files.deleteIfExists(configDir.resolve("config.json")); + Files.deleteIfExists(configDir.resolve("lastUpdateCheck")); + } catch (IOException ignored) { + // Fail silently + } } return Optional.empty(); diff --git a/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java b/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java index 4268c3c13d..981bc09cd9 100644 --- a/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java +++ b/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java @@ -17,7 +17,7 @@ package com.google.cloud.tools.jib.plugins.common; import com.google.cloud.tools.jib.http.TestWebServer; -import com.google.cloud.tools.jib.json.JsonTemplateMapper; +import com.google.common.util.concurrent.MoreExecutors; import java.io.IOException; import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; @@ -30,7 +30,7 @@ import java.util.Collections; import java.util.Optional; import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; +import java.util.concurrent.Future; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -38,8 +38,12 @@ import org.junit.Test; import org.junit.contrib.java.lang.system.RestoreSystemProperties; import org.junit.rules.TemporaryFolder; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; /** Tests for {@link UpdateChecker} */ +@RunWith(MockitoJUnitRunner.class) public class UpdateCheckerTest { @Rule public final RestoreSystemProperties systemPropertyRestorer = new RestoreSystemProperties(); @@ -54,7 +58,7 @@ public void setUp() testWebServer = new TestWebServer( false, Collections.singletonList("HTTP/1.1 200 OK\nContent-Length:5\n\n2.0.0"), 1); - configDir = temporaryFolder.newFolder().toPath(); + configDir = temporaryFolder.getRoot().toPath(); } @After @@ -144,10 +148,9 @@ public void testPerformUpdateCheck_systemProperty() { @Test public void testPerformUpdateCheck_configDisabled() throws IOException { - UpdateChecker.ConfigJsonTemplate config = new UpdateChecker.ConfigJsonTemplate(); - config.setDisableUpdateCheck(true); - JsonTemplateMapper.writeTo(config, Files.newOutputStream(configDir.resolve("config.json"))); - + Files.write( + configDir.resolve("config.json"), + "{\"disableUpdateCheck\":true}".getBytes(StandardCharsets.UTF_8)); Optional message = UpdateChecker.performUpdateCheck(true, "1.0.2", testWebServer.getEndpoint(), configDir); Assert.assertFalse(message.isPresent()); @@ -164,11 +167,10 @@ public void testPerformUpdateCheck_failSilently() } @Test - public void testFinishUpdateCheck_success() throws InterruptedException { - ExecutorService executorService = Executors.newSingleThreadExecutor(); + public void testFinishUpdateCheck_success() { + ExecutorService executorService = MoreExecutors.newDirectExecutorService(); UpdateChecker updateChecker = new UpdateChecker(executorService.submit(() -> Optional.of("Hello"))); - Thread.sleep(100); Optional result = updateChecker.finishUpdateCheck(); Assert.assertTrue(result.isPresent()); Assert.assertEquals("Hello", result.get()); @@ -176,24 +178,19 @@ public void testFinishUpdateCheck_success() throws InterruptedException { @Test public void testFinishUpdateCheck_notDone() { - ExecutorService executorService = Executors.newSingleThreadExecutor(); - UpdateChecker updateChecker = - new UpdateChecker( - executorService.submit( - () -> { - try { - Thread.sleep(100); - } catch (InterruptedException ignored) { - } - return Optional.of("Hello"); - })); + @SuppressWarnings("unchecked") + Future> future = (Future>) Mockito.mock(Future.class); + Mockito.when(future.isDone()).thenReturn(false); + + UpdateChecker updateChecker = new UpdateChecker(future); Optional result = updateChecker.finishUpdateCheck(); Assert.assertFalse(result.isPresent()); } private void setupConfigAndLastUpdateCheck() throws IOException { - UpdateChecker.ConfigJsonTemplate config = new UpdateChecker.ConfigJsonTemplate(); - JsonTemplateMapper.writeTo(config, Files.newOutputStream(configDir.resolve("config.json"))); + Files.write( + configDir.resolve("config.json"), + "{\"disableUpdateCheck\":false}".getBytes(StandardCharsets.UTF_8)); Files.write( configDir.resolve("lastUpdateCheck"), Instant.now().minus(Duration.ofDays(2)).toString().getBytes(StandardCharsets.UTF_8)); From 55b0f1d76324201c34944f9ab5417a40a7c8ee45 Mon Sep 17 00:00:00 2001 From: "tad.cordle@gmail.com" Date: Mon, 13 Jan 2020 17:05:19 -0500 Subject: [PATCH 18/36] Comments --- .../tools/jib/gradle/BuildDockerTask.java | 4 +- .../tools/jib/gradle/BuildImageTask.java | 4 +- .../cloud/tools/jib/gradle/BuildTarTask.java | 4 +- .../tools/jib/maven/BuildDockerMojo.java | 4 +- .../cloud/tools/jib/maven/BuildImageMojo.java | 4 +- .../cloud/tools/jib/maven/BuildTarMojo.java | 4 +- .../jib/plugins/common/UpdateChecker.java | 55 ++++++++++--------- .../jib/plugins/common/UpdateCheckerTest.java | 1 - 8 files changed, 47 insertions(+), 33 deletions(-) diff --git a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildDockerTask.java b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildDockerTask.java index 2b5449db62..4b036e19f7 100644 --- a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildDockerTask.java +++ b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildDockerTask.java @@ -154,7 +154,9 @@ public void buildDocker() updateChecker .finishUpdateCheck() .ifPresent( - s -> projectProperties.log(LogEvent.lifecycle("\n\u001B[33m" + s + "\u001B[0m\n"))); + updateMessage -> + projectProperties.log( + LogEvent.lifecycle("\n\u001B[33m" + updateMessage + "\u001B[0m\n"))); projectProperties.waitForLoggingThread(); } } diff --git a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildImageTask.java b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildImageTask.java index db72f364f4..ad7e32163d 100644 --- a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildImageTask.java +++ b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildImageTask.java @@ -152,7 +152,9 @@ public void buildImage() updateChecker .finishUpdateCheck() .ifPresent( - s -> projectProperties.log(LogEvent.lifecycle("\n\u001B[33m" + s + "\u001B[0m\n"))); + updateMessage -> + projectProperties.log( + LogEvent.lifecycle("\n\u001B[33m" + updateMessage + "\u001B[0m\n"))); projectProperties.waitForLoggingThread(); } } diff --git a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildTarTask.java b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildTarTask.java index 95dbec7a91..14bf1822b9 100644 --- a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildTarTask.java +++ b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildTarTask.java @@ -168,7 +168,9 @@ public void buildTar() updateChecker .finishUpdateCheck() .ifPresent( - s -> projectProperties.log(LogEvent.lifecycle("\n\u001B[33m" + s + "\u001B[0m\n"))); + updateMessage -> + projectProperties.log( + LogEvent.lifecycle("\n\u001B[33m" + updateMessage + "\u001B[0m\n"))); projectProperties.waitForLoggingThread(); } } diff --git a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildDockerMojo.java b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildDockerMojo.java index 13772b35c0..926a214867 100644 --- a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildDockerMojo.java +++ b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildDockerMojo.java @@ -142,7 +142,9 @@ public void execute() throws MojoExecutionException, MojoFailureException { updateChecker .finishUpdateCheck() .ifPresent( - s -> projectProperties.log(LogEvent.lifecycle("\n\u001B[33m" + s + "\u001B[0m\n"))); + updateMessage -> + projectProperties.log( + LogEvent.lifecycle("\n\u001B[33m" + updateMessage + "\u001B[0m\n"))); projectProperties.waitForLoggingThread(); getLog().info(""); } diff --git a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildImageMojo.java b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildImageMojo.java index 40cbf53f77..d89f75af96 100644 --- a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildImageMojo.java +++ b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildImageMojo.java @@ -156,7 +156,9 @@ public void execute() throws MojoExecutionException, MojoFailureException { updateChecker .finishUpdateCheck() .ifPresent( - s -> projectProperties.log(LogEvent.lifecycle("\n\u001B[33m" + s + "\u001B[0m\n"))); + updateMessage -> + projectProperties.log( + LogEvent.lifecycle("\n\u001B[33m" + updateMessage + "\u001B[0m\n"))); projectProperties.waitForLoggingThread(); getLog().info(""); } diff --git a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildTarMojo.java b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildTarMojo.java index d603c0ce76..8260fe132e 100644 --- a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildTarMojo.java +++ b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildTarMojo.java @@ -134,7 +134,9 @@ public void execute() throws MojoExecutionException, MojoFailureException { updateChecker .finishUpdateCheck() .ifPresent( - s -> projectProperties.log(LogEvent.lifecycle("\n\u001B[33m" + s + "\u001B[0m\n"))); + updateMessage -> + projectProperties.log( + LogEvent.lifecycle("\n\u001B[33m" + updateMessage + "\u001B[0m\n"))); projectProperties.waitForLoggingThread(); getLog().info(""); } diff --git a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java index 77cfffda83..8c60bb5540 100644 --- a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java +++ b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java @@ -21,11 +21,12 @@ import com.google.cloud.tools.jib.json.JsonTemplate; import com.google.cloud.tools.jib.json.JsonTemplateMapper; import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; import com.google.common.base.Strings; +import com.google.common.base.Verify; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; +import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.nio.charset.StandardCharsets; @@ -68,10 +69,7 @@ public static UpdateChecker checkForUpdate(boolean skip, String versionUrl) { executorService.submit( () -> performUpdateCheck( - skip, - Preconditions.checkNotNull(ProjectInfo.VERSION), - versionUrl, - getConfigDir())); + skip, Verify.verifyNotNull(ProjectInfo.VERSION), versionUrl, getConfigDir())); executorService.shutdown(); return new UpdateChecker(messageFuture); } @@ -84,8 +82,9 @@ static Optional performUpdateCheck( return Optional.empty(); } + Path configFile = configDir.resolve("config.json"); + Path lastUpdateCheck = configDir.resolve("lastUpdateCheck"); try { - Path configFile = configDir.resolve("config.json"); if (Files.exists(configFile)) { // Abort if update checks are disabled ConfigJsonTemplate config = @@ -97,11 +96,12 @@ static Optional performUpdateCheck( // Generate config file if it doesn't exist ConfigJsonTemplate config = new ConfigJsonTemplate(); Files.createDirectories(configDir); - JsonTemplateMapper.writeTo(config, Files.newOutputStream(configFile)); + try (OutputStream outputStream = Files.newOutputStream(configFile)) { + JsonTemplateMapper.writeTo(config, outputStream); + } } // Check time of last update check - Path lastUpdateCheck = configDir.resolve("lastUpdateCheck"); if (Files.exists(lastUpdateCheck)) { String fileContents = new String(Files.readAllBytes(lastUpdateCheck), StandardCharsets.UTF_8); @@ -117,28 +117,31 @@ static Optional performUpdateCheck( // Check for update HttpURLConnection connection = (HttpURLConnection) new URL(versionUrl).openConnection(); - connection.setConnectTimeout(3000); - BufferedReader bufferedReader = - new BufferedReader( - new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8)); - String latestVersion = bufferedReader.readLine().trim(); - connection.disconnect(); - - Files.write(lastUpdateCheck, Instant.now().toString().getBytes(StandardCharsets.UTF_8)); - if (currentVersion.equals(latestVersion)) { - return Optional.empty(); + try { + connection.setConnectTimeout(3000); + BufferedReader bufferedReader = + new BufferedReader( + new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8)); + String latestVersion = bufferedReader.readLine().trim(); + Files.write(lastUpdateCheck, Instant.now().toString().getBytes(StandardCharsets.UTF_8)); + if (currentVersion.equals(latestVersion)) { + return Optional.empty(); + } + return Optional.of( + "A new version of Jib (" + + latestVersion + + ") is available (currently using " + + currentVersion + + "). Update your build configuration to use the latest features and fixes!"); + + } finally { + connection.disconnect(); } - return Optional.of( - "A new version of Jib (" - + latestVersion - + ") is available (currently using " - + currentVersion - + "). Update your build configuration to use the latest features and fixes!"); } catch (IOException ex) { try { - Files.deleteIfExists(configDir.resolve("config.json")); - Files.deleteIfExists(configDir.resolve("lastUpdateCheck")); + Files.deleteIfExists(configFile); + Files.deleteIfExists(lastUpdateCheck); } catch (IOException ignored) { // Fail silently } diff --git a/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java b/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java index 981bc09cd9..4661ab2386 100644 --- a/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java +++ b/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java @@ -119,7 +119,6 @@ public void testPerformUpdateCheck_lastUpdateCheckTooSoon() throws IOException { Files.write( configDir.resolve("lastUpdateCheck"), modifiedTime.toString().getBytes(StandardCharsets.UTF_8)); - Files.setLastModifiedTime(configDir.resolve("lastUpdateCheck"), modifiedTime); Optional message = UpdateChecker.performUpdateCheck(false, "1.0.2", testWebServer.getEndpoint(), configDir); Assert.assertFalse(message.isPresent()); From bb25ca9768f6960807de68c783ce90298b7d8cea Mon Sep 17 00:00:00 2001 From: "tad.cordle@gmail.com" Date: Tue, 14 Jan 2020 11:21:33 -0500 Subject: [PATCH 19/36] Extract 'skip' --- .../tools/jib/gradle/BuildDockerTask.java | 9 ++++--- .../tools/jib/gradle/BuildImageTask.java | 8 +++---- .../cloud/tools/jib/gradle/BuildTarTask.java | 8 +++---- .../cloud/tools/jib/gradle/TaskCommon.java | 12 ++++++++++ .../tools/jib/maven/BuildDockerMojo.java | 8 +++---- .../cloud/tools/jib/maven/BuildImageMojo.java | 8 +++---- .../cloud/tools/jib/maven/BuildTarMojo.java | 8 +++---- .../cloud/tools/jib/maven/MojoCommon.java | 10 ++++++++ .../jib/plugins/common/UpdateChecker.java | 9 ++++--- .../jib/plugins/common/UpdateCheckerTest.java | 24 +++++++------------ 10 files changed, 57 insertions(+), 47 deletions(-) diff --git a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildDockerTask.java b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildDockerTask.java index 4b036e19f7..48f6f705c9 100644 --- a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildDockerTask.java +++ b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildDockerTask.java @@ -36,6 +36,7 @@ import com.google.common.base.Preconditions; import java.io.IOException; import java.nio.file.Path; +import java.util.Optional; import javax.annotation.Nullable; import org.gradle.api.DefaultTask; import org.gradle.api.GradleException; @@ -94,10 +95,8 @@ public void buildDocker() GradleProjectProperties projectProperties = GradleProjectProperties.getForProject(getProject(), getLogger(), tempDirectoryProvider); - UpdateChecker updateChecker = - UpdateChecker.checkForUpdate( - projectProperties.isOffline() || !getLogger().isLifecycleEnabled(), - TaskCommon.VERSION_URL); + Optional updateChecker = + TaskCommon.newUpdateChecker(projectProperties, getLogger()); try { PluginConfigurationProcessor.createJibBuildRunnerForDockerDaemonImage( new GradleRawConfiguration(jibExtension), @@ -152,7 +151,7 @@ public void buildDocker() } finally { tempDirectoryProvider.close(); updateChecker - .finishUpdateCheck() + .flatMap(UpdateChecker::finishUpdateCheck) .ifPresent( updateMessage -> projectProperties.log( diff --git a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildImageTask.java b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildImageTask.java index ad7e32163d..111edf62e9 100644 --- a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildImageTask.java +++ b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildImageTask.java @@ -83,10 +83,8 @@ public void buildImage() GradleProjectProperties projectProperties = GradleProjectProperties.getForProject(getProject(), getLogger(), tempDirectoryProvider); - UpdateChecker updateChecker = - UpdateChecker.checkForUpdate( - projectProperties.isOffline() || !getLogger().isLifecycleEnabled(), - TaskCommon.VERSION_URL); + Optional updateChecker = + TaskCommon.newUpdateChecker(projectProperties, getLogger()); try { if (Strings.isNullOrEmpty(jibExtension.getTo().getImage())) { throw new GradleException( @@ -150,7 +148,7 @@ public void buildImage() } finally { tempDirectoryProvider.close(); updateChecker - .finishUpdateCheck() + .flatMap(UpdateChecker::finishUpdateCheck) .ifPresent( updateMessage -> projectProperties.log( diff --git a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildTarTask.java b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildTarTask.java index 14bf1822b9..719132d6f6 100644 --- a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildTarTask.java +++ b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildTarTask.java @@ -108,10 +108,8 @@ public void buildTar() GradleProjectProperties projectProperties = GradleProjectProperties.getForProject(getProject(), getLogger(), tempDirectoryProvider); - UpdateChecker updateChecker = - UpdateChecker.checkForUpdate( - projectProperties.isOffline() || !getLogger().isLifecycleEnabled(), - TaskCommon.VERSION_URL); + Optional updateChecker = + TaskCommon.newUpdateChecker(projectProperties, getLogger()); try { PluginConfigurationProcessor.createJibBuildRunnerForTarImage( new GradleRawConfiguration(jibExtension), @@ -166,7 +164,7 @@ public void buildTar() } finally { tempDirectoryProvider.close(); updateChecker - .finishUpdateCheck() + .flatMap(UpdateChecker::finishUpdateCheck) .ifPresent( updateMessage -> projectProperties.log( diff --git a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/TaskCommon.java b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/TaskCommon.java index 140bd3ec94..48bc5d3181 100644 --- a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/TaskCommon.java +++ b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/TaskCommon.java @@ -19,13 +19,17 @@ import com.google.api.client.http.HttpTransport; import com.google.cloud.tools.jib.api.AbsoluteUnixPath; import com.google.cloud.tools.jib.api.FilePermissions; +import com.google.cloud.tools.jib.plugins.common.ProjectProperties; +import com.google.cloud.tools.jib.plugins.common.UpdateChecker; import java.util.HashMap; import java.util.Map; +import java.util.Optional; import java.util.logging.Level; import javax.annotation.Nullable; import org.gradle.api.Project; import org.gradle.api.Task; import org.gradle.api.UnknownTaskException; +import org.gradle.api.logging.Logger; import org.gradle.api.plugins.WarPlugin; import org.gradle.api.tasks.TaskProvider; import org.gradle.internal.logging.events.LogEvent; @@ -38,6 +42,14 @@ class TaskCommon { public static final String VERSION_URL = "https://storage.googleapis.com/jib-versions/jib-gradle"; + static Optional newUpdateChecker( + ProjectProperties projectProperties, Logger logger) { + if (projectProperties.isOffline() || !logger.isLifecycleEnabled()) { + return Optional.of(UpdateChecker.checkForUpdate(VERSION_URL)); + } + return Optional.empty(); + } + @Nullable static TaskProvider getWarTaskProvider(Project project) { if (project.getPlugins().hasPlugin(WarPlugin.class)) { diff --git a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildDockerMojo.java b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildDockerMojo.java index 926a214867..8425c49767 100644 --- a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildDockerMojo.java +++ b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildDockerMojo.java @@ -36,6 +36,7 @@ import com.google.common.annotations.VisibleForTesting; import java.io.IOException; import java.nio.file.Path; +import java.util.Optional; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Mojo; @@ -75,9 +76,8 @@ public void execute() throws MojoExecutionException, MojoFailureException { MavenProjectProperties projectProperties = MavenProjectProperties.getForProject( getProject(), getSession(), getLog(), tempDirectoryProvider); - UpdateChecker updateChecker = - UpdateChecker.checkForUpdate( - projectProperties.isOffline() || !getLog().isInfoEnabled(), MojoCommon.VERSION_URL); + Optional updateChecker = + MojoCommon.newUpdateChecker(projectProperties, getLog()); try { PluginConfigurationProcessor.createJibBuildRunnerForDockerDaemonImage( new MavenRawConfiguration(this), @@ -140,7 +140,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { } finally { tempDirectoryProvider.close(); updateChecker - .finishUpdateCheck() + .flatMap(UpdateChecker::finishUpdateCheck) .ifPresent( updateMessage -> projectProperties.log( diff --git a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildImageMojo.java b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildImageMojo.java index d89f75af96..049419fcb7 100644 --- a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildImageMojo.java +++ b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildImageMojo.java @@ -37,6 +37,7 @@ import com.google.common.base.Strings; import java.io.IOException; import java.util.Arrays; +import java.util.Optional; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Mojo; @@ -89,9 +90,8 @@ public void execute() throws MojoExecutionException, MojoFailureException { MavenProjectProperties projectProperties = MavenProjectProperties.getForProject( getProject(), getSession(), getLog(), tempDirectoryProvider); - UpdateChecker updateChecker = - UpdateChecker.checkForUpdate( - projectProperties.isOffline() || !getLog().isInfoEnabled(), MojoCommon.VERSION_URL); + Optional updateChecker = + MojoCommon.newUpdateChecker(projectProperties, getLog()); try { PluginConfigurationProcessor.createJibBuildRunnerForRegistryImage( new MavenRawConfiguration(this), @@ -154,7 +154,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { } finally { tempDirectoryProvider.close(); updateChecker - .finishUpdateCheck() + .flatMap(UpdateChecker::finishUpdateCheck) .ifPresent( updateMessage -> projectProperties.log( diff --git a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildTarMojo.java b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildTarMojo.java index 8260fe132e..5a8ff15f6b 100644 --- a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildTarMojo.java +++ b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildTarMojo.java @@ -34,6 +34,7 @@ import com.google.cloud.tools.jib.plugins.common.UpdateChecker; import com.google.common.annotations.VisibleForTesting; import java.io.IOException; +import java.util.Optional; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Mojo; @@ -67,9 +68,8 @@ public void execute() throws MojoExecutionException, MojoFailureException { MavenProjectProperties projectProperties = MavenProjectProperties.getForProject( getProject(), getSession(), getLog(), tempDirectoryProvider); - UpdateChecker updateChecker = - UpdateChecker.checkForUpdate( - projectProperties.isOffline() || !getLog().isInfoEnabled(), MojoCommon.VERSION_URL); + Optional updateChecker = + MojoCommon.newUpdateChecker(projectProperties, getLog()); try { PluginConfigurationProcessor.createJibBuildRunnerForTarImage( new MavenRawConfiguration(this), @@ -132,7 +132,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { } finally { tempDirectoryProvider.close(); updateChecker - .finishUpdateCheck() + .flatMap(UpdateChecker::finishUpdateCheck) .ifPresent( updateMessage -> projectProperties.log( diff --git a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/MojoCommon.java b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/MojoCommon.java index d233c3a1f7..dc68d17dfe 100644 --- a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/MojoCommon.java +++ b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/MojoCommon.java @@ -19,7 +19,9 @@ import com.google.cloud.tools.jib.api.AbsoluteUnixPath; import com.google.cloud.tools.jib.api.FilePermissions; import com.google.cloud.tools.jib.maven.JibPluginConfiguration.PermissionConfiguration; +import com.google.cloud.tools.jib.plugins.common.ProjectProperties; import com.google.cloud.tools.jib.plugins.common.PropertyNames; +import com.google.cloud.tools.jib.plugins.common.UpdateChecker; import com.google.cloud.tools.jib.plugins.common.VersionChecker; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; @@ -28,6 +30,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import org.apache.maven.artifact.versioning.DefaultArtifactVersion; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.descriptor.PluginDescriptor; @@ -42,6 +45,13 @@ public class MojoCommon { public static final String VERSION_URL = "https://storage.googleapis.com/jib-versions/jib-maven"; + static Optional newUpdateChecker(ProjectProperties projectProperties, Log logger) { + if (projectProperties.isOffline() || !logger.isInfoEnabled()) { + return Optional.of(UpdateChecker.checkForUpdate(VERSION_URL)); + } + return Optional.empty(); + } + /** * Gets the list of extra directory paths from a {@link JibPluginConfiguration}. Returns {@code * (project dir)/src/main/jib} by default if not configured. diff --git a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java index 8c60bb5540..c238713ef7 100644 --- a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java +++ b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java @@ -59,26 +59,25 @@ void setDisableUpdateCheck(boolean disableUpdateCheck) { /** * Begins checking for an update in a separate thread. * - * @param skip if {@code true}, the update check itself will be skipped * @param versionUrl the location to check for the latest version * @return a new {@link UpdateChecker} */ - public static UpdateChecker checkForUpdate(boolean skip, String versionUrl) { + public static UpdateChecker checkForUpdate(String versionUrl) { ExecutorService executorService = Executors.newSingleThreadExecutor(); Future> messageFuture = executorService.submit( () -> performUpdateCheck( - skip, Verify.verifyNotNull(ProjectInfo.VERSION), versionUrl, getConfigDir())); + Verify.verifyNotNull(ProjectInfo.VERSION), versionUrl, getConfigDir())); executorService.shutdown(); return new UpdateChecker(messageFuture); } @VisibleForTesting static Optional performUpdateCheck( - boolean skip, String currentVersion, String versionUrl, Path configDir) { + String currentVersion, String versionUrl, Path configDir) { // Abort if offline or update checks are disabled - if (skip || Boolean.getBoolean(PropertyNames.DISABLE_UPDATE_CHECKS)) { + if (Boolean.getBoolean(PropertyNames.DISABLE_UPDATE_CHECKS)) { return Optional.empty(); } diff --git a/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java b/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java index 4661ab2386..e1c0b8689d 100644 --- a/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java +++ b/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java @@ -71,7 +71,7 @@ public void testPerformUpdateCheck_newVersionFound() throws IOException { Instant before = Instant.now(); setupConfigAndLastUpdateCheck(); Optional message = - UpdateChecker.performUpdateCheck(false, "1.0.2", testWebServer.getEndpoint(), configDir); + UpdateChecker.performUpdateCheck("1.0.2", testWebServer.getEndpoint(), configDir); Assert.assertTrue(message.isPresent()); Assert.assertEquals( "A new version of Jib (2.0.0) is available (currently using 1.0.2). Update your build " @@ -88,7 +88,7 @@ public void testPerformUpdateCheck_onLatest() throws IOException { Instant before = Instant.now(); setupConfigAndLastUpdateCheck(); Optional message = - UpdateChecker.performUpdateCheck(false, "2.0.0", testWebServer.getEndpoint(), configDir); + UpdateChecker.performUpdateCheck("2.0.0", testWebServer.getEndpoint(), configDir); Assert.assertFalse(message.isPresent()); String modifiedTime = new String( @@ -100,7 +100,7 @@ public void testPerformUpdateCheck_onLatest() throws IOException { public void testPerformUpdateCheck_noConfigOrLastUpdateCheck() throws IOException { Instant before = Instant.now(); Optional message = - UpdateChecker.performUpdateCheck(false, "1.0.2", testWebServer.getEndpoint(), configDir); + UpdateChecker.performUpdateCheck("1.0.2", testWebServer.getEndpoint(), configDir); Assert.assertTrue(message.isPresent()); Assert.assertEquals( "A new version of Jib (2.0.0) is available (currently using 1.0.2). Update your build " @@ -120,7 +120,7 @@ public void testPerformUpdateCheck_lastUpdateCheckTooSoon() throws IOException { configDir.resolve("lastUpdateCheck"), modifiedTime.toString().getBytes(StandardCharsets.UTF_8)); Optional message = - UpdateChecker.performUpdateCheck(false, "1.0.2", testWebServer.getEndpoint(), configDir); + UpdateChecker.performUpdateCheck("1.0.2", testWebServer.getEndpoint(), configDir); Assert.assertFalse(message.isPresent()); // lastUpdateCheck should not have changed @@ -130,18 +130,11 @@ public void testPerformUpdateCheck_lastUpdateCheckTooSoon() throws IOException { Assert.assertEquals(Instant.parse(lastUpdateTime), modifiedTime.toInstant()); } - @Test - public void testPerformUpdateCheck_skip() { - Optional message = - UpdateChecker.performUpdateCheck(true, "1.0.2", testWebServer.getEndpoint(), configDir); - Assert.assertFalse(message.isPresent()); - } - @Test public void testPerformUpdateCheck_systemProperty() { System.setProperty(PropertyNames.DISABLE_UPDATE_CHECKS, "true"); Optional message = - UpdateChecker.performUpdateCheck(true, "1.0.2", testWebServer.getEndpoint(), configDir); + UpdateChecker.performUpdateCheck("1.0.2", testWebServer.getEndpoint(), configDir); Assert.assertFalse(message.isPresent()); } @@ -151,16 +144,17 @@ public void testPerformUpdateCheck_configDisabled() throws IOException { configDir.resolve("config.json"), "{\"disableUpdateCheck\":true}".getBytes(StandardCharsets.UTF_8)); Optional message = - UpdateChecker.performUpdateCheck(true, "1.0.2", testWebServer.getEndpoint(), configDir); + UpdateChecker.performUpdateCheck("1.0.2", testWebServer.getEndpoint(), configDir); Assert.assertFalse(message.isPresent()); } @Test public void testPerformUpdateCheck_failSilently() throws InterruptedException, GeneralSecurityException, URISyntaxException, IOException { - try (TestWebServer badServer = new TestWebServer(false, Collections.singletonList("bad"), 1)) { + try (TestWebServer badServer = + new TestWebServer(false, Collections.singletonList("HTTP/1.1 400 Bad Request\n\n"), 1)) { Optional message = - UpdateChecker.performUpdateCheck(true, "1.0.2", badServer.getEndpoint(), configDir); + UpdateChecker.performUpdateCheck("1.0.2", badServer.getEndpoint(), configDir); Assert.assertFalse(message.isPresent()); } } From 789defa56482019432632f6bc98aa4baaffbbf0b Mon Sep 17 00:00:00 2001 From: "tad.cordle@gmail.com" Date: Tue, 14 Jan 2020 15:00:02 -0500 Subject: [PATCH 20/36] Fix reversed logic --- .../main/java/com/google/cloud/tools/jib/gradle/TaskCommon.java | 2 +- .../main/java/com/google/cloud/tools/jib/maven/MojoCommon.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/TaskCommon.java b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/TaskCommon.java index 48bc5d3181..280cb883be 100644 --- a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/TaskCommon.java +++ b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/TaskCommon.java @@ -44,7 +44,7 @@ class TaskCommon { static Optional newUpdateChecker( ProjectProperties projectProperties, Logger logger) { - if (projectProperties.isOffline() || !logger.isLifecycleEnabled()) { + if (!projectProperties.isOffline() && logger.isLifecycleEnabled()) { return Optional.of(UpdateChecker.checkForUpdate(VERSION_URL)); } return Optional.empty(); diff --git a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/MojoCommon.java b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/MojoCommon.java index dc68d17dfe..f4022d1c1d 100644 --- a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/MojoCommon.java +++ b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/MojoCommon.java @@ -46,7 +46,7 @@ public class MojoCommon { public static final String VERSION_URL = "https://storage.googleapis.com/jib-versions/jib-maven"; static Optional newUpdateChecker(ProjectProperties projectProperties, Log logger) { - if (projectProperties.isOffline() || !logger.isInfoEnabled()) { + if (!projectProperties.isOffline() && logger.isInfoEnabled()) { return Optional.of(UpdateChecker.checkForUpdate(VERSION_URL)); } return Optional.empty(); From 3a7ab0f9d2bc873ddfadb11ee1cfcde66523a57b Mon Sep 17 00:00:00 2001 From: "tad.cordle@gmail.com" Date: Wed, 15 Jan 2020 11:18:37 -0500 Subject: [PATCH 21/36] Improve maven formatting --- .../cloud/tools/jib/maven/BuildDockerMojo.java | 8 +------- .../cloud/tools/jib/maven/BuildImageMojo.java | 8 +------- .../google/cloud/tools/jib/maven/BuildTarMojo.java | 8 +------- .../google/cloud/tools/jib/maven/MojoCommon.java | 13 +++++++++++++ 4 files changed, 16 insertions(+), 21 deletions(-) diff --git a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildDockerMojo.java b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildDockerMojo.java index 8425c49767..1ec56d2b79 100644 --- a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildDockerMojo.java +++ b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildDockerMojo.java @@ -18,7 +18,6 @@ import com.google.cloud.tools.jib.api.CacheDirectoryCreationException; import com.google.cloud.tools.jib.api.InvalidImageReferenceException; -import com.google.cloud.tools.jib.api.LogEvent; import com.google.cloud.tools.jib.docker.DockerClient; import com.google.cloud.tools.jib.filesystem.TempDirectoryProvider; import com.google.cloud.tools.jib.plugins.common.BuildStepsExecutionException; @@ -139,12 +138,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { } finally { tempDirectoryProvider.close(); - updateChecker - .flatMap(UpdateChecker::finishUpdateCheck) - .ifPresent( - updateMessage -> - projectProperties.log( - LogEvent.lifecycle("\n\u001B[33m" + updateMessage + "\u001B[0m\n"))); + MojoCommon.finishUpdateChecker(projectProperties, updateChecker); projectProperties.waitForLoggingThread(); getLog().info(""); } diff --git a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildImageMojo.java b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildImageMojo.java index 049419fcb7..c8789bd0bb 100644 --- a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildImageMojo.java +++ b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildImageMojo.java @@ -19,7 +19,6 @@ import com.google.cloud.tools.jib.api.CacheDirectoryCreationException; import com.google.cloud.tools.jib.api.ImageFormat; import com.google.cloud.tools.jib.api.InvalidImageReferenceException; -import com.google.cloud.tools.jib.api.LogEvent; import com.google.cloud.tools.jib.filesystem.TempDirectoryProvider; import com.google.cloud.tools.jib.plugins.common.BuildStepsExecutionException; import com.google.cloud.tools.jib.plugins.common.HelpfulSuggestions; @@ -153,12 +152,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { } finally { tempDirectoryProvider.close(); - updateChecker - .flatMap(UpdateChecker::finishUpdateCheck) - .ifPresent( - updateMessage -> - projectProperties.log( - LogEvent.lifecycle("\n\u001B[33m" + updateMessage + "\u001B[0m\n"))); + MojoCommon.finishUpdateChecker(projectProperties, updateChecker); projectProperties.waitForLoggingThread(); getLog().info(""); } diff --git a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildTarMojo.java b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildTarMojo.java index 5a8ff15f6b..e6bb5f6e23 100644 --- a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildTarMojo.java +++ b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildTarMojo.java @@ -18,7 +18,6 @@ import com.google.cloud.tools.jib.api.CacheDirectoryCreationException; import com.google.cloud.tools.jib.api.InvalidImageReferenceException; -import com.google.cloud.tools.jib.api.LogEvent; import com.google.cloud.tools.jib.filesystem.TempDirectoryProvider; import com.google.cloud.tools.jib.plugins.common.BuildStepsExecutionException; import com.google.cloud.tools.jib.plugins.common.HelpfulSuggestions; @@ -131,12 +130,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { } finally { tempDirectoryProvider.close(); - updateChecker - .flatMap(UpdateChecker::finishUpdateCheck) - .ifPresent( - updateMessage -> - projectProperties.log( - LogEvent.lifecycle("\n\u001B[33m" + updateMessage + "\u001B[0m\n"))); + MojoCommon.finishUpdateChecker(projectProperties, updateChecker); projectProperties.waitForLoggingThread(); getLog().info(""); } diff --git a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/MojoCommon.java b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/MojoCommon.java index f4022d1c1d..fe789b28f1 100644 --- a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/MojoCommon.java +++ b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/MojoCommon.java @@ -18,6 +18,7 @@ import com.google.cloud.tools.jib.api.AbsoluteUnixPath; import com.google.cloud.tools.jib.api.FilePermissions; +import com.google.cloud.tools.jib.api.LogEvent; import com.google.cloud.tools.jib.maven.JibPluginConfiguration.PermissionConfiguration; import com.google.cloud.tools.jib.plugins.common.ProjectProperties; import com.google.cloud.tools.jib.plugins.common.PropertyNames; @@ -52,6 +53,18 @@ static Optional newUpdateChecker(ProjectProperties projectPropert return Optional.empty(); } + static void finishUpdateChecker( + ProjectProperties projectProperties, Optional updateChecker) { + updateChecker + .flatMap(UpdateChecker::finishUpdateCheck) + .ifPresent( + updateMessage -> { + projectProperties.log(LogEvent.lifecycle("")); + projectProperties.log(LogEvent.lifecycle("\u001B[33m" + updateMessage + "\u001B[0m")); + projectProperties.log(LogEvent.lifecycle("")); + }); + } + /** * Gets the list of extra directory paths from a {@link JibPluginConfiguration}. Returns {@code * (project dir)/src/main/jib} by default if not configured. From 9aa3c32929106d6c7cb9112b052573f572daa9da Mon Sep 17 00:00:00 2001 From: "tad.cordle@gmail.com" Date: Wed, 15 Jan 2020 11:24:56 -0500 Subject: [PATCH 22/36] Share gradle code --- .../cloud/tools/jib/gradle/BuildDockerTask.java | 8 +------- .../google/cloud/tools/jib/gradle/BuildImageTask.java | 8 +------- .../google/cloud/tools/jib/gradle/BuildTarTask.java | 8 +------- .../com/google/cloud/tools/jib/gradle/TaskCommon.java | 11 +++++++++++ 4 files changed, 14 insertions(+), 21 deletions(-) diff --git a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildDockerTask.java b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildDockerTask.java index 48f6f705c9..f9ca63a67b 100644 --- a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildDockerTask.java +++ b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildDockerTask.java @@ -18,7 +18,6 @@ import com.google.cloud.tools.jib.api.CacheDirectoryCreationException; import com.google.cloud.tools.jib.api.InvalidImageReferenceException; -import com.google.cloud.tools.jib.api.LogEvent; import com.google.cloud.tools.jib.docker.DockerClient; import com.google.cloud.tools.jib.filesystem.TempDirectoryProvider; import com.google.cloud.tools.jib.plugins.common.BuildStepsExecutionException; @@ -150,12 +149,7 @@ public void buildDocker() } finally { tempDirectoryProvider.close(); - updateChecker - .flatMap(UpdateChecker::finishUpdateCheck) - .ifPresent( - updateMessage -> - projectProperties.log( - LogEvent.lifecycle("\n\u001B[33m" + updateMessage + "\u001B[0m\n"))); + TaskCommon.finishUpdateChecker(projectProperties, updateChecker); projectProperties.waitForLoggingThread(); } } diff --git a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildImageTask.java b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildImageTask.java index 111edf62e9..3c6e73c84e 100644 --- a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildImageTask.java +++ b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildImageTask.java @@ -18,7 +18,6 @@ import com.google.cloud.tools.jib.api.CacheDirectoryCreationException; import com.google.cloud.tools.jib.api.InvalidImageReferenceException; -import com.google.cloud.tools.jib.api.LogEvent; import com.google.cloud.tools.jib.filesystem.TempDirectoryProvider; import com.google.cloud.tools.jib.plugins.common.BuildStepsExecutionException; import com.google.cloud.tools.jib.plugins.common.HelpfulSuggestions; @@ -147,12 +146,7 @@ public void buildImage() } finally { tempDirectoryProvider.close(); - updateChecker - .flatMap(UpdateChecker::finishUpdateCheck) - .ifPresent( - updateMessage -> - projectProperties.log( - LogEvent.lifecycle("\n\u001B[33m" + updateMessage + "\u001B[0m\n"))); + TaskCommon.finishUpdateChecker(projectProperties, updateChecker); projectProperties.waitForLoggingThread(); } } diff --git a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildTarTask.java b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildTarTask.java index 719132d6f6..f9b7d00408 100644 --- a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildTarTask.java +++ b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildTarTask.java @@ -18,7 +18,6 @@ import com.google.cloud.tools.jib.api.CacheDirectoryCreationException; import com.google.cloud.tools.jib.api.InvalidImageReferenceException; -import com.google.cloud.tools.jib.api.LogEvent; import com.google.cloud.tools.jib.filesystem.TempDirectoryProvider; import com.google.cloud.tools.jib.plugins.common.BuildStepsExecutionException; import com.google.cloud.tools.jib.plugins.common.HelpfulSuggestions; @@ -163,12 +162,7 @@ public void buildTar() } finally { tempDirectoryProvider.close(); - updateChecker - .flatMap(UpdateChecker::finishUpdateCheck) - .ifPresent( - updateMessage -> - projectProperties.log( - LogEvent.lifecycle("\n\u001B[33m" + updateMessage + "\u001B[0m\n"))); + TaskCommon.finishUpdateChecker(projectProperties, updateChecker); projectProperties.waitForLoggingThread(); } } diff --git a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/TaskCommon.java b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/TaskCommon.java index 280cb883be..cef9f15240 100644 --- a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/TaskCommon.java +++ b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/TaskCommon.java @@ -50,6 +50,17 @@ static Optional newUpdateChecker( return Optional.empty(); } + static void finishUpdateChecker( + ProjectProperties projectProperties, Optional updateChecker) { + updateChecker + .flatMap(UpdateChecker::finishUpdateCheck) + .ifPresent( + updateMessage -> + projectProperties.log( + com.google.cloud.tools.jib.api.LogEvent.lifecycle( + "\n\u001B[33m" + updateMessage + "\u001B[0m\n"))); + } + @Nullable static TaskProvider getWarTaskProvider(Project project) { if (project.getPlugins().hasPlugin(WarPlugin.class)) { From 746d7f40aec8f286b7b9cffa8e132459f560e777 Mon Sep 17 00:00:00 2001 From: "tad.cordle@gmail.com" Date: Wed, 15 Jan 2020 15:06:27 -0500 Subject: [PATCH 23/36] More explicit error handling --- .../cloud/tools/jib/gradle/TaskCommon.java | 11 ++--- .../cloud/tools/jib/maven/MojoCommon.java | 3 +- .../jib/plugins/common/UpdateChecker.java | 45 ++++++++++++------- .../jib/plugins/common/UpdateCheckerTest.java | 14 +++--- 4 files changed, 43 insertions(+), 30 deletions(-) diff --git a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/TaskCommon.java b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/TaskCommon.java index cef9f15240..9367988a45 100644 --- a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/TaskCommon.java +++ b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/TaskCommon.java @@ -19,6 +19,7 @@ import com.google.api.client.http.HttpTransport; import com.google.cloud.tools.jib.api.AbsoluteUnixPath; import com.google.cloud.tools.jib.api.FilePermissions; +import com.google.cloud.tools.jib.api.LogEvent; import com.google.cloud.tools.jib.plugins.common.ProjectProperties; import com.google.cloud.tools.jib.plugins.common.UpdateChecker; import java.util.HashMap; @@ -32,7 +33,6 @@ import org.gradle.api.logging.Logger; import org.gradle.api.plugins.WarPlugin; import org.gradle.api.tasks.TaskProvider; -import org.gradle.internal.logging.events.LogEvent; import org.gradle.internal.logging.events.OutputEventListener; import org.gradle.internal.logging.slf4j.OutputEventListenerBackedLoggerContext; import org.slf4j.LoggerFactory; @@ -45,7 +45,8 @@ class TaskCommon { static Optional newUpdateChecker( ProjectProperties projectProperties, Logger logger) { if (!projectProperties.isOffline() && logger.isLifecycleEnabled()) { - return Optional.of(UpdateChecker.checkForUpdate(VERSION_URL)); + return Optional.of( + UpdateChecker.checkForUpdate(s -> projectProperties.log(LogEvent.warn(s)), VERSION_URL)); } return Optional.empty(); } @@ -57,8 +58,7 @@ static void finishUpdateChecker( .ifPresent( updateMessage -> projectProperties.log( - com.google.cloud.tools.jib.api.LogEvent.lifecycle( - "\n\u001B[33m" + updateMessage + "\u001B[0m\n"))); + LogEvent.lifecycle("\n\u001B[33m" + updateMessage + "\u001B[0m\n"))); } @Nullable @@ -88,7 +88,8 @@ static void disableHttpLogging() { OutputEventListener defaultOutputEventListener = context.getOutputEventListener(); context.setOutputEventListener( event -> { - LogEvent logEvent = (LogEvent) event; + org.gradle.internal.logging.events.LogEvent logEvent = + (org.gradle.internal.logging.events.LogEvent) event; if (!logEvent.getCategory().contains("org.apache")) { defaultOutputEventListener.onOutput(event); } diff --git a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/MojoCommon.java b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/MojoCommon.java index fe789b28f1..1e0451376b 100644 --- a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/MojoCommon.java +++ b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/MojoCommon.java @@ -48,7 +48,8 @@ public class MojoCommon { static Optional newUpdateChecker(ProjectProperties projectProperties, Log logger) { if (!projectProperties.isOffline() && logger.isInfoEnabled()) { - return Optional.of(UpdateChecker.checkForUpdate(VERSION_URL)); + return Optional.of( + UpdateChecker.checkForUpdate(s -> projectProperties.log(LogEvent.warn(s)), VERSION_URL)); } return Optional.empty(); } diff --git a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java index c238713ef7..f66fe0e7cf 100644 --- a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java +++ b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java @@ -41,6 +41,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; +import java.util.function.Consumer; /** Checks if Jib is up-to-date. */ public class UpdateChecker { @@ -62,20 +63,23 @@ void setDisableUpdateCheck(boolean disableUpdateCheck) { * @param versionUrl the location to check for the latest version * @return a new {@link UpdateChecker} */ - public static UpdateChecker checkForUpdate(String versionUrl) { + public static UpdateChecker checkForUpdate(Consumer warningLogger, String versionUrl) { ExecutorService executorService = Executors.newSingleThreadExecutor(); Future> messageFuture = executorService.submit( () -> performUpdateCheck( - Verify.verifyNotNull(ProjectInfo.VERSION), versionUrl, getConfigDir())); + warningLogger, + Verify.verifyNotNull(ProjectInfo.VERSION), + versionUrl, + getConfigDir())); executorService.shutdown(); return new UpdateChecker(messageFuture); } @VisibleForTesting static Optional performUpdateCheck( - String currentVersion, String versionUrl, Path configDir) { + Consumer warningLogger, String currentVersion, String versionUrl, Path configDir) { // Abort if offline or update checks are disabled if (Boolean.getBoolean(PropertyNames.DISABLE_UPDATE_CHECKS)) { return Optional.empty(); @@ -83,12 +87,20 @@ static Optional performUpdateCheck( Path configFile = configDir.resolve("config.json"); Path lastUpdateCheck = configDir.resolve("lastUpdateCheck"); + try { + // Check global config if (Files.exists(configFile)) { // Abort if update checks are disabled - ConfigJsonTemplate config = - JsonTemplateMapper.readJsonFromFile(configFile, ConfigJsonTemplate.class); - if (config.disableUpdateCheck) { + try { + ConfigJsonTemplate config = + JsonTemplateMapper.readJsonFromFile(configFile, ConfigJsonTemplate.class); + if (config.disableUpdateCheck) { + return Optional.empty(); + } + } catch (IOException ex) { + warningLogger.accept( + "Global Jib config may be corrupt; you may need to fix or delete " + configFile); return Optional.empty(); } } else { @@ -97,20 +109,24 @@ static Optional performUpdateCheck( Files.createDirectories(configDir); try (OutputStream outputStream = Files.newOutputStream(configFile)) { JsonTemplateMapper.writeTo(config, outputStream); + } catch (IOException ex) { + // If attempt to generate new config file failed, delete so we can try again next time + Files.deleteIfExists(configFile); } } // Check time of last update check if (Files.exists(lastUpdateCheck)) { - String fileContents = - new String(Files.readAllBytes(lastUpdateCheck), StandardCharsets.UTF_8); try { + String fileContents = + new String(Files.readAllBytes(lastUpdateCheck), StandardCharsets.UTF_8); Instant modifiedTime = Instant.parse(fileContents); if (modifiedTime.plus(Duration.ofDays(1)).isAfter(Instant.now())) { return Optional.empty(); } - } catch (DateTimeParseException ex) { - // Ignore parse failure; assume update check hasn't been performed + } catch (DateTimeParseException | IOException ex) { + // If reading update time failed, file might be corrupt, so delete it + Files.delete(lastUpdateCheck); } } @@ -137,13 +153,8 @@ static Optional performUpdateCheck( connection.disconnect(); } - } catch (IOException ex) { - try { - Files.deleteIfExists(configFile); - Files.deleteIfExists(lastUpdateCheck); - } catch (IOException ignored) { - // Fail silently - } + } catch (IOException ignored) { + // Fail other exceptions silently } return Optional.empty(); diff --git a/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java b/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java index e1c0b8689d..af944a9f07 100644 --- a/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java +++ b/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java @@ -71,7 +71,7 @@ public void testPerformUpdateCheck_newVersionFound() throws IOException { Instant before = Instant.now(); setupConfigAndLastUpdateCheck(); Optional message = - UpdateChecker.performUpdateCheck("1.0.2", testWebServer.getEndpoint(), configDir); + UpdateChecker.performUpdateCheck(s -> {}, "1.0.2", testWebServer.getEndpoint(), configDir); Assert.assertTrue(message.isPresent()); Assert.assertEquals( "A new version of Jib (2.0.0) is available (currently using 1.0.2). Update your build " @@ -88,7 +88,7 @@ public void testPerformUpdateCheck_onLatest() throws IOException { Instant before = Instant.now(); setupConfigAndLastUpdateCheck(); Optional message = - UpdateChecker.performUpdateCheck("2.0.0", testWebServer.getEndpoint(), configDir); + UpdateChecker.performUpdateCheck(s -> {}, "2.0.0", testWebServer.getEndpoint(), configDir); Assert.assertFalse(message.isPresent()); String modifiedTime = new String( @@ -100,7 +100,7 @@ public void testPerformUpdateCheck_onLatest() throws IOException { public void testPerformUpdateCheck_noConfigOrLastUpdateCheck() throws IOException { Instant before = Instant.now(); Optional message = - UpdateChecker.performUpdateCheck("1.0.2", testWebServer.getEndpoint(), configDir); + UpdateChecker.performUpdateCheck(s -> {}, "1.0.2", testWebServer.getEndpoint(), configDir); Assert.assertTrue(message.isPresent()); Assert.assertEquals( "A new version of Jib (2.0.0) is available (currently using 1.0.2). Update your build " @@ -120,7 +120,7 @@ public void testPerformUpdateCheck_lastUpdateCheckTooSoon() throws IOException { configDir.resolve("lastUpdateCheck"), modifiedTime.toString().getBytes(StandardCharsets.UTF_8)); Optional message = - UpdateChecker.performUpdateCheck("1.0.2", testWebServer.getEndpoint(), configDir); + UpdateChecker.performUpdateCheck(s -> {}, "1.0.2", testWebServer.getEndpoint(), configDir); Assert.assertFalse(message.isPresent()); // lastUpdateCheck should not have changed @@ -134,7 +134,7 @@ public void testPerformUpdateCheck_lastUpdateCheckTooSoon() throws IOException { public void testPerformUpdateCheck_systemProperty() { System.setProperty(PropertyNames.DISABLE_UPDATE_CHECKS, "true"); Optional message = - UpdateChecker.performUpdateCheck("1.0.2", testWebServer.getEndpoint(), configDir); + UpdateChecker.performUpdateCheck(s -> {}, "1.0.2", testWebServer.getEndpoint(), configDir); Assert.assertFalse(message.isPresent()); } @@ -144,7 +144,7 @@ public void testPerformUpdateCheck_configDisabled() throws IOException { configDir.resolve("config.json"), "{\"disableUpdateCheck\":true}".getBytes(StandardCharsets.UTF_8)); Optional message = - UpdateChecker.performUpdateCheck("1.0.2", testWebServer.getEndpoint(), configDir); + UpdateChecker.performUpdateCheck(s -> {}, "1.0.2", testWebServer.getEndpoint(), configDir); Assert.assertFalse(message.isPresent()); } @@ -154,7 +154,7 @@ public void testPerformUpdateCheck_failSilently() try (TestWebServer badServer = new TestWebServer(false, Collections.singletonList("HTTP/1.1 400 Bad Request\n\n"), 1)) { Optional message = - UpdateChecker.performUpdateCheck("1.0.2", badServer.getEndpoint(), configDir); + UpdateChecker.performUpdateCheck(s -> {}, "1.0.2", badServer.getEndpoint(), configDir); Assert.assertFalse(message.isPresent()); } } From 23d9f473aefb4cb717bc619b59adfd7e51e66af8 Mon Sep 17 00:00:00 2001 From: "tad.cordle@gmail.com" Date: Wed, 15 Jan 2020 15:09:36 -0500 Subject: [PATCH 24/36] Javadoc and better warning message --- .../google/cloud/tools/jib/plugins/common/UpdateChecker.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java index f66fe0e7cf..114eef6bc1 100644 --- a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java +++ b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java @@ -60,6 +60,7 @@ void setDisableUpdateCheck(boolean disableUpdateCheck) { /** * Begins checking for an update in a separate thread. * + * @param warningLogger {@link Consumer} used to log warnings * @param versionUrl the location to check for the latest version * @return a new {@link UpdateChecker} */ @@ -100,7 +101,7 @@ static Optional performUpdateCheck( } } catch (IOException ex) { warningLogger.accept( - "Global Jib config may be corrupt; you may need to fix or delete " + configFile); + "Failed to read global Jib config; you may need to fix or delete " + configFile); return Optional.empty(); } } else { From 28f4a8c210baed8f40a682860e664e678e0eb594 Mon Sep 17 00:00:00 2001 From: "tad.cordle@gmail.com" Date: Wed, 15 Jan 2020 15:34:03 -0500 Subject: [PATCH 25/36] More logging --- .../cloud/tools/jib/gradle/TaskCommon.java | 3 +-- .../cloud/tools/jib/maven/MojoCommon.java | 3 +-- .../jib/plugins/common/UpdateChecker.java | 27 +++++++++++-------- .../jib/plugins/common/UpdateCheckerTest.java | 21 ++++++++++----- 4 files changed, 32 insertions(+), 22 deletions(-) diff --git a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/TaskCommon.java b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/TaskCommon.java index 9367988a45..006afaa570 100644 --- a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/TaskCommon.java +++ b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/TaskCommon.java @@ -45,8 +45,7 @@ class TaskCommon { static Optional newUpdateChecker( ProjectProperties projectProperties, Logger logger) { if (!projectProperties.isOffline() && logger.isLifecycleEnabled()) { - return Optional.of( - UpdateChecker.checkForUpdate(s -> projectProperties.log(LogEvent.warn(s)), VERSION_URL)); + return Optional.of(UpdateChecker.checkForUpdate(projectProperties::log, VERSION_URL)); } return Optional.empty(); } diff --git a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/MojoCommon.java b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/MojoCommon.java index 1e0451376b..d1bf73ed93 100644 --- a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/MojoCommon.java +++ b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/MojoCommon.java @@ -48,8 +48,7 @@ public class MojoCommon { static Optional newUpdateChecker(ProjectProperties projectProperties, Log logger) { if (!projectProperties.isOffline() && logger.isInfoEnabled()) { - return Optional.of( - UpdateChecker.checkForUpdate(s -> projectProperties.log(LogEvent.warn(s)), VERSION_URL)); + return Optional.of(UpdateChecker.checkForUpdate(projectProperties::log, VERSION_URL)); } return Optional.empty(); } diff --git a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java index 114eef6bc1..b5b36c3424 100644 --- a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java +++ b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java @@ -17,6 +17,7 @@ package com.google.cloud.tools.jib.plugins.common; import com.google.cloud.tools.jib.ProjectInfo; +import com.google.cloud.tools.jib.api.LogEvent; import com.google.cloud.tools.jib.filesystem.XdgDirectories; import com.google.cloud.tools.jib.json.JsonTemplate; import com.google.cloud.tools.jib.json.JsonTemplateMapper; @@ -60,27 +61,24 @@ void setDisableUpdateCheck(boolean disableUpdateCheck) { /** * Begins checking for an update in a separate thread. * - * @param warningLogger {@link Consumer} used to log warnings + * @param log {@link Consumer} used to log messages * @param versionUrl the location to check for the latest version * @return a new {@link UpdateChecker} */ - public static UpdateChecker checkForUpdate(Consumer warningLogger, String versionUrl) { + public static UpdateChecker checkForUpdate(Consumer log, String versionUrl) { ExecutorService executorService = Executors.newSingleThreadExecutor(); Future> messageFuture = executorService.submit( () -> performUpdateCheck( - warningLogger, - Verify.verifyNotNull(ProjectInfo.VERSION), - versionUrl, - getConfigDir())); + log, Verify.verifyNotNull(ProjectInfo.VERSION), versionUrl, getConfigDir())); executorService.shutdown(); return new UpdateChecker(messageFuture); } @VisibleForTesting static Optional performUpdateCheck( - Consumer warningLogger, String currentVersion, String versionUrl, Path configDir) { + Consumer log, String currentVersion, String versionUrl, Path configDir) { // Abort if offline or update checks are disabled if (Boolean.getBoolean(PropertyNames.DISABLE_UPDATE_CHECKS)) { return Optional.empty(); @@ -100,8 +98,13 @@ static Optional performUpdateCheck( return Optional.empty(); } } catch (IOException ex) { - warningLogger.accept( - "Failed to read global Jib config; you may need to fix or delete " + configFile); + log.accept( + LogEvent.warn( + "Failed to read global Jib config: " + + ex.getMessage() + + "; you may need to fix or delete " + + configFile + + "; ")); return Optional.empty(); } } else { @@ -113,6 +116,7 @@ static Optional performUpdateCheck( } catch (IOException ex) { // If attempt to generate new config file failed, delete so we can try again next time Files.deleteIfExists(configFile); + log.accept(LogEvent.debug("Failed to generate global Jib config; " + ex.getMessage())); } } @@ -128,6 +132,7 @@ static Optional performUpdateCheck( } catch (DateTimeParseException | IOException ex) { // If reading update time failed, file might be corrupt, so delete it Files.delete(lastUpdateCheck); + log.accept(LogEvent.debug("Failed to read lastUpdateCheck; " + ex.getMessage())); } } @@ -154,8 +159,8 @@ static Optional performUpdateCheck( connection.disconnect(); } - } catch (IOException ignored) { - // Fail other exceptions silently + } catch (IOException ex) { + log.accept(LogEvent.debug("Update check failed; " + ex.getMessage())); } return Optional.empty(); diff --git a/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java b/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java index af944a9f07..87729bfbb6 100644 --- a/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java +++ b/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java @@ -71,7 +71,8 @@ public void testPerformUpdateCheck_newVersionFound() throws IOException { Instant before = Instant.now(); setupConfigAndLastUpdateCheck(); Optional message = - UpdateChecker.performUpdateCheck(s -> {}, "1.0.2", testWebServer.getEndpoint(), configDir); + UpdateChecker.performUpdateCheck( + ignored -> {}, "1.0.2", testWebServer.getEndpoint(), configDir); Assert.assertTrue(message.isPresent()); Assert.assertEquals( "A new version of Jib (2.0.0) is available (currently using 1.0.2). Update your build " @@ -88,7 +89,8 @@ public void testPerformUpdateCheck_onLatest() throws IOException { Instant before = Instant.now(); setupConfigAndLastUpdateCheck(); Optional message = - UpdateChecker.performUpdateCheck(s -> {}, "2.0.0", testWebServer.getEndpoint(), configDir); + UpdateChecker.performUpdateCheck( + ignored -> {}, "2.0.0", testWebServer.getEndpoint(), configDir); Assert.assertFalse(message.isPresent()); String modifiedTime = new String( @@ -100,7 +102,8 @@ public void testPerformUpdateCheck_onLatest() throws IOException { public void testPerformUpdateCheck_noConfigOrLastUpdateCheck() throws IOException { Instant before = Instant.now(); Optional message = - UpdateChecker.performUpdateCheck(s -> {}, "1.0.2", testWebServer.getEndpoint(), configDir); + UpdateChecker.performUpdateCheck( + ignored -> {}, "1.0.2", testWebServer.getEndpoint(), configDir); Assert.assertTrue(message.isPresent()); Assert.assertEquals( "A new version of Jib (2.0.0) is available (currently using 1.0.2). Update your build " @@ -120,7 +123,8 @@ public void testPerformUpdateCheck_lastUpdateCheckTooSoon() throws IOException { configDir.resolve("lastUpdateCheck"), modifiedTime.toString().getBytes(StandardCharsets.UTF_8)); Optional message = - UpdateChecker.performUpdateCheck(s -> {}, "1.0.2", testWebServer.getEndpoint(), configDir); + UpdateChecker.performUpdateCheck( + ignored -> {}, "1.0.2", testWebServer.getEndpoint(), configDir); Assert.assertFalse(message.isPresent()); // lastUpdateCheck should not have changed @@ -134,7 +138,8 @@ public void testPerformUpdateCheck_lastUpdateCheckTooSoon() throws IOException { public void testPerformUpdateCheck_systemProperty() { System.setProperty(PropertyNames.DISABLE_UPDATE_CHECKS, "true"); Optional message = - UpdateChecker.performUpdateCheck(s -> {}, "1.0.2", testWebServer.getEndpoint(), configDir); + UpdateChecker.performUpdateCheck( + ignored -> {}, "1.0.2", testWebServer.getEndpoint(), configDir); Assert.assertFalse(message.isPresent()); } @@ -144,7 +149,8 @@ public void testPerformUpdateCheck_configDisabled() throws IOException { configDir.resolve("config.json"), "{\"disableUpdateCheck\":true}".getBytes(StandardCharsets.UTF_8)); Optional message = - UpdateChecker.performUpdateCheck(s -> {}, "1.0.2", testWebServer.getEndpoint(), configDir); + UpdateChecker.performUpdateCheck( + ignored -> {}, "1.0.2", testWebServer.getEndpoint(), configDir); Assert.assertFalse(message.isPresent()); } @@ -154,7 +160,8 @@ public void testPerformUpdateCheck_failSilently() try (TestWebServer badServer = new TestWebServer(false, Collections.singletonList("HTTP/1.1 400 Bad Request\n\n"), 1)) { Optional message = - UpdateChecker.performUpdateCheck(s -> {}, "1.0.2", badServer.getEndpoint(), configDir); + UpdateChecker.performUpdateCheck( + ignored -> {}, "1.0.2", badServer.getEndpoint(), configDir); Assert.assertFalse(message.isPresent()); } } From 946626a35f3b27aac3f6016fc44da8c734b31c69 Mon Sep 17 00:00:00 2001 From: "tad.cordle@gmail.com" Date: Thu, 16 Jan 2020 18:11:08 -0500 Subject: [PATCH 26/36] Log before deletion --- .../google/cloud/tools/jib/plugins/common/UpdateChecker.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java index b5b36c3424..8991b47b04 100644 --- a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java +++ b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java @@ -115,8 +115,8 @@ static Optional performUpdateCheck( JsonTemplateMapper.writeTo(config, outputStream); } catch (IOException ex) { // If attempt to generate new config file failed, delete so we can try again next time - Files.deleteIfExists(configFile); log.accept(LogEvent.debug("Failed to generate global Jib config; " + ex.getMessage())); + Files.deleteIfExists(configFile); } } @@ -131,8 +131,8 @@ static Optional performUpdateCheck( } } catch (DateTimeParseException | IOException ex) { // If reading update time failed, file might be corrupt, so delete it - Files.delete(lastUpdateCheck); log.accept(LogEvent.debug("Failed to read lastUpdateCheck; " + ex.getMessage())); + Files.delete(lastUpdateCheck); } } From b1fba58ae41fd747e559d54ede4ce45a97675c6f Mon Sep 17 00:00:00 2001 From: "tad.cordle@gmail.com" Date: Fri, 17 Jan 2020 10:47:40 -0500 Subject: [PATCH 27/36] Comments --- .../google/cloud/tools/jib/gradle/TaskCommon.java | 14 ++++++++++---- .../google/cloud/tools/jib/maven/MojoCommon.java | 12 +++++++++--- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/TaskCommon.java b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/TaskCommon.java index 006afaa570..bd9db536b9 100644 --- a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/TaskCommon.java +++ b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/TaskCommon.java @@ -17,6 +17,7 @@ package com.google.cloud.tools.jib.gradle; import com.google.api.client.http.HttpTransport; +import com.google.cloud.tools.jib.ProjectInfo; import com.google.cloud.tools.jib.api.AbsoluteUnixPath; import com.google.cloud.tools.jib.api.FilePermissions; import com.google.cloud.tools.jib.api.LogEvent; @@ -44,10 +45,10 @@ class TaskCommon { static Optional newUpdateChecker( ProjectProperties projectProperties, Logger logger) { - if (!projectProperties.isOffline() && logger.isLifecycleEnabled()) { - return Optional.of(UpdateChecker.checkForUpdate(projectProperties::log, VERSION_URL)); + if (projectProperties.isOffline() || !logger.isLifecycleEnabled()) { + return Optional.empty(); } - return Optional.empty(); + return Optional.of(UpdateChecker.checkForUpdate(projectProperties::log, VERSION_URL)); } static void finishUpdateChecker( @@ -57,7 +58,12 @@ static void finishUpdateChecker( .ifPresent( updateMessage -> projectProperties.log( - LogEvent.lifecycle("\n\u001B[33m" + updateMessage + "\u001B[0m\n"))); + LogEvent.lifecycle( + "\n\u001B[33m" + + updateMessage + + "\n" + + ProjectInfo.GITHUB_URL + + "/blob/master/jib-gradle-plugin/CHANGELOG.md\u001B[0m\n"))); } @Nullable diff --git a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/MojoCommon.java b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/MojoCommon.java index d1bf73ed93..d922acb2dc 100644 --- a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/MojoCommon.java +++ b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/MojoCommon.java @@ -16,6 +16,7 @@ package com.google.cloud.tools.jib.maven; +import com.google.cloud.tools.jib.ProjectInfo; import com.google.cloud.tools.jib.api.AbsoluteUnixPath; import com.google.cloud.tools.jib.api.FilePermissions; import com.google.cloud.tools.jib.api.LogEvent; @@ -47,10 +48,10 @@ public class MojoCommon { public static final String VERSION_URL = "https://storage.googleapis.com/jib-versions/jib-maven"; static Optional newUpdateChecker(ProjectProperties projectProperties, Log logger) { - if (!projectProperties.isOffline() && logger.isInfoEnabled()) { - return Optional.of(UpdateChecker.checkForUpdate(projectProperties::log, VERSION_URL)); + if (projectProperties.isOffline() || !logger.isInfoEnabled()) { + return Optional.empty(); } - return Optional.empty(); + return Optional.of(UpdateChecker.checkForUpdate(projectProperties::log, VERSION_URL)); } static void finishUpdateChecker( @@ -61,6 +62,11 @@ static void finishUpdateChecker( updateMessage -> { projectProperties.log(LogEvent.lifecycle("")); projectProperties.log(LogEvent.lifecycle("\u001B[33m" + updateMessage + "\u001B[0m")); + projectProperties.log( + LogEvent.lifecycle( + "\u001B[33m" + + ProjectInfo.GITHUB_URL + + "/blob/master/jib-maven-plugin/CHANGELOG.md\u001B[0m")); projectProperties.log(LogEvent.lifecycle("")); }); } From c865371ab7bf8dab76361796af551f485dc743e3 Mon Sep 17 00:00:00 2001 From: "tad.cordle@gmail.com" Date: Fri, 17 Jan 2020 11:34:34 -0500 Subject: [PATCH 28/36] Copyright --- .../google/cloud/tools/jib/plugins/common/UpdateChecker.java | 2 +- .../cloud/tools/jib/plugins/common/UpdateCheckerTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java index 8991b47b04..e62f68e345 100644 --- a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java +++ b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 Google LLC. + * Copyright 2020 Google LLC. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of diff --git a/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java b/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java index 87729bfbb6..ca488cff29 100644 --- a/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java +++ b/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 Google LLC. + * Copyright 2020 Google LLC. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of From f6a0aa52fd7b38b0cf1d123326e56f82ca6932e0 Mon Sep 17 00:00:00 2001 From: "tad.cordle@gmail.com" Date: Fri, 17 Jan 2020 12:16:50 -0500 Subject: [PATCH 29/36] More tests --- .../jib/plugins/common/UpdateCheckerTest.java | 38 ++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java b/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java index ca488cff29..af3a06bbd0 100644 --- a/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java +++ b/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java @@ -16,6 +16,7 @@ package com.google.cloud.tools.jib.plugins.common; +import com.google.cloud.tools.jib.api.LogEvent.Level; import com.google.cloud.tools.jib.http.TestWebServer; import com.google.common.util.concurrent.MoreExecutors; import java.io.IOException; @@ -154,6 +155,35 @@ public void testPerformUpdateCheck_configDisabled() throws IOException { Assert.assertFalse(message.isPresent()); } + @Test + public void testPerformUpdateCheck_badConfig() throws IOException { + Files.write( + configDir.resolve("config.json"), "corrupt config".getBytes(StandardCharsets.UTF_8)); + Optional message = + UpdateChecker.performUpdateCheck( + ignored -> {}, "1.0.2", testWebServer.getEndpoint(), configDir); + Assert.assertFalse(message.isPresent()); + } + + @Test + public void testPerformUpdateCheck_badLastUpdateTime() throws IOException { + Instant before = Instant.now(); + Files.write( + configDir.resolve("lastUpdateCheck"), "bad timestamp".getBytes(StandardCharsets.UTF_8)); + Optional message = + UpdateChecker.performUpdateCheck( + ignored -> {}, "1.0.2", testWebServer.getEndpoint(), configDir); + String modifiedTime = + new String( + Files.readAllBytes(configDir.resolve("lastUpdateCheck")), StandardCharsets.UTF_8); + Assert.assertTrue(Instant.parse(modifiedTime).isAfter(before)); + Assert.assertTrue(message.isPresent()); + Assert.assertEquals( + "A new version of Jib (2.0.0) is available (currently using 1.0.2). Update your build " + + "configuration to use the latest features and fixes!", + message.get()); + } + @Test public void testPerformUpdateCheck_failSilently() throws InterruptedException, GeneralSecurityException, URISyntaxException, IOException { @@ -161,7 +191,13 @@ public void testPerformUpdateCheck_failSilently() new TestWebServer(false, Collections.singletonList("HTTP/1.1 400 Bad Request\n\n"), 1)) { Optional message = UpdateChecker.performUpdateCheck( - ignored -> {}, "1.0.2", badServer.getEndpoint(), configDir); + logEvent -> { + Assert.assertEquals(logEvent.getLevel(), Level.DEBUG); + Assert.assertTrue(logEvent.getMessage().contains("Update check failed; ")); + }, + "1.0.2", + badServer.getEndpoint(), + configDir); Assert.assertFalse(message.isPresent()); } } From a7b70a8cf465db9b498161041c6c16dde6d99a8b Mon Sep 17 00:00:00 2001 From: "tad.cordle@gmail.com" Date: Fri, 17 Jan 2020 12:36:52 -0500 Subject: [PATCH 30/36] Stuff --- .../tools/jib/gradle/BuildDockerTask.java | 6 +-- .../tools/jib/gradle/BuildImageTask.java | 6 +-- .../cloud/tools/jib/gradle/BuildTarTask.java | 6 +-- .../cloud/tools/jib/gradle/TaskCommon.java | 15 +++--- .../tools/jib/maven/BuildDockerMojo.java | 6 +-- .../cloud/tools/jib/maven/BuildImageMojo.java | 6 +-- .../cloud/tools/jib/maven/BuildTarMojo.java | 6 +-- .../cloud/tools/jib/maven/MojoCommon.java | 16 +++--- .../jib/plugins/common/UpdateChecker.java | 49 +++++++++---------- .../jib/plugins/common/UpdateCheckerTest.java | 13 +++-- 10 files changed, 65 insertions(+), 64 deletions(-) diff --git a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildDockerTask.java b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildDockerTask.java index f9ca63a67b..b8c19f2b75 100644 --- a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildDockerTask.java +++ b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildDockerTask.java @@ -31,11 +31,11 @@ import com.google.cloud.tools.jib.plugins.common.InvalidWorkingDirectoryException; import com.google.cloud.tools.jib.plugins.common.MainClassInferenceException; import com.google.cloud.tools.jib.plugins.common.PluginConfigurationProcessor; -import com.google.cloud.tools.jib.plugins.common.UpdateChecker; import com.google.common.base.Preconditions; import java.io.IOException; import java.nio.file.Path; import java.util.Optional; +import java.util.concurrent.Future; import javax.annotation.Nullable; import org.gradle.api.DefaultTask; import org.gradle.api.GradleException; @@ -94,7 +94,7 @@ public void buildDocker() GradleProjectProperties projectProperties = GradleProjectProperties.getForProject(getProject(), getLogger(), tempDirectoryProvider); - Optional updateChecker = + Future> updateCheckFuture = TaskCommon.newUpdateChecker(projectProperties, getLogger()); try { PluginConfigurationProcessor.createJibBuildRunnerForDockerDaemonImage( @@ -149,7 +149,7 @@ public void buildDocker() } finally { tempDirectoryProvider.close(); - TaskCommon.finishUpdateChecker(projectProperties, updateChecker); + TaskCommon.finishUpdateChecker(projectProperties, updateCheckFuture); projectProperties.waitForLoggingThread(); } } diff --git a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildImageTask.java b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildImageTask.java index 3c6e73c84e..c8cb88abaf 100644 --- a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildImageTask.java +++ b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildImageTask.java @@ -30,11 +30,11 @@ import com.google.cloud.tools.jib.plugins.common.InvalidWorkingDirectoryException; import com.google.cloud.tools.jib.plugins.common.MainClassInferenceException; import com.google.cloud.tools.jib.plugins.common.PluginConfigurationProcessor; -import com.google.cloud.tools.jib.plugins.common.UpdateChecker; import com.google.common.base.Preconditions; import com.google.common.base.Strings; import java.io.IOException; import java.util.Optional; +import java.util.concurrent.Future; import javax.annotation.Nullable; import org.gradle.api.DefaultTask; import org.gradle.api.GradleException; @@ -82,7 +82,7 @@ public void buildImage() GradleProjectProperties projectProperties = GradleProjectProperties.getForProject(getProject(), getLogger(), tempDirectoryProvider); - Optional updateChecker = + Future> updateCheckFuture = TaskCommon.newUpdateChecker(projectProperties, getLogger()); try { if (Strings.isNullOrEmpty(jibExtension.getTo().getImage())) { @@ -146,7 +146,7 @@ public void buildImage() } finally { tempDirectoryProvider.close(); - TaskCommon.finishUpdateChecker(projectProperties, updateChecker); + TaskCommon.finishUpdateChecker(projectProperties, updateCheckFuture); projectProperties.waitForLoggingThread(); } } diff --git a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildTarTask.java b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildTarTask.java index f9b7d00408..10180a84bd 100644 --- a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildTarTask.java +++ b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/BuildTarTask.java @@ -30,12 +30,12 @@ import com.google.cloud.tools.jib.plugins.common.InvalidWorkingDirectoryException; import com.google.cloud.tools.jib.plugins.common.MainClassInferenceException; import com.google.cloud.tools.jib.plugins.common.PluginConfigurationProcessor; -import com.google.cloud.tools.jib.plugins.common.UpdateChecker; import com.google.common.base.Preconditions; import java.io.IOException; import java.nio.file.Path; import java.util.List; import java.util.Optional; +import java.util.concurrent.Future; import javax.annotation.Nullable; import org.gradle.api.DefaultTask; import org.gradle.api.GradleException; @@ -107,7 +107,7 @@ public void buildTar() GradleProjectProperties projectProperties = GradleProjectProperties.getForProject(getProject(), getLogger(), tempDirectoryProvider); - Optional updateChecker = + Future> updateCheckFuture = TaskCommon.newUpdateChecker(projectProperties, getLogger()); try { PluginConfigurationProcessor.createJibBuildRunnerForTarImage( @@ -162,7 +162,7 @@ public void buildTar() } finally { tempDirectoryProvider.close(); - TaskCommon.finishUpdateChecker(projectProperties, updateChecker); + TaskCommon.finishUpdateChecker(projectProperties, updateCheckFuture); projectProperties.waitForLoggingThread(); } } diff --git a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/TaskCommon.java b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/TaskCommon.java index bd9db536b9..cd1b88a351 100644 --- a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/TaskCommon.java +++ b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/TaskCommon.java @@ -23,9 +23,12 @@ import com.google.cloud.tools.jib.api.LogEvent; import com.google.cloud.tools.jib.plugins.common.ProjectProperties; import com.google.cloud.tools.jib.plugins.common.UpdateChecker; +import com.google.common.util.concurrent.Futures; import java.util.HashMap; import java.util.Map; import java.util.Optional; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; import java.util.logging.Level; import javax.annotation.Nullable; import org.gradle.api.Project; @@ -43,18 +46,18 @@ class TaskCommon { public static final String VERSION_URL = "https://storage.googleapis.com/jib-versions/jib-gradle"; - static Optional newUpdateChecker( + static Future> newUpdateChecker( ProjectProperties projectProperties, Logger logger) { if (projectProperties.isOffline() || !logger.isLifecycleEnabled()) { - return Optional.empty(); + return Futures.immediateFuture(Optional.empty()); } - return Optional.of(UpdateChecker.checkForUpdate(projectProperties::log, VERSION_URL)); + return UpdateChecker.checkForUpdate( + Executors.newSingleThreadExecutor(), projectProperties::log, VERSION_URL); } static void finishUpdateChecker( - ProjectProperties projectProperties, Optional updateChecker) { - updateChecker - .flatMap(UpdateChecker::finishUpdateCheck) + ProjectProperties projectProperties, Future> updateCheckFuture) { + UpdateChecker.finishUpdateCheck(updateCheckFuture) .ifPresent( updateMessage -> projectProperties.log( diff --git a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildDockerMojo.java b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildDockerMojo.java index 1ec56d2b79..1ac5d09c18 100644 --- a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildDockerMojo.java +++ b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildDockerMojo.java @@ -31,11 +31,11 @@ import com.google.cloud.tools.jib.plugins.common.InvalidWorkingDirectoryException; import com.google.cloud.tools.jib.plugins.common.MainClassInferenceException; import com.google.cloud.tools.jib.plugins.common.PluginConfigurationProcessor; -import com.google.cloud.tools.jib.plugins.common.UpdateChecker; import com.google.common.annotations.VisibleForTesting; import java.io.IOException; import java.nio.file.Path; import java.util.Optional; +import java.util.concurrent.Future; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Mojo; @@ -75,7 +75,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { MavenProjectProperties projectProperties = MavenProjectProperties.getForProject( getProject(), getSession(), getLog(), tempDirectoryProvider); - Optional updateChecker = + Future> updateCheckFuture = MojoCommon.newUpdateChecker(projectProperties, getLog()); try { PluginConfigurationProcessor.createJibBuildRunnerForDockerDaemonImage( @@ -138,7 +138,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { } finally { tempDirectoryProvider.close(); - MojoCommon.finishUpdateChecker(projectProperties, updateChecker); + MojoCommon.finishUpdateChecker(projectProperties, updateCheckFuture); projectProperties.waitForLoggingThread(); getLog().info(""); } diff --git a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildImageMojo.java b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildImageMojo.java index c8789bd0bb..c76788c3f2 100644 --- a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildImageMojo.java +++ b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildImageMojo.java @@ -31,12 +31,12 @@ import com.google.cloud.tools.jib.plugins.common.InvalidWorkingDirectoryException; import com.google.cloud.tools.jib.plugins.common.MainClassInferenceException; import com.google.cloud.tools.jib.plugins.common.PluginConfigurationProcessor; -import com.google.cloud.tools.jib.plugins.common.UpdateChecker; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Strings; import java.io.IOException; import java.util.Arrays; import java.util.Optional; +import java.util.concurrent.Future; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Mojo; @@ -89,7 +89,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { MavenProjectProperties projectProperties = MavenProjectProperties.getForProject( getProject(), getSession(), getLog(), tempDirectoryProvider); - Optional updateChecker = + Future> updateCheckFuture = MojoCommon.newUpdateChecker(projectProperties, getLog()); try { PluginConfigurationProcessor.createJibBuildRunnerForRegistryImage( @@ -152,7 +152,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { } finally { tempDirectoryProvider.close(); - MojoCommon.finishUpdateChecker(projectProperties, updateChecker); + MojoCommon.finishUpdateChecker(projectProperties, updateCheckFuture); projectProperties.waitForLoggingThread(); getLog().info(""); } diff --git a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildTarMojo.java b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildTarMojo.java index e6bb5f6e23..30057dab23 100644 --- a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildTarMojo.java +++ b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/BuildTarMojo.java @@ -30,10 +30,10 @@ import com.google.cloud.tools.jib.plugins.common.InvalidWorkingDirectoryException; import com.google.cloud.tools.jib.plugins.common.MainClassInferenceException; import com.google.cloud.tools.jib.plugins.common.PluginConfigurationProcessor; -import com.google.cloud.tools.jib.plugins.common.UpdateChecker; import com.google.common.annotations.VisibleForTesting; import java.io.IOException; import java.util.Optional; +import java.util.concurrent.Future; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Mojo; @@ -67,7 +67,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { MavenProjectProperties projectProperties = MavenProjectProperties.getForProject( getProject(), getSession(), getLog(), tempDirectoryProvider); - Optional updateChecker = + Future> updateCheckFuture = MojoCommon.newUpdateChecker(projectProperties, getLog()); try { PluginConfigurationProcessor.createJibBuildRunnerForTarImage( @@ -130,7 +130,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { } finally { tempDirectoryProvider.close(); - MojoCommon.finishUpdateChecker(projectProperties, updateChecker); + MojoCommon.finishUpdateChecker(projectProperties, updateCheckFuture); projectProperties.waitForLoggingThread(); getLog().info(""); } diff --git a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/MojoCommon.java b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/MojoCommon.java index d922acb2dc..4133c01359 100644 --- a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/MojoCommon.java +++ b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/MojoCommon.java @@ -27,12 +27,15 @@ import com.google.cloud.tools.jib.plugins.common.VersionChecker; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; +import com.google.common.util.concurrent.Futures; import java.nio.file.Path; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; import org.apache.maven.artifact.versioning.DefaultArtifactVersion; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.descriptor.PluginDescriptor; @@ -47,17 +50,18 @@ public class MojoCommon { public static final String VERSION_URL = "https://storage.googleapis.com/jib-versions/jib-maven"; - static Optional newUpdateChecker(ProjectProperties projectProperties, Log logger) { + static Future> newUpdateChecker( + ProjectProperties projectProperties, Log logger) { if (projectProperties.isOffline() || !logger.isInfoEnabled()) { - return Optional.empty(); + return Futures.immediateFuture(Optional.empty()); } - return Optional.of(UpdateChecker.checkForUpdate(projectProperties::log, VERSION_URL)); + return UpdateChecker.checkForUpdate( + Executors.newSingleThreadExecutor(), projectProperties::log, VERSION_URL); } static void finishUpdateChecker( - ProjectProperties projectProperties, Optional updateChecker) { - updateChecker - .flatMap(UpdateChecker::finishUpdateCheck) + ProjectProperties projectProperties, Future> updateCheckFuture) { + UpdateChecker.finishUpdateCheck(updateCheckFuture) .ifPresent( updateMessage -> { projectProperties.log(LogEvent.lifecycle("")); diff --git a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java index e62f68e345..2873d94705 100644 --- a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java +++ b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java @@ -40,7 +40,6 @@ import java.util.Optional; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.function.Consumer; @@ -65,15 +64,15 @@ void setDisableUpdateCheck(boolean disableUpdateCheck) { * @param versionUrl the location to check for the latest version * @return a new {@link UpdateChecker} */ - public static UpdateChecker checkForUpdate(Consumer log, String versionUrl) { - ExecutorService executorService = Executors.newSingleThreadExecutor(); + public static Future> checkForUpdate( + ExecutorService executorService, Consumer log, String versionUrl) { Future> messageFuture = executorService.submit( () -> performUpdateCheck( log, Verify.verifyNotNull(ProjectInfo.VERSION), versionUrl, getConfigDir())); executorService.shutdown(); - return new UpdateChecker(messageFuture); + return messageFuture; } @VisibleForTesting @@ -166,37 +165,16 @@ static Optional performUpdateCheck( return Optional.empty(); } - /** - * Returns the config directory set by {@link PropertyNames#CONFIG_DIRECTORY} if not null, - * otherwise returns the default config directory. - * - * @return the config directory set by {@link PropertyNames#CONFIG_DIRECTORY} if not null, - * otherwise returns the default config directory. - */ - private static Path getConfigDir() { - String configDirProperty = System.getProperty(PropertyNames.CONFIG_DIRECTORY); - if (!Strings.isNullOrEmpty(configDirProperty)) { - return Paths.get(configDirProperty); - } - return XdgDirectories.getConfigHome(); - } - - private final Future> updateMessageFuture; - - @VisibleForTesting - UpdateChecker(Future> updateMessageFuture) { - this.updateMessageFuture = updateMessageFuture; - } - /** * Returns a message indicating Jib should be upgraded if the check succeeded and the current * version is outdated, or returns {@code Optional.empty()} if the check was interrupted or did * not determine that a later version was available. * + * @param updateMessageFuture the {@link Future} returned by {@link UpdateChecker#checkForUpdate} * @return the {@link Optional} message to upgrade Jib if a later version was found, else {@code * Optional.empty()}. */ - public Optional finishUpdateCheck() { + public static Optional finishUpdateCheck(Future> updateMessageFuture) { if (updateMessageFuture.isDone()) { try { return updateMessageFuture.get(); @@ -207,4 +185,21 @@ public Optional finishUpdateCheck() { updateMessageFuture.cancel(true); return Optional.empty(); } + + /** + * Returns the config directory set by {@link PropertyNames#CONFIG_DIRECTORY} if not null, + * otherwise returns the default config directory. + * + * @return the config directory set by {@link PropertyNames#CONFIG_DIRECTORY} if not null, + * otherwise returns the default config directory. + */ + private static Path getConfigDir() { + String configDirProperty = System.getProperty(PropertyNames.CONFIG_DIRECTORY); + if (!Strings.isNullOrEmpty(configDirProperty)) { + return Paths.get(configDirProperty); + } + return XdgDirectories.getConfigHome(); + } + + private UpdateChecker() {} } diff --git a/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java b/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java index af3a06bbd0..71655cb42c 100644 --- a/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java +++ b/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java @@ -205,9 +205,8 @@ public void testPerformUpdateCheck_failSilently() @Test public void testFinishUpdateCheck_success() { ExecutorService executorService = MoreExecutors.newDirectExecutorService(); - UpdateChecker updateChecker = - new UpdateChecker(executorService.submit(() -> Optional.of("Hello"))); - Optional result = updateChecker.finishUpdateCheck(); + Future> updateCheckFuture = executorService.submit(() -> Optional.of("Hello")); + Optional result = UpdateChecker.finishUpdateCheck(updateCheckFuture); Assert.assertTrue(result.isPresent()); Assert.assertEquals("Hello", result.get()); } @@ -215,11 +214,11 @@ public void testFinishUpdateCheck_success() { @Test public void testFinishUpdateCheck_notDone() { @SuppressWarnings("unchecked") - Future> future = (Future>) Mockito.mock(Future.class); - Mockito.when(future.isDone()).thenReturn(false); + Future> updateCheckFuture = + (Future>) Mockito.mock(Future.class); + Mockito.when(updateCheckFuture.isDone()).thenReturn(false); - UpdateChecker updateChecker = new UpdateChecker(future); - Optional result = updateChecker.finishUpdateCheck(); + Optional result = UpdateChecker.finishUpdateCheck(updateCheckFuture); Assert.assertFalse(result.isPresent()); } From e8befde7c10b88ddbabcb55bc41154817a456ab7 Mon Sep 17 00:00:00 2001 From: "tad.cordle@gmail.com" Date: Fri, 17 Jan 2020 12:43:53 -0500 Subject: [PATCH 31/36] Javadoc --- .../com/google/cloud/tools/jib/plugins/common/UpdateChecker.java | 1 + 1 file changed, 1 insertion(+) diff --git a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java index 2873d94705..cbcca3b724 100644 --- a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java +++ b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java @@ -60,6 +60,7 @@ void setDisableUpdateCheck(boolean disableUpdateCheck) { /** * Begins checking for an update in a separate thread. * + * @param executorService the {@link ExecutorService} * @param log {@link Consumer} used to log messages * @param versionUrl the location to check for the latest version * @return a new {@link UpdateChecker} From 0c94c7660639458d2e617486ddf1346fc16e67f1 Mon Sep 17 00:00:00 2001 From: "tad.cordle@gmail.com" Date: Fri, 17 Jan 2020 15:26:58 -0500 Subject: [PATCH 32/36] Json --- .../tools/jib/plugins/common/UpdateChecker.java | 13 ++++++++++--- .../tools/jib/plugins/common/UpdateCheckerTest.java | 5 ++++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java index cbcca3b724..c34fb81f12 100644 --- a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java +++ b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java @@ -57,6 +57,11 @@ void setDisableUpdateCheck(boolean disableUpdateCheck) { } } + /** JSON template for content downloaded during version check. */ + private static class VersionJsonTemplate implements JsonTemplate { + private String latest = ""; + } + /** * Begins checking for an update in a separate thread. * @@ -143,14 +148,16 @@ static Optional performUpdateCheck( BufferedReader bufferedReader = new BufferedReader( new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8)); - String latestVersion = bufferedReader.readLine().trim(); + VersionJsonTemplate version = + JsonTemplateMapper.readJson( + bufferedReader.readLine().trim(), VersionJsonTemplate.class); Files.write(lastUpdateCheck, Instant.now().toString().getBytes(StandardCharsets.UTF_8)); - if (currentVersion.equals(latestVersion)) { + if (currentVersion.equals(version.latest)) { return Optional.empty(); } return Optional.of( "A new version of Jib (" - + latestVersion + + version.latest + ") is available (currently using " + currentVersion + "). Update your build configuration to use the latest features and fixes!"); diff --git a/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java b/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java index 71655cb42c..22133d7829 100644 --- a/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java +++ b/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java @@ -58,7 +58,10 @@ public void setUp() throws InterruptedException, GeneralSecurityException, URISyntaxException, IOException { testWebServer = new TestWebServer( - false, Collections.singletonList("HTTP/1.1 200 OK\nContent-Length:5\n\n2.0.0"), 1); + false, + Collections.singletonList( + "HTTP/1.1 200 OK\nContent-Length:18\n\n{\"latest\":\"2.0.0\"}"), + 1); configDir = temporaryFolder.getRoot().toPath(); } From ae6288ccd5b1bbe54b2dad2a2d710f76277cb216 Mon Sep 17 00:00:00 2001 From: "tad.cordle@gmail.com" Date: Fri, 17 Jan 2020 15:33:34 -0500 Subject: [PATCH 33/36] More code --- .../com/google/cloud/tools/jib/gradle/TaskCommon.java | 9 +++++++-- .../com/google/cloud/tools/jib/maven/MojoCommon.java | 9 +++++++-- .../tools/jib/plugins/common/UpdateCheckerTest.java | 6 ++---- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/TaskCommon.java b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/TaskCommon.java index cd1b88a351..2a7df70fb3 100644 --- a/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/TaskCommon.java +++ b/jib-gradle-plugin/src/main/java/com/google/cloud/tools/jib/gradle/TaskCommon.java @@ -27,6 +27,7 @@ import java.util.HashMap; import java.util.Map; import java.util.Optional; +import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.logging.Level; @@ -51,8 +52,12 @@ static Future> newUpdateChecker( if (projectProperties.isOffline() || !logger.isLifecycleEnabled()) { return Futures.immediateFuture(Optional.empty()); } - return UpdateChecker.checkForUpdate( - Executors.newSingleThreadExecutor(), projectProperties::log, VERSION_URL); + ExecutorService executorService = Executors.newSingleThreadExecutor(); + try { + return UpdateChecker.checkForUpdate(executorService, projectProperties::log, VERSION_URL); + } finally { + executorService.shutdown(); + } } static void finishUpdateChecker( diff --git a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/MojoCommon.java b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/MojoCommon.java index 4133c01359..b193e9373c 100644 --- a/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/MojoCommon.java +++ b/jib-maven-plugin/src/main/java/com/google/cloud/tools/jib/maven/MojoCommon.java @@ -34,6 +34,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import org.apache.maven.artifact.versioning.DefaultArtifactVersion; @@ -55,8 +56,12 @@ static Future> newUpdateChecker( if (projectProperties.isOffline() || !logger.isInfoEnabled()) { return Futures.immediateFuture(Optional.empty()); } - return UpdateChecker.checkForUpdate( - Executors.newSingleThreadExecutor(), projectProperties::log, VERSION_URL); + ExecutorService executorService = Executors.newSingleThreadExecutor(); + try { + return UpdateChecker.checkForUpdate(executorService, projectProperties::log, VERSION_URL); + } finally { + executorService.shutdown(); + } } static void finishUpdateChecker( diff --git a/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java b/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java index 22133d7829..b8837cf0ba 100644 --- a/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java +++ b/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java @@ -18,7 +18,7 @@ import com.google.cloud.tools.jib.api.LogEvent.Level; import com.google.cloud.tools.jib.http.TestWebServer; -import com.google.common.util.concurrent.MoreExecutors; +import com.google.common.util.concurrent.Futures; import java.io.IOException; import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; @@ -30,7 +30,6 @@ import java.time.Instant; import java.util.Collections; import java.util.Optional; -import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import org.junit.After; import org.junit.Assert; @@ -207,8 +206,7 @@ public void testPerformUpdateCheck_failSilently() @Test public void testFinishUpdateCheck_success() { - ExecutorService executorService = MoreExecutors.newDirectExecutorService(); - Future> updateCheckFuture = executorService.submit(() -> Optional.of("Hello")); + Future> updateCheckFuture = Futures.immediateFuture(Optional.of("Hello")); Optional result = UpdateChecker.finishUpdateCheck(updateCheckFuture); Assert.assertTrue(result.isPresent()); Assert.assertEquals("Hello", result.get()); From d95d34bd3aaaae05e986bc69760169e7e925aec0 Mon Sep 17 00:00:00 2001 From: "tad.cordle@gmail.com" Date: Fri, 17 Jan 2020 15:45:41 -0500 Subject: [PATCH 34/36] Fix --- .../cloud/tools/jib/plugins/common/UpdateChecker.java | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java index c34fb81f12..df52fcce97 100644 --- a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java +++ b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java @@ -72,13 +72,10 @@ private static class VersionJsonTemplate implements JsonTemplate { */ public static Future> checkForUpdate( ExecutorService executorService, Consumer log, String versionUrl) { - Future> messageFuture = - executorService.submit( - () -> - performUpdateCheck( - log, Verify.verifyNotNull(ProjectInfo.VERSION), versionUrl, getConfigDir())); - executorService.shutdown(); - return messageFuture; + return executorService.submit( + () -> + performUpdateCheck( + log, Verify.verifyNotNull(ProjectInfo.VERSION), versionUrl, getConfigDir())); } @VisibleForTesting From 216bda4c48975c84729b6e9a123cc23b65157224 Mon Sep 17 00:00:00 2001 From: "tad.cordle@gmail.com" Date: Tue, 21 Jan 2020 10:49:09 -0500 Subject: [PATCH 35/36] Ignore unknown fields from pulled json --- .../jib/plugins/common/UpdateChecker.java | 2 ++ .../jib/plugins/common/UpdateCheckerTest.java | 20 +++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java index df52fcce97..40242292b5 100644 --- a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java +++ b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java @@ -16,6 +16,7 @@ package com.google.cloud.tools.jib.plugins.common; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.google.cloud.tools.jib.ProjectInfo; import com.google.cloud.tools.jib.api.LogEvent; import com.google.cloud.tools.jib.filesystem.XdgDirectories; @@ -58,6 +59,7 @@ void setDisableUpdateCheck(boolean disableUpdateCheck) { } /** JSON template for content downloaded during version check. */ + @JsonIgnoreProperties(ignoreUnknown = true) private static class VersionJsonTemplate implements JsonTemplate { private String latest = ""; } diff --git a/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java b/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java index b8837cf0ba..91434c2909 100644 --- a/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java +++ b/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/UpdateCheckerTest.java @@ -87,6 +87,26 @@ public void testPerformUpdateCheck_newVersionFound() throws IOException { Assert.assertTrue(Instant.parse(modifiedTime).isAfter(before)); } + @Test + public void testPerformUpdateCheck_newJsonField() + throws IOException, InterruptedException, GeneralSecurityException, URISyntaxException { + testWebServer = + new TestWebServer( + false, + Collections.singletonList( + "HTTP/1.1 200 OK\nContent-Length:18\n\n{\"latest\":\"2.0.0\",\"unknownField\":\"unknown\"}"), + 1); + setupConfigAndLastUpdateCheck(); + Optional message = + UpdateChecker.performUpdateCheck( + ignored -> {}, "1.0.2", testWebServer.getEndpoint(), configDir); + Assert.assertTrue(message.isPresent()); + Assert.assertEquals( + "A new version of Jib (2.0.0) is available (currently using 1.0.2). Update your build " + + "configuration to use the latest features and fixes!", + message.get()); + } + @Test public void testPerformUpdateCheck_onLatest() throws IOException { Instant before = Instant.now(); From 05bd091cf4f3228fcd6b46f2d7241c21668179af Mon Sep 17 00:00:00 2001 From: "tad.cordle@gmail.com" Date: Tue, 21 Jan 2020 10:59:52 -0500 Subject: [PATCH 36/36] Input stream --- .../cloud/tools/jib/plugins/common/UpdateChecker.java | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java index 40242292b5..62ea433a84 100644 --- a/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java +++ b/jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/UpdateChecker.java @@ -25,9 +25,7 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Strings; import com.google.common.base.Verify; -import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; @@ -144,12 +142,8 @@ static Optional performUpdateCheck( HttpURLConnection connection = (HttpURLConnection) new URL(versionUrl).openConnection(); try { connection.setConnectTimeout(3000); - BufferedReader bufferedReader = - new BufferedReader( - new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8)); VersionJsonTemplate version = - JsonTemplateMapper.readJson( - bufferedReader.readLine().trim(), VersionJsonTemplate.class); + JsonTemplateMapper.readJson(connection.getInputStream(), VersionJsonTemplate.class); Files.write(lastUpdateCheck, Instant.now().toString().getBytes(StandardCharsets.UTF_8)); if (currentVersion.equals(version.latest)) { return Optional.empty();