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

Request K8s API, But it return bad-request (400) #418

Closed
YouRNotPaulChan opened this issue Aug 14, 2019 · 12 comments · Fixed by #457
Closed

Request K8s API, But it return bad-request (400) #418

YouRNotPaulChan opened this issue Aug 14, 2019 · 12 comments · Fixed by #457

Comments

@YouRNotPaulChan
Copy link

YouRNotPaulChan commented Aug 14, 2019

versions

ruby: 2.5.0
k8s client version: 1.13.4
k8s server version: 1.14.5
kubeclient: 4.4.0

My code:

require 'kubeclient'
require 'json'
require 'open3'

content = File.open("nginx.yaml").read

p suffix_name = File.extname("nginx.yaml")

case suffix_name
when '.yaml' then
    hash = YAML.safe_load(content)
    p "yaml content is:#{hash}"
when '.json' then
    hash = JSON.parse(content)
    p "json content is:#{hash}"
end

hash.each do |key, value|
    puts "#{key} is: #{value}"
    if key == "kind"
    @kind = value.to_s.downcase
    end
end

config = Kubeclient::Config.read("rancher_kube_config.kubeconfig")

kubeconfig_text = File.read("rancher_kube_config.kubeconfig")
config_context = Kubeclient::Config.new(YAML.safe_load(kubeconfig_text), nil)
@config = config_context.instance_eval { @kcfg }
config = @config
deployment = Kubeclient::Resource.new(hash)
cert_store = OpenSSL::X509::Store.new
ssl_options = {
	cert_store: cert_store,
	verify_ssl: OpenSSL::SSL::VERIFY_NONE
}
context = config_context.context
auth_options = {
		bearer_token: context.auth_options[:bearer_token]
}
client = Kubeclient::Client.new('https://{my_host}/k8s/clusters/c-h4mdn/api', auth_options: auth_options, ssl_options: ssl_options)

begin
  @create_entity = client.send("create_#{@kind}", deployment)
rescue Kubeclient::HttpError => e
	p e
	@error_code = e.error_code
	@message = e.message
end

if @create_entity.nil?
	p "false"
else
	p "success"
end

The contents of config.kubeconfig:

apiVersion: v1
kind: Config
clusters:
- name: "k8s"
  cluster:
    server: "https://MY_HOST/k8s/clusters/c-h4mdn"
    certificate-authority-data: ...
- name: "k8s-k8smaster"
  cluster:
    server: "https://MY_HOST:6443"
    certificate-authority-data: ...

users:
- name: "user-8lhbv"
  user:
    token: my_token

contexts:
- name: "k8s"
  context:
    user: "user-8lhbv"
    cluster: "k8s"
- name: "k8s-k8smaster"
  context:
    user: "user-8lhbv"
    cluster: "k8s-k8smaster"

current-context: "k8s"

The contents of nginx.yaml:

apiVersion: apps/v1
kind: Pod
metadata:
  name: nginx-test2
  labels:
     app: nginx
  namespace: default
spec:
     containers:
        - name: nginx
          image: nginx
          imagePullPolicy: IfNotPresent
          ports:
          - containerPort: 80
     restartPolicy: Always

The error I'm getting is this, and I think it maybe the apiVersion is wrong:

#<Kubeclient::HttpError: HTTP status code 400, Pod in version "v1" cannot be handled as a Pod: no kind "Pod" is registered for version "clusters/v1" in scheme "k8s.io/kubernetes/pkg/api/legacyscheme/scheme.go:29" for POST https://MY_HOST/k8s/clusters/c-h4mdn/api/v1/namespaces/default/pods>
@YouRNotPaulChan YouRNotPaulChan changed the title Request K8s API with a gem(kubeclient) of ruby, return bad-request (404) Request K8s API with a gem(kubeclient) of ruby, return bad-request (400) Aug 14, 2019
@YouRNotPaulChan YouRNotPaulChan changed the title Request K8s API with a gem(kubeclient) of ruby, return bad-request (400) Request K8s API, But it return bad-request (400) Aug 15, 2019
@cben
Copy link
Collaborator

cben commented Aug 16, 2019

Off the top of my head: Rancher puts API at a sub-path (server: "https://MY_HOST/k8s/clusters/c-h4mdn"), which kubeclient has a silly long-standing problem with: #318
but the error you give sounds different, let me look deeper...

@cben
Copy link
Collaborator

cben commented Aug 16, 2019

BTW, for send("create_#{@kind}", ...) you might want to follow #332, we'll simplify this one day. But for now you wrote it correctly.

@cben
Copy link
Collaborator

cben commented Aug 16, 2019

Obligatory warning about SSL::VERIFY_NONE: if you're using bearer token for authentication, a MITM attacker can just steal the token and get all your permissions on the cluster 😟
It's less catastrophic if you use client certs for authentication, though still unsafe.

@cben
Copy link
Collaborator

cben commented Aug 16, 2019

@YouRNotPaulChan can you post output of require "pp"; pp client? I want to see its instance var to confirm whether you're hitting #318 .

@YouRNotPaulChan
Copy link
Author

Thank you for your reply, but the situation I encountered only happened in the POST method, and everything was normal when using the GET method

@YouRNotPaulChan
Copy link
Author

Thanks again, I am on vacation now, but that Kubernetes is deployed in my company's Intranet, I will post the instance variable of client next Monday:)

@YouRNotPaulChan
Copy link
Author

YouRNotPaulChan commented Aug 19, 2019

@cben This is the output with pp client

"==============client============="
#<Kubeclient::Client:0x00007ff6312e1ba0
 @api_endpoint=#<URI::HTTPS https://MY_HOST/k8s/clusters/c-h4mdn/api>,
 @api_group="clusters/",
 @api_version="v1",
 @as=:ros,
 @auth_options=
  {:bearer_token=>
    "my_token"},
 @discovered=false,
 @entities={},
 @headers=
  {:Authorization=>
    "my_token"},
 @http_max_redirects=10,
 @http_proxy_uri=nil,
 @socket_options={:socket_class=>nil, :ssl_socket_class=>nil},
 @ssl_options=
  {:cert_store=>
    #<OpenSSL::X509::Store:0x00007ff6312e2050
     @chain=nil,
     @error=nil,
     @error_string=nil,
     @time=nil,
     @verify_callback=nil>,
   :verify_ssl=>0},
 @timeouts={:open=>60, :read=>60}>
"==============client============="

@Go-Macyun
Copy link

Have you solved this problem?I have the same question with you.

@Go-Macyun
Copy link

Off the top of my head: Rancher puts API at a sub-path (server: "https://MY_HOST/k8s/clusters/c-h4mdn"), which kubeclient has a silly long-standing problem with: #318
but the error you give sounds different, let me look deeper...

I have the same question and when I DELETE a entity , I got the Uncaught exception: HTTP status code 404, the server could not find the requested resource for DELETE https://{my_host}/k8s/clusters/c-h4mdn/api/v1/pods/nginx-test.WHY? Here is my code:

deleted = client.delete_pod("nginx-test")

@cben
Copy link
Collaborator

cben commented Sep 8, 2019

[Sorry for silence, frantic time at work and home... BTW, I'd be happy to add more maintainers to kubeclient if anyone is interested.]

@api_group="clusters/" is wrongly inferred from the path, this does sound like #318.
This doesn't currently matter much, except it affects apiVersion kubeclient sends to server, so it makes sense GET works and POST fails.
Can you try with #333 (use my
cben dont-set-apiversion branch)? It not the right fix, be confirming it helps and doesnt break other things would be nice.

@Go-Macyun
Copy link

[Sorry for silence, frantic time at work and home... BTW, I'd be happy to add more maintainers to kubeclient if anyone is interested.]

@api_group="clusters/" is wrongly inferred from the path, this does sound like #318.
This doesn't currently matter much, except it affects apiVersion kubeclient sends to server, so it makes sense GET works and POST fails.
Can you try with #333 (use my
cben dont-set-apiversion branch)? It not the right fix, be confirming it helps and doesnt break other things would be nice.

Thanks for your reply! I have tried many times and found that api 'https://{my_host}/k8s/clusters/c-h4mdn/api' can only GET method not POST ,PUT and DELETE methods.After I change my api into "https://MY_HOST:6443" ,everything be OK.But I don't konw why ,maybe which is related to configuration inside k8s.

@cben
Copy link
Collaborator

cben commented Oct 3, 2019

@Go-Macyun No, it's not k8s's fault, it's kubeclient's — it's quite clearly #318.
kubeclient has a bug that it doesn't work with URL structure not rooted at the domain root ☹️
We really should get it fixed. Unfortunately it seems the discussion there has been too long so it became scary so nobody contributed a fix, waiting for me and I haven't found the time.

Can you try my branch from #333?
As I said it's not the right fix (I think it only work with one of two styles of initializing Kubeclient::Client? Need to add those tests I outlined on #318...) but it'll probably work for you.
[EDIT: both of you, will probably work for YouRNotPaulChan too]

T4cC0re added a commit to T4cC0re/kubeclient that referenced this issue Aug 12, 2020
`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.

Implements ManageIQ#318
Fixes ManageIQ#418
T4cC0re added a commit to T4cC0re/kubeclient that referenced this issue Aug 25, 2020
`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
T4cC0re added a commit to T4cC0re/kubeclient that referenced this issue Aug 25, 2020
`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
T4cC0re added a commit to T4cC0re/kubeclient that referenced this issue Aug 25, 2020
`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
@cben cben closed this as completed in #457 Aug 28, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants