/* * Copyright 2012 Amazon Technologies, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://aws.amazon.com/apache2.0 * * This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES * OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and * limitations under the License. */ package com.amazonaws.eclipse.explorer.cloudformation; import java.util.Date; import java.util.List; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.action.Action; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.TabFolder; import org.eclipse.swt.widgets.TabItem; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorSite; import org.eclipse.ui.PartInitException; import org.eclipse.ui.forms.IFormColors; import org.eclipse.ui.forms.widgets.FormToolkit; import org.eclipse.ui.forms.widgets.ScrolledForm; import org.eclipse.ui.part.EditorPart; import org.eclipse.ui.statushandlers.StatusManager; import com.amazonaws.AmazonClientException; import com.amazonaws.eclipse.cloudformation.CloudFormationPlugin; import com.amazonaws.eclipse.core.AWSClientFactory; import com.amazonaws.eclipse.core.AwsToolkitCore; import com.amazonaws.eclipse.core.regions.Region; import com.amazonaws.eclipse.core.regions.RegionUtils; import com.amazonaws.services.cloudformation.AmazonCloudFormation; import com.amazonaws.services.cloudformation.model.DescribeStacksRequest; import com.amazonaws.services.cloudformation.model.Stack; public class StackEditor extends EditorPart { private StackEditorInput stackEditorInput; private Text stackNameLabel; private Text createdLabel; private Text statusLabel; private Text createTimeoutLabel; private Text statusReasonLabel; private Text lastUpdatedLabel; private Text descriptionLabel; private Text rollbackOnFailureLabel; private StackEventsTable stackEventsTable; private StackOutputsTable stackOutputsTable; private StackParametersTable stackParametersTable; private StackResourcesTable stackResourcesTable; @Override public void doSave(IProgressMonitor monitor) {} @Override public void doSaveAs() {} @Override public void init(IEditorSite site, IEditorInput input) throws PartInitException { setSite(site); setInput(input); setPartName(input.getName()); this.stackEditorInput = (StackEditorInput)input; } @Override public boolean isDirty() { return false; } @Override public boolean isSaveAsAllowed() { return false; } @Override public void createPartControl(Composite parent) { FormToolkit toolkit = new FormToolkit(Display.getDefault()); ScrolledForm form = new ScrolledForm(parent, SWT.V_SCROLL); form.setExpandHorizontal(true); form.setExpandVertical(true); form.setBackground(toolkit.getColors().getBackground()); form.setForeground(toolkit.getColors().getColor(IFormColors.TITLE)); form.setFont(JFaceResources.getHeaderFont()); form.setText(getFormTitle()); toolkit.decorateFormHeading(form.getForm()); form.setImage(AwsToolkitCore.getDefault().getImageRegistry().get(AwsToolkitCore.IMAGE_STACK)); form.getBody().setLayout(new GridLayout()); createSummarySection(form.getBody(), toolkit); createTabsSection(form.getBody(), toolkit); form.getToolBarManager().add(new RefreshAction()); form.getToolBarManager().update(true); new LoadStackSummaryThread().start(); } private String getFormTitle() { String formTitle = stackEditorInput.getName(); Region region = RegionUtils.getRegionByEndpoint(stackEditorInput.getRegionEndpoint()); if (region != null) { formTitle += " - " + region.getName(); } else { formTitle += " - " + stackEditorInput.getRegionEndpoint(); } return formTitle; } private void createSummarySection(Composite parent, FormToolkit toolkit) { GridDataFactory gridDataFactory = GridDataFactory.swtDefaults() .align(SWT.FILL, SWT.TOP).grab(true, false).minSize(200, SWT.DEFAULT).hint(200, SWT.DEFAULT); Composite composite = toolkit.createComposite(parent, SWT.NONE); composite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); composite.setLayout(new GridLayout(4, false)); toolkit.createLabel(composite, "Stack Name:"); stackNameLabel = new Text(composite, SWT.READ_ONLY | SWT.NONE); gridDataFactory.applyTo(stackNameLabel); toolkit.createLabel(composite, "Created:"); createdLabel = new Text(composite, SWT.READ_ONLY | SWT.NONE); gridDataFactory.applyTo(createdLabel); toolkit.createLabel(composite, "Status:"); statusLabel = new Text(composite, SWT.READ_ONLY | SWT.NONE); gridDataFactory.applyTo(statusLabel); toolkit.createLabel(composite, "Create Timeout:"); createTimeoutLabel = new Text(composite, SWT.READ_ONLY | SWT.NONE); gridDataFactory.applyTo(createTimeoutLabel); toolkit.createLabel(composite, "Status Reason:"); statusReasonLabel = new Text(composite, SWT.READ_ONLY | SWT.NONE); gridDataFactory.applyTo(statusReasonLabel); toolkit.createLabel(composite, "Last Updated:"); lastUpdatedLabel = new Text(composite, SWT.READ_ONLY | SWT.NONE); gridDataFactory.applyTo(lastUpdatedLabel); toolkit.createLabel(composite, "Rollback on Failure:"); rollbackOnFailureLabel = new Text(composite, SWT.READ_ONLY | SWT.NONE); toolkit.createLabel(composite, ""); toolkit.createLabel(composite, ""); Label l = toolkit.createLabel(composite, "Description:"); gridDataFactory.copy().hint(100, SWT.DEFAULT).minSize(1, SWT.DEFAULT).align(SWT.LEFT, SWT.TOP).grab(false, false).applyTo(l); descriptionLabel = new Text(composite, SWT.READ_ONLY | SWT.NONE | SWT.MULTI | SWT.WRAP); gridDataFactory.copy().span(3, 1).applyTo(descriptionLabel); } private void createTabsSection(Composite parent, FormToolkit toolkit) { Composite tabsSection = toolkit.createComposite(parent, SWT.NONE); tabsSection.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); tabsSection.setLayout(new FillLayout()); TabFolder tabFolder = new TabFolder (tabsSection, SWT.BORDER); Rectangle clientArea = parent.getClientArea(); tabFolder.setLocation(clientArea.x, clientArea.y); TabItem eventsTab = new TabItem(tabFolder, SWT.NONE); eventsTab.setText("Events"); stackEventsTable = new StackEventsTable(tabFolder, toolkit, stackEditorInput); eventsTab.setControl(stackEventsTable); TabItem resourcesTab = new TabItem(tabFolder, SWT.NONE); resourcesTab.setText("Resources"); stackResourcesTable = new StackResourcesTable(tabFolder, toolkit, stackEditorInput); resourcesTab.setControl(stackResourcesTable); TabItem parametersTab = new TabItem(tabFolder, SWT.NONE); parametersTab.setText("Parameters"); stackParametersTable = new StackParametersTable(tabFolder, toolkit); parametersTab.setControl(stackParametersTable); TabItem outputsTab = new TabItem(tabFolder, SWT.NONE); outputsTab.setText("Outputs"); stackOutputsTable = new StackOutputsTable(tabFolder, toolkit); outputsTab.setControl(stackOutputsTable); tabFolder.pack(); } @Override public void setFocus() {} private AmazonCloudFormation getClient() { AWSClientFactory clientFactory = AwsToolkitCore.getClientFactory(stackEditorInput.getAccountId()); return clientFactory.getCloudFormationClientByEndpoint(stackEditorInput.getRegionEndpoint()); } private class LoadStackSummaryThread extends Thread { private Stack describeStack() { DescribeStacksRequest request = new DescribeStacksRequest().withStackName(stackEditorInput.getStackName()); List<Stack> stacks = getClient().describeStacks(request).getStacks(); if (stacks.size() == 0) { return new Stack(); } else if (stacks.size() > 1) { throw new RuntimeException("Unexpected number of stacks returned"); } return stacks.get(0); } @Override public void run() { try { final Stack stack = describeStack(); Display.getDefault().asyncExec(new Runnable() { public void run() { descriptionLabel.setText(stack.getDescription()); lastUpdatedLabel.setText(valueOrDefault(stack.getLastUpdatedTime(), "N/A")); stackNameLabel.setText(stack.getStackName()); statusLabel.setText(stack.getStackStatus()); statusReasonLabel.setText(stack.getStackStatusReason()); createdLabel.setText(valueOrDefault(stack.getCreationTime(), "N/A")); createTimeoutLabel.setText(valueOrDefault(stack.getTimeoutInMinutes(), "N/A")); Boolean disableRollback = stack.getDisableRollback(); if (disableRollback != null) disableRollback = !disableRollback; rollbackOnFailureLabel.setText(booleanYesOrNo(disableRollback)); stackNameLabel.getParent().layout(); stackNameLabel.getParent().getParent().layout(true); stackOutputsTable.setStackOutputs(stack.getOutputs()); stackParametersTable.setStackParameters(stack.getParameters()); } }); } catch (Exception e) { Status status = new Status(IStatus.WARNING, CloudFormationPlugin.PLUGIN_ID, "Unable to describe stack " + stackEditorInput.getStackName(), e); StatusManager.getManager().handle(status, StatusManager.LOG | StatusManager.SHOW); } } private String booleanYesOrNo(Boolean b) { if (b == null) return ""; if (b == true) return "Yes"; else return "No"; } private String valueOrDefault(Date date, String defaultValue) { if (date != null) return date.toString(); else return defaultValue; } private String valueOrDefault(Integer integer, String defaultValue) { if (integer != null) return integer.toString(); else return defaultValue; } private String valueOrDefault(String value, String defaultValue) { if (value != null) return value; else return defaultValue; } } private class RefreshAction extends Action { public RefreshAction() { this.setText("Refresh"); this.setToolTipText("Refresh stack information"); this.setImageDescriptor(AwsToolkitCore.getDefault().getImageRegistry().getDescriptor(AwsToolkitCore.IMAGE_REFRESH)); } @Override public void run() { new LoadStackSummaryThread().start(); stackEventsTable.refresh(); stackResourcesTable.refresh(); } } }