github.com/erda-project/erda-infra@v1.0.9/providers/component-protocol/protocol/protocol.go (about) 1 // Copyright (c) 2021 Terminus, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package protocol 16 17 import ( 18 "context" 19 "fmt" 20 "io/ioutil" 21 "strings" 22 23 "github.com/sirupsen/logrus" 24 "gopkg.in/yaml.v3" 25 26 "github.com/erda-project/erda-infra/pkg/strutil" 27 "github.com/erda-project/erda-infra/providers/component-protocol/cptype" 28 "github.com/erda-project/erda-infra/providers/component-protocol/utils/cputil" 29 ) 30 31 // defaultProtocols contains all default protocols. 32 // map key: scenarioKey 33 // map value: default protocol 34 var defaultProtocols = make(map[string]cptype.ComponentProtocol) 35 var defaultProtocolsRaw = make(map[string]string) 36 37 // RegisterDefaultProtocols register protocol contents. 38 func RegisterDefaultProtocols(protocolYAMLs ...[]byte) { 39 for idx, protocolYAML := range protocolYAMLs { 40 var p cptype.ComponentProtocol 41 if err := yaml.Unmarshal(protocolYAML, &p); err != nil { 42 panic(fmt.Errorf("failed to parse protocol yaml, index: %d, err: %v", idx, err)) 43 } 44 if p.Scenario == "" { 45 continue 46 } 47 defaultProtocols[p.Scenario] = p 48 if CpPlaceHolderRe.Match(protocolYAML) { 49 defaultProtocolsRaw[p.Scenario] = string(protocolYAML) 50 } 51 logrus.Infof("default protocol registered for scenario: %s", p.Scenario) 52 } 53 } 54 55 // RegisterDefaultProtocolsFromBasePath register default component protocols under base path. 56 // default path: libs/erda-configs/permission 57 func RegisterDefaultProtocolsFromBasePath(basePath string) { 58 var err error 59 defer func() { 60 if err != nil { 61 logrus.Errorf("failed to register default component protocol, err: %v", err) 62 panic(err) 63 } 64 }() 65 rd, err := ioutil.ReadDir(basePath) 66 if err != nil { 67 return 68 } 69 for _, fi := range rd { 70 if fi.IsDir() { 71 fullDir := basePath + "/" + fi.Name() 72 RegisterDefaultProtocolsFromBasePath(fullDir) 73 } else { 74 if fi.Name() != "protocol.yml" && fi.Name() != "protocol.yaml" { 75 continue 76 } 77 fullName := basePath + "/" + fi.Name() 78 yamlFile, er := ioutil.ReadFile(fullName) 79 if er != nil { 80 err = er 81 return 82 } 83 var p cptype.ComponentProtocol 84 if er := yaml.Unmarshal(yamlFile, &p); er != nil { 85 err = er 86 return 87 } 88 defaultProtocols[p.Scenario] = p 89 logrus.Infof("default protocol registered for scenario: %s", p.Scenario) 90 } 91 } 92 } 93 94 // getDefaultProtocol get default protocol by scenario. 95 func getDefaultProtocol(ctx context.Context, scenario string) (cptype.ComponentProtocol, error) { 96 rawYamlStr, ok := defaultProtocolsRaw[scenario] 97 if !ok { 98 // protocol not have cp placeholder 99 p, ok := defaultProtocols[scenario] 100 if !ok { 101 return cptype.ComponentProtocol{}, fmt.Errorf(i18n(ctx, "${default.protocol.not.exist}, ${scenario}: %s", scenario)) 102 } 103 return p, nil 104 } 105 lang := cputil.Language(ctx) 106 tran := ctx.Value(cptype.GlobalInnerKeyCtxSDK).(*cptype.SDK).Tran 107 replaced := strutil.ReplaceAllStringSubmatchFunc(CpPlaceHolderRe, rawYamlStr, func(v []string) string { 108 if len(v) == 2 && strings.HasPrefix(v[1], I18n+".") { 109 key := strings.TrimPrefix(v[1], I18n+".") 110 if len(key) > 0 { 111 return tran.Text(lang, key) 112 } 113 } 114 return v[0] 115 }) 116 var p cptype.ComponentProtocol 117 if err := yaml.Unmarshal([]byte(replaced), &p); err != nil { 118 return cptype.ComponentProtocol{}, fmt.Errorf("failed to parse protocol yaml i18n, err: %v", err) 119 } 120 return p, nil 121 } 122 123 // getProtoComp . 124 func getProtoComp(ctx context.Context, p *cptype.ComponentProtocol, compName string) (c *cptype.Component, err error) { 125 if p.Components == nil { 126 err = fmt.Errorf("empty protocol components") 127 return 128 } 129 130 c, ok := p.Components[compName] 131 if !ok { 132 defaultProtocol, err := getDefaultProtocol(ctx, p.Scenario) 133 if err != nil { 134 return c, err 135 } 136 c, ok = defaultProtocol.Components[compName] 137 if !ok { 138 err = fmt.Errorf("empty component [%s] in default protocol", compName) 139 } 140 p.Components[compName] = c 141 return c, err 142 } 143 return 144 } 145 146 // getProtoCompStateValue . 147 func getProtoCompStateValue(ctx context.Context, p *cptype.ComponentProtocol, compName, sk string) (interface{}, error) { 148 c, err := getProtoComp(ctx, p, compName) 149 if err != nil { 150 return nil, err 151 } 152 v, err := getCompStateKV(c, sk) 153 if err != nil { 154 return nil, err 155 } 156 return v, nil 157 } 158 159 // polishProtocol . 160 func polishProtocol(req *cptype.ComponentProtocol) { 161 if req == nil { 162 return 163 } 164 // polish component name 165 for name, component := range req.Components { 166 component.Name = name 167 } 168 }