Merge "K8s doesn't necessarily support DNS"
[aaf/authz.git] / cadi / aaf / src / main / java / org / onap / aaf / cadi / aaf / v2_0 / AAFLocator.java
index 468bb91..38f6bce 100644 (file)
@@ -28,6 +28,8 @@ import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
 
+import org.onap.aaf.cadi.Access;
+import org.onap.aaf.cadi.Access.Level;
 import org.onap.aaf.cadi.CadiException;
 import org.onap.aaf.cadi.LocatorException;
 import org.onap.aaf.cadi.SecuritySetter;
@@ -35,6 +37,10 @@ import org.onap.aaf.cadi.client.Future;
 import org.onap.aaf.cadi.config.Config;
 import org.onap.aaf.cadi.config.SecurityInfoC;
 import org.onap.aaf.cadi.http.HClient;
+import org.onap.aaf.cadi.locator.DNSLocator;
+import org.onap.aaf.cadi.locator.SingleEndpointLocator;
+import org.onap.aaf.cadi.locator.SizedLocator;
+import org.onap.aaf.cadi.util.FixURIinfo;
 import org.onap.aaf.cadi.util.Split;
 import org.onap.aaf.misc.env.APIException;
 import org.onap.aaf.misc.env.Data.TYPE;
@@ -47,13 +53,17 @@ import locate.v1_0.Endpoints;
 
 public class AAFLocator extends AbsAAFLocator<BasicTrans>  {
     private static RosettaEnv env;
-    HClient client;
+    private HClient client;
+    private HClient lclient;
     private RosettaDF<Endpoints> epsDF;
+    private SizedLocator<URI> locatorLocator;
+    private Item locatorItem;
+
 
     public AAFLocator(SecurityInfoC<HttpURLConnection> si, URI locatorURI) throws LocatorException {
         super(si.access, nameFromLocatorURI(locatorURI), 10000L /* Wait at least 10 seconds between refreshes */);
         synchronized(sr) {
-            if(env==null) {
+            if (env==null) {
                 env = new RosettaEnv(access.getProperties());
             }
         }
@@ -61,56 +71,99 @@ public class AAFLocator extends AbsAAFLocator<BasicTrans>  {
         int connectTimeout = Integer.parseInt(si.access.getProperty(Config.AAF_CONN_TIMEOUT, Config.AAF_CONN_TIMEOUT_DEF));
         try {
             String[] path = Split.split('/',locatorURI.getPath());
-            String host = locatorURI.getHost();
-            if(host==null) {
-                host = locatorURI.getAuthority(); // this happens when no port
-            }
-            if("AAF_LOCATE_URL".equals(host)) {
-                URI uri = new URI(
-                        locatorURI.getScheme(),
-                        locatorURI.getUserInfo(),
-                        aaf_locator_uri.getHost(),
-                        aaf_locator_uri.getPort(),
-                        "/locate"+locatorURI.getPath(),
-                        null,
-                        null
-                        );
-                client = createClient(si.defSS, uri, connectTimeout);
-            } else if(path.length>1 && "locate".equals(path[1])) {
+            FixURIinfo fui = new FixURIinfo(locatorURI);
+            if ("AAF_LOCATE_URL".equals(fui.getHost())) {
+                client = createClient(si.defSS, locatorURI, connectTimeout);
+            } else if (path.length>1 && "locate".equals(path[1])) {
                 StringBuilder sb = new StringBuilder();
-                for(int i=3;i<path.length;++i) {
+                for (int i=3;i<path.length;++i) {
                     sb.append('/');
                     sb.append(path[i]);
                 }
                 setPathInfo(sb.toString());
-                URI uri = new URI(
-                            locatorURI.getScheme(),
-                            locatorURI.getUserInfo(),
-                            locatorURI.getHost(),
-                            locatorURI.getPort(),
-                            "/locate/"+name + ':' + version,
-                            null,
-                            null
-                            );
-                client = createClient(si.defSS, uri, connectTimeout);
+                client = createClient(si.defSS, locatorURI, connectTimeout);
             } else {
                 client = new HClient(si.defSS, locatorURI, connectTimeout);
             }
             epsDF = env.newDataFactory(Endpoints.class);
-        } catch (APIException | URISyntaxException e) {
+            
+        } catch (APIException /*| URISyntaxException*/ e) {
             throw new LocatorException(e);
         }
+        lclient = new HClient(si.defSS, locatorURI, connectTimeout);
+        
+        if(si.access.willLog(Access.Level.DEBUG)) {
+            si.access.log(Access.Level.DEBUG, "Root URI:",client.getURI());
+        }
+        
+        String dnsString;
+        if(locatorURI.getPort()<0) {
+               dnsString=locatorURI.getScheme() + "://" + locatorURI.getHost();
+        } else {
+               dnsString=locatorURI.getScheme() + "://" +locatorURI.getHost()+':'+locatorURI.getPort();
+        }
+        if(dnsString.contains("null")) { // for Testing Purposes, mostly.
+               locatorLocator = null;
+        } else {
+               locatorLocator = new DNSLocator(access, dnsString);
+               if(locatorLocator.hasItems()) {
+                       locatorItem = locatorLocator.best();
+               } else {
+                       // For when DNS doesn't work, including some K8s Installations
+                               locatorLocator = new SingleEndpointLocator(dnsString);
+               }
+        }
     }
 
+    private URI locatorFail(URI uri) throws LocatorException, URISyntaxException {
+        locatorLocator.invalidate(locatorItem);
+        locatorItem = locatorLocator.best();
+        URI newURI = locatorLocator.get(locatorItem);
+        return new URI(uri.getScheme(),
+                       uri.getUserInfo(),
+                       newURI.getHost(),
+                       newURI.getPort(),
+                       uri.getPath(),
+                       uri.getQuery(),
+                       uri.getFragment());
+    }
+
+    protected final int maxIters() {
+       
+        return locatorLocator.size();
+    }
+
+
     @Override
     public boolean refresh() {
         try {
-            client.setMethod("GET");
-            client.send();
-            Future<Endpoints> fr = client.futureRead(epsDF, TYPE.JSON);
-            if(fr.get(client.timeout())) {
+            int max = locatorLocator.size();
+            for(int i=0;i<max;) {
+                ++i;
+                try {
+                    lclient.setMethod("GET");
+                    lclient.send();
+                    break;
+                } catch (APIException connectE) {
+                    Throwable ce = connectE.getCause();
+                    if(ce!=null && ce instanceof java.net.ConnectException && i< maxIters()) {
+                        try {
+                            URI old = client.getURI();
+                            lclient.setURI(locatorFail(old));
+                            access.printf(Level.INFO, "AAF Locator changed from %s to %s",old, lclient.getURI());
+                            continue;
+                        } catch (LocatorException e) {
+                            throw connectE;
+                        }
+                    }
+                    // last one, just throw
+                    throw connectE;
+                }
+            }
+            Future<Endpoints> fr = lclient.futureRead(epsDF, TYPE.JSON);
+            if (fr.get(lclient.timeout())) {
                 List<EP> epl = new LinkedList<>();
-                for(Endpoint endpoint : fr.value.getEndpoint()) {
+                for (Endpoint endpoint : fr.value.getEndpoint()) {
                     epl.add(new EP(endpoint,latitude,longitude));
                 }
                 
@@ -137,4 +190,5 @@ public class AAFLocator extends AbsAAFLocator<BasicTrans>  {
     protected HClient createClient(SecuritySetter<HttpURLConnection> ss, URI uri, int connectTimeout) throws LocatorException {
         return new HClient(ss, uri, connectTimeout);
     }
+    
 }