diff --git a/plugins/org.jboss.tools.openshift.client/.classpath b/plugins/org.jboss.tools.openshift.client/.classpath index 455b6c4c08..01630f32b6 100644 --- a/plugins/org.jboss.tools.openshift.client/.classpath +++ b/plugins/org.jboss.tools.openshift.client/.classpath @@ -2,7 +2,7 @@ - + diff --git a/plugins/org.jboss.tools.openshift.common.core/src/org/jboss/tools/openshift/common/core/utils/StringUtils.java b/plugins/org.jboss.tools.openshift.common.core/src/org/jboss/tools/openshift/common/core/utils/StringUtils.java index 70b0345186..004480ea49 100644 --- a/plugins/org.jboss.tools.openshift.common.core/src/org/jboss/tools/openshift/common/core/utils/StringUtils.java +++ b/plugins/org.jboss.tools.openshift.common.core/src/org/jboss/tools/openshift/common/core/utils/StringUtils.java @@ -27,6 +27,10 @@ public class StringUtils { private static final String LINE_SEPARATOR_KEY = "line.separator"; private static final String SHORTENING_MARKER = "..."; + public static String pluralize(String value) { + return value + "s"; + } + public static String null2emptyString(String value) { if (value != null) { return value; diff --git a/plugins/org.jboss.tools.openshift.common.ui/.classpath b/plugins/org.jboss.tools.openshift.common.ui/.classpath index e03f2a6efe..a2c0e3b258 100644 --- a/plugins/org.jboss.tools.openshift.common.ui/.classpath +++ b/plugins/org.jboss.tools.openshift.common.ui/.classpath @@ -1,8 +1,7 @@ - + - diff --git a/plugins/org.jboss.tools.openshift.common.ui/META-INF/MANIFEST.MF b/plugins/org.jboss.tools.openshift.common.ui/META-INF/MANIFEST.MF index e9b90344e1..48e1e3e96a 100644 --- a/plugins/org.jboss.tools.openshift.common.ui/META-INF/MANIFEST.MF +++ b/plugins/org.jboss.tools.openshift.common.ui/META-INF/MANIFEST.MF @@ -23,8 +23,7 @@ Require-Bundle: org.jboss.tools.openshift.common.core;bundle-version="[3.0.0,4.0 org.eclipse.core.resources;bundle-version="3.9.100", org.eclipse.core.runtime, org.eclipse.m2e.core;bundle-version="1.6.0", - org.apache.commons.lang;bundle-version="2.6.0", - org.jboss.tools.openshift.client;bundle-version="3.1.0" + org.apache.commons.lang;bundle-version="2.6.0" Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-ActivationPolicy: lazy Bundle-Vendor: %Bundle-Vendor diff --git a/plugins/org.jboss.tools.openshift.common.ui/plugin.xml b/plugins/org.jboss.tools.openshift.common.ui/plugin.xml index 0f9c9add9d..6c2312d54d 100644 --- a/plugins/org.jboss.tools.openshift.common.ui/plugin.xml +++ b/plugins/org.jboss.tools.openshift.common.ui/plugin.xml @@ -348,15 +348,12 @@ - - - 0){ + builder.append(parts[0]).append(" hrs."); + } + if(Integer.valueOf(parts[1]) > 0){ + builder.append(" ").append(parts[1]).append(" min."); + } + if(Integer.valueOf(parts[2]) > 0){ + builder.append(" ").append(parts[2]).append(" sec."); + } + if(builder.length() == 0) { + builder.append("Now"); + } + return builder.toString().trim(); + } + + public static String formatSince(String value) { + return formatSince(value, null); + } + public static String formatSince(String value, TimeZone timezone) { + try { + Date date = parse(value); + DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.FULL); + if(timezone != null) { + formatter.setTimeZone(timezone); + } + return formatter.format(date); + } catch (ParseException e) { + OpenShiftCommonUIActivator.getDefault().getLogger().logWarning("Unable to parse format duration value: " + value, e); + } + return value; + } + public static Date parse(String value) throws ParseException { + //ref: http://www.java2s.com/Code/Java/Data-Type/ISO8601dateparsingutility.htm + //assume date is like: '2015-11-11T20:32:37Z' + String modValue = value.substring(0, value.length()-1) + "GMT-00:00"; + SimpleDateFormat parser = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssz"); + return parser.parse(modValue); + } +} diff --git a/plugins/org.jboss.tools.openshift.common.ui/src/org/jboss/tools/openshift/internal/common/ui/utils/OpenShiftUIUtils.java b/plugins/org.jboss.tools.openshift.common.ui/src/org/jboss/tools/openshift/internal/common/ui/utils/OpenShiftUIUtils.java index 4cabe722dc..605820a341 100644 --- a/plugins/org.jboss.tools.openshift.common.ui/src/org/jboss/tools/openshift/internal/common/ui/utils/OpenShiftUIUtils.java +++ b/plugins/org.jboss.tools.openshift.common.ui/src/org/jboss/tools/openshift/internal/common/ui/utils/OpenShiftUIUtils.java @@ -20,7 +20,7 @@ */ public class OpenShiftUIUtils { - private static final String OPENSHIFT_EXPLORER_VIEW_ID = "org.jboss.tools.openshift.express.ui.explorer.expressConsoleView"; + public static final String OPENSHIFT_EXPLORER_VIEW_ID = "org.jboss.tools.openshift.express.ui.explorer.expressConsoleView"; public static void showOpenShiftExplorerView() { Display.getDefault().asyncExec(new Runnable() { diff --git a/plugins/org.jboss.tools.openshift.core/src/org/jboss/tools/openshift/core/OpenShiftAPIAnnotations.java b/plugins/org.jboss.tools.openshift.core/src/org/jboss/tools/openshift/core/OpenShiftAPIAnnotations.java index b23cd43359..846cc13c11 100644 --- a/plugins/org.jboss.tools.openshift.core/src/org/jboss/tools/openshift/core/OpenShiftAPIAnnotations.java +++ b/plugins/org.jboss.tools.openshift.core/src/org/jboss/tools/openshift/core/OpenShiftAPIAnnotations.java @@ -18,5 +18,14 @@ */ public interface OpenShiftAPIAnnotations { + static final String BUILD_NAME = "openshift.io/build.name"; + static final String BUILD_NUMBER = "openshift.io/build.number"; + + static final String BUILD_CONFIG_NAME = "openshift.io/build-config.name"; + + static final String DEPLOYMENT_CONFIG_LATEST_VERSION = "openshift.io/deployment-config.latest-version"; + static final String DEPLOYMENT_CONFIG_NAME = "openshift.io/deployment-config.name"; + static final String DEPLOYMENT_NAME = "openshift.io/deployment.name"; + static final String GENERATED_BY = "openshift.io/generated-by"; } diff --git a/plugins/org.jboss.tools.openshift.ui/META-INF/MANIFEST.MF b/plugins/org.jboss.tools.openshift.ui/META-INF/MANIFEST.MF index d503e75efd..3d6ff0e639 100644 --- a/plugins/org.jboss.tools.openshift.ui/META-INF/MANIFEST.MF +++ b/plugins/org.jboss.tools.openshift.ui/META-INF/MANIFEST.MF @@ -36,6 +36,7 @@ Require-Bundle: org.jboss.tools.openshift.common.ui;bundle-version="[3.0.0,4.0.0 org.eclipse.jdt.launching;bundle-version="3.8.0", org.eclipse.linuxtools.docker.core;bundle-version="1.2.0", org.eclipse.linuxtools.docker.ui;bundle-version="1.2.0", + org.eclipse.ui.views.properties.tabbed, org.eclipse.ui.ide, org.eclipse.core.variables, org.apache.commons.io;bundle-version="2.0.1", diff --git a/plugins/org.jboss.tools.openshift.ui/plugin.properties b/plugins/org.jboss.tools.openshift.ui/plugin.properties index 9cc086da8f..a2780ae40e 100644 --- a/plugins/org.jboss.tools.openshift.ui/plugin.properties +++ b/plugins/org.jboss.tools.openshift.ui/plugin.properties @@ -16,3 +16,6 @@ openshift.command.project.manage = Manage Projects... openshift.command.project.delete = Delete Project openshift.command.editresource=Edit... openshift.preferences.page.title = OpenShift 3 + +#Labels for Explorer view tabbed properties +openshift.explorer.properties.tab.builds=Builds \ No newline at end of file diff --git a/plugins/org.jboss.tools.openshift.ui/plugin.xml b/plugins/org.jboss.tools.openshift.ui/plugin.xml index 52ac83f0f9..b154fae506 100644 --- a/plugins/org.jboss.tools.openshift.ui/plugin.xml +++ b/plugins/org.jboss.tools.openshift.ui/plugin.xml @@ -503,6 +503,39 @@ + + + + + + + + + + + + + + + + @@ -586,11 +619,28 @@ + + + + + + + + + + @@ -653,6 +703,11 @@ + + - - + locationURI="popup:org.eclipse.ui.views.PropertySheet"> + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/explorer/Deployment.java b/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/explorer/Deployment.java deleted file mode 100644 index 5074e5c4e0..0000000000 --- a/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/explorer/Deployment.java +++ /dev/null @@ -1,65 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Red Hat, Inc. - * Distributed under license by Red Hat, Inc. All rights reserved. - * This program is made available under the terms of the - * Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - ******************************************************************************/ -package org.jboss.tools.openshift.internal.ui.explorer; - -<<<<<<< HEAD -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; -======= -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; ->>>>>>> [JBIDE-19178] Simple deployment view - -import com.openshift.restclient.model.IPod; -import com.openshift.restclient.model.IService; -import com.openshift.restclient.model.route.IRoute; - -/** - * A deployment is the collection of resources - * that makes up an 'application' - * - * @author jeff.cantrill - * - */ -public class Deployment { - - private IService service; - private Set routes; - private Set pods; - - public Deployment(IService service, Collection routes, Collection pods) { - this.service = service; - this.pods = new HashSet<>(pods); - this.routes = new HashSet<>(routes); - } - - public Collection getPods() { - return Collections.unmodifiableSet(pods); - } - public Collection getRoutes() { - return Collections.unmodifiableSet(this.routes); - } - public IService getService() { - return this.service; - } - - public void add(IPod pod) { - this.pods.add(pod); - } - - public void remove(IPod pod) { - this.pods.remove(pod); - } - -} diff --git a/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/explorer/DeploymentResourceMapper.java b/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/explorer/DeploymentResourceMapper.java deleted file mode 100644 index aeae4c67e4..0000000000 --- a/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/explorer/DeploymentResourceMapper.java +++ /dev/null @@ -1,75 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Red Hat, Inc. - * Distributed under license by Red Hat, Inc. All rights reserved. - * This program is made available under the terms of the - * Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - ******************************************************************************/ -package org.jboss.tools.openshift.internal.ui.explorer; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.List; -import java.util.stream.Collectors; - -import org.jboss.tools.openshift.core.connection.Connection; -import org.jboss.tools.openshift.core.connection.ConnectionsRegistryUtil; - -import com.openshift.restclient.ResourceKind; -import com.openshift.restclient.model.IPod; -import com.openshift.restclient.model.IProject; -import com.openshift.restclient.model.IService; -import com.openshift.restclient.model.route.IRoute; - -public class DeploymentResourceMapper { - - private IProject project; - private Connection conn; - - public DeploymentResourceMapper(Connection conn, IProject project) { - this.project = project; - this.conn = conn; - } - - public List getDeployments(){ - List services = conn.getResources(ResourceKind.SERVICE, project.getName()); - Map> serviceToRoutes = mapServiceToRoutes(project.getName()); - - List adapters = new ArrayList<>(services.size()); - for (IService service : services) { - adapters.add(getDeployment(service, serviceToRoutes.get(service.getName()))); - } - - return adapters; - } - - public static Deployment getDeployment(IService service) { - List routes = ConnectionsRegistryUtil.getConnectionFor(service).getResources(ResourceKind.ROUTE, service.getNamespace()); - return getDeployment(service, routes); - } - - private static Deployment getDeployment(IService service, Collection routes) { - List pods = service.getPods(); - return new Deployment(service, routes, pods); - } - - private Map> mapServiceToRoutes(String projectName){ - List routes = conn.getResources(ResourceKind.ROUTE, project.getName()); - Map> map = new HashMap>(routes.size()); - for (IRoute route : routes) { - String service = route.getServiceName(); - if(!map.containsKey(service)) { - map.put(service, new HashSet<>()); - } - map.get(service).add(route); - } - return map; - } -} diff --git a/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/explorer/OpenShiftExplorerContentProvider.java b/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/explorer/OpenShiftExplorerContentProvider.java index 5e8700672f..cb51aac383 100644 --- a/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/explorer/OpenShiftExplorerContentProvider.java +++ b/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/explorer/OpenShiftExplorerContentProvider.java @@ -23,13 +23,13 @@ import org.jboss.tools.openshift.core.connection.ConnectionsRegistryUtil; import org.jboss.tools.openshift.internal.common.ui.explorer.BaseExplorerContentProvider; import org.jboss.tools.openshift.internal.core.WatchManager; +import org.jboss.tools.openshift.internal.ui.models.Deployment; +import org.jboss.tools.openshift.internal.ui.models.DeploymentResourceMapper; import com.openshift.restclient.OpenShiftException; import com.openshift.restclient.ResourceKind; -import com.openshift.restclient.model.IPod; import com.openshift.restclient.model.IProject; import com.openshift.restclient.model.IResource; -import com.openshift.restclient.model.IService; /** * Contributes OpenShift 3 specific content to the OpenShift explorer view @@ -38,12 +38,10 @@ */ public class OpenShiftExplorerContentProvider extends BaseExplorerContentProvider { - private Map> deploymentsByProject = new HashMap<>(); - private Map deploymentByService = new HashMap<>(); + private Map deploymentCache = new HashMap<>(); @Override protected void handleConnectionChanged(IConnection connection, String property, Object oldValue, Object newValue) { - if (!(connection instanceof Connection)) { return; } @@ -57,6 +55,7 @@ protected void handleConnectionChanged(IConnection connection, String property, handleRemoveResource((IResource) oldValue); } else { //update + handleUpdateResource((IResource) newValue); updateChildrenFromViewer(newValue); } } else if (ConnectionProperties.PROPERTY_PROJECTS.equals(property)) { @@ -65,57 +64,23 @@ protected void handleConnectionChanged(IConnection connection, String property, super.handleConnectionChanged(connection, property, oldValue, newValue); } } - private void handleAddResource(IResource resource) { - switch(resource.getKind()) { - case ResourceKind.SERVICE: - IService service = (IService) resource; - Deployment deployment = DeploymentResourceMapper.getDeployment(service); - deploymentByService.put(service, deployment); - addChildrenToViewer(resource.getProject(), deployment); - break; - case ResourceKind.POD: - IPod pod = (IPod)resource; - Map labels = pod.getLabels(); - for (IService depService : deploymentByService.keySet()) { - Map selector = depService.getSelector(); - if(selectorsOverlap(selector, labels)) { - Deployment deploymentForPod = deploymentByService.get(depService); - deploymentForPod.add(pod); - addChildrenToViewer(depService, deploymentForPod); - } - } - default: - } + + private void handleUpdateResource(IResource resource) { + final String project = resource.getNamespace(); + if(!deploymentCache.containsKey(project)) return; + deploymentCache.get(project).update(resource); } - private void handleRemoveResource(IResource resource) { - switch(resource.getKind()) { - case ResourceKind.SERVICE: - IService service = (IService)resource; - deploymentByService.remove(service); - removeChildrenFromViewer(resource.getProject(), deploymentByService.get(service)); - break; - case ResourceKind.POD: - IPod pod = (IPod)resource; - for (IService deployedService : deploymentByService.keySet()) { - if(selectorsOverlap(deployedService.getSelector(), pod.getLabels())){ - deploymentByService.get(deployedService).remove(pod); - removeChildrenFromViewer(deploymentByService, pod); - } - } - default: - } + + private void handleAddResource(IResource resource) { + final String project = resource.getNamespace(); + if(!deploymentCache.containsKey(project)) return; + deploymentCache.get(project).add(resource); } - private boolean selectorsOverlap(Map source, Map target) { - if(!target.keySet().containsAll(source.keySet())) { - return false; - } - for (String key : source.keySet()) { - if(!target.get(key).equals(source.get(key))) { - return false; - } - } - return true; + private void handleRemoveResource(IResource resource) { + final String project = resource.getNamespace(); + if(!deploymentCache.containsKey(project)) return; + deploymentCache.get(project).remove(resource); } //TODO: Handle updates to a project when needed. Back-end doesnt support edit of resources(most?) now @@ -132,7 +97,6 @@ private void handleProjectChanges(Connection connection, Object oldValue, Object public void handleRemove(int index, Object element) { IProject project = (IProject) element; removed.add(project); - deploymentsByProject.remove(project); } @Override @@ -147,14 +111,6 @@ public void handleAdd(int index, Object element) { @Override protected void handleConnectionRemoved(IConnection connection) { - if(!(connection instanceof Connection))return; - for (IProject project : deploymentsByProject.keySet()) { - Connection conn = ConnectionsRegistryUtil.getConnectionFor(project); - if(connection.equals(conn)) { - deploymentsByProject.remove(project); - break; - } - } super.handleConnectionRemoved(connection); } @@ -186,13 +142,9 @@ public Object[] getChildrenFor(Object parentElement) { } else if (parentElement instanceof IProject) { IProject project = (IProject) parentElement; DeploymentResourceMapper mapper = new DeploymentResourceMapper(ConnectionsRegistryUtil.getConnectionFor(project), project); - deploymentsByProject.put(project, mapper.getDeployments()); - for (Deployment deployment : mapper.getDeployments()) { - deploymentByService.put(deployment.getService(),deployment); - } + deploymentCache.put(project.getName(), mapper); WatchManager.getInstance().startWatch(project); return mapper.getDeployments().toArray(); - } else if (parentElement instanceof Deployment) { return ((Deployment) parentElement).getPods().toArray(); } diff --git a/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/explorer/OpenShiftExplorerLabelProvider.java b/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/explorer/OpenShiftExplorerLabelProvider.java index e984f6b4a9..e9bf5d1357 100644 --- a/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/explorer/OpenShiftExplorerLabelProvider.java +++ b/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/explorer/OpenShiftExplorerLabelProvider.java @@ -11,9 +11,7 @@ package org.jboss.tools.openshift.internal.ui.explorer; import java.util.Collection; -import java.util.List; -import org.apache.commons.lang.ObjectUtils; import org.eclipse.jface.viewers.StyledString; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.graphics.Image; @@ -22,6 +20,8 @@ import org.jboss.tools.openshift.internal.common.ui.OpenShiftCommonImages; import org.jboss.tools.openshift.internal.common.ui.explorer.BaseExplorerLabelProvider; import org.jboss.tools.openshift.internal.ui.OpenShiftImages; +import org.jboss.tools.openshift.internal.ui.models.Deployment; +import org.jboss.tools.openshift.internal.ui.models.IResourceUIModel; import com.openshift.restclient.ResourceKind; import com.openshift.restclient.capability.CapabilityVisitor; @@ -62,8 +62,8 @@ public String getText(Object element) { public Image getImage(Object element) { if (element instanceof Deployment) { return OpenShiftImages.GEAR_IMG; - } else if (element instanceof IResource) { - IResource resource = (IResource) element; + } else if (element instanceof IResource || element instanceof IResourceUIModel) { + IResource resource = element instanceof IResourceUIModel ? ((IResourceUIModel)element).getResource() : (IResource) element; switch (resource.getKind()) { case ResourceKind.BUILD_CONFIG: return OpenShiftImages.BUILDCONFIG_IMG; @@ -85,8 +85,8 @@ public Image getImage(Object element) { @Override public StyledString getStyledText(Object element) { - if (element instanceof IResource) { - IResource resource = (IResource) element; + if (element instanceof IResource || element instanceof IResourceUIModel) { + IResource resource = element instanceof IResourceUIModel ? ((IResourceUIModel)element).getResource() : (IResource) element; switch (resource.getKind()) { case ResourceKind.BUILD: return getStyledText((IBuild) resource); @@ -123,10 +123,10 @@ public StyledString getStyledText(Object element) { return super.getStyledText(element); } - private String formatRoute(Collection routes) { + private String formatRoute(Collection routes) { if(routes.size() > 0) { - IRoute route = (IRoute)routes.toArray()[0]; - return String.format("%s%s", route.getHost(), route.getPath()); + IRoute route = (IRoute)routes.iterator().next().getResource(); + return route.getURL(); } return ""; diff --git a/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/handler/DeleteResourceHandler.java b/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/handler/DeleteResourceHandler.java index 18e7e6564c..4801e83c0b 100644 --- a/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/handler/DeleteResourceHandler.java +++ b/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/handler/DeleteResourceHandler.java @@ -20,6 +20,7 @@ import org.eclipse.ui.handlers.HandlerUtil; import org.jboss.tools.openshift.internal.common.ui.utils.UIUtils; import org.jboss.tools.openshift.internal.ui.job.DeleteResourceJob; +import org.jboss.tools.openshift.internal.ui.models.IResourceUIModel; import com.openshift.restclient.model.IResource; @@ -32,8 +33,14 @@ public class DeleteResourceHandler extends AbstractHandler { @Override public Object execute(final ExecutionEvent event) throws ExecutionException { - ISelection selection = HandlerUtil.getCurrentSelection(event); + ISelection selection = HandlerUtil.getActivePart(event).getSite().getWorkbenchWindow().getSelectionService().getSelection(); IResource resource = UIUtils.getFirstElement(selection, IResource.class); + if(resource == null) { + IResourceUIModel model = UIUtils.getFirstElement(selection, IResourceUIModel.class); + if(model != null) { + resource = model.getResource(); + } + } if(resource == null) { return Status.OK_STATUS; } diff --git a/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/handler/PodLogsHandler.java b/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/handler/PodLogsHandler.java index 8ea3fcca97..03bfe22f9b 100644 --- a/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/handler/PodLogsHandler.java +++ b/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/handler/PodLogsHandler.java @@ -18,25 +18,27 @@ import org.eclipse.jface.viewers.ISelection; import org.eclipse.osgi.util.NLS; import org.eclipse.ui.handlers.HandlerUtil; +import org.jboss.tools.openshift.core.OpenShiftAPIAnnotations; import org.jboss.tools.openshift.core.connection.Connection; import org.jboss.tools.openshift.core.connection.ConnectionsRegistryUtil; import org.jboss.tools.openshift.internal.common.ui.utils.UIUtils; import org.jboss.tools.openshift.internal.ui.job.PodLogsJob; +import org.jboss.tools.openshift.internal.ui.models.IResourceUIModel; import com.openshift.restclient.ResourceKind; import com.openshift.restclient.model.IBuild; import com.openshift.restclient.model.IPod; +import com.openshift.restclient.model.IResource; /** * @author jeff.cantrill */ public class PodLogsHandler extends AbstractOpenShiftCliHandler { private static final String [] STATES = new String [] {"Running", "Succeeded", "Failed"}; - private static final String BUILDNAME_ANNOTATION = "openshift.io/build.name"; @Override protected void handleEvent(ExecutionEvent event){ - ISelection selection = HandlerUtil.getCurrentSelection(event); + ISelection selection = HandlerUtil.getActivePart(event).getSite().getWorkbenchWindow().getSelectionService().getSelection(); IPod pod = UIUtils.getFirstElement(selection, IPod.class); if(pod == null) { pod = getPodFromBuild(selection); @@ -62,12 +64,21 @@ private void showLogs(IPod pod, ExecutionEvent event) { private IPod getPodFromBuild(ISelection selection) { IBuild build = UIUtils.getFirstElement(selection, IBuild.class); + if(build == null) { + IResourceUIModel model = UIUtils.getFirstElement(selection, IResourceUIModel.class); + if(model != null) { + IResource resource = model.getResource(); + if(resource != null && ResourceKind.BUILD.equals(resource.getKind())) { + build = (IBuild) resource; + } + } + } if(build != null) { final String buildName = build.getName(); Connection connection = ConnectionsRegistryUtil.safeGetConnectionFor(build); List pods = connection.getResources(ResourceKind.POD, build.getNamespace()); for (IPod pod : pods) { - if(buildName.equals(pod.getAnnotation(BUILDNAME_ANNOTATION))) { + if(buildName.equals(pod.getAnnotation(OpenShiftAPIAnnotations.BUILD_NAME))) { return pod; } } diff --git a/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/handler/StartBuildHandler.java b/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/handler/StartBuildHandler.java index 40cc8ab4c7..1700c5b290 100644 --- a/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/handler/StartBuildHandler.java +++ b/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/handler/StartBuildHandler.java @@ -13,14 +13,18 @@ import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; -import org.eclipse.core.runtime.Status; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.ISelection; import org.eclipse.ui.handlers.HandlerUtil; +import org.jboss.tools.openshift.core.OpenShiftAPIAnnotations; +import org.jboss.tools.openshift.core.connection.Connection; +import org.jboss.tools.openshift.core.connection.ConnectionsRegistryUtil; import org.jboss.tools.openshift.internal.common.ui.utils.UIUtils; +import org.jboss.tools.openshift.internal.ui.OpenShiftUIActivator; import org.jboss.tools.openshift.internal.ui.job.StartBuildJob; +import org.jboss.tools.openshift.internal.ui.models.IResourceUIModel; -import com.openshift.restclient.model.IBuildConfig; +import com.openshift.restclient.ResourceKind; import com.openshift.restclient.model.IResource; /** @@ -29,17 +33,48 @@ * */ public class StartBuildHandler extends AbstractHandler{ + + private static final String SOURCE = "org.jboss.tools.openshift.ui.command.startbuild.source"; @Override - public Object execute(ExecutionEvent event) throws ExecutionException { - ISelection selection = HandlerUtil.getCurrentSelection(event); - IResource buildConfig = UIUtils.getFirstElement(selection, IResource.class); - if(buildConfig == null) { - MessageDialog.openInformation(HandlerUtil.getActiveShell(event), "Trigger Build", "A build or build config must be selected in order to trigger a build"); - return Status.OK_STATUS; + public Object execute(ExecutionEvent event) throws ExecutionException { + ISelection selection = HandlerUtil.getActivePart(event).getSite().getWorkbenchWindow().getSelectionService().getSelection(); + IResource buildAble = getBuildableResource(selection, event.getParameter(SOURCE)); + if(buildAble == null) { + MessageDialog.openInformation(HandlerUtil.getActiveShell(event), "Trigger Build", "A build or build config must be selected in order to trigger a build."); + return null; } - new StartBuildJob(buildConfig).schedule();; + new StartBuildJob(buildAble).schedule(); + return null; + } + + public IResource getBuildableResource(ISelection selection, String source) { + IResource buildAble = UIUtils.getFirstElement(selection, IResource.class); + if(buildAble == null) { + IResourceUIModel model = UIUtils.getFirstElement(selection, IResourceUIModel.class); + if(model != null) { + buildAble = model.getResource(); + //starting from a build instead of cloning + if(isStartingFromABuild(buildAble, source)) { + buildAble = loadBuildConfig(buildAble); + } + } + } + return buildAble; + } + + private boolean isStartingFromABuild(IResource resource, String source) { + return ResourceKind.BUILD_CONFIG.equals(source) && ResourceKind.BUILD.equals(resource.getKind()); + } + + private IResource loadBuildConfig(IResource build) { + Connection connection = ConnectionsRegistryUtil.safeGetConnectionFor(build); + String buildConfigName = build.getLabels().get(OpenShiftAPIAnnotations.BUILD_CONFIG_NAME); + if(!buildConfigName.isEmpty()) { + IResource proto = connection.getResourceFactory().stub(ResourceKind.BUILD_CONFIG, buildConfigName, build.getNamespace()); + return connection.getResource(proto); + } + OpenShiftUIActivator.getDefault().getLogger().logInfo("Unable to determine associated BuildConfig from Build: " + build.toJson()); return null; } - } diff --git a/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/job/StartBuildJob.java b/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/job/StartBuildJob.java index 67acd2847f..b9233cb313 100644 --- a/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/job/StartBuildJob.java +++ b/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/job/StartBuildJob.java @@ -14,10 +14,6 @@ import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.osgi.util.NLS; -import org.jboss.tools.openshift.common.core.connection.ConnectionsRegistrySingleton; -import org.jboss.tools.openshift.core.connection.Connection; -import org.jboss.tools.openshift.core.connection.ConnectionProperties; -import org.jboss.tools.openshift.core.connection.ConnectionsRegistryUtil; import org.jboss.tools.openshift.internal.common.core.job.AbstractDelegatingMonitorJob; import org.jboss.tools.openshift.internal.ui.OpenShiftUIActivator; @@ -55,12 +51,6 @@ public IBuild visit(IBuildTriggerable triggerable) { if(build == null) { return new Status(Status.INFO, OpenShiftUIActivator.PLUGIN_ID, "Manually triggering builds is unsupported"); } - Connection connection = ConnectionsRegistryUtil.getConnectionFor(buildsource); - ConnectionsRegistrySingleton.getInstance().fireConnectionChanged( - connection, - ConnectionProperties.PROPERTY_RESOURCE, - null, - build); return Status.OK_STATUS; }catch(OpenShiftException e) { return new Status(Status.ERROR, OpenShiftUIActivator.PLUGIN_ID, NLS.bind("Error starting build {0}.", buildsource.getName()), e); diff --git a/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/models/Deployment.java b/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/models/Deployment.java new file mode 100644 index 0000000000..6fe8b23367 --- /dev/null +++ b/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/models/Deployment.java @@ -0,0 +1,186 @@ +/******************************************************************************* + * Copyright (c) 2015 Red Hat, Inc. + * Distributed under license by Red Hat, Inc. All rights reserved. + * This program is made available under the terms of the + * Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + ******************************************************************************/ +package org.jboss.tools.openshift.internal.ui.models; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +import org.jboss.tools.common.databinding.ObservablePojo; +import org.jboss.tools.openshift.common.core.utils.StringUtils; + +import com.openshift.restclient.model.IPod; +import com.openshift.restclient.ResourceKind; +import com.openshift.restclient.model.IBuild; +import com.openshift.restclient.model.IReplicationController; +import com.openshift.restclient.model.IResource; +import com.openshift.restclient.model.IService; +import com.openshift.restclient.model.route.IRoute; + +/** + * A deployment is the collection of resources + * that makes up an 'application' + * + * @author jeff.cantrill + * + */ +public class Deployment extends ObservablePojo { + + public static final String PROP_BUILDS = getProperty(ResourceKind.BUILD); + public static final String PROP_PODS = getProperty(ResourceKind.BUILD); + public static final String PROP_ROUTES = getProperty(ResourceKind.ROUTE); + public static final String PROP_REPLICATION_CONTROLLERS = getProperty(ResourceKind.REPLICATION_CONTROLLER); + public static final String PROP_BUILD_CONFIGS = getProperty(ResourceKind.BUILD_CONFIG); + + private IService service; + private Map> resources = new ConcurrentHashMap<>(); + + public Deployment(IService service) { + this.service = service; + for (String kind : new String [] {ResourceKind.BUILD, ResourceKind.POD, ResourceKind.ROUTE, ResourceKind.REPLICATION_CONTROLLER, ResourceKind.BUILD_CONFIG}) { + resources.put(kind, new ArrayList<>()); + } + } + + public Deployment(IService service, Collection routes, Collection builds, Collection pods, Collection rcs) { + this.service = service; + resources.put(ResourceKind.BUILD, init(builds)); + resources.put(ResourceKind.POD, init(pods)); + resources.put(ResourceKind.ROUTE, init(routes)); + resources.put(ResourceKind.REPLICATION_CONTROLLER, init(rcs)); + } + private List init(Collection resources) { + if(resources != null) { + return resources.stream().map(r->new OpenShiftResourceUIModel(r)).collect(Collectors.toList()); + } + return new ArrayList<>(); + } + + public IService getService() { + return this.service; + } + + public Collection getBuilds() { + return resources.get(ResourceKind.BUILD); + } + + public void setBuilds(Collection builds) { + firePropertyChange(PROP_BUILDS, resources.get(ResourceKind.BUILD), resources.put(ResourceKind.BUILD, new ArrayList<>(builds))); + } + + public void setBuildResources(Collection builds) { + firePropertyChange(PROP_BUILDS, resources.get(ResourceKind.BUILD), resources.put(ResourceKind.BUILD, init(builds))); + } + + public Collection getPods() { + return resources.get(ResourceKind.POD); + } + + public void setPods(Collection pods) { + firePropertyChange(PROP_PODS, resources.get(ResourceKind.POD), resources.put(ResourceKind.POD, new ArrayList<>(pods))); + } + + public void setPodResources(Collection pods) { + firePropertyChange(PROP_PODS, resources.get(ResourceKind.POD), resources.put(ResourceKind.POD, init(pods))); + } + + public Collection getRoutes() { + return resources.get(ResourceKind.ROUTE); + } + + public void setRoutes(Collection routes) { + firePropertyChange(PROP_ROUTES, resources.get(ResourceKind.ROUTE), resources.put(ResourceKind.ROUTE, new ArrayList<>(routes))); + } + + public void setRouteResources(Collection routes) { + firePropertyChange(PROP_ROUTES, resources.get(ResourceKind.ROUTE), resources.put(ResourceKind.ROUTE, init(routes))); + } + + public Collection getReplicationControllers() { + return resources.get(ResourceKind.REPLICATION_CONTROLLER); + } + + public void setReplicationControllers(Collection rcs) { + firePropertyChange(PROP_REPLICATION_CONTROLLERS, resources.get(ResourceKind.REPLICATION_CONTROLLER), resources.put(ResourceKind.REPLICATION_CONTROLLER, new ArrayList<>(rcs))); + } + + public void setReplicationControllerResources(Collection rcs) { + firePropertyChange(PROP_REPLICATION_CONTROLLERS, resources.get(ResourceKind.REPLICATION_CONTROLLER), resources.put(ResourceKind.REPLICATION_CONTROLLER, init(rcs))); + } + public Collection getBuildConfigs(){ + return resources.get(ResourceKind.BUILD_CONFIG); + } + + public void setBuildConfigs(Collection buildConfigs) { + firePropertyChange(PROP_BUILD_CONFIGS, resources.get(ResourceKind.BUILD_CONFIG), resources.put(ResourceKind.BUILD_CONFIG, new ArrayList<>(buildConfigs))); + } + + public void setBuildConfigResources(Collection buildConfigs) { + firePropertyChange(PROP_BUILD_CONFIGS, resources.get(ResourceKind.BUILD_CONFIG), resources.put(ResourceKind.BUILD_CONFIG, init(buildConfigs))); + } + + public void add(IResource resource) { + final String property = getProperty(resource.getKind()); + List models = resources.get(resource.getKind()); + if(models != null) { + models.add(new OpenShiftResourceUIModel(resource)); + int index = models.size(); + fireIndexedPropertyChange(property, index, null, Collections.unmodifiableList(models)); + } + } + + public void remove(IResource resource) { + final String property = getProperty(resource.getKind()); + List models = resources.get(resource.getKind()); + if(models != null) { + int index = indexOf(models, resource); + if(index > -1) { + models.remove(index); + fireIndexedPropertyChange(property, index, Collections.unmodifiableList(models), null); + } + } + } + + public void update(IResource resource) { + final String property = getProperty(resource.getKind()); + List models = resources.get(resource.getKind()); + if(models != null) { + int index = indexOf(models, resource); + if(index > -1) { + List old = new ArrayList<>(models); + models.set(index, new OpenShiftResourceUIModel(resource)); + fireIndexedPropertyChange(property, index, old, Collections.unmodifiableList(models)); + } + } + } + + private int indexOf(List models, IResource resource) { + for (int i = 0; i < models.size(); i++) { + IResourceUIModel model = models.get(i); + if(model != null) { + IResource old = model.getResource(); + if(old.equals(resource)) { + return i; + } + } + } + return -1; + } + + private static String getProperty(String kind) { + return StringUtils.pluralize(kind.toLowerCase()); + } + +} diff --git a/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/models/DeploymentResourceMapper.java b/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/models/DeploymentResourceMapper.java new file mode 100644 index 0000000000..17c4f7f147 --- /dev/null +++ b/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/models/DeploymentResourceMapper.java @@ -0,0 +1,451 @@ +/******************************************************************************* + * Copyright (c) 2015 Red Hat, Inc. + * Distributed under license by Red Hat, Inc. All rights reserved. + * This program is made available under the terms of the + * Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + ******************************************************************************/ +package org.jboss.tools.openshift.internal.ui.models; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.eclipse.osgi.util.NLS; +import org.jboss.tools.openshift.core.OpenShiftAPIAnnotations; +import org.jboss.tools.openshift.core.connection.Connection; +import org.jboss.tools.openshift.internal.core.Trace; +import org.jboss.tools.openshift.internal.ui.OpenShiftUIActivator; + +import com.openshift.restclient.ResourceKind; +import com.openshift.restclient.model.IPod; +import com.openshift.restclient.model.IProject; +import com.openshift.restclient.model.IService; +import com.openshift.restclient.model.route.IRoute; + +import com.openshift.restclient.images.DockerImageURI; +import com.openshift.restclient.model.IBuild; +import com.openshift.restclient.model.IBuildConfig; +import com.openshift.restclient.model.IDeploymentConfig; +import com.openshift.restclient.model.IReplicationController; +import com.openshift.restclient.model.IResource; +import com.openshift.restclient.model.deploy.DeploymentTriggerType; +import com.openshift.restclient.model.deploy.IDeploymentImageChangeTrigger; +import com.openshift.restclient.model.deploy.IDeploymentTrigger; + +/** + * Figures out the resources in a project associated + * with a deployment + * + * @author jeff.cantrill + * + */ +public class DeploymentResourceMapper implements OpenShiftAPIAnnotations{ + + private static final String DOCKER_IMAGE_KIND = "DockerImage"; + private static final String IMAGE_STREAM_IMAGE_KIND = "ImageStreamImage"; + private static final String IMAGE_STREAM_TAG_KIND = "ImageStreamTag"; + private static final String RELATION_DELIMITER = "->"; + private static final Map RELATIONSHIP_TYPE_MAP = new HashMap<>(); + + private IProject project; + private Connection conn; + private List deployments = new ArrayList<>(); + private Map> resourceToDeployments = new ConcurrentHashMap<>(); + private Map> imageRefToDeployConfigs; + private Map> relationMap = new ConcurrentHashMap<>(); + private Map cache = new ConcurrentHashMap<>(); + + static { + RELATIONSHIP_TYPE_MAP.put(ResourceKind.BUILD, new String [] { + ResourceKind.BUILD_CONFIG, + ResourceKind.DEPLOYMENT_CONFIG, + ResourceKind.POD + }); + } + + public DeploymentResourceMapper(Connection conn, IProject project) { + this.project = project; + this.conn = conn; + + List rcs = load(ResourceKind.REPLICATION_CONTROLLER); + List services = load(ResourceKind.SERVICE); + List builds = load(ResourceKind.BUILD); + List pods = load(ResourceKind.POD); + List deployConfigs = load(ResourceKind.DEPLOYMENT_CONFIG); + List buildConfigs = load(ResourceKind.BUILD_CONFIG); + + imageRefToDeployConfigs = mapImageRefToDeployConfigs(deployConfigs); + + mapBuildsToDeploymentConfigs(builds); + mapChildToParent(pods, rcs, DEPLOYMENT_NAME); + mapChildToParent(rcs, deployConfigs, DEPLOYMENT_CONFIG_NAME); + mapChildToParent(pods, builds, BUILD_NAME); + mapChildToParent(builds, buildConfigs, BUILD_CONFIG_NAME); + + + + Map> serviceToRoutes = mapServiceToRoutes(project.getName()); + + //serice by name->deployment join selector + //service by name ->dc->deployment + for (IService service : services) { + Deployment deployment = new Deployment(service); + List servicePods = selectPodsForService(service, pods); + List appBuilds = getBuildsForDeployment(pods, builds); + List appBuildConfigs = getBuildConfigsForBuilds(appBuilds); + + deployment.setBuildResources(appBuilds); + deployment.setPodResources(servicePods); + deployment.setRouteResources(serviceToRoutes.get(service.getName())); + deployment.setBuildConfigResources(appBuildConfigs); + + mapResourcesFor(deployment); + deployments.add(deployment); + } + } + private List getBuildConfigsForBuilds(Collection builds){ + List buildConfigs = new ArrayList<>(); + for (IBuild build : builds) { + Collection configs = relationMap.get(getKey(build, ResourceKind.BUILD_CONFIG)); + if(configs != null) { + buildConfigs.addAll(configs); + } + } + return buildConfigs; + } + + private List load(String kind){ + List resources = conn.getResources(kind, project.getName()); + resources.forEach(r->cache.put(getCacheKey(r), r)); + return resources; + } + + private void mapBuildsToDeploymentConfigs(Collection builds) { + builds.forEach(build->mapBuildToDeploymentConfig(build)); + } + + private void mapBuildToDeploymentConfig(IBuild build) { + String imageRef = imageRef(build, project); + Collection deploymentConfigs = imageRefToDeployConfigs.get(imageRef); + if(deploymentConfigs != null) { + deploymentConfigs.forEach(dc->createRelation(build, dc)); + } + } + + private void mapChildToParent(Collection manys, Collection ones, String annotation) { + mapChildToParent(manys, ones, annotation, false); + } + /* + * Create a mapping between resources based on an annotation + * (e.g. pod-> resourcecontroller). Mapping key is KIND::NAME + */ + private void mapChildToParent(Collection manys, Collection ones, String annotation, boolean annotationKeyIsLabel) { + Map parents = ones.stream().collect(Collectors.toMap(IResource::getName, Function.identity())); + for (IResource child : manys) { + String parentName = annotationKeyIsLabel ? child.getLabels().get(annotation) : child.getAnnotation(annotation); + if(parents.containsKey(parentName)) { + IResource parent = parents.get(parentName); + createRelation(child, parent); + } + } + } + + /** + * Key for caching an object + * @param resource + * @return + */ + private String getCacheKey(IResource resource) { + return NLS.bind("{0}::{1}",resource.getName(),resource.getKind()); + } + + /** + * The key for mapping relationships + * @param resource + * @param targetKind + * @return + */ + private String getKey(IResource resource, String targetKind) { + return getKey(resource.getName(), resource.getKind(), targetKind); + } + + /** + * The key for mapping relationships + * @param resource + * @param targetKind + * @return + */ + private String getKey(String name, String sourceKind, String targetKind) { + return NLS.bind("{0}::{1}{2}{3}", new Object [] {name, sourceKind, RELATION_DELIMITER, targetKind}); + } + + private void createRelation(IResource start, IResource end) { + String startKey = getKey(start, end.getKind()); + if(!relationMap.containsKey(startKey)) { + relationMap.put(startKey, Collections.synchronizedList(new ArrayList<>())); + } + relationMap.get(startKey).add(end); + String endKey = getKey(end, start.getKind()); + if(!relationMap.containsKey(endKey)) { + relationMap.put(endKey, Collections.synchronizedList(new ArrayList<>())); + } + relationMap.get(endKey).add(start); + } + + private List selectPodsForService(IService service, List pods) { + final Map serviceSelector = service.getSelector(); + return pods.stream() + .filter(p->selectorsOverlap(serviceSelector, p.getLabels())) + .collect(Collectors.toList()); + } + + private boolean selectorsOverlap(Map source, Map target) { + if(!target.keySet().containsAll(source.keySet())) { + return false; + } + for (String key : source.keySet()) { + if(!target.get(key).equals(source.get(key))) { + return false; + } + } + return true; + } + + private void mapResourcesFor(Deployment deployment) { + mapResourcesToDeployment(deployment.getBuilds(), deployment); + mapResourcesToDeployment(deployment.getPods(), deployment); + mapResourcesToDeployment(deployment.getReplicationControllers(), deployment); + mapResourcesToDeployment(deployment.getRoutes(), deployment); + } + + private void mapResourcesToDeployment(Collection resources, Deployment deployment) { + for (IResourceUIModel model : resources) { + mapResourceToDeployment(model.getResource(), deployment); + } + } + + private void mapResourceToDeployment(IResource resource, Deployment deployment) { + if(!resourceToDeployments.containsKey(resource)) { + resourceToDeployments.put(resource, Collections.synchronizedList(new ArrayList<>())); + } + resourceToDeployments.get(resource).add(deployment); + } + + public Collection getDeployments(){ + return deployments; + } + + + private Map> mapServiceToRoutes(String projectName){ + List routes = conn.getResources(ResourceKind.ROUTE, project.getName()); + Map> map = new HashMap>(routes.size()); + for (IRoute route : routes) { + String service = route.getServiceName(); + if(!map.containsKey(service)) { + map.put(service, Collections.synchronizedSet(new HashSet<>())); + } + map.get(service).add(route); + } + return map; + } + private Map> mapServicesToRepControllers(Collection services, Collection rcs){ + Map> map = new HashMap<>(services.size()); + for (IReplicationController rc : rcs) { + Map deploymentSelector = rc.getReplicaSelector(); + for (IService service : services) { + Map serviceSelector = service.getSelector(); + if(selectorsJoin(serviceSelector, deploymentSelector)) { + if(!map.containsKey(service)) { + map.put(service, Collections.synchronizedList(new ArrayList<>())); + } + map.get(service).add(rc); + } + } + } + return map; + } + + /** + * + * @param source + * @param target + * @return true if target includes all source keys and values; false otherwise + */ + private boolean selectorsJoin(Map source, Map target) { + if(!target.keySet().containsAll(source.keySet())) { + return false; + } + for (String key : source.keySet()) { + if(!target.get(key).equals(source.get(key))) { + return false; + } + } + return true; + } + + private List getBuildsForDeployment(List pods, List builds) { + List buildsForDeployment = new ArrayList(); + for (IBuild build : builds) { + String buildImageRef = imageRef(build, this.project); + if(imageRefToDeployConfigs.containsKey(buildImageRef)) { + buildsForDeployment.add(build); + } + } + return buildsForDeployment; + } + + private Map> mapImageRefToDeployConfigs(Collection configs){ + Map> map = new ConcurrentHashMap<>(); + for (IDeploymentConfig dc : configs) { + List imageChangeTriggers = filterImageChangeTriggers(dc); + for (IDeploymentTrigger trigger : imageChangeTriggers) { + String imageRef = imageRef((IDeploymentImageChangeTrigger) trigger, this.project); + if(!map.containsKey(imageRef)) { + map.put(imageRef, Collections.synchronizedList(new ArrayList<>())); + } + map.get(imageRef).add(dc); + } + } + return map; + } + + private String imageRef(IBuild build, IProject project) { + final String kind = build.getOutputKind(); + if(IMAGE_STREAM_TAG_KIND.equals(kind) || IMAGE_STREAM_IMAGE_KIND.equals(kind)) { + return new DockerImageURI("", project.getName(),build.getOutputTo().getNameAndTag()).toString(); + } + if(DOCKER_IMAGE_KIND.equals(kind)) { + return build.getOutputTo().getNameAndTag().toString(); + } + return ""; + + } + + private String imageRef(IDeploymentImageChangeTrigger trigger, IProject project) { + final String kind = trigger.getKind(); + if(IMAGE_STREAM_TAG_KIND.equals(kind) || IMAGE_STREAM_IMAGE_KIND.equals(kind)) { + return new DockerImageURI("", project.getName(),trigger.getFrom().getNameAndTag()).toString(); + } + if(DOCKER_IMAGE_KIND.equals(kind)) { + return trigger.getFrom().getNameAndTag().toString(); + } + return ""; + } + + private List filterImageChangeTriggers(IDeploymentConfig dc){ + return dc.getTriggers() + .stream(). + filter(t->t.getType().equals(DeploymentTriggerType.IMAGE_CHANGE)).collect(Collectors.toList()); + } + + public synchronized void add(IResource resource) { + try { + Trace.debug("Trying to add resource to deployment {0}", resource); + switch(resource.getKind()) { + case ResourceKind.BUILD: + mapBuildToDeploymentConfig((IBuild) resource); + } + Collection deployments = findDeploymentsFor(resource); + if(deployments != null && !deployments.isEmpty()) { + for (Deployment deployment : deployments) { + deployment.add(resource); + mapResourceToDeployment(resource, deployment); + } + } + cache.put(getCacheKey(resource), resource); + }catch(Exception e) { + OpenShiftUIActivator.getDefault().getLogger().logError(e); + } + } + + public synchronized void remove(IResource resource) { + try { + Trace.debug("Trying to remove resource to deployment {0}", resource); + switch(resource.getKind()) { + case ResourceKind.BUILD: + } + Collection deployments = findDeploymentsFor(resource); + if(deployments != null && !deployments.isEmpty()) { + for (Deployment deployment : deployments) { + resourceToDeployments.remove(resource); + deployment.remove(resource); + } + } + if(RELATIONSHIP_TYPE_MAP.containsKey(ResourceKind.BUILD)) { + for (String kind : RELATIONSHIP_TYPE_MAP.get(ResourceKind.BUILD)) { + String left = getKey(resource, kind); + if(relationMap.containsKey(left)) { + for (IResource target: relationMap.get(left)) { + String right = getKey(target, resource.getKind()); + if(relationMap.containsKey(right)) { + relationMap.get(right).remove(resource); + } + } + relationMap.remove(left); + } + } + } + cache.remove(getCacheKey(resource)); + }catch(Exception e) { + OpenShiftUIActivator.getDefault().getLogger().logError(e); + } + } + + public synchronized void update(IResource resource) { + try { + Collection deployments = findDeploymentsFor(resource); + if(deployments != null && !deployments.isEmpty()) { + for (Deployment deployment : deployments) { + deployment.update(resource); + } + } + }catch(Exception e) { + OpenShiftUIActivator.getDefault().getLogger().logError(e); + } + } + + private Collection findDeploymentsFor(IResource resource) { + Trace.debug("Looking for deployment associated with: {0}", resource); + //build->dc->rc->pod->d + if(resourceToDeployments.containsKey(resource)) { + return resourceToDeployments.get(resource); + } + String path = null; + switch(resource.getKind()) { + case ResourceKind.BUILD: + path = ResourceKind.DEPLOYMENT_CONFIG; + break; + case ResourceKind.DEPLOYMENT_CONFIG: + path = ResourceKind.REPLICATION_CONTROLLER; + break; + case ResourceKind.REPLICATION_CONTROLLER: + path = ResourceKind.POD; + break; + case ResourceKind.POD: + default: + } + if(path != null) { + String key = getKey(resource, path); + if(relationMap.containsKey(key) && relationMap.get(key) != null) { + Collection deployments = new ArrayList<>(); + for (IResource relation : relationMap.get(key)) { + deployments.addAll(findDeploymentsFor(relation)); + } + return deployments; + } + } + return Collections.emptyList(); + } + +} diff --git a/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/models/IResourceUIModel.java b/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/models/IResourceUIModel.java new file mode 100644 index 0000000000..41eeb37e52 --- /dev/null +++ b/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/models/IResourceUIModel.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2015 Red Hat, Inc. + * Distributed under license by Red Hat, Inc. All rights reserved. + * This program is made available under the terms of the + * Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + ******************************************************************************/ +package org.jboss.tools.openshift.internal.ui.models; + +import com.openshift.restclient.model.IResource; + +/** + * UI Model to wrapper an OpenShift resource + * @author jeff.cantrill + * + */ +public interface IResourceUIModel { + + /** + * Get the underlying resource for this display model. + * This will throw a cast exception if it can not be cast + * @return + */ + T getResource(); +} diff --git a/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/models/OpenShiftResourceUIModel.java b/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/models/OpenShiftResourceUIModel.java new file mode 100644 index 0000000000..e9184accb5 --- /dev/null +++ b/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/models/OpenShiftResourceUIModel.java @@ -0,0 +1,79 @@ +/******************************************************************************* + * Copyright (c) 2015 Red Hat, Inc. + * Distributed under license by Red Hat, Inc. All rights reserved. + * This program is made available under the terms of the + * Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + ******************************************************************************/ +package org.jboss.tools.openshift.internal.ui.models; + +import com.openshift.restclient.OpenShiftException; +import com.openshift.restclient.model.IResource; + +/** + * Display model for OpenShift resources to allow + * overriding equals and hash + * @author jeff.cantrill + * + */ +public class OpenShiftResourceUIModel implements IResourceUIModel{ + + private IResource resource; + + public OpenShiftResourceUIModel(IResource resource){ + if(resource == null) + throw new OpenShiftException("A null resource was passed while trying to create a display model"); + this.resource = resource; + } + + /** + * Get the underlying resource for this display model. + * This will throw a cast exception if it can not be cast + * @return + */ + @SuppressWarnings("unchecked") + @Override + public T getResource() { + return (T) this.resource; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + final String resourceVersion = resource == null ? "" : resource.getResourceVersion(); + result = prime * result + ((resource == null) ? 0 : resource.hashCode()); + result = prime * result + ((resourceVersion == null) ? 0 : resourceVersion.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + OpenShiftResourceUIModel other = (OpenShiftResourceUIModel) obj; + if (resource == null) { + if (other.resource != null) + return false; + } else if (!resource.equals(other.resource)) + return false; + final String resourceVersion = resource.getResourceVersion(); + if (resourceVersion == null) { + if (other.getResource().getResourceVersion() != null) + return false; + } else if (!resourceVersion.equals(other.getResource().getResourceVersion())) + return false; + return true; + } + + + + +} diff --git a/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/property/BuildPropertySource.java b/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/property/BuildPropertySource.java index 89e7c1aa0f..f1d8ea53ee 100644 --- a/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/property/BuildPropertySource.java +++ b/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/property/BuildPropertySource.java @@ -10,8 +10,16 @@ import org.eclipse.ui.views.properties.IPropertyDescriptor; import org.eclipse.ui.views.properties.TextPropertyDescriptor; +import org.jboss.tools.openshift.core.OpenShiftAPIAnnotations; +import org.jboss.tools.openshift.internal.common.ui.utils.DateTimeUtils; import com.openshift.restclient.model.IBuild; +import com.openshift.restclient.model.build.IBuildSource; +import com.openshift.restclient.model.build.IBuildStatus; +import com.openshift.restclient.model.build.IBuildStrategy; +import com.openshift.restclient.model.build.IDockerBuildStrategy; +import com.openshift.restclient.model.build.IGitBuildSource; +import com.openshift.restclient.model.build.ISourceBuildStrategy; public class BuildPropertySource extends ResourcePropertySource { @@ -19,27 +27,91 @@ public BuildPropertySource(IBuild resource) { super(resource); } + @Override - public IPropertyDescriptor[] getResourcePropertyDescriptors() { + public IPropertyDescriptor[] getPropertyDescriptors() { return new IPropertyDescriptor[] { - new TextPropertyDescriptor("podName", "Build Pod"), - new TextPropertyDescriptor("message", "Build Message"), - new TextPropertyDescriptor("status", "Status"), + new TextPropertyDescriptor("status", "Status"), + new TextPropertyDescriptor("started", "Started"), + new TextPropertyDescriptor("duration", "Duration"), + new TextPropertyDescriptor("build.config", "Build Configuration"), + new TextPropertyDescriptor("build.strategy", "Build Strategy"), + new TextPropertyDescriptor("builder.image", "Builder Image"), + new TextPropertyDescriptor("source.type", "Source Type"), + new TextPropertyDescriptor("source.repo", "Source Repo"), + new TextPropertyDescriptor("source.ref", "Source Ref."), + new TextPropertyDescriptor("source.contextDir", "Source Context Dir."), + new TextPropertyDescriptor("output.image", "Output Image"), + new TextPropertyDescriptor("push.secret", "Push Secret") }; } + @Override public Object getPropertyValue(Object id) { - if("status".equals(id)){ - return getResource().getStatus(); + IBuild build = getResource(); + switch((String)id) { + case "status": return build.getStatus(); + case "started": + return DateTimeUtils.formatSince(build .getCreationTimeStamp()); + case "build.config": + return build.getLabels().get(OpenShiftAPIAnnotations.BUILD_CONFIG_NAME); + case "build.strategy" : + case "builder.image" : + return handleBuildStrategy((String)id, build.getBuildStrategy()); + case "source.type" : + case "source.repo" : + case "source.ref" : + case "source.contextDir" : + return handleBuildSource((String) id, build.getBuildSource()); + case "duration": + case "output.image": + return handleBuildStatus((String)id, build.getBuildStatus()); + case "push.secret" : + return build.getPushSecret(); } - if("message".equals(id)){ - return getResource().getMessage(); + return super.getPropertyValue(id); + } + + private Object handleBuildStatus(String id, IBuildStatus status) { + if(status != null) { + switch(id){ + case "output.image": + return status.getOutputDockerImage() != null ? status.getOutputDockerImage().getUriWithoutHost() : ""; + case "duration": + return DateTimeUtils.formatDuration(status.getDuration()); + } } - if("podName".equals(id)){ - return getResource().getPodName(); + return ""; + } + + private Object handleBuildStrategy(String id, IBuildStrategy strategy) { + if(strategy == null) return ""; + switch(id) { + case "build.strategy" : return strategy.getType(); + case "builder.image" : + if(strategy instanceof IDockerBuildStrategy) { + return ((IDockerBuildStrategy) strategy).getBaseImage(); + } + if(strategy instanceof ISourceBuildStrategy) { + return ((ISourceBuildStrategy) strategy).getImage(); + } } - return super.getPropertyValue(id); + return ""; } + private Object handleBuildSource(String id, IBuildSource buildSource) { + if(buildSource == null) return ""; + if("source.type".equals(id)) return buildSource.getType(); + if(buildSource instanceof IGitBuildSource) { + IGitBuildSource source = (IGitBuildSource) buildSource; + switch(id) { + case "source.repo": return source.getURI(); + case "source.ref": return source.getRef(); + case "source.contextDir": return source.getContextDir(); + } + } + return ""; + + } } diff --git a/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/property/DeploymentPropertySource.java b/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/property/DeploymentPropertySource.java new file mode 100644 index 0000000000..97fb02c4ad --- /dev/null +++ b/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/property/DeploymentPropertySource.java @@ -0,0 +1,102 @@ +/******************************************************************************* + * Copyright (c) 2015 Red Hat, Inc. + * Distributed under license by Red Hat, Inc. All rights reserved. + * This program is made available under the terms of the + * Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + ******************************************************************************/ +package org.jboss.tools.openshift.internal.ui.property; + +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.eclipse.osgi.util.NLS; +import org.eclipse.ui.views.properties.IPropertyDescriptor; +import org.eclipse.ui.views.properties.IPropertySource; +import org.eclipse.ui.views.properties.TextPropertyDescriptor; +import org.jboss.tools.openshift.internal.ui.models.Deployment; + +import com.openshift.restclient.model.IPod; +import com.openshift.restclient.model.IServicePort; + +/** + * Property source for Deployments + * + * @author jeff.cantrill + * + */ +public class DeploymentPropertySource implements IPropertySource { + + private Deployment deployment; + + public DeploymentPropertySource(Deployment deployment) { + this.deployment = deployment; + } + + @Override + public Object getEditableValue() { + return null; + } + + @Override + public IPropertyDescriptor[] getPropertyDescriptors() { + return new IPropertyDescriptor[] { + new ExtTextPropertyDescriptor("service.name", "Name", "Service"), + new ExtTextPropertyDescriptor("service.port", "Port Mapping", "Service"), + new ExtTextPropertyDescriptor("service.route", "Route", "Service"), + new ExtTextPropertyDescriptor("deployment.name", "Name", "Deployment"), + new ExtTextPropertyDescriptor("deployment.date", "Date", "Deployment"), + new TextPropertyDescriptor("pods", "Pods") //running, pending, succeeded/ failed/ unknown + }; + } + +// private Collection getPodStatusDescriptors(){ +// Set status = new HashSet<>(); +// for (IPod pod : deployment.getPods()) { +// status.add(new ExtTextPropertyDescriptor("pod", pod.getStatus(), "Pods")); +// } +// return status; +// } + + @Override + public Object getPropertyValue(Object id) { + switch((String)id) { + case "service.name": + return deployment.getService().getName(); + case "service.port": + List ports = deployment.getService().getPorts(); + if(ports.size() > 0) { + IServicePort port = ports.get(0); + return NLS.bind("{0}/{1}->{2}", new Object[] { port.getPort(), port.getProtocol(), port.getTargetPort()}); + } + break; + case "service.route": + case "deployment.name": +// return NLS.bind("", deployment.get) + case "deployment.date": + + case "pods": + return deployment.getPods().size(); + } + return null; + } + + @Override + public boolean isPropertySet(Object id) { + return false; + } + + @Override + public void resetPropertyValue(Object id) { + } + + @Override + public void setPropertyValue(Object id, Object value) { + } + +} diff --git a/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/property/OpenShiftPropertySourceAdapterFactory.java b/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/property/OpenShiftPropertySourceAdapterFactory.java index c59df7434d..ca9133cfa9 100644 --- a/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/property/OpenShiftPropertySourceAdapterFactory.java +++ b/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/property/OpenShiftPropertySourceAdapterFactory.java @@ -13,7 +13,8 @@ import org.eclipse.core.runtime.IAdapterFactory; import org.eclipse.ui.views.properties.IPropertySource; import org.jboss.tools.openshift.core.connection.Connection; -import org.jboss.tools.openshift.internal.ui.explorer.Deployment; +import org.jboss.tools.openshift.internal.ui.models.Deployment; +import org.jboss.tools.openshift.internal.ui.models.IResourceUIModel; import com.openshift.restclient.ResourceKind; import com.openshift.restclient.model.IBuild; @@ -34,8 +35,8 @@ public Object getAdapter(Object adaptableObject, Class adapterType) { if(adaptableObject instanceof Connection){ return new ConnectionPropertySource((Connection) adaptableObject); } - if(adaptableObject instanceof IResource){ - IResource resource = (IResource) adaptableObject; + if(adaptableObject instanceof IResource || adaptableObject instanceof IResourceUIModel){ + IResource resource = adaptableObject instanceof IResourceUIModel ? ((IResourceUIModel) adaptableObject).getResource() :(IResource) adaptableObject; switch(resource.getKind()){ case ResourceKind.BUILD: return new BuildPropertySource((IBuild)resource); diff --git a/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/property/tabbed/BuildsPropertySection.java b/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/property/tabbed/BuildsPropertySection.java new file mode 100644 index 0000000000..7bfe87e303 --- /dev/null +++ b/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/property/tabbed/BuildsPropertySection.java @@ -0,0 +1,169 @@ +/******************************************************************************* + * Copyright (c) 2015 Red Hat, Inc. + * Distributed under license by Red Hat, Inc. All rights reserved. + * This program is made available under the terms of the + * Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + ******************************************************************************/ + +package org.jboss.tools.openshift.internal.ui.property.tabbed; + +import java.text.ParseException; +import org.eclipse.core.databinding.beans.BeanProperties; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.databinding.viewers.ObservableListContentProvider; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerSorter; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.SashForm; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Table; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.views.properties.PropertySheetPage; +import org.eclipse.ui.views.properties.tabbed.AbstractPropertySection; +import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage; +import org.jboss.tools.openshift.core.OpenShiftAPIAnnotations; +import org.jboss.tools.openshift.internal.common.ui.utils.DateTimeUtils; +import org.jboss.tools.openshift.internal.common.ui.utils.TableViewerBuilder; +import org.jboss.tools.openshift.internal.common.ui.utils.TableViewerBuilder.IColumnLabelProvider; +import org.jboss.tools.openshift.internal.common.ui.utils.UIUtils; +import org.jboss.tools.openshift.internal.ui.models.Deployment; +import org.jboss.tools.openshift.internal.ui.models.IResourceUIModel; + +import com.openshift.restclient.model.IBuild; + +public class BuildsPropertySection extends AbstractPropertySection implements OpenShiftAPIAnnotations { + + private static final String CONTEXT_MENU_ID = "popup:org.jboss.tools.openshift.ui.properties.tab.BuildsTab"; + private TableViewer table; + private PropertySheetPage buildDetails; + + @Override + public void createControls(Composite parent, TabbedPropertySheetPage aTabbedPropertySheetPage) { + super.createControls(parent, aTabbedPropertySheetPage); + + SashForm container = new SashForm(parent, SWT.VERTICAL); + Composite tableContainer = new Composite(container, SWT.NONE); + + tableContainer.setLayout(new FillLayout()); + this.table = createTable(tableContainer); + + buildDetails = new PropertySheetPage(); + buildDetails.createControl(container); + aTabbedPropertySheetPage.getSite().setSelectionProvider(new ISelectionProvider() { + + @Override + public void setSelection(ISelection selection) { + } + + @Override + public void removeSelectionChangedListener(ISelectionChangedListener listener) { + } + + @Override + public ISelection getSelection() { + return table.getSelection(); + } + + @Override + public void addSelectionChangedListener(ISelectionChangedListener listener) { + } + }); + } + + protected TableViewer createTable(Composite tableContainer) { + Table table = new Table(tableContainer, SWT.BORDER | SWT.FULL_SELECTION | SWT.V_SCROLL | SWT.H_SCROLL); + table.setLinesVisible(true); + table.setHeaderVisible(true); + TableViewer viewer = new TableViewerBuilder(table, tableContainer) + .contentProvider(new ObservableListContentProvider()) + .sorter(new ViewerSorter() { + + @Override + public int compare(Viewer viewer, Object e1, Object e2) { + IBuild build1 = ((IResourceUIModel)e1).getResource(); + IBuild build2 = ((IResourceUIModel)e2).getResource(); + try { + return -1 * DateTimeUtils.parse(build1.getCreationTimeStamp()) + .compareTo(DateTimeUtils.parse(build2.getCreationTimeStamp())); + } catch (ParseException e) { + } + return 0; + } + + }) + .column(new IColumnLabelProvider() { + @Override + public String getValue(IResourceUIModel model) { + return model.getResource().getName(); + } + }).name("Name").align(SWT.LEFT).weight(1).minWidth(10).buildColumn() + .column(new IColumnLabelProvider() { + @Override + public String getValue(IResourceUIModel model) { + return model.getResource().getAnnotation(BUILD_NUMBER); + } + }).name("Build").align(SWT.LEFT).weight(1).minWidth(5).buildColumn() + .column(new IColumnLabelProvider() { + @Override + public String getValue(IResourceUIModel model) { + return model.getResource().getStatus(); + } + }).name("Status").align(SWT.LEFT).weight(1).minWidth(25).buildColumn() + .column(new IColumnLabelProvider() { + @Override + public String getValue(IResourceUIModel model) { + return DateTimeUtils.formatSince(model.getResource().getCreationTimeStamp()); + } + }).name("Started").align(SWT.LEFT).weight(1).buildColumn() + .buildViewer(); + viewer.addSelectionChangedListener(new ISelectionChangedListener() { + + @Override + public void selectionChanged(SelectionChangedEvent event) { + buildDetails.selectionChanged(null, event.getSelection()); + } + }); + addContextMenu(table); + return viewer; + } + + private void addContextMenu(Table table) { + IMenuManager contextMenu = UIUtils.createContextMenu(table); + UIUtils.registerContributionManager(CONTEXT_MENU_ID, contextMenu, table); + } + + @Override + public void setInput(IWorkbenchPart part, ISelection selection) { + super.setInput(part, selection); + Deployment deployment = UIUtils.getFirstElement(selection, Deployment.class); + if(deployment == null) return; + table.setInput(BeanProperties.list(Deployment.PROP_BUILDS).observe(deployment)); + } + + @Override + public void dispose() { + this.table.getTable().dispose(); + this.buildDetails.dispose(); + } + + @Override + public boolean shouldUseExtraSpace() { + return true; + } + + @Override + public void refresh() { + this.table.refresh(); + this.buildDetails.refresh(); + } +} diff --git a/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/property/tabbed/DeploymentPropertySection.java b/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/property/tabbed/DeploymentPropertySection.java new file mode 100644 index 0000000000..2207c622fe --- /dev/null +++ b/plugins/org.jboss.tools.openshift.ui/src/org/jboss/tools/openshift/internal/ui/property/tabbed/DeploymentPropertySection.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2015 Red Hat, Inc. + * Distributed under license by Red Hat, Inc. All rights reserved. + * This program is made available under the terms of the + * Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + ******************************************************************************/ +package org.jboss.tools.openshift.internal.ui.property.tabbed; + +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.views.properties.tabbed.AbstractPropertySection; +import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage; + +public class DeploymentPropertySection extends AbstractPropertySection { + + private Text createText; + + @Override + public void createControls(Composite parent, TabbedPropertySheetPage aTabbedPropertySheetPage) { + super.createControls(parent, aTabbedPropertySheetPage); + createText = getWidgetFactory().createText(parent, "myValue"); + } + + @Override + public boolean shouldUseExtraSpace() { + return true; + } + + + +} diff --git a/tests/org.jboss.tools.openshift.test/src/org/jboss/tools/openshift/test/common/ui/utils/DateTimeUtilsTest.java b/tests/org.jboss.tools.openshift.test/src/org/jboss/tools/openshift/test/common/ui/utils/DateTimeUtilsTest.java new file mode 100644 index 0000000000..3749183a6e --- /dev/null +++ b/tests/org.jboss.tools.openshift.test/src/org/jboss/tools/openshift/test/common/ui/utils/DateTimeUtilsTest.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2015 Red Hat, Inc. + * Distributed under license by Red Hat, Inc. All rights reserved. + * This program is made available under the terms of the + * Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + ******************************************************************************/ +package org.jboss.tools.openshift.test.common.ui.utils; + +import static org.junit.Assert.*; + +import java.util.TimeZone; + +import static org.jboss.tools.openshift.internal.common.ui.utils.DateTimeUtils.*; + +import org.junit.Test; + +public class DateTimeUtilsTest { + + @Test + public void testFormatDurationLessThanSec() { + long duration = 33000000L; + assertEquals("Now", formatDuration(duration)); + } + + @Test + public void testFormatDurationLessThanHour() { + long duration = 330000000000L; + assertEquals("5 min. 30 sec.", formatDuration(duration)); + } + + @Test + public void testFormatDurationLessThanDay() { + long duration = 33000000000000L; + assertEquals("9 hrs. 10 min.", formatDuration(duration)); + } + + @Test + public void testFormatSince() { + String date = "2015-11-11T20:32:37Z"; + assertEquals("11/11/15 3:32:37 PM EST", formatSince(date, TimeZone.getTimeZone("EST"))); + } + +}