diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index aa57db57..24a09e75 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -4,10 +4,10 @@ name: Docker Build on: push: branches: - - main - - release-* + - "main" + - "release-*" tags: - - 'v*' + - "v*" jobs: build: @@ -22,6 +22,16 @@ jobs: distribution: 'adopt' - name: Build with Maven run: mvn -B package --file pom.xml -Dmaven.test.skip + - name: Docker meta + id: meta + uses: docker/metadata-action@v4 + with: + images: ${{ secrets.DOCKER_HUB_USERNAME }}/hango-portal + flavor: latest=true + tags: | + type=ref,event=branch + type=ref,event=pr + type=semver,pattern={{version}} - name: Login to Docker Hub uses: docker/login-action@v2 with: @@ -34,5 +44,5 @@ jobs: with: context: . file: ./gateway-portal/Dockerfile - push: true - tags: ${{ secrets.DOCKER_HUB_USERNAME }}/hango-portal:latest \ No newline at end of file + push: ${{ github.ref_type == 'tag' }} + tags: ${{ steps.meta.outputs.tags }} \ No newline at end of file diff --git a/gateway-api/pom.xml b/gateway-api/pom.xml index 2a537a3e..1cfde3eb 100644 --- a/gateway-api/pom.xml +++ b/gateway-api/pom.xml @@ -11,7 +11,7 @@ 4.0.0 gateway-api - 0.1.5-SNAPSHOT + 0.1.6-SNAPSHOT jar @@ -69,7 +69,7 @@ io.swagger swagger-core - 1.5.20 + 1.6.6 @@ -94,14 +94,8 @@ org.apache.cxf - cxf-spring-boot-starter-jaxws - 3.1.12 - - - ch.qos.logback - logback-core - - + cxf-rt-frontend-jaxws + 3.5.3 diff --git a/gateway-portal/pom.xml b/gateway-portal/pom.xml index 78e72e2c..7d1f0df2 100644 --- a/gateway-portal/pom.xml +++ b/gateway-portal/pom.xml @@ -22,7 +22,8 @@ UTF-8 UTF-8 1.8 - 1.5.4.RELEASE + 1.48.1 + 2.0.9 org.hango.cloud.dashboard.DashboardApplication @@ -35,18 +36,9 @@ - - - org.springframework.boot - spring-boot-dependencies - ${spring.boot.version} - pom - import - org.springframework.boot spring-boot-starter-web - ${spring.boot.version} @@ -61,7 +53,6 @@ org.springframework.boot spring-boot-starter - ${spring.boot.version} org.springframework.boot @@ -73,15 +64,9 @@ org.springframework.boot spring-boot-starter-test - ${spring.boot.version} test - - - - - org.apache.logging.log4j log4j-slf4j-impl @@ -114,27 +99,23 @@ org.slf4j jul-to-slf4j - 1.7.30 compile - - - - - + + com.querydsl + querydsl-core + org.springframework.boot spring-boot-starter-tomcat - ${spring.boot.version} org.springframework.boot spring-boot-starter-jdbc - ${spring.boot.version} mysql @@ -144,7 +125,6 @@ org.apache.commons commons-dbcp2 - 2.1.1 commons-logging @@ -156,13 +136,11 @@ redis.clients jedis - 2.10.2 org.springframework.boot spring-boot-starter-data-redis - ${spring.boot.version} redis.clients @@ -175,7 +153,6 @@ org.apache.commons commons-lang3 - 3.6 io.swagger @@ -186,7 +163,6 @@ commons-codec commons-codec - 1.8 commons-httpclient @@ -209,7 +185,6 @@ com.nimbusds nimbus-jose-jwt - 4.3.1 @@ -221,7 +196,6 @@ org.yaml snakeyaml - 1.25 @@ -246,10 +220,16 @@ jest 5.3.3 + + + gson + com.google.code.gson + + - org.elasticsearch - elasticsearch - 6.8.4 + io.netty + netty-common + 4.1.77.Final @@ -267,19 +247,17 @@ org.hango.cloud gateway-api - 0.1.5-SNAPSHOT + 0.1.6-SNAPSHOT org.springframework.cloud spring-cloud-starter-consul-discovery - 1.3.4.RELEASE org.springframework.cloud - spring-cloud-starter-eureka - 1.3.4.RELEASE + spring-cloud-starter-netflix-eureka-client org.springframework.boot @@ -311,13 +289,13 @@ com.h2database h2 - 2.1.214 + runtime org.apache.zookeeper zookeeper - 3.6.0 + 3.6.3 org.slf4j @@ -383,7 +361,6 @@ org.springframework.boot spring-boot-starter-aop - ${spring.boot.version} spring-expression @@ -394,7 +371,7 @@ org.redisson redisson-spring-boot-starter - 2.15.2 + 3.16.4 @@ -408,7 +385,6 @@ net.minidev json-smart - 2.2.1 test @@ -416,17 +392,17 @@ io.grpc grpc-netty-shaded - 1.20.0 + ${grpc.version} io.grpc grpc-protobuf - 1.20.0 + ${grpc.version} io.grpc grpc-stub - 1.20.0 + ${grpc.version} com.google.protobuf @@ -455,21 +431,20 @@ javax.validation validation-api - 2.0.1.Final org.powermock powermock-module-junit4 - 1.6.5 + ${mockit.version} test org.powermock - powermock-api-mockito - 1.6.5 + powermock-api-mockito2 + ${mockit.version} @@ -482,8 +457,19 @@ com.hubspot.jinjava jinjava 2.5.6 + + + jsoup + org.jsoup + + + + jsoup + org.jsoup + 1.14.2 + @@ -503,6 +489,31 @@ false + + maven-surefire-plugin + 2.19.1 + + ${argLine} + + **/*Test.java + + + **/BaseTest.java + + + + + default-test + test + + test + + + ${surefireArgLine} + + + + diff --git a/gateway-portal/src/main/java/org/hango/cloud/dashboard/DashboardApplication.java b/gateway-portal/src/main/java/org/hango/cloud/dashboard/DashboardApplication.java index 3d47b63b..a908ff8a 100644 --- a/gateway-portal/src/main/java/org/hango/cloud/dashboard/DashboardApplication.java +++ b/gateway-portal/src/main/java/org/hango/cloud/dashboard/DashboardApplication.java @@ -5,17 +5,11 @@ import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration; -import org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration; -import org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration; -import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration; -import org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration; import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; -import org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration; import org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration; -import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration; -import org.springframework.boot.autoconfigure.web.HttpMessageConverters; -import org.springframework.boot.web.support.SpringBootServletInitializer; +import org.springframework.boot.autoconfigure.http.HttpMessageConverters; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; +import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ImportResource; import org.springframework.context.annotation.PropertySource; @@ -31,7 +25,12 @@ * @Author: Wang Dacheng(wangdacheng) * @Date: 创建时间: 2017/12/4 上午10:33. */ -@SpringBootApplication(exclude = {GsonAutoConfiguration.class, JestAutoConfiguration.class, RedisAutoConfiguration.class}) +@SpringBootApplication( + exclude = { + GsonAutoConfiguration.class, + RedisAutoConfiguration.class, + AutoServiceRegistrationAutoConfiguration.class + }) @ImportResource({"classpath:applicationContext.xml"}) @EnableScheduling @PropertySource({"classpath:gdashboard-application.properties", "classpath:gdashboard-jdbc.properties"}) diff --git a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/config/ServerConfiguration.java b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/config/ServerConfiguration.java index 5fdad8e6..1769827a 100644 --- a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/config/ServerConfiguration.java +++ b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/config/ServerConfiguration.java @@ -1,13 +1,12 @@ package org.hango.cloud.dashboard.apiserver.config; -import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration; +import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; /** * @author Weng Yanghui (wengyanghui) @@ -20,7 +19,7 @@ public class ServerConfiguration extends WebMvcAutoConfiguration { @Bean public WebMvcConfigurer corsConfigurer() { - return new WebMvcConfigurerAdapter() { + return new WebMvcConfigurer() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/**") diff --git a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/dto/DubboInfoDto.java b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/dto/DubboInfoDto.java index ebddb84a..cb3894d7 100644 --- a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/dto/DubboInfoDto.java +++ b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/dto/DubboInfoDto.java @@ -2,12 +2,15 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.annotation.JSONField; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; import org.hango.cloud.dashboard.apiserver.meta.DubboInfo; import org.hango.cloud.dashboard.apiserver.util.Const; import org.hibernate.validator.constraints.NotEmpty; import org.springframework.util.CollectionUtils; import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; import java.util.ArrayList; import java.util.List; @@ -53,7 +56,7 @@ public class DubboInfoDto { private String version; /** - * 是否开启自定义参数映射开关, 默认false + * 是否开启自定义参数映射开关, 目前只支持开启 */ @JSONField(name = "CustomParamMapping") private boolean customParamMapping; @@ -70,6 +73,27 @@ public class DubboInfoDto { @JSONField(name = "Params") private List params = new ArrayList<>(); + + /** + * 参数来源,支持query和body两种参数来源配置 + */ + @JSONField(name = "ParamSource") + @Pattern(regexp = "query|body") + private String paramSource; + + /** + * dubbo attachmentInfo + */ + @JSONField(name = "Attachment") + private List dubboAttachment; + + /** + * 方法是否有效 + */ + @JSONField(name = "MethodWorks") + private Boolean methodWorks; + + public static DubboInfoDto toDto(DubboInfo info) { if (info == null) { return null; @@ -83,7 +107,9 @@ public static DubboInfoDto toDto(DubboInfo info) { dubboInfoDto.setVersion(meta.getVersion()); dubboInfoDto.setGroup(meta.getGroup()); dubboInfoDto.setParams(meta.getParams()); + dubboInfoDto.setParamSource(meta.getParamSource()); dubboInfoDto.setCustomParamMapping(meta.getCustomParamMapping()); + dubboInfoDto.setDubboAttachment(meta.getAttachmentInfo()); return dubboInfoDto; } @@ -103,6 +129,22 @@ public void setParams(List params) { this.params = params; } + public String getParamSource() { + return paramSource; + } + + public void setParamSource(String paramSource) { + this.paramSource = paramSource; + } + + public List getDubboAttachment() { + return dubboAttachment; + } + + public void setDubboAttachment(List dubboAttachment) { + this.dubboAttachment = dubboAttachment; + } + public String getParamToStr() { if (CollectionUtils.isEmpty(params)) { return null; @@ -162,6 +204,14 @@ public void setCustomParamMapping(boolean customParamMapping) { this.customParamMapping = customParamMapping; } + public Boolean getMethodWorks() { + return methodWorks; + } + + public void setMethodWorks(Boolean methodWorks) { + this.methodWorks = methodWorks; + } + public DubboInfo toMeta() { DubboInfo dubboInfo = new DubboInfo(); dubboInfo.setObjectId(objectId); @@ -172,7 +222,9 @@ public DubboInfo toMeta() { meta.setMethod(method); meta.setInterfaceName(interfaceName); meta.setParams(params); + meta.setParamSource(paramSource); meta.setCustomParamMapping(customParamMapping); + meta.setAttachmentInfo(dubboAttachment); dubboInfo.setDubboInfo(JSON.toJSONString(meta)); return dubboInfo; } @@ -205,12 +257,26 @@ public static class DubboMeta { */ private List params; - /** * 是否开启自定义参数映射开关, 默认false */ private boolean customParamMapping; + /** + * 参数来源,支持:query和body三种参数来源配置 + */ + private String paramSource = Const.POSITION_BODY; + + /** + * dubbo attachment信息 + */ + private List attachmentInfo; + + /** + * dubbo 泛型信息 + */ + private String genericInfo; + public String getMethod() { return method; } @@ -258,6 +324,30 @@ public boolean getCustomParamMapping() { public void setCustomParamMapping(boolean customParamMapping) { this.customParamMapping = customParamMapping; } + + public String getParamSource() { + return paramSource; + } + + public void setParamSource(String paramSource) { + this.paramSource = paramSource; + } + + public List getAttachmentInfo() { + return attachmentInfo; + } + + public void setAttachmentInfo(List attachmentInfo) { + this.attachmentInfo = attachmentInfo; + } + + public String getGenericInfo() { + return genericInfo; + } + + public void setGenericInfo(String genericInfo) { + this.genericInfo = genericInfo; + } } public static class DubboParam { @@ -272,6 +362,15 @@ public static class DubboParam { @JSONField(name = "Value") private String value; + @JSONField(name = "Required") + private boolean required; + + @JSONField(name = "DefaultValue") + private Object defaultValue; + + @JSONField(name = "GenericInfo") + private String genericInfo; + public String getKey() { return key; } @@ -287,5 +386,96 @@ public String getValue() { public void setValue(String value) { this.value = value; } + + public boolean isRequired() { + return required; + } + + public void setRequired(boolean required) { + this.required = required; + } + + public Object getDefaultValue() { + return defaultValue; + } + + public void setDefaultValue(Object defaultValue) { + this.defaultValue = defaultValue; + } + + public String getGenericInfo() { + return genericInfo; + } + + public void setGenericInfo(String genericInfo) { + this.genericInfo = genericInfo; + } + } + + + public static class DubboAttachmentDto{ + /** + * attachment位置 Header/Cookie + */ + @JSONField(name = "ParamPosition") + private String paramPosition; + /** + * 客户端参数名称 + */ + @JSONField(name = "ClientParamName") + private String clientParamName; + + /** + * 服务端参数名称 + */ + @JSONField(name = "ServerParamName") + private String serverParamName; + + /** + * 备注信息 + */ + @JSONField(name = "Description") + private String description; + + public String getParamPosition() { + return paramPosition; + } + + public void setParamPosition(String paramPosition) { + this.paramPosition = paramPosition; + } + + public String getClientParamName() { + return clientParamName; + } + + public void setClientParamName(String clientParamName) { + this.clientParamName = clientParamName; + } + + public String getServerParamName() { + return serverParamName; + } + + public void setServerParamName(String serverParamName) { + this.serverParamName = serverParamName; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getDistinctName(){ + return paramPosition + clientParamName; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); + } } } diff --git a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/dto/DubboMetaDto.java b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/dto/DubboMetaDto.java index 4f7ecb05..3e241b26 100644 --- a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/dto/DubboMetaDto.java +++ b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/dto/DubboMetaDto.java @@ -63,7 +63,7 @@ public class DubboMetaDto implements Comparable { */ @JSONField(name = "Group") - private String group; + private String group= StringUtils.EMPTY;; /** @@ -71,7 +71,7 @@ public class DubboMetaDto implements Comparable { */ @JSONField(name = "Version") - private String version; + private String version = StringUtils.EMPTY;; /** diff --git a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/handler/PluginHandler.java b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/handler/PluginHandler.java index ac43dbd7..9ba0393d 100644 --- a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/handler/PluginHandler.java +++ b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/handler/PluginHandler.java @@ -21,11 +21,16 @@ public abstract class PluginHandler { public static final Map pluginUseSubNameList = new HashMap<>(); static { + //21GA版本插件 + pluginIgnoreList.add("com.netease.metadatahub"); + pluginIgnoreList.add("com.netease.metadataext"); //22GA版本插件 pluginIgnoreList.add("proxy.filters.http.metadatahub"); } static { + //21GA版本插件 + pluginUseSubNameList.put("com.netease.resty", new RestyPluginHandler()); //22GA版本插件 pluginUseSubNameList.put("proxy.filters.http.rider", new RiderPluginHandler()); } diff --git a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/meta/BasePageInfo.java b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/meta/BasePageInfo.java index 4ef5f4f8..a6d0aed7 100644 --- a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/meta/BasePageInfo.java +++ b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/meta/BasePageInfo.java @@ -37,7 +37,7 @@ public void setOffset(int offset) { @JSONField(serialize = false) public Pageable getPageable() { - return new QPageRequest(Math.floorDiv(offset, limit), limit); + return QPageRequest.of(Math.floorDiv(offset, limit), limit); } } diff --git a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/meta/RegistryCenterEnum.java b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/meta/RegistryCenterEnum.java index f3ddc645..8c0af8bb 100644 --- a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/meta/RegistryCenterEnum.java +++ b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/meta/RegistryCenterEnum.java @@ -12,24 +12,27 @@ public enum RegistryCenterEnum { /** * Eureka注册中心方式发布的服务,对应的host拼接为{appName}.eureka,且格式为小写 */ - Eureka("Eureka", "%s.eureka"), - Zookeeper("Zookeeper", "%s.dubbo"), - Nacos("Nacos", "%s.nacos"), + Eureka("Eureka", "%s.eureka",2), + Zookeeper("Zookeeper", "%s.dubbo",3), + Nacos("Nacos", "%s.nacos",4), /** * Consul注册中心方式发布的服务,对应的host拼接为{appName}.service.consul.{consul别名} * consul别名,用于区分不同consul应用 */ - Consul("Consul", "%s.service.consul.%s"), - Kubernetes("Kubernetes", "%s"); + Consul("Consul", "%s.service.consul.%s",1), + Kubernetes("Kubernetes", "%s",0), + ; private String type; private String suffix; + private int order; - RegistryCenterEnum(String type, String suffix) { + RegistryCenterEnum(String type, String suffix, int order) { this.type = type; this.suffix = suffix; + this.order = order; } public static RegistryCenterEnum get(String type) { @@ -48,4 +51,8 @@ public String getType() { public String getSuffix() { return suffix; } + + public int getOrder() { + return order; + } } diff --git a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/meta/ServiceType.java b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/meta/ServiceType.java index 136e16d5..0920b700 100644 --- a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/meta/ServiceType.java +++ b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/meta/ServiceType.java @@ -17,17 +17,17 @@ public enum ServiceType { /** - * 获取服务类别(默认HTTP服务) + * 获取服务类别(无默认值) * * @param serviceType * @return */ - public static String getByName(String serviceType) { + public static ServiceType getServiceTypeByName(String serviceType) { for (ServiceType type : ServiceType.values()) { if (type.name().equalsIgnoreCase(serviceType)) { - return type.name(); + return type; } } - return http.name(); + return null; } } diff --git a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/meta/errorcode/CommonErrorCode.java b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/meta/errorcode/CommonErrorCode.java index b70da1bb..49e732d5 100644 --- a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/meta/errorcode/CommonErrorCode.java +++ b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/meta/errorcode/CommonErrorCode.java @@ -61,6 +61,7 @@ public class CommonErrorCode extends ErrorCode { public static ErrorCode CannotDownloadSDK = new ErrorCode(ErrorCodeEnum.CannotDownloadServiceSDK); public static ErrorCode NoSuchService = new ErrorCode(ErrorCodeEnum.NoSuchService); public static ErrorCode ServicePublishedUpdateLimit = new ErrorCode(ErrorCodeEnum.ServicePublishedUpdateLimit); + public static ErrorCode ServiceTypeInvalid = new ErrorCode(ErrorCodeEnum.ServiceTypeInvalid); /** * 授权相关 */ @@ -138,6 +139,10 @@ public class CommonErrorCode extends ErrorCode { public static ErrorCode RepeatParamValue = new ErrorCode(ErrorCodeEnum.RepeatValue, "ParamValue"); public static ErrorCode UpdateNotAllowedRuleName = new ErrorCode(ErrorCodeEnum.UpdateNotAllowed, "RuleName"); public static ErrorCode CustomParamMappingInvalid = new ErrorCode(ErrorCodeEnum.CustomParamMappingInvalid); + public static ErrorCode GenericInfoInvalid = new ErrorCode(ErrorCodeEnum.GenericInfoInvalid); + public static ErrorCode UnSupportedDefaultValueType = new ErrorCode(ErrorCodeEnum.UnSupportedDefaultValueType); + public static ErrorCode DefaultValueConfigInvaild = new ErrorCode(ErrorCodeEnum.DefaultValueConfigInvaild); + public static ErrorCode DubboAttachmentConfigInvaild = new ErrorCode(ErrorCodeEnum.DubboAttachmentConfigInvaild); public static ErrorCode ServiceNotFound = new ErrorCode(ErrorCodeEnum.ServiceNotFound); public static ErrorCode CannotOfflineService = new ErrorCode(ErrorCodeEnum.CannotOfflineService); public static ErrorCode CannotOfflineGrpcService = new ErrorCode(ErrorCodeEnum.CannotOfflineGrpcService); @@ -197,6 +202,8 @@ public class CommonErrorCode extends ErrorCode { public static ErrorCode MirrorByRouteRule = new ErrorCode(ErrorCodeEnum.MirrorByRouteRule); public static ErrorCode RouteRuleNotPublished = new ErrorCode(ErrorCodeEnum.RouteRuleNotPublished); public static ErrorCode RouteRuleServiceNotMatch = new ErrorCode(ErrorCodeEnum.RouteRuleServiceNotMatch); + + public static ErrorCode RouteHasTrafficMarkRules = new ErrorCode(ErrorCodeEnum.RouteHasTrafficMarkRules); public static ErrorCode RouteRuleMethodInvalid = new ErrorCode(ErrorCodeEnum.RouteRuleMethodInvalid); public static ErrorCode CannotDeleteRouteRuleService = new ErrorCode(ErrorCodeEnum.CannotDeleteRouteRuleService); public static ErrorCode SortKeyInvalid = new ErrorCode(ErrorCodeEnum.SortKeyInvalid); diff --git a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/meta/errorcode/ErrorCodeEnum.java b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/meta/errorcode/ErrorCodeEnum.java index 460bef8b..3f75f23f 100644 --- a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/meta/errorcode/ErrorCodeEnum.java +++ b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/meta/errorcode/ErrorCodeEnum.java @@ -178,6 +178,8 @@ public enum ErrorCodeEnum { //服务相关 CannotUpdateService("CannotUpdateService", "You can't update service until offline the service", "在下线服务之前,不能修改服务的基本信息", 400), ServicePublishedUpdateLimit("ServicePublishedUpdateLimit", "You can't update service publish type", "不能更新发布服务的发布方式", 400), + + ServiceTypeInvalid("ServiceTypeInvalid", "Service type is invalid", "服务类型不合法", 400), CannotUpdateServiceName("CannotUpdateServiceName", "You can't update service name cause of sync", "从元数据同步服务,不允许修改服务名称", 400), CannotDeleteOnlineService("CannotDeleteOnlineService", "You can't delete service until offline the service", "在下线服务之前,不能删除服务", 400), CannotDeleteApiService("CannotDeleteApiService", "You can't delete service until delete all apis", "在删除api前,不能删除服务", 400), @@ -268,6 +270,7 @@ public enum ErrorCodeEnum { RouteRuleAlreadyPublishedToGw("RouteRuleAlreadyPublishedToGw", "The route rule has already published to gw, gw is: %s.", "路由规则已发布至网关: %s", 400), RouteRuleNotPublished("RouteRuleNotPublished", "The route rule not published", "路由规则未发布", 400), RouteRuleServiceNotMatch("RouteRuleServiceNotMatch", "The route rule not match the service", "服务和路由规则不匹配", 400), + RouteHasTrafficMarkRules("RouteHasTrafficMarkRules", "The route rule has traffic mark rules", "该路由存在流量染色规则,请先删除流量染色规则再下线路由", 400), RouteRuleMethodInvalid("RouteRuleMethodInvalid", "The route rule method is invalid", "路由规则指定的method不合法", 400), CannotDeleteRouteRuleService("CannotDeleteRouteRuleService", "The service has route rule", "服务存在路由规则,不允许删除", 400), SortKeyInvalid("SortKeyInvalid", "The sort key is invalid", "搜索查询查询搜索项不正确", 400), @@ -348,6 +351,10 @@ public enum ErrorCodeEnum { FailedToOfflineServiceOrRoute("FailedToOfflineServiceOrRoute", "Failed to automatically offline service or route", "自动下线服务或路由失败", 400), PublishTypeNotSupport("PublishTypeNotSupport", "The publish type of service can not support this operation", "该服务的发布方式并不支持本操作", 400), CustomParamMappingInvalid("CustomParamMappingInvalid", "All params name must be blank when custom mapping switch is closed", "关闭自定义参数映射开关后, 所有自定义名称必须为空", 400), + GenericInfoInvalid("GenericInfoInvalid", "generic config invalid", "泛型配置格式错误", 400), + UnSupportedDefaultValueType("UnSupportedDefaultValueType", "default value type not support", "默认值类型不支持", 400), + DefaultValueConfigInvaild("DefaultValueConfigInvaild", "default value config invaild", "默认值配置错误", 400), + DubboAttachmentConfigInvaild("DubboAttachmentConfigInvaild", "dubbo attachment config invaild", "隐式参数配置错误", 400), ; private String code; diff --git a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/service/IDubboService.java b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/service/IDubboService.java index 2214df58..5b45a422 100644 --- a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/service/IDubboService.java +++ b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/service/IDubboService.java @@ -59,6 +59,12 @@ public interface IDubboService { */ DubboInfo getDubboInfo(long objectId, String objectType); + + /** + * 判断方法是否有效 + */ + void processMethodWorks(DubboInfoDto dto); + /** * 更新Dubbo转换参数 * diff --git a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/service/IRegistryCenterService.java b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/service/IRegistryCenterService.java index abbda8c7..efa842b0 100644 --- a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/service/IRegistryCenterService.java +++ b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/service/IRegistryCenterService.java @@ -54,10 +54,9 @@ public interface IRegistryCenterService { * 所以该接口暂不需携带项目隔离信息 * * @param registryType - * @param registryAddr * @return */ - RegistryCenterDto findByTypeAndAddr(String registryType, String registryAddr); + RegistryCenterDto findByType(String registryType); /** * 通过类型获取项目下注册中心信息 @@ -93,4 +92,10 @@ public interface IRegistryCenterService { */ List getApplicationsFromConsul(String registryCenter); + /** + * 根据服务类型查询支持的注册中心类型 + * @param serviceType + * @return + */ + List describeRegistryTypesByServiceType(String serviceType); } diff --git a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/service/IRouteRuleProxyService.java b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/service/IRouteRuleProxyService.java index a5069e50..31b9097f 100644 --- a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/service/IRouteRuleProxyService.java +++ b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/service/IRouteRuleProxyService.java @@ -80,20 +80,6 @@ public interface IRouteRuleProxyService { List getRouteRuleProxyList(long gwId, long serviceId, String pattern, String sortKey, String sortValue, long offset, long limit); - /** - * 分页查询认证授权的已发布路由 - * - * @param gwId 网关id - * @param serviceId 服务id - * @param routeId 路由id - * @param auth 是否认证 - * @param offset 分页查询offset - * @param limit 分页查询limit - * @return - */ - List getAuthRouteProxy(long gwId, long serviceId, long routeId, boolean auth, long offset, - long limit); - /** * 查询已发布路由规则列表 * diff --git a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/service/IServiceInfoService.java b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/service/IServiceInfoService.java index 9b3f00f6..8690d686 100644 --- a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/service/IServiceInfoService.java +++ b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/service/IServiceInfoService.java @@ -150,4 +150,11 @@ public interface IServiceInfoService { * @return {@link List} 服务详情列表 */ List getServiceInfoList(List serviceIdList); + + /** + * 校验serviceType是否合法 + * @param serviceType + * @return + */ + ErrorCode checkServiceType(String serviceType); } diff --git a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/service/IServiceProxyService.java b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/service/IServiceProxyService.java index cbee190f..f2e3aab5 100644 --- a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/service/IServiceProxyService.java +++ b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/service/IServiceProxyService.java @@ -217,14 +217,6 @@ List getAuthServiceProxyByLimit(long gwId, long serviceId, lon */ String getBackendServiceSendToApiPlane(ServiceProxyDto serviceProxyDto); - /** - * 校验注册中心地址是否合法 - * - * @param registerCenterAddr - * @return - */ - ErrorCode checkEurekaRegistryCenterAddr(String registerCenterAddr); - /** * 获取subsetsName * diff --git a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/service/impl/DubboServiceImpl.java b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/service/impl/DubboServiceImpl.java index fbd2a22f..b291ca2f 100644 --- a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/service/impl/DubboServiceImpl.java +++ b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/service/impl/DubboServiceImpl.java @@ -2,21 +2,22 @@ import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.math.NumberUtils; import org.hango.cloud.dashboard.apiserver.dao.IDubboDao; import org.hango.cloud.dashboard.apiserver.dto.DubboInfoDto; +import org.hango.cloud.dashboard.apiserver.dto.DubboMetaDto; import org.hango.cloud.dashboard.apiserver.meta.DubboInfo; import org.hango.cloud.dashboard.apiserver.meta.RegistryCenterEnum; import org.hango.cloud.dashboard.apiserver.meta.errorcode.CommonErrorCode; import org.hango.cloud.dashboard.apiserver.meta.errorcode.ErrorCode; -import org.hango.cloud.dashboard.apiserver.service.IDubboService; -import org.hango.cloud.dashboard.apiserver.service.IRouteRuleInfoService; -import org.hango.cloud.dashboard.apiserver.service.IRouteRuleProxyService; -import org.hango.cloud.dashboard.apiserver.service.IServiceProxyService; +import org.hango.cloud.dashboard.apiserver.service.*; +import org.hango.cloud.dashboard.apiserver.util.ClassTypeUtil; import org.hango.cloud.dashboard.apiserver.util.Const; import org.hango.cloud.dashboard.apiserver.util.ZkClientUtils; +import org.hango.cloud.dashboard.envoy.dao.IRouteRuleProxyDao; import org.hango.cloud.dashboard.envoy.meta.RouteRuleInfo; import org.hango.cloud.dashboard.envoy.meta.RouteRuleProxyInfo; import org.hango.cloud.dashboard.envoy.meta.ServiceProxyInfo; @@ -27,11 +28,12 @@ import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; +import static org.hango.cloud.dashboard.apiserver.util.Const.POSITION_COOKIE; +import static org.hango.cloud.dashboard.apiserver.util.Const.POSITION_HEADER; + /** * @author zhangbj * @version 1.0 @@ -56,6 +58,12 @@ public class DubboServiceImpl implements IDubboService { @Autowired private IRouteRuleInfoService envoyRouteRuleInfoService; + @Autowired + private IRouteRuleProxyDao routeRuleProxyDao; + + @Autowired + private IDubboMetaService dubboMetaService; + @Override public long addDubboInfo(DubboInfoDto dto) { if (dto == null) { @@ -106,7 +114,14 @@ public void delete(long objectId, String objectType) { @Override public DubboInfoDto getDubboDto(long objectId, String objectType) { - return DubboInfoDto.toDto(getDubboInfo(objectId, objectType)); + DubboInfoDto dubboInfoDto = DubboInfoDto.toDto(getDubboInfo(objectId, objectType)); + //默认值json格式转换为json string以适配前端api + if (dubboInfoDto != null && dubboInfoDto.getParams() != null){ + for (DubboInfoDto.DubboParam param : dubboInfoDto.getParams()) { + param.setDefaultValue(JSONObject.toJSONString(param.getDefaultValue())); + } + } + return dubboInfoDto; } @Override @@ -122,6 +137,40 @@ public DubboInfo getDubboInfo(long objectId, String objectType) { return infoList.get(0); } + + @Override + public void processMethodWorks(DubboInfoDto dto) { + if (dto == null){ + return; + } + //获取已发布路由信息 + Map params = new HashMap<>(Const.DEFAULT_MAP_SIZE); + params.put("Id", dto.getObjectId()); + List routeRuleProxyInfos = routeRuleProxyDao.getRecordsByField(params); + if (CollectionUtils.isEmpty(routeRuleProxyInfos)){ + logger.error("未找到已发布路由信息,查询条件为 routeRuleProxyId:{}", dto.getObjectId()); + return; + } + RouteRuleProxyInfo proxyInfo = routeRuleProxyInfos.get(0); + //获取dubbo meta信息 + List dubboMetaDtos = dubboMetaService.findByCondition(proxyInfo.getGwId(), dto.getInterfaceName(), dto.getGroup(), dto.getVersion()); + //判断方法是否失效 + for (DubboMetaDto dubboMetaDto : dubboMetaDtos) { + if (dto.getMethod().equals(dubboMetaDto.getMethod()) && equalParams(dto.getParams(), dubboMetaDto.getParams())){ + dto.setMethodWorks(true); + return; + } + } + dto.setMethodWorks(false); + } + + private boolean equalParams(List dubboParams, List params){ + List dubboParamInfo = CollectionUtils.isEmpty(dubboParams) ? new ArrayList<>() : dubboParams.stream().map(DubboInfoDto.DubboParam::getValue).collect(Collectors.toList()); + List paramInfo = CollectionUtils.isEmpty(params) ? new ArrayList<>() : params; + return dubboParamInfo.equals(paramInfo); + } + + @Override public long updateDubboInfo(DubboInfoDto dto) { DubboInfo dtoFromDb = getDubboInfo(dto.getObjectId(), dto.getObjectType()); @@ -169,17 +218,12 @@ private ErrorCode checkAndCompleteEnvoyDubbo(DubboInfoDto dto) { logger.info("参数校验失败,该服务的发布方式并不支持本操作, 服务发布方式为 {}", serviceProxy.getRegistryCenterType()); return CommonErrorCode.PublishTypeNotSupport; } - List paramWithNoneKeyList = dto.getParams().stream().filter(f -> StringUtils.isBlank(f.getKey())).collect(Collectors.toList()); - //开启自定义参数映射开关后, 不允许自定义名称为空的存在 - if (dto.getCustomParamMapping() && !CollectionUtils.isEmpty(paramWithNoneKeyList)) { - logger.info("开启自定义参数映射开关后, 不允许自定义名称为空的存在 : {}", JSON.toJSONString(paramWithNoneKeyList)); - return CommonErrorCode.ParameterNull; - } - //关闭自定义参数映射开关后, 所有自定义名称必须为空 - //当dto.getParams()元素数与paramWithNoneKeyList 元素数相等,代表所有自定义名称为空 - if (!dto.getCustomParamMapping() && dto.getParams().size() != paramWithNoneKeyList.size()) { - logger.info("关闭自定义参数映射开关后, 所有自定义名称必须为空 : {}", JSON.toJSONString(dto)); - return CommonErrorCode.CustomParamMappingInvalid; + //自定义参数校验 + if (dto.getCustomParamMapping()){ + ErrorCode errorCode = checkCustomParamMapping(dto); + if (CommonErrorCode.Success != errorCode){ + return errorCode; + } } String backendService = serviceProxy.getBackendService(); String[] meta = ZkClientUtils.splitIgv(backendService); @@ -189,6 +233,136 @@ private ErrorCode checkAndCompleteEnvoyDubbo(DubboInfoDto dto) { return CommonErrorCode.Success; } + //自定义参数映射校验 + private ErrorCode checkCustomParamMapping(DubboInfoDto dto){ + List params = dto.getParams(); + for (DubboInfoDto.DubboParam param : params) { + //参数名不能为空 + if (StringUtils.isBlank(param.getKey())){ + logger.error("自定义参数映射不允许参数名为空 : {}", JSON.toJSONString(dto)); + return CommonErrorCode.ParameterNull; + } + //参数类型不能为空 + if (StringUtils.isBlank(param.getValue())){ + logger.error("自定义参数映射不允许参数类型为空 : {}", JSON.toJSONString(dto)); + return CommonErrorCode.ParameterNull; + } + //默认值类型校验 + if (param.getDefaultValue() != null){ + ErrorCode errorCode = checkDefaultValue(param.getValue(), param.getDefaultValue()); + if (!CommonErrorCode.Success.equals(errorCode)){ + return errorCode; + } + } + //泛型校验 + Boolean checkResult = checkGenericInfo(param.getGenericInfo()); + if (!checkResult){ + logger.error("无效的泛型配置 : {}", JSON.toJSONString(dto)); + return CommonErrorCode.GenericInfoInvalid; + } + } + //隐式参数校验 + if (!checkDubboAttachment(dto.getDubboAttachment())){ + return CommonErrorCode.DubboAttachmentConfigInvaild; + } + return CommonErrorCode.Success; + } + + private Boolean checkDubboAttachment(List dubboAttachmentDtos){ + if (CollectionUtils.isEmpty(dubboAttachmentDtos)){ + return Boolean.TRUE; + } + for (DubboInfoDto.DubboAttachmentDto dubboAttachmentDto : dubboAttachmentDtos) { + String paramPosition = dubboAttachmentDto.getParamPosition(); + if (StringUtils.isBlank(paramPosition)){ + logger.error("隐式参数来源不能为空 : {}", JSON.toJSONString(dubboAttachmentDto)); + return Boolean.FALSE; + } + if (!POSITION_COOKIE.equalsIgnoreCase(paramPosition) && !POSITION_HEADER.equalsIgnoreCase(paramPosition)){ + logger.error("隐式参数来源错误 : {}", paramPosition); + return Boolean.FALSE; + } + if (StringUtils.isBlank(dubboAttachmentDto.getClientParamName())){ + logger.error("参数名不能为空 : {}", JSON.toJSONString(dubboAttachmentDto)); + return Boolean.FALSE; + } + + if (StringUtils.isBlank(dubboAttachmentDto.getServerParamName())){ + logger.error("隐式参数名不能为空 : {}", JSON.toJSONString(dubboAttachmentDto)); + return Boolean.FALSE; + } + } + long clientCount = dubboAttachmentDtos.stream().map(o -> o.getParamPosition() + o.getClientParamName()).distinct().count(); + if (clientCount != dubboAttachmentDtos.size()){ + logger.error("参数名重复 : {}", JSON.toJSONString(dubboAttachmentDtos)); + + return Boolean.FALSE; + } + long serverCount = dubboAttachmentDtos.stream().map(DubboInfoDto.DubboAttachmentDto::getServerParamName).distinct().count(); + if (serverCount != dubboAttachmentDtos.size()){ + logger.error("隐式参数名重复 : {}", JSON.toJSONString(dubboAttachmentDtos)); + return Boolean.FALSE; + } + return Boolean.TRUE; + } + + private ErrorCode checkDefaultValue(String javaType, Object defaultValue){ + if (!ClassTypeUtil.isMapClass(javaType) && !ClassTypeUtil.isCollectionClass(javaType) && !ClassTypeUtil.isPrimitive(javaType) && !ClassTypeUtil.isWrapperClass(javaType)){ + logger.error("默认值类型不支持 : {}", javaType); + return CommonErrorCode.UnSupportedDefaultValueType; + } + //boolean类型校验 + if (ClassTypeUtil.isBooleanClass(javaType) && !(defaultValue instanceof Boolean)){ + return CommonErrorCode.DefaultValueConfigInvaild; + } + //数值类型校验 + if (ClassTypeUtil.isNumberClass(javaType) && !(defaultValue instanceof Number)){ + return CommonErrorCode.DefaultValueConfigInvaild; + } + //字符串类型校验 + if (ClassTypeUtil.isStringClass(javaType) && !(defaultValue instanceof String)){ + return CommonErrorCode.DefaultValueConfigInvaild; + } + //集合类型校验 + if (ClassTypeUtil.isCollectionClass(javaType) && !(defaultValue instanceof Collection)){ + return CommonErrorCode.DefaultValueConfigInvaild; + } + //字典类型校验 + if (ClassTypeUtil.isMapClass(javaType) && !(defaultValue instanceof Map)){ + return CommonErrorCode.DefaultValueConfigInvaild; + } + //兜底校验 + String str = JSONObject.toJSONString(defaultValue); + try { + JSONObject.parseObject(str, ClassTypeUtil.getClassForName(javaType)); + } catch (Exception e) { + logger.error("默认值配置错误,type:{}, defaultValue:{}", javaType, str); + return CommonErrorCode.DefaultValueConfigInvaild; + } + return CommonErrorCode.Success; + } + + public Boolean checkGenericInfo(String genericInfo){ + if (StringUtils.isBlank(genericInfo)){ + return Boolean.TRUE; + } + String[] genericConfigs = genericInfo.split(","); + for (String genericConfig : genericConfigs) { + if (StringUtils.isBlank(genericConfig)) { + return Boolean.FALSE; + } + if (!genericConfig.startsWith(".")){ + return Boolean.FALSE; + } + String[] split = genericConfig.split(":"); + if (split.length != 2){ + return Boolean.FALSE; + } + } + return Boolean.TRUE; + } + + private ErrorCode checkAndCompleteG0Dubbo(DubboInfoDto dto) { //暂未实现 return CommonErrorCode.Success; @@ -236,7 +410,53 @@ public EnvoyRouteRuleHeaderOperationDto getDubboHeaderOperation(DubboInfoDto dto add.put(Const.HEADER_DUBBO_GROUP, dto.getGroup()); add.put(Const.HEADER_DUBBO_VERSION, dto.getVersion()); add.put(Const.HEADER_DUBBO_PARAMS, dto.getParamToStr()); + add.put(Const.HEADER_DUBBO_PARAM_SOURCE, dto.getParamSource()); add.put(Const.HEADER_DUBBO_CUSTOM_PARAMS_MAPPING_SWITCH, BooleanUtils.toStringTrueFalse(dto.getCustomParamMapping())); + List params = dto.getParams(); + if (!CollectionUtils.isEmpty(params)){ + List genericInfoList = params.stream().map(DubboInfoDto.DubboParam::getGenericInfo).collect(Collectors.toList()); + if (!CollectionUtils.isEmpty(genericInfoList)){ + add.put(Const.HEADER_DUBBO_GENERIC, StringUtils.join(genericInfoList, ";")); + } + if (dto.getCustomParamMapping()){ + List defaultValueList = params.stream().map(o -> parseDefaultValue(o.getValue(), o.getDefaultValue())).collect(Collectors.toList()); + if (!CollectionUtils.isEmpty(defaultValueList)){ + add.put(Const.HEADER_DUBBO_DEFAULT, JSONObject.toJSONString(defaultValueList)); + } + List requiredList = params.stream().map(o -> o.isRequired() ? "T" : "F").collect(Collectors.toList()); + if (!CollectionUtils.isEmpty(requiredList)){ + add.put(Const.HEADER_DUBBO_REQUIRED, StringUtils.join(requiredList, ";")); + } + } + + } + List dubboAttachment = dto.getDubboAttachment(); + if (!CollectionUtils.isEmpty(dubboAttachment)){ + List headers = new ArrayList<>(); + List cookies = new ArrayList<>(); + for (DubboInfoDto.DubboAttachmentDto dubboAttachmentDto : dubboAttachment) { + String paramPosition = dubboAttachmentDto.getParamPosition(); + if (POSITION_HEADER.equalsIgnoreCase(paramPosition)){ + headers.add(dubboAttachmentDto.getClientParamName() + ":" + dubboAttachmentDto.getServerParamName()); + }else if (POSITION_COOKIE.equalsIgnoreCase(paramPosition)){ + cookies.add(dubboAttachmentDto.getClientParamName() + ":" + dubboAttachmentDto.getServerParamName()); + + } + } + if (!CollectionUtils.isEmpty(headers)){ + add.put(Const.HEADER_DUBBO_ATTACTMENT_HEADER, String.join(";", headers)); + } + if (!CollectionUtils.isEmpty(cookies)){ + add.put(Const.HEADER_DUBBO_ATTACTMENT_COOKIE, String.join(";", cookies)); + } + } return headerOperation; } + + public Object parseDefaultValue(String typeString, Object value){ + if (value == null && ClassTypeUtil.PrimitiveTypeEnum.isPrimitiveType(typeString)){ + return ClassTypeUtil.PrimitiveTypeEnum.getDefaultValueByName(typeString); + } + return value; + } } diff --git a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/service/impl/RegistryCenterServiceImpl.java b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/service/impl/RegistryCenterServiceImpl.java index 8017c8e6..975f23b4 100644 --- a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/service/impl/RegistryCenterServiceImpl.java +++ b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/service/impl/RegistryCenterServiceImpl.java @@ -2,12 +2,14 @@ import com.ecwid.consul.v1.ConsulClient; import com.google.common.collect.Maps; +import com.google.common.collect.Sets; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.math.NumberUtils; import org.hango.cloud.dashboard.apiserver.dao.IRegistryCenterDao; import org.hango.cloud.dashboard.apiserver.dto.RegistryCenterDto; import org.hango.cloud.dashboard.apiserver.meta.RegistryCenterEnum; import org.hango.cloud.dashboard.apiserver.meta.RegistryCenterInfo; +import org.hango.cloud.dashboard.apiserver.meta.ServiceType; import org.hango.cloud.dashboard.apiserver.meta.errorcode.CommonErrorCode; import org.hango.cloud.dashboard.apiserver.meta.errorcode.ErrorCode; import org.hango.cloud.dashboard.apiserver.service.IRegistryCenterService; @@ -19,9 +21,7 @@ import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; +import java.util.*; import java.util.stream.Collectors; /** @@ -41,6 +41,13 @@ public class RegistryCenterServiceImpl implements IRegistryCenterService { @Autowired private IRegistryCenterDao registryCenterDao; + private static final Map> SERVICE_TYPE_2_REGISTER_TYPES_MAP = new HashMap<>(); + + static { + SERVICE_TYPE_2_REGISTER_TYPES_MAP.put(ServiceType.dubbo.name(), Sets.newHashSet(RegistryCenterEnum.Zookeeper)); + SERVICE_TYPE_2_REGISTER_TYPES_MAP.put(ServiceType.webservice.name(), Sets.newHashSet(RegistryCenterEnum.Kubernetes)); + SERVICE_TYPE_2_REGISTER_TYPES_MAP.put(ServiceType.http.name(), Sets.newHashSet(RegistryCenterEnum.Nacos, RegistryCenterEnum.Kubernetes, RegistryCenterEnum.Eureka)); + } @Override public void saveRegistryCenter(RegistryCenterDto registryCenter) { RegistryCenterInfo centerInfo = RegistryCenterDto.trans(registryCenter); @@ -133,7 +140,7 @@ public List findByTypeAndProject(String registryType, long pr } @Override - public RegistryCenterDto findByTypeAndAddr(String registryType, String registryAddr) { + public RegistryCenterDto findByType(String registryType) { RegistryCenterEnum registryCenterEnum = RegistryCenterEnum.get(registryType); if (registryCenterEnum == null) { logger.info("Error Registry Type {}", registryType); @@ -146,10 +153,6 @@ public RegistryCenterDto findByTypeAndAddr(String registryType, String registryA HashMap param = Maps.newHashMap(); param.put("registryType", registryType); - if (StringUtils.isNotBlank(registryAddr)) { - param.put("registryAddr", registryAddr); - } - List records = registryCenterDao.getRecordsByField(param); if (CollectionUtils.isEmpty(records)) { return null; @@ -190,4 +193,28 @@ public List getApplicationsFromConsul(String registryCenter) { ConsulClient defaultConsulClient = ConsulClientUtils.getDefaultConsulClient(registryCenter); return ConsulClientUtils.getApplications(defaultConsulClient, ConsulClientUtils.getDataCenter(registryCenter)); } + + @Override + public List describeRegistryTypesByServiceType(String serviceType) { + List registryCenterInfos = registryCenterDao.findAll(); + List currentRegistryList = CollectionUtils.isEmpty(registryCenterInfos) ? new ArrayList<>() + : registryCenterInfos.stream().map(RegistryCenterInfo::getRegistryType).collect(Collectors.toList()); + //k8s注册中心不在注册中心表中,且默认支持 + currentRegistryList.add(RegistryCenterEnum.Kubernetes.getType()); + return filterAndSort(serviceType, currentRegistryList); + } + + private static List filterAndSort(String serviceType, List registryList) { + Set registryTypeSet = registryList.stream() + .map(RegistryCenterEnum::get) + .collect(Collectors.toSet()); + + registryTypeSet.add(RegistryCenterEnum.Kubernetes); + return registryTypeSet.stream() + .filter(registryType -> SERVICE_TYPE_2_REGISTER_TYPES_MAP.containsKey(serviceType) + && SERVICE_TYPE_2_REGISTER_TYPES_MAP.get(serviceType).contains(registryType)) + .sorted(Comparator.comparingInt(RegistryCenterEnum::getOrder)) + .map(RegistryCenterEnum::getType) + .collect(Collectors.toList()); + } } diff --git a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/service/impl/RouteRuleProxyServiceImpl.java b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/service/impl/RouteRuleProxyServiceImpl.java index 3afca960..85e0c933 100644 --- a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/service/impl/RouteRuleProxyServiceImpl.java +++ b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/service/impl/RouteRuleProxyServiceImpl.java @@ -1,7 +1,6 @@ package org.hango.cloud.dashboard.apiserver.service.impl; import com.alibaba.fastjson.JSON; -import com.google.common.collect.Lists; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.math.NumberUtils; @@ -11,42 +10,24 @@ import org.hango.cloud.dashboard.apiserver.meta.errorcode.CommonErrorCode; import org.hango.cloud.dashboard.apiserver.meta.errorcode.ErrorCode; import org.hango.cloud.dashboard.apiserver.meta.errorcode.ErrorCodeEnum; -import org.hango.cloud.dashboard.apiserver.service.IDubboService; -import org.hango.cloud.dashboard.apiserver.service.IGatewayInfoService; -import org.hango.cloud.dashboard.apiserver.service.IRouteRuleInfoService; -import org.hango.cloud.dashboard.apiserver.service.IRouteRuleProxyService; -import org.hango.cloud.dashboard.apiserver.service.IServiceInfoService; -import org.hango.cloud.dashboard.apiserver.service.IServiceProxyService; +import org.hango.cloud.dashboard.apiserver.service.*; import org.hango.cloud.dashboard.apiserver.util.Const; import org.hango.cloud.dashboard.apiserver.web.holder.ProjectTraceHolder; import org.hango.cloud.dashboard.envoy.core.constant.PluginConstant; import org.hango.cloud.dashboard.envoy.dao.IRouteRuleProxyDao; -import org.hango.cloud.dashboard.envoy.meta.BindingPluginInfo; -import org.hango.cloud.dashboard.envoy.meta.EnvoyDestinationInfo; -import org.hango.cloud.dashboard.envoy.meta.EnvoyPluginBindingInfo; -import org.hango.cloud.dashboard.envoy.meta.EnvoyVirtualHostInfo; -import org.hango.cloud.dashboard.envoy.meta.RouteRuleInfo; -import org.hango.cloud.dashboard.envoy.meta.RouteRuleProxyInfo; -import org.hango.cloud.dashboard.envoy.meta.ServiceProxyInfo; +import org.hango.cloud.dashboard.envoy.meta.*; import org.hango.cloud.dashboard.envoy.service.IEnvoyGatewayService; import org.hango.cloud.dashboard.envoy.service.IEnvoyPluginInfoService; import org.hango.cloud.dashboard.envoy.service.IEnvoyWebServiceService; import org.hango.cloud.dashboard.envoy.service.IGetFromApiPlaneService; -import org.hango.cloud.dashboard.envoy.web.dto.EnvoyDestinationDto; -import org.hango.cloud.dashboard.envoy.web.dto.EnvoyRouteRuleHeaderOperationDto; -import org.hango.cloud.dashboard.envoy.web.dto.EnvoySubsetDto; -import org.hango.cloud.dashboard.envoy.web.dto.RouteRuleProxyDto; -import org.hango.cloud.dashboard.envoy.web.dto.VirtualClusterDto; +import org.hango.cloud.dashboard.envoy.service.ITrafficMarkService; +import org.hango.cloud.dashboard.envoy.web.dto.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; /** @@ -89,6 +70,8 @@ public class RouteRuleProxyServiceImpl implements IRouteRuleProxyService { private IEnvoyWebServiceService webServiceService; + @Autowired + private ITrafficMarkService trafficMarkService; @Override public ErrorCode checkPublishParam(RouteRuleProxyDto routeRuleProxyDto) { RouteRuleInfo routeRuleInfo = routeRuleInfoService.getRouteRuleInfoById(routeRuleProxyDto.getRouteRuleId()); @@ -377,9 +360,8 @@ public long addRouteRuleProxy(RouteRuleProxyInfo routeRuleProxyInfo) { public List getRouteRuleProxyList(long gwId, long serviceId, String pattern, String sortKey, String sortValue, long offset, long limit) { - long projectId = ProjectTraceHolder.getProId(); - List routeIds = Collections.EMPTY_LIST; + List routeIds = Collections.emptyList(); if (StringUtils.isNotBlank(pattern)) { routeIds = routeRuleInfoService.getRouteRuleInfoByPattern(pattern, -1, serviceId, projectId, "", "", 0, 1000).stream().map(RouteRuleInfo::getId) @@ -392,21 +374,6 @@ public List getRouteRuleProxyList(long gwId, long serviceId, limit); } - @Override - public List getAuthRouteProxy(final long gwId, final long serviceId, final long routeId, - final boolean auth, final long offset, final long limit) { - if (!auth) { - if (routeId == 0) { - return getRouteRuleProxyList(gwId, serviceId, StringUtils.EMPTY, Const.CONST_PRIORITY, "", offset, - limit); - } - List routeRuleProxyList = Lists.newArrayList(); - routeRuleProxyList.add(getRouteRuleProxy(gwId, routeId)); - return routeRuleProxyList; - } - return routeRuleProxyDao.getRouteRuleProxyList(gwId, serviceId, ProjectTraceHolder.getProId(), routeId, - Collections.emptyList(), offset, limit); - } @Override public List getRouteRuleProxyList(long serviceId) { @@ -573,6 +540,10 @@ private void updateRouteRulePublishStatus(long routeRuleId) { @Override public ErrorCode checkDeleteRouteRuleProxy(long gwId, long routeRuleId, List serviceIds) { + List trafficMarkInfos = trafficMarkService.getTrafficColorRulesByRouteRuleId(routeRuleId); + if (CollectionUtils.isNotEmpty(trafficMarkInfos)) { + return CommonErrorCode.RouteHasTrafficMarkRules; + } Map params = new HashMap<>(Const.DEFAULT_MAP_SIZE); params.put("gwId", gwId); params.put("routeRuleId", routeRuleId); diff --git a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/service/impl/ServiceInfoImpl.java b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/service/impl/ServiceInfoImpl.java index 4363cdad..a7dc8f98 100644 --- a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/service/impl/ServiceInfoImpl.java +++ b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/service/impl/ServiceInfoImpl.java @@ -6,6 +6,7 @@ import org.hango.cloud.dashboard.apiserver.dao.ServiceInfoDao; import org.hango.cloud.dashboard.apiserver.dto.servicedto.ServiceInfoDto; import org.hango.cloud.dashboard.apiserver.meta.ServiceInfo; +import org.hango.cloud.dashboard.apiserver.meta.ServiceType; import org.hango.cloud.dashboard.apiserver.meta.errorcode.CommonErrorCode; import org.hango.cloud.dashboard.apiserver.meta.errorcode.ErrorCode; import org.hango.cloud.dashboard.apiserver.service.IServiceInfoService; @@ -243,4 +244,12 @@ public List getServiceInfoList(List serviceIdList) { List serviceInfoList = serviceInfoDao.getServiceInfoList(serviceIdList); return CollectionUtils.isEmpty(serviceIdList) ? Lists.newArrayList() : serviceInfoList; } + + @Override + public ErrorCode checkServiceType(String serviceType) { + if (ServiceType.getServiceTypeByName(serviceType) == null) { + return CommonErrorCode.ServiceTypeInvalid; + } + return CommonErrorCode.Success; + } } \ No newline at end of file diff --git a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/util/ClassTypeUtil.java b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/util/ClassTypeUtil.java new file mode 100644 index 00000000..51a82953 --- /dev/null +++ b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/util/ClassTypeUtil.java @@ -0,0 +1,166 @@ +package org.hango.cloud.dashboard.apiserver.util; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.util.*; +import java.util.stream.Stream; + +/** + * @Author: zhufengwei.sx + * @Date: 2022/4/8 13:53 + **/ +@Component +public class ClassTypeUtil { + + private static final Logger logger = LoggerFactory.getLogger(ClassTypeUtil.class); + + private static final List MAP_CLASS = Arrays.asList(Map.class.getName(), HashMap.class.getName(), + TreeMap.class.getName(), LinkedHashMap.class.getName()); + + private static final List SET_CLASS = Arrays.asList(Set.class.getName(), HashSet.class.getName(), + TreeSet.class.getName(), LinkedHashSet.class.getName()); + + private static final List LIST_CLASS = Arrays.asList(List.class.getName(), ArrayList.class.getName(), + LinkedList.class.getName()); + + private static final List WRAPPER_CLASS = Arrays.asList(Integer.class.getName(), Boolean.class.getName(), Long.class.getName(), + Short.class.getName(), Double.class.getName(), Float.class.getName(), Character.class.getName(), Byte.class.getName(), String.class.getName()); + + + public enum PrimitiveTypeEnum { + + BOOLEAN("boolean", boolean.class, false), + CHAR("char", char.class, "\u0000"), + BYTE("byte", byte.class, 0), + SHORT("short", short.class, 0), + INT("int", int.class, 0), + LONG("long", long.class, 0), + FLOAT("float", float.class, 0.0f), + DOUBLE("double", double.class, 0.0d); + + /** + * 类名 + */ + private String className; + /** + * java类 + */ + private Class javaClass; + + /** + * 对应Prometheus类型 + */ + private Object defaultValue; + + + PrimitiveTypeEnum(String className, Class javaClass, Object defaultValue) { + this.className = className; + this.javaClass = javaClass; + this.defaultValue = defaultValue; + } + + public static boolean isPrimitiveType(String javaType){ + return Stream.of(values()).map(PrimitiveTypeEnum::getClassName).anyMatch(o -> o.equals(javaType)); + } + + public static PrimitiveTypeEnum getByName(String className){ + return Stream.of(values()) + .filter(o -> o.getClassName().equals(className)) + .findFirst() + .orElse(null); + } + + + public static Object getDefaultValueByName(String className){ + PrimitiveTypeEnum matchEnum = getByName(className); + return matchEnum == null ? null : matchEnum.getDefaultValue(); + } + + public static Class getClassByName(String className){ + PrimitiveTypeEnum matchEnum = getByName(className); + return matchEnum == null ? null : matchEnum.getJavaClass(); + } + + public String getClassName() { + return className; + } + + public void setClassName(String className) { + this.className = className; + } + + public Class getJavaClass() { + return javaClass; + } + + public void setJavaClass(Class javaClass) { + this.javaClass = javaClass; + } + + public Object getDefaultValue() { + return defaultValue; + } + + public void setDefaultValue(Object defaultValue) { + this.defaultValue = defaultValue; + } + } + + + public static boolean isPrimitive(String typeString){ + return PrimitiveTypeEnum.isPrimitiveType(typeString); + } + + public static boolean isWrapperClass(String typeString){ + return WRAPPER_CLASS.contains(typeString); + } + + public static boolean isCollectionClass(String typeString) { + return SET_CLASS.contains(typeString) || LIST_CLASS.contains(typeString); + } + + public static boolean isMapClass(String typeString) { + return MAP_CLASS.contains(typeString); + } + + public static boolean isBooleanClass(String typeString){ + return Arrays.asList(boolean.class.getName(), Boolean.class.getName()).contains(typeString); + } + + public static boolean isNumberClass(String typeString){ + return Arrays.asList( + byte.class.getName(), + short.class.getName(), + int.class.getName(), + long.class.getName(), + float.class.getName(), + double.class.getName(), + Integer.class.getName(), + Short.class.getName(), + Double.class.getName(), + Float.class.getName(), + Byte.class.getName(), + Long.class.getName() + ).contains(typeString); + } + + public static boolean isStringClass(String typeString){ + return Arrays.asList( + char.class.getName(), + String.class.getName(), + Character.class.getName() + ).contains(typeString); + } + + + public static Class getClassForName(String typeString) throws Exception{ + if (isPrimitive(typeString)){ + return PrimitiveTypeEnum.getClassByName(typeString); + } + return Class.forName(typeString); + } + + +} diff --git a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/util/Const.java b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/util/Const.java index ae7b5984..c34184d2 100644 --- a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/util/Const.java +++ b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/util/Const.java @@ -176,6 +176,8 @@ public class Const { public static final String POSITION_HEADER = "header"; + public static final String POSITION_COOKIE = "cookie"; + public static final String POSITION_DUBBO_PARAM = "dubbo_param"; public static final String REQUEST_EXAMPLE = "REQUEST_EXAMPLE"; @@ -445,6 +447,8 @@ public class Const { public static final Set HTTP_STATUS_CODE = new HashSet(Arrays.asList(100, 101, 103, 200, 201, 202, 203, 204, 205, 206, 300, 301, 302, 303, 304, 307, 308, 400, 401, 402, 403, 404, 405, 406, 407, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 422, 425, 426, 428, 429, 431, 451, 500, 502, 503, 504, 505, 511)); public static final String GLOBAL_PLUGIN_TRACE = "neTraceFileLog"; + public static final String PLUGIN_NAME_RETRY = "com.netease.resty"; + public static final String PLUGIN_NAME_TRAFFIC_MARK = "proxy.filters.http.traffic_mark"; /** * 流量染色插件的plugin_type */ @@ -462,6 +466,12 @@ public class Const { public static final String HEADER_DUBBO_GROUP = "x-dubbo-group"; public static final String HEADER_DUBBO_VERSION = "x-dubbo-version"; public static final String HEADER_DUBBO_PARAMS = "x-dubbo-params"; + public static final String HEADER_DUBBO_GENERIC = "x-dubbo-generic"; + public static final String HEADER_DUBBO_REQUIRED = "x-dubbo-required"; + public static final String HEADER_DUBBO_DEFAULT = "x-dubbo-default"; + public static final String HEADER_DUBBO_PARAM_SOURCE = "x-dubbo-source"; + public static final String HEADER_DUBBO_ATTACTMENT_HEADER = "x-dubbo-header"; + public static final String HEADER_DUBBO_ATTACTMENT_COOKIE = "x-dubbo-cookie"; public static final String HEADER_DUBBO_CUSTOM_PARAMS_MAPPING_SWITCH = "x-dubbo-custom-param-mapping-switch"; public static final String DUBBO_SERVICE_SUFFIX = ".dubbo"; public static final String DUBBO_META_REFRESH_KEY_TEMPLATE = "api-gateway-dubbo-org.hango.cloud.dashboard.meta-%d-%s"; diff --git a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/web/controller/dubbo/DubboController.java b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/web/controller/dubbo/DubboController.java index 0160ca1e..485ad57f 100644 --- a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/web/controller/dubbo/DubboController.java +++ b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/web/controller/dubbo/DubboController.java @@ -18,12 +18,7 @@ import org.hango.cloud.dashboard.apiserver.web.holder.UserPermissionHolder; import org.hango.cloud.dashboard.common.distributedlock.MethodReentrantLock; import org.hango.cloud.gdashboard.api.dto.DubboParamInfoDto; -import org.hango.cloud.gdashboard.api.meta.ApiInfo; -import org.hango.cloud.gdashboard.api.meta.ApiParamType; -import org.hango.cloud.gdashboard.api.meta.DubboParamInfo; -import org.hango.cloud.gdashboard.api.meta.DubboType; -import org.hango.cloud.gdashboard.api.meta.OperationLog; -import org.hango.cloud.gdashboard.api.meta.ServiceType; +import org.hango.cloud.gdashboard.api.meta.*; import org.hango.cloud.gdashboard.api.meta.errorcode.ApiErrorCode; import org.hango.cloud.gdashboard.api.meta.errorcode.CommonApiErrorCode; import org.hango.cloud.gdashboard.api.service.IApiInfoService; @@ -35,12 +30,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.CollectionUtils; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import java.util.ArrayList; import java.util.HashMap; @@ -234,6 +224,7 @@ public String describeEnvoyDubbo(@RequestParam(value = "ObjectId") long objectId @RequestParam(value = "ObjectType", required = false, defaultValue = Const.ROUTE) String objectType) { logger.info("进行路由Dubbo转换查询操作,,关联类型:{} ,关联ID:{} , 操作人:{}", objectType, objectId, UserPermissionHolder.getAccountId()); DubboInfoDto dubboDto = dubboService.getDubboDto(objectId, objectType); + dubboService.processMethodWorks(dubboDto); return apiReturnSuccess(dubboDto); } diff --git a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/web/controller/published/ServiceProxyController.java b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/web/controller/published/ServiceProxyController.java index 586ec141..a9a41626 100644 --- a/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/web/controller/published/ServiceProxyController.java +++ b/gateway-portal/src/main/java/org/hango/cloud/dashboard/apiserver/web/controller/published/ServiceProxyController.java @@ -7,12 +7,10 @@ import org.hango.cloud.dashboard.apiserver.dto.RegistryCenterDto; import org.hango.cloud.dashboard.apiserver.dto.auditdto.ResourceDataDto; import org.hango.cloud.dashboard.apiserver.meta.GatewayInfo; -import org.hango.cloud.dashboard.apiserver.meta.RegistryCenterEnum; import org.hango.cloud.dashboard.apiserver.meta.errorcode.CommonErrorCode; import org.hango.cloud.dashboard.apiserver.meta.errorcode.ErrorCode; import org.hango.cloud.dashboard.apiserver.meta.errorcode.ErrorCodeEnum; import org.hango.cloud.dashboard.apiserver.service.IGatewayInfoService; -import org.hango.cloud.dashboard.apiserver.service.IGatewayProjectService; import org.hango.cloud.dashboard.apiserver.service.IRegistryCenterService; import org.hango.cloud.dashboard.apiserver.service.IServiceInfoService; import org.hango.cloud.dashboard.apiserver.service.IServiceProxyService; @@ -72,23 +70,27 @@ public class ServiceProxyController extends AbstractController { private IGetFromApiPlaneService getFromApiPlaneService; @Autowired private IServiceInfoService serviceInfoService; - @Autowired - private IGatewayProjectService gatewayProjectService; + @RequestMapping(params = {"Action=DescribeRegistryTypes"}, method = RequestMethod.GET) + public String describeRegistryTypes(@RequestParam(value = "ServiceType") String serviceType) { + ErrorCode errorCode = serviceInfoService.checkServiceType(serviceType); + if (!ErrorCodeEnum.Success.getCode().equals(errorCode.getCode())) { + return apiReturn(errorCode); + } + Map result = new HashMap<>(Const.DEFAULT_MAP_SIZE); + List registryTypes = registryCenterService.describeRegistryTypesByServiceType(serviceType); + result.put("RegistryTypes", registryTypes); + return apiReturn(HttpStatus.SC_OK, StringUtils.EMPTY, StringUtils.EMPTY, result); + } @RequestMapping(params = {"Action=DescribeServiceListByGw"}, method = RequestMethod.GET) public String describeServiceList(@RequestParam(value = "GwId") long gwId, @RequestParam(value = "Name", required = false) String name, @RequestParam(value = "RegistryCenterType") String registryCenterType, - @RequestParam(value = "RegistryCenterAddr", required = false) String registryCenterAddr, final HttpServletRequest request) { logger.info("查询网关id:{}下的所有发布服务name:{}", gwId, name); Map result = new HashMap<>(Const.DEFAULT_MAP_SIZE); - // eureka有多个注册中心地址,需要拆分查询数据库 - if (RegistryCenterEnum.Eureka.getType().equals(registryCenterType)) { - registryCenterAddr = registryCenterAddr.split(",")[0]; - } - RegistryCenterDto registry = registryCenterService.findByTypeAndAddr(registryCenterType, registryCenterAddr); + RegistryCenterDto registry = registryCenterService.findByType(registryCenterType); String registryAlias = registry == null ? StringUtils.EMPTY : registry.getRegistryAlias(); Map serviceFilters = serviceProxyService.createServiceFilters(registry); List serviceListFromApiPlane = diff --git a/gateway-portal/src/main/java/org/hango/cloud/dashboard/common/distributedlock/MethodReentrantLockAspect.java b/gateway-portal/src/main/java/org/hango/cloud/dashboard/common/distributedlock/MethodReentrantLockAspect.java index 1ca0e214..8780c26e 100644 --- a/gateway-portal/src/main/java/org/hango/cloud/dashboard/common/distributedlock/MethodReentrantLockAspect.java +++ b/gateway-portal/src/main/java/org/hango/cloud/dashboard/common/distributedlock/MethodReentrantLockAspect.java @@ -15,6 +15,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; @@ -105,6 +106,9 @@ private String getValue(Object o) { json = "InputStream"; } else if (o instanceof OutputStream) { json = "OutputStream"; + } else if (o instanceof MultipartFile) { + MultipartFile file = (MultipartFile) o; + json = "MultipartFile:" + file.getOriginalFilename(); } if (json != null) { return json; diff --git a/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/dao/ITrafficMarkDao.java b/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/dao/ITrafficMarkDao.java index 4744cf1c..62dfd5be 100644 --- a/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/dao/ITrafficMarkDao.java +++ b/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/dao/ITrafficMarkDao.java @@ -35,4 +35,6 @@ public interface ITrafficMarkDao extends IBaseDao { * @return */ long getCount(); + + List getTrafficColorRulesByRouteRuleId(long routeRuleId); } diff --git a/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/dao/impl/TrafficMarkDaoImpl.java b/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/dao/impl/TrafficMarkDaoImpl.java index ccaf4ea1..c7c78e90 100644 --- a/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/dao/impl/TrafficMarkDaoImpl.java +++ b/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/dao/impl/TrafficMarkDaoImpl.java @@ -1,6 +1,7 @@ package org.hango.cloud.dashboard.envoy.dao.impl; import org.apache.commons.lang3.StringUtils; +import org.apache.poi.ss.formula.functions.T; import org.hango.cloud.dashboard.apiserver.dao.impl.BaseDao; import org.hango.cloud.dashboard.apiserver.util.Const; import org.hango.cloud.dashboard.envoy.dao.ITrafficMarkDao; @@ -14,12 +15,15 @@ import org.springframework.jdbc.support.GeneratedKeyHolder; import org.springframework.jdbc.support.KeyHolder; import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** * 网关流量染色相关dao @@ -34,8 +38,8 @@ public class TrafficMarkDaoImpl extends BaseDao implements ITrafficMarkDao { @Override public long add(TrafficMarkInfo trafficMarkInfo) { KeyHolder keyHolder = new GeneratedKeyHolder(); - String sql = "insert into apigw_gportal_entry_traffic_policy (gw_id, gw_name, protocol, traffic_color_name, service_name, route_rule_name, create_time, update_time, route_rule_id, enable_status, traffic_match, color_tag, param) " - + " values (:gwId, :gwName, :protocol, :trafficColorName, :serviceName, :routeRuleName, :createTime, :updateTime, :routeRuleId, :enableStatus, :trafficMatch, :colorTag, :trafficParam)"; + String sql = "insert into apigw_gportal_entry_traffic_policy (gw_id, gw_name, protocol, traffic_color_name, service_name, route_rule_names, create_time, update_time, route_rule_ids, enable_status, traffic_match, color_tag, param) " + + " values (:gwId, :gwName, :protocol, :trafficColorName, :serviceName, :routeRuleNames, :createTime, :updateTime, :routeRuleIds, :enableStatus, :trafficMatch, :colorTag, :trafficParam)"; SqlParameterSource ps = new BeanPropertySqlParameterSource(trafficMarkInfo); namedParameterJdbcTemplate.update(sql, ps, keyHolder); logger.info("add TrafficMarkInfo: {}", trafficMarkInfo); @@ -44,8 +48,8 @@ public long add(TrafficMarkInfo trafficMarkInfo) { @Override public long update(TrafficMarkInfo trafficMarkInfo) { - String sql = "update apigw_gportal_entry_traffic_policy set gw_id=:gwId, gw_name=:gwName, update_time=:updateTime, route_rule_id=:routeRuleId, enable_status=:enableStatus, traffic_match=:trafficMatch, color_tag=:colorTag," + - " param=:trafficParam, service_name=:serviceName, route_rule_name=:routeRuleName, traffic_color_name=:trafficColorName where id=:id"; + String sql = "update apigw_gportal_entry_traffic_policy set gw_id=:gwId, gw_name=:gwName, update_time=:updateTime, route_rule_ids=:routeRuleIds, enable_status=:enableStatus, traffic_match=:trafficMatch, color_tag=:colorTag," + + " param=:trafficParam, service_name=:serviceName, route_rule_names=:routeRuleNames, traffic_color_name=:trafficColorName where id=:id"; SqlParameterSource ps = new BeanPropertySqlParameterSource(trafficMarkInfo); logger.info("update TrafficMarkInfo: {}", trafficMarkInfo); return namedParameterJdbcTemplate.update(sql, ps); @@ -94,6 +98,31 @@ public long getCount() { return namedParameterJdbcTemplate.queryForObject(sql, new HashMap<>(0), Long.class); } + @Override + public List getTrafficColorRulesByRouteRuleId(long routeRuleId) { + String sql = "select * from apigw_gportal_entry_traffic_policy where route_rule_ids like :pattern"; + Map params = new HashMap<>(Const.DEFAULT_MAP_SIZE); + params.put("pattern", "%" + routeRuleId + "%"); + List trafficMarkInfos = namedParameterJdbcTemplate.query(sql, params, new TrafficMarkRowMapper()); + // 因路由id为like匹配故需要recheck过滤 + return CollectionUtils.isEmpty(trafficMarkInfos) ? Collections.emptyList() : + trafficMarkInfos.stream() + .filter(trafficMarkInfo -> isTrafficMarkMatchRouteRuleId(trafficMarkInfo, routeRuleId)) + .collect(Collectors.toList()); + } + + private boolean isTrafficMarkMatchRouteRuleId(TrafficMarkInfo trafficMarkInfo, long routeRuleId) { + if (trafficMarkInfo == null || StringUtils.isEmpty(trafficMarkInfo.getRouteRuleIds())) { + return false; + } + for (String rId : trafficMarkInfo.getRouteRuleIds().split(",")) { + if (rId.equals(String.valueOf(routeRuleId))) { + return true; + } + } + return false; + } + @Override public List getTrafficColorByTagLimit(String colorTag, long offset, long limit) { Map params = new HashMap<>(Const.DEFAULT_MAP_SIZE); @@ -116,14 +145,14 @@ public TrafficMarkInfo mapRow(ResultSet rs, int rowNum) throws SQLException { trafficMarkInfo.setGwName(rs.getString("gw_name")); trafficMarkInfo.setCreateTime(rs.getLong("create_time")); trafficMarkInfo.setUpdateTime(rs.getLong("update_time")); - trafficMarkInfo.setRouteRuleId(rs.getLong("route_rule_id")); + trafficMarkInfo.setRouteRuleIds(rs.getString("route_rule_ids")); trafficMarkInfo.setEnableStatus(rs.getInt("enable_status")); trafficMarkInfo.setTrafficMatch(rs.getString("traffic_match")); trafficMarkInfo.setColorTag(rs.getString("color_tag")); trafficMarkInfo.setTrafficParam(rs.getString("param")); trafficMarkInfo.setTrafficColorName(rs.getString("traffic_color_name")); trafficMarkInfo.setServiceName(rs.getString("service_name")); - trafficMarkInfo.setRouteRuleName(rs.getString("route_rule_name")); + trafficMarkInfo.setRouteRuleNames(rs.getString("route_rule_names")); trafficMarkInfo.setProtocol(rs.getString("protocol")); return trafficMarkInfo; } diff --git a/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/meta/TrafficMarkInfo.java b/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/meta/TrafficMarkInfo.java index d765eb0f..0c257f97 100644 --- a/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/meta/TrafficMarkInfo.java +++ b/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/meta/TrafficMarkInfo.java @@ -5,7 +5,6 @@ /** * 流量染色相关元数据 - * * @author qilu */ public class TrafficMarkInfo { @@ -37,9 +36,9 @@ public class TrafficMarkInfo { private long updateTime; /** - * 流量染色的路由规则id + * 流量染色的路由规则id列表,英文逗号(,)分割 */ - private long routeRuleId; + private String routeRuleIds; /** * 流量染色开启状态:0表示关闭;1表示开启 @@ -67,9 +66,9 @@ public class TrafficMarkInfo { private String serviceName; /** - * 路由名称 + * 路由名称列表,英文逗号(,)分割 */ - private String routeRuleName; + private String routeRuleNames; /** * 协议 @@ -116,12 +115,12 @@ public void setUpdateTime(long updateTime) { this.updateTime = updateTime; } - public long getRouteRuleId() { - return routeRuleId; + public String getRouteRuleIds() { + return routeRuleIds; } - public void setRouteRuleId(long routeRuleId) { - this.routeRuleId = routeRuleId; + public void setRouteRuleIds(String routeRuleIds) { + this.routeRuleIds = routeRuleIds; } public int getEnableStatus() { @@ -172,12 +171,12 @@ public void setServiceName(String serviceName) { this.serviceName = serviceName; } - public String getRouteRuleName() { - return routeRuleName; + public String getRouteRuleNames() { + return routeRuleNames; } - public void setRouteRuleName(String routeRuleName) { - this.routeRuleName = routeRuleName; + public void setRouteRuleNames(String routeRuleNames) { + this.routeRuleNames = routeRuleNames; } public String getProtocol() { diff --git a/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/service/ITrafficMarkService.java b/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/service/ITrafficMarkService.java new file mode 100644 index 00000000..f79fc7de --- /dev/null +++ b/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/service/ITrafficMarkService.java @@ -0,0 +1,155 @@ +package org.hango.cloud.dashboard.envoy.service; + + +import org.hango.cloud.dashboard.apiserver.meta.errorcode.ErrorCode; +import org.hango.cloud.dashboard.envoy.meta.TrafficMarkInfo; +import org.hango.cloud.dashboard.envoy.web.dto.TrafficMarkDto; + +import java.util.List; + +/** + * 流量染色service层接口 + * + * @author qilu01 + */ +public interface ITrafficMarkService { + + /** + * 获取染色标识下的所有流量染色规则 + * + * @param colorTag 流量染色标识 + * @param offset 偏移 + * @param limit 每页的条数 + * @return 流量染色规则列表 + */ + List getTrafficColorByTagLimit(String colorTag, long offset, long limit); + + /** + * 获取染色标识下的染色规则数量 + * + * @param colorTag 流量染色标识 + * @return 当前染色标识下的染色规则数量 + */ + long getTrafficColorRuleCountByColorTag(String colorTag); + + /** + * 增加入口流量染色规则 + * + * @param envoyTrafficColorDto 流量染色规则信息 + * @return 流量染色元数据 + */ + TrafficMarkInfo addTrafficColorInfo(TrafficMarkDto envoyTrafficColorDto); + + /** + * 修改入口流量染色规则 + * + * @param envoyTrafficColorInfo 流量染色规则信息 + * @return true为修改成功 false为失败 + */ + boolean updateTrafficColorInfo(TrafficMarkInfo envoyTrafficColorInfo); + + /** + * 创建流量染色规则,参数校验 + * + * @param envoyTrafficColorDto 流量染色规则信息 + * @return errorcode 错误码 + */ + ErrorCode checkCreateTrafficColorParam(TrafficMarkDto envoyTrafficColorDto); + + /** + * 修改流量染色规则,参数校验 + * + * @param envoyTrafficColorDto 流量染色规则信息 + * @return errorcode 错误码 + */ + ErrorCode checkUpdateTrafficColorParam(TrafficMarkDto envoyTrafficColorDto); + + /** + * 检验染色规则名称是否存在 + * + * @param trafficColorName 染色规则名称 + * @return 存在返回true 不存在返回false + */ + boolean isTrafficColorNameExists(String trafficColorName); + + /** + * 判断当前服务路由下是否已经有流量染色规则 + * + * @param serviceName 服务名称 + * @param routeRuleName 路由名称 + * @return true为已经存在流量染色规则 false为不存在 + */ + boolean isTrafficColorExists(String serviceName, String routeRuleName); + + /** + * 判断流量染色规则是否存在 + * + * @param id 流量染色规则id + * @return true为已经存在流量染色规则 false为不存在 + */ + boolean isTrafficColorExists(long id); + + /** + * 通过id获取流量染色规则 + * + * @param id 流量染色规则id + * @return 流量染色规则信息 + */ + TrafficMarkInfo getTrafficColorRuleById(long id); + + /** + * 删除流量染色规则 + * + * @param trafficColorRuleId 流量染色规则id + * @return + */ + void delete(long trafficColorRuleId); + + /** + * 校验规则状态 + * 0: 禁用 + * 1: 启用 + * + * @param trafficMarkStatus 流量染色状态 + * @return 是否合法 + */ + boolean checkTrafficMarkStatus(Integer trafficMarkStatus); + + /** + * 修改流量染色规则的状态(启用\停用) + * + * @param trafficMarkRuleId 流量染色规则ID + * @param trafficMarkStatus 流量染色状态(0:停用; 1:启用) + * @return 操作结果 + */ + ErrorCode modifyTrafficMarkRuleStatus(Long trafficMarkRuleId, Integer trafficMarkStatus); + + /** + * 根据流量染色规则对象中的“规则”组装流量染色插件字符串,下面对关键参数做阐述 + * trafficMatch 代表匹配类型(Header\Cookie等) + * param 代表流量染色“规则”,是集合形式,单个元素规则:"key + 匹配规则 + value" + * colorTag 代表染色标记(例如"red"; "dev1"等) + * + * @param trafficColorRule 流量染色规则对象,param代表流量染色“规则” + * @return 流量染色插件配置字符串 + */ + String assembleTrafficMarkPlugin(TrafficMarkInfo trafficColorRule); + + /** + * 启用流量染色插件 + * + * @param trafficMarkRuleId 流量染色规则ID + * @return 操作结果 + */ + ErrorCode enableTrafficMarkPlugin(Long trafficMarkRuleId); + + /** + * 停用流量染色插件 + * + * @param trafficMarkRuleId 流量染色规则ID + * @return 操作结果 + */ + ErrorCode disableTrafficMarkPlugin(Long trafficMarkRuleId); + + List getTrafficColorRulesByRouteRuleId(long routeRuleId); +} diff --git a/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/service/impl/EnvoyGatewayServiceImpl.java b/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/service/impl/EnvoyGatewayServiceImpl.java index c54ab6fb..7bb8fbc5 100644 --- a/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/service/impl/EnvoyGatewayServiceImpl.java +++ b/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/service/impl/EnvoyGatewayServiceImpl.java @@ -30,18 +30,14 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpMethod; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; +import javax.annotation.PostConstruct; +import java.util.*; import java.util.stream.Collectors; @@ -75,6 +71,23 @@ public class EnvoyGatewayServiceImpl implements IEnvoyGatewayService { @Autowired private IRouteRuleProxyService routeRuleProxyService; + private Set ignorePluginSet; + + @Value("${ignorePlugins:#{null}}") + private String ignorePlugins; + + public String getIgnorePlugins() { + return ignorePlugins; + } + + public void setIgnorePlugins(String ignorePlugins) { + this.ignorePlugins = ignorePlugins; + } + + @PostConstruct + public void init() { + this.ignorePluginSet = StringUtils.isEmpty(ignorePlugins) ? Collections.emptySet() : new HashSet<>(Arrays.asList(ignorePlugins.split(","))); + } @Override public ErrorCode checkVirtualHostList(long gwId, List vhList) { @@ -419,7 +432,11 @@ public List getEnvoyPluginManager(GatewayInfo gatewayInfo return Collections.emptyList(); } List envoyPluginManager = getEnvoyPluginManager(gatewayInfo.getApiPlaneAddr(), gatewayInfo.getGwClusterName()); - return envoyPluginManager.stream().map(e -> toPluginManagerDto(e, apiServerConfig.getPluginManagerMap())).filter(e -> !PluginHandler.pluginIgnoreList.contains(e.getName())).collect(Collectors.toList()); + return envoyPluginManager.stream() + .map(e -> toPluginManagerDto(e, apiServerConfig.getPluginManagerMap())) + .filter(e -> !PluginHandler.pluginIgnoreList.contains(e.getName())) + .filter(e -> !ignorePluginSet.contains(e.getName())) + .collect(Collectors.toList()); } public EnvoyPluginManagerDto toPluginManagerDto(PluginOrderItemDto item, Map extra) { diff --git a/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/service/impl/EnvoyPluginServiceImpl.java b/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/service/impl/EnvoyPluginServiceImpl.java index 7cf2f951..2980f812 100644 --- a/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/service/impl/EnvoyPluginServiceImpl.java +++ b/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/service/impl/EnvoyPluginServiceImpl.java @@ -48,11 +48,7 @@ import org.springframework.http.HttpMethod; import org.springframework.stereotype.Service; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; /** @@ -881,8 +877,7 @@ public boolean bindingPlugin(BindingPluginInfo bindingPluginInfo, long projectId bindingInfo.setPluginType(bindingPluginInfo.getPluginType()); bindingInfo.setPluginPriority(pluginInfo.getPluginPriority()); bindingInfo.setBindingStatus(EnvoyPluginBindingInfo.BINDING_STATUS_ENABLE); - long bindingInfoId = envoyPluginBindingInfoDao.add(bindingInfo); - return true; + return envoyPluginBindingInfoDao.add(bindingInfo) > 0; } @Override diff --git a/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/service/impl/EnvoyServiceProxyServiceImpl.java b/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/service/impl/EnvoyServiceProxyServiceImpl.java index dfe6f5a2..05b7ef68 100644 --- a/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/service/impl/EnvoyServiceProxyServiceImpl.java +++ b/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/service/impl/EnvoyServiceProxyServiceImpl.java @@ -320,30 +320,6 @@ private ErrorCode checkRegistryCenterInfo(ServiceProxyDto serviceProxyDto) { return CommonErrorCode.Success; } - //校验consul & ZK - if (StringUtils.equalsAny(serviceProxyDto.getRegistryCenterType() - , RegistryCenterEnum.Consul.getType(), RegistryCenterEnum.Zookeeper.getType())) { - RegistryCenterEnum registryCenterEnum = RegistryCenterEnum.get(serviceProxyDto.getRegistryCenterType()); - if (registryCenterEnum == null) { - logger.info("错误的注册中心类型,RegistryCenterType = {} ", serviceProxyDto.getRegistryCenterType()); - return CommonErrorCode.InvalidParameterRegistryCenterType(serviceProxyDto.getRegistryCenterType()); - } - - if (StringUtils.isBlank(serviceProxyDto.getRegistryCenterAddr())) { - return CommonErrorCode.MissingParameterRegistryCenterAddr; - } - //暂时只支持单一应用 - RegistryCenterDto registryCenter = registryCenterService.findByTypeAndAddr(serviceProxyDto.getRegistryCenterType(), serviceProxyDto.getRegistryCenterAddr()); - if (registryCenter == null) { - return CommonErrorCode.InvalidParameterRegistryAddr(serviceProxyDto.getRegistryCenterAddr()); - } - } - - //校验eureka - if (RegistryCenterEnum.Eureka.getType().equals(serviceProxyDto.getRegistryCenterType())) { - return checkEurekaRegistryCenterAddr(serviceProxyDto.getRegistryCenterAddr()); - } - return CommonErrorCode.Success; } @@ -877,7 +853,7 @@ public ServiceProxyDto fromMetaWithPort(ServiceProxyInfo serviceProxyInfo) { if (Const.STATIC_PUBLISH_TYPE.equals(serviceProxyInfo.getPublishType())) { return serviceProxyDto; } - RegistryCenterDto registry = registryCenterService.findByTypeAndAddr(serviceProxyInfo.getRegistryCenterType(), serviceProxyInfo.getRegistryCenterAddr()); + RegistryCenterDto registry = registryCenterService.findByType(serviceProxyInfo.getRegistryCenterType()); String registryAlias = registry == null ? StringUtils.EMPTY : registry.getRegistryAlias(); //dynamic发布,获取port数据 if (RegistryCenterEnum.Eureka.getType().equals(serviceProxyInfo.getRegistryCenterType()) || @@ -1030,13 +1006,13 @@ public String getBackendServiceSendToApiPlane(ServiceProxyDto serviceProxyDto) { return backendService; } if (RegistryCenterEnum.Consul.equals(registryCenterEnum)) { - RegistryCenterDto registryCenter = registryCenterService.findByTypeAndAddr(serviceProxyDto.getRegistryCenterType(), serviceProxyDto.getRegistryCenterAddr()); + RegistryCenterDto registryCenter = registryCenterService.findByType(serviceProxyDto.getRegistryCenterType()); backendService = String.format(registryCenterEnum.getSuffix(), serviceProxyDto.getBackendService(), registryCenter.getRegistryAlias()); } if (RegistryCenterEnum.Eureka.equals(registryCenterEnum)) { //针对nsf eureka做特殊处理,galley上生成se时,其host的格式为{applicationname}.nsf.{projectCode}.eureka - RegistryCenterDto registryCenterDto = registryCenterService.findByTypeAndAddr(serviceProxyDto.getRegistryCenterType(), serviceProxyDto.getRegistryCenterAddr().split(",")[0]); + RegistryCenterDto registryCenterDto = registryCenterService.findByType(serviceProxyDto.getRegistryCenterType()); if (registryCenterDto != null && registryCenterDto.getRegistryAlias().contains(Const.NSF_EUREKA_ALIAS)) { //以nsf eureka发布的服务,其对应的backendservice为{applicationname}.nsf.{projectCode}.eureka long projectId = serviceInfoService.getServiceByServiceId(serviceProxyDto.getServiceId()).getProjectId(); @@ -1060,6 +1036,10 @@ public String getBackendServiceSendToApiPlane(ServiceProxyDto serviceProxyDto) { backendService = String.format(registryCenterEnum.getSuffix(), serviceProxyDto.getBackendService()); } + if (RegistryCenterEnum.Nacos.equals(registryCenterEnum)) { + backendService = String.format(registryCenterEnum.getSuffix(), serviceProxyDto.getBackendService()); + } + /** * fix dns host * @@ -1067,26 +1047,6 @@ public String getBackendServiceSendToApiPlane(ServiceProxyDto serviceProxyDto) { return backendService.replace('_', '-'); } - @Override - public ErrorCode checkEurekaRegistryCenterAddr(String registryCenterAddr) { - if (StringUtils.isBlank(registryCenterAddr)) { - return CommonErrorCode.InvalidEurekaAddress; - } - - RegistryCenterDto registryCenterDto; - String[] registryCenterList = registryCenterAddr.split(","); - for (String registryCenter : registryCenterList) { - if (!registryCenter.endsWith("/eureka/") && !registryCenter.startsWith("http://")) { - return CommonErrorCode.InvalidEurekaAddress; - } - registryCenterDto = registryCenterService.findByTypeAndAddr(RegistryCenterEnum.Eureka.getType(), registryCenter); - if (registryCenterDto == null) { - return CommonErrorCode.InvalidEurekaAddress; - } - } - return CommonErrorCode.Success; - } - @Override public List getSubsetsName(ServiceProxyInfo serviceProxyInfo) { GatewayInfo gatewayInfo = gatewayInfoService.get(serviceProxyInfo.getGwId()); @@ -1167,10 +1127,7 @@ public List getPublishedDetailByService(long serviceId) { @Override public Map createServiceFilters(RegistryCenterDto registry) { Map filters = new HashMap<>(); - if (registry != null && registry.getRegistryAlias().contains(Const.NSF_EUREKA_ALIAS)) { - PermissionScopeDto projectScopeDto = gatewayProjectService.getProjectScopeDto(ProjectTraceHolder.getProId()); - filters.put(Const.PREFIX_LABEL + Const.PROJECT_CODE, projectScopeDto.getPermissionScopeEnName()); - } + // 此处扩展服务过滤条件 return filters; } } diff --git a/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/service/impl/GetFromApiPlaneServiceImpl.java b/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/service/impl/GetFromApiPlaneServiceImpl.java index 5337bbef..fdc7c737 100644 --- a/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/service/impl/GetFromApiPlaneServiceImpl.java +++ b/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/service/impl/GetFromApiPlaneServiceImpl.java @@ -480,14 +480,6 @@ private boolean checkRegistryCenter(ServiceProxyDto serviceProxyDto) { if (RegistryCenterEnum.Kubernetes.equals(registryCenterEnum)) { return true; } - String[] registryCenterAddrList = StringUtils.split(serviceProxyDto.getRegistryCenterAddr(), ","); - for (String registryCenterAddr : registryCenterAddrList) { - RegistryCenterDto registryCenter = registryCenterService.findByTypeAndAddr(serviceProxyDto.getRegistryCenterType(), registryCenterAddr); - if (registryCenter == null) { - logger.warn("注册中心不存在 {}", registryCenter); - return false; - } - } return true; } diff --git a/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/service/impl/TrafficMarkServiceImpl.java b/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/service/impl/TrafficMarkServiceImpl.java new file mode 100644 index 00000000..ed060db1 --- /dev/null +++ b/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/service/impl/TrafficMarkServiceImpl.java @@ -0,0 +1,460 @@ +package org.hango.cloud.dashboard.envoy.service.impl; + + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import org.apache.commons.lang.StringUtils; +import org.hango.cloud.dashboard.apiserver.meta.GatewayInfo; +import org.hango.cloud.dashboard.apiserver.meta.errorcode.CommonErrorCode; +import org.hango.cloud.dashboard.apiserver.meta.errorcode.ErrorCode; +import org.hango.cloud.dashboard.apiserver.service.IGatewayInfoService; +import org.hango.cloud.dashboard.apiserver.service.IRouteRuleInfoService; +import org.hango.cloud.dashboard.apiserver.util.Const; +import org.hango.cloud.dashboard.envoy.dao.ITrafficMarkDao; +import org.hango.cloud.dashboard.envoy.meta.BindingPluginInfo; +import org.hango.cloud.dashboard.envoy.meta.EnvoyPluginBindingInfo; +import org.hango.cloud.dashboard.envoy.meta.RouteRuleInfo; +import org.hango.cloud.dashboard.envoy.meta.TrafficMarkInfo; +import org.hango.cloud.dashboard.envoy.service.IEnvoyGatewayService; +import org.hango.cloud.dashboard.envoy.service.IEnvoyPluginInfoService; +import org.hango.cloud.dashboard.envoy.service.ITrafficMarkService; +import org.hango.cloud.dashboard.envoy.web.dto.PluginOrderItemDto; +import org.hango.cloud.dashboard.envoy.web.dto.TrafficMarkDto; +import org.hango.cloud.dashboard.envoy.web.dto.TrafficMarkParamDto; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.Assert; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +/** + * 流量染色 service层接口实现 + * + * @author qilu01 + */ +@Service +public class TrafficMarkServiceImpl implements ITrafficMarkService { + private static final Logger logger = LoggerFactory.getLogger(TrafficMarkServiceImpl.class); + + @Autowired + private ITrafficMarkDao envoyTrafficColorDao; + + @Autowired + private IRouteRuleInfoService routeRuleInfoService; + + @Autowired + private IEnvoyPluginInfoService pluginInfoService; + + @Autowired + private IGatewayInfoService gatewayInfoService; + + @Autowired + private IEnvoyGatewayService envoyGatewayService; + + @Override + public List getTrafficColorByTagLimit(String colorTag, long offset, long limit) { + return envoyTrafficColorDao.getTrafficColorByTagLimit(colorTag, offset, limit); + } + + @Override + public long getTrafficColorRuleCountByColorTag(String colorTag) { + Map params = new HashMap<>(Const.DEFAULT_MAP_SIZE); + if (StringUtils.isBlank(colorTag)) { + return envoyTrafficColorDao.getCount(); + } + params.put("colorTag", colorTag); + return envoyTrafficColorDao.getCountByFields(params); + } + + @Override + public TrafficMarkInfo addTrafficColorInfo(TrafficMarkDto envoyTrafficColorDto) { + TrafficMarkInfo envoyTrafficColorInfo = TrafficMarkDto.toMeta(envoyTrafficColorDto); + envoyTrafficColorInfo.setEnableStatus(Const.PLUGIN_STATE_DISABLE); + envoyTrafficColorInfo.setCreateTime(System.currentTimeMillis()); + envoyTrafficColorInfo.setUpdateTime(System.currentTimeMillis()); + envoyTrafficColorInfo.setId(envoyTrafficColorDao.add(envoyTrafficColorInfo)); + return envoyTrafficColorInfo; + } + + @Override + public ErrorCode checkCreateTrafficColorParam(TrafficMarkDto envoyTrafficColorDto) { + String trafficColorName; + try { + trafficColorName = envoyTrafficColorDto.getTrafficColorName(); + } catch (Exception e) { + logger.info("流量染色规则名称为空"); + return CommonErrorCode.TrafficColorRuleNameIsEmpty; + } + if (!trafficMatchCheck(envoyTrafficColorDto.getTrafficMatch())) { + logger.info("流量匹配不支持 当前仅支持Header、Parameter匹配"); + return CommonErrorCode.TrafficMatchNotSupport; + } + //判断该流量规则名称是否已经存在 + if (isTrafficColorNameExists(trafficColorName)) { + logger.info("创建流量染色规则,该流量染色规则名称 trafficColorName {} 已经存在", trafficColorName); + return CommonErrorCode.TrafficColorRuleNameAlreadyExist; + } + //判断该服务 路由下是否已有流量染色规则 如果有则返回错误码 + if (isTrafficColorExists(envoyTrafficColorDto.getServiceName(), envoyTrafficColorDto.getRouteRuleNames())) { + logger.info("创建流量染色规则,当前服务路由下已存在流量染色规则,不允许重复创建"); + return CommonErrorCode.TrafficColorRuleAlreadyExist; + } + return CommonErrorCode.Success; + } + + + @Override + public boolean isTrafficColorNameExists(String trafficColorName) { + Map params = new HashMap<>(Const.DEFAULT_MAP_SIZE); + params.put("trafficColorName", trafficColorName); + return envoyTrafficColorDao.getCountByFields(params) > 0; + } + + /** + * 流量匹配校验 + * + * @param trafficMatch 流量匹配 目前仅支持Header + * @return Header为校验成功返回true 其他情况校验失败返回false + */ + public boolean trafficMatchCheck(String trafficMatch) { + if (StringUtils.isEmpty(trafficMatch)) { + logger.info("流量匹配为空"); + return false; + } + switch (trafficMatch) { + case "Header": + case "Parameter": + return true; + default: + logger.info("流量匹配 {} 不支持 当前仅支持Header、Parameter匹配", trafficMatch); + return false; + } + } + + @Override + public boolean isTrafficColorExists(String serviceName, String routeRuleName) { + Map params = new HashMap<>(Const.DEFAULT_MAP_SIZE); + params.put("serviceName", serviceName); + params.put("routeRuleNames", routeRuleName); + + return envoyTrafficColorDao.getCountByFields(params) > 0; + } + + @Override + public ErrorCode checkUpdateTrafficColorParam(TrafficMarkDto envoyTrafficColorDto) { + //参数校验 + if (!isTrafficColorExists(envoyTrafficColorDto.getId())) { + logger.info("更新流量染色规则,流量染色规则不存在"); + return CommonErrorCode.NoSuchTrafficColorRule; + } + return CommonErrorCode.Success; + } + + @Override + public boolean isTrafficColorExists(long id) { + Map params = new HashMap<>(); + params.put("id", id); + return envoyTrafficColorDao.getCountByFields(params) > 0; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public boolean updateTrafficColorInfo(TrafficMarkInfo envoyTrafficColorInfo) { + if (null == envoyTrafficColorInfo) { + return false; + } + + long trafficMarkRuleId = envoyTrafficColorInfo.getId(); + String paramRule = envoyTrafficColorInfo.getTrafficParam(); + + // 更新染色规则DB + envoyTrafficColorInfo.setUpdateTime(System.currentTimeMillis()); + if (1 != envoyTrafficColorDao.update(envoyTrafficColorInfo)) { + logger.error("[traffic mark] update traffic_mark_rule failed, trafficMarkRuleId: {}", trafficMarkRuleId); + return false; + } + + // 未启用状态不需要流量染色更新插件 + if (envoyTrafficColorInfo.getEnableStatus() == Const.PLUGIN_STATE_DISABLE) { + return true; + } + + // 染色规则启用状态下,更新插件动态生效;按照新规则(paramRule)启用流量染色规则插件 + ErrorCode enableResult = enableTrafficMarkPlugin(trafficMarkRuleId); + if (!enableResult.equals(CommonErrorCode.Success)) { + logger.error("[traffic mark] enable traffic_mark_plugin failed when updateTrafficColorInfo." + "trafficMarkRuleId: {}, new param_rules: {}", trafficMarkRuleId, paramRule); + return false; + } + + return true; + } + + @Override + public TrafficMarkInfo getTrafficColorRuleById(long id) { + return envoyTrafficColorDao.get(id); + } + + @Override + public void delete(long trafficColorRuleId) { + envoyTrafficColorDao.delete(trafficColorRuleId); + } + + @Override + public boolean checkTrafficMarkStatus(Integer trafficMarkStatus) { + return trafficMarkStatus.equals(Const.PLUGIN_STATE_DISABLE) || trafficMarkStatus.equals(Const.PLUGIN_STATE_ENABLE); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public ErrorCode modifyTrafficMarkRuleStatus(Long trafficMarkRuleId, Integer trafficMarkStatus) { + TrafficMarkInfo trafficColorRule = getTrafficColorRuleById(trafficMarkRuleId); + + // 根据trafficMarkStatus进行traffic_mark插件的更新或删除 + ErrorCode resultCode; + if (trafficMarkStatus.equals(Const.PLUGIN_STATE_ENABLE)) { + resultCode = enableTrafficMarkPlugin(trafficMarkRuleId); + } else { + resultCode = disableTrafficMarkPlugin(trafficMarkRuleId); + } + if (!resultCode.equals(CommonErrorCode.Success)) { + return resultCode; + } + + // 更新流量染色规则DB + trafficColorRule.setEnableStatus(trafficMarkStatus); + if (!updateTrafficColorInfo(trafficColorRule)) { + return CommonErrorCode.UpdateFailure; + } + return CommonErrorCode.Success; + } + + /** + * 案例: + * { + * "kind": "traffic-mark", + * "headerKey": [ + * { + * "request": { + * "headers": [ + * { + * "match_type": "safe_regex_match", + * "headerKey": "test_header_1", + * "value": "test_value_1" + * } + * ], + * "requestSwitch": true + * }, + * "headerValue": "dev1", + * "headerKey": "x-nsf-mark", + * "operation": "create" + * } + * ] + * } + * + * @param trafficColorRule 流量染色规则对象 + * @return 流量染色插件字符串,见案例 + */ + @Override + public String assembleTrafficMarkPlugin(TrafficMarkInfo trafficColorRule) { + if (trafficColorRule == null) { + logger.error("[traffic mark] error trafficColorRule when assembleTrafficMarkPlugin"); + return ""; + } + List paramList = JSON.parseArray(trafficColorRule.getTrafficParam(), TrafficMarkParamDto.class); + JSONObject plugin = new JSONObject(); + plugin.put("kind", Const.PLUGIN_TYPE_TRAFFIC_MARK); + JSONArray array = new JSONArray(); + plugin.put("headerKey", array); + JSONObject rewriter = new JSONObject(); + array.add(rewriter); + processRewriter(trafficColorRule, rewriter); + switch (trafficColorRule.getTrafficMatch()) { + case "Header": + processHeaderMatcher(paramList, rewriter); + break; + case "Parameter": + processParameterMatcher(paramList, rewriter); + break; + default: + //不可达,前置已做流量染色匹配规则校验 + break; + } + return plugin.toJSONString(); + } + + private void processRewriter(TrafficMarkInfo trafficColorRule, JSONObject rewriter) { + rewriter.put("headerKey", getTrafficMarkKey(trafficColorRule)); + rewriter.put("operation", "create"); + rewriter.put("headerValue", trafficColorRule.getColorTag()); + } + + private void processHeaderMatcher(List paramList, JSONObject rewriter) { + rewriter.put("request", generateHeaderMatcher(paramList)); + } + + private void processParameterMatcher(List paramList, JSONObject rewriter) { + rewriter.put("request", generateParameterMatcher(paramList)); + } + + private JSONObject generateHeaderMatcher(List paramList) { + JSONObject request = new JSONObject(); + JSONArray matchList = new JSONArray(); + for (TrafficMarkParamDto trafficColorMatch : paramList) { + Map matcher = new HashMap<>(); + matcher.put("headerKey", trafficColorMatch.getParaName()); + matcher.put("match_type", convertToEnvoyMatchType(trafficColorMatch.getType())); + matcher.put("value", trafficColorMatch.getValue()); + matchList.add(matcher); + } + + request.put("headers", matchList); + return request; + } + + private JSONObject generateParameterMatcher(List paramList) { + JSONObject request = new JSONObject(); + JSONArray matchList = new JSONArray(); + for (TrafficMarkParamDto trafficColorMatch : paramList) { + Map matcher = new HashMap<>(); + matcher.put("parameterKey", trafficColorMatch.getParaName()); + matcher.put("match_type", convertToEnvoyMatchType(trafficColorMatch.getType())); + matcher.put("value", trafficColorMatch.getValue()); + matchList.add(matcher); + } + + request.put("parameters", matchList); + return request; + } + + private String getTrafficMarkKey(TrafficMarkInfo trafficColorRule) { + GatewayInfo gatewayInfo = gatewayInfoService.get(trafficColorRule.getGwId()); + List envoyPluginManager = envoyGatewayService.getEnvoyPluginManager(gatewayInfo.getApiPlaneAddr(), gatewayInfo.getGwClusterName()); + Optional optional = envoyPluginManager.stream().filter(e -> e.getName().equals(Const.PLUGIN_NAME_TRAFFIC_MARK)).findFirst(); + Assert.isTrue(optional.isPresent(), "PluginManager不存在插件com.netease.traffic_mark的配置,请排查"); + logger.info("getTrafficMarkKey info :{}", JSON.toJSONString(optional.get())); + JSONObject inline = (JSONObject) optional.get().getInline(); + Assert.notNull(inline,"PluginManager插件proxy.filters.http.traffic_mark的配置信息有问题,请排查"); + JSONObject settings = inline.getJSONObject("settings"); + Assert.notNull(settings,"PluginManager插件proxy.filters.http.traffic_mark的配置信息有问题,请排查"); + return settings.getString("header_key"); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public ErrorCode enableTrafficMarkPlugin(Long trafficMarkRuleId) { + logger.info("[traffic mark] start to enable traffic_mark_plugin, trafficMarkRuleId: {}", trafficMarkRuleId); + TrafficMarkInfo trafficColorRule = getTrafficColorRuleById(trafficMarkRuleId); + for (String routeId : trafficColorRule.getRouteRuleIds().split(",")) { + RouteRuleInfo route = routeRuleInfoService.getRouteRuleInfoById(Long.parseLong(routeId)); + + // 未发布的路由不允许启用流量染色插件 + if (route.getPublishStatus() != Const.PLUGIN_STATE_ENABLE) { + logger.warn("[traffic mark] route not publish, please publish route firstly," + "route_id: {}, trafficMarkRuleId: {}", routeId, trafficMarkRuleId); + return CommonErrorCode.RouteRuleNotPublished; + } + + // 组装插件 + String trafficMarkPlugin = assembleTrafficMarkPlugin(trafficColorRule); + logger.info("[traffic mark] assembleTrafficMarkPlugin finished, traffic_mark_plugin: {}", trafficMarkPlugin); + + List pluginBindingList = pluginInfoService.getPluginBindingList(trafficColorRule.getGwId(), routeId, EnvoyPluginBindingInfo.BINDING_OBJECT_TYPE_ROUTE_RULE); + + boolean isAddTrafficMarkPlugin = true; + for (EnvoyPluginBindingInfo pluginBinding : pluginBindingList) { + // 已存在"traffic-mark"插件,进行插件配置修改 + if (pluginBinding.getPluginType().equals(Const.PLUGIN_TYPE_TRAFFIC_MARK)) { + logger.info("[traffic mark] traffic_mark_plugin already exists, start to update, plugin_id: {}", pluginBinding.getId()); + isAddTrafficMarkPlugin = false; + boolean updateOk = pluginInfoService.updatePluginConfiguration(pluginBinding.getId(), trafficMarkPlugin, -1); + if (!updateOk) { + logger.error("[traffic mark] update traffic_mark_plugin failed, plugin_id: {}", pluginBinding.getId()); + return CommonErrorCode.UpdatePluginInfoFailed; + } + break; + } + } + // 新增"traffic-mark"插件 + if (isAddTrafficMarkPlugin) { + BindingPluginInfo bindingPluginInfo = new BindingPluginInfo(); + bindingPluginInfo.setGwId(trafficColorRule.getGwId()); + bindingPluginInfo.setBindingObjectType(BindingPluginInfo.PLUGIN_TYPE_ROUTE); + bindingPluginInfo.setBindingObjectId(route.getId()); + bindingPluginInfo.setPluginType(Const.PLUGIN_TYPE_TRAFFIC_MARK); + bindingPluginInfo.setPluginConfiguration(trafficMarkPlugin); + boolean addOk = pluginInfoService.bindingPlugin(bindingPluginInfo, -1, -1); + if (!addOk) { + logger.error("[traffic mark] add new traffic_mark_plugin failed"); + return CommonErrorCode.UpdatePluginInfoFailed; + } + } + } + return CommonErrorCode.Success; + } + + @Transactional(rollbackFor = Exception.class) + @Override + public ErrorCode disableTrafficMarkPlugin(Long trafficMarkRuleId) { + logger.info("[traffic mark] start to disable traffic_mark_plugin, trafficMarkRuleId: {}", trafficMarkRuleId); + TrafficMarkInfo trafficColorRule = getTrafficColorRuleById(trafficMarkRuleId); + for (String routeId : trafficColorRule.getRouteRuleIds().split(",")) { + // 获取路由ID + RouteRuleInfo route = routeRuleInfoService.getRouteRuleInfoById(Long.parseLong(routeId)); + + List pluginBindingList = pluginInfoService.getPluginBindingList(trafficColorRule.getGwId(), routeId, EnvoyPluginBindingInfo.BINDING_OBJECT_TYPE_ROUTE_RULE); + + boolean isExists = false; + for (EnvoyPluginBindingInfo pluginBinding : pluginBindingList) { + if (pluginBinding.getPluginType().equals(Const.PLUGIN_TYPE_TRAFFIC_MARK)) { + isExists = true; + boolean deleteOk = pluginInfoService.unbindingPlugin(pluginBinding.getId()); + if (!deleteOk) { + logger.error("[traffic mark] delete traffic_mark_plugin failed, plugin_id: {}", pluginBinding.getId()); + return CommonErrorCode.DeletePluginInfoFailed; + } + break; + } + } + if (!isExists) { + logger.warn("[traffic mark] traffic_mark_plugin not exists on this route, route_id: {}, route_name: {}", routeId, route.getRouteRuleName()); + } + } + return CommonErrorCode.Success; + } + + @Override + public List getTrafficColorRulesByRouteRuleId(long routeRuleId) { + return envoyTrafficColorDao.getTrafficColorRulesByRouteRuleId(routeRuleId); + } + + /** + * 将前台的匹配规则转换为服务envoy格式的匹配规则 + * + * @param matchType 前台的匹配规则 + * @return envoy可识别的匹配规则 + */ + private String convertToEnvoyMatchType(String matchType) { + String envoyMatchType = "exact_match"; + if (StringUtils.isEmpty(matchType)) { + return envoyMatchType; + } + switch (matchType) { + case "exact": + envoyMatchType = "exact_match"; + break; + case "regex": + envoyMatchType = "safe_regex_match"; + break; + case "prefix": + envoyMatchType = "prefix_match"; + default: + } + return envoyMatchType; + } +} \ No newline at end of file diff --git a/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/web/controller/TrafficMarkController.java b/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/web/controller/TrafficMarkController.java new file mode 100644 index 00000000..44566a19 --- /dev/null +++ b/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/web/controller/TrafficMarkController.java @@ -0,0 +1,181 @@ +package org.hango.cloud.dashboard.envoy.web.controller; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.math.NumberUtils; +import org.hango.cloud.dashboard.apiserver.aop.Audit; +import org.hango.cloud.dashboard.apiserver.dto.auditdto.ResourceDataDto; +import org.hango.cloud.dashboard.apiserver.meta.errorcode.CommonErrorCode; +import org.hango.cloud.dashboard.apiserver.meta.errorcode.ErrorCode; +import org.hango.cloud.dashboard.apiserver.util.AuditResourceHolder; +import org.hango.cloud.dashboard.apiserver.util.CommonUtil; +import org.hango.cloud.dashboard.apiserver.util.Const; +import org.hango.cloud.dashboard.apiserver.web.controller.AbstractController; +import org.hango.cloud.dashboard.common.distributedlock.MethodReentrantLock; +import org.hango.cloud.dashboard.envoy.meta.TrafficMarkInfo; +import org.hango.cloud.dashboard.envoy.service.ITrafficMarkService; +import org.hango.cloud.dashboard.envoy.web.dto.TrafficMarkDto; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * 入口流量染色相关controller + * 流量染色控制台crud + * + * @author qilu + */ +@RestController +@Validated +@RequestMapping(value = Const.G_DASHBOARD_PREFIX, params = {"Version=2019-09-01"}) +public class TrafficMarkController extends AbstractController { + private static final Logger logger = LoggerFactory.getLogger(TrafficMarkController.class); + + @Autowired + private ITrafficMarkService trafficMarkService; + + /** + * 创建流量染色规则 + * + * @param trafficColorDto 流量染色dto + * @return + */ + @MethodReentrantLock + @Audit(eventName = "CreateTrafficColorRuleBatch", description = "创建流量染色规则") + @RequestMapping(params = {"Action=CreateTrafficColorRule"}, method = RequestMethod.POST) + public Object createTrafficColorRuleBatch(@Validated @RequestBody TrafficMarkDto trafficColorDto) { + logger.info("创建入口流量染色规则,trafficColorDto:{}", trafficColorDto); + //操作审计记录资源名称 + ResourceDataDto resource = new ResourceDataDto(Const.AUDIT_RESOURCE_TYPE_ROUTE_RULE, null, trafficColorDto.getRouteRuleNames()); + AuditResourceHolder.set(resource); + + ErrorCode errorCode = trafficMarkService.checkCreateTrafficColorParam(trafficColorDto); + //参数校验 + if (!CommonErrorCode.Success.getCode().equals(errorCode.getCode())) { + return apiReturn(errorCode); + } + trafficColorDto.setEnableStatus(Const.PLUGIN_STATE_DISABLE); + TrafficMarkInfo trafficMarkInfo = trafficMarkService.addTrafficColorInfo(trafficColorDto); + resource.setResourceId(trafficMarkInfo.getId()); + return apiReturn(CommonErrorCode.Success); + + } + + /** + * 修改流量染色规则 + * + * @param trafficColorDto 流量染色dto + * @return + */ + @MethodReentrantLock + @Audit(eventName = "UpdateTrafficColorRule", description = "修改流量染色规则") + @RequestMapping(params = {"Action=UpdateTrafficColorRule"}, method = RequestMethod.POST) + public Object updateTrafficColorRule(@Validated @RequestBody TrafficMarkDto trafficColorDto) { + logger.info("修改入口流量染色规则,trafficColorDto:{}", trafficColorDto); + //操作审计记录资源名称 + AuditResourceHolder.set(new ResourceDataDto(Const.AUDIT_RESOURCE_TYPE_ROUTE_RULE, null, trafficColorDto.getRouteRuleNames())); + + ErrorCode errorCode = trafficMarkService.checkUpdateTrafficColorParam(trafficColorDto); + //参数校验 + if (!CommonErrorCode.Success.getCode().equals(errorCode.getCode())) { + return apiReturn(errorCode); + } + TrafficMarkInfo trafficMarkInfo = trafficMarkService.getTrafficColorRuleById(trafficColorDto.getId()); + trafficMarkInfo.setTrafficParam(TrafficMarkDto.toMeta(trafficColorDto).getTrafficParam()); + trafficMarkInfo.setGwId(trafficColorDto.getGwId()); + trafficMarkInfo.setTrafficMatch(trafficColorDto.getTrafficMatch()); + trafficMarkService.updateTrafficColorInfo(trafficMarkInfo); + return apiReturn(CommonErrorCode.Success); + } + + /** + * 根据流量染色id删除流量染色规则 + * + * @param trafficColorRuleId 流量染色规则id + * @return + */ + @MethodReentrantLock + @Audit(eventName = "DeleteTrafficColorRule", description = "删除流量染色规则") + @RequestMapping(params = {"Action=DeleteTrafficColorRule"}, method = RequestMethod.GET) + public Object deleteTrafficColorRule(@RequestParam(value = "TrafficColorRuleId") long trafficColorRuleId) { + logger.info("删除入口流量染色规则,trafficColorRuleId:{}", trafficColorRuleId); + //操作审计记录资源名称 + ResourceDataDto resource = new ResourceDataDto(Const.AUDIT_RESOURCE_TYPE_ROUTE_RULE, trafficColorRuleId, null); + AuditResourceHolder.set(resource); + + TrafficMarkInfo trafficMarkInfo = trafficMarkService.getTrafficColorRuleById(trafficColorRuleId); + if (null != trafficMarkInfo) { + resource.setResourceName(trafficMarkInfo.getRouteRuleNames()); + if (trafficMarkInfo.getEnableStatus() == 1) { + logger.info("流量染色规则已启用, 不允许删除"); + return apiReturn(CommonErrorCode.CannotDeleteOnlineTrafficColorRule); + } + } + trafficMarkService.delete(trafficColorRuleId); + return apiReturn(CommonErrorCode.Success); + } + + /** + * 查询某个染色标识下所有的流量染色规则,返回前端当前染色标识下的所有染色规则列表 + * + * @param colorTag 流量染色标识 + * @param offset 偏移 + * @param limit 每页条数 + * @return 流量染色规则列表 + */ + @RequestMapping(params = {"Action=DescribeTrafficColorRuleList"}, method = RequestMethod.GET) + public Object trafficColorRuleList(@RequestParam(value = "ColorTag", required = false) String colorTag, @RequestParam(value = "Offset", required = false, defaultValue = "0") long offset, @RequestParam(value = "Limit", required = false, defaultValue = "20") long limit) { + logger.info("获取当前染色标识下的染色规则列表,colorTag:{}", colorTag); + //offset,limit校验 + ErrorCode errorCode = CommonUtil.checkOffsetAndLimit(offset, limit); + if (!CommonErrorCode.Success.getCode().equals(errorCode.getCode())) { + return apiReturn(errorCode); + } + Map result = new HashMap<>(Const.DEFAULT_MAP_SIZE); + + List trafficColorInfos = trafficMarkService.getTrafficColorByTagLimit(colorTag, offset, limit); + if (CollectionUtils.isEmpty(trafficColorInfos)) { + result.put("TrafficColorRuleCount", NumberUtils.INTEGER_ZERO); + result.put("TrafficColorRuleList", Collections.EMPTY_LIST); + return apiReturn(CommonErrorCode.Success, result); + } + List trafficColorDtos = trafficColorInfos.stream().map(TrafficMarkDto::toDto).collect(Collectors.toList()); + result.put("TrafficColorRuleCount", trafficMarkService.getTrafficColorRuleCountByColorTag(colorTag)); + result.put("TrafficColorRuleList", trafficColorDtos); + return apiReturn(CommonErrorCode.Success, result); + } + + /** + * 开启流量染色规则 + * + * @param trafficMarkRuleId 流量染色规则id + * @return 操作结果 + */ + @PostMapping(params = {"Action=ModifyTrafficMarkRuleStatus"}) + public Object modifyTrafficMarkRuleStatus(@RequestParam(value = "TrafficColorRuleId") Long trafficMarkRuleId, @RequestParam(value = "TrafficMarkStatus") Integer trafficMarkStatus) { + logger.info("modifyTrafficMarkRuleStatus id:{}, status: {}", trafficMarkRuleId, trafficMarkStatus); + + AuditResourceHolder.set(new ResourceDataDto(Const.AUDIT_RESOURCE_TYPE_TRAFFIC_MARK, trafficMarkRuleId, null)); + + // 校验参数 + if (!trafficMarkService.checkTrafficMarkStatus(trafficMarkStatus)) { + logger.error("trafficMarkStatus is illegal, trafficMarkStatus: {}", trafficMarkStatus); + return apiReturn(CommonErrorCode.InvalidParameter(String.valueOf(trafficMarkStatus), "trafficMarkStatus")); + } + if (!trafficMarkService.isTrafficColorExists(trafficMarkRuleId)) { + logger.error("trafficMarkRuleId is illegal, trafficMarkRule not found, trafficMarkRuleId: {}", trafficMarkRuleId); + return apiReturn(CommonErrorCode.NoSuchTrafficColorRule); + } + + // 执行染色规则状态修改业务 + ErrorCode resultCode = trafficMarkService.modifyTrafficMarkRuleStatus(trafficMarkRuleId, trafficMarkStatus); + return apiReturn(resultCode); + } +} diff --git a/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/web/dto/ServiceProxyDto.java b/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/web/dto/ServiceProxyDto.java index 49c07ebf..215eb299 100644 --- a/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/web/dto/ServiceProxyDto.java +++ b/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/web/dto/ServiceProxyDto.java @@ -68,13 +68,6 @@ public class ServiceProxyDto { @JSONField(name = "RegistryCenterType") private String registryCenterType; - /** - * 注册中心地址 - */ - @JSONField(name = "RegistryCenterAddr") - private String registryCenterAddr; - - /** * 路由发布协议,可以为空,默认为 */ @@ -170,7 +163,6 @@ public static ServiceProxyInfo toMeta(ServiceProxyDto serviceProxyDto) { serviceProxyInfo.setPublishProtocol(serviceProxyDto.getPublishProtocol()); serviceProxyInfo.setPublishType(serviceProxyDto.getPublishType()); serviceProxyInfo.setRegistryCenterType(serviceProxyDto.getRegistryCenterType()); - serviceProxyInfo.setRegistryCenterAddr(serviceProxyDto.getRegistryCenterAddr()); serviceProxyInfo.setGwId(serviceProxyDto.getGwId()); serviceProxyInfo.setGwType(serviceProxyDto.getGwType()); serviceProxyInfo.setCreateTime(serviceProxyDto.getCreateTime()); @@ -188,7 +180,6 @@ public static ServiceProxyDto toDto(ServiceProxyInfo serviceProxyInfo) { serviceProxyDto.setCode(serviceProxyInfo.getCode()); serviceProxyDto.setBackendService(serviceProxyInfo.getBackendService()); serviceProxyDto.setRegistryCenterType(serviceProxyInfo.getRegistryCenterType()); - serviceProxyDto.setRegistryCenterAddr(serviceProxyInfo.getRegistryCenterAddr()); serviceProxyDto.setPublishProtocol(serviceProxyInfo.getPublishProtocol()); serviceProxyDto.setPublishType(serviceProxyInfo.getPublishType()); serviceProxyDto.setGwId(serviceProxyInfo.getGwId()); @@ -398,14 +389,6 @@ public void setRegistryCenterType(String registryCenterType) { this.registryCenterType = registryCenterType; } - public String getRegistryCenterAddr() { - return registryCenterAddr; - } - - public void setRegistryCenterAddr(String registryCenterAddr) { - this.registryCenterAddr = registryCenterAddr; - } - public EnvoyServiceTrafficPolicyDto getTrafficPolicy() { return trafficPolicy; } diff --git a/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/web/dto/TrafficMarkDto.java b/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/web/dto/TrafficMarkDto.java index fc8c5ffd..0fadba8c 100644 --- a/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/web/dto/TrafficMarkDto.java +++ b/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/web/dto/TrafficMarkDto.java @@ -16,16 +16,9 @@ /** * 流量染色相关dto - * * @author qilu */ public class TrafficMarkDto { - /** - * 流量染色参数 - */ - @JSONField(name = "TrafficParam") - @Valid - List trafficMarkParams; /** * 数据库主键自增id */ @@ -56,32 +49,43 @@ public class TrafficMarkDto { */ @JSONField(name = "CreateTime") private long createTime; + /** * 更新时间 */ @JSONField(name = "UpdateTime") private long updateTime; + /** - * 流量染色的路由规则id + * 流量染色的路由规则id列表,英文逗号(,)分割 */ - @JSONField(name = "RouteRuleId") - @Min(1) - private long routeRuleId; + @JSONField(name = "RouteRuleIds") + private String routeRuleIds; /** * 流量染色开启状态:0表示关闭;1表示开启 */ @JSONField(name = "EnableStatus") private int enableStatus; + /** * 流量匹配 当前仅支持Header匹配 */ @JSONField(name = "TrafficMatch") private String trafficMatch = "Header"; + /** * 染色标识 */ @JSONField(name = "ColorTag") private String colorTag; + + /** + * 流量染色参数 + */ + @JSONField(name = "TrafficParam") + @Valid + List trafficMarkParams; + /** * 服务名称 */ @@ -89,10 +93,10 @@ public class TrafficMarkDto { private String serviceName; /** - * 路由名称 + * 路由名称列表,英文逗号(,)分割 */ - @JSONField(name = "RouteRuleName") - private String routeRuleName; + @JSONField(name = "RouteRuleNames") + private String routeRuleNames; public static TrafficMarkInfo toMeta(TrafficMarkDto trafficMarkDto) { TrafficMarkInfo trafficMarkInfo = new TrafficMarkInfo(); @@ -102,7 +106,7 @@ public static TrafficMarkInfo toMeta(TrafficMarkDto trafficMarkDto) { trafficMarkInfo.setProtocol(trafficMarkDto.getProtocol()); trafficMarkInfo.setCreateTime(trafficMarkDto.getCreateTime()); trafficMarkInfo.setUpdateTime(trafficMarkDto.getUpdateTime()); - trafficMarkInfo.setRouteRuleId(trafficMarkDto.getRouteRuleId()); + trafficMarkInfo.setRouteRuleIds(trafficMarkDto.getRouteRuleIds()); trafficMarkInfo.setEnableStatus(trafficMarkDto.getEnableStatus()); trafficMarkInfo.setTrafficMatch(trafficMarkDto.getTrafficMatch()); trafficMarkInfo.setColorTag(trafficMarkDto.getColorTag()); @@ -110,7 +114,7 @@ public static TrafficMarkInfo toMeta(TrafficMarkDto trafficMarkDto) { JSON.toJSONString(trafficMarkDto.getTrafficMarkParams()) : null); trafficMarkInfo.setTrafficColorName(trafficMarkDto.getTrafficColorName()); trafficMarkInfo.setServiceName(trafficMarkDto.getServiceName()); - trafficMarkInfo.setRouteRuleName(trafficMarkDto.getRouteRuleName()); + trafficMarkInfo.setRouteRuleNames(trafficMarkDto.getRouteRuleNames()); return trafficMarkInfo; } @@ -122,14 +126,14 @@ public static TrafficMarkDto toDto(TrafficMarkInfo trafficMarkInfo) { trafficMarkDto.setProtocol(trafficMarkInfo.getProtocol()); trafficMarkDto.setCreateTime(trafficMarkInfo.getCreateTime()); trafficMarkDto.setUpdateTime(trafficMarkInfo.getUpdateTime()); - trafficMarkDto.setRouteRuleId(trafficMarkInfo.getRouteRuleId()); + trafficMarkDto.setRouteRuleIds(trafficMarkInfo.getRouteRuleIds()); trafficMarkDto.setEnableStatus(trafficMarkInfo.getEnableStatus()); trafficMarkDto.setTrafficMatch(trafficMarkInfo.getTrafficMatch()); trafficMarkDto.setColorTag(trafficMarkInfo.getColorTag()); trafficMarkDto.setTrafficMarkParams(setTrafficColorParamForDto(trafficMarkInfo)); trafficMarkDto.setTrafficColorName(trafficMarkInfo.getTrafficColorName()); trafficMarkDto.setServiceName(trafficMarkInfo.getServiceName()); - trafficMarkDto.setRouteRuleName(trafficMarkInfo.getRouteRuleName()); + trafficMarkDto.setRouteRuleNames(trafficMarkInfo.getRouteRuleNames()); return trafficMarkDto; } @@ -201,12 +205,12 @@ public void setUpdateTime(long updateTime) { this.updateTime = updateTime; } - public long getRouteRuleId() { - return routeRuleId; + public String getRouteRuleIds() { + return routeRuleIds; } - public void setRouteRuleId(long routeRuleId) { - this.routeRuleId = routeRuleId; + public void setRouteRuleIds(String routeRuleIds) { + this.routeRuleIds = routeRuleIds; } public int getEnableStatus() { @@ -257,14 +261,13 @@ public void setServiceName(String serviceName) { this.serviceName = serviceName; } - public String getRouteRuleName() { - return routeRuleName; + public String getRouteRuleNames() { + return routeRuleNames; } - public void setRouteRuleName(String routeRuleName) { - this.routeRuleName = routeRuleName; + public void setRouteRuleNames(String routeRuleNames) { + this.routeRuleNames = routeRuleNames; } - @Override public String toString() { return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); diff --git a/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/web/dto/TrafficMarkParamDto.java b/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/web/dto/TrafficMarkParamDto.java index d55cb6ee..ce25b6d4 100644 --- a/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/web/dto/TrafficMarkParamDto.java +++ b/gateway-portal/src/main/java/org/hango/cloud/dashboard/envoy/web/dto/TrafficMarkParamDto.java @@ -10,8 +10,7 @@ /** * 流量染色参数相关dto - * - * @author qilu + * @author qilu */ public class TrafficMarkParamDto implements Serializable { @@ -58,7 +57,6 @@ public String getValue() { public void setValue(String value) { this.value = value; } - @Override public String toString() { return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); diff --git a/gateway-portal/src/main/resources/application.properties b/gateway-portal/src/main/resources/application.properties index 68f116f5..7985c538 100644 --- a/gateway-portal/src/main/resources/application.properties +++ b/gateway-portal/src/main/resources/application.properties @@ -2,8 +2,9 @@ server.port=8898 #设置上传的文件大小 spring.http.multipart.max-file-size=10Mb spring.http.multipart.max-request-size=10Mb -spring.http.encoding.charset=UTF-8 -spring.http.encoding.force=true +server.servlet.encoding.charset=UTF-8 +server.servlet.encoding.force=true spring.cloud.consul.enabled=false databasePrefix=apigw_gportal_ -endpoints.actuator.enabled=false \ No newline at end of file +endpoints.actuator.enabled=false +spring.main.allow-bean-definition-overriding=true \ No newline at end of file diff --git a/gateway-portal/src/main/resources/schema.sql b/gateway-portal/src/main/resources/schema.sql index 9b3586ca..8bcf9879 100644 --- a/gateway-portal/src/main/resources/schema.sql +++ b/gateway-portal/src/main/resources/schema.sql @@ -765,7 +765,7 @@ CREATE TABLE IF NOT EXISTS apigw_gportal_api ( CREATE TABLE IF NOT EXISTS apigw_gportal_dubbo_meta ( id bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, application_name varchar(255) NOT NULL , - protocol_version varchar(255) NOT NULL , + protocol_version varchar(255) DEFAULT NULL , interface_name varchar(255) NOT NULL , dubbo_group varchar(255) DEFAULT NULL , dubbo_version varchar(255) DEFAULT NULL , @@ -863,4 +863,23 @@ CREATE TABLE IF NOT EXISTS apigw_gportal_api ( PRIMARY KEY (id) ) ; - alter table apigw_envoy_health_check_rule add COLUMN min_health_percent tinyint(4) DEFAULT 50 ; \ No newline at end of file + alter table apigw_envoy_health_check_rule add COLUMN min_health_percent tinyint(4) DEFAULT 50 ; + + CREATE TABLE IF NOT EXISTS apigw_gportal_entry_traffic_policy + ( + id bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + gw_id bigint(11) not null , + gw_name varchar(255) DEFAULT null , + traffic_color_name varchar(255) DEFAULT null , + application_name varchar(255) DEFAULT null , + service_name varchar(255) DEFAULT null , + route_rule_names varchar(255) DEFAULT null , + create_time bigint not null , + update_time bigint not null , + route_rule_ids varchar(255) not null, + enable_status int(4) default 0 , + traffic_match varchar(255) DEFAULT null , + color_tag varchar(255) DEFAULT null , + protocol varchar(255) DEFAULT null , + param text DEFAULT null + ); \ No newline at end of file diff --git a/gateway-portal/src/test/java/org/hango/cloud/dashboard/apiserver/service/impl/RegistryCenterServiceImplTest.java b/gateway-portal/src/test/java/org/hango/cloud/dashboard/apiserver/service/impl/RegistryCenterServiceImplTest.java new file mode 100644 index 00000000..585b4c06 --- /dev/null +++ b/gateway-portal/src/test/java/org/hango/cloud/dashboard/apiserver/service/impl/RegistryCenterServiceImplTest.java @@ -0,0 +1,39 @@ +package org.hango.cloud.dashboard.apiserver.service.impl; + +import org.hango.cloud.dashboard.BaseServiceImplTest; +import org.hango.cloud.dashboard.apiserver.meta.RegistryCenterEnum; +import org.hango.cloud.dashboard.apiserver.meta.ServiceType; +import org.hango.cloud.dashboard.apiserver.service.IRegistryCenterService; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; + +/** + * @author xin li + * @date 2022/8/16 09:23 + */ +public class RegistryCenterServiceImplTest extends BaseServiceImplTest { + private static final Logger logger = LoggerFactory.getLogger(RegistryCenterServiceImplTest.class); + + @Autowired + private IRegistryCenterService registryCenterService; + + @Test + public void testDescribeRegistryTypesByServiceType() { + List httpRegistryList = registryCenterService.describeRegistryTypesByServiceType(ServiceType.http.name()); + Assert.assertEquals(1, httpRegistryList.size()); + Assert.assertEquals(RegistryCenterEnum.Kubernetes.getType(), httpRegistryList.get(0)); + List dubboRegistryList = registryCenterService.describeRegistryTypesByServiceType(ServiceType.dubbo.name()); + Assert.assertEquals(0, dubboRegistryList.size()); + List webserviceRegistryList = registryCenterService.describeRegistryTypesByServiceType(ServiceType.webservice.name()); + Assert.assertEquals(1, webserviceRegistryList.size()); + Assert.assertEquals(RegistryCenterEnum.Kubernetes.getType(), webserviceRegistryList.get(0)); + List grpcRegistryList = registryCenterService.describeRegistryTypesByServiceType(ServiceType.grpc.name()); + Assert.assertEquals(0, grpcRegistryList.size()); + } + +} diff --git a/gateway-portal/src/test/java/org/hango/cloud/dashboard/envoy/service/impl/EnvoyHealthCheckServiceImplTest.java b/gateway-portal/src/test/java/org/hango/cloud/dashboard/envoy/service/impl/EnvoyHealthCheckServiceImplTest.java index 2bf22d1d..3f308429 100644 --- a/gateway-portal/src/test/java/org/hango/cloud/dashboard/envoy/service/impl/EnvoyHealthCheckServiceImplTest.java +++ b/gateway-portal/src/test/java/org/hango/cloud/dashboard/envoy/service/impl/EnvoyHealthCheckServiceImplTest.java @@ -19,9 +19,11 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.annotation.Rollback; import java.util.Arrays; @@ -44,7 +46,7 @@ public class EnvoyHealthCheckServiceImplTest extends BaseServiceImplTest { @Autowired @InjectMocks private EnvoyHealthCheckServiceImpl envoyHealthCheckService; - @Mock + @MockBean private GetFromApiPlaneServiceImpl getFromApiPlaneService; private ServiceInfo serviceInfo; private GatewayInfo gatewayInfo; @@ -53,8 +55,8 @@ public class EnvoyHealthCheckServiceImplTest extends BaseServiceImplTest { @Before public void init() { + MockitoAnnotations.openMocks(this); -// Mockito.doReturn(true).when(getFromApiPlaneService).publishServiceByApiPlane(Mockito.any(), Mockito.any()); Mockito.when(getFromApiPlaneService.publishServiceByApiPlane(Mockito.any(), Mockito.any())).thenReturn(true); //初始化ServiceInfo serviceInfo = new ServiceInfo(); diff --git a/gateway-portal/src/test/java/org/hango/cloud/dashboard/envoy/service/impl/EnvoyRouteRuleProxyServiceImplTest.java b/gateway-portal/src/test/java/org/hango/cloud/dashboard/envoy/service/impl/EnvoyRouteRuleProxyServiceImplTest.java index b13c2984..850655ab 100644 --- a/gateway-portal/src/test/java/org/hango/cloud/dashboard/envoy/service/impl/EnvoyRouteRuleProxyServiceImplTest.java +++ b/gateway-portal/src/test/java/org/hango/cloud/dashboard/envoy/service/impl/EnvoyRouteRuleProxyServiceImplTest.java @@ -8,13 +8,11 @@ import org.hango.cloud.dashboard.apiserver.meta.errorcode.ErrorCode; import org.hango.cloud.dashboard.apiserver.service.IGatewayInfoService; import org.hango.cloud.dashboard.apiserver.service.IRouteRuleInfoService; -import org.hango.cloud.dashboard.apiserver.service.IRouteRuleProxyService; import org.hango.cloud.dashboard.apiserver.service.IServiceInfoService; -import org.hango.cloud.dashboard.apiserver.service.IServiceProxyService; +import org.hango.cloud.dashboard.apiserver.service.impl.RouteRuleProxyServiceImpl; import org.hango.cloud.dashboard.apiserver.util.Const; import org.hango.cloud.dashboard.envoy.meta.RouteRuleInfo; import org.hango.cloud.dashboard.envoy.meta.RouteRuleProxyInfo; -import org.hango.cloud.dashboard.envoy.service.ISyncRouteProxyService; import org.hango.cloud.dashboard.envoy.web.dto.EnvoyDestinationDto; import org.hango.cloud.dashboard.envoy.web.dto.EnvoyRouteRuleMapMatchDto; import org.hango.cloud.dashboard.envoy.web.dto.EnvoyRouteStringMatchDto; @@ -28,8 +26,8 @@ import org.junit.Before; import org.junit.Test; import org.mockito.InjectMocks; -import org.mockito.Mock; import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -52,14 +50,14 @@ public class EnvoyRouteRuleProxyServiceImplTest extends BaseServiceImplTest { public IServiceInfoService serviceInfoService; @Autowired @InjectMocks - public IServiceProxyService serviceProxyService; + public EnvoyServiceProxyServiceImpl serviceProxyService; @Autowired public IRouteRuleInfoService routeRuleInfoService; @Autowired public IGatewayInfoService gatewayInfoService; @Autowired @InjectMocks - public IRouteRuleProxyService routeRuleProxyService; + public RouteRuleProxyServiceImpl routeRuleProxyService; public ServiceInfo serviceInfo; public GatewayInfo gatewayInfo; public ServiceProxyDto serviceProxyDto; @@ -71,7 +69,7 @@ public class EnvoyRouteRuleProxyServiceImplTest extends BaseServiceImplTest { public long routeId; @Autowired @InjectMocks - private ISyncRouteProxyService syncRouteProxyService; + private SyncRouteProxyServiceImpl syncRouteProxyService; @MockBean private GetFromApiPlaneServiceImpl getFromApiPlaneService; @@ -79,6 +77,7 @@ public class EnvoyRouteRuleProxyServiceImplTest extends BaseServiceImplTest { @Before public void init() { + MockitoAnnotations.openMocks(this); Mockito.when(getFromApiPlaneService.publishServiceByApiPlane(Mockito.any(), Mockito.any())).thenReturn(true); Mockito.doReturn(true).when(getFromApiPlaneService).offlineServiceByApiPlane(Mockito.any(), Mockito.any()); diff --git a/gateway-portal/src/test/java/org/hango/cloud/dashboard/envoy/service/impl/EnvoyServiceProxyServiceImplTest.java b/gateway-portal/src/test/java/org/hango/cloud/dashboard/envoy/service/impl/EnvoyServiceProxyServiceImplTest.java index 0cfc9477..2a57cba4 100644 --- a/gateway-portal/src/test/java/org/hango/cloud/dashboard/envoy/service/impl/EnvoyServiceProxyServiceImplTest.java +++ b/gateway-portal/src/test/java/org/hango/cloud/dashboard/envoy/service/impl/EnvoyServiceProxyServiceImplTest.java @@ -23,7 +23,6 @@ import org.junit.Before; import org.junit.Test; import org.mockito.InjectMocks; -import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.slf4j.Logger; @@ -81,6 +80,8 @@ public class EnvoyServiceProxyServiceImplTest extends BaseServiceImplTest { @Before public void init() { + MockitoAnnotations.openMocks(this); + Mockito.when(getFromApiPlaneService.publishServiceByApiPlane(Mockito.any(), Mockito.any())).thenReturn(true); Mockito.doReturn(true).when(getFromApiPlaneService).offlineServiceByApiPlane(Mockito.any(), Mockito.any()); // Mockito.doReturn(Lists.newArrayList()).when(getFromApiPlaneService).getServiceListFromApiPlane(Mockito.any(), @@ -183,6 +184,10 @@ public void getServiceListFromApiPlane() { List serviceListFromApiPlane = getFromApiPlaneService.getServiceListFromApiPlane(gwId, "", "Kubernetes", "", Collections.EMPTY_MAP); assertTrue(serviceListFromApiPlane.size() == 0); + + serviceListFromApiPlane = getFromApiPlaneService.getServiceListFromApiPlane(gwId, + "", "Nacos", "", Collections.EMPTY_MAP); + assertTrue(serviceListFromApiPlane.size() == 0); } /** diff --git a/gateway-portal/src/test/java/org/hango/cloud/dashboard/meta/DaoMetaUnitTest.java b/gateway-portal/src/test/java/org/hango/cloud/dashboard/meta/DaoMetaUnitTest.java deleted file mode 100644 index 48ef6d01..00000000 --- a/gateway-portal/src/test/java/org/hango/cloud/dashboard/meta/DaoMetaUnitTest.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.hango.cloud.dashboard.meta; - -import org.hango.cloud.dashboard.BaseServiceImplTest; -import org.junit.Test; -import org.reflections.Configuration; -import org.reflections.Reflections; -import org.reflections.scanners.SubTypesScanner; -import org.reflections.util.ClasspathHelper; -import org.reflections.util.ConfigurationBuilder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Set; - -public class DaoMetaUnitTest extends BaseServiceImplTest { - private static final Logger logger = LoggerFactory.getLogger(DaoMetaUnitTest.class); - - @Test - public void testForAllDaoMeta() { - logger.info("DaoMetaUnitTest ==== start ===="); - Configuration configuration = new ConfigurationBuilder().setUrls(ClasspathHelper.forPackage("org.hango.cloud.dashboard.apiserver")) - .setScanners(new SubTypesScanner(false)); - Reflections reflections = new Reflections(configuration); - Set> allClass = reflections.getSubTypesOf(Object.class); - for (Class clazz : allClass) { - if (clazz.getCanonicalName() != null && (clazz.getCanonicalName().endsWith("Info") || clazz.getCanonicalName().endsWith("Dto") - || clazz.getCanonicalName().endsWith("DTO"))) { - ClassMethodExecutor executor = new ClassMethodExecutor(clazz); - executor.executeAllMethod(); - } - } - System.out.println(projectId); - logger.info("DaoMetaUnitTest ==== end ===="); - - } - -} diff --git a/gateway-portal/src/test/resources/application.properties b/gateway-portal/src/test/resources/application.properties index 72655345..2037b5fc 100644 --- a/gateway-portal/src/test/resources/application.properties +++ b/gateway-portal/src/test/resources/application.properties @@ -2,20 +2,21 @@ server.port=8898 #设置上传的文件大小 spring.http.multipart.max-file-size=10Mb spring.http.multipart.max-request-size=10Mb -spring.http.encoding.charset=UTF-8 -spring.http.encoding.force=true +server.servlet.encoding.charset=UTF-8 +server.servlet.encoding.force=true # 使用H2数据库 spring.datasource.url=jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;MODE=MYSQL;TRACE_LEVEL_FIle=4;TRACE_LEVEL_SYSTEM_OUT=3;DATABASE_TO_UPPER=false -spring.datasource.platform=h2 +spring.sql.init.platform=h2 spring.datasource.driverClassName=org.h2.Driver spring.datasource.username=sa spring.datasource.password=root spring.jpa.database-platform=org.hibernate.dialect.H2Dialect spring.jpa.hibernate.ddl-auto=create-drop -spring.datasource.initialization-mode=always -spring.datasource.schema=classpath:schema.sql -spring.datasource.data=classpath:data.sql +spring.sql.init.mode=always +spring.sql.init.schema-locations=classpath:schema.sql +spring.sql.init.data-locations=classpath:data.sql spring.h2.console.enabled=true spring.h2.console.path=/h2 # 数据库前缀 -databasePrefix=apigw_gportal_ \ No newline at end of file +databasePrefix=apigw_gportal_ +spring.main.allow-bean-definition-overriding=true \ No newline at end of file diff --git a/gateway-portal/src/test/resources/schema.sql b/gateway-portal/src/test/resources/schema.sql index d8668208..b23a3326 100644 --- a/gateway-portal/src/test/resources/schema.sql +++ b/gateway-portal/src/test/resources/schema.sql @@ -859,3 +859,21 @@ CREATE TABLE IF NOT EXISTS apigw_gportal_api ( PRIMARY KEY (id) ) ; + CREATE TABLE IF NOT EXISTS apigw_gportal_entry_traffic_policy + ( + id bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + gw_id bigint(11) not null , + gw_name varchar(255) DEFAULT null , + traffic_color_name varchar(255) DEFAULT null , + application_name varchar(255) DEFAULT null , + service_name varchar(255) DEFAULT null , + route_rule_names varchar(255) DEFAULT null , + create_time bigint not null , + update_time bigint not null , + route_rule_ids varchar(255) not null, + enable_status int(4) default 0 , + traffic_match varchar(255) DEFAULT null , + color_tag varchar(255) DEFAULT null , + protocol varchar(255) DEFAULT null , + param text DEFAULT null + ); diff --git a/pom.xml b/pom.xml index 786db038..d0ce8e0c 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot spring-boot-starter-parent - 1.5.4.RELEASE + 2.5.14 @@ -18,9 +18,22 @@ ${project.basedir}/../target/jacoco.exec java 0.0.2 + 2020.0.6 + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring.cloud.version} + pom + import + + + + 4.0.0 org.hango.cloud hango-gateway-portal-parent