/*******************************************************************************
* Copyright (c) 2015, 2016 Pivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are 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:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.boot.dash.cloudfoundry.client.v1;
import static org.springframework.ide.eclipse.boot.dash.cloudfoundry.client.v1.CFWrapping.wrapBuildpacks;
import static org.springframework.ide.eclipse.boot.dash.cloudfoundry.client.v1.CFWrapping.wrapDomains;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.UUID;
import java.util.zip.ZipFile;
import org.cloudfoundry.client.lib.ApplicationLogListener;
import org.cloudfoundry.client.lib.CloudCredentials;
import org.cloudfoundry.client.lib.CloudFoundryClient;
import org.cloudfoundry.client.lib.CloudFoundryOperations;
import org.cloudfoundry.client.lib.HttpProxyConfiguration;
import org.cloudfoundry.client.lib.StreamingLogToken;
import org.cloudfoundry.client.lib.domain.CloudInfo;
import org.cloudfoundry.client.lib.domain.Staging;
import org.eclipse.core.runtime.Assert;
import org.osgi.framework.Version;
import org.springframework.ide.eclipse.boot.dash.BootDashActivator;
import org.springframework.ide.eclipse.boot.dash.cloudfoundry.MissingPasswordException;
import org.springframework.ide.eclipse.boot.dash.cloudfoundry.client.CFBuildpack;
import org.springframework.ide.eclipse.boot.dash.cloudfoundry.client.CFClientParams;
import org.springframework.ide.eclipse.boot.dash.cloudfoundry.client.CFCloudDomain;
import org.springframework.ide.eclipse.boot.dash.cloudfoundry.client.CFCredentials;
import org.springframework.ide.eclipse.boot.dash.cloudfoundry.client.CFCredentials.CFCredentialType;
import org.springframework.ide.eclipse.boot.dash.cloudfoundry.client.CFSpace;
import org.springframework.ide.eclipse.boot.dash.cloudfoundry.client.CFStack;
import org.springframework.ide.eclipse.boot.dash.cloudfoundry.client.v2.CFPushArguments;
import org.springframework.ide.eclipse.boot.dash.cloudfoundry.deployment.CloudApplicationDeploymentProperties;
import org.springsource.ide.eclipse.commons.cloudfoundry.client.RefreshTokenUtil;
import org.springsource.ide.eclipse.commons.cloudfoundry.client.diego.BuildpackSupport;
import org.springsource.ide.eclipse.commons.cloudfoundry.client.diego.CloudInfoV2;
import org.springsource.ide.eclipse.commons.cloudfoundry.client.diego.HealthCheckSupport;
import org.springsource.ide.eclipse.commons.cloudfoundry.client.diego.SshClientSupport;
import org.springsource.ide.eclipse.commons.cloudfoundry.client.diego.SshClientSupportV1;
@Deprecated
public class DefaultClientRequestsV1 {
/*
* System property. Set to "true" if connection pool is to be used. "false"
* otherwise or omit as a system property
*/
public static final String BOOT_DASH_CONNECTION_POOL = "sts.boot.dash.connection.pool";
private static final boolean DEBUG = false; //(""+Platform.getLocation()).contains("kdvolder");
private static void debug(String string) {
if (DEBUG) {
System.out.println(string);
}
}
protected final CloudFoundryOperations client;
private CloudInfoV2 cachedCloudInfo;
private CFClientParams clientParams;
private int tokens;
public DefaultClientRequestsV1(CFClientParams params) throws Exception {
this.client = createClient(params);
this.clientParams = params;
}
private static CloudFoundryOperations createClient(CFClientParams params) throws Exception {
CloudCredentials credentials = getCloudCredentials(params);
return getOperations(
credentials,
new URL(params.getApiUrl()),
params.getOrgName(),
params.getSpaceName(),
params.isSelfsigned() || params.skipSslValidation()
);
}
private static CloudCredentials getCloudCredentials(CFClientParams params) {
CFCredentials creds = params.getCredentials();
Assert.isLegal(creds.getType()==CFCredentialType.REFRESH_TOKEN, "V1 client should only be created with refresh token auth");
return refreshTokenCredentials(creds.getSecret());
}
private static CloudCredentials refreshTokenCredentials(String refreshToken) {
return RefreshTokenUtil.credentialsFromRefreshToken(refreshToken);
}
private static CloudFoundryOperations getOperations(
CloudCredentials credentials,
URL apiUrl, String orgName, String spaceName,
boolean isSelfsigned
) throws Exception {
checkCredentials(credentials);
Properties properties = System.getProperties();
// By default disable connection pool (i.e. flag is set to true) unless
// a property exists that sets
// USING connection pool to "true" (so, i.e., disable connection pool is
// false)
boolean disableConnectionPool = properties == null || !properties.containsKey(BOOT_DASH_CONNECTION_POOL)
|| !"true".equals(properties.getProperty(BOOT_DASH_CONNECTION_POOL));
return spaceName != null
? new CloudFoundryClient(credentials, apiUrl, orgName, spaceName, isSelfsigned, disableConnectionPool)
: new CloudFoundryClient(credentials, apiUrl, isSelfsigned, disableConnectionPool);
}
private static void checkCredentials(CloudCredentials credentials) throws MissingPasswordException {
String id = credentials.getEmail();
String password = credentials.getPassword();
Object token = credentials.getToken();
if (password == null && token==null) {
throw new MissingPasswordException("No password or token stored or set for: " + id
+ ". Please ensure that the password is set in the run target and it is up-to-date.");
}
}
public void logout() {
client.logout();
}
public void createApplication(final CFPushArguments params) throws Exception {
new BasicRequest(this.client, params.getAppName(), "Creating application") {
@Override
protected void runRequest(CloudFoundryOperations client) throws Exception {
client.createApplication(params.getAppName(),
new Staging(params.getCommand(), params.getBuildpack(),
params.getStack(), params.getTimeout()),
params.getDiskQuota(),
params.getMemory(),
params.getRoutes(),
params.getServices()
);
}
}.call();
}
public void createApplication(final CloudApplicationDeploymentProperties deploymentProperties) throws Exception {
new BasicRequest(this.client, deploymentProperties.getAppName(), "Creating application") {
@Override
protected void runRequest(CloudFoundryOperations client) throws Exception {
client.createApplication(deploymentProperties.getAppName(),
new Staging(deploymentProperties.getCommand(), deploymentProperties.getBuildpack(),
deploymentProperties.getStack(), deploymentProperties.getTimeout()),
deploymentProperties.getDiskQuota(),
deploymentProperties.getMemory(),
new ArrayList<>(deploymentProperties.getUris()),
deploymentProperties.getServices()
);
}
}.call();
}
protected HttpProxyConfiguration getProxyConf() {
return clientParams.getProxyConf();
}
private CloudInfoV2 getCloudInfoV2() throws Exception {
//cached cloudInfo as it doesn't really change and is more like a bunch of static info about how a target is configured.
if (this.cachedCloudInfo==null) {
CloudCredentials creds = getCloudCredentials(clientParams);
HttpProxyConfiguration proxyConf = getProxyConf();
this.cachedCloudInfo = new CloudInfoV2(creds, client.getCloudControllerUrl(), proxyConf, clientParams.isSelfsigned());
}
return this.cachedCloudInfo;
}
public void updateApplicationDiskQuota(final String appName, final int diskQuota) throws Exception {
new BasicRequest(this.client, appName, "Updating application disk quota") {
@Override
protected void runRequest(CloudFoundryOperations client) throws Exception {
client.updateApplicationDiskQuota(appName, diskQuota);
}
}.call();
}
// public CFApplicationDetail getApplication(final String appName) throws Exception {
//
// return new ApplicationRequest<CFApplicationDetail>(this.client, appName) {
// @Override
// protected CFApplicationDetail doRun(CloudFoundryOperations client) throws Exception {
// try {
// return CFWrapping.wrapDetails(client.getApplication(appName));
// } catch (Exception e) {
// if (CloudErrors.is503Error(e)) {
// // Alternate way to fetch applications that does not
// // fetch instances and
// // may not throw 503 due to fetching stats on app
// // instances if app is not running
// List<CloudApplication> apps =client.getApplicationsWithBasicInfo();
// if (apps != null) {
// for (CloudApplication app : apps) {
// if (app.getName().equals(appName)) {
// return CFWrapping.wrapDetails(app);
// }
// }
// }
// return null;
// } else {
// throw e;
// }
// }
// }
// }.call();
// }
// public CFApplication getApplication(final UUID appUUID) throws Exception {
// return new ApplicationRequest<CFApplication>(this.client, appUUID.toString()) {
// @Override
// protected CFApplication doRun(CloudFoundryOperations client) throws Exception {
// try {
// return wrap(client.getApplication(appUUID));
// } catch (Exception e) {
// if (CloudErrors.is503Error(e)) {
// // Alternate way to fetch applications that does not
// // fetch instances and
// // may not throw 503 due to fetching stats on app
// // instances if app is not running
// List<CloudApplication> apps = client.getApplicationsWithBasicInfo();
// if (apps != null) {
// for (CloudApplication app : apps) {
// if (app.getMeta().getGuid().equals(appUUID)) {
// return wrap(app);
// }
// }
// }
// return null;
// } else {
// throw e;
// }
// }
// }
// }.call();
// }
// public CFApplicationStats getApplicationStats(final String appName) throws Exception {
// return CFWrapping.wrap(new ApplicationInstanceRequest(this.client, appName).call());
// }
//
// public List<CFApplicationDetail> waitForApplicationDetails(final List<CFApplication> appsToLookUp,
// final long timeout) throws Exception {
//
// Callable<List<CloudAppInstances>> task = new AllApplicationInstancesRequest(this.client,
// appsToLookUp);
// return RetryUtil.retry(2000, timeout, task);
// }
// public List<CFApplication> getApplicationsWithBasicInfo() throws Exception {
// return new ClientRequest<List<CFApplication>>(this.client, "Getting all Cloud applications") {
// @Override
// protected List<CFApplication> doRun(CloudFoundryOperations client) throws Exception {
// return wrapApps(client.getApplicationsWithBasicInfo());
// }
// }.call();
// }
public void uploadApplication(final String appName, final ZipFile archive) throws Exception {
new BasicRequest(this.client, appName, "Uploading application archive") {
@Override
protected void runRequest(CloudFoundryOperations client) throws Exception {
client.uploadApplication(appName, new CloudZipApplicationArchive(archive));
}
}.call();
}
public void stopApplication(final String appName) throws Exception {
new ApplicationRequest<Void>(this.client, appName) {
@Override
protected Void doRun(CloudFoundryOperations client) throws Exception {
client.stopApplication(appName);
return null;
}
}.call();
}
public void restartApplication(final String appName) throws Exception {
new BasicRequest(this.client, appName, "Restarting application") {
@Override
protected void runRequest(CloudFoundryOperations client) throws Exception {
client.restartApplication(appName);
}
}.call();
}
public void updateApplicationEnvironment(final String appName, final Map<String, String> varsToUpdate)
throws Exception {
new BasicRequest(this.client, appName, "Updating application environment variables") {
@Override
protected void runRequest(CloudFoundryOperations client) throws Exception {
client.updateApplicationEnv(appName, varsToUpdate);
}
}.call();
}
public void updateApplicationStaging(final String appName, final Staging staging) throws Exception {
new BasicRequest(this.client, appName, "Updating application buildpack") {
@Override
protected void runRequest(CloudFoundryOperations client) throws Exception {
client.updateApplicationStaging(appName, staging);
}
}.call();
}
public void updateApplicationServices(final String appName, final List<String> services) throws Exception {
new BasicRequest(this.client, appName, "Updating application service bindings") {
@Override
protected void runRequest(CloudFoundryOperations client) throws Exception {
client.updateApplicationServices(appName, services);
}
}.call();
}
public void updateApplicationMemory(final String appName, final int memory) throws Exception {
new BasicRequest(this.client, appName, "Updating application memory") {
@Override
protected void runRequest(CloudFoundryOperations client) throws Exception {
client.updateApplicationMemory(appName, memory);
}
}.call();
}
public void updateApplicationInstances(final String appName, final int instances) throws Exception {
new BasicRequest(this.client, appName, "Updating application instances") {
@Override
protected void runRequest(CloudFoundryOperations client) throws Exception {
client.updateApplicationInstances(appName, instances);
}
}.call();
}
public void updateApplicationUris(final String appName, final List<String> urls) throws Exception {
new BasicRequest(this.client, appName, "Updating application URLs") {
@Override
protected void runRequest(CloudFoundryOperations client) throws Exception {
client.updateApplicationUris(appName, urls);
}
}.call();
}
public void deleteApplication(final String appName) throws Exception {
new BasicRequest(this.client, appName, "Deleting application") {
@Override
protected void runRequest(CloudFoundryOperations client) throws Exception {
client.deleteApplication(appName);
}
}.call();
}
public List<CFCloudDomain> getDomains() throws Exception {
return new ClientRequest<List<CFCloudDomain>>(this.client, "Getting Cloud domains") {
@Override
protected List<CFCloudDomain> doRun(CloudFoundryOperations client) throws Exception {
return wrapDomains(client.getDomains());
}
}.call();
}
public List<CFStack> getStacks() throws Exception {
return new ClientRequest<List<CFStack>>(this.client, "Getting Cloud Stacks") {
@Override
protected List<CFStack> doRun(CloudFoundryOperations client) throws Exception {
return CFWrapping.wrapStacks(client.getStacks());
}
}.call();
}
public List<CFSpace> getSpaces() throws Exception {
return new ClientRequest<List<CFSpace>>(this.client, "Getting Cloud spaces") {
@Override
protected List<CFSpace> doRun(CloudFoundryOperations client) throws Exception {
return CFWrapping.wrapSpaces(client.getSpaces());
}
}.call();
}
// /**
// * A more efficient API that fetches instances based on app {@link UUID}
// *
// * @param guid
// * @return app instances for the specified app guid, or null if the app does
// * not exist
// * @throws Exception
// */
// public CloudAppInstances getExistingAppInstances(final UUID guid) throws Exception {
// return new ClientRequest<CloudAppInstances>(this.client, "Getting application instances") {
// @Override
// protected CloudAppInstances doRun(CloudFoundryOperations client) throws Exception {
// CFApplication app = getApplication(guid);
// if (app != null) {
// CFApplicationStats stats = getApplicationStats(app.getName());
// return new CloudAppInstances(app, stats);
// }
// return null;
// }
// }.call();
// }
//
// public CloudAppInstances getExistingAppInstances(final String appName) throws Exception {
// return new ClientRequest<CloudAppInstances>(this.client, appName, "Getting application instances", null) {
// @Override
// protected CloudAppInstances doRun(CloudFoundryOperations client) throws Exception {
// CFApplication app = getApplication(appName);
// if (app != null) {
// CFApplicationStats stats = getApplicationStats(appName);
// return new CloudAppInstances(app, stats);
// }
// return null;
//
// }
// }.call();
// }
public Version getApiVersion() {
CloudInfo info = client.getCloudInfo();
if (info!=null) {
String versionString = info.getApiVersion();
if (versionString!=null) {
return new Version(versionString);
}
}
return null;
}
public HealthCheckSupport getHealthCheckSupport() throws Exception {
return new HealthCheckSupport(client, getCloudInfoV2(), clientParams.isSelfsigned(), getProxyConf());
}
public SshClientSupport getSshClientSupport() throws Exception {
HttpProxyConfiguration proxyConf = getProxyConf();
return new SshClientSupportV1(client, getCloudInfoV2(), clientParams.isSelfsigned(), proxyConf);
}
private BuildpackSupport getBuildpackSupport() throws Exception {
CloudCredentials creds = getCloudCredentials(clientParams);
HttpProxyConfiguration proxyConf = getProxyConf();
return BuildpackSupport.create(client, creds, proxyConf,
clientParams.isSelfsigned());
}
public StreamingLogToken streamLogs(String appName, ApplicationLogListener logConsole) {
debug("streamLogs "+appName);
StreamingLogToken orgToken = client.streamLogs(appName, logConsole);
debug("streamLogs "+appName+" got token : "+ orgToken);
tokenCreated();
StreamingLogToken token;
if (DEBUG) {
token = new StreamingLogToken() {
@Override
public void cancel() {
tokenDisposed();
debug("streamLogs "+appName+" canceled token : "+orgToken);
orgToken.cancel();
}
};
} else {
token = orgToken;
}
return token;
}
synchronized void tokenCreated() {
if (DEBUG) {
tokens++;
debug("Active Log Token Count = "+tokens);
}
}
synchronized void tokenDisposed() {
if (DEBUG) {
tokens--;
debug("Active Log Token Count = "+tokens);
}
}
public List<CFBuildpack> getBuildpacks() throws Exception {
return wrapBuildpacks(getBuildpackSupport().getBuildpacks());
}
public String getHealthCheck(UUID appGuid) {
try {
return getHealthCheckSupport().getHealthCheck(appGuid);
} catch (Exception e) {
BootDashActivator.log(e);
}
return null;
}
public void setHealthCheck(UUID guid, String hcType) {
try {
getHealthCheckSupport().setHealthCheck(guid, hcType);
} catch (Exception e) {
BootDashActivator.log(e);
}
}
}