-
Notifications
You must be signed in to change notification settings - Fork 3.2k
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
fix: add Warning message on Version mismatch between CLI and Server. fixes #9212 #11909
Conversation
71d24fd
to
9b5f40b
Compare
I've placed the version check into the root command so it get's executed and prints the warning no matter command the user actually uses and gets notified in case. but I'm not sure whether that's the right as it does execute a few network calls for all commands. happy to implement changes if you have a way to implement this in a smarter way |
Great start, thanks!
There are some unit tests for the CLI already that you can use as an example. Same directory,
If we wanted to optimize this specific call, we could run it async (e.g. in a goroutine) so it doesn't block other commands. |
|
||
// printVersionMismatchWarning logs a warning if the CLI version does not match the server version | ||
func printVersionMismatchWarning(command *cobra.Command) { | ||
// if ARGO_SERVER isn't set there's no need to compare server and cli version |
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'm not sure that this is necessarily accurate. Any usage of the CLI could have unexpected results if there is a version mismatch. For example, through the k8s API, the CLI could be using an outdated spec
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.
you're right. a check would definitely be useful in this case as well. do you know whether there's a way to get a version that's comparable with the cli version directly via api access? I haven't been able to find one but then again I am not very familiar with the codebase yet.
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.
While I agree with:
Any usage of the CLI could have unexpected results if there is a version mismatch.
Even the version
command does not check the server version if ARGO_SERVER
is not defined. I'm assuming is not that simple to determine the version in that case.
https://github.com/argoproj/argo-workflows/blob/main/cmd/argo/commands/version.go#L23
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 comment was about the "there's no need to compare" comment. That is inaccurate.
You may not be able to retrieve it without ARGO_SERVER
set, but it is nonetheless inaccurate to say "there is no need compare". It would be more apt to say "you can't compare". But the comment is a bit redundant at that point
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.
Great, I agree.
…ixes argoproj#9212 Signed-off-by: fhochleitner <[email protected]>
if serverVersion.GitTag != argo.GetVersion().GitTag { | ||
log.Warnf("CLI version (%s) does not match server version (%s). This can lead to unexpected behavior.", argo.GetVersion().GitTag, serverVersion.GitTag) | ||
} |
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 it might be a better idea if you separated out the logic that checks for a mismatch from the code that presents this information to the user.
Only saying this because we could make this a bit more strict then, we could fail on a version mismatch and have a flag to force any action to be performed regardless.
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.
ah sorry for not having able to continue working on this PR. work and private life got quite busy as of late.
I'm not sure this will change a lot in the coming months, but I do think that's a great idea @isubasinghe
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.
No worries, take your time!
Since this is marked as stale and relatively simple, I can take a look. |
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
…ixes argoproj#9212 This adds a warning message to the CLI when it detects a mismatch between the client and server versions. There was another PR (argoproj#11909) for this implemented it by making a blocking API call to `/api/v1/version` in a `PersistentPreRun` hook. This PR takes a different approach: have the server send the version in a new header called `argo-version`, which the client will detect and extract. There's several advantages to this approach: 1. Negligible performance impact, since no additional requests are needed. 2. Warning is only shown when the command would normally send an API request, so we 3. Can be useful for bug triaging, since the header can be seen in `curl` output. Exposing the version information has security implictions, since it could be used by attackers to identify vulnerable Argo servers. To mitigate that, the header is not sent on 401 errors. Of course, if a user is exposing their Argo server to the internet without authentication, then an attacker could see this header, but then they've got bigger problems (and an attacker could just call `/api/v1/version`). This is implemented on the client and server side using [grpc-go interceptors](https://github.com/grpc/grpc-go/blob/master/examples/features/interceptor/README.md). On the server side, there's interceptors to set the version header in the response. On the client side, there's an interceptor to check the response for the header and stash it in a global variable (which is obviously not ideal, but I couldn't think of a better way to handle that). Testing process: 1. Manually changed the version to `v9.99`: https://github.com/argoproj/argo-workflows/blob/ce7f9bfb9b45f009b3e85fabe5e6410de23c7c5f/Makefile#L95 2. Ran `make cli && cp dist/argo argo2` 3. Ran `make start API=true` 4. Ran `ARGO_SECURE=false ARGO_TOKEN="Bearer $(kubectl get secret argo-server.service-account-token -o=jsonpath='{.data.token}' | base64 --decode)" ARGO_SERVER=localhost:2746 ./dist/argo2 list` Output: ``` No workflows found WARN[2024-09-20T18:03:26.116Z] CLI version (v9.99+303bcce.dirty) does not match server version (latest+303bcce.dirty). This can lead to unexpected behavior. ```
…ixes argoproj#9212 This adds a warning message to the CLI when it detects a mismatch between the client and server versions. There was another PR (argoproj#11909) for this implemented it by making a blocking API call to `/api/v1/version` in a `PersistentPreRun` hook. This PR takes a different approach: have the server send the version in a new header called `argo-version`, which the client will detect and extract. There's several advantages to this approach: 1. Negligible performance impact, since no additional requests are needed. 2. Warning is only shown when the command would normally send an API request. 3. Can be useful for bug triaging, since the header can be seen in `curl` output. Exposing the version information has security implictions, since it could be used by attackers to identify vulnerable Argo servers. To mitigate that, the header is not sent on 401 errors. Of course, if a user is exposing their Argo server to the internet without authentication, then an attacker could see this header, but then they've got bigger problems (and an attacker could just call `/api/v1/version`). This is implemented on the client and server side using [grpc-go interceptors](https://github.com/grpc/grpc-go/blob/master/examples/features/interceptor/README.md). On the server side, there's interceptors to set the version header in the response. On the client side, there's an interceptor to check the response for the header and stash it in a global variable (which is obviously not ideal, but I couldn't think of a better way to handle that). Testing process: 1. Manually changed the version to `v9.99`: https://github.com/argoproj/argo-workflows/blob/ce7f9bfb9b45f009b3e85fabe5e6410de23c7c5f/Makefile#L95 2. Ran `make cli && cp dist/argo argo2` 3. Ran `make start API=true` 4. Ran `ARGO_SECURE=false ARGO_TOKEN="Bearer $(kubectl get secret argo-server.service-account-token -o=jsonpath='{.data.token}' | base64 --decode)" ARGO_SERVER=localhost:2746 ./dist/argo2 list` Output: ``` No workflows found WARN[2024-09-20T18:03:26.116Z] CLI version (v9.99+303bcce.dirty) does not match server version (latest+303bcce.dirty). This can lead to unexpected behavior. ``` Signed-off-by: Mason Malone <[email protected]>
…ixes argoproj#9212 This adds a warning message to the CLI when it detects a mismatch between the client and server versions. There was another PR (argoproj#11909) for this implemented it by making a blocking API call to `/api/v1/version` in a `PersistentPreRun` hook. This PR takes a different approach: have the server send the version in a new header called `argo-version`, which the client will detect and extract. There's several advantages to this approach: 1. Negligible performance impact, since no additional requests are needed. 2. Warning is only shown when the command would normally send an API request. 3. Can be useful for bug triaging, since the header can be seen in `curl` output. Exposing the version information has security implictions, since it could be used by attackers to identify vulnerable Argo servers. To mitigate that, the header is not sent on 401 errors. Of course, if a user is exposing their Argo server to the internet without authentication, then an attacker could see this header, but then they've got bigger problems (and an attacker could just call `/api/v1/version`). This is implemented on the client and server side using [grpc-go interceptors](https://github.com/grpc/grpc-go/blob/master/examples/features/interceptor/README.md). On the server side, there's interceptors to set the version header in the response. On the client side, there's an interceptor to check the response for the header and stash it in a global variable (which is obviously not ideal, but I couldn't think of a better way to handle that). Testing process: 1. Manually changed the version to `v9.99`: https://github.com/argoproj/argo-workflows/blob/ce7f9bfb9b45f009b3e85fabe5e6410de23c7c5f/Makefile#L95 2. Ran `make cli && cp dist/argo argo2` 3. Ran `make start API=true` 4. Ran `ARGO_SECURE=false ARGO_TOKEN="Bearer $(kubectl get secret argo-server.service-account-token -o=jsonpath='{.data.token}' | base64 --decode)" ARGO_SERVER=localhost:2746 ./dist/argo2 list` Output: ``` No workflows found WARN[2024-09-20T18:03:26.116Z] CLI version (v9.99+303bcce.dirty) does not match server version (latest+303bcce.dirty). This can lead to unexpected behavior. ``` Signed-off-by: Mason Malone <[email protected]>
Superseded by #13635 |
add Warning message on Version mismatch between CLI and Server.
implemented a check whether argocli and arger-server version are based on the same git-tag and print a warning when versions are mismatched.
Fixes #9212
Motivation
Wanted to start contributing and found an issue that seemed to be a nice start for this journey
Modifications
added function to compare cli and server version and prints a warning in case versions do not match. function fails with warning messages if it cannot contact server as it should not break everything in case of an error.
Verification
built cli and tested it against argo-workflows running on a cluster. happy to implement some e2e tests if required but would need some pointers.