/* * Copyright 2000-2020 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License 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 jetbrains.teamcity.ui.actions; import com.intellij.openapi.util.Pair; import jetbrains.buildServer.AgentPoolData; import jetbrains.buildServer.BuildAgentData; import jetbrains.buildServer.BuildType; import jetbrains.buildServer.ConnectionStatusListener.ErrorProcessingKind; import jetbrains.buildServer.serverProxy.RemoteBuildServerFacade; import jetbrains.teamcity.Activator; import jetbrains.teamcity.Constants; import jetbrains.teamcity.SharedImages; import jetbrains.teamcity.core.Util; import jetbrains.teamcity.core.remote.RemoteRunCustomData; import jetbrains.teamcity.core.remote.RemoteRunPreferencesHelper; import jetbrains.teamcity.ui.views.SimpleRemoteRunCustomizationDialog; import jetbrains.teamcity.ui.views.model.ProjectTreeBuildTypeNode; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Platform; import org.eclipse.jface.action.Action; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.swt.custom.BusyIndicator; import org.eclipse.swt.widgets.Shell; import org.jetbrains.annotations.NotNull; import java.lang.reflect.InvocationTargetException; import java.util.*; import java.util.concurrent.atomic.AtomicReference; public class CustomizeAction extends Action implements ISelectionChangedListener { private final Shell myShell; private final Map myHolder; private BuildType myBuildType; public CustomizeAction(@NotNull final Shell shell, @NotNull final Map holder) { super(Messages.getString("CustomizeAction.name"), //$NON-NLS-1$ SharedImages.getImageDescriptorByPath(SharedImages.REMOTE_RUN_ACTION_CUSTOMIZE)); setEnabled(false); myShell = shell; myHolder = holder; } private static class AgentsLoader implements IRunnableWithProgress, Runnable { private final BuildType myBuildType; private final ArrayList>> myAgents = new ArrayList>>(); public AgentsLoader(final BuildType buildType) { myBuildType = buildType; } public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { myAgents.clear(); myAgents.addAll(getAllAvailableAgents(myBuildType, monitor)); } public void run() { try { run(new NullProgressMonitor()); } catch (InterruptedException ignored) { } catch (InvocationTargetException ignored) { } } public ArrayList>> getAgents() { return myAgents; } @NotNull private static Collection>> getAllAvailableAgents(@NotNull final BuildType buildType, @NotNull final IProgressMonitor monitor) throws InterruptedException { final AtomicReference>>> agents = new AtomicReference>>>(); Activator.getDefault().getSnapshot().getProcessManager().performAction(new Runnable() { public void run() { monitor.beginTask(Messages.getString("CustomizeAction.task_name"), 1); //$NON-NLS-1$ final RemoteBuildServerFacade serverFacade = Activator.getDefault().getSnapshot().getServerFacade(); final List>> list = serverFacade.getGroupedByPoolCanRunAndCompatibleAgents(buildType); agents.set(list); monitor.worked(1); if (monitor.isCanceled()) { // canceled return; } monitor.done(); } }, "Get Available Agents", ErrorProcessingKind.IGNORE); final Collection>> collection = agents.get(); return collection != null ? collection : new ArrayList>>(); } } private class ConfigurationParameterParser { private final Map myConfigurationParameters = new HashMap(); private final Map mySystemProperties = new HashMap(); private final Map myEnvironmentVariables = new HashMap(); ConfigurationParameterParser(final @NotNull Map rawParams) { for (Map.Entry param : rawParams.entrySet()) { if (param.getKey().toLowerCase().startsWith(Constants.BuildParameters.SYS_PROP_PREFIX)) { mySystemProperties.put(param.getKey().substring(Constants.BuildParameters.SYS_PROP_PREFIX.length(), param.getKey().length()), param.getValue()); } else if (param.getKey().toLowerCase().startsWith(Constants.BuildParameters.ENV_VAR_PREFIX)) { myEnvironmentVariables.put(param.getKey().substring(Constants.BuildParameters.ENV_VAR_PREFIX.length(), param.getKey().length()), param.getValue()); } else { myConfigurationParameters.put(param.getKey(), param.getValue()); } } } private Map getConfigurationParameters() { return myConfigurationParameters; } private Map getSystemProperties() { return mySystemProperties; } private Map getEnvironmentVariables() { return myEnvironmentVariables; } } @Override public void run() { try { final BuildType configuration = getConfiguration(); final String customizeFor = configuration.getBuildTypeId(); // load all available agents for the Configuration final AgentsLoader agentsLoader = new AgentsLoader(configuration); BusyIndicator.showWhile(myShell.getDisplay(), agentsLoader); // show Customization dlg final Map runtimeParams = getBuildParameters(configuration); final ConfigurationParameterParser cpParser = new ConfigurationParameterParser(runtimeParams); // // final Map rawProps = runtimeParams; // final Map defaultProps = unwrap(rawProps, Constants.BuildParameters.SYS_PROP_PREFIX); // final Map rawEnv = runtimeParams; // final Map defaultEnvs = unwrap(rawEnv, Constants.BuildParameters.ENV_VAR_PREFIX); // @SuppressWarnings("unchecked") // final Map defaultConfigParams = diff(runtimeParams, defaultProps, defaultEnvs); final SimpleRemoteRunCustomizationDialog dlg = new SimpleRemoteRunCustomizationDialog(myShell, myBuildType, Collections.emptyList(), agentsLoader.getAgents(), myHolder.get(customizeFor), cpParser.getConfigurationParameters(), cpParser.getSystemProperties(), cpParser.getEnvironmentVariables()); // new CustomizationDialog(myShell, myBuildType, // agentsLoader.getAgents(), myHolder.get(customizeFor)).open(); if (Dialog.OK == dlg.open()) { final RemoteRunCustomData newCustomData = dlg.getCustomData(); // replace with new one if (newCustomData != null) { myHolder.put(customizeFor, newCustomData); } else { myHolder.remove(customizeFor); } // notify (decorators?) Activator.broadcastPropertyChange(new PropertyChangeEvent(this, Constants.Notification.REMOTE_RUN_CUSTOM_DATA_CHANGED, null, myHolder)); notifyResult(true); new RemoteRunPreferencesHelper(Platform.getPreferencesService()).save(myHolder); } } catch (Exception e) { Activator.getDefault().getLog().log(Util.createStatus(e)); } } private Map getBuildParameters(final BuildType configuration) { final Map out = new HashMap(); Activator.getDefault().getSnapshot().getProcessManager().performAction(new Runnable() { public void run() { out.putAll(configuration.getParameters()); } }, "Get Build Parameters", ErrorProcessingKind.IGNORE); return out; } // private Map diff(final @NotNull Map all, final Map... parts) { // final HashMap diff = new HashMap(); // all: for (final Map.Entry element : all.entrySet()) { // for (Map part : parts) { // if (part.containsKey(element.getKey())) { // continue all; // } // } // diff.put(element.getKey(), element.getValue()); // } // return diff; // } // // private Map unwrap(Map runtimeParams, String prefix) { // final HashMap out = new HashMap(); // for (Map.Entry entry : runtimeParams.entrySet()) { // if (entry.getKey().toLowerCase().startsWith(prefix)) { // out.put(entry.getKey().substring(prefix.length(), entry.getKey().length()), entry.getValue()); // } // } // return out; // } public BuildType getConfiguration() { return myBuildType; } public void selectionChanged(final SelectionChangedEvent event) { setEnabled(false); myBuildType = null; IStructuredSelection selection = (IStructuredSelection) event.getSelection(); if (selection.size() == 1 && selection.getFirstElement() instanceof ProjectTreeBuildTypeNode) { myBuildType = ((ProjectTreeBuildTypeNode) selection.getFirstElement()).getBuildType(); } setEnabled(myBuildType != null); } }