Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.regex.Pattern;
Expand Down Expand Up @@ -58,13 +59,14 @@
import com.blackduck.integration.detect.workflow.bdio.BdioOptions;
import com.blackduck.integration.detect.workflow.blackduck.BlackDuckPostOptions;
import com.blackduck.integration.detect.workflow.blackduck.developer.RapidScanOptions;
import com.blackduck.integration.detect.workflow.blackduck.settings.DetectPropertiesSetting;
import com.blackduck.integration.detect.workflow.blackduck.project.customfields.CustomFieldDocument;
import com.blackduck.integration.detect.workflow.blackduck.project.options.FindCloneOptions;
import com.blackduck.integration.detect.workflow.blackduck.project.options.ParentProjectMapOptions;
import com.blackduck.integration.detect.workflow.blackduck.project.options.ProjectGroupOptions;
import com.blackduck.integration.detect.workflow.blackduck.project.options.ProjectSyncOptions;
import com.blackduck.integration.detect.workflow.blackduck.project.options.ProjectVersionLicenseOptions;
import com.blackduck.integration.detect.workflow.blackduck.settings.DetectPropertiesSetting;
import com.blackduck.integration.detect.workflow.file.DirectoryManager;
import com.blackduck.integration.detect.workflow.file.DirectoryOptions;
import com.blackduck.integration.detect.workflow.phonehome.PhoneHomeOptions;
import com.blackduck.integration.detect.workflow.project.ProjectNameVersionOptions;
Expand Down Expand Up @@ -679,4 +681,11 @@ public Optional<String> getContainerScanFilePath() {
return Optional.ofNullable(detectConfiguration.getNullableValue(DetectProperties.DETECT_CONTAINER_SCAN_FILE));
}

