Skip to content

Conversation

@jrushford
Copy link
Contributor

@jrushford jrushford commented Aug 10, 2018

This PR adds a YAML parser for the proposed parents.yaml file in PR #3870 under discussion by the nexhop, working group.

@jrushford
Copy link
Contributor Author

[approve ci autest]

@jrushford
Copy link
Contributor Author

[approve ci autest]

@jrushford jrushford force-pushed the nh_yaml_parser branch 2 times, most recently from bc08898 to 0e7fc42 Compare August 14, 2018 16:17
@jrushford
Copy link
Contributor Author

[approve ci autest]

@a-canary
Copy link
Collaborator

+1

Copy link
Member

@SolidWallOfCode SolidWallOfCode left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A key question is whether it's better to do so much of the parsing work in the converters or not. I did as little work as possible there and put most of the parsing logic elsewhere.


#include "ts/Diags.h"

#define BUFSIZE 8192
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use constexpr, not #define. But better, don't use fixed sized buffers.

decode(const Node &node, NextHopStrategyConfig &cfg)
{
YAML::Node strategy = node;
try {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bad API design by YAMLCPP IMHO. It means either map access is fraught or you have to do it twice, e.g.

if (!node[NH_strategy]) { ...
} else { // error - missing key
}

I suspect, though, the thrown exception has the data you need and you don't have to catch and rethrow for every access.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that was my mistake, twice is not necessary.

}
if (strategy.Type() == YAML::NodeType::Map) {
// verify keys
for (const_iterator it = strategy.begin(); it != strategy.end(); it++) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use range for loops on the nodes -

for ( auto const& item : strategy ) {
  if (std::none_of(... item.first.as<std::string>()) ) ...

try {
strategy = node[NH_strategy];
} catch (std::exception &ex) {
throw std::runtime_error("the required 'strategy' node does not exist in the yaml document.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Look at the Mark method, which gives you access to the line and column location of the node, which is very nice for error messages.

@SolidWallOfCode
Copy link
Member

That's a first pass of commentary. One additional note - I don't like the fixed buffer size approach to reading the configuration files. I think it's better to do something like ts::file::load in the IP Allow PR, which loads the entire file in to a std::string at the beginning. Parsing is much easier then and has no arbitrary limits. It's even easier if you use TextView, so that getting the first line is something like

std::string content = ts::file::load(path);
ts::TextView line = ts::TextView{content}.split_prefix_at('\n').trim_if(&isspace);
// line has the first line with white space removed from both ends, so "  #include" is valid

// verify the keys
for (const_iterator it = node.begin(); it != node.end(); it++) {
if (std::none_of(valid_host_keys.begin(), valid_host_keys.end(),
[it](std::string s) { return s == it->first.as<std::string>(); })) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const std::string &

p1: &p1
host: p1-cache.foo.com
protocol:
- http: 80
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Support there are two "http" ports, say 80 and 3128. How would that be done?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a list of maps, then? It might be better to have either a list of lists, that is a list of pairs effectively, or a map of lists. That is,

protocol:
  - [ http, 80 ]
  - [ http, 3128 ]
  - [ https, 443 ]

or

protocol:
  - http:
    - 80
    - 3128
  - https:
    - 443

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of your two, I'd choose the latter -- implied order of an array seems like it will lead to problems. An alternative solution would be to require the admin to list the server twice. I believe the effect of listing multiple ports would be that the server would be in the list twice, and thus get 2x the selections than a server with 1 port. That would be obvious to someone listing the server twice, but, I think not obvious when "just" listing multiple ports.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm +1 on leaving the protocol as is and just listing a server twice as @mlibbey suggests so that it is obvious to the person configuring this.

@jrushford
Copy link
Contributor Author

[approve ci]

@jrushford jrushford closed this Feb 26, 2019
@zwoop zwoop removed this from the 8.1.0 milestone Mar 1, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants