Skip to content

Commit

Permalink
Merge pull request #10 from cnf-testsuite/feature/1822
Browse files Browse the repository at this point in the history
[feature/1822] Update kubectl version parsing to detect newer versions
  • Loading branch information
agentpoyo authored Sep 6, 2023
2 parents 8b22227 + 04a5be6 commit 7f9e327
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 20 deletions.
2 changes: 1 addition & 1 deletion shard.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: kubectl_client
version: 1.0.1
version: 1.0.2

authors:
- William Harris <[email protected]>
Expand Down
70 changes: 51 additions & 19 deletions src/utils/system_information.cr
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,13 @@ def kubectl_installation(verbose = false, offline_mode = false)
end

def kubectl_global_response(verbose = false)
status = Process.run("kubectl version", shell: true, output: kubectl_response = IO::Memory.new, error: stderr = IO::Memory.new)
status = Process.run("kubectl version -o json", shell: true, output: kubectl_response = IO::Memory.new, error: stderr = IO::Memory.new)
Log.for("verbose").info { kubectl_response } if verbose
kubectl_response.to_s
end

def kubectl_local_response(verbose = false)
current_dir = FileUtils.pwd
Log.for("verbose").info { current_dir } if verbose
status = Process.run("#{local_kubectl_path} version", shell: true, output: kubectl_response = IO::Memory.new, error: stderr = IO::Memory.new)
status = Process.run("#{local_kubectl_path} version -o json", shell: true, output: kubectl_response = IO::Memory.new, error: stderr = IO::Memory.new)
Log.for("verbose").info { kubectl_response.to_s } if verbose
kubectl_response.to_s
end
Expand All @@ -105,26 +103,60 @@ end
# version # => "1.12"
# ```
#
# For reference, below are example client and server version strings from "kubectl version" output
#
# ```
# Client Version: version.Info{Major:"1", Minor:"21", GitVersion:"v1.21.0", GitCommit:"cb303e613a121a29364f75cc67d3d580833a7479", GitTreeState:"clean", BuildDate:"2021-04-08T16:31:21Z", GoVersion:"go1.16.1", Compiler:"gc", Platform:"linux/amd64"}
# Server Version: version.Info{Major:"1", Minor:"20", GitVersion:"v1.20.2", GitCommit:"faecb196815e248d3ecfb03c680a4507229c2a56", GitTreeState:"clean", BuildDate:"2021-01-21T01:11:42Z", GoVersion:"go1.15.5", Compiler:"gc", Platform:"linux/amd64"}
# ```
#
# TODO Function could be updated to rely on the JSON output of "kubectl version -o json" instead of regex parsing
#
# Returns the version as a string (Example: 1.12, 1.20, etc)
def kubectl_version(kubectl_response, version_for = "client", verbose = false)
# version_for can be "client" or "server"
resp = kubectl_response.match /#{version_for.capitalize} Version: version.Info{(Major:"(([0-9]{1,3})"\, )Minor:"([0-9]{1,3}[+]?)")/
Log.for("verbose").info { resp } if verbose
version_info_json = kubectl_response

# The version skew or the server connection warnings are mutually exclusive.
# Only one of them may be present in the output.

# Strip the server connection warning if it exists in the output.
# Server connection warning looks like below:
# The connection to the server localhost:8080 was refused - did you specify the right host or port?
if kubectl_response.includes?("The connection to the server")
version_info_lines = version_info_json.split("\n")
version_info_json = version_info_lines[0, version_info_lines.size - 1].join("\n")
end

# Strip the version skew warning if it exists in the output.
# Version skew warning looks like below:
# WARNING: version difference between client (1.28) and server (1.25) exceeds the supported minor version skew of +/-1
if kubectl_response.includes?("WARNING: version difference between client")
version_info_lines = version_info_json.split("\n")
version_info_json = version_info_lines[0, version_info_lines.size - 1].join("\n")
end

# Look for the appropriate key depending on client or server version lookup
version_key = "clientVersion"
if version_for == "server"
version_key = "serverVersion"
end

# Attempt to parse version output
# Or return blank string if json parse exception
begin
version_data = JSON.parse(version_info_json)
rescue ex : JSON::ParseException
return ""
end

if resp
"#{resp && resp.not_nil![3]}.#{resp && resp.not_nil![4]}"
# If the specific server/client version info does not exist,
# then return blank string
if version_data.as_h.has_key?(version_key)
version_info = version_data[version_key]
else
""
return ""
end

# If major and minor keys do not exist, then return blank string
if version_info.as_h.has_key?("major") && version_info.as_h.has_key?("minor")
major_version = version_info["major"].as_s
minor_version = version_info["minor"].as_s
else
return ""
end

"#{major_version}.#{minor_version}"
end

# Check if client version is not too many versions behind server version
Expand Down

0 comments on commit 7f9e327

Please sign in to comment.