package eu.mikroskeem.utils.etcdconnector; import com.google.gson.Gson; import mousio.etcd4j.EtcdClient; import mousio.etcd4j.responses.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; import java.net.URI; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeoutException; abstract class EtcdConnectorBase { final Logger logger; EtcdClient etcdClient; EtcdConnectorBase() throws IOException { /* Set up logger */ logger = LoggerFactory.getLogger("EtcdConnector"); } /** * Initializes EtcdClient object */ abstract void initClient(URI... urls); /** * Tests if Etcd connection is working * * @throws IOException if connection doesn't work */ void testEtcd() throws IOException { /* Test client */ try { logger.debug("Testing Etcd connection..."); EtcdVersionResponse ver = etcdClient.version(); logger.debug("Etcd server version: {}", ver.getServer()); } catch (NullPointerException e){ throw new IOException("Etcd connection test failed!"); } logger.debug("Etcd is working!"); } /** * Closes Etcd4j client * * @throws IOException Thrown by Etcd4j */ public void close() throws IOException { if(this.etcdClient != null){ this.etcdClient.close(); } } /** * Gets etcd key value * * @param path Key path * @return Key value */ @Nullable public String getKey(@NotNull String path){ logger.debug("getKey: {}", path); try { EtcdKeysResponse response = etcdClient.get(path).send().get(); /* Parse object */ String rawResp = response.getNode().getValue(); if(rawResp != null){ return new Gson().fromJson(rawResp, String.class); } return null; } catch(EtcdException e){ if(!e.isErrorCode(EtcdErrorCode.KeyNotFound)) { e.printStackTrace(); } } catch(IOException|EtcdAuthenticationException |TimeoutException e){ e.printStackTrace(); } return null; } /** * Gets etcd key value and sets default, * if key isn't defined * * @param path Key path * @param defaultValue Value to set if key is nonexistent * @return Key value */ @Nullable public String getKey(@NotNull String path, @NotNull String defaultValue){ logger.debug("getKey: {}, {}", path, defaultValue); try { EtcdKeysResponse response = etcdClient.get(path).send().get(); /* Parse object */ String rawResp = response.getNode().getValue(); if(rawResp != null){ return new Gson().fromJson(rawResp, String.class); } return null; } catch(EtcdException e){ if(e.isErrorCode(EtcdErrorCode.KeyNotFound)){ /* Put default value to there then */ putKey(path, defaultValue); return defaultValue; } else e.printStackTrace(); } catch(IOException|EtcdAuthenticationException|TimeoutException e){ e.printStackTrace(); } return null; } /** * Gets etcd directory contents and returns it as * List of String * * @param path directory path * @return directory contents */ @Nullable public List getDir(@NotNull String path){ logger.debug("getDir: {}", path); List ret = new ArrayList<>(); try { EtcdKeysResponse response = etcdClient.getDir(path).send().get(); response.getNode().getNodes().forEach(etcdNode -> ret.add((new File(etcdNode.getKey())).getName())); return ret; } catch(EtcdException e){ if(!(e.isErrorCode(EtcdErrorCode.KeyNotFound))){ e.printStackTrace(); } return null; } catch(IOException|EtcdAuthenticationException|TimeoutException e){ e.printStackTrace(); } return null; } /** * Sets etcd key value * * @param path key path * @param value key value * @return whether write succeeded or not */ public boolean putKey(@NotNull String path, @NotNull String value){ logger.debug("putKey: {}, {}", path, value); try { /* Serialize value */ EtcdKeysResponse response = etcdClient.put(path, new Gson().toJson(value)).send().get(); response.getNode().getValue(); return true; } catch(Exception e) { e.printStackTrace(); } return false; } /** * Sets etcd key value with TTL * * @param path key path * @param value key value * @param ttl key ttl (seconds) * @return whether write succeeded or not */ public boolean putKey(@NotNull String path, @NotNull String value, @NotNull int ttl){ logger.debug("putKey: {}, {}, {}", path, value, ttl); try { EtcdKeysResponse response = etcdClient.put(path, new Gson().toJson(value)).ttl(ttl).send().get(); response.getNode().getValue(); return true; } catch(Exception e) { e.printStackTrace(); } return false; } /** * Deletes etcd key * @param path key path * @return whether delete succeeded or not */ public boolean deleteKey(@NotNull String path){ logger.debug("deleteKey: {}", path); try { EtcdKeysResponse response = etcdClient.delete(path).send().get(); response.getNode().getValue(); return true; } catch(EtcdException e){ if(!(e.isErrorCode(EtcdErrorCode.KeyNotFound))){ e.printStackTrace(); } } catch(Exception e){ e.printStackTrace(); } return false; } }