Skip to content

Commit

Permalink
Merge pull request #41808 from iocanel/kubernetes-output-directory
Browse files Browse the repository at this point in the history
Introduce build item to control kubernetes output dir
  • Loading branch information
geoand authored Jul 11, 2024
2 parents aaf2960 + e365794 commit a0a7fb5
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package io.quarkus.kubernetes.spi;

import java.nio.file.Path;

import io.quarkus.builder.item.SimpleBuildItem;

/**
* Build item that allows us to supply a custom output dir instead of defaulting to {project.target.dir}/kubernetes
* It's different from the {@link KubernetesOutputDirBuildItem} as it's used to communicate the intention to override the dir
* while {@link KubernetesOutputDirBuildItem} is used to communicate the effective output dir.
*/
public final class CustomKubernetesOutputDirBuildItem extends SimpleBuildItem {

private final Path outputDir;

public CustomKubernetesOutputDirBuildItem(Path outputDir) {
this.outputDir = outputDir;
}

public Path getOutputDir() {
return outputDir;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
import io.quarkus.deployment.util.FileUtil;
import io.quarkus.kubernetes.spi.ConfigurationSupplierBuildItem;
import io.quarkus.kubernetes.spi.ConfiguratorBuildItem;
import io.quarkus.kubernetes.spi.CustomKubernetesOutputDirBuildItem;
import io.quarkus.kubernetes.spi.CustomProjectRootBuildItem;
import io.quarkus.kubernetes.spi.DecoratorBuildItem;
import io.quarkus.kubernetes.spi.DekorateOutputBuildItem;
Expand Down Expand Up @@ -115,6 +116,7 @@ public void build(ApplicationInfoBuildItem applicationInfo,
List<DecoratorBuildItem> decorators,
BuildProducer<DekorateOutputBuildItem> dekorateSessionProducer,
Optional<CustomProjectRootBuildItem> customProjectRoot,
Optional<CustomKubernetesOutputDirBuildItem> customOutputDir,
BuildProducer<GeneratedFileSystemResourceBuildItem> generatedResourceProducer,
BuildProducer<GeneratedKubernetesResourceBuildItem> generatedKubernetesResourceProducer,
BuildProducer<KubernetesOutputDirectoryBuildItem> outputDirectoryBuildItemBuildProducer) {
Expand Down Expand Up @@ -187,8 +189,13 @@ public void build(ApplicationInfoBuildItem applicationInfo,
}
});

Path targetDirectory = getEffectiveOutputDirectory(kubernetesConfig, project.getRoot(),
outputTarget.getOutputDirectory());
//The targetDirectory should be the custom if provided, oterwise the 'default' output directory.
//I this case 'default' means that one that we used until now (up until we introduced the ability to override).
Path targetDirectory = customOutputDir
.map(c -> c.getOutputDir())
.map(d -> d.isAbsolute() ? d : project.getRoot().resolve(d))
.orElseGet(() -> getEffectiveOutputDirectory(kubernetesConfig, project.getRoot(),
outputTarget.getOutputDirectory()));

outputDirectoryBuildItemBuildProducer.produce(new KubernetesOutputDirectoryBuildItem(targetDirectory));

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package io.quarkus.it.kubernetes;

import static org.assertj.core.api.Assertions.assertThat;

import java.io.IOException;
import java.nio.file.Path;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.fabric8.kubernetes.api.model.HasMetadata;
import io.fabric8.kubernetes.api.model.apps.Deployment;
import io.quarkus.builder.BuildContext;
import io.quarkus.kubernetes.spi.CustomKubernetesOutputDirBuildItem;
import io.quarkus.kubernetes.spi.CustomProjectRootBuildItem;
import io.quarkus.test.ProdBuildResults;
import io.quarkus.test.ProdModeTestBuildStep;
import io.quarkus.test.ProdModeTestResults;
import io.quarkus.test.QuarkusProdModeTest;

public class KubernetesWithCustomOutputDirTest {

private static final String APP_NAME = "kubernetes-with-custom-output-dir";
@RegisterExtension
static final QuarkusProdModeTest config = new QuarkusProdModeTest()
.withApplicationRoot((jar) -> jar.addClasses(GreetingResource.class))
.setApplicationName(APP_NAME)
.setApplicationVersion("0.1-SNAPSHOT")
.addBuildChainCustomizerEntries(
new QuarkusProdModeTest.BuildChainCustomizerEntry(CustomProjectRootBuildItemProducerProdMode.class,
List.of(CustomProjectRootBuildItem.class, CustomKubernetesOutputDirBuildItem.class),
Collections.emptyList()));

@ProdBuildResults
private ProdModeTestResults prodModeTestResults;

@Test
public void assertGeneratedResources() throws IOException {
final Path kubernetesDir = prodModeTestResults.getBuildDir().getParent().resolve("custom-sources")
.resolve(".kubernetes");
assertThat(kubernetesDir)
.isDirectoryContaining(p -> p.getFileName().endsWith("kubernetes.json"))
.isDirectoryContaining(p -> p.getFileName().endsWith("kubernetes.yml"))
.satisfies(p -> assertThat(p.toFile().listFiles()).hasSize(2));
List<HasMetadata> kubernetesList = DeserializationUtil.deserializeAsList(kubernetesDir.resolve("kubernetes.yml"));
assertThat(kubernetesList).filteredOn(h -> h.getMetadata().getName().equals(APP_NAME))
.filteredOn(e -> e instanceof Deployment).singleElement().satisfies(d -> {
assertThat(d.getMetadata()).satisfies(m -> {
assertThat(m.getName()).isEqualTo(APP_NAME);
});
});
}

public static class CustomProjectRootBuildItemProducerProdMode extends ProdModeTestBuildStep {

public CustomProjectRootBuildItemProducerProdMode(Map<String, Object> testContext) {
super(testContext);
}

@Override
public void execute(BuildContext context) {
context.produce(new CustomProjectRootBuildItem(
(Path) getTestContext().get(QuarkusProdModeTest.BUILD_CONTEXT_CUSTOM_SOURCES_PATH_KEY)));
context.produce(new CustomKubernetesOutputDirBuildItem(
((Path) getTestContext().get(QuarkusProdModeTest.BUILD_CONTEXT_CUSTOM_SOURCES_PATH_KEY))
.resolve(".kubernetes")));
}
}
}

0 comments on commit a0a7fb5

Please sign in to comment.