Skip to content
This repository has been archived by the owner on Feb 24, 2024. It is now read-only.

Commit

Permalink
Implement usage of nested APIs
Browse files Browse the repository at this point in the history
`handle_uri` expected the Kubernetes API to be rooted at `/` if more than 2
components were included in the provided URL. This was done to extract a
potential `api_group` from the URL.

This commit changes that behaviour, to parse that `api_group` via a regex,
rather than leaning on a strict URL pattern.
This commit also takes into account, that OpenShift uses `/oapi`, as well
as including a test-suite for that new API URL handling.
Tests also include checks for the `@api_group` and `@api_version` instance
variables and a non-default version.

Implements ManageIQ#318
Fixes ManageIQ#418
  • Loading branch information
T4cC0re committed Aug 25, 2020
1 parent 7430f17 commit 1c9cfa3
Show file tree
Hide file tree
Showing 2 changed files with 170 additions and 4 deletions.
20 changes: 16 additions & 4 deletions lib/kubeclient/common.rb
Original file line number Diff line number Diff line change
Expand Up @@ -194,10 +194,22 @@ def self.resolve_unconventional_method_names(name, kind, singular_name)
def handle_uri(uri, path)
raise ArgumentError, 'Missing uri' unless uri
@api_endpoint = (uri.is_a?(URI) ? uri : URI.parse(uri))
@api_endpoint.path = path if @api_endpoint.path.empty?
@api_endpoint.path = @api_endpoint.path.chop if @api_endpoint.path.end_with?('/')
components = @api_endpoint.path.to_s.split('/') # ["", "api"] or ["", "apis", batch]
@api_group = components.length > 2 ? components[2] + '/' : ''

# This regex will anchor at the last `/api`, `/oapi` or`/apis/:group`) part of the URL
# The whole path will be matched and if existing, the api_group will be extracted.
re = /^(?<path>.*\/o?api(?:s\/(?<apigroup>[^\/]+))?)$/mi
match = re.match(@api_endpoint.path.chomp('/'))

if match
# Since `re` captures 2 groups, match will always have 3 elements
# If thus we have a non-nil value in match 2, this is our api_group.
@api_group = match[:apigroup].nil? ? '' : match[:apigroup] + '/'
@api_endpoint.path = match[:path]
else
# This is a fallback, for when `/api` was not provided as part of the uri
@api_group = ''
@api_endpoint.path = @api_endpoint.path.chomp('/') + path
end
end

def build_namespace_prefix(namespace)
Expand Down
154 changes: 154 additions & 0 deletions test/test_common_url_handling.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
require_relative 'test_helper'

# URLHandling tests
class TestCommonUrlHandling < MiniTest::Test
def test_no_path_in_uri
client = Kubeclient::Client.new('http://localhost:8080', 'v1')
rest_client = client.rest_client
assert_equal('v1', client.instance_variable_get(:@api_version))
assert_equal('', client.instance_variable_get(:@api_group))
assert_equal('http://localhost:8080/api/v1', rest_client.url.to_s)
end

def test_with_api_path_in_uri
client = Kubeclient::Client.new('http://localhost:8080/api', 'v1')
rest_client = client.rest_client
assert_equal('v1', client.instance_variable_get(:@api_version))
assert_equal('', client.instance_variable_get(:@api_group))
assert_equal('http://localhost:8080/api/v1', rest_client.url.to_s)
end

def test_with_api_path_in_uri_other_version
client = Kubeclient::Client.new('http://localhost:8080/api', 'v2')
rest_client = client.rest_client
assert_equal('v2', client.instance_variable_get(:@api_version))
assert_equal('', client.instance_variable_get(:@api_group))
assert_equal('http://localhost:8080/api/v2', rest_client.url.to_s)
end

def test_with_api_group_path_in_uri
client = Kubeclient::Client.new('http://localhost:8080/apis/this_is_the_group', 'v1')
rest_client = client.rest_client
assert_equal('v1', client.instance_variable_get(:@api_version))
assert_equal('this_is_the_group/', client.instance_variable_get(:@api_group))
assert_equal('http://localhost:8080/apis/this_is_the_group/v1', rest_client.url.to_s)
end

def test_with_api_group_path_in_uri_other_version
client = Kubeclient::Client.new('http://localhost:8080/apis/this_is_the_group', 'v2')
rest_client = client.rest_client
assert_equal('v2', client.instance_variable_get(:@api_version))
assert_equal('this_is_the_group/', client.instance_variable_get(:@api_group))
assert_equal('http://localhost:8080/apis/this_is_the_group/v2', rest_client.url.to_s)
end

def test_with_api_path_in_uri_trailing_slash
client = Kubeclient::Client.new('http://localhost:8080/api/', 'v1')
rest_client = client.rest_client
assert_equal('v1', client.instance_variable_get(:@api_version))
assert_equal('', client.instance_variable_get(:@api_group))
assert_equal('http://localhost:8080/api/v1', rest_client.url.to_s)
end

