-
Notifications
You must be signed in to change notification settings - Fork 5.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Expose v4/v6-only connection-schemes through GosnmpWrapper #8804
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks so much for the pull request!
🤝 ✒️ Just a reminder that the CLA has not yet been signed, and we'll need it before merging. Please sign the CLA when you get a chance, then post a comment here saying !signed-cla
!signed-cla |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤝 ✒️ Just a reminder that the CLA has not yet been signed, and we'll need it before merging. Please sign the CLA when you get a chance, then post a comment here saying !signed-cla
!signed-cla |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤝 ✅ CLA has been signed. Thank you!
## example: agents = ["udp://127.0.0.1:161"] | ||
## agents = ["tcp://127.0.0.1:161"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would keep the tcp
example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have re-added the example.
plugins/inputs/snmp/README.md
Outdated
@@ -22,8 +22,11 @@ information. | |||
```toml | |||
[[inputs.snmp]] | |||
## Agent addresses to retrieve values from. | |||
## format: agents = ["<scheme>://<hostname>:<port>"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would mention that scheme
and port
are optional.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, thank you!
Could you check your markup for the checkbox? Should be |
internal/snmp/wrapper.go
Outdated
case "udp4": | ||
gs.Transport = "udp4" | ||
case "udp6": | ||
gs.Transport = "udp6" | ||
case "", "udp": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume the empty string can be removed?
case "", "udp": | |
case "udp": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gosnmp will default to "udp" if no scheme is specified.
However, in userconfig we can omit the "udp://" which will then cause the switch-case to fall through to the default-case.
Regarding #7879:
The default case is reached when an invalid scheme is specified, but telegraf does not output the error nor stop execution. I will look into it further.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct, but isn't that handled by this part?
telegraf/internal/snmp/wrapper.go
Lines 158 to 160 in 3b8df55
if !strings.Contains(agent, "://") { | |
agent = "udp://" + agent | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, you're right.
I removed the line.
plugins/inputs/snmp/snmp.go
Outdated
@@ -24,9 +24,15 @@ import ( | |||
|
|||
const description = `Retrieves SNMP values from remote agents` | |||
const sampleConfig = ` | |||
[[inputs.snmp]] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this line addition is causing the test suite to fail..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed the line.
Thank you for your patience!
internal/snmp/wrapper.go
Outdated
case "udp4": | ||
gs.Transport = "udp4" | ||
case "udp6": | ||
gs.Transport = "udp6" | ||
case "udp": | ||
gs.Transport = "udp" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe keep a more logical ordering?
case "udp4": | |
gs.Transport = "udp4" | |
case "udp6": | |
gs.Transport = "udp6" | |
case "udp": | |
gs.Transport = "udp" | |
case "udp": | |
gs.Transport = "udp" | |
case "udp4": | |
gs.Transport = "udp4" | |
case "udp6": | |
gs.Transport = "udp6" |
internal/snmp/wrapper.go
Outdated
switch u.Scheme { | ||
case "tcp": | ||
gs.Transport = "tcp" | ||
case "tcp4": | ||
gs.Transport = "tcp4" | ||
case "tcp6": | ||
gs.Transport = "tcp6" | ||
case "udp": | ||
gs.Transport = "udp" | ||
case "udp4": | ||
gs.Transport = "udp4" | ||
case "udp6": | ||
gs.Transport = "udp6" | ||
case "tcp", "tcp4", "tcp6", "udp", "udp4", "udp6": | ||
gs.Transport = u.Scheme | ||
default: | ||
return fmt.Errorf("unsupported scheme: %v", u.Scheme) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This got me thinking, why even bother checking it? This block could be replaced with gs.Transport = u.Scheme
and gosnmp will handle it further when connecting. So the snmp input plugin will always support all the schemes that gosnmp is supporting..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi and thank you for you reviews! This is a pleasant experience!
I thought the same thing but I am not sure of the side-effects that the remaining schemes like unix-sockets have. I am not sure if this plays well with windows or if it would play well with non-privileged users on Unix.
After all, the only schemes we do not support with the above code are "unix", "unixgram" and "unixpacket"
.
Usually I prefer to just expose everything the library has to offer and let the user handle the aftermath, but in this case I am a little intimidated by the size of the project here.
I think it would be better to limit the connection possibilities to the "well-known" ones.
What do you think of that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My opinion is still to let gosnmp handle it. I'm calling @reimda in to hear his opinion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did a little digging and I think I know what the intention behind the check in gosnmpwrapper was:
gosnmp will happily take arbitrary values as connetion scheme and not complain about them. The first time the code can fail due to a wrong connection scheme is when gs.Connect
in plugins/input/snmp.go
is called.
However, the error raised by gosnmp is quite descriptive of what is going on:
agent upd4://test: setting up connection: error establishing connection to host: dial upd4:test: unknown network upd
Additionally, this is error is handeled here (line 576 ongoing):
if err := gs.Connect(); err != nil {
return nil, fmt.Errorf("setting up connection: %w", err)
}
So indeed: There should be no problem in letting gosnmp handle the error and just feeding it with anything inu.Scheme
.
Additionally this is more future-proof... maybe gosnmp will add some more schemes later on.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct indeed, that's what I meant.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently I am looking into why the schemes ip
, ip4
and ip6
always seem to fail and return UnknownNetworkError.
I traced it down to dial.go
in the go-sources line 175.
167 func parseNetwork(ctx context.Context, network string, needsProto bool) (afnet string, proto int, err error) {
168 i := last(network, ':')
169 if i < 0 { // no colon
170 switch network {
171 case "tcp", "tcp4", "tcp6":
172 case "udp", "udp4", "udp6":
173 case "ip", "ip4", "ip6":
174 if needsProto {
175 return "", 0, UnknownNetworkError(network)
176 }
177 case "unix", "unixgram", "unixpacket":
178 default:
179 return "", 0, UnknownNetworkError(network)
180 }
181 return network, 0, nil
182 }
Of course: As soon as you specify a port, you also need to specify the protocol! However, the error is not really clear on whats happening.
Since we are using port 161 by default for snmp, it is clear that the aformentiones schemes will not work. And in fact, they don't really make any sense to me... I really don't know why go-snmp offers them in the first place.
For the sockets as connection-schemes:
A socket does not need a port. Unfortunately, specifying something like unix://test:123
will also result in an UnknownNetworkError
. I think this can be quite confusing for the user.
Maybe, after all, it does make sense to limit the connection-schemes to udp{4,6} and tcp{4,6}. Or we have to implement checks in snmp.go
to ensure correct formatting of the schemes.
Maybe this is the reason why the connection-schemes were limited in the first place.
Otherwise, mis-configuration may result in confusing error-messages for the user.
Penny for your thoughts :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, you convinced me 😆 Fine for me to keep it as is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added some documentation, so the next guy is spared of this discovery-process :)
Thanks for your input. Greatly appreciated!
plugins/inputs/snmp/snmp.go
Outdated
if err := gs.SetAgent(agent); err != nil { | ||
return nil, fmt.Errorf("setting gosnmpwrapper agent: %w", err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the idea was to behave it similar like the lines above, so it should have been err = gs.SetAgent(agent)
if err := gs.SetAgent(agent); err != nil { | |
return nil, fmt.Errorf("setting gosnmpwrapper agent: %w", err) | |
err = gs.SetAgent(agent) | |
if err != nil { | |
return nil, err |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you run go test
before you commit? Anyway, last commit is not well formatted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for your work!
plugins/inputs/snmp/README.md
Outdated
## example: agents = ["udp://127.0.0.1:161"] | ||
## agents = ["tcp://127.0.0.1:161"] | ||
## agents = ["udpv4://v4only-snmp-agent"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there an extra "v" in the scheme in this example?
## agents = ["udpv4://v4only-snmp-agent"] | |
## agents = ["udp4://v4only-snmp-agent"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow, good catch!
plugins/inputs/snmp/snmp.go
Outdated
## example: agents = ["udp://127.0.0.1:161"] | ||
## agents = ["tcp://127.0.0.1:161"] | ||
## agents = ["udpv4://v4only-snmp-agent"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extra v here too
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Uhhh.
How many Typos can there be in a few-line-change!
Thanks for your input! :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's what reviews are for!
Hey I noticed you said you're just getting started with go. If you're looking for more opportunities to write go code, feel free to grab issues with the "enhancement" or "good first issue" label. The influx and community devs and I are happy to give you feedback on PRs.
Thanks again for this PR!
(cherry picked from commit 198bcc8)
Hi,
This PR fixes #7879.
I modified the Gosnmpwrapper to expose tcp{4,6} and udp{4,6} as connection-scheme and pass them to Gosnmp.
This way, one can indirectly specify the address-family to be used for snmp-requests.
I updated the according README-files.
In my small test-setup everything is working as intended.
However, I did not find a unit-test for the snmp input-plugin or the wrapper to alter, so I assume this small 4 line change can (hopefully) be reviewed by hand.
This is my first PR on a go-project ever, so please be gentle! :)
Have a nice day.
Required for all PRs: