Skip to content

Commit

Permalink
fix: fixed compatibility with old agentctl yaml output (removed addit…
Browse files Browse the repository at this point in the history
…ional config root)

Signed-off-by: Filip Gschwandtner <filip.gschwandtner@pantheon.tech>
  • Loading branch information
fgschwan committed Nov 9, 2020
1 parent b59cf0d commit 7ed4739
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 60 deletions.
62 changes: 17 additions & 45 deletions client/dynamic_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,29 +146,14 @@ func createDynamicConfigDescriptorProto(knownModels []*ModelInfo, dependencyRegi

// create config message
configDP := &descriptorpb.DescriptorProto{
Name: proto.String("Config"),
}

// create fake root to mimic the same usage as with hardcoded configurator.Config proto message
// (idea is to not break anything for user that is using yaml configs from/for old
// hardcoded configurator.Config proto message)
fakeConfigRootDP := &descriptorpb.DescriptorProto{
Name: proto.String("Dynamic_config"),
Field: []*descriptorpb.FieldDescriptorProto{
&descriptorpb.FieldDescriptorProto{
Name: proto.String(configName),
Number: proto.Int32(1), // field numbering
JsonName: proto.String("config"),
Type: protoType(descriptorpb.FieldDescriptorProto_TYPE_MESSAGE),
TypeName: proto.String(*configDP.Name),
Label: protoLabel(descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL),
},
},
}
rootMsgName = protoreflect.Name(*(fakeConfigRootDP.Name))

// add new messages to proto file
fileDP.MessageType = []*descriptorpb.DescriptorProto{fakeConfigRootDP, configDP}
// add config message to proto file
fileDP.MessageType = []*descriptorpb.DescriptorProto{configDP}

// define configuration root (for users of this function)
rootMsgName = protoreflect.Name(*(configDP.Name))

// fill dynamic message with given known models
configGroups := make(map[string]*descriptorpb.DescriptorProto)
Expand Down Expand Up @@ -264,16 +249,19 @@ func DynamicConfigExport(dynamicConfig *dynamicpb.Message) ([]proto.Message, err
return nil, errors.Errorf("dynamic config can't be nil")
}

// moving from fake config root to real config root
configField := dynamicConfig.Descriptor().Fields().ByName(configName)
if configField == nil {
return nil, errors.Errorf("can't find field %v. Was provided dynamic config created by "+
"NewDynamicConfig(...) method or equivalently?", configName)
}
configMessage := dynamicConfig.Get(configField).Message()
// iterate over config group messages and extract proto message from them
result := make([]proto.Message, 0)
fields := dynamicConfig.Descriptor().Fields()
for i := 0; i < fields.Len(); i++ {
fieldName := fields.Get(i).Name()
if strings.HasSuffix(string(fieldName), configGroupSuffix) {
configGroupMessage := dynamicConfig.Get(fields.Get(i)).Message()

// handling export from inner config layers by using helper methods
return exportFromConfigMessage(configMessage), nil
// handling export from inner config layers by using helper method
result = append(result, exportFromConfigGroupMessage(configGroupMessage)...)
}
}
return result, nil
}

// ExportDynamicConfigStructure is a debugging helper function revealing current structure of dynamic config.
Expand Down Expand Up @@ -308,22 +296,6 @@ func ExportDynamicConfigStructure(dynamicConfig proto.Message) (string, error) {
return string(bb), nil
}

// exportFromConfigMessage exports proto messages from config message layer of dynamic config
func exportFromConfigMessage(configMessage protoreflect.Message) []proto.Message {
result := make([]proto.Message, 0)
fields := configMessage.Descriptor().Fields()
for i := 0; i < fields.Len(); i++ {
fieldName := fields.Get(i).Name()
if strings.HasSuffix(string(fieldName), configGroupSuffix) {
configGroupMessage := configMessage.Get(fields.Get(i)).Message()

// handling export from inner config layers by using helper methods
result = append(result, exportFromConfigGroupMessage(configGroupMessage)...)
}
}
return result
}

// exportFromConfigGroupMessage exports proto messages from config group message layer of dynamic config
func exportFromConfigGroupMessage(configGroupMessage protoreflect.Message) []proto.Message {
result := make([]proto.Message, 0)
Expand Down
21 changes: 8 additions & 13 deletions client/dynamic_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,11 @@ func TestYamlCompatibility(t *testing.T) {
RegisterTestingT(t)

// fill hardcoded Config with configuration
// (Note: using fake Config root (configurator.GetResponse) to get "config" root element
// in json/yaml (mimicking agentctl config yaml handling))
ifaces := []*interfaces.Interface{memIFRed, memIFBlack, loop1, vppTap1}
configRoot := &configurator.GetResponse{
Config: &configurator.Config{
VppConfig: &vpp.ConfigData{
Interfaces: ifaces,
Srv6Global: srv6Global,
},
config := &configurator.Config{
VppConfig: &vpp.ConfigData{
Interfaces: ifaces,
Srv6Global: srv6Global,
},
}
// TODO add more configuration to hardcoded version of configuration so it can cover all configuration
Expand All @@ -71,12 +67,12 @@ func TestYamlCompatibility(t *testing.T) {
}

// create dynamic config
// Note: for revealing dynamic sctructure use fmt.Println(client.ExportDynamicConfigStructure(dynConfig))
// Note: for revealing dynamic structure use fmt.Println(client.ExportDynamicConfigStructure(dynConfig))
dynConfig, err := client.NewDynamicConfig(knownModels)
Expect(err).ShouldNot(HaveOccurred(), "can't create dynamic config")

// Hardcoded Config filled with data -> YAML -> JSON -> load to empty dynamic Config -> YAML
yamlFromHardcodedConfig, err := toYAML(configRoot) // should be the same output as agentctl config get
// Hardcoded Config filled with data -> YAML -> JSON -> load into empty dynamic Config -> YAML
yamlFromHardcodedConfig, err := toYAML(config) // should be the same output as agentctl config get
Expect(err).ShouldNot(HaveOccurred(), "can't export hardcoded config as yaml (initial export)")
bj, err := yaml2.YAMLToJSON([]byte(yamlFromHardcodedConfig))
Expect(err).ShouldNot(HaveOccurred(), "can't convert yaml (from hardcoded config) to json")
Expand All @@ -93,8 +89,7 @@ func TestYamlCompatibility(t *testing.T) {
// data can be loaded into dynamic config from yaml form
func TestDynamicConfigWithThirdPartyModel(t *testing.T) {
RegisterTestingT(t)
yaml := `config:
modelConfig:
yaml := `modelConfig:
Basic_list:
- name: testName1
- name: testName2
Expand Down
4 changes: 2 additions & 2 deletions client/remoteclient/grpc_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,9 +182,9 @@ func (c *grpcClient) GetConfig(dsts ...interface{}) error {
protoDsts := extractProtoMessages(dsts)
if len(dsts) == len(protoDsts) { // all dsts are proto messages
// TODO the clearIgnoreLayerCount function argument should be a option of generic.Client
// (the value 2 generates from dynamic config the same json/yaml output as the hardcoded
// (the value 1 generates from dynamic config the same json/yaml output as the hardcoded
// configurator.Config and therefore serves for backward compatibility)
util.PlaceProtosIntoProtos(convertToProtoV2(protos), 2, protoDsts...)
util.PlaceProtosIntoProtos(convertToProtoV2(protos), 1, protoDsts...)
} else {
util.PlaceProtos(protos, dsts...)
}
Expand Down

0 comments on commit 7ed4739

Please sign in to comment.