Skip to content
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

Allowing URI path prefixes in server URLs #110

Merged
merged 9 commits into from
May 8, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/k8s/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
require 'base64'
require 'yajl'
require 'monitor'
require 'uri'

require 'k8s/util'

Expand Down
14 changes: 8 additions & 6 deletions lib/k8s/transport.rb
Original file line number Diff line number Diff line change
Expand Up @@ -142,15 +142,17 @@ def self.in_cluster_config(**options)
)
end

attr_reader :server, :options
attr_reader :server, :options, :path_prefix

# @param server [String] URL with protocol://host:port - any /path is ignored
# @param server [String] URL with protocol://host:port (paths are preserved as well)
# @param auth_token [String] optional Authorization: Bearer token
# @param auth_username [String] optional Basic authentication username
# @param auth_password [String] optional Basic authentication password
# @param options [Hash] @see Excon.new
def initialize(server, auth_token: nil, auth_username: nil, auth_password: nil, **options)
@server = server
uri = URI.parse(server)
@server = "#{uri.scheme}://#{uri.host}:#{uri.port}"
@path_prefix = File.join('/', uri.path, '/') # add leading and/or trailing slashes
Copy link
Contributor

Choose a reason for hiding this comment

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

irb(main):001:0> File.join('/', '', '/')
=> "/"

irb(main):004:0> File.join('/', '/', '/')
=> "/"

irb(main):003:0> File.join('/', '/foo/', '/')
=> "/foo/"

irb(main):005:0> File.join('/', '/foo', '/')
=> "/foo/"

Copy link
Contributor

Choose a reason for hiding this comment

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

The prefix now always has either / or a path with leading and trailing /s.

@auth_token = auth_token
@auth_username = auth_username
@auth_password = auth_password
Expand All @@ -175,10 +177,10 @@ def build_excon
)
end

# @param path [Array<String>] join path parts together to build the full URL
# @param parts [Array<String>] join path parts together to build the full URL
# @return [String]
def path(*path)
File.join('/', *path)
def path(*parts)
File.join(path_prefix, *parts)
end

# @param request_object [Object] include request body using to_json
Expand Down
19 changes: 19 additions & 0 deletions spec/fixtures/config/kubeadm-admin-with-path-prefix.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5RENDQWJDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRFNE1EY3dOVEEyTWpjeE5Gb1hEVEk0TURjd01qQTJNamN4TkZvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBS0V4CjR0ZXN2V1hUV1Z4dlVQdzFwS29NNmE3NFhPRlRTdGF4d0YrcDFMVENUN3JmdlE3Nncwems4c3F1ZEh0MUlMRkgKMnpia1d2b3UrcFlhNUE1YUkxUjlMZk1vSGRPQ2ZUeXBqZmdDVVRzdDl1amxuZ0dmK3M0VFRqRndZMzBvSVNRWQpHaHUvajZBL3gzbWhhQ0psODM2SkhGeTZDTnE1OTk5MU5uMDlDT0RXc0NPbUZ6RHY3K2VaSGZiVzNIMjU1YUpFCm5zS2RHRTJ2ejNSdnVpbmRUUk1FZnhpc1RkRmx1YTZCMWp3MDF2MWRhWlcvek5sSXF6NDRieFJOTmlONFhLVngKeTJqb0dYSDI1aW5udmc4dDQwL1JCSStvamppcU1nQUlRUHVkdVJacW1pYnJMcytDdmtGcUVVWml3cWdWS0ZGQgpwVHQ0dHB5NjVIckZGZVdwcGFjQ0F3RUFBYU1qTUNFd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFKbGE3ejFWb0dPMmNiL00vK0RJcW1vQit4T2UKY0FJTUJxYTNXZUZQUXZ1N2dFbGh3cTBFRndTQmRtOUp6R0xqVHRxbGZ5ai8veEgwc08wdWt3WS9NTkRhODdsZQpXT1lsZFN3RW5WQXhmVjRvU0U1N2J4ci9NeE1YVnlYRXVDc1VOTFhXbG9SM251Y3hINHQzUFRSV0ZrejRyZ1ZSCk95WUtsL2w4VW9ZQWQ5VytsRHBaa1ZXa2oxbDZXQTJZck5YQVdtZTNnb2xMS3FLSUpZTUhKUlhVbnBHSWN2SHUKWVZDaGxqbjVQMnpubkVrRms5aTVtZjZ0ZDlXNEErc0cwTUJkV3c2bUl0RWRSZmM0MVNQWUgrcUQwZDZaZDNzUwo2ZzRhaXA4Z2dmRG9SbjBDL0FKb3lFVkxRL0ZPdy9ua0NJNnRDSDQ2amZXak0rb2plbFVDSHRMcHFjRT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
server: "https://192.168.56.11:6443/k8s/clusters/c-dnmgm"
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: kubernetes-admin
name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
user:
client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM4akNDQWRxZ0F3SUJBZ0lJWlFXeXFFQW8yaEF3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB4T0RBM01EVXdOakkzTVRSYUZ3MHhPVEEzTURVd05qSTNNVFphTURReApGekFWQmdOVkJBb1REbk41YzNSbGJUcHRZWE4wWlhKek1Sa3dGd1lEVlFRREV4QnJkV0psY201bGRHVnpMV0ZrCmJXbHVNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTBYVWZYNlJnRnVVTGxJcWYKbm4xSkpNM0UvVTZNRUMzVVNNaVRTZUp1dERRL25wVEpVcUxLVXNVTWxCYWtrQ1dueERVTE93RDZvTW5UYmVmVgpkWVp3djIyU3hRRDRiNjd5Yk1ZSVlVdmFYOVVCQ3VvNDdvb2c3RDYraDJ1TWZRNnR4MVZ6Uk85TGIvbCtTeDNsClF4RkJhcC9lUDZ3KzZrc3NWejFReDE2a3pEaE80bkRPZ2g3b2FLUTVpOElIUUhYKzBTUVhITlZyTVRWTjk2aHQKRU5PK0tVZThHRXJvR0JTNktnNlo4MkE4TzBEejVrU2xrMWVVZ054WGQwQldlazkwRFNJcGVkZUxocE1pVnBwTApnUmVmbGloWmxuYWRoNHY0amxrUk9LMTRjS1k1SXdZSzRUdVM3bkpBSWd0blJOa2dXUENNTkRWdXl1R0R2V2U4CnZzMVhCd0lEQVFBQm95Y3dKVEFPQmdOVkhROEJBZjhFQkFNQ0JhQXdFd1lEVlIwbEJBd3dDZ1lJS3dZQkJRVUgKQXdJd0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFIdkE5bVVxVGZEQ1VuRDBXQUs5Ni9na2VidnVlK0dUMTFMdApYV05RQTZoekN6MHhHck9pSDhGWTNLb3piZ215TTR5VzFwOEkvR29HVzNmSGl2OHVRTVdqZFFIbVBnZVc1cW9VCm54QlBrOXRuZm1RS2E1UGxEQllIdWFVR3owYzBCdW8zdklQbCs3cU91bkh2YUxUbTR5MnBmQ1ZXaFAraHFmSVUKY24weTdsTzlsbEczWU5ZTW01SEpjSFM1SkdZaEh5cm9JclZnN0NORE5Rak9kNVF3ZnRXVnlMMWVJbktzUEVUMApjV0tRMnNPcmZ2R0pIQ0l6R2tjdWhPM09kems5M0QwbnNrNG05OVlZZ3FpdFJqdWtsdldzOXpjd3pxc3hrQWNlCnZEM011Zzk4TFFSQ1Vxcm9CVldXK0JVb2FvTTZJVER3aDV3cDhuMmE3RVNJR052S096dz0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBMFhVZlg2UmdGdVVMbElxZm5uMUpKTTNFL1U2TUVDM1VTTWlUU2VKdXREUS9ucFRKClVxTEtVc1VNbEJha2tDV254RFVMT3dENm9NblRiZWZWZFlad3YyMlN4UUQ0YjY3eWJNWUlZVXZhWDlVQkN1bzQKN29vZzdENitoMnVNZlE2dHgxVnpSTzlMYi9sK1N4M2xReEZCYXAvZVA2dys2a3NzVnoxUXgxNmt6RGhPNG5ETwpnaDdvYUtRNWk4SUhRSFgrMFNRWEhOVnJNVFZOOTZodEVOTytLVWU4R0Vyb0dCUzZLZzZaODJBOE8wRHo1a1NsCmsxZVVnTnhYZDBCV2VrOTBEU0lwZWRlTGhwTWlWcHBMZ1JlZmxpaFpsbmFkaDR2NGpsa1JPSzE0Y0tZNUl3WUsKNFR1UzduSkFJZ3RuUk5rZ1dQQ01ORFZ1eXVHRHZXZTh2czFYQndJREFRQUJBb0lCQVFDKzl5QzJpMkFNSDZHUwpPVnpVRy9mZTlUZ2Zsa2greTduYTdmdlRoZjFXa0xoY05kempXWVpMTmxxRWZheGx1OThjTlJ4YkhFWms1LzI3CkczNXpXekphWldWRjlkK0x1NTVNNjdSaU9NME5TRjlkK3pRU3o1NjZwVzRDZTF5bi9BVVdVdUw0TzQrMHRHeWYKd2M3dmVjRUJuR1g5K1dXWEtSaHhKWGNMZmsrVDNEQlE0c3hmOHlGVklPQnMrcW9tVUxHWnREK3Y2YUsyaGk5Zwp5VXE2aTN4R2k1ejZVMU04VmZGN0pJZWV6Y2EyVXVHeVdaeGZtK2JyQkZnaXZPZmYxVlZFdjRTWnVKc3RDSnAvClJNUEMwb2pEN2ptSjVEci9QbXM1MjdMYm9qK3o4TmV6TmJhZW8xVmlDYmtKVkM5ZmNKcm05SGlVWVM2dHZmRzEKRVl3ZUpXVWhBb0dCQU9wMlByeGFzTWYxSlR1Zk9NcjdMeE04NTh4bVN4RndGcnlzVUhOcVYxeW9mT0N3TjF5cQplVXNIbE92RnRLd2ZmaFJBSVJTWEhiMGI5aG84STZLQWY4ZmxOUmR3eENpbVhWeUs0NUQ2WklRMXg3V3hSUDdaCllQcVZKdFp6cWp2S1pWWENNaWZWdWUyd25tWS90NXlidzd1MUR6VGpqWjZ0QklMNXBKeUhJU1RSQW9HQkFPU3kKMjhYQUpKSDJVaDA5VnlIdkovR3NrbUxaMXE4VkxrSHpaTmtHWkcxalZVRmNDU2NISXFGeE9URWdkcnZGVkJwNwpaVjQ1K2Z2VmJlTnV6Y1cyN1FNT214dUVFcC9CVEhnb2FCdmY5djdxektsMjdpY3p4S0JGZVBpbWk2VEpVS2IzCm9UL3ZQZnhDNWw1QWVpSnFoOTRvVS9wTTQvaDdFclBMWjVJWmNaUlhBb0dBRGRId2VydkJ4ZGVPWFVoU1dheWEKcHNDbFRTZ09icld6c1dWYXpLTE5DWG9vK2ptSTJkNTJqZFNoazVBd3lTQ0dGdjE4dGJEK29NSUFMS1cwMkFSSgpBK2hmeThUcTJ4YUxWRVFmaTlFbWthQjE2Q0ROMTFQSzRwcGVFcS80cmRPTlM1UEp6dzFMQzFhb3o1QWI2NUJHCjVrNlMyZVE3MmNtTEJZbGZpWlp4ZnJFQ2dZQkFBTUk2dklRL2lTVC80OXZQdG1PQ1loNXhwYTlNUG13OHJzWXAKYW4yT2szOFhsSTlIS2RzS1BXcVpFaEhJaVBmNWxWRVFKcitNTi9YUjhYK0s5cCtyL0ZseVFPc0paSXBuRWovWQpsVHhGcVNadndzWHhtSzVOZ0VQVHFxQm9GS01LcDBDc2FPTDdCeW43ZEtYNW5jQzZicVRaNXN6aURHZDJnOVZQCmNPbDFid0tCZ0VSUG5xei9Jc3VhdnFhK1FxWG0wWWRycmd2VXBrU2J1a1hsZFVjSVhWR1ZvSDlaNGVmWXE5TnQKa21LQkduNHB2VVppR3hhNkhtd0hGOVRhUVMwbUI1R2dyQ0haQkZkbVVIS1Z1TTVSMVJwejkvR1owV3Fhd0x5YgpGWnVPV0RUa01YTzFNMG45VVV0K1pITDJ5a1gxc2tGdm1lNDNzZEZTTUNZVGhwV1dKd0tMCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==
15 changes: 15 additions & 0 deletions spec/k8s/api_client_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
include FixtureHelpers

