Skip to content

Commit

Permalink
增加postgresql和openGauss的数据库禁写功能实现
Browse files Browse the repository at this point in the history
Signed-off-by: hanbingleixue <[email protected]>
  • Loading branch information
hanbingleixue committed Feb 22, 2024
1 parent 61c932f commit 680a651
Show file tree
Hide file tree
Showing 25 changed files with 1,492 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,12 @@

import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext;
import com.huaweicloud.sermant.core.plugin.agent.interceptor.AbstractInterceptor;
import com.huaweicloud.sermant.database.controller.DatabaseController;
import com.huaweicloud.sermant.database.entity.DatabaseInfo;
import com.huaweicloud.sermant.database.handler.DatabaseHandler;
import com.huaweicloud.sermant.database.utils.SqlParserUtils;

import java.util.Set;

/**
* 数据库抽象interceptor
Expand Down Expand Up @@ -90,4 +94,19 @@ public ExecuteContext onThrow(ExecuteContext context) throws Exception {
protected DatabaseInfo getDataBaseInfo(ExecuteContext context) {
return (DatabaseInfo) context.getLocalFieldValue(DATABASE_INFO);
}

/**
* 如果当前数据库开启禁写,并且为写操作,则执行禁写逻辑处理,
*
* @param sql 执行的SQL
* @param databaseName 执行SQL的数据库名称
* @param prohibitionDatabases 禁写的数据库集合
* @param context 上下文信息
*/
protected void handleWriteOperationIfWriteDisabled(String sql, String databaseName,
Set<String> prohibitionDatabases, ExecuteContext context) {
if (prohibitionDatabases.contains(databaseName) && SqlParserUtils.isWriteOperation(sql)) {
DatabaseController.disableDatabaseWriteOperation(databaseName, context);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>sermant-database-write-prohibition</artifactId>
<groupId>com.huaweicloud.sermant</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>opengauss-3.0.x-plugin</artifactId>

<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<config.skip.flag>false</config.skip.flag>
<package.plugin.type>plugin</package.plugin.type>
<opengauss.version>3.0.0</opengauss.version>
</properties>

<dependencies>
<dependency>
<groupId>com.huaweicloud.sermant</groupId>
<artifactId>sermant-agentcore-core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.opengauss</groupId>
<artifactId>opengauss-jdbc</artifactId>
<version>${opengauss.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.huaweicloud.sermant</groupId>
<artifactId>database-controller</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright (C) 2024-2024 Huawei Technologies Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.huaweicloud.sermant.opengaussv30.declarers;

import com.huaweicloud.sermant.core.plugin.agent.declarer.AbstractPluginDeclarer;
import com.huaweicloud.sermant.core.plugin.agent.declarer.InterceptDeclarer;
import com.huaweicloud.sermant.core.plugin.agent.matcher.ClassMatcher;
import com.huaweicloud.sermant.opengaussv30.utils.QueryExecutorImplEnhancementHelper;

/**
* SQL执行器增强声明器
*
* @author zhp
* @since 2024-02-04
**/
public class QueryExecutorImplDeclarer extends AbstractPluginDeclarer {
@Override
public ClassMatcher getClassMatcher() {
return QueryExecutorImplEnhancementHelper.getQueryExecutorImplClassMatcher();
}

@Override
public InterceptDeclarer[] getInterceptDeclarers(ClassLoader classLoader) {
return new InterceptDeclarer[]{QueryExecutorImplEnhancementHelper.getSendQueryInterceptDeclarer()};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Copyright (C) 2024-2024 Huawei Technologies Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.huaweicloud.sermant.opengaussv30.interceptors;

import com.huaweicloud.sermant.core.common.LoggerFactory;
import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext;
import com.huaweicloud.sermant.database.config.DatabaseWriteProhibitionManager;
import com.huaweicloud.sermant.database.constant.DatabaseType;
import com.huaweicloud.sermant.database.entity.DatabaseInfo;
import com.huaweicloud.sermant.database.handler.DatabaseHandler;
import com.huaweicloud.sermant.database.interceptor.AbstractDatabaseInterceptor;

import org.opengauss.core.Query;
import org.opengauss.core.v3.QueryExecutorImpl;
import org.opengauss.util.HostSpec;

import java.util.logging.Logger;

/**
* 执行SQL操作的拦截器
*
* @author zhp
* @since 2024-02-04
**/
public class QueryExecutorImplInterceptor extends AbstractDatabaseInterceptor {
private static final Logger LOGGER = LoggerFactory.getLogger();

/**
* 无参构造方法
*/
public QueryExecutorImplInterceptor() {
}

/**
* 有参构造方法
*
* @param handler 写操作处理器
*/
public QueryExecutorImplInterceptor(DatabaseHandler handler) {
this.handler = handler;
}

@Override
public ExecuteContext doBefore(ExecuteContext context) {
DatabaseInfo databaseInfo = getDataBaseInfo(context);
String database = databaseInfo.getDatabaseName();
Query query = (Query) context.getArguments()[0];
String sql = query.getNativeSql();
handleWriteOperationIfWriteDisabled(sql, database,
DatabaseWriteProhibitionManager.getOpenGaussProhibitionDatabases(), context);
return context;
}

@Override
protected void createAndCacheDatabaseInfo(ExecuteContext context) {
QueryExecutorImpl queryExecutor = (QueryExecutorImpl) context.getObject();
DatabaseInfo databaseInfo = new DatabaseInfo(DatabaseType.OPENGAUSS);
context.setLocalFieldValue(DATABASE_INFO, databaseInfo);
databaseInfo.setDatabaseName(queryExecutor.getDatabase());
HostSpec hostSpec = queryExecutor.getHostSpec();
if (hostSpec == null) {
LOGGER.info("Unable to obtain the link address of the database.");
return;
}
databaseInfo.setPort(hostSpec.getPort());
databaseInfo.setHostAddress(hostSpec.getHost());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* Copyright (C) 2024-2024 Huawei Technologies Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.huaweicloud.sermant.opengaussv30.utils;

import com.huaweicloud.sermant.core.plugin.agent.declarer.InterceptDeclarer;
import com.huaweicloud.sermant.core.plugin.agent.matcher.ClassMatcher;
import com.huaweicloud.sermant.core.plugin.agent.matcher.MethodMatcher;
import com.huaweicloud.sermant.database.handler.DatabaseHandler;
import com.huaweicloud.sermant.opengaussv30.interceptors.QueryExecutorImplInterceptor;

/**
* postgresql拦截点辅助类
*
* @author zhp
* @since 2024-02-04
**/
public class QueryExecutorImplEnhancementHelper {
private static final String EXECUTE_METHOD_NAME = "sendQuery";

private static final String ENHANCE_CLASS_NAME = "org.opengauss.core.v3.QueryExecutorImpl";

private static final String INT_CLASS_NAME = "int";

private static final String QUERY_CLASS_NAME = "org.opengauss.core.Query";

private static final String V3_PARAMETER_LIST_CLASS_NAME = "org.opengauss.core.v3.V3ParameterList";

private static final String RESULT_HANDLER_CLASS_NAME = "org.opengauss.core.ResultHandler";

private static final String BATCH_RESULT_HANDLER_CLASS_NAME = "org.opengauss.jdbc.BatchResultHandler";

private static final String[] EXECUTE_INTERNAL_METHOD_PARAMS_TYPE = {
QUERY_CLASS_NAME,
V3_PARAMETER_LIST_CLASS_NAME,
INT_CLASS_NAME,
INT_CLASS_NAME,
INT_CLASS_NAME,
RESULT_HANDLER_CLASS_NAME,
BATCH_RESULT_HANDLER_CLASS_NAME
};

private QueryExecutorImplEnhancementHelper() {
}

private static MethodMatcher getSendQueryMethodMatcher() {
return MethodMatcher.nameEquals(EXECUTE_METHOD_NAME)
.and(MethodMatcher.paramTypesEqual(EXECUTE_INTERNAL_METHOD_PARAMS_TYPE));
}

/**
* 获取QueryExecutorImpl sendQuery方法有参拦截声明器
*
* @param handler 数据库自定义处理器
* @return InterceptDeclarer QueryExecutorImpl sendQuery方法有参拦截声明器
*/
public static InterceptDeclarer getSendQueryInterceptDeclarer(DatabaseHandler handler) {
return InterceptDeclarer.build(getSendQueryMethodMatcher(), new QueryExecutorImplInterceptor(handler));
}

/**
* 获取QueryExecutorImpl sendQuery方法无参拦截声明器
*
* @return InterceptDeclarer QueryExecutorImpl sendQuery方法无参拦截声明器
*/
public static InterceptDeclarer getSendQueryInterceptDeclarer() {
return InterceptDeclarer.build(getSendQueryMethodMatcher(), new QueryExecutorImplInterceptor());
}

/**
* 获取QueryExecutorImpl类的ClassMatcher
*
* @return ClassMatcher 类匹配器
*/
public static ClassMatcher getQueryExecutorImplClassMatcher() {
return ClassMatcher.nameEquals(ENHANCE_CLASS_NAME);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#
# Copyright (C) 2024-2024 Huawei Technologies Co., Ltd. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
com.huaweicloud.sermant.opengaussv30.declarers.QueryExecutorImplDeclarer
Loading

0 comments on commit 680a651

Please sign in to comment.