public String getQuackPatchOutputDirectory(DirectoryManager directoryManager) {
String quackPatchOutput = detectConfiguration.getValue(DetectProperties.DETECT_QUACK_PATCH_OUTPUT);
if (Objects.isNull(quackPatchOutput) || quackPatchOutput.isEmpty()) {
return directoryManager.getScanOutputDirectory().getAbsolutePath();
}
return quackPatchOutput.trim();
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.blackduck.integration.detect.configuration;

import java.lang.reflect.Field;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
Expand Down Expand Up @@ -1148,7 +1147,7 @@ private DetectProperties() {
.build();

public static final StringProperty DETECT_QUACK_PATCH_OUTPUT =
StringProperty.newBuilder("detect.quack.patch.output", Paths.get("").toAbsolutePath().toString())
StringProperty.newBuilder("detect.quack.patch.output", "")
.setInfo("Quack Patch Output Directory", DetectPropertyFromVersion.VERSION_11_4_0)
.setHelp(
"Specifies the output directory for Quack Patch results.",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.util.Map;
import java.util.Set;

import com.blackduck.integration.detect.workflow.file.DirectoryManager;
import org.jetbrains.annotations.Nullable;

import static com.blackduck.integration.detect.workflow.componentlocationanalysis.GenerateComponentLocationAnalysisOperation.INVOKED_DETECTORS_AND_RELEVANT_FILES_JSON;
Expand Down Expand Up @@ -356,7 +357,11 @@ public NugetInspectorOptions createNugetInspectorOptions() {
Path nugetArtifactsPath = detectConfiguration.getPathOrNull(DetectProperties.DETECT_NUGET_ARTIFACTS_PATH);
Path relevantDetectorsAndFilesInfoPath = null;
if (detectConfiguration.getValue(DetectProperties.DETECT_QUACK_PATCH_ENABLED)) {
relevantDetectorsAndFilesInfoPath = Paths.get(detectConfiguration.getValue(DetectProperties.DETECT_QUACK_PATCH_OUTPUT).trim())
String quackPatchOutputPath = detectConfiguration.getValue(DetectProperties.DETECT_QUACK_PATCH_OUTPUT);
if (quackPatchOutputPath.isEmpty()) {
quackPatchOutputPath = DirectoryManager.getScanDirectoryName();
}
relevantDetectorsAndFilesInfoPath = Paths.get(quackPatchOutputPath)
.resolve(QUACKPATCH_SUBDIRECTORY_NAME)
.resolve(INVOKED_DETECTORS_AND_RELEVANT_FILES_JSON);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import com.blackduck.integration.configuration.property.base.TypedProperty;
import com.blackduck.integration.configuration.property.deprecation.DeprecatedValueUsage;
import com.blackduck.integration.detect.configuration.DetectProperties;
import com.blackduck.integration.detect.configuration.DetectPropertyConfiguration;
import com.blackduck.integration.detect.configuration.DetectUserFriendlyException;
import com.blackduck.integration.detect.configuration.enumeration.ExitCodeType;
import com.blackduck.integration.detect.workflow.event.EventSystem;
Expand Down Expand Up @@ -108,9 +107,7 @@ public Optional<DetectUserFriendlyException> validateForPropertyParseErrors() th
}

// Method to validate Quack Patch output path and return an Optional containing a DetectUserFriendlyException if the validation fails, or an empty Optional if it passes.
public Optional<DetectUserFriendlyException> validateQuackPatchOutputPath(DetectPropertyConfiguration detectConfiguration) {
String quackPatchOutput = detectConfiguration.getValue(DetectProperties.DETECT_QUACK_PATCH_OUTPUT).trim();

public Optional<DetectUserFriendlyException> validateQuackPatchOutputPath(String quackPatchOutput) {
// Fail for empty string since that would cause issues later on when we try to write to it, and it's likely the user just forgot to set it if they enabled Quack Patch but left this blank.
if (quackPatchOutput.isEmpty()) {
return Optional.of(new DetectUserFriendlyException(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,11 @@
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.Collections;
import java.util.LinkedHashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.blackduck.integration.configuration.config.MaskedRawValueResult;
import com.blackduck.integration.configuration.property.base.TypedProperty;
import com.blackduck.integration.configuration.config.PropertyConfiguration;
import com.blackduck.integration.configuration.property.base.TypedProperty;
import com.blackduck.integration.configuration.property.types.enumallnone.list.AllEnumList;
Expand Down Expand Up @@ -56,7 +53,6 @@
import com.blackduck.integration.detect.lifecycle.boot.product.ProductBoot;
import com.blackduck.integration.detect.lifecycle.run.data.ProductRunData;
import com.blackduck.integration.detect.lifecycle.run.singleton.BootSingletons;
import com.blackduck.integration.detect.workflow.blackduck.settings.DetectPropertiesSetting;
import com.blackduck.integration.detect.tool.cache.InstalledToolLocator;
import com.blackduck.integration.detect.tool.cache.InstalledToolManager;
import com.blackduck.integration.detect.util.filter.DetectToolFilter;
Expand Down Expand Up @@ -168,26 +164,19 @@ public Optional<DetectBootResult> boot(String detectVersion, String detectBuildD

Configuration freemarkerConfiguration = detectBootFactory.createFreemarkerConfiguration();
DetectPropertyConfiguration detectConfiguration = new DetectPropertyConfiguration(propertyConfiguration, new SimplePathResolver());
// If quack patch is enabled, we need to validate the output path before doing anything else since it could cause Detect to fail later on if it's not valid, and we want to fail as early as possible with a clear message about what the issue is.
Optional<DetectUserFriendlyException> quackPatchError = detectConfigurationBootManager.validateQuackPatchOutputPath(detectConfiguration);
if (quackPatchError.isPresent()) {
return Optional.of(DetectBootResult.exception(quackPatchError.get(), propertyConfiguration));
}

DetectConfigurationFactory detectConfigurationFactory = new DetectConfigurationFactory(detectConfiguration, gson);
DirectoryManager directoryManager = detectBootFactory.createDirectoryManager(detectConfigurationFactory);

// If quack patch is enabled, we need to validate the output path before doing anything else since it could cause Detect to fail later on if it's not valid, and we want to fail as early as possible with a clear message about what the issue is.
// If quack patch is enabled, we need to validate the output path before doing anything else since it could cause Detect to fail later on if it's not valid, and we want to fail as early as possible with a clear message about what the issue is.
if (Boolean.TRUE.equals(detectConfigurationFactory.isQuackPatchEnabled())) {
Optional<DetectUserFriendlyException> quackPatchError = detectConfigurationBootManager.validateQuackPatchOutputPath(detectConfiguration);
if (quackPatchError.isPresent()) {
return Optional.of(DetectBootResult.exception(quackPatchError.get(), propertyConfiguration));
}
Optional<DetectUserFriendlyException> quackPatchError = detectConfigurationBootManager.validateQuackPatchOutputPath(detectConfigurationFactory.getQuackPatchOutputDirectory(directoryManager));
if (quackPatchError.isPresent()) {
return Optional.of(DetectBootResult.exception(quackPatchError.get(), propertyConfiguration));
}
}

boolean autonomousScanEnabled = detectConfiguration.getValue(DetectProperties.DETECT_AUTONOMOUS_SCAN_ENABLED);

DirectoryManager directoryManager = detectBootFactory.createDirectoryManager(detectConfigurationFactory);

// TODO Scan settings model obtained below is to be used by the delta-checking operations
AutonomousManager autonomousManager = new AutonomousManager(directoryManager, detectConfiguration, autonomousScanEnabled, maskedRawPropertyValues);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@
import com.blackduck.integration.componentlocator.beans.Component;
import com.blackduck.integration.detect.configuration.DetectConfigurationFactory;
import com.blackduck.integration.detect.configuration.DetectInfo;
import com.blackduck.integration.detect.configuration.DetectProperties;
import com.blackduck.integration.detect.configuration.DetectUserFriendlyException;
import com.blackduck.integration.detect.configuration.DetectorToolOptions;
import com.blackduck.integration.detect.configuration.connection.ConnectionFactory;
Expand All @@ -80,8 +79,6 @@
import com.blackduck.integration.detect.lifecycle.OperationException;
import com.blackduck.integration.detect.lifecycle.autonomous.AutonomousManager;
import com.blackduck.integration.detect.lifecycle.boot.decision.CorrelatedScanningDecision;
import com.blackduck.integration.detect.lifecycle.boot.decision.CorrelatedScanningDecision;
import com.blackduck.integration.detect.workflow.DetectRunId;
import com.blackduck.integration.detect.lifecycle.run.DetectFontLoaderFactory;
import com.blackduck.integration.detect.lifecycle.run.data.BlackDuckRunData;
import com.blackduck.integration.detect.lifecycle.run.data.DockerTargetData;
Expand Down Expand Up @@ -402,7 +399,7 @@ public final DetectorToolResult executeDetectors() throws OperationException {

if (detectConfigurationFactory.isQuackPatchPossible()) {
try {
detectorTool.saveExtractedDetectorsAndTheirRelevantFilePaths(toolResult);
detectorTool.saveExtractedDetectorsAndTheirRelevantFilePaths(toolResult, directoryManager);
} catch (IOException e) {
throw new RuntimeException("Something went wrong writing relevant files: " + e.getMessage());
}
Expand Down Expand Up @@ -873,7 +870,7 @@ public final File generateFullRapidJsonFile(List<Response> scanResults) throws O
return auditLog.namedPublic(
"Generate Rapid Full Json File",
"RapidScan",
() -> new RapidModeGenerateJsonOperation(htmlEscapeDisabledGson, directoryManager).generateJsonFileFromString(scanResults.get(0).getContentString(), detectConfigurationFactory.getDetectPropertyConfiguration().getValue(DetectProperties.DETECT_QUACK_PATCH_OUTPUT).trim())
() -> new RapidModeGenerateJsonOperation(htmlEscapeDisabledGson, directoryManager).generateJsonFileFromString(scanResults.get(0).getContentString(), detectConfigurationFactory.getQuackPatchOutputDirectory(directoryManager))
);
}

Expand All @@ -887,7 +884,7 @@ public void runQuackPatch(File rapidFullResultsJson) throws OperationException {
() -> {
publishResult(
new GenerateComponentLocationAnalysisOperation(detectConfigurationFactory, statusEventPublisher, exitCodePublisher)
.runQuackPatch(rapidFullResultsJson, detectConfigurationFactory)
.runQuackPatch(rapidFullResultsJson, detectConfigurationFactory, detectConfigurationFactory.getQuackPatchOutputDirectory(directoryManager))
);
}
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import com.blackduck.integration.blackduck.bdio2.model.GitInfo;
import com.blackduck.integration.common.util.finder.FileFinder;
import com.blackduck.integration.detect.configuration.DetectConfigurationFactory;
import com.blackduck.integration.detect.configuration.DetectProperties;
import com.blackduck.integration.detect.configuration.ExcludeIncludeEnumFilter;
import com.blackduck.integration.detect.configuration.enumeration.ExitCodeType;
import com.blackduck.integration.detect.lifecycle.shutdown.ExitCodePublisher;
Expand Down Expand Up @@ -96,10 +95,10 @@ public DetectorTool(
this.detectConfigurationFactory = detectConfigurationFactory;
}

public void saveExtractedDetectorsAndTheirRelevantFilePaths(DetectorToolResult toolResult) throws IOException {
public void saveExtractedDetectorsAndTheirRelevantFilePaths(DetectorToolResult toolResult, DirectoryManager directoryManager) throws IOException {
// Create map of extracted detectors and their relevant files
Map<String, List<String>> detectorsAndFiles = new HashMap<>();
Path quackDir = Paths.get(detectConfigurationFactory.getDetectPropertyConfiguration().getValue(DetectProperties.DETECT_QUACK_PATCH_OUTPUT).trim(), QUACKPATCH_SUBDIRECTORY_NAME);
Path quackDir = Paths.get(detectConfigurationFactory.getQuackPatchOutputDirectory(directoryManager), QUACKPATCH_SUBDIRECTORY_NAME);
ObjectMapper mapper = new ObjectMapper();
Path jsonFile = quackDir.resolve(INVOKED_DETECTORS_AND_RELEVANT_FILES_JSON);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,15 +85,13 @@ public ComponentLocatorResult locateComponents(Set<Component> componentsSet, Fil
return new ComponentLocatorResult(outputFilepath);
}

public QuackPatchResult runQuackPatch(File rapidFullResultsFile, DetectConfigurationFactory configFactory) {
public QuackPatchResult runQuackPatch(File rapidFullResultsFile, DetectConfigurationFactory configFactory, String quackPatchOutputDir) {
logger.info("Attempting Quack Patch.");
// if the detect.quack.patch.output property value set use that as output folder, otherwise default it to current working directory
String quackPatchOutputDir = configFactory.getDetectPropertyConfiguration().getValue(DetectProperties.DETECT_QUACK_PATCH_OUTPUT).trim();
logger.debug("Quack Patch output directory set to: {}", quackPatchOutputDir);
Map<String, List<String>> relevantDetectorsAndFiles = loadDetectorsAndFiles(quackPatchOutputDir + File.separator + QUACKPATCH_SUBDIRECTORY_NAME + File.separator + INVOKED_DETECTORS_AND_RELEVANT_FILES_JSON);
String llmKey = configFactory.getDetectPropertyConfiguration().getValue(DetectProperties.DETECT_LLM_API_KEY);
String llmName = configFactory.getDetectPropertyConfiguration().getValue(DetectProperties.DETECT_LLM_NAME);
String llmURL = configFactory.getDetectPropertyConfiguration().getValue(DetectProperties.DETECT_LLM_API_ENDPOINT);
String llmURL = configFactory.getDetectPropertyConfiguration().getValue(DetectProperties.DETECT_LLM_API_ENDPOINT);
ComponentLocator.runQuackPatch(rapidFullResultsFile, relevantDetectorsAndFiles, llmKey, llmName, llmURL, quackPatchOutputDir);
return new QuackPatchResult(getQuackPatchOutputDirectory(new File(quackPatchOutputDir)));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
package com.blackduck.integration.detect.workflow.diagnostic;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;

import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.blackduck.integration.configuration.config.PropertyConfiguration;
import com.blackduck.integration.detect.configuration.DetectInfo;
import com.blackduck.integration.detect.configuration.DetectProperties;
import com.blackduck.integration.detect.workflow.DetectRunId;
import static com.blackduck.integration.detect.workflow.componentlocationanalysis.GenerateComponentLocationAnalysisOperation.QUACKPATCH_SUBDIRECTORY_NAME;
import com.blackduck.integration.detect.workflow.event.EventSystem;
import com.blackduck.integration.detect.workflow.file.DirectoryManager;

Expand Down Expand Up @@ -134,9 +138,24 @@ public void appendBlackDuckServerProperties(Map<String, String> serverProperties
}

private boolean createZip() {
// If quack patch is enabled, then add quack patch output directory to the zip
if (propertyConfiguration.getValueOrDefault(DetectProperties.DETECT_QUACK_PATCH_ENABLED)) {
String quackPatchOutputDirPath = propertyConfiguration.getValueOrDefault(DetectProperties.DETECT_QUACK_PATCH_OUTPUT);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unable to use the helper function (getQuackPatchOutputDirectory from detectConfigurationFactory) to get the quack patch output path here due to missing config context. Hence, the duplication of code.

// If quack patch output path is customized, then explicitly include it in the diagnostic zip. Otherwise, default behaviour will automatically pack it.
if (!quackPatchOutputDirPath.isEmpty()) {
quackPatchOutputDirPath = quackPatchOutputDirPath + File.separator + QUACKPATCH_SUBDIRECTORY_NAME;
logger.info("Adding quack patch output dir {} to the diagnostic zip.", quackPatchOutputDirPath);
// Copy directory quackPatchOutputDirPath to directoryManager.getRunsOutputDirectory()
try {
FileUtils.copyDirectory(new File(quackPatchOutputDirPath), new File(directoryManager.getScanOutputDirectory().getAbsolutePath() + File.separator + QUACKPATCH_SUBDIRECTORY_NAME));
} catch (IOException e) {
logger.error("Failed to copy quack patch output directory to runs directory. Error: {}", e.getMessage());
return false;
}
}
}
Comment on lines +142 to +156
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If quack patch output path is not set, output will be written to runs/<timestamp-dir>/scan folder and diagnostics will have that information by default. If the output path is customized, then copying that directory into runs/<timestamp-dir>/scan folder so that diagnostics process can pick it up as default.

Note: Diagnostics archive process was adding the files based on its path. If the target file is outside runs dir context, compress logic is trying to add it as a relative path (e.g. runs/../../quack-patch/***). Copying quack-patch files into scan would keep the behaviour consistent.

List<File> directoriesToCompress = new ArrayList<>();
directoriesToCompress.add(directoryManager.getRunHomeDirectory());

DiagnosticZipCreator zipper = new DiagnosticZipCreator();
return zipper.createDiagnosticZip(detectRunId.getRunId(), directoryManager.getRunsOutputDirectory(), directoriesToCompress);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ void testSaveExtractedDetectorsAndTheirRelevantFilePaths_gradle() throws Excepti
DetectConfigurationFactory detectConfigurationFactory = DetectConfigurationFactoryTestUtils.factoryOf(Pair.of(DetectProperties.DETECT_QUACK_PATCH_OUTPUT, tempDir.toString()));

new DetectorTool(null, null, null, null, null, null, null, detectConfigurationFactory)
.saveExtractedDetectorsAndTheirRelevantFilePaths(toolResult);
.saveExtractedDetectorsAndTheirRelevantFilePaths(toolResult, directoryManager);

File outputFile = new File(
new File(detectConfigurationFactory.getDetectPropertyConfiguration().getValue(DetectProperties.DETECT_QUACK_PATCH_OUTPUT), QUACKPATCH_SUBDIRECTORY_NAME),
Expand Down