let(:transport) { K8s::Transport.new('http://localhost:8080') }
let(:transport_with_prefix) { K8s::Transport.new('http://localhost:8080/k8s/clusters/c-dnmgm') }

context "for the v1 API" do
subject { described_class.new(transport, 'v1') }
Expand All @@ -22,6 +23,20 @@
end
end

context "for URIs with a path prefix" do
subject { described_class.new(transport_with_prefix, 'v1') }

describe '#path' do
it "returns the correct root path" do
expect(subject.path).to eq '/k8s/clusters/c-dnmgm/api/v1'
end

it "returns the correct resource path" do
expect(subject.path('tests')).to eq '/k8s/clusters/c-dnmgm/api/v1/tests'
end
end
end

before do
stub_request(:get, 'localhost:8080/api/v1')
.to_return(
Expand Down
43 changes: 43 additions & 0 deletions spec/k8s/transport_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
expect(subject.server).to eq 'https://192.168.56.11:6443'
end

it 'uses the correct path' do
expect(subject.path).to eq '/'
end

it 'uses the correct options' do
expect(subject.options).to match(
ssl_cert_store: OpenSSL::X509::Store,
Expand All @@ -23,6 +27,30 @@
expect(subject.options[:ssl_cert_store].verify(server_cert)).to eq true
end

context "for URIs with a path prefix" do
subject { described_class.config(K8s::Config.load_file(fixture_path('config/kubeadm-admin-with-path-prefix.conf')))}

it 'uses the correct server' do
expect(subject.server).to eq 'https://192.168.56.11:6443'
end

it 'uses the correct path' do
expect(subject.path).to eq '/k8s/clusters/c-dnmgm/'
end

it 'uses the correct options' do
expect(subject.options).to match(
ssl_cert_store: OpenSSL::X509::Store,
client_cert_data: /^-----BEGIN CERTIFICATE-----\n/,
client_key_data: /^-----BEGIN RSA PRIVATE KEY-----\n/,
)
end

it 'uses an ssl_cert_store that verifies the server cert' do
expect(subject.options[:ssl_cert_store].verify(server_cert)).to eq true
end
end

context "overriding the server option" do
subject {
described_class.config(K8s::Config.load_file(fixture_path('config/kubeadm-admin.conf')),
Expand All @@ -33,6 +61,21 @@
it "uses the overriden server" do
expect(subject.server).to eq 'http://localhost:8001'
end

context "for URIs with a path prefix" do
subject { described_class.config(K8s::Config.load_file(fixture_path('config/kubeadm-admin-with-path-prefix.conf')),
server: 'http://localhost:8001',
)
}

it 'uses the correct server' do
expect(subject.server).to eq 'http://localhost:8001'
end

it 'uses the correct path' do
expect(subject.path).to eq '/'
end
end
end

context "overriding other options" do
Expand Down