All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.predic8.membrane.core.interceptor.apimanagement.apiconfig.EtcdRegistryApiConfig Maven / Gradle / Ivy
/*
* Copyright 2015 predic8 GmbH, www.predic8.com
* 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 com.predic8.membrane.core.interceptor.apimanagement.apiconfig;
import com.predic8.membrane.annot.MCAttribute;
import com.predic8.membrane.annot.MCElement;
import com.predic8.membrane.core.Router;
import com.predic8.membrane.core.cloud.ExponentialBackoff;
import com.predic8.membrane.core.cloud.etcd.EtcdNodeInformation;
import com.predic8.membrane.core.cloud.etcd.EtcdRequest;
import com.predic8.membrane.core.cloud.etcd.EtcdResponse;
import com.predic8.membrane.core.config.spring.BaseLocationApplicationContext;
import com.predic8.membrane.core.interceptor.Interceptor;
import com.predic8.membrane.core.interceptor.administration.AdminConsoleInterceptor;
import com.predic8.membrane.core.interceptor.apimanagement.ApiManagementConfiguration;
import com.predic8.membrane.core.rules.AbstractServiceProxy;
import com.predic8.membrane.core.rules.Rule;
import com.predic8.membrane.core.rules.ServiceProxy;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.Lifecycle;
import java.io.IOException;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.UnknownHostException;
@MCElement(name="etcdRegistryApiConfig")
public class EtcdRegistryApiConfig implements Lifecycle, ApplicationContextAware, ApiConfig, DisposableBean {
private static final Logger log = LoggerFactory.getLogger(EtcdRegistryApiConfig.class.getName());
private ApplicationContext context;
private ApiManagementConfiguration amc;
private String url;
private String membraneId;
private String baseKeyPrefix = "/membrane/";
private int ttl = 300;
private int retryDelayMin = 10 * 1000;
private int retryDelayMax = 10 * 60 * 1000;
private double expDelayFactor = 2.0d;
Thread publisher = new Thread(new Runnable() {
int sleepTime = (ttl - 10) * 1000;
@Override
public void run() {
try {
boolean connectionLost = false;
while (true) {
String baseKey = baseKeyPrefix+membraneId;
EtcdResponse respTTLDirRefresh = EtcdRequest.create(url, baseKey, "")
.refreshTTL(ttl).sendRequest();
if (!respTTLDirRefresh.is2XX()) {
log.warn("Could not contact etcd at " + url);
connectionLost = true;
}
Thread.sleep(sleepTime);
if (connectionLost) {
log.warn("Connection lost to etcd");
ExponentialBackoff.retryAfter(retryDelayMin, retryDelayMax, expDelayFactor,
"Republish from thread after failed ttl refresh", jobPublisher);
}
}
} catch (InterruptedException ignored) {
}
}
});
ExponentialBackoff.Job jobPublisher = () -> publishToEtcd();
private boolean publishToEtcd() {
String baseKey = baseKeyPrefix+membraneId;
EtcdResponse respPublishApiUrl = EtcdRequest.create(url,baseKey,"/apiconfig").setValue("url","").sendRequest();
if(!respPublishApiUrl.is2XX()){
System.out.println(respPublishApiUrl.getBody());
return false;
}
EtcdResponse respPublishApiFingerprint = EtcdRequest.create(url,baseKey,"/apiconfig").setValue("fingerprint","").sendRequest();
if(!respPublishApiFingerprint.is2XX()){
System.out.println(respPublishApiFingerprint.getBody());
return false;
}
EtcdNodeInformation adminConsole = findAdminConsole();
EtcdResponse respPublishEndpointName = EtcdRequest.create(url,baseKey,"/endpoint").setValue("name",adminConsole.getName()).sendRequest();
if(!respPublishEndpointName.is2XX()){
System.out.println(respPublishEndpointName.getBody());
return false;
}
EtcdResponse respPublishEndpointHost = EtcdRequest.create(url,baseKey,"/endpoint").setValue("host",adminConsole.getTargetHost()).sendRequest();
if(!respPublishEndpointHost.is2XX()){
System.out.println(respPublishEndpointHost.getBody());
return false;
}
EtcdResponse respPublishEndpointPort = EtcdRequest.create(url,baseKey,"/endpoint").setValue("port",adminConsole.getTargetPort()).sendRequest();
if(!respPublishEndpointPort.is2XX()){
System.out.println(respPublishEndpointPort.getBody());
return false;
}
return true;
}
private EtcdNodeInformation findAdminConsole() {
Object routerObj = context.getBean(Router.class);
if(routerObj == null)
throw new RuntimeException("Router not found, cannot publish admin console");
Router router = (Router) routerObj;
for (Rule r : router.getRuleManager().getRules()) {
if (!(r instanceof AbstractServiceProxy)) continue;
for (Interceptor i : r.getInterceptors()) {
if (i instanceof AdminConsoleInterceptor) {
String name = r.getName();
String host = ((ServiceProxy) r).getExternalHostname();
if(host == null)
host = getLocalHostname();
String port = Integer.toString(((AbstractServiceProxy) r).getPort());
EtcdNodeInformation node = new EtcdNodeInformation(null,null,host,port,name);
return node;
}
}
}
throw new RuntimeException("Admin console not found but is needed. Add a service proxy with an admin console.");
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = applicationContext;
}
@Override
public void start() {
Object routerObj = context.getBean(Router.class);
if(routerObj == null)
throw new RuntimeException("Router cannot be found");
Router router = (Router) routerObj;
membraneId = router.getId();
try {
log.info("Started membrane publishing");
ExponentialBackoff.retryAfter(retryDelayMin, retryDelayMax, expDelayFactor,
"First publish from thread", jobPublisher);
} catch (InterruptedException ignored) {
}
initAmc();
if(!publisher.isAlive()) {
publisher.start();
}
}
public void initAmc(){
String workingDir = ((BaseLocationApplicationContext)context).getBaseLocation();
String etcdUrlForAmc = null;
URL u = null;
try {
u = new URL(getUrl());
} catch (MalformedURLException e) {
try {
u = new URL("http://" + getUrl());
} catch (MalformedURLException ignored) {
}
}
if(u == null){
log.error("Url malformed: " + getUrl());
}
etcdUrlForAmc = "etcd://" + u.getHost() + ":" + u.getPort();
amc = new ApiManagementConfiguration(workingDir,etcdUrlForAmc,membraneId);
}
@Override
public void stop() {
amc.shutdown();
}
@Override
public boolean isRunning() {
return false;
}
public String getUrl() {
return url;
}
/**
* @description the url to where details are published
* @default ...
*/
@MCAttribute
public void setUrl(String url) {
this.url = url;
}
public int getTtl() {
return ttl;
}
/**
* @description ttl in seconds
* @default 300
*/
@MCAttribute
public void setTtl(int ttl) {
this.ttl = ttl;
}
@Override
public ApiManagementConfiguration getConfiguration() {
return amc;
}
@Override
public void destroy() throws Exception {
stop();
}
public String getLocalHostname() {
try {
return InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e) {
try {
return IOUtils.toString(Runtime.getRuntime().exec("hostname").getInputStream());
} catch (IOException e1) {
e1.printStackTrace();
return "localhost";
}
}
}
}