package com.amazonaws.eclipse.opsworks.deploy.util; import java.io.File; import java.io.IOException; import java.util.LinkedList; import java.util.List; import java.util.UUID; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.Path; import com.amazonaws.eclipse.core.AwsToolkitCore; import com.amazonaws.eclipse.core.regions.ServiceAbbreviations; import com.amazonaws.eclipse.opsworks.OpsWorksPlugin; import com.amazonaws.eclipse.opsworks.deploy.wizard.model.DeployProjectToOpsworksWizardDataModel; import com.amazonaws.services.opsworks.AWSOpsWorks; import com.amazonaws.services.opsworks.model.App; import com.amazonaws.services.opsworks.model.AppType; import com.amazonaws.services.opsworks.model.CreateAppRequest; import com.amazonaws.services.opsworks.model.CreateDeploymentRequest; import com.amazonaws.services.opsworks.model.CreateDeploymentResult; import com.amazonaws.services.opsworks.model.DeploymentCommand; import com.amazonaws.services.opsworks.model.DeploymentCommandName; import com.amazonaws.services.opsworks.model.DescribeAppsRequest; import com.amazonaws.services.opsworks.model.EnvironmentVariable; import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.model.CannedAccessControlList; import com.amazonaws.services.s3.model.PutObjectRequest; public class DeployUtils { public static File repackWarFileToZipFile(File warFile) throws IOException { File unpackDir = createTempDirectory(); File zipFile = File.createTempFile("eclipse-opsworks-content-zip-", null); // Unpack the .war file to the temp directory unpackWarFile(warFile, unpackDir); // Zip it ZipUtils.createZipFileOfDirectory(unpackDir, zipFile); return zipFile; } private static void unpackWarFile(File warFile, File targetDir) throws IOException { // Just treat the .war file as a zip file ZipUtils.unzipFileToDirectory(warFile, targetDir); } private static File createTempDirectory() throws IOException { File tempDir = File.createTempFile("eclipse-opsworks-deployment-content-dir-", null); if ( !tempDir.delete() ) { throw new RuntimeException("Could not delete temp file: " + tempDir.getAbsolutePath()); } if ( !tempDir.mkdirs() ) { throw new RuntimeException("Could not create temp directory: " + tempDir.getAbsolutePath()); } return tempDir; } /** * @return the deployment ID */ public static String runDeployment( DeployProjectToOpsworksWizardDataModel dataModel, IProgressMonitor progressMonitor) { OpsWorksPlugin.getDefault().logInfo( "Preparing for deployment: " + dataModel.toString()); /* * (1) Create a new OpsWorks app if necessary */ App targetApp = null; if (dataModel.getIsCreatingNewJavaApp()) { progressMonitor.subTask(String.format( "Create new Java app [%s]...", dataModel.getNewJavaAppName())); OpsWorksPlugin.getDefault().logInfo( "Making CreateApp API call..."); String endpoint = dataModel.getRegion().getServiceEndpoints() .get(ServiceAbbreviations.OPSWORKS); AWSOpsWorks client = AwsToolkitCore.getClientFactory() .getOpsWorksClientByEndpoint(endpoint); CreateAppRequest createAppRequest = new CreateAppRequest() .withName(dataModel.getNewJavaAppName()) .withStackId(dataModel.getExistingStack().getStackId()) .withType(AppType.Java) .withAppSource(dataModel.getS3ApplicationSource().toGenericSource()) .withEnableSsl(dataModel.isEnableSsl()); if (dataModel.getCustomDomains() != null && !dataModel.getCustomDomains().isEmpty()) { createAppRequest.setDomains(dataModel.getCustomDomains()); } if (dataModel.getEnvironmentVariables() != null && !dataModel.getEnvironmentVariables().isEmpty()) { List<EnvironmentVariable> vars = new LinkedList<EnvironmentVariable>(); for (com.amazonaws.eclipse.opsworks.deploy.wizard.model.DeployProjectToOpsworksWizardDataModel.EnvironmentVariable envVar : dataModel .getEnvironmentVariables()) { vars.add(envVar.toSdkModel()); } createAppRequest.setEnvironment(vars); } if (dataModel.isEnableSsl()) { createAppRequest.setSslConfiguration(dataModel.getSslConfiguration().toSdkModel()); } String newAppId = client.createApp(createAppRequest) .getAppId(); targetApp = client .describeApps( new DescribeAppsRequest().withAppIds(newAppId)) .getApps().get(0); } else { targetApp = dataModel.getExistingJavaApp(); } progressMonitor.worked(30); /* * (2) Export application archive WAR file */ final IProject project = dataModel.getProject(); String uuid = UUID.randomUUID().toString(); String tempDirName = targetApp.getShortname() + "-" + uuid + "-deployment-dir"; File tempDir = new File( new File(System.getProperty("java.io.tmpdir")), tempDirName); File archiveContentDir = new File( tempDir, "archive-content"); progressMonitor.subTask("Export project to WAR file..."); OpsWorksPlugin.getDefault().logInfo( "Preparing to export project [" + project.getName() + "] to a WAR file [" + new File(archiveContentDir, "archive.war").getAbsolutePath() + "]."); File warFile = WTPWarUtils.exportProjectToWar( project, new Path(archiveContentDir.getAbsolutePath()), "archive.war").toFile(); OpsWorksPlugin.getDefault().logInfo( "WAR file created at [" + warFile.getAbsolutePath() + "]"); progressMonitor.worked(10); progressMonitor.subTask("Repackage the war file..."); /* * https://forums.aws.amazon.com/thread.jspa?messageID=557948&tstart=0 */ File zipArchive = null; try { zipArchive = repackWarFileToZipFile(warFile); } catch (IOException e) { OpsWorksPlugin.getDefault().reportException( "Error when packaging the web application into zip archive.", e); } progressMonitor.worked(5); /* * (3) Upload to S3 */ String bucketName = dataModel.getS3ApplicationSource().getBucketName(); String keyName = dataModel.getS3ApplicationSource().getKeyName(); AmazonS3 s3Client = AwsToolkitCore.getClientFactory() .getS3ClientByEndpoint("https://s3.amazonaws.com/"); progressMonitor.subTask("Upload ZIP file to S3..."); OpsWorksPlugin.getDefault().logInfo( "Uploading zip file to S3 bucket [" + bucketName + "]."); PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, keyName, zipArchive); if (dataModel.getS3ApplicationSource().isAsPublicHttpArchive()) { putObjectRequest.setCannedAcl(CannedAccessControlList.PublicRead); } s3Client.putObject(putObjectRequest); OpsWorksPlugin.getDefault().logInfo( "Upload succeed. [s3://" + bucketName + "/" + keyName + "]"); progressMonitor.worked(35); /* * (4) CreateDeployment */ progressMonitor.subTask("Initiate deployment..."); OpsWorksPlugin.getDefault().logInfo( "Making CreateDeployment API call..."); String endpoint = dataModel.getRegion().getServiceEndpoints() .get(ServiceAbbreviations.OPSWORKS); AWSOpsWorks client = AwsToolkitCore.getClientFactory() .getOpsWorksClientByEndpoint(endpoint); CreateDeploymentRequest createDeploymentRequest = new CreateDeploymentRequest() .withStackId(dataModel.getExistingStack().getStackId()) .withAppId(targetApp.getAppId()) .withCommand(new DeploymentCommand().withName(DeploymentCommandName.Deploy)); if (dataModel.getDeployComment() != null && !dataModel.getDeployComment().isEmpty()) { createDeploymentRequest.setComment(dataModel.getDeployComment()); } if (dataModel.getCustomChefJson() != null && !dataModel.getCustomChefJson().isEmpty()) { createDeploymentRequest.setCustomJson(dataModel.getCustomChefJson()); } CreateDeploymentResult result = client.createDeployment(createDeploymentRequest); OpsWorksPlugin.getDefault().logInfo( "Deployment submitted. Deployment ID [" + result.getDeploymentId() + "]"); progressMonitor.worked(20); return result.getDeploymentId(); } }