001/* 002 * Copyright 2017-2022 original authors 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package io.micronaut.maven.jib; 017 018import com.fasterxml.jackson.core.JsonProcessingException; 019import com.fasterxml.jackson.databind.DeserializationFeature; 020import com.fasterxml.jackson.dataformat.xml.XmlMapper; 021import com.google.cloud.tools.jib.api.Credential; 022import com.google.cloud.tools.jib.maven.MavenProjectProperties; 023import com.google.cloud.tools.jib.plugins.common.PropertyNames; 024import org.apache.maven.model.Plugin; 025import org.apache.maven.project.MavenProject; 026 027import javax.inject.Inject; 028import javax.inject.Singleton; 029import java.util.Collections; 030import java.util.HashSet; 031import java.util.List; 032import java.util.Optional; 033import java.util.Set; 034 035import static io.micronaut.maven.jib.JibConfiguration.*; 036 037/** 038 * Exposes the Jib plugin configuration so that it can be read by other mojos. 039 * 040 * @author Álvaro Sánchez-Mariscal 041 * @since 1.1 042 */ 043@Singleton 044public class JibConfigurationService { 045 046 private final Optional<JibConfiguration> configuration; 047 048 @Inject 049 public JibConfigurationService(MavenProject mavenProject) { 050 final Plugin plugin = mavenProject.getPlugin(MavenProjectProperties.PLUGIN_KEY); 051 if (plugin != null && plugin.getConfiguration() != null) { 052 final XmlMapper mapper = XmlMapper.builder() 053 .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) 054 .findAndAddModules() 055 .build(); 056 try { 057 configuration = Optional.ofNullable(mapper.readValue(plugin.getConfiguration().toString(), JibConfiguration.class)); 058 } catch (JsonProcessingException e) { 059 throw new IllegalArgumentException("Error parsing Jib plugin configuration", e); 060 } 061 } else { 062 configuration = Optional.empty(); 063 } 064 } 065 066 /** 067 * @return the <code>to.image</code> configuration. 068 */ 069 public Optional<String> getToImage() { 070 final String value = configuration.flatMap(c -> c.to().flatMap(ToConfiguration::image)) 071 .orElse(null); 072 return Optional.ofNullable(System.getProperties().getProperty(PropertyNames.TO_IMAGE, value)); 073 } 074 075 /** 076 * @return the <code>from.image</code> configuration. 077 */ 078 public Optional<String> getFromImage() { 079 final String value = configuration.flatMap(c -> c.from().flatMap(FromConfiguration::image)) 080 .orElse(null); 081 return Optional.ofNullable(System.getProperties().getProperty(PropertyNames.FROM_IMAGE, value)); 082 } 083 084 /** 085 * @return the <code>to.tags</code> configuration. 086 */ 087 public Set<String> getTags() { 088 final Set<String> tags = configuration.flatMap(c -> c.to().map(ToConfiguration::tags)) 089 .orElse(Collections.emptySet()); 090 return Optional.ofNullable(System.getProperties().getProperty(PropertyNames.TO_TAGS)) 091 .map(JibConfigurationService::parseCommaSeparatedList) 092 .orElse(tags); 093 } 094 095 /** 096 * @return the <code>to.auth.username</code> and <code>to.auth.password</code> configuration. 097 */ 098 public Optional<Credential> getToCredentials() { 099 String usernameProperty = System.getProperties().getProperty(PropertyNames.TO_AUTH_USERNAME); 100 String passwordProperty = System.getProperties().getProperty(PropertyNames.TO_AUTH_PASSWORD); 101 if (usernameProperty != null || passwordProperty != null) { 102 return Optional.of(Credential.from(usernameProperty, passwordProperty)); 103 } else { 104 return configuration 105 .flatMap(c -> c.to().flatMap(ToConfiguration::auth)) 106 .map(this::getCredentials); 107 } 108 } 109 110 /** 111 * @return the <code>from.auth.username</code> and <code>from.auth.password</code> configuration. 112 */ 113 public Optional<Credential> getFromCredentials() { 114 String usernameProperty = System.getProperties().getProperty(PropertyNames.FROM_AUTH_USERNAME); 115 String passwordProperty = System.getProperties().getProperty(PropertyNames.FROM_AUTH_PASSWORD); 116 if (usernameProperty != null || passwordProperty != null) { 117 return Optional.of(Credential.from(usernameProperty, passwordProperty)); 118 } else { 119 return configuration 120 .flatMap(c -> c.from().flatMap(FromConfiguration::auth)) 121 .map(this::getCredentials); 122 } 123 124 } 125 126 private Credential getCredentials(AuthConfiguration authConfiguration) { 127 return Credential.from( 128 authConfiguration.username().orElse(null), 129 authConfiguration.password().orElse(null) 130 ); 131 } 132 133 /** 134 * @return the <code>container.workingDirectory</code> configuration. 135 */ 136 public Optional<String> getWorkingDirectory() { 137 final String value = configuration.flatMap(c -> c.container().flatMap(ContainerConfiguration::workingDirectory)) 138 .orElse(null); 139 return Optional.ofNullable(System.getProperties().getProperty(PropertyNames.CONTAINER_WORKING_DIRECTORY, value)); 140 } 141 142 /** 143 * @return the <code>container.args</code> configuration. 144 */ 145 public List<String> getArgs() { 146 final List<String> args = configuration.flatMap(c -> c.container().map(ContainerConfiguration::args)) 147 .orElse(Collections.emptyList()); 148 return Optional.ofNullable(System.getProperties().getProperty(PropertyNames.CONTAINER_ARGS)) 149 .map(JibConfigurationService::parseCommaSeparatedList) 150 .map(List::copyOf) 151 .orElse(args); 152 } 153 154 /** 155 * @return the <code>container.ports</code> configuration. 156 */ 157 public Optional<String> getPorts() { 158 final Set<String> ports = configuration.flatMap(c -> c.container().map(ContainerConfiguration::ports)) 159 .orElse(Collections.emptySet()); 160 return Optional.ofNullable(System.getProperties().getProperty(PropertyNames.CONTAINER_PORTS)) 161 .map(s -> s.replace(",", " ")) 162 .or(() -> ports.isEmpty() ? Optional.empty() : Optional.of(String.join(" ", ports))); 163 } 164 165 private static Set<String> parseCommaSeparatedList(String list) { 166 String[] parts = list.split(","); 167 var items = new HashSet<String>(parts.length); 168 for (String part : parts) { 169 items.add(part.trim()); 170 } 171 return items; 172 } 173}