From 54d46f14d3bd025c25aed6489d4c481e74d1c818 Mon Sep 17 00:00:00 2001 From: varnson Date: Thu, 20 Aug 2026 19:50:15 +0800 Subject: [PATCH 1/2] add catalog/register and catalog/deregister Signed-off-by: varnson --- .../consul/binder/ConsulSendingHandler.java | 2 +- .../cloud/consul/binder/EventService.java | 7 +- .../cloud/consul/ConsulAutoConfiguration.java | 4 +- .../cloud/consul/ConsulClient.java | 42 +- .../http/catalog/CatalogDeregistration.java | 101 ++++ .../http/catalog/CatalogRegistration.java | 516 ++++++++++++++++++ .../consul/ConsulClientIntegrationTests.java | 122 ++++- 7 files changed, 776 insertions(+), 18 deletions(-) create mode 100644 spring-cloud-consul-core/src/main/java/org/springframework/cloud/consul/model/http/catalog/CatalogDeregistration.java create mode 100644 spring-cloud-consul-core/src/main/java/org/springframework/cloud/consul/model/http/catalog/CatalogRegistration.java diff --git a/spring-cloud-consul-binder/src/main/java/org/springframework/cloud/consul/binder/ConsulSendingHandler.java b/spring-cloud-consul-binder/src/main/java/org/springframework/cloud/consul/binder/ConsulSendingHandler.java index becc4f3d0..89d6885a9 100644 --- a/spring-cloud-consul-binder/src/main/java/org/springframework/cloud/consul/binder/ConsulSendingHandler.java +++ b/spring-cloud-consul-binder/src/main/java/org/springframework/cloud/consul/binder/ConsulSendingHandler.java @@ -53,7 +53,7 @@ protected void handleMessageInternal(Message message) { // TODO: support headers // TODO: support consul event filters: NodeFilter, ServiceFilter, TagFilter - ResponseEntity event = this.consul.eventFire(this.eventName, (String) payload); + ResponseEntity event = this.consul.eventFire(this.eventName, (String) payload, null); // TODO: return event? } diff --git a/spring-cloud-consul-binder/src/main/java/org/springframework/cloud/consul/binder/EventService.java b/spring-cloud-consul-binder/src/main/java/org/springframework/cloud/consul/binder/EventService.java index fa6973dd8..827c007ba 100644 --- a/spring-cloud-consul-binder/src/main/java/org/springframework/cloud/consul/binder/EventService.java +++ b/spring-cloud-consul-binder/src/main/java/org/springframework/cloud/consul/binder/EventService.java @@ -68,12 +68,12 @@ private void setLastIndex(ResponseEntity response) { } public Event fire(String name, String payload) { - ResponseEntity response = this.consul.eventFire(name, payload); + ResponseEntity response = this.consul.eventFire(name, payload, null); return response.getBody(); } public ResponseEntity> getEventsResponse() { - return this.consul.eventList(); + return this.consul.eventList(null, null, null, null, null); } public List getEvents() { @@ -98,7 +98,8 @@ public List watch(Long lastIndex) { if (this.properties != null) { eventTimeout = this.properties.getEventTimeout(); } - ResponseEntity> watch = this.consul.eventList((long) eventTimeout, index); + ResponseEntity> watch = this.consul.eventList((long) eventTimeout, index, null, null, null, null, + null); return filterEvents(readEvents(watch), lastIndex); } diff --git a/spring-cloud-consul-core/src/main/java/org/springframework/cloud/consul/ConsulAutoConfiguration.java b/spring-cloud-consul-core/src/main/java/org/springframework/cloud/consul/ConsulAutoConfiguration.java index 673496ab9..26c01055e 100644 --- a/spring-cloud-consul-core/src/main/java/org/springframework/cloud/consul/ConsulAutoConfiguration.java +++ b/spring-cloud-consul-core/src/main/java/org/springframework/cloud/consul/ConsulAutoConfiguration.java @@ -24,7 +24,6 @@ import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; -import java.util.Collections; import org.aspectj.lang.annotation.Aspect; import org.slf4j.Logger; @@ -242,8 +241,7 @@ public boolean resolve(Object argument, MethodParameter parameter, HttpRequestVa } if (params.getConsistencyMode() != ConsulClient.ConsistencyMode.DEFAULT) { - builder.configureRequestParams( - map -> map.put(params.getConsistencyMode().getParamName(), Collections.emptyList())); + builder.addRequestParameter(params.getConsistencyMode().getParamName(), "true"); } if (params.getWaitTime() != -1) { diff --git a/spring-cloud-consul-core/src/main/java/org/springframework/cloud/consul/ConsulClient.java b/spring-cloud-consul-core/src/main/java/org/springframework/cloud/consul/ConsulClient.java index 369a5effb..8a0381693 100644 --- a/spring-cloud-consul-core/src/main/java/org/springframework/cloud/consul/ConsulClient.java +++ b/spring-cloud-consul-core/src/main/java/org/springframework/cloud/consul/ConsulClient.java @@ -21,6 +21,8 @@ import org.springframework.cloud.consul.model.http.agent.NewService; import org.springframework.cloud.consul.model.http.agent.Service; +import org.springframework.cloud.consul.model.http.catalog.CatalogDeregistration; +import org.springframework.cloud.consul.model.http.catalog.CatalogRegistration; import org.springframework.cloud.consul.model.http.catalog.CatalogService; import org.springframework.cloud.consul.model.http.catalog.Node; import org.springframework.cloud.consul.model.http.event.Event; @@ -97,6 +99,16 @@ ResponseEntity agentServiceSetMaintenance(@PathVariable String serviceId, @GetExchange("/v1/catalog/nodes") ResponseEntity> getCatalogNodes(); + @PutExchange("/v1/catalog/register") + ResponseEntity catalogServiceRegister( + @RequestHeader(name = ACL_TOKEN_HEADER, required = false) String aclToken, + @RequestBody CatalogRegistration registration); + + @PutExchange("/v1/catalog/deregister") + ResponseEntity catalogServiceDeregister( + @RequestHeader(name = ACL_TOKEN_HEADER, required = false) String aclToken, + @RequestBody CatalogDeregistration deregistration); + @GetExchange("/v1/health/checks/{serviceName}") ResponseEntity> getHealthChecksForService(@PathVariable String serviceName); @@ -108,6 +120,12 @@ ResponseEntity> getHealthServices(@PathVariable String servi @RequestParam boolean passing, @RequestHeader(name = ACL_TOKEN_HEADER, required = false) String aclToken, @RequestParam(required = false) List tag, QueryParams queryParams); + @GetExchange("/v1/health/service/{serviceName}") + ResponseEntity> getHealthServices(@PathVariable String serviceName, + @RequestParam boolean passing, @RequestHeader(name = ACL_TOKEN_HEADER, required = false) String aclToken, + @RequestParam(required = false) List tag, QueryParams queryParams, + @RequestParam(required = false) boolean cached); + @DeleteExchange("/v1/kv/{context}") ResponseEntity deleteKVValues(@PathVariable String context); @@ -131,15 +149,24 @@ ResponseEntity> getKVValues(@PathVariable String context, @PutExchange(url = "/v1/kv/{context}", contentType = MediaType.TEXT_PLAIN_VALUE) ResponseEntity setKVValue(@PathVariable String context, @RequestBody String value); - @GetExchange("/v1/events") - ResponseEntity> eventList(); + @GetExchange("/v1/event/list") + ResponseEntity> eventList(@RequestParam(name = "name", required = false) String name, + @RequestParam(name = "node", required = false) String node, + @RequestParam(name = "service", required = false) String service, + @RequestParam(name = "tag", required = false) String tag, + @RequestHeader(name = ACL_TOKEN_HEADER, required = false) String aclToken); - @GetExchange("/v1/events") + @GetExchange("/v1/event/list") ResponseEntity> eventList(@RequestParam("wait") @WaitTimeFormat Long eventTimeout, - @RequestParam("index") long index); + @RequestParam("index") long index, @RequestParam(name = "name", required = false) String name, + @RequestParam(name = "node", required = false) String node, + @RequestParam(name = "service", required = false) String service, + @RequestParam(name = "tag", required = false) String tag, + @RequestHeader(name = ACL_TOKEN_HEADER, required = false) String aclToken); @PostExchange("/v1/event/fire/{name}") - ResponseEntity eventFire(@PathVariable String name, @RequestBody String payload); + ResponseEntity eventFire(@PathVariable String name, @RequestBody String payload, + @RequestHeader(name = ACL_TOKEN_HEADER, required = false) String aclToken); class QueryParams { @@ -182,12 +209,11 @@ public QueryParams(String datacenter, long waitTime, long index) { this(datacenter, ConsistencyMode.DEFAULT, waitTime, index, null); } - private QueryParams(String datacenter, ConsistencyMode consistencyMode, long waitTime, long index) { + public QueryParams(String datacenter, ConsistencyMode consistencyMode, long waitTime, long index) { this(datacenter, consistencyMode, waitTime, index, null); } - private QueryParams(String datacenter, ConsistencyMode consistencyMode, long waitTime, long index, - String near) { + public QueryParams(String datacenter, ConsistencyMode consistencyMode, long waitTime, long index, String near) { this.datacenter = datacenter; this.consistencyMode = consistencyMode; this.waitTime = waitTime; diff --git a/spring-cloud-consul-core/src/main/java/org/springframework/cloud/consul/model/http/catalog/CatalogDeregistration.java b/spring-cloud-consul-core/src/main/java/org/springframework/cloud/consul/model/http/catalog/CatalogDeregistration.java new file mode 100644 index 000000000..7eda60865 --- /dev/null +++ b/spring-cloud-consul-core/src/main/java/org/springframework/cloud/consul/model/http/catalog/CatalogDeregistration.java @@ -0,0 +1,101 @@ +/* + * Copyright 2026-present the original author or authors. + * + * 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 + * + * https://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 org.springframework.cloud.consul.model.http.catalog; + +import java.util.Objects; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import org.springframework.core.style.ToStringCreator; + +/** + * This class is for /v1/catalog/deregister API. + * + * @author Varnson Fan + * @since 5.0.3 + */ +public class CatalogDeregistration { + + @JsonProperty("Datacenter") + private String datacenter; + + @JsonProperty("Node") + private String node; + + @JsonProperty("ServiceID") + private String serviceId; + + @JsonProperty("CheckID") + private String checkId; + + public String getDatacenter() { + return datacenter; + } + + public void setDatacenter(String datacenter) { + this.datacenter = datacenter; + } + + public String getNode() { + return node; + } + + public void setNode(String node) { + this.node = node; + } + + public String getServiceId() { + return serviceId; + } + + public void setServiceId(String serviceId) { + this.serviceId = serviceId; + } + + public String getCheckId() { + return checkId; + } + + public void setCheckId(String checkId) { + this.checkId = checkId; + } + + @Override + public String toString() { + return new ToStringCreator(this).append("datacenter", datacenter) + .append("node", node) + .append("serviceId", serviceId) + .append("checkId", checkId) + .toString(); + } + + @Override + public boolean equals(Object o) { + if (o == null || getClass() != o.getClass()) { + return false; + } + CatalogDeregistration that = (CatalogDeregistration) o; + return Objects.equals(datacenter, that.datacenter) && Objects.equals(node, that.node) + && Objects.equals(serviceId, that.serviceId) && Objects.equals(checkId, that.checkId); + } + + @Override + public int hashCode() { + return Objects.hash(datacenter, node, serviceId, checkId); + } + +} diff --git a/spring-cloud-consul-core/src/main/java/org/springframework/cloud/consul/model/http/catalog/CatalogRegistration.java b/spring-cloud-consul-core/src/main/java/org/springframework/cloud/consul/model/http/catalog/CatalogRegistration.java new file mode 100644 index 000000000..b474c5b1f --- /dev/null +++ b/spring-cloud-consul-core/src/main/java/org/springframework/cloud/consul/model/http/catalog/CatalogRegistration.java @@ -0,0 +1,516 @@ +/* + * Copyright 2026-present the original author or authors. + * + * 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 + * + * https://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 org.springframework.cloud.consul.model.http.catalog; + +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import org.springframework.core.style.ToStringCreator; + +/** + * This class is for /v1/catalog/register API. + * + * @author Varnson Fan + * @since 5.0.3 + */ +public class CatalogRegistration { + + @JsonProperty("Datacenter") + private String datacenter; + + @JsonProperty("ID") + private String id; + + @JsonProperty("Node") + private String node; + + @JsonProperty("Address") + private String address; + + @JsonProperty("TaggedAddresses") + private Map taggedAddresses; + + @JsonProperty("NodeMeta") + private Map nodeMeta; + + @JsonProperty("Service") + private Service service; + + @JsonProperty("Check") + private Check check; + + @JsonProperty("SkipNodeUpdate") + private Boolean skipNodeUpdate; + + public String getDatacenter() { + return datacenter; + } + + public void setDatacenter(String datacenter) { + this.datacenter = datacenter; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getNode() { + return node; + } + + public void setNode(String node) { + this.node = node; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public Map getTaggedAddresses() { + return taggedAddresses; + } + + public void setTaggedAddresses(Map taggedAddresses) { + this.taggedAddresses = taggedAddresses; + } + + public Map getNodeMeta() { + return nodeMeta; + } + + public void setNodeMeta(Map nodeMeta) { + this.nodeMeta = nodeMeta; + } + + public Service getService() { + return service; + } + + public void setService(Service service) { + this.service = service; + } + + public Check getCheck() { + return check; + } + + public void setCheck(Check check) { + this.check = check; + } + + public Boolean getSkipNodeUpdate() { + return skipNodeUpdate; + } + + public void setSkipNodeUpdate(Boolean skipNodeUpdate) { + this.skipNodeUpdate = skipNodeUpdate; + } + + @Override + public String toString() { + return new ToStringCreator(this).append("datacenter", datacenter) + .append("id", id) + .append("node", node) + .append("address", address) + .append("taggedAddresses", taggedAddresses) + .append("nodeMeta", nodeMeta) + .append("service", service) + .append("check", check) + .append("skipNodeUpdate", skipNodeUpdate) + .toString(); + } + + @Override + public boolean equals(Object o) { + if (o == null || getClass() != o.getClass()) { + return false; + } + CatalogRegistration that = (CatalogRegistration) o; + return Objects.equals(datacenter, that.datacenter) && Objects.equals(id, that.id) + && Objects.equals(node, that.node) && Objects.equals(address, that.address) + && Objects.equals(taggedAddresses, that.taggedAddresses) && Objects.equals(nodeMeta, that.nodeMeta) + && Objects.equals(service, that.service) && Objects.equals(check, that.check) + && Objects.equals(skipNodeUpdate, that.skipNodeUpdate); + } + + @Override + public int hashCode() { + return Objects.hash(datacenter, id, node, address, taggedAddresses, nodeMeta, service, check, skipNodeUpdate); + } + + public static class Service { + + @JsonProperty("ID") + private String id; + + @JsonProperty("Service") + private String service; + + @JsonProperty("Tags") + private List tags; + + @JsonProperty("Address") + private String address; + + @JsonProperty("TaggedAddresses") + private Map taggedAddresses; + + @JsonProperty("Meta") + private Map meta; + + @JsonProperty("Port") + private Integer port; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getService() { + return service; + } + + public void setService(String service) { + this.service = service; + } + + public List getTags() { + return tags; + } + + public void setTags(List tags) { + this.tags = tags; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public Map getTaggedAddresses() { + return taggedAddresses; + } + + public void setTaggedAddresses(Map taggedAddresses) { + this.taggedAddresses = taggedAddresses; + } + + public Map getMeta() { + return meta; + } + + public void setMeta(Map meta) { + this.meta = meta; + } + + public Integer getPort() { + return port; + } + + public void setPort(Integer port) { + this.port = port; + } + + @Override + public String toString() { + return new ToStringCreator(this).append("id", id) + .append("service", service) + .append("tags", tags) + .append("address", address) + .append("taggedAddresses", taggedAddresses) + .append("meta", meta) + .append("port", port) + .toString(); + } + + @Override + public boolean equals(Object o) { + if (o == null || getClass() != o.getClass()) { + return false; + } + Service that = (Service) o; + return Objects.equals(id, that.id) && Objects.equals(service, that.service) + && Objects.equals(tags, that.tags) && Objects.equals(address, that.address) + && Objects.equals(taggedAddresses, that.taggedAddresses) && Objects.equals(meta, that.meta) + && Objects.equals(port, that.port); + } + + @Override + public int hashCode() { + return Objects.hash(id, service, tags, address, taggedAddresses, meta, port); + } + + } + + public static class TaggedServiceAddress { + + @JsonProperty("Address") + private String address; + + @JsonProperty("Port") + private Integer port; + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public Integer getPort() { + return port; + } + + public void setPort(Integer port) { + this.port = port; + } + + @Override + public String toString() { + return new ToStringCreator(this).append("address", address).append("port", port).toString(); + } + + @Override + public boolean equals(Object o) { + if (o == null || getClass() != o.getClass()) { + return false; + } + TaggedServiceAddress that = (TaggedServiceAddress) o; + return Objects.equals(address, that.address) && Objects.equals(port, that.port); + } + + @Override + public int hashCode() { + return Objects.hash(address, port); + } + + } + + public static class Check { + + @JsonProperty("Node") + private String node; + + @JsonProperty("CheckID") + private String checkId; + + @JsonProperty("Name") + private String name; + + @JsonProperty("Notes") + private String notes; + + @JsonProperty("Status") + private String status; + + @JsonProperty("ServiceID") + private String serviceId; + + @JsonProperty("Definition") + private CheckDefinition definition; + + public String getNode() { + return node; + } + + public void setNode(String node) { + this.node = node; + } + + public String getCheckId() { + return checkId; + } + + public void setCheckId(String checkId) { + this.checkId = checkId; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getNotes() { + return notes; + } + + public void setNotes(String notes) { + this.notes = notes; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getServiceId() { + return serviceId; + } + + public void setServiceId(String serviceId) { + this.serviceId = serviceId; + } + + public CheckDefinition getDefinition() { + return definition; + } + + public void setDefinition(CheckDefinition definition) { + this.definition = definition; + } + + @Override + public String toString() { + return new ToStringCreator(this).append("node", node) + .append("checkId", checkId) + .append("name", name) + .append("notes", notes) + .append("status", status) + .append("serviceId", serviceId) + .append("definition", definition) + .toString(); + } + + @Override + public boolean equals(Object o) { + if (o == null || getClass() != o.getClass()) { + return false; + } + Check that = (Check) o; + return Objects.equals(node, that.node) && Objects.equals(checkId, that.checkId) + && Objects.equals(name, that.name) && Objects.equals(notes, that.notes) + && Objects.equals(status, that.status) && Objects.equals(serviceId, that.serviceId) + && Objects.equals(definition, that.definition); + } + + @Override + public int hashCode() { + return Objects.hash(node, checkId, name, notes, status, serviceId, definition); + } + + } + + public static class CheckDefinition { + + @JsonProperty("HTTP") + private String http; + + @JsonProperty("TCP") + private String tcp; + + @JsonProperty("Interval") + private String interval; + + @JsonProperty("Timeout") + private String timeout; + + @JsonProperty("DeregisterCriticalServiceAfter") + private String deregisterCriticalServiceAfter; + + public String getHttp() { + return http; + } + + public void setHttp(String http) { + this.http = http; + } + + public String getTcp() { + return tcp; + } + + public void setTcp(String tcp) { + this.tcp = tcp; + } + + public String getInterval() { + return interval; + } + + public void setInterval(String interval) { + this.interval = interval; + } + + public String getTimeout() { + return timeout; + } + + public void setTimeout(String timeout) { + this.timeout = timeout; + } + + public String getDeregisterCriticalServiceAfter() { + return deregisterCriticalServiceAfter; + } + + public void setDeregisterCriticalServiceAfter(String deregisterCriticalServiceAfter) { + this.deregisterCriticalServiceAfter = deregisterCriticalServiceAfter; + } + + @Override + public String toString() { + return new ToStringCreator(this).append("tcp", tcp) + .append("http", http) + .append("interval", interval) + .append("timeout", timeout) + .append("deregisterCriticalServiceAfter", deregisterCriticalServiceAfter) + .toString(); + } + + @Override + public boolean equals(Object o) { + if (o == null || getClass() != o.getClass()) { + return false; + } + CheckDefinition that = (CheckDefinition) o; + return Objects.equals(tcp, that.tcp) && Objects.equals(interval, that.interval) + && Objects.equals(timeout, that.timeout) + && Objects.equals(deregisterCriticalServiceAfter, that.deregisterCriticalServiceAfter); + } + + @Override + public int hashCode() { + return Objects.hash(tcp, interval, timeout, deregisterCriticalServiceAfter); + } + + } + +} diff --git a/spring-cloud-consul-core/src/test/java/org/springframework/cloud/consul/ConsulClientIntegrationTests.java b/spring-cloud-consul-core/src/test/java/org/springframework/cloud/consul/ConsulClientIntegrationTests.java index d2aec3689..e21e17a14 100644 --- a/spring-cloud-consul-core/src/test/java/org/springframework/cloud/consul/ConsulClientIntegrationTests.java +++ b/spring-cloud-consul-core/src/test/java/org/springframework/cloud/consul/ConsulClientIntegrationTests.java @@ -34,7 +34,10 @@ import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.utility.DockerImageName; +import org.springframework.cloud.consul.model.http.catalog.CatalogDeregistration; +import org.springframework.cloud.consul.model.http.catalog.CatalogRegistration; import org.springframework.cloud.consul.model.http.event.Event; +import org.springframework.cloud.consul.model.http.health.HealthService; import org.springframework.cloud.consul.model.http.kv.GetValue; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -154,7 +157,7 @@ void getKVValues_WithWaitTimeAndIndexAndAclToken() { @Test void eventListWithWaitTimeAndIndex() { - mockServerClient.when(request().withMethod("GET").withPath("/v1/events")) + mockServerClient.when(request().withMethod("GET").withPath("/v1/event/list")) .respond(response().withStatusCode(200) .withHeaders(new Header("Content-Type", "application/json")) .withBody(json("[\n" + " {\n" + " \"ID\": \"5548d61d-9e97-8e0e-e2b3-1f5f0af5b1a2\",\n" @@ -163,11 +166,11 @@ void eventListWithWaitTimeAndIndex() { + " \"TagFilter\": \"\",\n" + " \"Version\": 1,\n" + " \"LTime\": 19\n" + " }\n" + "]\n"))); - ResponseEntity> response = client.eventList(5L, 2); + ResponseEntity> response = client.eventList(5L, 2, "", "", "", "", ""); mockServerClient.verify( request().withMethod("GET") - .withPath("/v1/events") + .withPath("/v1/event/list") .withQueryStringParameters(Parameter.param("wait", "5s"), Parameter.param("index", "2")), VerificationTimes.exactly(1)); @@ -182,6 +185,119 @@ void eventListWithWaitTimeAndIndex() { assertThat(event.getName()).isEqualTo("deploy"); } + @Test + void getHealthService() { + + mockServerClient.when(request().withMethod("GET").withPath("/v1/health/service/testservice")) + .respond(response().withStatusCode(200)); + ResponseEntity> response = client.getHealthServices("testservice", true, "token12345", + List.of("tag1", "tag2"), + new ConsulClient.QueryParams(null, ConsulClient.ConsistencyMode.STALE, 3, 12345), true); + + mockServerClient.verify(request().withMethod("GET") + .withPath("/v1/health/service/testservice") + .withHeader(Header.header("X-Consul-Token", "token12345")) + .withQueryStringParameter("tag", "tag1", "tag2") + .withQueryStringParameter("passing", "true") + .withQueryStringParameter("stale", "true") + .withQueryStringParameter("wait", "3s") + .withQueryStringParameter("index", "12345") + .withQueryStringParameter("cached", "true"), VerificationTimes.exactly(1)); + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); + } + + @Test + void catalogServiceRegister() { + + mockServerClient.when(request().withMethod("PUT").withPath("/v1/catalog/register")) + .respond(response().withStatusCode(200)); + + CatalogRegistration registration = new CatalogRegistration(); + registration.setDatacenter("dc1"); + registration.setNode("test-node"); + registration.setAddress("192.168.1.1"); + + CatalogRegistration.Service service = new CatalogRegistration.Service(); + service.setId("test-service-1"); + service.setService("test-service"); + service.setPort(8080); + registration.setService(service); + + ResponseEntity response = client.catalogServiceRegister(null, registration); + + mockServerClient.verify(request().withMethod("PUT") + .withPath("/v1/catalog/register") + .withHeader(Header.header("X-Consul-Token", "")), VerificationTimes.exactly(0)); + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); + } + + @Test + void catalogServiceRegisterWithAclToken() { + mockServerClient + .when(request().withMethod("PUT") + .withPath("/v1/catalog/register") + .withHeader(Header.header("X-Consul-Token", "myAclToken"))) + .respond(response().withStatusCode(200)); + + CatalogRegistration registration = new CatalogRegistration(); + registration.setDatacenter("dc1"); + registration.setNode("test-node"); + registration.setAddress("192.168.1.1"); + + CatalogRegistration.Service service = new CatalogRegistration.Service(); + service.setId("test-service-1"); + service.setService("test-service"); + service.setPort(8080); + registration.setService(service); + + ResponseEntity response = client.catalogServiceRegister("myAclToken", registration); + + mockServerClient.verify(request().withMethod("PUT") + .withPath("/v1/catalog/register") + .withHeader(Header.header("X-Consul-Token", "myAclToken")), VerificationTimes.exactly(1)); + + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); + } + + @Test + void catalogServiceDeregister() { + mockServerClient.when(request().withMethod("PUT").withPath("/v1/catalog/deregister")) + .respond(response().withStatusCode(200)); + + CatalogDeregistration deregistration = new CatalogDeregistration(); + deregistration.setDatacenter("dc1"); + deregistration.setNode("test-node"); + deregistration.setServiceId("test-service-1"); + + ResponseEntity response = client.catalogServiceDeregister(null, deregistration); + + verifyRequestSentToConsul("PUT", "/v1/catalog/deregister", 1); + + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); + } + + @Test + void catalogServiceDeregisterWithAclToken() { + mockServerClient + .when(request().withMethod("PUT") + .withPath("/v1/catalog/deregister") + .withHeader(Header.header("X-Consul-Token", "myAclToken"))) + .respond(response().withStatusCode(200)); + + CatalogDeregistration deregistration = new CatalogDeregistration(); + deregistration.setDatacenter("dc1"); + deregistration.setNode("test-node"); + deregistration.setServiceId("test-service-1"); + + ResponseEntity response = client.catalogServiceDeregister("myAclToken", deregistration); + + mockServerClient.verify(request().withMethod("PUT") + .withPath("/v1/catalog/deregister") + .withHeader(Header.header("X-Consul-Token", "myAclToken")), VerificationTimes.exactly(1)); + + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); + } + private void verifyRequestSentToConsul(String method, String path, int times) { mockServerClient.verify(request().withMethod(method).withPath(path), VerificationTimes.exactly(times)); } From 86606acf705612a600dd367b96cc95dcf57d162c Mon Sep 17 00:00:00 2001 From: varnson Date: Thu, 20 Aug 2026 20:26:20 +0800 Subject: [PATCH 2/2] remove consul-api and gson Signed-off-by: varnson --- spring-cloud-consul-config/pom.xml | 6 +----- spring-cloud-consul-core/pom.xml | 13 ++----------- spring-cloud-consul-dependencies/pom.xml | 16 ++-------------- spring-cloud-consul-discovery/pom.xml | 12 +----------- spring-cloud-starter-consul/pom.xml | 9 --------- 5 files changed, 6 insertions(+), 50 deletions(-) diff --git a/spring-cloud-consul-config/pom.xml b/spring-cloud-consul-config/pom.xml index 207d03f61..7e0f19072 100644 --- a/spring-cloud-consul-config/pom.xml +++ b/spring-cloud-consul-config/pom.xml @@ -77,11 +77,7 @@ junit-vintage-engine test - - com.ecwid.consul - consul-api - test - + org.testcontainers consul diff --git a/spring-cloud-consul-core/pom.xml b/spring-cloud-consul-core/pom.xml index 92ebb3888..dc436aa9f 100644 --- a/spring-cloud-consul-core/pom.xml +++ b/spring-cloud-consul-core/pom.xml @@ -61,17 +61,8 @@ - - com.ecwid.consul - consul-api - true - - - - com.google.code.gson - gson - true - + + org.apache.httpcomponents httpclient diff --git a/spring-cloud-consul-dependencies/pom.xml b/spring-cloud-consul-dependencies/pom.xml index 404df79f9..33aad157c 100644 --- a/spring-cloud-consul-dependencies/pom.xml +++ b/spring-cloud-consul-dependencies/pom.xml @@ -14,9 +14,7 @@ pom spring-cloud-consul-dependencies Spring Cloud Consul Dependencies - - 1.4.5 - + @@ -64,17 +62,7 @@ spring-cloud-starter-consul-all ${project.version} - - com.ecwid.consul - consul-api - ${consul-api.version} - - - javax.servlet - servlet-api - - - + diff --git a/spring-cloud-consul-discovery/pom.xml b/spring-cloud-consul-discovery/pom.xml index 65466cf0a..47125a41d 100644 --- a/spring-cloud-consul-discovery/pom.xml +++ b/spring-cloud-consul-discovery/pom.xml @@ -46,17 +46,7 @@ spring-cloud-config-server true - - com.ecwid.consul - consul-api - true - - - - com.google.code.gson - gson - true - + org.apache.httpcomponents httpclient diff --git a/spring-cloud-starter-consul/pom.xml b/spring-cloud-starter-consul/pom.xml index 66db2d95f..4446ea6d4 100644 --- a/spring-cloud-starter-consul/pom.xml +++ b/spring-cloud-starter-consul/pom.xml @@ -29,15 +29,6 @@ org.springframework.cloud spring-cloud-consul-core - - com.ecwid.consul - consul-api - - - - com.google.code.gson - gson - org.apache.httpcomponents httpclient