Add MySQL DataBase (#6968)
This commit is contained in:
parent
76ac84344c
commit
3c0508d2da
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2021 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* 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.alibaba.nacos.auth.configuration;
|
||||||
|
|
||||||
|
import com.alibaba.nacos.auth.util.AuthPropertyUtil;
|
||||||
|
import org.springframework.context.annotation.Condition;
|
||||||
|
import org.springframework.context.annotation.ConditionContext;
|
||||||
|
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Judge whether to user ExternalStorage by condition.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||||
|
*/
|
||||||
|
public class ConditionOnExternalStorage implements Condition {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
|
||||||
|
return !AuthPropertyUtil.isEmbeddedStorage();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* 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.alibaba.nacos.auth.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PropertiesConstant.
|
||||||
|
*
|
||||||
|
* @author lixiaoshuang
|
||||||
|
*/
|
||||||
|
public class PropertiesConstant {
|
||||||
|
|
||||||
|
public static final String NOTIFY_CONNECT_TIMEOUT = "notifyConnectTimeout";
|
||||||
|
|
||||||
|
public static final String NOTIFY_SOCKET_TIMEOUT = "notifySocketTimeout";
|
||||||
|
|
||||||
|
public static final String IS_HEALTH_CHECK = "isHealthCheck";
|
||||||
|
|
||||||
|
public static final String MAX_HEALTH_CHECK_FAIL_COUNT = "maxHealthCheckFailCount";
|
||||||
|
|
||||||
|
public static final String MAX_CONTENT = "maxContent";
|
||||||
|
|
||||||
|
public static final String IS_MANAGE_CAPACITY = "isManageCapacity";
|
||||||
|
|
||||||
|
public static final String IS_CAPACITY_LIMIT_CHECK = "isCapacityLimitCheck";
|
||||||
|
|
||||||
|
public static final String DEFAULT_CLUSTER_QUOTA = "defaultClusterQuota";
|
||||||
|
|
||||||
|
public static final String DEFAULT_GROUP_QUOTA = "defaultGroupQuota";
|
||||||
|
|
||||||
|
public static final String DEFAULT_TENANT_QUOTA = "defaultTenantQuota";
|
||||||
|
|
||||||
|
public static final String DEFAULT_MAX_SIZE = "defaultMaxSize";
|
||||||
|
|
||||||
|
public static final String DEFAULT_MAX_AGGR_COUNT = "defaultMaxAggrCount";
|
||||||
|
|
||||||
|
public static final String DEFAULT_MAX_AGGR_SIZE = "defaultMaxAggrSize";
|
||||||
|
|
||||||
|
public static final String CORRECT_USAGE_DELAY = "correctUsageDelay";
|
||||||
|
|
||||||
|
public static final String INITIAL_EXPANSION_PERCENT = "initialExpansionPercent";
|
||||||
|
|
||||||
|
public static final String SPRING_DATASOURCE_PLATFORM = "spring.datasource.platform";
|
||||||
|
|
||||||
|
public static final String MYSQL = "mysql";
|
||||||
|
|
||||||
|
public static final String EMBEDDED_STORAGE = "embeddedStorage";
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2021 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* 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.alibaba.nacos.auth.persist;
|
||||||
|
|
||||||
|
import com.alibaba.nacos.auth.configuration.ConditionOnExternalStorage;
|
||||||
|
import com.alibaba.nacos.auth.model.Page;
|
||||||
|
import com.alibaba.nacos.auth.model.PermissionInfo;
|
||||||
|
import com.alibaba.nacos.auth.persist.repository.PaginationHelper;
|
||||||
|
import com.alibaba.nacos.auth.persist.repository.externel.ExternalStoragePersistServiceImpl;
|
||||||
|
import com.alibaba.nacos.auth.util.LogUtil;
|
||||||
|
import com.alibaba.nacos.common.utils.StringUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Conditional;
|
||||||
|
import org.springframework.jdbc.CannotGetJdbcConnectionException;
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
import org.springframework.jdbc.core.RowMapper;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implemetation of ExternalPermissionPersistServiceImpl.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||||
|
*/
|
||||||
|
@Conditional(value = ConditionOnExternalStorage.class)
|
||||||
|
@Component
|
||||||
|
public class ExternalPermissionPersistServiceImpl implements PermissionPersistService {
|
||||||
|
|
||||||
|
public static final PermissionRowMapper PERMISSION_ROW_MAPPER = new PermissionRowMapper();
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ExternalStoragePersistServiceImpl persistService;
|
||||||
|
|
||||||
|
private JdbcTemplate jt;
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
protected void init() {
|
||||||
|
jt = persistService.getJdbcTemplate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Page<PermissionInfo> getPermissions(String role, int pageNo, int pageSize) {
|
||||||
|
PaginationHelper<PermissionInfo> helper = persistService.createPaginationHelper();
|
||||||
|
|
||||||
|
String sqlCountRows = "SELECT count(*) FROM permissions WHERE ";
|
||||||
|
String sqlFetchRows = "SELECT role,resource,action FROM permissions WHERE ";
|
||||||
|
|
||||||
|
String where = " role= ? ";
|
||||||
|
List<String> params = new ArrayList<>();
|
||||||
|
if (StringUtils.isNotBlank(role)) {
|
||||||
|
params = Collections.singletonList(role);
|
||||||
|
} else {
|
||||||
|
where = " 1=1 ";
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Page<PermissionInfo> pageInfo = helper
|
||||||
|
.fetchPage(sqlCountRows + where, sqlFetchRows + where, params.toArray(), pageNo,
|
||||||
|
pageSize, PERMISSION_ROW_MAPPER);
|
||||||
|
|
||||||
|
if (pageInfo == null) {
|
||||||
|
pageInfo = new Page<>();
|
||||||
|
pageInfo.setTotalCount(0);
|
||||||
|
pageInfo.setPageItems(new ArrayList<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
return pageInfo;
|
||||||
|
|
||||||
|
} catch (CannotGetJdbcConnectionException e) {
|
||||||
|
LogUtil.FATAL_LOG.error("[db-error] " + e.toString(), e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class PermissionRowMapper implements RowMapper<PermissionInfo> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PermissionInfo mapRow(ResultSet rs, int rowNum) throws SQLException {
|
||||||
|
PermissionInfo info = new PermissionInfo();
|
||||||
|
info.setResource(rs.getString("resource"));
|
||||||
|
info.setAction(rs.getString("action"));
|
||||||
|
info.setRole(rs.getString("role"));
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2021 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* 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.alibaba.nacos.auth.persist;
|
||||||
|
|
||||||
|
import com.alibaba.nacos.auth.configuration.ConditionOnExternalStorage;
|
||||||
|
import com.alibaba.nacos.auth.model.Page;
|
||||||
|
import com.alibaba.nacos.auth.persist.repository.PaginationHelper;
|
||||||
|
import com.alibaba.nacos.auth.persist.repository.externel.ExternalStoragePersistServiceImpl;
|
||||||
|
import com.alibaba.nacos.auth.roles.RoleInfo;
|
||||||
|
import com.alibaba.nacos.auth.util.LogUtil;
|
||||||
|
import com.alibaba.nacos.common.utils.StringUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Conditional;
|
||||||
|
import org.springframework.jdbc.CannotGetJdbcConnectionException;
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
import org.springframework.jdbc.core.RowMapper;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implemetation of ExternalRolePersistServiceImpl.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||||
|
*/
|
||||||
|
@Conditional(value = ConditionOnExternalStorage.class)
|
||||||
|
@Component
|
||||||
|
public class ExternalRolePersistServiceImpl implements RolePersistService {
|
||||||
|
|
||||||
|
public static final RoleInfoRowMapper ROLE_INFO_ROW_MAPPER = new RoleInfoRowMapper();
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ExternalStoragePersistServiceImpl persistService;
|
||||||
|
|
||||||
|
private JdbcTemplate jt;
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
protected void init() {
|
||||||
|
jt = persistService.getJdbcTemplate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Page<RoleInfo> getRolesByUserName(String username, int pageNo, int pageSize) {
|
||||||
|
|
||||||
|
PaginationHelper<RoleInfo> helper = persistService.createPaginationHelper();
|
||||||
|
|
||||||
|
String sqlCountRows = "SELECT count(*) FROM roles WHERE ";
|
||||||
|
|
||||||
|
String sqlFetchRows = "SELECT role,username FROM roles WHERE ";
|
||||||
|
|
||||||
|
String where = " username= ? ";
|
||||||
|
List<String> params = new ArrayList<>();
|
||||||
|
if (StringUtils.isNotBlank(username)) {
|
||||||
|
params = Collections.singletonList(username);
|
||||||
|
} else {
|
||||||
|
where = " 1=1 ";
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return helper.fetchPage(sqlCountRows + where, sqlFetchRows + where, params.toArray(), pageNo, pageSize,
|
||||||
|
ROLE_INFO_ROW_MAPPER);
|
||||||
|
} catch (CannotGetJdbcConnectionException e) {
|
||||||
|
LogUtil.FATAL_LOG.error("[db-error] " + e.toString(), e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class RoleInfoRowMapper implements RowMapper<RoleInfo> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RoleInfo mapRow(ResultSet rs, int rowNum) throws SQLException {
|
||||||
|
RoleInfo roleInfo = new RoleInfo();
|
||||||
|
roleInfo.setRole(rs.getString("role"));
|
||||||
|
roleInfo.setUsername(rs.getString("username"));
|
||||||
|
return roleInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,136 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2021 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* 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.alibaba.nacos.auth.persist;
|
||||||
|
|
||||||
|
import com.alibaba.nacos.auth.configuration.ConditionOnExternalStorage;
|
||||||
|
import com.alibaba.nacos.auth.model.Page;
|
||||||
|
import com.alibaba.nacos.auth.persist.repository.PaginationHelper;
|
||||||
|
import com.alibaba.nacos.auth.persist.repository.externel.ExternalStoragePersistServiceImpl;
|
||||||
|
import com.alibaba.nacos.auth.users.User;
|
||||||
|
import com.alibaba.nacos.auth.util.LogUtil;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Conditional;
|
||||||
|
import org.springframework.dao.EmptyResultDataAccessException;
|
||||||
|
import org.springframework.jdbc.CannotGetJdbcConnectionException;
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
import org.springframework.jdbc.core.RowMapper;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implemetation of ExternalUserPersistServiceImpl.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||||
|
*/
|
||||||
|
@Conditional(value = ConditionOnExternalStorage.class)
|
||||||
|
@Component
|
||||||
|
public class ExternalUserPersistServiceImpl implements UserPersistService {
|
||||||
|
|
||||||
|
public static final RowMapper<User> USER_ROW_MAPPER = new UserRowMapper();
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ExternalStoragePersistServiceImpl persistService;
|
||||||
|
|
||||||
|
private JdbcTemplate jt;
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
protected void init() {
|
||||||
|
jt = persistService.getJdbcTemplate();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute create user operation.
|
||||||
|
*
|
||||||
|
* @param username username string value.
|
||||||
|
* @param password password string value.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void createUser(String username, String password) {
|
||||||
|
String sql = "INSERT INTO users (username, password, enabled) VALUES (?, ?, ?)";
|
||||||
|
|
||||||
|
try {
|
||||||
|
jt.update(sql, username, password, true);
|
||||||
|
} catch (CannotGetJdbcConnectionException e) {
|
||||||
|
LogUtil.FATAL_LOG.error("[db-error] " + e.toString(), e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute find user by username operation.
|
||||||
|
*
|
||||||
|
* @param username username string value.
|
||||||
|
* @return User model.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public User findUserByUsername(String username) {
|
||||||
|
String sql = "SELECT username,password FROM users WHERE username=? ";
|
||||||
|
try {
|
||||||
|
return this.jt.queryForObject(sql, new Object[] {username}, USER_ROW_MAPPER);
|
||||||
|
} catch (CannotGetJdbcConnectionException e) {
|
||||||
|
LogUtil.FATAL_LOG.error("[db-error] " + e.toString(), e);
|
||||||
|
throw e;
|
||||||
|
} catch (EmptyResultDataAccessException e) {
|
||||||
|
return null;
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogUtil.FATAL_LOG.error("[db-other-error]" + e.getMessage(), e);
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Page<User> getUsers(int pageNo, int pageSize) {
|
||||||
|
|
||||||
|
PaginationHelper<User> helper = persistService.createPaginationHelper();
|
||||||
|
|
||||||
|
String sqlCountRows = "SELECT count(*) FROM users WHERE ";
|
||||||
|
|
||||||
|
String sqlFetchRows = "SELECT username,password FROM users WHERE ";
|
||||||
|
|
||||||
|
String where = " 1=1 ";
|
||||||
|
|
||||||
|
try {
|
||||||
|
Page<User> pageInfo = helper
|
||||||
|
.fetchPage(sqlCountRows + where, sqlFetchRows + where, new ArrayList<String>().toArray(), pageNo,
|
||||||
|
pageSize, USER_ROW_MAPPER);
|
||||||
|
if (pageInfo == null) {
|
||||||
|
pageInfo = new Page<>();
|
||||||
|
pageInfo.setTotalCount(0);
|
||||||
|
pageInfo.setPageItems(new ArrayList<>());
|
||||||
|
}
|
||||||
|
return pageInfo;
|
||||||
|
} catch (CannotGetJdbcConnectionException e) {
|
||||||
|
LogUtil.FATAL_LOG.error("[db-error] " + e.toString(), e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class UserRowMapper implements RowMapper<User> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
|
||||||
|
User user = new User();
|
||||||
|
user.setUsername(rs.getString("username"));
|
||||||
|
user.setPassword(rs.getString("password"));
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2021 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* 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.alibaba.nacos.auth.persist.datasource;
|
||||||
|
|
||||||
|
import com.zaxxer.hikari.HikariDataSource;
|
||||||
|
import org.springframework.boot.context.properties.bind.Bindable;
|
||||||
|
import org.springframework.boot.context.properties.bind.Binder;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DataSource pool properties.
|
||||||
|
*
|
||||||
|
* <p>Nacos server use HikariCP as the datasource pool. So the basic pool properties will based on {@link
|
||||||
|
* HikariDataSource}.
|
||||||
|
*
|
||||||
|
* @author xiweng.yy
|
||||||
|
*/
|
||||||
|
public class DataSourcePoolProperties {
|
||||||
|
|
||||||
|
public static final long DEFAULT_CONNECTION_TIMEOUT = TimeUnit.SECONDS.toMillis(30L);
|
||||||
|
|
||||||
|
public static final long DEFAULT_VALIDATION_TIMEOUT = TimeUnit.SECONDS.toMillis(10L);
|
||||||
|
|
||||||
|
public static final int DEFAULT_MAX_POOL_SIZE = 20;
|
||||||
|
|
||||||
|
public static final int DEFAULT_MINIMUM_IDLE = 2;
|
||||||
|
|
||||||
|
private final HikariDataSource dataSource;
|
||||||
|
|
||||||
|
private DataSourcePoolProperties() {
|
||||||
|
dataSource = new HikariDataSource();
|
||||||
|
dataSource.setConnectionTimeout(DEFAULT_CONNECTION_TIMEOUT);
|
||||||
|
dataSource.setValidationTimeout(DEFAULT_VALIDATION_TIMEOUT);
|
||||||
|
dataSource.setMaximumPoolSize(DEFAULT_MAX_POOL_SIZE);
|
||||||
|
dataSource.setMinimumIdle(DEFAULT_MINIMUM_IDLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build new Hikari config.
|
||||||
|
*
|
||||||
|
* @return new hikari config
|
||||||
|
*/
|
||||||
|
public static DataSourcePoolProperties build(Environment environment) {
|
||||||
|
DataSourcePoolProperties result = new DataSourcePoolProperties();
|
||||||
|
Binder.get(environment).bind("db.pool.config", Bindable.ofInstance(result.getDataSource()));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDriverClassName(final String driverClassName) {
|
||||||
|
dataSource.setDriverClassName(driverClassName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setJdbcUrl(final String jdbcUrl) {
|
||||||
|
dataSource.setJdbcUrl(jdbcUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsername(final String username) {
|
||||||
|
dataSource.setUsername(username);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPassword(final String password) {
|
||||||
|
dataSource.setPassword(password);
|
||||||
|
}
|
||||||
|
|
||||||
|
public HikariDataSource getDataSource() {
|
||||||
|
return dataSource;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2021 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* 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.alibaba.nacos.auth.persist.datasource;
|
||||||
|
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
import org.springframework.transaction.support.TransactionTemplate;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Datasource interface.
|
||||||
|
*
|
||||||
|
* @author Nacos
|
||||||
|
*/
|
||||||
|
public interface DataSourceService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the relevant resource information.
|
||||||
|
*
|
||||||
|
* @throws Exception exception.
|
||||||
|
*/
|
||||||
|
void init() throws Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reload.
|
||||||
|
*
|
||||||
|
* @throws IOException exception.
|
||||||
|
*/
|
||||||
|
void reload() throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check master db.
|
||||||
|
*
|
||||||
|
* @return is master.
|
||||||
|
*/
|
||||||
|
boolean checkMasterWritable();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get jdbc template.
|
||||||
|
*
|
||||||
|
* @return JdbcTemplate.
|
||||||
|
*/
|
||||||
|
JdbcTemplate getJdbcTemplate();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get transaction template.
|
||||||
|
*
|
||||||
|
* @return TransactionTemplate.
|
||||||
|
*/
|
||||||
|
TransactionTemplate getTransactionTemplate();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get current db url.
|
||||||
|
*
|
||||||
|
* @return database url
|
||||||
|
*/
|
||||||
|
String getCurrentDbUrl();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get heath information.
|
||||||
|
*
|
||||||
|
* @return heath info.
|
||||||
|
*/
|
||||||
|
String getHealth();
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2021 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* 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.alibaba.nacos.auth.persist.datasource;
|
||||||
|
|
||||||
|
import com.alibaba.nacos.auth.util.AuthPropertyUtil;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Datasource adapter.
|
||||||
|
*
|
||||||
|
* @author Nacos
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class DynamicDataSource {
|
||||||
|
|
||||||
|
private DataSourceService localDataSourceService = null;
|
||||||
|
|
||||||
|
private DataSourceService basicDataSourceService = null;
|
||||||
|
|
||||||
|
private static final DynamicDataSource INSTANCE = new DynamicDataSource();
|
||||||
|
|
||||||
|
public static DynamicDataSource getInstance() {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized DataSourceService getDataSource() {
|
||||||
|
try {
|
||||||
|
|
||||||
|
// Embedded storage is used by default in stand-alone mode
|
||||||
|
// In cluster mode, external databases are used by default
|
||||||
|
|
||||||
|
if (AuthPropertyUtil.isEmbeddedStorage()) {
|
||||||
|
if (localDataSourceService == null) {
|
||||||
|
localDataSourceService = new LocalDataSourceServiceImpl();
|
||||||
|
localDataSourceService.init();
|
||||||
|
}
|
||||||
|
return localDataSourceService;
|
||||||
|
} else {
|
||||||
|
if (basicDataSourceService == null) {
|
||||||
|
basicDataSourceService = new ExternalDataSourceServiceImpl();
|
||||||
|
basicDataSourceService.init();
|
||||||
|
}
|
||||||
|
return basicDataSourceService;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2021 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* 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.alibaba.nacos.auth.persist.datasource;
|
||||||
|
|
||||||
|
import com.alibaba.nacos.auth.util.Preconditions;
|
||||||
|
|
||||||
|
import com.alibaba.nacos.common.utils.CollectionUtils;
|
||||||
|
import com.zaxxer.hikari.HikariDataSource;
|
||||||
|
import org.springframework.boot.context.properties.bind.Bindable;
|
||||||
|
import org.springframework.boot.context.properties.bind.Binder;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import static com.alibaba.nacos.common.utils.CollectionUtils.getOrDefault;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Properties of external DataSource.
|
||||||
|
*
|
||||||
|
* @author Nacos
|
||||||
|
*/
|
||||||
|
public class ExternalDataSourceProperties {
|
||||||
|
|
||||||
|
private static final String JDBC_DRIVER_NAME = "com.mysql.cj.jdbc.Driver";
|
||||||
|
|
||||||
|
private static final String TEST_QUERY = "SELECT 1";
|
||||||
|
|
||||||
|
private Integer num;
|
||||||
|
|
||||||
|
private List<String> url = new ArrayList<>();
|
||||||
|
|
||||||
|
private List<String> user = new ArrayList<>();
|
||||||
|
|
||||||
|
private List<String> password = new ArrayList<>();
|
||||||
|
|
||||||
|
public void setNum(Integer num) {
|
||||||
|
this.num = num;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUrl(List<String> url) {
|
||||||
|
this.url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUser(List<String> user) {
|
||||||
|
this.user = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPassword(List<String> password) {
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build serveral HikariDataSource.
|
||||||
|
*
|
||||||
|
* @param environment {@link Environment}
|
||||||
|
* @param callback Callback function when constructing data source
|
||||||
|
* @return List of {@link HikariDataSource}
|
||||||
|
*/
|
||||||
|
List<HikariDataSource> build(Environment environment, Callback<HikariDataSource> callback) {
|
||||||
|
List<HikariDataSource> dataSources = new ArrayList<>();
|
||||||
|
Binder.get(environment).bind("db", Bindable.ofInstance(this));
|
||||||
|
Preconditions.checkArgument(Objects.nonNull(num), "db.num is null");
|
||||||
|
Preconditions.checkArgument(CollectionUtils.isNotEmpty(user), "db.user or db.user.[index] is null");
|
||||||
|
Preconditions.checkArgument(CollectionUtils.isNotEmpty(password), "db.password or db.password.[index] is null");
|
||||||
|
for (int index = 0; index < num; index++) {
|
||||||
|
int currentSize = index + 1;
|
||||||
|
Preconditions.checkArgument(url.size() >= currentSize, "db.url.%s is null", index);
|
||||||
|
DataSourcePoolProperties poolProperties = DataSourcePoolProperties.build(environment);
|
||||||
|
poolProperties.setDriverClassName(JDBC_DRIVER_NAME);
|
||||||
|
poolProperties.setJdbcUrl(url.get(index).trim());
|
||||||
|
poolProperties.setUsername(getOrDefault(user, index, user.get(0)).trim());
|
||||||
|
poolProperties.setPassword(getOrDefault(password, index, password.get(0)).trim());
|
||||||
|
HikariDataSource ds = poolProperties.getDataSource();
|
||||||
|
ds.setConnectionTestQuery(TEST_QUERY);
|
||||||
|
ds.setIdleTimeout(TimeUnit.MINUTES.toMillis(10L));
|
||||||
|
ds.setConnectionTimeout(TimeUnit.SECONDS.toMillis(3L));
|
||||||
|
dataSources.add(ds);
|
||||||
|
callback.accept(ds);
|
||||||
|
}
|
||||||
|
Preconditions.checkArgument(CollectionUtils.isNotEmpty(dataSources), "no datasource available");
|
||||||
|
return dataSources;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Callback<D> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform custom logic.
|
||||||
|
*
|
||||||
|
* @param datasource dataSource.
|
||||||
|
*/
|
||||||
|
void accept(D datasource);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,260 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2021 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* 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.alibaba.nacos.auth.persist.datasource;
|
||||||
|
|
||||||
|
import com.alibaba.nacos.auth.util.AuthPropertyUtil;
|
||||||
|
import com.alibaba.nacos.common.utils.ConvertUtils;
|
||||||
|
import com.alibaba.nacos.common.utils.InternetAddressUtil;
|
||||||
|
import com.alibaba.nacos.common.utils.StringUtils;
|
||||||
|
import com.alibaba.nacos.sys.env.EnvUtil;
|
||||||
|
import com.zaxxer.hikari.HikariDataSource;
|
||||||
|
import org.springframework.dao.DataAccessException;
|
||||||
|
import org.springframework.jdbc.CannotGetJdbcConnectionException;
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
||||||
|
import org.springframework.transaction.support.TransactionTemplate;
|
||||||
|
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import static com.alibaba.nacos.auth.util.LogUtil.DEFAULT_LOG;
|
||||||
|
import static com.alibaba.nacos.auth.util.LogUtil.FATAL_LOG;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base data source.
|
||||||
|
*
|
||||||
|
* @author Nacos
|
||||||
|
*/
|
||||||
|
public class ExternalDataSourceServiceImpl implements DataSourceService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JDBC execute timeout value, unit:second.
|
||||||
|
*/
|
||||||
|
private int queryTimeout = 3;
|
||||||
|
|
||||||
|
private static final int TRANSACTION_QUERY_TIMEOUT = 5;
|
||||||
|
|
||||||
|
private static final int DB_MASTER_SELECT_THRESHOLD = 1;
|
||||||
|
|
||||||
|
private static final String DB_LOAD_ERROR_MSG = "[db-load-error]load jdbc.properties error";
|
||||||
|
|
||||||
|
private List<HikariDataSource> dataSourceList = new ArrayList<>();
|
||||||
|
|
||||||
|
private JdbcTemplate jt;
|
||||||
|
|
||||||
|
private DataSourceTransactionManager tm;
|
||||||
|
|
||||||
|
private TransactionTemplate tjt;
|
||||||
|
|
||||||
|
private JdbcTemplate testMasterJT;
|
||||||
|
|
||||||
|
private JdbcTemplate testMasterWritableJT;
|
||||||
|
|
||||||
|
private volatile List<JdbcTemplate> testJtList;
|
||||||
|
|
||||||
|
private volatile List<Boolean> isHealthList;
|
||||||
|
|
||||||
|
private volatile int masterIndex;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init() {
|
||||||
|
queryTimeout = ConvertUtils.toInt(System.getProperty("QUERYTIMEOUT"), 3);
|
||||||
|
jt = new JdbcTemplate();
|
||||||
|
// Set the maximum number of records to prevent memory expansion
|
||||||
|
jt.setMaxRows(50000);
|
||||||
|
jt.setQueryTimeout(queryTimeout);
|
||||||
|
|
||||||
|
testMasterJT = new JdbcTemplate();
|
||||||
|
testMasterJT.setQueryTimeout(queryTimeout);
|
||||||
|
|
||||||
|
testMasterWritableJT = new JdbcTemplate();
|
||||||
|
// Prevent the login interface from being too long because the main library is not available
|
||||||
|
testMasterWritableJT.setQueryTimeout(1);
|
||||||
|
|
||||||
|
// Database health check
|
||||||
|
|
||||||
|
testJtList = new ArrayList<JdbcTemplate>();
|
||||||
|
isHealthList = new ArrayList<Boolean>();
|
||||||
|
|
||||||
|
tm = new DataSourceTransactionManager();
|
||||||
|
tjt = new TransactionTemplate(tm);
|
||||||
|
|
||||||
|
// Transaction timeout needs to be distinguished from ordinary operations.
|
||||||
|
tjt.setTimeout(TRANSACTION_QUERY_TIMEOUT);
|
||||||
|
if (AuthPropertyUtil.isUseExternalDB()) {
|
||||||
|
try {
|
||||||
|
reload();
|
||||||
|
} catch (IOException e) {
|
||||||
|
FATAL_LOG.error("[ExternalDataSourceService] dats source reload error", e);
|
||||||
|
throw new RuntimeException(DB_LOAD_ERROR_MSG);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
if (this.dataSourceList.size() > DB_MASTER_SELECT_THRESHOLD) {
|
||||||
|
ConfigExecutor.scheduleConfigTask(new SelectMasterTask(), 10, 10, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
ConfigExecutor.scheduleConfigTask(new CheckDbHealthTask(), 10, 10, TimeUnit.SECONDS);
|
||||||
|
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void reload() throws IOException {
|
||||||
|
try {
|
||||||
|
dataSourceList = new ExternalDataSourceProperties()
|
||||||
|
.build(EnvUtil.getEnvironment(), (dataSource) -> {
|
||||||
|
JdbcTemplate jdbcTemplate = new JdbcTemplate();
|
||||||
|
jdbcTemplate.setQueryTimeout(queryTimeout);
|
||||||
|
jdbcTemplate.setDataSource(dataSource);
|
||||||
|
testJtList.add(jdbcTemplate);
|
||||||
|
isHealthList.add(Boolean.TRUE);
|
||||||
|
});
|
||||||
|
new SelectMasterTask().run();
|
||||||
|
//new CheckDbHealthTask().run();
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
FATAL_LOG.error(DB_LOAD_ERROR_MSG, e);
|
||||||
|
throw new IOException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checkMasterWritable() {
|
||||||
|
|
||||||
|
testMasterWritableJT.setDataSource(jt.getDataSource());
|
||||||
|
// Prevent the login interface from being too long because the main library is not available
|
||||||
|
testMasterWritableJT.setQueryTimeout(1);
|
||||||
|
String sql = " SELECT @@read_only ";
|
||||||
|
|
||||||
|
try {
|
||||||
|
Integer result = testMasterWritableJT.queryForObject(sql, Integer.class);
|
||||||
|
if (result == null) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return result == 0;
|
||||||
|
}
|
||||||
|
} catch (CannotGetJdbcConnectionException e) {
|
||||||
|
FATAL_LOG.error("[db-error] " + e.toString(), e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JdbcTemplate getJdbcTemplate() {
|
||||||
|
return this.jt;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TransactionTemplate getTransactionTemplate() {
|
||||||
|
return this.tjt;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getCurrentDbUrl() {
|
||||||
|
DataSource ds = this.jt.getDataSource();
|
||||||
|
if (ds == null) {
|
||||||
|
return StringUtils.EMPTY;
|
||||||
|
}
|
||||||
|
HikariDataSource bds = (HikariDataSource) ds;
|
||||||
|
return bds.getJdbcUrl();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getHealth() {
|
||||||
|
for (int i = 0; i < isHealthList.size(); i++) {
|
||||||
|
if (!isHealthList.get(i)) {
|
||||||
|
if (i == masterIndex) {
|
||||||
|
// The master is unhealthy.
|
||||||
|
return "DOWN:" + InternetAddressUtil.getIPFromString(dataSourceList.get(i).getJdbcUrl());
|
||||||
|
} else {
|
||||||
|
// The slave is unhealthy.
|
||||||
|
return "WARN:" + InternetAddressUtil.getIPFromString(dataSourceList.get(i).getJdbcUrl());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "UP";
|
||||||
|
}
|
||||||
|
|
||||||
|
class SelectMasterTask implements Runnable {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (DEFAULT_LOG.isDebugEnabled()) {
|
||||||
|
DEFAULT_LOG.debug("check master db.");
|
||||||
|
}
|
||||||
|
boolean isFound = false;
|
||||||
|
|
||||||
|
int index = -1;
|
||||||
|
for (HikariDataSource ds : dataSourceList) {
|
||||||
|
index++;
|
||||||
|
testMasterJT.setDataSource(ds);
|
||||||
|
testMasterJT.setQueryTimeout(queryTimeout);
|
||||||
|
try {
|
||||||
|
testMasterJT.update("DELETE FROM config_info WHERE data_id='com.alibaba.nacos.testMasterDB'");
|
||||||
|
if (jt.getDataSource() != ds) {
|
||||||
|
FATAL_LOG.warn("[master-db] {}", ds.getJdbcUrl());
|
||||||
|
}
|
||||||
|
jt.setDataSource(ds);
|
||||||
|
tm.setDataSource(ds);
|
||||||
|
isFound = true;
|
||||||
|
masterIndex = index;
|
||||||
|
break;
|
||||||
|
} catch (DataAccessException e) { // read only
|
||||||
|
FATAL_LOG.warn("[master-db] master db access error", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isFound) {
|
||||||
|
FATAL_LOG.error("[master-db] master db not found.");
|
||||||
|
//MetricsMonitor.getDbException().increment();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
@SuppressWarnings("PMD.ClassNamingShouldBeCamelRule")
|
||||||
|
class CheckDbHealthTask implements Runnable {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (DEFAULT_LOG.isDebugEnabled()) {
|
||||||
|
DEFAULT_LOG.debug("check db health.");
|
||||||
|
}
|
||||||
|
String sql = "SELECT * FROM config_info_beta WHERE id = 1";
|
||||||
|
|
||||||
|
for (int i = 0; i < testJtList.size(); i++) {
|
||||||
|
JdbcTemplate jdbcTemplate = testJtList.get(i);
|
||||||
|
try {
|
||||||
|
jdbcTemplate.query(sql, CONFIG_INFO4BETA_ROW_MAPPER);
|
||||||
|
isHealthList.set(i, Boolean.TRUE);
|
||||||
|
} catch (DataAccessException e) {
|
||||||
|
if (i == masterIndex) {
|
||||||
|
FATAL_LOG.error("[db-error] master db {} down.",
|
||||||
|
InternetAddressUtil.getIPFromString(dataSourceList.get(i).getJdbcUrl()));
|
||||||
|
} else {
|
||||||
|
FATAL_LOG.error("[db-error] slave db {} down.",
|
||||||
|
InternetAddressUtil.getIPFromString(dataSourceList.get(i).getJdbcUrl()));
|
||||||
|
}
|
||||||
|
isHealthList.set(i, Boolean.FALSE);
|
||||||
|
|
||||||
|
MetricsMonitor.getDbException().increment();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
}
|
@ -0,0 +1,265 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2021 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* 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.alibaba.nacos.auth.persist.datasource;
|
||||||
|
|
||||||
|
import com.alibaba.nacos.api.exception.NacosException;
|
||||||
|
import com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;
|
||||||
|
import com.alibaba.nacos.auth.util.AuthPropertyUtil;
|
||||||
|
import com.alibaba.nacos.auth.util.LogUtil;
|
||||||
|
import com.alibaba.nacos.common.utils.IoUtils;
|
||||||
|
import com.alibaba.nacos.common.utils.StringUtils;
|
||||||
|
import com.alibaba.nacos.sys.env.EnvUtil;
|
||||||
|
import com.alibaba.nacos.sys.utils.DiskUtils;
|
||||||
|
import com.zaxxer.hikari.HikariDataSource;
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
||||||
|
import org.springframework.transaction.support.TransactionTemplate;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.DriverManager;
|
||||||
|
import java.sql.Statement;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* local data source.
|
||||||
|
*
|
||||||
|
* @author Nacos
|
||||||
|
*/
|
||||||
|
public class LocalDataSourceServiceImpl implements DataSourceService {
|
||||||
|
|
||||||
|
private final String jdbcDriverName = "org.apache.derby.jdbc.EmbeddedDriver";
|
||||||
|
|
||||||
|
private final String userName = "nacos";
|
||||||
|
|
||||||
|
private final String password = "nacos";
|
||||||
|
|
||||||
|
private final String derbyBaseDir = "data" + File.separator + "derby-data";
|
||||||
|
|
||||||
|
private final String derbyShutdownErrMsg = "Derby system shutdown.";
|
||||||
|
|
||||||
|
private volatile JdbcTemplate jt;
|
||||||
|
|
||||||
|
private volatile TransactionTemplate tjt;
|
||||||
|
|
||||||
|
private boolean initialize = false;
|
||||||
|
|
||||||
|
private boolean jdbcTemplateInit = false;
|
||||||
|
|
||||||
|
private String healthStatus = "UP";
|
||||||
|
|
||||||
|
private static final String ENCODE = "UTF-8";
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
@Override
|
||||||
|
public synchronized void init() throws Exception {
|
||||||
|
if (AuthPropertyUtil.isUseExternalDB()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!initialize) {
|
||||||
|
LogUtil.DEFAULT_LOG.info("use local db service for init");
|
||||||
|
final String jdbcUrl =
|
||||||
|
"jdbc:derby:" + Paths.get(EnvUtil.getNacosHome(), derbyBaseDir).toString()
|
||||||
|
+ ";create=true";
|
||||||
|
initialize(jdbcUrl);
|
||||||
|
initialize = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void reload() {
|
||||||
|
DataSource ds = jt.getDataSource();
|
||||||
|
if (ds == null) {
|
||||||
|
throw new RuntimeException("datasource is null");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
execute(ds.getConnection(), "META-INF/schema.sql");
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (LogUtil.DEFAULT_LOG.isErrorEnabled()) {
|
||||||
|
LogUtil.DEFAULT_LOG.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
throw new NacosRuntimeException(NacosException.SERVER_ERROR, "load schema.sql error.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataSource getDatasource() {
|
||||||
|
return jt.getDataSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clean and reopen Derby.
|
||||||
|
*
|
||||||
|
* @throws Exception exception.
|
||||||
|
*/
|
||||||
|
public void cleanAndReopenDerby() throws Exception {
|
||||||
|
doDerbyClean();
|
||||||
|
final String jdbcUrl =
|
||||||
|
"jdbc:derby:" + Paths.get(EnvUtil.getNacosHome(), derbyBaseDir).toString() + ";create=true";
|
||||||
|
initialize(jdbcUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restore derby.
|
||||||
|
*
|
||||||
|
* @param jdbcUrl jdbcUrl string value.
|
||||||
|
* @param callable callable.
|
||||||
|
* @throws Exception exception.
|
||||||
|
*/
|
||||||
|
public void restoreDerby(String jdbcUrl, Callable<Void> callable) throws Exception {
|
||||||
|
doDerbyClean();
|
||||||
|
callable.call();
|
||||||
|
initialize(jdbcUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doDerbyClean() throws Exception {
|
||||||
|
LogUtil.DEFAULT_LOG.warn("use local db service for reopenDerby");
|
||||||
|
try {
|
||||||
|
DriverManager.getConnection("jdbc:derby:;shutdown=true");
|
||||||
|
} catch (Exception e) {
|
||||||
|
// An error is thrown when the Derby shutdown is executed, which should be ignored
|
||||||
|
if (!StringUtils.containsIgnoreCase(e.getMessage(), derbyShutdownErrMsg)) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DiskUtils.deleteDirectory(Paths.get(EnvUtil.getNacosHome(), derbyBaseDir).toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void initialize(String jdbcUrl) {
|
||||||
|
DataSourcePoolProperties poolProperties = DataSourcePoolProperties.build(EnvUtil.getEnvironment());
|
||||||
|
poolProperties.setDriverClassName(jdbcDriverName);
|
||||||
|
poolProperties.setJdbcUrl(jdbcUrl);
|
||||||
|
poolProperties.setUsername(userName);
|
||||||
|
poolProperties.setPassword(password);
|
||||||
|
HikariDataSource ds = poolProperties.getDataSource();
|
||||||
|
DataSourceTransactionManager tm = new DataSourceTransactionManager();
|
||||||
|
tm.setDataSource(ds);
|
||||||
|
if (jdbcTemplateInit) {
|
||||||
|
jt.setDataSource(ds);
|
||||||
|
tjt.setTransactionManager(tm);
|
||||||
|
} else {
|
||||||
|
jt = new JdbcTemplate();
|
||||||
|
jt.setMaxRows(50000);
|
||||||
|
jt.setQueryTimeout(5000);
|
||||||
|
jt.setDataSource(ds);
|
||||||
|
tjt = new TransactionTemplate(tm);
|
||||||
|
tjt.setTimeout(5000);
|
||||||
|
jdbcTemplateInit = true;
|
||||||
|
}
|
||||||
|
reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checkMasterWritable() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JdbcTemplate getJdbcTemplate() {
|
||||||
|
return jt;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TransactionTemplate getTransactionTemplate() {
|
||||||
|
return tjt;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getCurrentDbUrl() {
|
||||||
|
return "jdbc:derby:" + EnvUtil.getNacosHome() + File.separator + derbyBaseDir + ";create=true";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getHealth() {
|
||||||
|
return healthStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHealthStatus(String healthStatus) {
|
||||||
|
this.healthStatus = healthStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load sql.
|
||||||
|
*
|
||||||
|
* @param sqlFile sql.
|
||||||
|
* @return sqls.
|
||||||
|
* @throws Exception Exception.
|
||||||
|
*/
|
||||||
|
private List<String> loadSql(String sqlFile) throws Exception {
|
||||||
|
List<String> sqlList = new ArrayList<String>();
|
||||||
|
InputStream sqlFileIn = null;
|
||||||
|
try {
|
||||||
|
File file = new File(
|
||||||
|
EnvUtil.getNacosHome() + File.separator + "conf" + File.separator + "schema.sql");
|
||||||
|
if (StringUtils.isBlank(EnvUtil.getNacosHome()) || !file.exists()) {
|
||||||
|
ClassLoader classLoader = getClass().getClassLoader();
|
||||||
|
URL url = classLoader.getResource(sqlFile);
|
||||||
|
sqlFileIn = url.openStream();
|
||||||
|
} else {
|
||||||
|
sqlFileIn = new FileInputStream(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder sqlSb = new StringBuilder();
|
||||||
|
byte[] buff = new byte[1024];
|
||||||
|
int byteRead = 0;
|
||||||
|
while ((byteRead = sqlFileIn.read(buff)) != -1) {
|
||||||
|
sqlSb.append(new String(buff, 0, byteRead, ENCODE));
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] sqlArr = sqlSb.toString().split(";");
|
||||||
|
for (int i = 0; i < sqlArr.length; i++) {
|
||||||
|
String sql = sqlArr[i].replaceAll("--.*", "").trim();
|
||||||
|
if (StringUtils.isNotEmpty(sql)) {
|
||||||
|
sqlList.add(sql);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sqlList;
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throw new Exception(ex.getMessage());
|
||||||
|
} finally {
|
||||||
|
IoUtils.closeQuietly(sqlFileIn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute sql.
|
||||||
|
*
|
||||||
|
* @param conn connect.
|
||||||
|
* @param sqlFile sql.
|
||||||
|
* @throws Exception Exception.
|
||||||
|
*/
|
||||||
|
private void execute(Connection conn, String sqlFile) throws Exception {
|
||||||
|
try (Statement stmt = conn.createStatement()) {
|
||||||
|
List<String> sqlList = loadSql(sqlFile);
|
||||||
|
for (String sql : sqlList) {
|
||||||
|
try {
|
||||||
|
stmt.execute(sql);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogUtil.DEFAULT_LOG.warn(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2021 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* 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.alibaba.nacos.auth.persist.repository;
|
||||||
|
|
||||||
|
import com.alibaba.nacos.auth.model.Page;
|
||||||
|
import org.springframework.jdbc.core.RowMapper;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pagination Utils interface.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("PMD.AbstractMethodOrInterfaceMethodMustUseJavadocRule")
|
||||||
|
public interface PaginationHelper<E> {
|
||||||
|
|
||||||
|
Page<E> fetchPage(final String sqlCountRows, final String sqlFetchRows, final Object[] args, final int pageNo,
|
||||||
|
final int pageSize, final RowMapper<E> rowMapper);
|
||||||
|
|
||||||
|
Page<E> fetchPage(final String sqlCountRows, final String sqlFetchRows, final Object[] args, final int pageNo,
|
||||||
|
final int pageSize, final Long lastMaxId, final RowMapper<E> rowMapper);
|
||||||
|
|
||||||
|
Page<E> fetchPageLimit(final String sqlCountRows, final String sqlFetchRows, final Object[] args, final int pageNo,
|
||||||
|
final int pageSize, final RowMapper<E> rowMapper);
|
||||||
|
|
||||||
|
Page<E> fetchPageLimit(final String sqlCountRows, final Object[] args1, final String sqlFetchRows,
|
||||||
|
final Object[] args2, final int pageNo, final int pageSize, final RowMapper<E> rowMapper);
|
||||||
|
|
||||||
|
Page<E> fetchPageLimit(final String sqlFetchRows, final Object[] args, final int pageNo, final int pageSize,
|
||||||
|
final RowMapper<E> rowMapper);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,211 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2021 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* 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.alibaba.nacos.auth.persist.repository.externel;
|
||||||
|
|
||||||
|
import com.alibaba.nacos.auth.model.Page;
|
||||||
|
import com.alibaba.nacos.auth.persist.repository.PaginationHelper;
|
||||||
|
import com.alibaba.nacos.auth.util.AuthPropertyUtil;
|
||||||
|
import com.alibaba.nacos.sys.env.EnvUtil;
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
import org.springframework.jdbc.core.RowMapper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* External Storage Pagination utils.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:liaochuntao@live.com">liaochuntao</a>
|
||||||
|
*/
|
||||||
|
|
||||||
|
class ExternalStoragePaginationHelperImpl<E> implements PaginationHelper {
|
||||||
|
|
||||||
|
private final JdbcTemplate jdbcTemplate;
|
||||||
|
|
||||||
|
public ExternalStoragePaginationHelperImpl(JdbcTemplate jdbcTemplate) {
|
||||||
|
this.jdbcTemplate = jdbcTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Take paging.
|
||||||
|
*
|
||||||
|
* @param sqlCountRows query total SQL
|
||||||
|
* @param sqlFetchRows query data sql
|
||||||
|
* @param args query parameters
|
||||||
|
* @param pageNo page number
|
||||||
|
* @param pageSize page size
|
||||||
|
* @param rowMapper {@link RowMapper}
|
||||||
|
* @return Paginated data {@code <E>}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Page<E> fetchPage(final String sqlCountRows, final String sqlFetchRows, final Object[] args,
|
||||||
|
final int pageNo, final int pageSize, final RowMapper rowMapper) {
|
||||||
|
return fetchPage(sqlCountRows, sqlFetchRows, args, pageNo, pageSize, null, rowMapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Page<E> fetchPage(final String sqlCountRows, final String sqlFetchRows, final Object[] args,
|
||||||
|
final int pageNo, final int pageSize, final Long lastMaxId, final RowMapper rowMapper) {
|
||||||
|
if (pageNo <= 0 || pageSize <= 0) {
|
||||||
|
throw new IllegalArgumentException("pageNo and pageSize must be greater than zero");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Query the total number of current records.
|
||||||
|
Integer rowCountInt = jdbcTemplate.queryForObject(sqlCountRows, args, Integer.class);
|
||||||
|
if (rowCountInt == null) {
|
||||||
|
throw new IllegalArgumentException("fetchPageLimit error");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute pages count
|
||||||
|
int pageCount = rowCountInt / pageSize;
|
||||||
|
if (rowCountInt > pageSize * pageCount) {
|
||||||
|
pageCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create Page object
|
||||||
|
final Page<E> page = new Page<E>();
|
||||||
|
page.setPageNumber(pageNo);
|
||||||
|
page.setPagesAvailable(pageCount);
|
||||||
|
page.setTotalCount(rowCountInt);
|
||||||
|
|
||||||
|
if (pageNo > pageCount) {
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int startRow = (pageNo - 1) * pageSize;
|
||||||
|
String selectSql = "";
|
||||||
|
if (isDerby()) {
|
||||||
|
selectSql = sqlFetchRows + " OFFSET " + startRow + " ROWS FETCH NEXT " + pageSize + " ROWS ONLY";
|
||||||
|
} else if (lastMaxId != null) {
|
||||||
|
selectSql = sqlFetchRows + " AND id > " + lastMaxId + " ORDER BY id ASC" + " LIMIT " + 0 + "," + pageSize;
|
||||||
|
} else {
|
||||||
|
selectSql = sqlFetchRows + " LIMIT " + startRow + "," + pageSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<E> result = jdbcTemplate.query(selectSql, args, rowMapper);
|
||||||
|
for (E item : result) {
|
||||||
|
page.getPageItems().add(item);
|
||||||
|
}
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Page<E> fetchPageLimit(final String sqlCountRows, final String sqlFetchRows, final Object[] args,
|
||||||
|
final int pageNo, final int pageSize, final RowMapper rowMapper) {
|
||||||
|
if (pageNo <= 0 || pageSize <= 0) {
|
||||||
|
throw new IllegalArgumentException("pageNo and pageSize must be greater than zero");
|
||||||
|
}
|
||||||
|
// Query the total number of current records
|
||||||
|
Integer rowCountInt = jdbcTemplate.queryForObject(sqlCountRows, Integer.class);
|
||||||
|
if (rowCountInt == null) {
|
||||||
|
throw new IllegalArgumentException("fetchPageLimit error");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute pages count
|
||||||
|
int pageCount = rowCountInt / pageSize;
|
||||||
|
if (rowCountInt > pageSize * pageCount) {
|
||||||
|
pageCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create Page object
|
||||||
|
final Page<E> page = new Page<E>();
|
||||||
|
page.setPageNumber(pageNo);
|
||||||
|
page.setPagesAvailable(pageCount);
|
||||||
|
page.setTotalCount(rowCountInt);
|
||||||
|
|
||||||
|
if (pageNo > pageCount) {
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
|
||||||
|
String selectSql = sqlFetchRows;
|
||||||
|
if (isDerby()) {
|
||||||
|
selectSql = selectSql.replaceAll("(?i)LIMIT \\?,\\?", "OFFSET ? ROWS FETCH NEXT ? ROWS ONLY");
|
||||||
|
}
|
||||||
|
|
||||||
|
List<E> result = jdbcTemplate.query(selectSql, args, rowMapper);
|
||||||
|
for (E item : result) {
|
||||||
|
page.getPageItems().add(item);
|
||||||
|
}
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Page<E> fetchPageLimit(final String sqlCountRows, final Object[] args1, final String sqlFetchRows,
|
||||||
|
final Object[] args2, final int pageNo, final int pageSize, final RowMapper rowMapper) {
|
||||||
|
if (pageNo <= 0 || pageSize <= 0) {
|
||||||
|
throw new IllegalArgumentException("pageNo and pageSize must be greater than zero");
|
||||||
|
}
|
||||||
|
// Query the total number of current records
|
||||||
|
Integer rowCountInt = jdbcTemplate.queryForObject(sqlCountRows, args1, Integer.class);
|
||||||
|
if (rowCountInt == null) {
|
||||||
|
throw new IllegalArgumentException("fetchPageLimit error");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute pages count
|
||||||
|
int pageCount = rowCountInt / pageSize;
|
||||||
|
if (rowCountInt > pageSize * pageCount) {
|
||||||
|
pageCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create Page object
|
||||||
|
final Page<E> page = new Page<E>();
|
||||||
|
page.setPageNumber(pageNo);
|
||||||
|
page.setPagesAvailable(pageCount);
|
||||||
|
page.setTotalCount(rowCountInt);
|
||||||
|
|
||||||
|
if (pageNo > pageCount) {
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
|
||||||
|
String selectSql = sqlFetchRows;
|
||||||
|
if (isDerby()) {
|
||||||
|
selectSql = selectSql.replaceAll("(?i)LIMIT \\?,\\?", "OFFSET ? ROWS FETCH NEXT ? ROWS ONLY");
|
||||||
|
}
|
||||||
|
|
||||||
|
List<E> result = jdbcTemplate.query(selectSql, args2, rowMapper);
|
||||||
|
for (E item : result) {
|
||||||
|
page.getPageItems().add(item);
|
||||||
|
}
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Page<E> fetchPageLimit(final String sqlFetchRows, final Object[] args, final int pageNo, final int pageSize,
|
||||||
|
final RowMapper rowMapper) {
|
||||||
|
if (pageNo <= 0 || pageSize <= 0) {
|
||||||
|
throw new IllegalArgumentException("pageNo and pageSize must be greater than zero");
|
||||||
|
}
|
||||||
|
// Create Page object
|
||||||
|
final Page<E> page = new Page<E>();
|
||||||
|
|
||||||
|
String selectSql = sqlFetchRows;
|
||||||
|
if (isDerby()) {
|
||||||
|
selectSql = selectSql.replaceAll("(?i)LIMIT \\?,\\?", "OFFSET ? ROWS FETCH NEXT ? ROWS ONLY");
|
||||||
|
}
|
||||||
|
|
||||||
|
List<E> result = jdbcTemplate.query(selectSql, args, rowMapper);
|
||||||
|
for (E item : result) {
|
||||||
|
page.getPageItems().add(item);
|
||||||
|
}
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isDerby() {
|
||||||
|
return (EnvUtil.getStandaloneMode() && !AuthPropertyUtil.isUseExternalDB()) || AuthPropertyUtil
|
||||||
|
.isEmbeddedStorage();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2021 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* 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.alibaba.nacos.auth.persist.repository.externel;
|
||||||
|
|
||||||
|
import com.alibaba.nacos.auth.configuration.ConditionOnExternalStorage;
|
||||||
|
import com.alibaba.nacos.auth.persist.datasource.DataSourceService;
|
||||||
|
import com.alibaba.nacos.auth.persist.datasource.DynamicDataSource;
|
||||||
|
import com.alibaba.nacos.auth.persist.repository.PaginationHelper;
|
||||||
|
import org.springframework.context.annotation.Conditional;
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
|
||||||
|
@SuppressWarnings(value = {"PMD.MethodReturnWrapperTypeRule", "checkstyle:linelength"})
|
||||||
|
@Conditional(value = ConditionOnExternalStorage.class)
|
||||||
|
@Component
|
||||||
|
public class ExternalStoragePersistServiceImpl {
|
||||||
|
|
||||||
|
private DataSourceService dataSourceService;
|
||||||
|
|
||||||
|
protected JdbcTemplate jt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* init datasource.
|
||||||
|
*/
|
||||||
|
@PostConstruct
|
||||||
|
public void init() {
|
||||||
|
dataSourceService = DynamicDataSource.getInstance().getDataSource();
|
||||||
|
|
||||||
|
jt = getJdbcTemplate();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For unit testing.
|
||||||
|
*/
|
||||||
|
public JdbcTemplate getJdbcTemplate() {
|
||||||
|
return this.dataSourceService.getJdbcTemplate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public <E> PaginationHelper<E> createPaginationHelper() {
|
||||||
|
return new ExternalStoragePaginationHelperImpl<E>(jt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,338 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2021 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* 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.alibaba.nacos.auth.util;
|
||||||
|
|
||||||
|
import com.alibaba.nacos.auth.constant.PropertiesConstant;
|
||||||
|
import com.alibaba.nacos.sys.env.EnvUtil;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.springframework.context.ApplicationContextInitializer;
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Properties util.
|
||||||
|
*
|
||||||
|
* @author Nacos
|
||||||
|
*/
|
||||||
|
public class AuthPropertyUtil implements ApplicationContextInitializer<ConfigurableApplicationContext> {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LogUtil.DEFAULT_LOG;
|
||||||
|
|
||||||
|
private static int notifyConnectTimeout = 100;
|
||||||
|
|
||||||
|
private static int notifySocketTimeout = 200;
|
||||||
|
|
||||||
|
private static int maxHealthCheckFailCount = 12;
|
||||||
|
|
||||||
|
private static boolean isHealthCheck = true;
|
||||||
|
|
||||||
|
private static int maxContent = 10 * 1024 * 1024;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to enable capacity management.
|
||||||
|
*/
|
||||||
|
private static boolean isManageCapacity = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to enable the limit check function of capacity management, including the upper limit of configuration
|
||||||
|
* number, configuration content size limit, etc.
|
||||||
|
*/
|
||||||
|
private static boolean isCapacityLimitCheck = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default cluster capacity limit.
|
||||||
|
*/
|
||||||
|
private static int defaultClusterQuota = 100000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the default capacity limit per Group.
|
||||||
|
*/
|
||||||
|
private static int defaultGroupQuota = 200;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default capacity limit per Tenant.
|
||||||
|
*/
|
||||||
|
private static int defaultTenantQuota = 200;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum size of the content in the configuration of a single, unit for bytes.
|
||||||
|
*/
|
||||||
|
private static int defaultMaxSize = 100 * 1024;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default Maximum number of aggregated data.
|
||||||
|
*/
|
||||||
|
private static int defaultMaxAggrCount = 10000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum size of content in a single subconfiguration of aggregated data.
|
||||||
|
*/
|
||||||
|
private static int defaultMaxAggrSize = 1024;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the expansion percentage of capacity has reached the limit.
|
||||||
|
*/
|
||||||
|
private static int initialExpansionPercent = 100;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fixed capacity information table usage (usage) time interval, the unit is in seconds.
|
||||||
|
*/
|
||||||
|
private static int correctUsageDelay = 10 * 60;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Standalone mode uses DB.
|
||||||
|
*/
|
||||||
|
private static boolean useExternalDB = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inline storage value = ${nacos.standalone}.
|
||||||
|
*/
|
||||||
|
private static boolean embeddedStorage = EnvUtil.getStandaloneMode();
|
||||||
|
|
||||||
|
public static int getNotifyConnectTimeout() {
|
||||||
|
return notifyConnectTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setNotifyConnectTimeout(int notifyConnectTimeout) {
|
||||||
|
AuthPropertyUtil.notifyConnectTimeout = notifyConnectTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getNotifySocketTimeout() {
|
||||||
|
return notifySocketTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setNotifySocketTimeout(int notifySocketTimeout) {
|
||||||
|
AuthPropertyUtil.notifySocketTimeout = notifySocketTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getMaxHealthCheckFailCount() {
|
||||||
|
return maxHealthCheckFailCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setMaxHealthCheckFailCount(int maxHealthCheckFailCount) {
|
||||||
|
AuthPropertyUtil.maxHealthCheckFailCount = maxHealthCheckFailCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isHealthCheck() {
|
||||||
|
return isHealthCheck;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setHealthCheck(boolean isHealthCheck) {
|
||||||
|
AuthPropertyUtil.isHealthCheck = isHealthCheck;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getMaxContent() {
|
||||||
|
return maxContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setMaxContent(int maxContent) {
|
||||||
|
AuthPropertyUtil.maxContent = maxContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isManageCapacity() {
|
||||||
|
return isManageCapacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setManageCapacity(boolean isManageCapacity) {
|
||||||
|
AuthPropertyUtil.isManageCapacity = isManageCapacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getDefaultClusterQuota() {
|
||||||
|
return defaultClusterQuota;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setDefaultClusterQuota(int defaultClusterQuota) {
|
||||||
|
AuthPropertyUtil.defaultClusterQuota = defaultClusterQuota;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isCapacityLimitCheck() {
|
||||||
|
return isCapacityLimitCheck;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setCapacityLimitCheck(boolean isCapacityLimitCheck) {
|
||||||
|
AuthPropertyUtil.isCapacityLimitCheck = isCapacityLimitCheck;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getDefaultGroupQuota() {
|
||||||
|
return defaultGroupQuota;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setDefaultGroupQuota(int defaultGroupQuota) {
|
||||||
|
AuthPropertyUtil.defaultGroupQuota = defaultGroupQuota;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getDefaultTenantQuota() {
|
||||||
|
return defaultTenantQuota;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setDefaultTenantQuota(int defaultTenantQuota) {
|
||||||
|
AuthPropertyUtil.defaultTenantQuota = defaultTenantQuota;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getInitialExpansionPercent() {
|
||||||
|
return initialExpansionPercent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setInitialExpansionPercent(int initialExpansionPercent) {
|
||||||
|
AuthPropertyUtil.initialExpansionPercent = initialExpansionPercent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getDefaultMaxSize() {
|
||||||
|
return defaultMaxSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setDefaultMaxSize(int defaultMaxSize) {
|
||||||
|
AuthPropertyUtil.defaultMaxSize = defaultMaxSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getDefaultMaxAggrCount() {
|
||||||
|
return defaultMaxAggrCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setDefaultMaxAggrCount(int defaultMaxAggrCount) {
|
||||||
|
AuthPropertyUtil.defaultMaxAggrCount = defaultMaxAggrCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getDefaultMaxAggrSize() {
|
||||||
|
return defaultMaxAggrSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setDefaultMaxAggrSize(int defaultMaxAggrSize) {
|
||||||
|
AuthPropertyUtil.defaultMaxAggrSize = defaultMaxAggrSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getCorrectUsageDelay() {
|
||||||
|
return correctUsageDelay;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setCorrectUsageDelay(int correctUsageDelay) {
|
||||||
|
AuthPropertyUtil.correctUsageDelay = correctUsageDelay;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isStandaloneMode() {
|
||||||
|
return EnvUtil.getStandaloneMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isUseExternalDB() {
|
||||||
|
return useExternalDB;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setUseExternalDB(boolean useExternalDB) {
|
||||||
|
AuthPropertyUtil.useExternalDB = useExternalDB;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isEmbeddedStorage() {
|
||||||
|
return embeddedStorage;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determines whether to read the data directly
|
||||||
|
// if use mysql, Reduce database read pressure
|
||||||
|
// if use raft+derby, Reduce leader read pressure
|
||||||
|
|
||||||
|
public static boolean isDirectRead() {
|
||||||
|
return EnvUtil.getStandaloneMode() && isEmbeddedStorage();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setEmbeddedStorage(boolean embeddedStorage) {
|
||||||
|
AuthPropertyUtil.embeddedStorage = embeddedStorage;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadSetting() {
|
||||||
|
try {
|
||||||
|
setNotifyConnectTimeout(Integer.parseInt(EnvUtil.getProperty(PropertiesConstant.NOTIFY_CONNECT_TIMEOUT,
|
||||||
|
String.valueOf(notifyConnectTimeout))));
|
||||||
|
LOGGER.info("notifyConnectTimeout:{}", notifyConnectTimeout);
|
||||||
|
setNotifySocketTimeout(Integer.parseInt(EnvUtil.getProperty(PropertiesConstant.NOTIFY_SOCKET_TIMEOUT,
|
||||||
|
String.valueOf(notifySocketTimeout))));
|
||||||
|
LOGGER.info("notifySocketTimeout:{}", notifySocketTimeout);
|
||||||
|
setHealthCheck(Boolean.parseBoolean(
|
||||||
|
EnvUtil.getProperty(PropertiesConstant.IS_HEALTH_CHECK, String.valueOf(isHealthCheck))));
|
||||||
|
LOGGER.info("isHealthCheck:{}", isHealthCheck);
|
||||||
|
setMaxHealthCheckFailCount(Integer.parseInt(
|
||||||
|
EnvUtil.getProperty(PropertiesConstant.MAX_HEALTH_CHECK_FAIL_COUNT,
|
||||||
|
String.valueOf(maxHealthCheckFailCount))));
|
||||||
|
LOGGER.info("maxHealthCheckFailCount:{}", maxHealthCheckFailCount);
|
||||||
|
setMaxContent(
|
||||||
|
Integer.parseInt(EnvUtil.getProperty(PropertiesConstant.MAX_CONTENT, String.valueOf(maxContent))));
|
||||||
|
LOGGER.info("maxContent:{}", maxContent);
|
||||||
|
// capacity management
|
||||||
|
setManageCapacity(getBoolean(PropertiesConstant.IS_MANAGE_CAPACITY, isManageCapacity));
|
||||||
|
setCapacityLimitCheck(getBoolean(PropertiesConstant.IS_CAPACITY_LIMIT_CHECK, isCapacityLimitCheck));
|
||||||
|
setDefaultClusterQuota(getInt(PropertiesConstant.DEFAULT_CLUSTER_QUOTA, defaultClusterQuota));
|
||||||
|
setDefaultGroupQuota(getInt(PropertiesConstant.DEFAULT_GROUP_QUOTA, defaultGroupQuota));
|
||||||
|
setDefaultTenantQuota(getInt(PropertiesConstant.DEFAULT_TENANT_QUOTA, defaultTenantQuota));
|
||||||
|
setDefaultMaxSize(getInt(PropertiesConstant.DEFAULT_MAX_SIZE, defaultMaxSize));
|
||||||
|
setDefaultMaxAggrCount(getInt(PropertiesConstant.DEFAULT_MAX_AGGR_COUNT, defaultMaxAggrCount));
|
||||||
|
setDefaultMaxAggrSize(getInt(PropertiesConstant.DEFAULT_MAX_AGGR_SIZE, defaultMaxAggrSize));
|
||||||
|
setCorrectUsageDelay(getInt(PropertiesConstant.CORRECT_USAGE_DELAY, correctUsageDelay));
|
||||||
|
setInitialExpansionPercent(getInt(PropertiesConstant.INITIAL_EXPANSION_PERCENT, initialExpansionPercent));
|
||||||
|
// External data sources are used by default in cluster mode
|
||||||
|
setUseExternalDB(PropertiesConstant.MYSQL
|
||||||
|
.equalsIgnoreCase(getString(PropertiesConstant.SPRING_DATASOURCE_PLATFORM, "")));
|
||||||
|
// must initialize after setUseExternalDB
|
||||||
|
// This value is true in stand-alone mode and false in cluster mode
|
||||||
|
// If this value is set to true in cluster mode, nacos's distributed storage engine is turned on
|
||||||
|
// default value is depend on ${nacos.standalone}
|
||||||
|
|
||||||
|
if (isUseExternalDB()) {
|
||||||
|
setEmbeddedStorage(false);
|
||||||
|
} else {
|
||||||
|
boolean embeddedStorage =
|
||||||
|
AuthPropertyUtil.embeddedStorage || Boolean.getBoolean(PropertiesConstant.EMBEDDED_STORAGE);
|
||||||
|
setEmbeddedStorage(embeddedStorage);
|
||||||
|
|
||||||
|
// If the embedded data source storage is not turned on, it is automatically
|
||||||
|
// upgraded to the external data source storage, as before
|
||||||
|
if (!embeddedStorage) {
|
||||||
|
setUseExternalDB(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.error("read application.properties failed", e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean getBoolean(String key, boolean defaultValue) {
|
||||||
|
return Boolean.parseBoolean(getString(key, String.valueOf(defaultValue)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getInt(String key, int defaultValue) {
|
||||||
|
return Integer.parseInt(getString(key, String.valueOf(defaultValue)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getString(String key, String defaultValue) {
|
||||||
|
String value = getProperty(key);
|
||||||
|
if (value == null) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
LOGGER.info("{}:{}", key, value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProperty(String key) {
|
||||||
|
return EnvUtil.getProperty(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProperty(String key, String defaultValue) {
|
||||||
|
return EnvUtil.getProperty(key, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
|
||||||
|
loadSetting();
|
||||||
|
}
|
||||||
|
}
|
96
auth/src/main/java/com/alibaba/nacos/auth/util/LogUtil.java
Normal file
96
auth/src/main/java/com/alibaba/nacos/auth/util/LogUtil.java
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2021 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* 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.alibaba.nacos.auth.util;
|
||||||
|
|
||||||
|
import ch.qos.logback.classic.Level;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log util.
|
||||||
|
*
|
||||||
|
* @author Nacos
|
||||||
|
*/
|
||||||
|
public class LogUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default log.
|
||||||
|
*/
|
||||||
|
public static final Logger DEFAULT_LOG = LoggerFactory.getLogger("com.alibaba.nacos.auth.startLog");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fatal error log, require alarm.
|
||||||
|
*/
|
||||||
|
public static final Logger FATAL_LOG = LoggerFactory.getLogger("com.alibaba.nacos.auth.fatal");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Http client log.
|
||||||
|
*/
|
||||||
|
public static final Logger PULL_LOG = LoggerFactory.getLogger("com.alibaba.nacos.auth.pullLog");
|
||||||
|
|
||||||
|
public static final Logger PULL_CHECK_LOG = LoggerFactory.getLogger("com.alibaba.nacos.auth.pullCheckLog");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dump log.
|
||||||
|
*/
|
||||||
|
public static final Logger DUMP_LOG = LoggerFactory.getLogger("com.alibaba.nacos.auth.dumpLog");
|
||||||
|
|
||||||
|
public static final Logger MEMORY_LOG = LoggerFactory.getLogger("com.alibaba.nacos.auth.monitorLog");
|
||||||
|
|
||||||
|
public static final Logger CLIENT_LOG = LoggerFactory.getLogger("com.alibaba.nacos.auth.clientLog");
|
||||||
|
|
||||||
|
public static final Logger TRACE_LOG = LoggerFactory.getLogger("com.alibaba.nacos.auth.traceLog");
|
||||||
|
|
||||||
|
public static final Logger NOTIFY_LOG = LoggerFactory.getLogger("com.alibaba.nacos.auth.notifyLog");
|
||||||
|
|
||||||
|
public static void setLogLevel(String logName, String level) {
|
||||||
|
|
||||||
|
switch (logName) {
|
||||||
|
case "config-server":
|
||||||
|
((ch.qos.logback.classic.Logger) DEFAULT_LOG).setLevel(Level.valueOf(level));
|
||||||
|
break;
|
||||||
|
case "config-fatal":
|
||||||
|
((ch.qos.logback.classic.Logger) FATAL_LOG).setLevel(Level.valueOf(level));
|
||||||
|
break;
|
||||||
|
case "config-pull":
|
||||||
|
((ch.qos.logback.classic.Logger) PULL_LOG).setLevel(Level.valueOf(level));
|
||||||
|
break;
|
||||||
|
case "config-pull-check":
|
||||||
|
((ch.qos.logback.classic.Logger) PULL_CHECK_LOG).setLevel(Level.valueOf(level));
|
||||||
|
break;
|
||||||
|
case "config-dump":
|
||||||
|
((ch.qos.logback.classic.Logger) DUMP_LOG).setLevel(Level.valueOf(level));
|
||||||
|
break;
|
||||||
|
case "config-memory":
|
||||||
|
((ch.qos.logback.classic.Logger) MEMORY_LOG).setLevel(Level.valueOf(level));
|
||||||
|
break;
|
||||||
|
case "config-client-request":
|
||||||
|
((ch.qos.logback.classic.Logger) CLIENT_LOG).setLevel(Level.valueOf(level));
|
||||||
|
break;
|
||||||
|
case "config-trace":
|
||||||
|
((ch.qos.logback.classic.Logger) TRACE_LOG).setLevel(Level.valueOf(level));
|
||||||
|
break;
|
||||||
|
case "config-notify":
|
||||||
|
((ch.qos.logback.classic.Logger) NOTIFY_LOG).setLevel(Level.valueOf(level));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2021 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* 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.alibaba.nacos.auth.util;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check precondition, throws an {@code IllegalArgumentException} If the conditions are not met.
|
||||||
|
* @author zzq
|
||||||
|
* @date 2021/7/29
|
||||||
|
*/
|
||||||
|
public class Preconditions {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* check precondition.
|
||||||
|
* @param expression a boolean expression
|
||||||
|
* @param errorMessage the exception message to use if the check fails
|
||||||
|
* @throws IllegalArgumentException if {@code expression} is false
|
||||||
|
*/
|
||||||
|
public static void checkArgument(boolean expression, Object errorMessage) {
|
||||||
|
if (Objects.isNull(errorMessage)) {
|
||||||
|
throw new IllegalArgumentException("errorMessage cannot be null.");
|
||||||
|
}
|
||||||
|
if (!expression) {
|
||||||
|
throw new IllegalArgumentException(String.valueOf(errorMessage));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* check precondition.
|
||||||
|
* @param expression a boolean expression
|
||||||
|
* @param errorMessageTemplate the exception message template to use if the check fails
|
||||||
|
* @param errorMessageArgs the arguments to be substituted into the message template.
|
||||||
|
* @throws IllegalArgumentException if {@code expression} is false
|
||||||
|
*/
|
||||||
|
public static void checkArgument(boolean expression, String errorMessageTemplate, Object... errorMessageArgs) {
|
||||||
|
if (Objects.isNull(errorMessageArgs) || Objects.isNull(errorMessageTemplate)) {
|
||||||
|
throw new IllegalArgumentException("errorMessageTemplate or errorMessage cannot be null.");
|
||||||
|
}
|
||||||
|
if (!expression) {
|
||||||
|
throw new IllegalArgumentException(String.format(errorMessageTemplate, errorMessageArgs));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2021 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* 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.alibaba.nacos.auth.persist;
|
||||||
|
|
||||||
|
import com.alibaba.nacos.auth.model.Page;
|
||||||
|
import com.alibaba.nacos.auth.model.PermissionInfo;
|
||||||
|
import com.alibaba.nacos.auth.persist.repository.PaginationHelper;
|
||||||
|
import com.alibaba.nacos.auth.persist.repository.externel.ExternalStoragePersistServiceImpl;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
import org.mockito.junit.MockitoJUnitRunner;
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
|
public class ExternalPermissionPersistServiceImplTest {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private ExternalStoragePersistServiceImpl externalStoragePersistService;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private JdbcTemplate jdbcTemplate;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private PaginationHelper paginationHelper;
|
||||||
|
|
||||||
|
private ExternalPermissionPersistServiceImpl externalPermissionPersistService;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
externalPermissionPersistService = new ExternalPermissionPersistServiceImpl();
|
||||||
|
|
||||||
|
Class<ExternalPermissionPersistServiceImpl> externalPermissionPersistServiceClass = ExternalPermissionPersistServiceImpl.class;
|
||||||
|
Field persistServiceClassDeclaredField = externalPermissionPersistServiceClass
|
||||||
|
.getDeclaredField("persistService");
|
||||||
|
persistServiceClassDeclaredField.setAccessible(true);
|
||||||
|
persistServiceClassDeclaredField.set(externalPermissionPersistService, externalStoragePersistService);
|
||||||
|
|
||||||
|
Mockito.when(externalStoragePersistService.getJdbcTemplate()).thenReturn(jdbcTemplate);
|
||||||
|
Mockito.when(externalStoragePersistService.createPaginationHelper()).thenReturn(paginationHelper);
|
||||||
|
|
||||||
|
externalPermissionPersistService.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetPermissions() {
|
||||||
|
Page<PermissionInfo> role = externalPermissionPersistService.getPermissions("role", 1, 10);
|
||||||
|
Assert.assertNotNull(role);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2021 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* 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.alibaba.nacos.auth.persist;
|
||||||
|
|
||||||
|
import com.alibaba.nacos.auth.model.Page;
|
||||||
|
import com.alibaba.nacos.auth.persist.repository.PaginationHelper;
|
||||||
|
import com.alibaba.nacos.auth.persist.repository.externel.ExternalStoragePersistServiceImpl;
|
||||||
|
import com.alibaba.nacos.auth.roles.RoleInfo;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
import org.mockito.junit.MockitoJUnitRunner;
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
|
public class ExternalRolePersistServiceImplTest {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private ExternalStoragePersistServiceImpl persistService;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private JdbcTemplate jt;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private PaginationHelper paginationHelper;
|
||||||
|
|
||||||
|
private ExternalRolePersistServiceImpl externalRolePersistService;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
externalRolePersistService = new ExternalRolePersistServiceImpl();
|
||||||
|
Class<ExternalRolePersistServiceImpl> externalRolePersistServiceClass = ExternalRolePersistServiceImpl.class;
|
||||||
|
Field persistServiceClassDeclaredField = externalRolePersistServiceClass.getDeclaredField("persistService");
|
||||||
|
persistServiceClassDeclaredField.setAccessible(true);
|
||||||
|
persistServiceClassDeclaredField.set(externalRolePersistService, persistService);
|
||||||
|
|
||||||
|
Mockito.when(persistService.getJdbcTemplate()).thenReturn(jt);
|
||||||
|
Mockito.when(persistService.createPaginationHelper()).thenReturn(paginationHelper);
|
||||||
|
|
||||||
|
externalRolePersistService.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetRolesByUserName() {
|
||||||
|
Page<RoleInfo> userName = externalRolePersistService.getRolesByUserName("userName", 1, 10);
|
||||||
|
Assert.assertNull(userName);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2021 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* 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.alibaba.nacos.auth.persist;
|
||||||
|
|
||||||
|
import com.alibaba.nacos.auth.model.Page;
|
||||||
|
import com.alibaba.nacos.auth.users.User;
|
||||||
|
import com.alibaba.nacos.auth.persist.repository.PaginationHelper;
|
||||||
|
import com.alibaba.nacos.auth.persist.repository.externel.ExternalStoragePersistServiceImpl;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
import org.mockito.junit.MockitoJUnitRunner;
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
|
public class ExternalUserPersistServiceImplTest {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private ExternalStoragePersistServiceImpl persistService;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private JdbcTemplate jdbcTemplate;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private PaginationHelper paginationHelper;
|
||||||
|
|
||||||
|
private ExternalUserPersistServiceImpl externalUserPersistService;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
externalUserPersistService = new ExternalUserPersistServiceImpl();
|
||||||
|
|
||||||
|
Class<ExternalUserPersistServiceImpl> externalUserPersistServiceClass = ExternalUserPersistServiceImpl.class;
|
||||||
|
Field persistServiceClassDeclaredField = externalUserPersistServiceClass.getDeclaredField("persistService");
|
||||||
|
persistServiceClassDeclaredField.setAccessible(true);
|
||||||
|
persistServiceClassDeclaredField.set(externalUserPersistService, persistService);
|
||||||
|
|
||||||
|
Mockito.when(persistService.getJdbcTemplate()).thenReturn(jdbcTemplate);
|
||||||
|
Mockito.when(persistService.createPaginationHelper()).thenReturn(paginationHelper);
|
||||||
|
externalUserPersistService.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateUser() {
|
||||||
|
externalUserPersistService.createUser("username", "password");
|
||||||
|
|
||||||
|
String sql = "INSERT INTO users (username, password, enabled) VALUES (?, ?, ?)";
|
||||||
|
Mockito.verify(jdbcTemplate).update(sql, "username", "password", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFindUserByUsername() {
|
||||||
|
User username = externalUserPersistService.findUserByUsername("username");
|
||||||
|
Assert.assertNull(username);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetUsers() {
|
||||||
|
Page<User> users = externalUserPersistService.getUsers(1, 10);
|
||||||
|
Assert.assertNotNull(users);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2020 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* 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.alibaba.nacos.auth.persist.datasource;
|
||||||
|
|
||||||
|
import com.zaxxer.hikari.HikariDataSource;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.springframework.mock.env.MockEnvironment;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
public class DataSourcePoolPropertiesTest {
|
||||||
|
|
||||||
|
private static final String JDBC_URL = "jdbc:derby://127.0.0.1:3306/nacos_devtest?characterEncoding=utf8&serverTimezone=UTC";
|
||||||
|
|
||||||
|
private static final String JDBC_DRIVER_CLASS_NAME = "org.apache.derby.jdbc.EmbeddedDriver";
|
||||||
|
|
||||||
|
private static final String PASSWORD = "nacos";
|
||||||
|
|
||||||
|
private static final String USERNAME = "nacos_devtest";
|
||||||
|
|
||||||
|
private static final Long CONNECTION_TIMEOUT = 10000L;
|
||||||
|
|
||||||
|
private static final Integer MAX_POOL_SIZE = 50;
|
||||||
|
|
||||||
|
private MockEnvironment environment;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
environment = new MockEnvironment();
|
||||||
|
environment.setProperty("db.user", USERNAME);
|
||||||
|
environment.setProperty("db.password", PASSWORD);
|
||||||
|
environment.setProperty("db.pool.config.connectionTimeout", CONNECTION_TIMEOUT.toString());
|
||||||
|
environment.setProperty("db.pool.config.maximumPoolSize", MAX_POOL_SIZE.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBuild() {
|
||||||
|
DataSourcePoolProperties poolProperties = DataSourcePoolProperties.build(environment);
|
||||||
|
poolProperties.setJdbcUrl(JDBC_URL);
|
||||||
|
// poolProperties.setDriverClassName(JDBC_DRIVER_CLASS_NAME);
|
||||||
|
poolProperties.setUsername(USERNAME);
|
||||||
|
poolProperties.setPassword(PASSWORD);
|
||||||
|
HikariDataSource actual = poolProperties.getDataSource();
|
||||||
|
assertEquals(JDBC_URL, actual.getJdbcUrl());
|
||||||
|
assertEquals(JDBC_DRIVER_CLASS_NAME, actual.getDriverClassName());
|
||||||
|
assertEquals(USERNAME, actual.getUsername());
|
||||||
|
assertEquals(PASSWORD, actual.getPassword());
|
||||||
|
assertEquals(CONNECTION_TIMEOUT.longValue(), actual.getConnectionTimeout());
|
||||||
|
assertEquals(DataSourcePoolProperties.DEFAULT_VALIDATION_TIMEOUT, actual.getValidationTimeout());
|
||||||
|
assertEquals(MAX_POOL_SIZE.intValue(), actual.getMaximumPoolSize());
|
||||||
|
assertEquals(DataSourcePoolProperties.DEFAULT_MINIMUM_IDLE, actual.getMinimumIdle());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,144 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2021 Alibaba Group Holding Ltd.
|
||||||
|
*
|
||||||
|
* 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.alibaba.nacos.auth.persist.datasource;
|
||||||
|
|
||||||
|
import com.zaxxer.hikari.HikariDataSource;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.springframework.mock.env.MockEnvironment;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ExternalDataSourcePropertiesTest {
|
||||||
|
|
||||||
|
@SuppressWarnings("checkstyle:linelength")
|
||||||
|
public static final String JDBC_URL = "jdbc:mysql://127.0.0.1:3306/nacos_devtest?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC";
|
||||||
|
|
||||||
|
public static final String PASSWORD = "nacos";
|
||||||
|
|
||||||
|
public static final String USERNAME = "nacos_devtest";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void externalDatasourceNormally() {
|
||||||
|
HikariDataSource expectedDataSource = new HikariDataSource();
|
||||||
|
expectedDataSource.setJdbcUrl(JDBC_URL);
|
||||||
|
expectedDataSource.setUsername(USERNAME);
|
||||||
|
expectedDataSource.setPassword(PASSWORD);
|
||||||
|
MockEnvironment environment = new MockEnvironment();
|
||||||
|
environment.setProperty("db.num", "1");
|
||||||
|
environment.setProperty("db.user", USERNAME);
|
||||||
|
environment.setProperty("db.password", PASSWORD);
|
||||||
|
environment.setProperty("db.url.0", JDBC_URL);
|
||||||
|
List<HikariDataSource> dataSources = new ExternalDataSourceProperties().build(environment, (dataSource -> {
|
||||||
|
Assert.assertEquals(dataSource.getJdbcUrl(), expectedDataSource.getJdbcUrl());
|
||||||
|
Assert.assertEquals(dataSource.getUsername(), expectedDataSource.getUsername());
|
||||||
|
Assert.assertEquals(dataSource.getPassword(), expectedDataSource.getPassword());
|
||||||
|
|
||||||
|
}));
|
||||||
|
Assert.assertEquals(dataSources.size(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void externalDatasourceToAssertMultiJdbcUrl() {
|
||||||
|
|
||||||
|
HikariDataSource expectedDataSource = new HikariDataSource();
|
||||||
|
expectedDataSource.setJdbcUrl(JDBC_URL);
|
||||||
|
expectedDataSource.setUsername(USERNAME);
|
||||||
|
expectedDataSource.setPassword(PASSWORD);
|
||||||
|
MockEnvironment environment = new MockEnvironment();
|
||||||
|
environment.setProperty("db.num", "2");
|
||||||
|
environment.setProperty("db.user", USERNAME);
|
||||||
|
environment.setProperty("db.password", PASSWORD);
|
||||||
|
environment.setProperty("db.url.0", JDBC_URL);
|
||||||
|
environment.setProperty("db.url.1", JDBC_URL);
|
||||||
|
List<HikariDataSource> dataSources = new ExternalDataSourceProperties().build(environment, (dataSource -> {
|
||||||
|
Assert.assertEquals(dataSource.getJdbcUrl(), expectedDataSource.getJdbcUrl());
|
||||||
|
Assert.assertEquals(dataSource.getUsername(), expectedDataSource.getUsername());
|
||||||
|
Assert.assertEquals(dataSource.getPassword(), expectedDataSource.getPassword());
|
||||||
|
|
||||||
|
}));
|
||||||
|
Assert.assertEquals(dataSources.size(), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void externalDatasourceToAssertMultiPasswordAndUsername() {
|
||||||
|
|
||||||
|
HikariDataSource expectedDataSource = new HikariDataSource();
|
||||||
|
expectedDataSource.setJdbcUrl(JDBC_URL);
|
||||||
|
expectedDataSource.setUsername(USERNAME);
|
||||||
|
expectedDataSource.setPassword(PASSWORD);
|
||||||
|
MockEnvironment environment = new MockEnvironment();
|
||||||
|
environment.setProperty("db.num", "2");
|
||||||
|
environment.setProperty("db.user.0", USERNAME);
|
||||||
|
environment.setProperty("db.user.1", USERNAME);
|
||||||
|
environment.setProperty("db.password.0", PASSWORD);
|
||||||
|
environment.setProperty("db.password.1", PASSWORD);
|
||||||
|
environment.setProperty("db.url.0", JDBC_URL);
|
||||||
|
environment.setProperty("db.url.1", JDBC_URL);
|
||||||
|
List<HikariDataSource> dataSources = new ExternalDataSourceProperties().build(environment, (dataSource -> {
|
||||||
|
Assert.assertEquals(dataSource.getJdbcUrl(), expectedDataSource.getJdbcUrl());
|
||||||
|
Assert.assertEquals(dataSource.getUsername(), expectedDataSource.getUsername());
|
||||||
|
Assert.assertEquals(dataSource.getPassword(), expectedDataSource.getPassword());
|
||||||
|
|
||||||
|
}));
|
||||||
|
Assert.assertEquals(dataSources.size(), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void externalDatasourceToAssertMinIdle() {
|
||||||
|
MockEnvironment environment = new MockEnvironment();
|
||||||
|
environment.setProperty("db.num", "1");
|
||||||
|
environment.setProperty("db.user", USERNAME);
|
||||||
|
environment.setProperty("db.password", PASSWORD);
|
||||||
|
environment.setProperty("db.url.0", JDBC_URL);
|
||||||
|
List<HikariDataSource> dataSources = new ExternalDataSourceProperties().build(environment, (dataSource -> {
|
||||||
|
dataSource.validate();
|
||||||
|
Assert.assertEquals(dataSource.getMinimumIdle(), DataSourcePoolProperties.DEFAULT_MINIMUM_IDLE);
|
||||||
|
}));
|
||||||
|
Assert.assertEquals(dataSources.size(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void externalDatasourceFailureWithLarkInfo() {
|
||||||
|
|
||||||
|
MockEnvironment environment = new MockEnvironment();
|
||||||
|
new ExternalDataSourceProperties().build(environment, null);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void externalDatasourceFailureWithErrorInfo() {
|
||||||
|
|
||||||
|
HikariDataSource expectedDataSource = new HikariDataSource();
|
||||||
|
expectedDataSource.setJdbcUrl(JDBC_URL);
|
||||||
|
expectedDataSource.setUsername(USERNAME);
|
||||||
|
expectedDataSource.setPassword(PASSWORD);
|
||||||
|
MockEnvironment environment = new MockEnvironment();
|
||||||
|
// error num of db
|
||||||
|
environment.setProperty("db.num", "2");
|
||||||
|
environment.setProperty("db.user", USERNAME);
|
||||||
|
environment.setProperty("db.password", PASSWORD);
|
||||||
|
environment.setProperty("db.url.0", JDBC_URL);
|
||||||
|
List<HikariDataSource> dataSources = new ExternalDataSourceProperties().build(environment, (dataSource -> {
|
||||||
|
Assert.assertEquals(dataSource.getJdbcUrl(), expectedDataSource.getJdbcUrl());
|
||||||
|
Assert.assertEquals(dataSource.getUsername(), expectedDataSource.getUsername());
|
||||||
|
Assert.assertEquals(dataSource.getPassword(), expectedDataSource.getPassword());
|
||||||
|
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user