/*******************************************************************************
* Copyright (c) 2016 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.wizard.newapp.fromimage;
import java.beans.PropertyChangeEvent;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.commons.lang.StringUtils;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.wizard.IWizardContainer;
import org.eclipse.osgi.util.NLS;
import org.jboss.tools.common.ui.WizardUtils;
import org.jboss.tools.openshift.core.connection.Connection;
import org.jboss.tools.openshift.core.connection.ConnectionsRegistryUtil;
import org.jboss.tools.openshift.egit.core.EGitUtils;
import org.jboss.tools.openshift.internal.core.IDockerImageMetadata;
import org.jboss.tools.openshift.internal.core.ImageStreamTagMetaData;
import org.jboss.tools.openshift.internal.ui.OpenShiftUIActivator;
import org.jboss.tools.openshift.internal.ui.job.CreateApplicationFromImageJob;
import org.jboss.tools.openshift.internal.ui.job.IResourcesModelJob;
import org.jboss.tools.openshift.internal.ui.wizard.common.EnvironmentVariablesPageModel;
import org.jboss.tools.openshift.internal.ui.wizard.common.IEnvironmentVariablesPageModel;
import org.jboss.tools.openshift.internal.ui.wizard.common.IResourceLabelsPageModel;
import org.jboss.tools.openshift.internal.ui.wizard.deployimage.DeployImageWizardModel;
import org.jboss.tools.openshift.internal.ui.wizard.newapp.IApplicationSource;
import org.jboss.tools.openshift.internal.ui.wizard.newapp.IApplicationSourceListPageModel;
import org.jboss.tools.openshift.internal.ui.wizard.newapp.IApplicationSourceModel;
import com.openshift.restclient.ResourceKind;
import com.openshift.restclient.model.IProject;
import com.openshift.restclient.model.IResource;
/**
* A Model to handle creating a microservice application
* based on an image
*
* @author jeff.cantrill
*
*/
public class ApplicationSourceFromImageModel
extends DeployImageWizardModel
implements IApplicationSourceModel, IBuildConfigPageModel {
private static final String ANNOTATION_SAMPLE_CONTEXT_DIR = "sampleContextDir";
private static final String ANNOTATION_SAMPLE_REPO = "sampleRepo";
private static final String ANNOTATION_SAMPLE_REF = "sampleRef";
private static final String DEFAULT_REFERENCE = "master";
private ImageStreamApplicationSource source;
private IWizardContainer container;
private IEnvironmentVariablesPageModel envModel = new EnvironmentVariablesPageModel();
private String gitRepositoryUrl = "";
private String gitReference = DEFAULT_REFERENCE;
private String contextDir = "";
private boolean imageChangeTrigger = true;
private boolean configChangeTrigger = true;
private boolean configWebHook = true;
private AtomicBoolean staleRepoInfo = new AtomicBoolean(true);
@Override
public IResourcesModelJob createFinishJob() {
return new CreateApplicationFromImageJob(this, this);
}
@SuppressWarnings("unchecked")
@Override
public void propertyChange(PropertyChangeEvent evt) {
if(evt == null) return;
super.propertyChange(evt);
switch(evt.getPropertyName()) {
case IResourceLabelsPageModel.PROPERTY_LABELS:
setLabels((List<Label>) evt.getNewValue());
break;
case IApplicationSourceListPageModel.PROPERTY_SELECTED_APP_SOURCE:
handleSelectedAppSource(evt);
break;
case IApplicationSourceListPageModel.PROPERTY_PROJECT:
setProject((IProject) evt.getNewValue());
break;
case IApplicationSourceListPageModel.PROPERTY_ECLIPSE_PROJECT:
handleEclipseProject(evt);
break;
}
}
private void handleEclipseProject(PropertyChangeEvent evt) {
org.eclipse.core.resources.IProject project = (org.eclipse.core.resources.IProject) evt.getNewValue();
if(project != null) {
try {
setGitRepositoryUrl(EGitUtils.getDefaultRemoteRepo(project));
setGitReference(EGitUtils.getCurrentBranch(project));
setContextDir(StringUtils.EMPTY);
return;
} catch (CoreException e) {
OpenShiftUIActivator.getDefault().getLogger().logWarning("Unable to retrieve the remote git repo from " + project.getName(), e);
}
}
setGitRepositoryUrl(null);
setGitReference(null);
setContextDir(null);
}
private void handleSelectedAppSource(PropertyChangeEvent evt) {
if(evt.getNewValue() instanceof ImageStreamApplicationSource
&& ResourceKind.IMAGE_STREAM.equals(((IApplicationSource) evt.getNewValue()).getKind())) {
this.source = (ImageStreamApplicationSource) evt.getNewValue();
staleRepoInfo.set(true);
setGitRepositoryUrl(null);
setResourceName(null);
}
}
@Override
public void init() {
if(staleRepoInfo.compareAndSet(true, false)) {
loadBuilderImageMetadata();
if ((this.source != null) && (this.getGitRepositoryUrl() == null)) {
setGitRepositoryUrl(this.source.getAnnotation(ANNOTATION_SAMPLE_REPO));
setContextDir(this.source.getAnnotation(ANNOTATION_SAMPLE_CONTEXT_DIR));
setGitReference(this.source.getAnnotation(ANNOTATION_SAMPLE_REF));
}
}
}
private void loadBuilderImageMetadata() {
if(source != null && container != null) {
setImageName(NLS.bind("{0}/{1}", source.getNamespace(), source.getName()));
Job loadImageJob = new Job("Load builder image metadata...") {
@Override
protected IStatus run(IProgressMonitor monitor) {
if(initializeContainerInfo()) {
return Status.OK_STATUS;
}
return Status.CANCEL_STATUS;
}
};
try {
final IStatus status = WizardUtils.runInWizard(loadImageJob, container);
if (!status.isOK()) {
MessageDialog.openWarning(container.getShell(), "Warning",
NLS.bind("No builder image metadata for {0} could be found.", getImageName()));
}
} catch (InvocationTargetException | InterruptedException e) {
final String message = NLS.bind("Failed to look-up metadata for a builder image {0}", getImageName());
MessageDialog.openError(container.getShell(), "Error", message);
OpenShiftUIActivator.getDefault().getLogger().logError(message, e);
}
}
}
@Override
protected IDockerImageMetadata lookupImageMetadata() {
if (source == null) {
return null;
}
try {
Connection conn = ConnectionsRegistryUtil.getConnectionFor(getProject());
IResource istag = conn.getResource(ResourceKind.IMAGE_STREAM_TAG, source.getNamespace(), source.getName());
return new ImageStreamTagMetaData(istag.toJson(true));
}catch(Exception e) {
OpenShiftUIActivator.getDefault().getLogger().logError(NLS.bind("Unable to retrieve imagestream tag for {0}", getImageName()), e);
}
return null;
}
@Override
public String getBuilderImageName() {
return source.getName();
}
@Override
public String getBuilderImageNamespace() {
return source.getNamespace();
}
public void setContainer(IWizardContainer container) {
this.container = container;
}
@Override
public IEnvironmentVariablesPageModel getEnvVariablesModel() {
return envModel;
}
@Override
public void setConfigWebHook(boolean value) {
firePropertyChange(PROPERTY_CONFIG_WEB_HOOK, configWebHook, this.configWebHook = value);
}
@Override
public boolean isConfigWebHook() {
return this.configWebHook;
}
@Override
public void setConfigChangeTrigger(boolean value) {
firePropertyChange(PROPERTY_CONFIG_CHANGE_TRIGGER, configChangeTrigger, this.configChangeTrigger = value);
}
@Override
public boolean isConfigChangeTrigger() {
return configChangeTrigger;
}
@Override
public void setImageChangeTrigger(boolean value) {
firePropertyChange(PROPERTY_IMAGE_CHANGE_TRIGGER, imageChangeTrigger, this.imageChangeTrigger = value);
}
@Override
public boolean isImageChangeTrigger() {
return imageChangeTrigger;
}
@Override
public String getGitRepositoryUrl() {
return this.gitRepositoryUrl;
}
@Override
public void setGitRepositoryUrl(String url) {
firePropertyChange(PROPERTY_GIT_REPOSITORY_URL, this.gitRepositoryUrl, this.gitRepositoryUrl = url);
}
@Override
public String getGitReference() {
return this.gitReference;
}
@Override
public void setGitReference(String ref) {
firePropertyChange(PROPERTY_GIT_REFERENCE, this.gitReference, this.gitReference = ref);
}
@Override
public String getContextDir() {
return this.contextDir;
}
@Override
public void setContextDir(String contextDir) {
firePropertyChange(PROPERTY_CONTEXT_DIR, this.contextDir, this.contextDir = contextDir);
}
@Override
public void dispose() {
super.dispose();
source = null;
container = null;
((EnvironmentVariablesPageModel)envModel).dispose();
}
}