case "ADDED": Record record = createRecord(service); if (addRecordIfNotContained(record)) { LOGGER.info("Adding service " + record.getName()); publishRecord(record, null); case "ERROR": record = createRecord(service); LOGGER.info("Removing service " + record.getName()); Record storedRecord = removeRecordIfContained(record); if (storedRecord != null) { unpublishRecord(storedRecord, null); record = createRecord(service); LOGGER.info("Modifying service " + record.getName()); storedRecord = replaceRecordIfContained(record); if (storedRecord != null) { unpublishRecord(storedRecord, x -> publishRecord(record, null));
static Record createRecord(JsonObject service) { JsonObject metadata = service.getJsonObject("metadata"); Record record = new Record() .setName(metadata.getString("name")); JsonObject labels = metadata.getJsonObject("labels"); if (labels != null) { labels.forEach(entry -> record.getMetadata().put(entry.getKey(), entry.getValue().toString())); } record.getMetadata().put("kubernetes.namespace", metadata.getString("namespace")); record.getMetadata().put("kubernetes.name", metadata.getString("name")); record.getMetadata().put(KUBERNETES_UUID, metadata.getString("uid")); String type = record.getMetadata().getString("service-type"); // If not set, try to discovery it if (type == null) { type = discoveryType(service, record); } switch (type) { case HttpEndpoint.TYPE: manageHttpService(record, service); break; // TODO Add JDBC client, redis and mongo default: manageUnknownService(record, service, type); break; } return record; }
private Record removeRecordIfContained(Record record) { for (Record rec : records) { if (areTheSameService(rec, record)) { records.remove(rec); return rec; } } return null; }
Future<String> retrieveTokenFuture = getToken(vertx, conf); this.namespace = conf.getString("namespace", getNamespaceOrDefault()); LOGGER.info("Kubernetes discovery configured for namespace: " + namespace); LOGGER.info("Kubernetes master url: http" + (conf.getBoolean("ssl", true) ? "s" : "") + "//" + host + ":" + port); list.forEach(s -> { JsonObject svc = ((JsonObject) s); Record record = createRecord(svc); if (addRecordIfNotContained(record)) { Future<Record> fut = Future.future(); publishRecord(record, fut.completer()); publications.add(fut);
@Test public void testHttpRecordCreation() { Service service = getHttpService(); Record record = KubernetesServiceImporter.createRecord(new JsonObject(Json.encodeToBuffer(service))); assertThat(record).isNotNull(); assertThat(record.getName()).isEqualTo("my-service"); assertThat(record.getMetadata().getString("kubernetes.name")).isEqualTo("my-service"); assertThat(record.getMetadata().getString("kubernetes.namespace")).isEqualTo("my-project"); assertThat(record.getMetadata().getString("kubernetes.uuid")).isEqualTo("uuid"); assertThat(record.getType()).isEqualTo(HttpEndpoint.TYPE); assertThat(record.getLocation().getInteger("port")).isEqualTo(8080); assertThat(record.getLocation().getBoolean("ssl")).isFalse(); }
ServiceDiscovery discovery = ServiceDiscovery.create(globals.getVertx()); if(new File("/var/run/secrets/kubernetes.io/serviceaccount/token").exists()) discovery.getDelegate().registerServiceImporter(new KubernetesServiceImporter(), new JsonObject()); globals.setGlobal(ServiceDiscovery.class, discovery);
assertThat(KubernetesServiceImporter.discoveryType(new JsonObject(Json.encodeToBuffer(service)), new Record())) .isEqualTo(HttpEndpoint.TYPE); assertThat(KubernetesServiceImporter.discoveryType(new JsonObject(Json.encodeToBuffer(service)), new Record())) .isEqualTo(HttpEndpoint.TYPE); assertThat(KubernetesServiceImporter.discoveryType(new JsonObject(Json.encodeToBuffer(service)), new Record())) .isEqualTo(ServiceType.UNKNOWN); assertThat(KubernetesServiceImporter.discoveryType(new JsonObject(Json.encodeToBuffer(service)), new Record())) .isEqualTo(HttpEndpoint.TYPE); assertThat(KubernetesServiceImporter.discoveryType(new JsonObject(Json.encodeToBuffer(service)), new Record())) .isEqualTo(HttpEndpoint.TYPE); assertThat(KubernetesServiceImporter.discoveryType(new JsonObject(Json.encodeToBuffer(service)), new Record())) .isEqualTo(HttpEndpoint.TYPE); assertThat(KubernetesServiceImporter.discoveryType(new JsonObject(Json.encodeToBuffer(service)), new Record())) .isEqualTo(HttpEndpoint.TYPE); assertThat(KubernetesServiceImporter.discoveryType(new JsonObject(Json.encodeToBuffer(service)), new Record())) .isEqualTo(RedisDataSource.TYPE); assertThat(KubernetesServiceImporter.discoveryType(new JsonObject(Json.encodeToBuffer(service)), new Record())) .isEqualTo(JDBCDataSource.TYPE); assertThat(KubernetesServiceImporter.discoveryType(new JsonObject(Json.encodeToBuffer(service)), new Record())) .isEqualTo(MongoDataSource.TYPE);
private static void manageHttpService(Record record, JsonObject service) { JsonObject spec = service.getJsonObject("spec"); JsonArray ports = spec.getJsonArray("ports"); if (ports != null && !ports.isEmpty()) { if (ports.size() > 1) { LOGGER.warn("More than one port has been found for " + record.getName() + " - taking the first" + " one to extract the HTTP endpoint location"); } JsonObject port = ports.getJsonObject(0); Integer p = port.getInteger("port"); record.setType(HttpEndpoint.TYPE); HttpLocation location = new HttpLocation(port.copy()); if (isExternalService(service)) { location.setHost(spec.getString("externalName")); } else { location.setHost(spec.getString("clusterIP")); } if (isTrue(record.getMetadata().getString("ssl")) || p != null && p == 443) { location.setSsl(true); } record.setLocation(location.toJson()); } else { throw new IllegalStateException("Cannot extract the HTTP URL from the service " + record + " - no port"); } }
private static void manageUnknownService(Record record, JsonObject service, String type) { JsonObject spec = service.getJsonObject("spec"); JsonArray ports = spec.getJsonArray("ports"); if (ports != null && !ports.isEmpty()) { if (ports.size() > 1) { LOGGER.warn("More than one ports has been found for " + record.getName() + " - taking the " + "first one to build the record location"); } JsonObject port = ports.getJsonObject(0); JsonObject location = port.copy(); if (isExternalService(service)) { location.put("host", spec.getString("externalName")); } else { //Number or name of the port to access on the pods targeted by the service. Object targetPort = port.getValue("targetPort"); if (targetPort instanceof Integer) { location.put("internal-port", (Integer) targetPort); } location.put("host", spec.getString("clusterIP")); } record.setLocation(location).setType(type); } else { throw new IllegalStateException("Cannot extract the location from the service " + record + " - no port"); } }
@Test public void testHttpRecordCreation() { Service service = getHttpService(); Record record = KubernetesServiceImporter.createRecord(new JsonObject(Json.encodeToBuffer(service))); assertThat(record).isNotNull(); assertThat(record.getName()).isEqualTo("my-service"); assertThat(record.getMetadata().getString("kubernetes.name")).isEqualTo("my-service"); assertThat(record.getMetadata().getString("kubernetes.namespace")).isEqualTo("my-project"); assertThat(record.getMetadata().getString("kubernetes.uuid")).isEqualTo("uuid"); assertThat(record.getType()).isEqualTo(HttpEndpoint.TYPE); assertThat(record.getLocation().getInteger("port")).isEqualTo(8080); assertThat(record.getLocation().getBoolean("ssl")).isFalse(); }
@Test public void testInitialRetrieval(TestContext tc) { Async async = tc.async(); ServiceDiscovery discovery = ServiceDiscovery.create(vertx, new ServiceDiscoveryOptions().setAutoRegistrationOfImporters(false)); discovery.registerServiceImporter(new KubernetesServiceImporter(), config().copy().put("namespace", "default"), ar -> { if (ar.failed()) { tc.fail(ar.cause()); } else { discovery.getRecords(s -> true, res -> { if (res.failed()) { tc.fail(res.cause()); } else { tc.assertEquals(2, res.result().size()); async.complete(); } }); } }); }
assertThat(KubernetesServiceImporter.discoveryType(new JsonObject(Json.encodeToBuffer(service)), new Record())) .isEqualTo(HttpEndpoint.TYPE); assertThat(KubernetesServiceImporter.discoveryType(new JsonObject(Json.encodeToBuffer(service)), new Record())) .isEqualTo(HttpEndpoint.TYPE); assertThat(KubernetesServiceImporter.discoveryType(new JsonObject(Json.encodeToBuffer(service)), new Record())) .isEqualTo(ServiceType.UNKNOWN); assertThat(KubernetesServiceImporter.discoveryType(new JsonObject(Json.encodeToBuffer(service)), new Record())) .isEqualTo(HttpEndpoint.TYPE); assertThat(KubernetesServiceImporter.discoveryType(new JsonObject(Json.encodeToBuffer(service)), new Record())) .isEqualTo(HttpEndpoint.TYPE); assertThat(KubernetesServiceImporter.discoveryType(new JsonObject(Json.encodeToBuffer(service)), new Record())) .isEqualTo(HttpEndpoint.TYPE); assertThat(KubernetesServiceImporter.discoveryType(new JsonObject(Json.encodeToBuffer(service)), new Record())) .isEqualTo(HttpEndpoint.TYPE); assertThat(KubernetesServiceImporter.discoveryType(new JsonObject(Json.encodeToBuffer(service)), new Record())) .isEqualTo(RedisDataSource.TYPE); assertThat(KubernetesServiceImporter.discoveryType(new JsonObject(Json.encodeToBuffer(service)), new Record())) .isEqualTo(JDBCDataSource.TYPE); assertThat(KubernetesServiceImporter.discoveryType(new JsonObject(Json.encodeToBuffer(service)), new Record())) .isEqualTo(MongoDataSource.TYPE);
@Test public void testUnknownExternalServiceRecordCreation() { // JDBC Example int servicePort = 5432; Service service = getExternalService(servicePort); Record record = KubernetesServiceImporter.createRecord(new JsonObject(Json.encodeToBuffer(service))); assertThat(record).isNotNull(); assertThat(record.getName()).isEqualTo("my-service"); assertThat(record.getMetadata().getString("kubernetes.name")).isEqualTo("my-service"); assertThat(record.getMetadata().getString("kubernetes.namespace")).isEqualTo("my-project"); assertThat(record.getMetadata().getString("kubernetes.uuid")).isEqualTo("uuid"); assertThat(record.getType()).isEqualTo(JDBCDataSource.TYPE); assertThat(record.getLocation().getString("host")).isEqualTo("my-external-service"); assertThat(record.getLocation().getInteger("port")).isEqualTo(servicePort); }
@Test public void testInitialRetrieval(TestContext tc) { Async async = tc.async(); ServiceDiscovery discovery = ServiceDiscovery.create(vertx, new ServiceDiscoveryOptions().setAutoRegistrationOfImporters(false)); discovery.registerServiceImporter(new KubernetesServiceImporter(), config().copy().put("namespace", "default"), ar -> { if (ar.failed()) { tc.fail(ar.cause()); } else { discovery.getRecords(s -> true, res -> { if (res.failed()) { tc.fail(res.cause()); } else { tc.assertEquals(2, res.result().size()); async.complete(); } }); } }); }
private synchronized boolean addRecordIfNotContained(Record record) { for (Record rec : records) { if (areTheSameService(rec, record)) { return false; } } return records.add(record); }
@Test public void testUnknownExternalServiceRecordCreation() { // JDBC Example int servicePort = 5432; Service service = getExternalService(servicePort); Record record = KubernetesServiceImporter.createRecord(new JsonObject(Json.encodeToBuffer(service))); assertThat(record).isNotNull(); assertThat(record.getName()).isEqualTo("my-service"); assertThat(record.getMetadata().getString("kubernetes.name")).isEqualTo("my-service"); assertThat(record.getMetadata().getString("kubernetes.namespace")).isEqualTo("my-project"); assertThat(record.getMetadata().getString("kubernetes.uuid")).isEqualTo("uuid"); assertThat(record.getType()).isEqualTo(JDBCDataSource.TYPE); assertThat(record.getLocation().getString("host")).isEqualTo("my-external-service"); assertThat(record.getLocation().getInteger("port")).isEqualTo(servicePort); }
/** * Reproduce issue https://github.com/vert-x3/vertx-service-discovery/issues/96. */ @Test public void testWatchWithDeletion() { AtomicBoolean done = new AtomicBoolean(); ServiceDiscovery discovery = ServiceDiscovery.create(vertx, new ServiceDiscoveryOptions().setAutoRegistrationOfImporters(false)); discovery.registerServiceImporter(new KubernetesServiceImporter(), config().copy().put("namespace", "issue96"), ar -> done.set(ar.succeeded())); await().untilAtomic(done, is(true)); await().until(() -> { List<Record> records = getRecordsBlocking(discovery); try { assertThatListDoesNotContain(records, "hello-minikube"); return true; } catch (Throwable e) { return false; } }); }
private Record replaceRecordIfContained(Record record) { for (Record rec : records) { if (areTheSameService(rec, record)) { records.remove(rec); records.add(record); return rec; } } return null; } }
@Test public void testHttpWithSSLExternalServiceRecordCreation() { int servicePort = 443; Service service = getExternalService(servicePort); Record record = KubernetesServiceImporter.createRecord(new JsonObject(Json.encodeToBuffer(service))); assertThat(record).isNotNull(); assertThat(record.getName()).isEqualTo("my-service"); assertThat(record.getMetadata().getString("kubernetes.name")).isEqualTo("my-service"); assertThat(record.getMetadata().getString("kubernetes.namespace")).isEqualTo("my-project"); assertThat(record.getMetadata().getString("kubernetes.uuid")).isEqualTo("uuid"); assertThat(record.getType()).isEqualTo(HttpEndpoint.TYPE); assertThat(record.getLocation().getString("host")).isEqualTo("my-external-service"); assertThat(record.getLocation().getInteger("port")).isEqualTo(servicePort); assertThat(record.getLocation().getBoolean("ssl")).isTrue(); assertThat(record.getLocation().getString("endpoint")).isEqualTo("https://my-external-service:" + servicePort); }
/** * Reproduce issue https://github.com/vert-x3/vertx-service-discovery/issues/96. */ @Test public void testWatchWithDeletion() { AtomicBoolean done = new AtomicBoolean(); ServiceDiscovery discovery = ServiceDiscovery.create(vertx, new ServiceDiscoveryOptions().setAutoRegistrationOfImporters(false)); discovery.registerServiceImporter(new KubernetesServiceImporter(), config().copy().put("namespace", "issue96"), ar -> done.set(ar.succeeded())); await().untilAtomic(done, is(true)); await().until(() -> { List<Record> records = getRecordsBlocking(discovery); try { assertThatListDoesNotContain(records, "hello-minikube"); return true; } catch (Throwable e) { return false; } }); }