blob: 9c2ac9e1a9f825ab0872428b91d7e9219adc3eee [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 traffic
import (
"strings"
"github.com/apache/dubbo-kubernetes/pkg/admin/config"
"github.com/apache/dubbo-kubernetes/pkg/admin/model"
"github.com/apache/dubbo-kubernetes/pkg/core/logger"
perrors "github.com/pkg/errors"
"gopkg.in/yaml.v2"
)
func removeFromOverride(key, side, param string) error {
oldRule, err := config.Governance.GetConfig(key)
if err != nil {
return err
}
if oldRule == "" {
return perrors.Errorf("Override rule does not exist!")
}
override := &model.Override{}
err = yaml.Unmarshal([]byte(oldRule), override)
if err != nil {
logger.Error("Unrecognized override rule!")
return err
}
for i, c := range override.Configs {
if c.Side == side && c.Parameters[param] != "" {
if len(c.Parameters) == 1 {
override.Configs = append(override.Configs[:i], override.Configs[i+1:]...)
} else {
delete(c.Parameters, param)
}
}
}
if len(override.Configs) == 0 {
err = config.Governance.DeleteConfig(key)
if err != nil {
logger.Error("Failed to delete override rule!")
return err
}
} else {
bytes, _ := yaml.Marshal(override)
err = config.Governance.SetConfig(key, string(bytes))
if err != nil {
return err
}
}
return nil
}
func createOrUpdateOverride(key string, side, param string, newRule model.Override) error {
var mergedRule string
newRuleByte, _ := yaml.Marshal(newRule)
oldRule, err := config.Governance.GetConfig(key)
if err != nil {
if _, ok := err.(*config.RuleNotFound); ok {
logger.Infof("No existing configuration found, will create a new one directly!")
err := config.Governance.SetConfig(key, string(newRuleByte))
if err != nil {
logger.Errorf("Failed to save configuration status, please try again!", err)
return err
}
return nil
} else {
logger.Errorf("Failed to check previous configuration status, please try again!", err)
}
return err
}
if oldRule != "" {
//oJsonByte, err := yaml2.YAMLToJSON([]byte(oldRule))
//if err != nil {
// logger.Errorf("Failed to convert yaml to json!", err)
//}
//nJsonByte, err := yaml2.YAMLToJSON(newRuleByte)
//if err != nil {
// logger.Errorf("Failed to convert yaml to json!", err)
//}
//patch, err := jsonpatch.CreateMergePatch(nJsonByte, oJsonByte)
//fmt.Printf(string(patch))
//testConsumer := `[ { "op": "test", "path": "/side", "value": "consumer" } ]`
//testTimeout := `[ { "op": "test", "path": "/parameters/timeout", "value": null } ]`
//consumerPatch, _ := jsonpatch.DecodePatch(testConsumer)
//timeoutPatch, _ := jsonpatch.DecodePatch(testTimeout)
override := &model.Override{}
_ = yaml.Unmarshal([]byte(oldRule), override)
if param == "weight" {
mergeWeight(override, side, param, newRule)
} else {
mergeOverride(override, side, param, newRule)
}
mergedRuleByte, err := yaml.Marshal(override)
if err != nil {
return err
}
mergedRule = string(mergedRuleByte)
} else {
mergedRule = string(newRuleByte)
}
err = config.Governance.SetConfig(key, mergedRule)
if err != nil {
logger.Errorf("Failed to save timeout yaml rule!", err)
}
return nil
}
// mergeOverride applies to keys like 'timeout', 'accesslog' and 'mock'
func mergeOverride(override *model.Override, side string, param string, newRule model.Override) {
updated := false
for _, c := range override.Configs {
if c.Side == side && c.Parameters[param] != "" {
c.Parameters[param] = newRule.Configs[0].Parameters[param]
c.Enabled = newRule.Enabled
updated = true
break
}
}
if !updated {
override.Configs = append(override.Configs, newRule.Configs[0])
}
override.Enabled = newRule.Enabled
}
// mergeWeight applies to key 'weight'
func mergeWeight(override *model.Override, side string, param string, newRule model.Override) {
for i, c := range override.Configs {
if c.Side == side && c.Parameters[param] != "" {
// todo, add warning promote
override.Configs = append(override.Configs[:i], override.Configs[i+1:]...)
}
}
override.Configs = append(override.Configs, newRule.Configs...)
override.Enabled = newRule.Enabled
}
func getValue(rawRule, side, param string) (interface{}, error) {
override := &model.Override{}
err := yaml.Unmarshal([]byte(rawRule), override)
if err != nil {
return nil, err
}
for _, c := range override.Configs {
if c.Side == side && c.Parameters[param] != nil {
return c.Parameters[param], nil
}
}
return nil, nil
}
func createOrUpdateCondition(key string, newRule model.ConditionRoute) error {
var mergedRule string
newRuleByte, _ := yaml.Marshal(newRule)
oldRule, err := config.Governance.GetConfig(key)
if err != nil {
if _, ok := err.(*config.RuleNotFound); ok {
logger.Infof("No existing configuration found, will create a new one directly!")
err := config.Governance.SetConfig(key, string(newRuleByte))
if err != nil {
logger.Errorf("Failed to save configuration status, please try again!", err)
return err
}
return nil
} else {
logger.Errorf("Failed to check previous configuration status, please try again!", err)
}
return err
}
if oldRule != "" {
route := &model.ConditionRoute{}
_ = yaml.Unmarshal([]byte(oldRule), route)
exist := false
for _, c := range route.Conditions {
if c == newRule.Conditions[0] {
exist = true
}
}
if !exist {
route.Conditions = append(route.Conditions, newRule.Conditions[0])
}
route.Force = newRule.Force
route.Enabled = newRule.Enabled
route.Runtime = newRule.Runtime
mergedRuleByte, err := yaml.Marshal(route)
if err != nil {
return err
}
mergedRule = string(mergedRuleByte)
} else {
mergedRule = string(newRuleByte)
}
err = config.Governance.SetConfig(key, mergedRule)
if err != nil {
logger.Errorf("Failed to save region condition rule!", err)
}
return nil
}
func removeCondition(key, rule string, identifier string) error {
oldRule, err := config.Governance.GetConfig(key)
if err != nil {
return err
}
if oldRule == "" {
return perrors.Errorf("Condition rule does not exist!")
}
route := &model.ConditionRoute{}
err = yaml.Unmarshal([]byte(oldRule), route)
if err != nil {
logger.Error("Unrecognized condition rule!")
return err
}
for i, c := range route.Conditions {
if strings.Contains(c, identifier) {
route.Conditions = append(route.Conditions[:i], route.Conditions[i+1:]...)
break
}
}
if len(route.Conditions) == 0 {
err = config.Governance.DeleteConfig(key)
if err != nil {
logger.Error("Failed to delete override rule!")
return err
}
} else {
bytes, _ := yaml.Marshal(route)
err = config.Governance.SetConfig(key, string(bytes))
if err != nil {
return err
}
}
return nil
}
func createOrUpdateTag(key string, newRule model.TagRoute) error {
var mergedRule string
newRuleByte, _ := yaml.Marshal(newRule)
oldRule, err := config.Governance.GetConfig(key)
if err != nil {
if _, ok := err.(*config.RuleNotFound); ok {
logger.Infof("No existing configuration found, will create a new one directly!")
err := config.Governance.SetConfig(key, string(newRuleByte))
if err != nil {
logger.Errorf("Failed to save configuration status, please try again!", err)
return err
}
return nil
} else {
logger.Errorf("Failed to check previous configuration status, please try again!", err)
}
return err
}
if oldRule != "" {
logger.Warn("Will override the existing tag rule with the new one!")
}
mergedRule = string(newRuleByte)
err = config.Governance.SetConfig(key, mergedRule)
if err != nil {
logger.Errorf("Failed to save region condition rule!", err)
}
return nil
}
func deleteTag(key string) error {
oldRule, err := config.Governance.GetConfig(key)
if err != nil {
return err
}
if oldRule == "" {
logger.Errorf("Tag rule does not exist!")
return nil
}
return config.Governance.DeleteConfig(key)
}