Skip to content

Commit

Permalink
Merge pull request #20113 from geoand/k8s-generated-resources
Browse files Browse the repository at this point in the history
Introduce build item that gives access to generated k8s resources
  • Loading branch information
geoand authored Sep 14, 2021
2 parents ad20820 + 7ca2664 commit 91d96c7
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package io.quarkus.kubernetes.spi;

import io.quarkus.builder.item.MultiBuildItem;

/**
* Represents a resource generated by the quarkus-kubernetes extension
*/
public final class GeneratedKubernetesResourceBuildItem extends MultiBuildItem {

private final String name;
private final byte[] content;

public GeneratedKubernetesResourceBuildItem(String name, byte[] content) {
this.name = name;
this.content = content;
}

public String getName() {
return name;
}

public byte[] getContent() {
return content;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import io.quarkus.kubernetes.spi.ConfiguratorBuildItem;
import io.quarkus.kubernetes.spi.CustomProjectRootBuildItem;
import io.quarkus.kubernetes.spi.DecoratorBuildItem;
import io.quarkus.kubernetes.spi.GeneratedKubernetesResourceBuildItem;
import io.quarkus.kubernetes.spi.KubernetesDeploymentTargetBuildItem;
import io.quarkus.kubernetes.spi.KubernetesPortBuildItem;
import io.quarkus.runtime.LaunchMode;
Expand Down Expand Up @@ -91,7 +92,8 @@ public void build(ApplicationInfoBuildItem applicationInfo,
List<ConfiguratorBuildItem> configurators,
List<DecoratorBuildItem> decorators,
Optional<CustomProjectRootBuildItem> customProjectRoot,
BuildProducer<GeneratedFileSystemResourceBuildItem> generatedResourceProducer) {
BuildProducer<GeneratedFileSystemResourceBuildItem> generatedResourceProducer,
BuildProducer<GeneratedKubernetesResourceBuildItem> generatedKubernetesResourceProducer) {

List<ConfiguratorBuildItem> allConfigurationRegistry = new ArrayList<>(configurators);
List<DecoratorBuildItem> allDecorators = new ArrayList<>(decorators);
Expand Down Expand Up @@ -169,6 +171,9 @@ public void build(ApplicationInfoBuildItem applicationInfo,
Path targetPath = outputTarget.getOutputDirectory().resolve(KUBERNETES).resolve(fileName);
String relativePath = targetPath.toAbsolutePath().toString().replace(root.toAbsolutePath().toString(), "");

generatedKubernetesResourceProducer.produce(new GeneratedKubernetesResourceBuildItem(fileName,
resourceEntry.getValue().getBytes(StandardCharsets.UTF_8)));

if (fileName.endsWith(".yml") || fileName.endsWith(".json")) {
String target = fileName.substring(0, fileName.lastIndexOf("."));
if (!deploymentTargets.contains(target)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package io.quarkus.it.kubernetes;

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

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

import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.builder.BuildContext;
import io.quarkus.deployment.builditem.GeneratedResourceBuildItem;
import io.quarkus.kubernetes.spi.GeneratedKubernetesResourceBuildItem;
import io.quarkus.test.ProdBuildResults;
import io.quarkus.test.ProdModeTestBuildStep;
import io.quarkus.test.ProdModeTestResults;
import io.quarkus.test.QuarkusProdModeTest;

public class GeneratedKubernetesResourcesBuildItemTest {

@RegisterExtension
static final QuarkusProdModeTest config = new QuarkusProdModeTest()
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class).addClasses(GreetingResource.class))
.setApplicationName("basic")
.setApplicationVersion("0.1-SNAPSHOT")
.addBuildChainCustomizerEntries(new QuarkusProdModeTest.BuildChainCustomizerEntry(
CustomGeneratedKubernetesResourcesHandler.class,
Collections.singletonList(GeneratedResourceBuildItem.class),
Collections.singletonList(GeneratedKubernetesResourceBuildItem.class)));

@ProdBuildResults
private ProdModeTestResults prodModeTestResults;

@Test
public void test() {
Path buildDir = prodModeTestResults.getBuildDir();
assertThat(buildDir).isDirectory();
Path quarkusAppDir = buildDir.resolve("quarkus-app");
assertThat(quarkusAppDir).isDirectory();
Path quarkusDir = quarkusAppDir.resolve("quarkus");
assertThat(quarkusDir).isDirectory();
Path generatedBytecodeJar = quarkusDir.resolve("generated-bytecode.jar");
assertThat(generatedBytecodeJar).isRegularFile();
try (JarFile jarFile = new JarFile(generatedBytecodeJar.toFile())) {
assertEntry(jarFile, "dummy-kubernetes.json");
assertEntry(jarFile, "dummy-kubernetes.yml");
} catch (IOException e) {
fail("Unable to verify contents of generated-bytecode jar file: " + e.getMessage());
}
}

private void assertEntry(JarFile jarFile, String name) {
JarEntry jarEntry = jarFile.getJarEntry(name);
if (jarEntry == null) {
fail(String.format("Unable to locate expected entry '%s' in generated-bytecode jar", name));
}
}

/**
* This simulates an extension using {@link GeneratedKubernetesResourceBuildItem}.
* It's testable because it writes the contents of each build item to the generate-bytecode jar.
*/
public static class CustomGeneratedKubernetesResourcesHandler extends ProdModeTestBuildStep {

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

@Override
public void execute(BuildContext context) {
List<GeneratedKubernetesResourceBuildItem> k8sResources = context
.consumeMulti(GeneratedKubernetesResourceBuildItem.class);
for (GeneratedKubernetesResourceBuildItem bi : k8sResources) {
context.produce(new GeneratedResourceBuildItem("dummy-" + bi.getName(), bi.getContent()));
}
}
}
}

0 comments on commit 91d96c7

Please sign in to comment.