
com.deliveredtechnologies.maven.terraform.TerraformPackage Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of tf-maven-plugin Show documentation
Show all versions of tf-maven-plugin Show documentation
Terraform Maven Plugin :: Bringing build lifecycle management to Terraform!
The newest version!
package com.deliveredtechnologies.maven.terraform;
import com.deliveredtechnologies.maven.io.Compressable;
import com.deliveredtechnologies.maven.io.CompressableGZipTarFile;
import com.deliveredtechnologies.maven.io.CompressableZipFile;
import com.deliveredtechnologies.maven.logs.MavenSlf4jAdapter;
import com.deliveredtechnologies.terraform.TerraformException;
import com.deliveredtechnologies.terraform.TerraformUtils;
import com.deliveredtechnologies.terraform.api.TerraformOperation;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.project.MavenProject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import java.util.stream.Collectors;
/**
* API for packaging a Terraform configuration as a zip.
*/
public class TerraformPackage implements TerraformOperation {
static final String targetDir = "target";
static final String targetTfRootDir = "tf-root-module";
static final List excludedFiles = Arrays.asList(new String[] {".terraform", "terraform.tfstate", "terraform.tfstate.backup", ".terraform.tfstate.lock.info"});
private Logger logger;
private MavenProject project;
//TODO: Consider using intsance variables instead.
enum TerraformPackageParams {
tfModulesDir,
tfRootDir,
tfVarFiles,
fatTar;
}
public TerraformPackage(MavenProject project, Logger logger) {
this.logger = logger;
this.project = project;
}
public TerraformPackage(MavenProject project, Log log) {
this(project, new MavenSlf4jAdapter(log));
}
public TerraformPackage(MavenProject project) {
this(project, LoggerFactory.getLogger(TerraformPackage.class));
}
/**
* Packages a Terraform config as a zip file.
*
* Valid Properties:
* tfModulesDir - the directory where Terraform Modules dependencies (i.e. Maven Terraform dependencies) are stored; defaults to src/main/.tfmodules
* tfRootDir - the directory containing the Terraform root module configuration; defaults to src/main/tf/{first dir found}
* fatTar - if "true", then tar.gz contains the Terraform code for all Maven dependencies ( valid values are "true" or "false"); defaults to "false"
*
* @param properties property options for packaging a Terraform configuration
* @return String message with the zip filename included
* @throws TerraformException
*/
@Override
public String execute(Properties properties) throws TerraformException {
try {
Path targetPath = Paths.get(targetDir);
Path targetTfRootPath = targetPath.resolve(targetTfRootDir);
String tfModulesDir = properties.getProperty(TerraformPackageParams.tfModulesDir.toString());
String tfRootDir = properties.getProperty(TerraformPackageParams.tfRootDir.toString());
String tfVarFiles = properties.getProperty(TerraformPackageParams.tfVarFiles.toString());
Object isFatTarObj = properties.getOrDefault(TerraformPackageParams.fatTar.toString(), false);
boolean isFatTar = isFatTarObj instanceof Boolean ? (Boolean)isFatTarObj : Boolean.valueOf(isFatTarObj.toString());
Path tfModulesPath = !StringUtils.isEmpty(tfModulesDir)
? Paths.get(tfModulesDir)
: TerraformUtils.getDefaultTfModulesDir();
logger.debug(String.format("tfModulesPath is %1$s", tfModulesPath.toAbsolutePath().toString()));
File tfSourceFile = Paths.get("src", "main", "tf").toFile();
Path tfRootPath = !StringUtils.isEmpty(tfRootDir)
? TerraformUtils.getTerraformRootModuleDir(tfRootDir)
: (tfSourceFile.exists() && tfSourceFile.isDirectory() && tfSourceFile.listFiles().length > 1
? tfSourceFile.toPath()
: TerraformUtils.getDefaultTerraformRootModuleDir());
logger.debug(String.format("tfRootPath is %1$s", tfRootPath.toAbsolutePath().toString()));
List tfVarFilePaths = StringUtils.isEmpty(tfVarFiles)
? new ArrayList<>()
: Arrays.stream(tfVarFiles.split(","))
.map(x -> tfRootPath.resolve(x.trim()))
.collect(Collectors.toList());
logger.debug(String.format("tfVarFiles is %1$s", tfVarFilePaths));
//copy tfRoot directory to target
if (targetTfRootPath.toFile().exists()) FileUtils.forceDelete(targetTfRootPath.toFile());
FileUtils.forceMkdir(targetTfRootPath.toFile());
List tfRootDirFiles = Files.walk(tfRootPath, 1)
.filter(path -> !path.equals(tfRootPath))
.collect(Collectors.toList());
for (Path file : tfRootDirFiles.stream().filter(f -> !excludedFiles.contains(f.getFileName().toString())).collect(Collectors.toList())) {
if (file.toFile().isDirectory()) {
FileUtils.copyDirectory(file.toFile(), targetTfRootPath.resolve(file.getFileName().toString()).toFile(), new FileFilter() {
@Override
public boolean accept(File pathname) {
return excludedFiles.stream().noneMatch(excludedFile -> pathname.getName().endsWith(excludedFile));
}
});
} else {
Files.copy(file, targetTfRootPath.resolve(file.getFileName().toString()));
}
}
for (Path tfVarFilePath : tfVarFilePaths) {
Files.copy(tfVarFilePath, targetTfRootPath.resolve(tfVarFilePath.getFileName().toString().replaceAll(".tfvars", "").concat(".auto.tfvars")));
}
if (isFatTar) {
updateDependenciesInTfRoot(targetTfRootPath, tfModulesPath, tfRootPath);
//copy tfmodules directory into tfRoot directory; i.e. {targetTfRootDir}/{tfModulesDir} if it exists
if (tfModulesPath.toFile().exists() && tfModulesPath.toFile().isDirectory()) {
FileUtils.copyDirectory(tfModulesPath.toFile(), targetTfRootPath.resolve(tfModulesPath.getFileName().toString()).toFile());
}
return String.format("Created fatTar gzipped tar file '%1$s'", createGZippedTar(targetPath, targetTfRootPath));
}
return String.format("Created zip file '%1$s'", createZip(targetPath, targetTfRootPath));
} catch (IOException e) {
throw new TerraformException(e.getMessage(), e);
}
}
private void updateDependenciesInTfRoot(Path targetTfRootPath, Path tfModulesPath, Path tfRootPath) throws IOException {
//replace all ../../.tfmodules with .tfmodules
String tfRootToModulesRelativePath = tfRootPath.relativize(tfModulesPath).toString();
List filesInTargetTfRoot = Files.walk(targetTfRootPath)
.filter(path -> !path.toFile().isDirectory())
.collect(Collectors.toList());
for (Path file : filesInTargetTfRoot) {
try (BufferedReader fileReader = new BufferedReader(new InputStreamReader(new FileInputStream(file.toFile())))) {
try (BufferedWriter fileWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file.resolveSibling(file.getFileName().toString() + ".working").toFile())))) {
while (fileReader.ready()) {
fileWriter.write(fileReader.readLine().replace(tfRootToModulesRelativePath.replace('\\', '/'), tfModulesPath.getFileName().toString()));
fileWriter.newLine();
}
}
}
Files.delete(file);
Files.move(file.resolveSibling(file.getFileName().toString() + ".working"), file);
}
}
private String createZip(Path targetDir, Path targetTfRootPath) throws IOException {
String zipFilename = targetDir.resolve(
String.format("%1$s-%2$s.zip", project.getArtifactId(), project.getVersion())).toString();
Compressable compressor = new CompressableZipFile(zipFilename);
Files.walk(targetTfRootPath, 1)
.filter(path -> !path.equals(targetTfRootPath))
.forEach(compressor::addToCompressedFile);
compressor.compress();
return zipFilename;
}
private String createGZippedTar(Path targetDir, Path targetTfRootPath) throws IOException {
String tarFilename = targetDir.resolve(
String.format("%1$s-%2$s.tar.gz", project.getArtifactId(), project.getVersion())).toString();
Compressable compressor = new CompressableGZipTarFile(tarFilename, targetTfRootPath);
Files.walk(targetTfRootPath, 1)
.filter(path -> !path.equals(targetTfRootPath))
.forEach(compressor::addToCompressedFile);
compressor.compress();
return tarFilename;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy