diff --git a/src/main/java/com/blackduck/integration/blackduck/dockerinspector/config/Config.java b/src/main/java/com/blackduck/integration/blackduck/dockerinspector/config/Config.java index dae196e1..802781db 100644 --- a/src/main/java/com/blackduck/integration/blackduck/dockerinspector/config/Config.java +++ b/src/main/java/com/blackduck/integration/blackduck/dockerinspector/config/Config.java @@ -156,6 +156,10 @@ public class Config { @Value("${inspector.repository:blackducksoftware}") private String inspectorRepository = "blackducksoftware"; + @ValueDescription(description = "Preferred registry for Docker Inspector images. If empty, the images will always be pulled from Docker HUB.", defaultValue = "repo.blackduck.com/containers/", group = Config.GROUP_PRIVATE, deprecated = false) + @Value("${inspector.repository.preferred.registry:repo.blackduck.com/containers/}") + private String inspectorRepositoryPreferredRegistry = "repo.blackduck.com/containers/"; + @ValueDescription(description = "Docker Inspector image \"family\"", defaultValue = "", group = Config.GROUP_PRIVATE, deprecated = false) @Value("${inspector.image.family:}") private String inspectorImageFamily = ""; @@ -427,6 +431,10 @@ public String getInspectorRepository() { return optionsByFieldName.get("inspectorRepository").getResolvedValue(); } + public String getInspectorRepositoryPreferredRegistry() { + return optionsByFieldName.get("inspectorRepositoryPreferredRegistry").getResolvedValue(); + } + public String getInspectorImageFamily() { return optionsByFieldName.get("inspectorImageFamily").getResolvedValue(); } @@ -573,6 +581,7 @@ protected void preventFinal() { this.workingDirPath = null; this.systemPropertiesPath = null; this.inspectorRepository = null; + this.inspectorRepositoryPreferredRegistry = null; this.cleanupInspectorContainer = null; this.cleanupInspectorImage = null; this.organizeComponentsByLayer = null; diff --git a/src/main/java/com/blackduck/integration/blackduck/dockerinspector/httpclient/ImageInspectorClientStartServices.java b/src/main/java/com/blackduck/integration/blackduck/dockerinspector/httpclient/ImageInspectorClientStartServices.java index 1862088c..8e4f5b4d 100644 --- a/src/main/java/com/blackduck/integration/blackduck/dockerinspector/httpclient/ImageInspectorClientStartServices.java +++ b/src/main/java/com/blackduck/integration/blackduck/dockerinspector/httpclient/ImageInspectorClientStartServices.java @@ -40,6 +40,9 @@ public class ImageInspectorClientStartServices extends ImageInspectorClient { private final String II_SERVICE_URI_SCHEME = "http"; private final String II_SERVICE_HOST = "localhost"; + // Track if preferred repository is unreachable to avoid repeated attempts + private boolean preferredRepoUnreachable = false; + @Autowired private Config config; @@ -247,16 +250,16 @@ private ContainerDetails ensureServiceReady(IntHttpClient httpClient, URI imageI imageInspectorRepo = inspectorImages.getInspectorImageName(inspectorOs); imageInspectorTag = inspectorImages.getInspectorImageTag(inspectorOs); logger.debug(String.format("Need to pull/run image %s:%s to start the %s service", imageInspectorRepo, imageInspectorTag, imageInspectorUri.toString())); - Optional imageId = pullImageTolerantly(imageInspectorRepo, imageInspectorTag); + PullResult pullResult = pullImageTolerantly(imageInspectorRepo, imageInspectorTag); int containerPort = imageInspectorServices.getImageInspectorContainerPort(inspectorOs); int hostPort = imageInspectorServices.getImageInspectorHostPort(inspectorOs); String containerName = containerNameManager.deriveContainerNameFromImageInspectorRepo(imageInspectorRepo); - String containerId = dockerClientManager.startContainerAsService(imageInspectorRepo, imageInspectorTag, containerName, inspectorOs, containerPort, hostPort, + String containerId = dockerClientManager.startContainerAsService(pullResult.getActualRepoName(), imageInspectorTag, containerName, inspectorOs, containerPort, hostPort, Config.IMAGEINSPECTOR_WS_APPNAME, String.format("%s/%s/%s.jar", Config.CONTAINER_BLACKDUCK_DIR, Config.IMAGEINSPECTOR_WS_APPNAME, Config.IMAGEINSPECTOR_WS_APPNAME), deriveInspectorBaseUri(config.getImageInspectorHostPortAlpine()).toString(), deriveInspectorBaseUri(config.getImageInspectorHostPortCentos()).toString(), deriveInspectorBaseUri(config.getImageInspectorHostPortUbuntu()).toString()); - ContainerDetails containerDetails = new ContainerDetails(imageId.orElse(null), containerId); + ContainerDetails containerDetails = new ContainerDetails(pullResult.getImageId().orElse(null), containerId); serviceIsUp = imageInspectorServices.startService(httpClient, imageInspectorUri, imageInspectorRepo, imageInspectorTag); if (!serviceIsUp) { dockerClientManager.logServiceLogAsDebug(containerId); @@ -266,15 +269,52 @@ private ContainerDetails ensureServiceReady(IntHttpClient httpClient, URI imageI return containerDetails; } - private Optional pullImageTolerantly(String imageInspectorRepo, String imageInspectorTag) { + private PullResult pullImageTolerantly(String imageInspectorRepo, String imageInspectorTag) { Optional imageId = Optional.empty(); + + String preferredRegistry = config.getInspectorRepositoryPreferredRegistry(); + logger.debug("Preferred registry: {}", preferredRegistry); + if (!preferredRepoUnreachable && !preferredRegistry.isEmpty()) { + String preferredRepo = preferredRegistry + imageInspectorRepo; + try { + logger.info("Attempting to pull from preferred repository: {}:{}", preferredRepo, imageInspectorTag); + imageId = Optional.ofNullable(dockerClientManager.pullImage(preferredRepo, imageInspectorTag)); + logger.info("Successfully pulled from preferred repository. Image ID: {}", imageId); + return new PullResult(imageId, preferredRepo); + } catch (Exception e) { + logger.warn("Unable to pull docker image from preferred repository {}:{}, marking as unreachable and falling back to Docker HUB. Error: {}", + preferredRepo, imageInspectorTag, e.getMessage()); + preferredRepoUnreachable = true; + } + } else { + logger.debug("Skipping preferred repository and proceeding to Docker HUB fallback"); + } + try { + logger.info("Attempting to pull from Docker HUB: {}:{}", imageInspectorRepo, imageInspectorTag); imageId = Optional.ofNullable(dockerClientManager.pullImage(imageInspectorRepo, imageInspectorTag)); - logger.debug(String.format("Pulled image ID %s", imageId.orElse(""))); + logger.debug("Pulled image ID {}", imageId); } catch (Exception e) { - logger.warn(String.format("Unable to pull docker image %s:%s; proceeding anyway since it may already exist locally", imageInspectorRepo, imageInspectorTag)); + logger.warn("Unable to pull docker image {}:{} from Docker HUB; proceeding anyway since it may already exist locally", imageInspectorRepo, imageInspectorTag); } - return imageId; + return new PullResult(imageId, imageInspectorRepo); } + private static class PullResult { + private final Optional imageId; + private final String actualRepoName; + + public PullResult(Optional imageId, String actualRepoName) { + this.imageId = imageId; + this.actualRepoName = actualRepoName; + } + + public Optional getImageId() { + return imageId; + } + + public String getActualRepoName() { + return actualRepoName; + } + } } diff --git a/src/test/java/com/blackduck/integration/blackduck/dockerinspector/unit/httpclient/IiClientContainersStartedAsNeededTest.java b/src/test/java/com/blackduck/integration/blackduck/dockerinspector/unit/httpclient/IiClientContainersStartedAsNeededTest.java index ef1cbd04..b980238f 100644 --- a/src/test/java/com/blackduck/integration/blackduck/dockerinspector/unit/httpclient/IiClientContainersStartedAsNeededTest.java +++ b/src/test/java/com/blackduck/integration/blackduck/dockerinspector/unit/httpclient/IiClientContainersStartedAsNeededTest.java @@ -61,6 +61,7 @@ public class IiClientContainersStartedAsNeededTest { @Test public void test() throws IntegrationException, IOException, InterruptedException { Mockito.when(config.isImageInspectorServiceStart()).thenReturn(true); + Mockito.when(config.getInspectorRepositoryPreferredRegistry()).thenReturn(""); Mockito.when(imageInspectorServices.getDefaultImageInspectorHostPortBasedOnDistro()).thenReturn(8080); Mockito.when(config.getCommandTimeout()).thenReturn(5000L); Mockito.when(config.getImageInspectorDefaultDistro()).thenReturn("ubuntu");