View Javadoc
1   package io.micronaut.build.jib;
2   
3   import com.google.cloud.tools.jib.api.buildplan.*;
4   import com.google.cloud.tools.jib.buildplan.UnixPathParser;
5   import com.google.cloud.tools.jib.maven.extension.JibMavenPluginExtension;
6   import com.google.cloud.tools.jib.maven.extension.MavenData;
7   import com.google.cloud.tools.jib.plugins.extension.ExtensionLogger;
8   import com.google.cloud.tools.jib.plugins.extension.JibPluginExtensionException;
9   import io.micronaut.build.MicronautRuntime;
10  import io.micronaut.build.services.ApplicationConfigurationService;
11  import io.micronaut.build.services.JibConfigurationService;
12  import org.apache.maven.artifact.versioning.ArtifactVersion;
13  import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
14  
15  import java.util.*;
16  
17  /**
18   * Jib extension to support building Docker images
19   *
20   * @author Álvaro Sánchez-Mariscal
21   * @since 1.1
22   */
23  public class JibMicronautExtension implements JibMavenPluginExtension<Void> {
24  
25      public static final String DEFAULT_BASE_IMAGE = "openjdk:15-alpine";
26  
27      @Override
28      public Optional<Class<Void>> getExtraConfigType() {
29          return Optional.empty();
30      }
31  
32      @Override
33      public ContainerBuildPlan extendContainerBuildPlan(ContainerBuildPlan buildPlan, Map<String, String> properties,
34                                                         Optional<Void> extraConfig, MavenData mavenData,
35                                                         ExtensionLogger logger) throws JibPluginExtensionException {
36  
37          ContainerBuildPlan.Builder builder = buildPlan.toBuilder();
38          MicronautRuntime runtime = MicronautRuntime.valueOf(mavenData.getMavenProject().getProperties().getProperty(MicronautRuntime.PROPERTY, "none").toUpperCase());
39  
40          JibConfigurationServicenfigurationService">JibConfigurationService jibConfigurationService = new JibConfigurationService(mavenData.getMavenProject());
41          String from = jibConfigurationService.getFromImage().orElse(DEFAULT_BASE_IMAGE);
42  
43          ApplicationConfigurationServicenfigurationService">ApplicationConfigurationService applicationConfigurationService = new ApplicationConfigurationService(mavenData.getMavenProject());
44          Map<String, Object> applicationConfiguration = applicationConfigurationService.getApplicationConfiguration();
45  
46          builder.setBaseImage(from);
47  
48          int port = Integer.parseInt(applicationConfiguration.getOrDefault("MICRONAUT_SERVER_PORT", applicationConfiguration.getOrDefault("micronaut.server.port", 8080)).toString());
49          if (port > 0) {
50              logger.log(ExtensionLogger.LogLevel.LIFECYCLE, "Exposing port: " + port);
51              builder.addExposedPort(Port.tcp(port));
52          }
53  
54          switch (runtime.getBuildStrategy()) {
55              case ORACLE_FUNCTION:
56  
57                  List<? extends LayerObject> originalLayers = buildPlan.getLayers();
58                  builder.setLayers(Collections.emptyList());
59  
60                  for (LayerObject layer : originalLayers) {
61                      builder.addLayer(remapLayer(layer));
62                  }
63  
64                  builder.setBaseImage("fnproject/fn-java-fdk:" + determineProjectFnVersion())
65                          .setWorkingDirectory(AbsoluteUnixPath.get("/function"))
66                          .setEntrypoint(null)
67                          .setCmd(Collections.singletonList("io.micronaut.oraclecloud.function.http.HttpFunction::handleRequest"));
68                  break;
69              case LAMBDA:
70                  List<String> entrypoint = buildPlan.getEntrypoint();
71                  Objects.requireNonNull(entrypoint).set(entrypoint.size() - 1, "io.micronaut.function.aws.runtime.MicronautLambdaRuntime");
72                  builder.setEntrypoint(entrypoint);
73                  break;
74          }
75          return builder.build();
76      }
77  
78      private LayerObject remapLayer(LayerObject layerObject) {
79          FileEntriesLayer originalLayer = (FileEntriesLayer) layerObject;
80          FileEntriesLayer.Builder builder = FileEntriesLayer.builder().setName(originalLayer.getName());
81          for (FileEntry originalEntry : originalLayer.getEntries()) {
82              builder.addEntry(remapEntry(originalEntry));
83          }
84  
85          return builder.build();
86      }
87  
88      private FileEntry remapEntry(FileEntry originalEntry) {
89          List<String> pathComponents = UnixPathParser.parse(originalEntry.getExtractionPath().toString());
90  
91          AbsoluteUnixPath newPath = AbsoluteUnixPath.get("/function/app/" + pathComponents.get(pathComponents.size() - 1));
92          return new FileEntry(originalEntry.getSourceFile(), newPath, originalEntry.getPermissions(),
93                  originalEntry.getModificationTime(), originalEntry.getOwnership());
94      }
95  
96      private String determineProjectFnVersion() {
97          ArtifactVersion javaVersion = new DefaultArtifactVersion(System.getProperty("java.version"));
98          if (javaVersion.getMajorVersion() >= 11) {
99              return "jre11-latest";
100         } else {
101             return "latest";
102         }
103     }
104 
105 
106 }