/* * Copyright 2011-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). * You may not use this file except in compliance with the License. * A copy of the License is located at * * http://aws.amazon.com/apache2.0 * * or in the "license" file accompanying this file. 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.elasticbeanstalk.server.ui.configEditor; import java.net.URI; import java.net.URISyntaxException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Map; import org.eclipse.jface.action.Action; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; 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.Link; import org.eclipse.ui.forms.ManagedForm; import org.eclipse.ui.forms.widgets.FormToolkit; import org.eclipse.ui.forms.widgets.ScrolledForm; import org.eclipse.ui.forms.widgets.Section; import org.eclipse.wst.server.ui.editor.ServerEditorPart; import org.eclipse.wst.server.ui.editor.ServerEditorSection; import org.eclipse.wst.server.ui.internal.ImageResource; import com.amazonaws.eclipse.core.AwsToolkitCore; import com.amazonaws.eclipse.core.regions.Region; import com.amazonaws.eclipse.core.regions.RegionUtils; import com.amazonaws.eclipse.core.regions.ServiceAbbreviations; import com.amazonaws.eclipse.ec2.ui.views.instances.InstanceSelectionTable; import com.amazonaws.eclipse.elasticbeanstalk.ConfigurationOptionConstants; import com.amazonaws.eclipse.elasticbeanstalk.Environment; import com.amazonaws.eclipse.explorer.sqs.AddMessageAction; import com.amazonaws.services.autoscaling.AmazonAutoScaling; import com.amazonaws.services.autoscaling.model.AutoScalingGroup; import com.amazonaws.services.autoscaling.model.DescribeAutoScalingGroupsRequest; import com.amazonaws.services.elasticbeanstalk.AWSElasticBeanstalk; import com.amazonaws.services.elasticbeanstalk.model.DescribeEnvironmentResourcesRequest; import com.amazonaws.services.elasticbeanstalk.model.EnvironmentResourceDescription; import com.amazonaws.services.elasticbeanstalk.model.Instance; import com.amazonaws.services.elasticloadbalancing.AmazonElasticLoadBalancing; import com.amazonaws.services.elasticloadbalancing.model.DescribeLoadBalancersRequest; import com.amazonaws.services.elasticloadbalancing.model.LoadBalancerDescription; import com.amazonaws.services.sqs.AmazonSQS; import com.amazonaws.services.sqs.model.GetQueueAttributesRequest; import com.amazonaws.services.sqs.model.QueueAttributeName; public class EnvironmentResourcesEditorPart extends ServerEditorPart { protected ManagedForm managedForm; private EnvironmentInstancesEditorSection instancesEditorSection; private EnvironmentAutoScalingEditorSection autoScalingEditorSection; private EnvironmentElasticLoadBalancingEditorSection elasticLoadBalancingEditorSection; private EnvironmentQueueEditorSection queueEditorSection; @Override public void createPartControl(Composite parent) { managedForm = new ManagedForm(parent); setManagedForm(managedForm); ScrolledForm form = managedForm.getForm(); FormToolkit toolkit = managedForm.getToolkit(); toolkit.decorateFormHeading(form.getForm()); form.setText("Environment Resources"); form.setImage(ImageResource.getImage(ImageResource.IMG_SERVER)); FillLayout fillLayout = new FillLayout(); form.getBody().setLayout(fillLayout); fillLayout.marginHeight = 10; fillLayout.marginWidth = 10; Composite composite = toolkit.createComposite(form.getBody()); composite.setLayout(new GridLayout(2, true)); if (!getEnvironment().getEnvironmentType().equals(ConfigurationOptionConstants.SINGLE_INSTANCE_ENV)) { autoScalingEditorSection = new EnvironmentAutoScalingEditorSection(); autoScalingEditorSection.setServerEditorPart(this); autoScalingEditorSection.init(this.getEditorSite(), this.getEditorInput()); autoScalingEditorSection.createSection(composite); if (ConfigurationOptionConstants.WEB_SERVER.equals(getEnvironment().getEnvironmentTier())) { elasticLoadBalancingEditorSection = new EnvironmentElasticLoadBalancingEditorSection(); elasticLoadBalancingEditorSection.setServerEditorPart(this); elasticLoadBalancingEditorSection.init(this.getEditorSite(), this.getEditorInput()); elasticLoadBalancingEditorSection.createSection(composite); } else { queueEditorSection = new EnvironmentQueueEditorSection(); queueEditorSection.setServerEditorPart(this); queueEditorSection.init(this.getEditorSite(), this.getEditorInput()); queueEditorSection.createSection(composite); } } instancesEditorSection = new EnvironmentInstancesEditorSection(); instancesEditorSection.setServerEditorPart(this); instancesEditorSection.init(this.getEditorSite(), this.getEditorInput()); instancesEditorSection.createSection(composite); form.getToolBarManager().add(new RefreshAction()); form.getToolBarManager().update(true); new RefreshThread().start(); } private class RefreshAction extends Action { public RefreshAction() { setImageDescriptor(AwsToolkitCore.getDefault().getImageRegistry().getDescriptor(AwsToolkitCore.IMAGE_REFRESH)); setText("Refresh"); setToolTipText("Refresh"); } @Override public void run() { new RefreshThread().start(); } } private class RefreshThread extends Thread { @Override public void run() { if (getEnvironment().doesEnvironmentExistInBeanstalk() == false) { return; } DescribeEnvironmentResourcesRequest request = new DescribeEnvironmentResourcesRequest() .withEnvironmentName(getEnvironment().getEnvironmentName()); EnvironmentResourceDescription resources = getClient().describeEnvironmentResources(request).getEnvironmentResources(); instancesEditorSection.update(resources); if (autoScalingEditorSection != null) { autoScalingEditorSection.update(resources); } if (elasticLoadBalancingEditorSection != null) { elasticLoadBalancingEditorSection.update(resources); } if (queueEditorSection != null) { queueEditorSection.update(resources); } } } private static abstract class AbstractEnvironmentResourcesEditorSection extends ServerEditorSection { protected Section section; protected FormToolkit toolkit; protected Composite createSection(Composite parent, String label, String description) { toolkit = getFormToolkit(Display.getDefault()); section = toolkit.createSection(parent, Section.TWISTIE | Section.EXPANDED | Section.TITLE_BAR | Section.DESCRIPTION | Section.FOCUS_TITLE); section.setText(label); section.setDescription(description); Composite composite = toolkit.createComposite(section); FillLayout layout = new FillLayout(); layout.marginHeight = 10; layout.marginWidth = 10; layout.type = SWT.VERTICAL; composite.setLayout(layout); toolkit.paintBordersFor(composite); section.setClient(composite); section.setLayout(layout); return composite; } public abstract void update(EnvironmentResourceDescription resources); } private class EnvironmentQueueEditorSection extends AbstractEnvironmentResourcesEditorSection { private Label nameLabel; private Link urlLink; private Label createdLabel; private Label numberOfMessagesLabel; private Label numberOfMessagesInFlightLabel; @Override public void createSection(Composite parent) { super.createSection(parent); Composite composite = createSection( parent, "Amazon SQS Queue", "Your Amazon SQS Queue queues work items for delivery to your " + "worker tier environment." ); section.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); composite.setLayout(new GridLayout(2, false)); GridDataFactory gdf = GridDataFactory .swtDefaults() .align(SWT.FILL, SWT.TOP) .grab(true, false); new Label(composite, SWT.NONE).setText("Name:"); nameLabel = new Label(composite, SWT.NONE); gdf.applyTo(nameLabel); new Label(composite, SWT.NONE).setText("URL:"); urlLink = new Link(composite, SWT.NONE); urlLink.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { String queueUrl = event.text; AmazonSQS sqs = AwsToolkitCore .getClientFactory(getEnvironment().getAccountId()) .getSQSClientByEndpoint(getEndpointFromUrl(queueUrl)); new AddMessageAction(sqs, event.text, null).run(); } }); gdf.applyTo(urlLink); new Label(composite, SWT.NONE).setText("Created:"); createdLabel = new Label(composite, SWT.NONE); gdf.applyTo(createdLabel); new Label(composite, SWT.NONE).setText("Messages Available:"); numberOfMessagesLabel = new Label(composite, SWT.NONE); gdf.applyTo(numberOfMessagesLabel); new Label(composite, SWT.NONE).setText("Messages in Flight:"); numberOfMessagesInFlightLabel = new Label(composite, SWT.NONE); gdf.applyTo(numberOfMessagesInFlightLabel); } @Override public void update(final EnvironmentResourceDescription resources) { if (resources.getQueues().isEmpty()) { return; } final String queueName = resources.getQueues().get(0).getName(); final String queueUrl = resources.getQueues().get(0).getURL(); AmazonSQS sqs = AwsToolkitCore .getClientFactory(getEnvironment().getAccountId()) .getSQSClientByEndpoint(getEndpointFromUrl(queueUrl)); final Map<String, String> attributes = sqs.getQueueAttributes(new GetQueueAttributesRequest() .withQueueUrl(queueUrl) .withAttributeNames( QueueAttributeName.ApproximateNumberOfMessages, QueueAttributeName.ApproximateNumberOfMessagesNotVisible, QueueAttributeName.CreatedTimestamp, QueueAttributeName.DelaySeconds)) .getAttributes(); if (attributes.isEmpty()) { return; } Display.getDefault().asyncExec(new Runnable() { public void run() { nameLabel.setText(queueName); urlLink.setText("<a>" + queueUrl + "</a>"); String createdTimestamp = attributes.get("CreatedTimestamp"); if (createdTimestamp != null) { String text; try { long timestamp = Long.parseLong(createdTimestamp); text = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy") .format(new Date(timestamp * 1000L)); } catch (NumberFormatException exception) { text = ""; } createdLabel.setText(text); } String numberOfMessages = attributes.get("ApproximateNumberOfMessages"); numberOfMessagesLabel.setText(numberOfMessages == null ? "" : numberOfMessages); String numberOfMessagesInFlight = attributes.get("ApproximateNumberOfMessagesNotVisible"); numberOfMessagesInFlightLabel.setText(numberOfMessagesInFlight == null ? "" : numberOfMessagesInFlight); } }); } private String getEndpointFromUrl(final String url) { try { URI parsed = new URI(url); return parsed.getScheme() + "://" + parsed.getAuthority(); } catch (URISyntaxException exception) { throw new RuntimeException("Could not parse URL: " + url, exception); } } } private class EnvironmentAutoScalingEditorSection extends AbstractEnvironmentResourcesEditorSection { private Label maxSizeLabel; private Label minSizeLabel; private Label launchConfigurationLabel; private Label desiredCapacityLabel; private Label healthCheckTypeLabel; private Label createdLabel; private Label availabilityZonesLabel; private Label nameLabel; @Override public void createSection(Composite parent) { super.createSection(parent); Composite composite = createSection(parent, "Amazon Auto Scaling Group", "Your Amazon Auto Scaling group controls how your fleet dynamically resizes."); section.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); composite.setLayout(new GridLayout(2, false)); GridDataFactory gdf = GridDataFactory.swtDefaults().align(SWT.FILL, SWT.TOP).grab(true, false); new Label(composite, SWT.NONE).setText("Name:"); nameLabel = new Label(composite, SWT.NONE); gdf.applyTo(nameLabel); new Label(composite, SWT.NONE).setText("Availability Zones:"); availabilityZonesLabel = new Label(composite, SWT.NONE); gdf.applyTo(availabilityZonesLabel); new Label(composite, SWT.NONE).setText("Created:"); createdLabel = new Label(composite, SWT.NONE); gdf.applyTo(createdLabel); new Label(composite, SWT.NONE).setText("Health Check Type:"); healthCheckTypeLabel = new Label(composite, SWT.NONE); gdf.applyTo(healthCheckTypeLabel); new Label(composite, SWT.NONE).setText("Launch Configuration:"); launchConfigurationLabel = new Label(composite, SWT.NONE); gdf.applyTo(launchConfigurationLabel); new Label(composite, SWT.NONE).setText("Desired Capacity:"); desiredCapacityLabel = new Label(composite, SWT.NONE); gdf.applyTo(desiredCapacityLabel); new Label(composite, SWT.NONE).setText("Min Size:"); minSizeLabel = new Label(composite, SWT.NONE); gdf.applyTo(minSizeLabel); new Label(composite, SWT.NONE).setText("Max Size:"); maxSizeLabel = new Label(composite, SWT.NONE); gdf.applyTo(maxSizeLabel); } @Override public void update(EnvironmentResourceDescription resources) { Region region = RegionUtils.getRegionByEndpoint(getEnvironment().getRegionEndpoint()); String endpoint = region.getServiceEndpoints().get(ServiceAbbreviations.AUTOSCALING); AmazonAutoScaling as = AwsToolkitCore.getClientFactory(getEnvironment().getAccountId()).getAutoScalingClientByEndpoint(endpoint); if ( !resources.getAutoScalingGroups().isEmpty() ) { DescribeAutoScalingGroupsRequest request = new DescribeAutoScalingGroupsRequest() .withAutoScalingGroupNames(resources.getAutoScalingGroups().get(0).getName()); List<AutoScalingGroup> autoScalingGroups = as.describeAutoScalingGroups(request).getAutoScalingGroups(); if ( autoScalingGroups.size() > 0 ) { final AutoScalingGroup group = autoScalingGroups.get(0); Display.getDefault().asyncExec(new Runnable() { public void run() { nameLabel.setText(group.getAutoScalingGroupName()); availabilityZonesLabel.setText(group.getAvailabilityZones().toString()); createdLabel.setText("" + group.getCreatedTime()); healthCheckTypeLabel.setText(group.getHealthCheckType()); desiredCapacityLabel.setText("" + group.getDesiredCapacity()); launchConfigurationLabel.setText(group.getLaunchConfigurationName()); minSizeLabel.setText("" + group.getMinSize()); maxSizeLabel.setText("" + group.getMaxSize()); } }); } } } } private class EnvironmentElasticLoadBalancingEditorSection extends AbstractEnvironmentResourcesEditorSection { private Label nameLabel; private Label dnsLabel; private Label createdLabel; private Label availabilityZonesLabel; @Override public void createSection(Composite parent) { super.createSection(parent); Composite composite = createSection(parent, "Amazon Elastic Load Balancer", "Your Elastic Load Balancer provides a single access point for the fleet of EC2 instances running your application."); GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false); gridData.widthHint = 300; section.setLayoutData(gridData); composite.setLayout(new GridLayout(2, false)); GridDataFactory gdf = GridDataFactory.swtDefaults().align(SWT.FILL, SWT.TOP).grab(true, false); new Label(composite, SWT.NONE).setText("Name:"); nameLabel = new Label(composite, SWT.NONE); gdf.applyTo(nameLabel); new Label(composite, SWT.NONE).setText("DNS:"); dnsLabel = new Label(composite, SWT.WRAP); gdf.applyTo(dnsLabel); new Label(composite, SWT.NONE).setText("Created:"); createdLabel = new Label(composite, SWT.NONE); gdf.applyTo(createdLabel); new Label(composite, SWT.NONE).setText("Availability Zones:"); availabilityZonesLabel = new Label(composite, SWT.NONE); gdf.applyTo(availabilityZonesLabel); } @Override public void update(EnvironmentResourceDescription resources) { Region region = RegionUtils.getRegionByEndpoint(getEnvironment().getRegionEndpoint()); String endpoint = region.getServiceEndpoints().get(ServiceAbbreviations.ELB); AmazonElasticLoadBalancing elb = AwsToolkitCore.getClientFactory(getEnvironment().getAccountId()).getElasticLoadBalancingClientByEndpoint(endpoint); if (resources.getLoadBalancers() == null || resources.getLoadBalancers().size() == 0) { return; } String loadBalancerName = resources.getLoadBalancers().get(0).getName(); DescribeLoadBalancersRequest request = new DescribeLoadBalancersRequest().withLoadBalancerNames(loadBalancerName); List<LoadBalancerDescription> loadBalancers = elb.describeLoadBalancers(request).getLoadBalancerDescriptions(); if (loadBalancers.size() == 0) { return; } final LoadBalancerDescription lb = loadBalancers.get(0); Display.getDefault().asyncExec(new Runnable() { public void run() { nameLabel.setText(lb.getLoadBalancerName()); dnsLabel.setText(lb.getDNSName()); createdLabel.setText(lb.getCreatedTime().toString()); availabilityZonesLabel.setText(lb.getAvailabilityZones().toString()); Composite parent = nameLabel.getParent(); parent.setSize(parent.computeSize(parent.getSize().x, SWT.DEFAULT, true)); parent.getParent().layout(true, true); } }); } } private class EnvironmentInstancesEditorSection extends AbstractEnvironmentResourcesEditorSection { private InstanceSelectionTable instanceSelectionTable; @Override public void createSection(Composite parent) { super.createSection(parent); Composite composite = createSection(parent, "Amazon EC2 Instances", "These instances make up the fleet in your environment"); GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1); section.setLayoutData(gridData); instanceSelectionTable = new InstanceSelectionTable(composite); instanceSelectionTable.setAccountIdOverride(getEnvironment().getAccountId()); Region region = RegionUtils.getRegionByEndpoint(getEnvironment().getRegionEndpoint()); String ec2Endpoint = region.getServiceEndpoints().get(ServiceAbbreviations.EC2); instanceSelectionTable.setEc2RegionOverride(region); } @Override public void update(EnvironmentResourceDescription resources) { List<String> instanceIds = new ArrayList<String>(); for (Instance instance : resources.getInstances()) { instanceIds.add(instance.getId()); } instanceSelectionTable.setInstancesToList(instanceIds); } } @Override public void setFocus() {} private AWSElasticBeanstalk getClient() { Environment environment = getEnvironment(); return AwsToolkitCore.getClientFactory(environment.getAccountId()) .getElasticBeanstalkClientByEndpoint(environment.getRegionEndpoint()); } private Environment getEnvironment() { return (Environment)server.loadAdapter(Environment.class, null); } }