blob: a095ea281dba09a9807c524abfb059b62c02e842 [file] [log] [blame]
/*
* Copyright 2019 WeBank
*
* 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.webank.wedatasphere.linkis.configuration.service
import java.lang.Long
import java.util
import com.webank.wedatasphere.linkis.common.utils.Logging
import com.webank.wedatasphere.linkis.configuration.conf.Configuration
import com.webank.wedatasphere.linkis.configuration.dao.{ConfigMapper, LabelMapper}
import com.webank.wedatasphere.linkis.configuration.entity.{ConfigKey, _}
import com.webank.wedatasphere.linkis.configuration.exception.ConfigurationException
import com.webank.wedatasphere.linkis.configuration.util.{LabelEntityParser, LabelParameterParser}
import com.webank.wedatasphere.linkis.configuration.validate.ValidatorManager
import com.webank.wedatasphere.linkis.governance.common.protocol.conf.ResponseQueryConfig
import com.webank.wedatasphere.linkis.manager.common.protocol.conf.RemoveCacheConfRequest
import com.webank.wedatasphere.linkis.manager.label.builder.CombinedLabelBuilder
import com.webank.wedatasphere.linkis.manager.label.builder.factory.LabelBuilderFactoryContext
import com.webank.wedatasphere.linkis.manager.label.constant.{LabelConstant, LabelKeyConstant}
import com.webank.wedatasphere.linkis.manager.label.entity.engine.{EngineTypeLabel, UserCreatorLabel}
import com.webank.wedatasphere.linkis.manager.label.entity.{CombinedLabel, CombinedLabelImpl, Label, SerializableLabel}
import com.webank.wedatasphere.linkis.manager.label.utils.{EngineTypeLabelCreator, LabelUtils}
import com.webank.wedatasphere.linkis.rpc.Sender
import org.apache.commons.lang.StringUtils
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import org.springframework.util.CollectionUtils
import scala.collection.JavaConverters._
@Service
class ConfigurationService extends Logging {
@Autowired private var configMapper: ConfigMapper = _
@Autowired private var labelMapper: LabelMapper = _
@Autowired private var validatorManager: ValidatorManager = _
private val combinedLabelBuilder: CombinedLabelBuilder = new CombinedLabelBuilder
@Transactional
def addKeyForEngine(engineType: String, version: String, key: ConfigKey): Unit ={
val labelList = LabelEntityParser.generateUserCreatorEngineTypeLabelList("*","*",engineType,version)
val combinedLabel = combinedLabelBuilder.build("", labelList).asInstanceOf[CombinedLabel]
var label = labelMapper.getLabelByKeyValue(combinedLabel.getLabelKey, combinedLabel.getStringValue)
var configs: util.List[ConfigKeyValue] = new util.ArrayList[ConfigKeyValue]()
if(label != null && label.getId > 0){
configs = configMapper.getConfigKeyValueByLabelId(label.getId)
}else{
val parsedLabel = LabelEntityParser.parseToConfigLabel(combinedLabel)
labelMapper.insertLabel(parsedLabel)
info(s"创建label成功:${parsedLabel.getStringValue}")
label = parsedLabel
}
val existsKey = configs.asScala.map(_.getKey).contains(key.getKey)
if(!existsKey){
configMapper.insertKey(key)
info(s"创建Key成功:${key.getKey}")
}else{
configs.asScala.foreach(conf => if(conf.getKey.equals(key.getKey)) key.setId(conf.getId))
}
val existsConfigValue = configMapper.getConfigKeyValueByLabelId(label.getId)
if(existsConfigValue == null){
val configValue = new ConfigValue()
configValue.setConfigKeyId(key.getId)
configValue.setConfigValue("")
configValue.setConfigLabelId(label.getId)
configMapper.insertValue(configValue)
info(s"key、label关联成功:key:${key.getKey},label:${label.getStringValue}")
}
}
def insertCreator(creator:String): Unit ={
val creatorID: Long = configMapper.selectAppIDByAppName(creator)
if(creatorID == null) configMapper.insertCreator(creator) else warn(s"creator${creator} exists")
}
@Transactional
def copyKeyFromIDE(key:ConfigKey,creator:String, appName:String) ={
/*val creatorID: Long = configMapper.selectAppIDByAppName(creator)
key.setApplicationID(creatorID)
val treeID = configMapper.selectTreeIDByKeyID(key.getId)
key.setId(null)
configMapper.insertKey(key)
configMapper.insertKeyTree(key.getId,treeID)*/
}
def checkAndCreateUserLabel(settings: util.List[ConfigKeyValue], username: String, creator: String): Integer ={
var labelId: Integer = null
if(!settings.isEmpty){
val setting = settings.get(0)
val configLabel = labelMapper.getLabelById(setting.getConfigLabelId)
val combinedLabel = combinedLabelBuilder.buildFromStringValue(configLabel.getLabelKey,configLabel.getStringValue).asInstanceOf[CombinedLabel]
combinedLabel.getValue.asScala.foreach(label => {
if (label.isInstanceOf[UserCreatorLabel]) {
if (label.asInstanceOf[UserCreatorLabel].getUser.equals(LabelUtils.COMMON_VALUE)) {
label.asInstanceOf[UserCreatorLabel].setUser(username)
label.asInstanceOf[UserCreatorLabel].setCreator(creator)
val parsedLabel = LabelEntityParser.parseToConfigLabel(combinedLabel)
val userLabel = labelMapper.getLabelByKeyValue(parsedLabel.getLabelKey, parsedLabel.getStringValue)
if (userLabel == null) {
labelMapper.insertLabel(parsedLabel)
labelId = parsedLabel.getId
}else{
labelId = userLabel.getId
}
}else{
labelId = configLabel.getId
}
}
})
}
if(labelId == null){
throw new ConfigurationException("create user label false, cannot save user configuration!(创建用户label信息失败,无法保存用户配置)")
}
labelId
}
def updateUserValue(createList: util.List[ConfigValue], updateList: util.List[ConfigValue]): Unit = {
if(!CollectionUtils.isEmpty(createList)){
configMapper.insertValueList(createList)
}
if(!CollectionUtils.isEmpty(updateList)){
configMapper.updateUserValueList(updateList)
}
}
def clearAMCacheConf(username: String, creator: String, engine: String, version: String): Unit = {
val sender = Sender.getSender(Configuration.MANAGER_SPRING_NAME.getValue)
if(StringUtils.isNotEmpty(username)){
val userCreatorLabel = LabelBuilderFactoryContext.getLabelBuilderFactory.createLabel(classOf[UserCreatorLabel])
userCreatorLabel.setUser(username)
userCreatorLabel.setCreator(creator)
val request = new RemoveCacheConfRequest
request.setUserCreatorLabel(userCreatorLabel)
if(StringUtils.isNotEmpty(engine) && StringUtils.isNotEmpty(version)){
val engineTypeLabel = EngineTypeLabelCreator.createEngineTypeLabel(engine)
engineTypeLabel.setVersion(version)
request.setEngineTypeLabel(engineTypeLabel)
}
sender.ask(request)
}
}
def updateUserValue(setting: ConfigKeyValue, userLabelId: Integer,
createList: util.List[ConfigValue], updateList: util.List[ConfigValue]) = {
paramCheck(setting)
if(setting.getIsUserDefined){
val configValue = new ConfigValue
if(StringUtils.isEmpty(setting.getConfigValue)){
configValue.setConfigValue("")
}else{
configValue.setConfigValue(setting.getConfigValue)
}
configValue.setId(setting.getValueId)
updateList.add(configValue)
}else{
if(!StringUtils.isEmpty(setting.getConfigValue)){
val configValue = new ConfigValue
configValue.setConfigKeyId(setting.getId)
configValue.setConfigLabelId(userLabelId)
configValue.setConfigValue(setting.getConfigValue)
createList.add(configValue)
}
}
}
def paramCheck(setting: ConfigKeyValue) = {
if (!StringUtils.isEmpty(setting.getConfigValue)) {
var key: ConfigKey = null
if(setting.getId != null){
key = configMapper.selectKeyByKeyID(setting.getId)
}else{
key = configMapper.seleteKeyByKeyName(setting.getKey)
}
if(key == null){
throw new ConfigurationException("config key is null, please check again!(配置信息为空,请重新检查key值)")
}
info(s"parameter ${key.getKey} value ${setting.getConfigValue} is not empty, enter checksum...(参数${key.getKey} 值${setting.getConfigValue}不为空,进入校验...)")
if (!validatorManager.getOrCreateValidator(key.getValidateType).validate(setting.getConfigValue, key.getValidateRange)) {
throw new ConfigurationException(s"Parameter verification failed(参数校验失败):${key.getKey}--${key.getValidateType}--${key.getValidateRange}--${setting.getConfigValue}")
}
}
}
def paramCheckByKeyValue(key: String, value: String) = {
val setting = new ConfigKeyValue
setting.setKey(key)
setting.setConfigValue(value)
paramCheck(setting)
}
def listAllEngineType(): Array[String] = {
val engineTypeString = Configuration.ENGINE_TYPE.getValue
val engineTypeList = engineTypeString.split(",")
engineTypeList
}
def generateCombinedLabel(engineType: String = "*", version: String, userName: String = "*", creator: String = "*"): CombinedLabel = {
val labelList = LabelEntityParser.generateUserCreatorEngineTypeLabelList(userName, creator, engineType, version)
val combinedLabel = combinedLabelBuilder.build("",labelList)
combinedLabel.asInstanceOf[CombinedLabelImpl]
}
def buildTreeResult(configs: util.List[ConfigKeyValue],defaultConfigs:util.List[ConfigKeyValue] = new util.ArrayList[ConfigKeyValue]()): util.ArrayList[ConfigTree] = {
var resultConfigs: util.List[ConfigKeyValue] = new util.ArrayList[ConfigKeyValue]()
if(!defaultConfigs.isEmpty){
defaultConfigs.asScala.foreach(defaultConfig => {
defaultConfig.setIsUserDefined(false)
configs.asScala.foreach(config => {
if(config.getKey != null && config.getKey.equals(defaultConfig.getKey)){
if(config.getConfigValue != null){
defaultConfig.setConfigValue(config.getConfigValue)
defaultConfig.setConfigLabelId(config.getConfigLabelId)
defaultConfig.setValueId(config.getValueId)
defaultConfig.setIsUserDefined(true)
}
}
})
})
resultConfigs = defaultConfigs
}
val treeNames = resultConfigs.asScala.map(config => config.getTreeName).distinct
val resultConfigsTree = new util.ArrayList[ConfigTree](treeNames.length)
resultConfigsTree.addAll(treeNames.map(treeName => {
val configTree = new ConfigTree()
configTree.setName(treeName)
configTree.getSettings.addAll(resultConfigs.asScala.filter(config => config.getTreeName.equals(treeName)).toList.asJava)
configTree
}).toList.asJava)
resultConfigsTree
}
// def getFullTree(engineType: String = "*", version: String, userName: String = "*", creator: String = "*", useDefaultConfig: Boolean = true): util.ArrayList[ConfigTree] = {
// val combinedLabel = generateCombinedLabel(engineType, version,userName,creator)
// info(s"start to get config by label:${combinedLabel.getStringValue}(开始通过标签获取配置信息:${combinedLabel.getStringValue})")
// val label = labelMapper.getLabelByKeyValue(combinedLabel.getLabelKey,combinedLabel.getStringValue)
// var configs: util.List[ConfigKeyValue] = new util.ArrayList[ConfigKeyValue]()
// if(label != null && label.getId > 0){
// configs = configMapper.getConfigKeyValueByLabelId(label.getId)
// }
// var defaultConfigs: util.List[ConfigKeyValue] = new util.ArrayList[ConfigKeyValue]()
// if(useDefaultConfig) {
// var defaultCombinedLabel: CombinedLabel = null
// defaultCombinedLabel = generateCombinedLabel(engineType, version)
// val defaultLabel = labelMapper.getLabelByKeyValue(defaultCombinedLabel.getLabelKey, defaultCombinedLabel.getStringValue)
// if(defaultLabel != null){
// defaultConfigs = configMapper.getConfigKeyValueByLabelId(defaultLabel.getId)
// }
// if(CollectionUtils.isEmpty(defaultConfigs)){
// throw new ConfigurationException(s"The default configuration is empty. Please check the default configuration information in the database table(默认配置为空,请检查数据库表中关于标签${defaultCombinedLabel.getStringValue}的默认配置信息是否完整)")
// }
// }
// //persisteUservalue(configs,defaultConfigs,combinedLabel,label)
// info("finished to get config by label, start to build config tree(获取配置信息结束,开始构造配置树)")
// buildTreeResult(configs,defaultConfigs)
// }
def labelCheck(labelList: java.util.List[Label[_]]):Boolean = {
if(!CollectionUtils.isEmpty(labelList)){
labelList.asScala.foreach(label => label match {
case a:UserCreatorLabel => Unit
case a:EngineTypeLabel => Unit
case _ => throw new ConfigurationException(s"this type of label is not supported:${label.getClass}(目前暂不支持该类型的label${label.getClass})")
})
true
}else{
throw new ConfigurationException("The label parameter is empty(label参数为空,无法根据label查询相关配置)")
}
}
def getFullTreeByLabelList(labelList: java.util.List[Label[_]], useDefaultConfig: Boolean = true): util.ArrayList[ConfigTree] = {
labelCheck(labelList)
val combinedLabel = combinedLabelBuilder.build("",labelList).asInstanceOf[CombinedLabelImpl]
info("start to get config by label(开始通过标签获取配置信息)")
val label = labelMapper.getLabelByKeyValue(combinedLabel.getLabelKey,combinedLabel.getStringValue)
var configs: util.List[ConfigKeyValue] = new util.ArrayList[ConfigKeyValue]()
if(label != null && label.getId > 0){
configs = configMapper.getConfigKeyValueByLabelId(label.getId)
}
var defaultConfigs: util.List[ConfigKeyValue] = new util.ArrayList[ConfigKeyValue]()
if(useDefaultConfig) {
//todo 优先级:用户配置-->creator的默认引擎配置-->默认引擎配置,现在缺少creator级别的覆盖
//现在所有获取的默认配置都是获取引擎级别的默认配置,暂时没有应用级别的默认配置。
//如果需要增强上述特性,需要考虑:
//1.对于获取引擎配置:需要将此处生成label的creator改成对应的应用
//2.对于新增引擎配置:需要修改createSecondCategory用于获取linkedEngineTypeLabel的label,同样将它的creator替换成应用的creator
//3.对于数据库初始化:需要修改linkis.dml文件中--关联label和默认配置,将label.label_value = @SPARK_ALL等引擎修改成@SPARK_IDE等等每个应用
//notice:第二点和第三点的性质是一样的,第三点是为了添加系统自带的引擎,第二点是通过管理台配置的方式,让用户省掉第三步
val defaultLabelList = LabelParameterParser.changeUserToDefault(labelList)
val defaultCombinedLabel = combinedLabelBuilder.build("", defaultLabelList).asInstanceOf[CombinedLabelImpl]
val defaultLabel = labelMapper.getLabelByKeyValue(defaultCombinedLabel.getLabelKey, defaultCombinedLabel.getStringValue)
if(defaultLabel != null){
defaultConfigs = configMapper.getConfigKeyValueByLabelId(defaultLabel.getId)
}
if(CollectionUtils.isEmpty(defaultConfigs)){
warn(s"The default configuration is empty. Please check the default configuration information in the database table(默认配置为空,请检查数据库表中关于标签${defaultCombinedLabel.getStringValue}的默认配置信息是否完整)")
}
}
//persisteUservalue(configs,defaultConfigs,combinedLabel,label)
info("finished to get config by label, start to build config tree(获取配置信息成功,开始返回配置树)")
buildTreeResult(configs,defaultConfigs)
}
@Transactional
def persisteUservalue(configs: util.List[ConfigKeyValue], defaultConfigs:util.List[ConfigKeyValue], combinedLabel: CombinedLabel, existsLabel: ConfigLabel): Unit = {
info(s"Start checking the integrity of user configuration data(开始检查用户配置数据的完整性): label标签为:${combinedLabel.getStringValue}")
val userConfigList = configs.asScala
val userConfigKeyIdList = userConfigList.map(config => config.getId)
val defaultConfigsList = defaultConfigs.asScala
val parsedLabel = LabelEntityParser.parseToConfigLabel(combinedLabel)
if(existsLabel == null){
info("start to create label for user(开始为用户创建label):" + "labelKey:" + parsedLabel.getLabelKey + " , " + "labelValue:" + parsedLabel.getStringValue)
labelMapper.insertLabel(parsedLabel)
info("Creation completed(创建完成!):" + parsedLabel)
}
defaultConfigsList.foreach(defaultConfig => {
if(!userConfigKeyIdList.contains(defaultConfig.getId)){
info(s"Initialize database configuration information for users(为用户初始化数据库配置信息):"+s"configKey: ${defaultConfig.getKey}")
val configValue = new ConfigValue
configValue.setConfigKeyId(defaultConfig.getId)
if(existsLabel == null){
configValue.setConfigLabelId(parsedLabel.getId)
}else{
configValue.setConfigLabelId(existsLabel.getId)
}
configValue.setConfigValue("")
configMapper.insertValue(configValue)
info(s"Initialization of user database configuration information completed(初始化用户数据库配置信息完成):configKey: ${defaultConfig.getKey}")
}
})
info(s"User configuration data integrity check completed!(用户配置数据完整性检查完毕!): label标签为:${combinedLabel.getStringValue}")
}
def queryConfigByLabel(labelList: java.util.List[Label[_]], isMerge:Boolean = true, filter:String = null): ResponseQueryConfig = {
labelCheck(labelList)
val allGolbalUserConfig = getFullTreeByLabelList(labelList)
val defaultLabel = LabelParameterParser.changeUserToDefault(labelList)
val allGolbalDefaultConfig = getFullTreeByLabelList(defaultLabel)
val config = new ResponseQueryConfig
config.setKeyAndValue(getMap(allGolbalDefaultConfig,allGolbalUserConfig,filter))
config
}
def queryDefaultEngineConfig(engineTypeLabel: EngineTypeLabel): ResponseQueryConfig = {
val labelList = LabelEntityParser.generateUserCreatorEngineTypeLabelList("*","*",engineTypeLabel.getEngineType,engineTypeLabel.getVersion)
queryConfigByLabel(labelList)
}
def queryGlobalConfig(userName: String): ResponseQueryConfig = {
val labelList = LabelEntityParser.generateUserCreatorEngineTypeLabelList(userName,"*","*","*")
queryConfigByLabel(labelList)
}
def queryConfig(userCreatorLabel: UserCreatorLabel, engineTypeLabel: EngineTypeLabel, filter: String): ResponseQueryConfig ={
val labelList = new util.ArrayList[Label[_]]
labelList.add(userCreatorLabel)
labelList.add(engineTypeLabel)
queryConfigByLabel(labelList, true,filter)
}
private def getMap(all: util.List[ConfigTree], user: util.List[ConfigTree], filter: String = null): util.Map[String, String] = {
val map = new util.HashMap[String, String]()
val allConfig = all.asScala.map(configTree => configTree.getSettings)
val userConfig = user.asScala.map(configTree => configTree.getSettings)
if(filter != null){
allConfig.foreach(f => f.asScala.foreach(configKeyValue => if(configKeyValue.getKey.contains(filter)) map.put(configKeyValue.getKey,configKeyValue.getDefaultValue)))
userConfig.foreach(f => f.asScala.foreach(configKeyValue => if(configKeyValue.getKey.contains(filter) && StringUtils.isNotEmpty(configKeyValue.getConfigValue)) map.put(configKeyValue.getKey,configKeyValue.getConfigValue)))
}else{
allConfig.foreach(f => f.asScala.foreach(configKeyValue => map.put(configKeyValue.getKey,configKeyValue.getDefaultValue)))
userConfig.foreach(f => f.asScala.foreach(configKeyValue => if(StringUtils.isNotEmpty(configKeyValue.getConfigValue))map.put(configKeyValue.getKey,configKeyValue.getConfigValue)))
}
/*此处的用户配置会覆盖默认的配置*/
map
}
}