def test_with_api_path_in_api
client = Kubeclient::Client.new('http://localhost:8080/api/but/I/want/a/hidden/k8s/api', 'v1')
rest_client = client.rest_client
assert_equal('v1', client.instance_variable_get(:@api_version))
assert_equal('', client.instance_variable_get(:@api_group))
assert_equal('http://localhost:8080/api/but/I/want/a/hidden/k8s/api/v1', rest_client.url.to_s)
end

def test_with_api_group_path_in_api
client = Kubeclient::Client.new(
'http://localhost:8080/api/but/I/want/a/hidden/k8s/apis/this_is_the_group',
'v1'
)
rest_client = client.rest_client
assert_equal('v1', client.instance_variable_get(:@api_version))
assert_equal('this_is_the_group/', client.instance_variable_get(:@api_group))
assert_equal(
'http://localhost:8080/api/but/I/want/a/hidden/k8s/apis/this_is_the_group/v1',
rest_client.url.to_s
)
end

def test_rancher_with_api_path_in_uri
client = Kubeclient::Client.new('http://localhost:8080/k8s/clusters/c-somerancherID/api', 'v1')
rest_client = client.rest_client
assert_equal('v1', client.instance_variable_get(:@api_version))
assert_equal('', client.instance_variable_get(:@api_group))
assert_equal('http://localhost:8080/k8s/clusters/c-somerancherID/api/v1', rest_client.url.to_s)
end

def test_rancher_no_api_path_in_uri
client = Kubeclient::Client.new('http://localhost:8080/k8s/clusters/c-somerancherID', 'v1')
rest_client = client.rest_client
assert_equal('v1', client.instance_variable_get(:@api_version))
assert_equal('', client.instance_variable_get(:@api_group))
assert_equal('http://localhost:8080/k8s/clusters/c-somerancherID/api/v1', rest_client.url.to_s)
end

def test_rancher_no_api_path_in_uri_trailing_slash
client = Kubeclient::Client.new('http://localhost:8080/k8s/clusters/c-somerancherID/', 'v1')
rest_client = client.rest_client
assert_equal('v1', client.instance_variable_get(:@api_version))
assert_equal('', client.instance_variable_get(:@api_group))
assert_equal('http://localhost:8080/k8s/clusters/c-somerancherID/api/v1', rest_client.url.to_s)
end

def test_rancher_with_api_path_in_uri_trailing_slash
client = Kubeclient::Client.new('http://localhost:8080/k8s/clusters/c-somerancherID/api/', 'v1')
rest_client = client.rest_client
assert_equal('v1', client.instance_variable_get(:@api_version))
assert_equal('', client.instance_variable_get(:@api_group))
assert_equal('http://localhost:8080/k8s/clusters/c-somerancherID/api/v1', rest_client.url.to_s)
end

def test_rancher_with_api_group_in_uri_trailing_slash
client = Kubeclient::Client.new('http://localhost:8080/k8s/clusters/c-somerancherID/apis/this_is_the_group', 'v1')
rest_client = client.rest_client
assert_equal('v1', client.instance_variable_get(:@api_version))
assert_equal('this_is_the_group/', client.instance_variable_get(:@api_group))
assert_equal('http://localhost:8080/k8s/clusters/c-somerancherID/apis/this_is_the_group/v1', rest_client.url.to_s)
end

def test_with_openshift_api_path_in_uri
client = Kubeclient::Client.new('http://localhost:8080/oapi', 'v1')
rest_client = client.rest_client
assert_equal('v1', client.instance_variable_get(:@api_version))
assert_equal('', client.instance_variable_get(:@api_group))
assert_equal('http://localhost:8080/oapi/v1', rest_client.url.to_s)
end

def test_arbitrary_path_with_openshift_api_path_in_uri
client = Kubeclient::Client.new('http://localhost:8080/foobarbaz/oapi', 'v1')
rest_client = client.rest_client
assert_equal('v1', client.instance_variable_get(:@api_version))
assert_equal('', client.instance_variable_get(:@api_group))
assert_equal('http://localhost:8080/foobarbaz/oapi/v1', rest_client.url.to_s)
end

def test_with_openshift_api_path_in_uri_trailing_slash
client = Kubeclient::Client.new('http://localhost:8080/oapi/', 'v1')
rest_client = client.rest_client
assert_equal('v1', client.instance_variable_get(:@api_version))
assert_equal('', client.instance_variable_get(:@api_group))
assert_equal('http://localhost:8080/oapi/v1', rest_client.url.to_s)
end

def test_with_arbitrary_path_in_uri
client = Kubeclient::Client.new('http://localhost:8080/foobarbaz', 'v1')
rest_client = client.rest_client
assert_equal('v1', client.instance_variable_get(:@api_version))
assert_equal('', client.instance_variable_get(:@api_group))
assert_equal('http://localhost:8080/foobarbaz/api/v1', rest_client.url.to_s)
end

def test_with_arbitrary_and_api_path_in_uri
client = Kubeclient::Client.new('http://localhost:8080/foobarbaz/api', 'v1')
rest_client = client.rest_client
assert_equal('v1', client.instance_variable_get(:@api_version))
assert_equal('', client.instance_variable_get(:@api_group))
assert_equal('http://localhost:8080/foobarbaz/api/v1', rest_client.url.to_s)
end
end

0 comments on commit 1c9cfa3

Please sign in to comment.