github.com/tenywen/fabric@v1.0.0-beta.0.20170620030522-a5b1ed380643/common/configtx/configmap.go (about) 1 /* 2 Copyright IBM Corp. 2017 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package configtx 18 19 import ( 20 "fmt" 21 "strings" 22 23 cb "github.com/hyperledger/fabric/protos/common" 24 ) 25 26 const ( 27 RootGroupKey = "Channel" 28 29 GroupPrefix = "[Groups] " 30 ValuePrefix = "[Values] " 31 PolicyPrefix = "[Policy] " // The plurarility doesn't match, but, it makes the logs much easier being the same length as "Groups" and "Values" 32 33 PathSeparator = "/" 34 ) 35 36 // MapConfig is intended to be called outside this file 37 // it takes a ConfigGroup and generates a map of fqPath to comparables (or error on invalid keys) 38 func MapConfig(channelGroup *cb.ConfigGroup) (map[string]comparable, error) { 39 result := make(map[string]comparable) 40 if channelGroup != nil { 41 err := recurseConfig(result, []string{RootGroupKey}, channelGroup) 42 if err != nil { 43 return nil, err 44 } 45 } 46 return result, nil 47 } 48 49 // addToMap is used only internally by MapConfig 50 func addToMap(cg comparable, result map[string]comparable) error { 51 var fqPath string 52 53 switch { 54 case cg.ConfigGroup != nil: 55 fqPath = GroupPrefix 56 case cg.ConfigValue != nil: 57 fqPath = ValuePrefix 58 case cg.ConfigPolicy != nil: 59 fqPath = PolicyPrefix 60 } 61 62 if err := validateConfigID(cg.key); err != nil { 63 return fmt.Errorf("Illegal characters in key: %s", fqPath) 64 } 65 66 if len(cg.path) == 0 { 67 fqPath += PathSeparator + cg.key 68 } else { 69 fqPath += PathSeparator + strings.Join(cg.path, PathSeparator) + PathSeparator + cg.key 70 } 71 72 logger.Debugf("Adding to config map: %s", fqPath) 73 74 result[fqPath] = cg 75 76 return nil 77 } 78 79 // recurseConfig is used only internally by MapConfig 80 func recurseConfig(result map[string]comparable, path []string, group *cb.ConfigGroup) error { 81 if err := addToMap(comparable{key: path[len(path)-1], path: path[:len(path)-1], ConfigGroup: group}, result); err != nil { 82 return err 83 } 84 85 for key, group := range group.Groups { 86 nextPath := append(path, key) 87 if err := recurseConfig(result, nextPath, group); err != nil { 88 return err 89 } 90 } 91 92 for key, value := range group.Values { 93 if err := addToMap(comparable{key: key, path: path, ConfigValue: value}, result); err != nil { 94 return err 95 } 96 } 97 98 for key, policy := range group.Policies { 99 if err := addToMap(comparable{key: key, path: path, ConfigPolicy: policy}, result); err != nil { 100 return err 101 } 102 } 103 104 return nil 105 } 106 107 // configMapToConfig is intended to be called from outside this file 108 // It takes a configMap and converts it back into a *cb.ConfigGroup structure 109 func configMapToConfig(configMap map[string]comparable) (*cb.ConfigGroup, error) { 110 rootPath := PathSeparator + RootGroupKey 111 return recurseConfigMap(rootPath, configMap) 112 } 113 114 // recurseConfigMap is used only internally by configMapToConfig 115 // Note, this function mutates the cb.Config* entrieswithin configMap, so errors are generally fatal 116 func recurseConfigMap(path string, configMap map[string]comparable) (*cb.ConfigGroup, error) { 117 groupPath := GroupPrefix + path 118 group, ok := configMap[groupPath] 119 if !ok { 120 return nil, fmt.Errorf("Missing group at path: %s", groupPath) 121 } 122 123 if group.ConfigGroup == nil { 124 return nil, fmt.Errorf("ConfigGroup not found at group path: %s", groupPath) 125 } 126 127 for key, _ := range group.Groups { 128 updatedGroup, err := recurseConfigMap(path+PathSeparator+key, configMap) 129 if err != nil { 130 return nil, err 131 } 132 group.Groups[key] = updatedGroup 133 } 134 135 for key, _ := range group.Values { 136 valuePath := ValuePrefix + path + PathSeparator + key 137 value, ok := configMap[valuePath] 138 if !ok { 139 return nil, fmt.Errorf("Missing value at path: %s", valuePath) 140 } 141 if value.ConfigValue == nil { 142 return nil, fmt.Errorf("ConfigValue not found at value path: %s", valuePath) 143 } 144 group.Values[key] = value.ConfigValue 145 } 146 147 for key, _ := range group.Policies { 148 policyPath := PolicyPrefix + path + PathSeparator + key 149 policy, ok := configMap[policyPath] 150 if !ok { 151 return nil, fmt.Errorf("Missing policy at path: %s", policyPath) 152 } 153 if policy.ConfigPolicy == nil { 154 return nil, fmt.Errorf("ConfigPolicy not found at policy path: %s", policyPath) 155 } 156 group.Policies[key] = policy.ConfigPolicy 157 } 158 159 return group.ConfigGroup, nil 160 }