Rust client for Kubernetes

Overview

kubernetes-rust

Build Status Client Capabilities Client Support Level

Rust client for Kubernetes API.

Example

List all Pods on kube-system:

(req) .expect("failed to list up pods"); println!("{:?}", list_pod); }">
extern crate failure;
extern crate k8s_openapi;
extern crate kubernetes;

use k8s_openapi::api::core::v1 as api;
use kubernetes::client::APIClient;
use kubernetes::config;

fn main() {
    let kubeconfig = config::load_kube_config().expect("failed to load kubeconfig");
    let kubeclient = APIClient::new(kubeconfig);
    let (req, _) = api::Pod::list_namespaced_pod("kube-system", Default::default())
        .expect("failed to create a request");
    let list_pod = kubeclient
        .request::
   (req)
        .
   expect(
   "failed to list up pods");
    
   println!(
   "{:?}", list_pod);
}
  
Comments
  • Add credential-plugin authentication support

    Add credential-plugin authentication support

    This adds support for credential-plugin authentication.

    https://kubernetes.io/docs/reference/access-authn-authz/authentication/#client-go-credential-plugins

    This is used by the Kubernetes AWS IAM authenticator.

    https://github.com/kubernetes-sigs/aws-iam-authenticator

    I took the data types from here:

    https://github.com/kubernetes/client-go/blob/03bfb9bdcfe5482795b999f39ca3ed9ad42ce5bb/pkg/apis/clientauthentication/v1beta1/types.go

    There is a timestamp that should probably be converted to a time object. I haven't looked into how the Go client handles refreshing the credentials.

    opened by svend 8
  • Package name should not contain

    Package name should not contain "-_rust"

    Hey there.

    Package names (Cargo.toml) should never contain "-rust" or "_rust". They are totally redundant and pretty annoying for users.

    opened by theduke 2
  • WIP threaded poll fix

    WIP threaded poll fix

    Trying to fix #97.

    Tried propagating BoxStream and the corresponding Send requirement on K it forced (this is reasonable because a kube object is always just raw data, no refcounts or other magic - but we might have to propagate it to k8s-openapi).

    I think it got almost all the way there, but now it complains at informer in poll(). It wants K to implement Sync as well, and that certainly is unreasonable. But it seems to come from Send being required on &K not being satisfied, looks like in a closure?

    
    error[E0277]: `K` cannot be shared between threads safely
       --> src/api/informer.rs:204:20
        |
    204 |                 }).boxed())
        |                    ^^^^^ `K` cannot be shared between threads safely
        |
        = help: the trait `std::marker::Sync` is not implemented for `K`
        = help: consider adding a `where K: std::marker::Sync` bound
        = note: required because of the requirements on the impl of `std::marker::Send` for `&K`
        = note: required because it appears within the type `for<'r, 's, 't0, 't1, 't2, 't3, 't4, 't5, 't6, 't7> {std::result::Result<api::resource::WatchEvent<K>, Error>, K, K, K, &'r K, K, api::metadata::ObjectMeta, &'s api::metadata::ObjectMeta, &'t0 std::option::Option<std::string::String>, std::option::Option<std::string::String>, std::option::Option<std::string::String>, std::string::String, &'t1 std::string::String, std::string::String, std::string::String, &'t2 futures_util::lock::mutex::Mutex<std::string::String>, std::sync::Arc<futures_util::lock::mutex::Mutex<std::string::String>>, futures_util::lock::mutex::MutexLockFuture<'t3, std::string::String>, futures_util::lock::mutex::MutexLockFuture<'t4, std::string::String>, (), ErrorResponse, bool, bool, bool, &'t5 futures_util::lock::mutex::Mutex<bool>, std::sync::Arc<futures_util::lock::mutex::Mutex<bool>>, futures_util::lock::mutex::MutexLockFuture<'t6, bool>, futures_util::lock::mutex::MutexLockFuture<'t7, bool>, ()}`
        = note: required because it appears within the type `[static generator@src/api/informer.rs:179:32: 203:22 event:std::result::Result<api::resource::WatchEvent<K>, Error>, version:std::sync::Arc<futures_util::lock::mutex::Mutex<std::string::String>>, needs_resync:std::sync::Arc<futures_util::lock::mutex::Mutex<bool>> for<'r, 's, 't0, 't1, 't2, 't3, 't4, 't5, 't6, 't7> {std::result::Result<api::resource::WatchEvent<K>, Error>, K, K, K, &'r K, K, api::metadata::ObjectMeta, &'s api::metadata::ObjectMeta, &'t0 std::option::Option<std::string::String>, std::option::Option<std::string::String>, std::option::Option<std::string::String>, std::string::String, &'t1 std::string::String, std::string::String, std::string::String, &'t2 futures_util::lock::mutex::Mutex<std::string::String>, std::sync::Arc<futures_util::lock::mutex::Mutex<std::string::String>>, futures_util::lock::mutex::MutexLockFuture<'t3, std::string::String>, futures_util::lock::mutex::MutexLockFuture<'t4, std::string::String>, (), ErrorResponse, bool, bool, bool, &'t5 futures_util::lock::mutex::Mutex<bool>, std::sync::Arc<futures_util::lock::mutex::Mutex<bool>>, futures_util::lock::mutex::MutexLockFuture<'t6, bool>, futures_util::lock::mutex::MutexLockFuture<'t7, bool>, ()}]`
        = note: required because it appears within the type `std::future::GenFuture<[static generator@src/api/informer.rs:179:32: 203:22 event:std::result::Result<api::resource::WatchEvent<K>, Error>, version:std::sync::Arc<futures_util::lock::mutex::Mutex<std::string::String>>, needs_resync:std::sync::Arc<futures_util::lock::mutex::Mutex<bool>> for<'r, 's, 't0, 't1, 't2, 't3, 't4, 't5, 't6, 't7> {std::result::Result<api::resource::WatchEvent<K>, Error>, K, K, K, &'r K, K, api::metadata::ObjectMeta, &'s api::metadata::ObjectMeta, &'t0 std::option::Option<std::string::String>, std::option::Option<std::string::String>, std::option::Option<std::string::String>, std::string::String, &'t1 std::string::String, std::string::String, std::string::String, &'t2 futures_util::lock::mutex::Mutex<std::string::String>, std::sync::Arc<futures_util::lock::mutex::Mutex<std::string::String>>, futures_util::lock::mutex::MutexLockFuture<'t3, std::string::String>, futures_util::lock::mutex::MutexLockFuture<'t4, std::string::String>, (), ErrorResponse, bool, bool, bool, &'t5 futures_util::lock::mutex::Mutex<bool>, std::sync::Arc<futures_util::lock::mutex::Mutex<bool>>, futures_util::lock::mutex::MutexLockFuture<'t6, bool>, futures_util::lock::mutex::MutexLockFuture<'t7, bool>, ()}]>`
        = note: required because it appears within the type `impl core::future::future::Future`
        = note: required because it appears within the type `std::option::Option<impl core::future::future::Future>`
        = note: required because it appears within the type `futures_util::stream::stream::then::Then<std::pin::Pin<std::boxed::Box<dyn futures_core::stream::Stream<Item = std::result::Result<api::resource::WatchEvent<K>, Error>> + std::marker::Send>>, impl core::future::future::Future, [closure@src/api/informer.rs:175:32: 204:18 needs_resync:std::sync::Arc<futures_util::lock::mutex::Mutex<bool>>, version:std::sync::Arc<futures_util::lock::mutex::Mutex<std::string::String>>]>`
    
    error: aborting due to previous error
    
    opened by clux 1
  • reading chunked values from watch requests

    reading chunked values from watch requests

    Watch API returns non-json as json:

    GET /api/v1/namespaces/test/pods?watch=1&resourceVersion=10245
    ---
    200 OK
    Transfer-Encoding: chunked
    Content-Type: application/json
    {
      "type": "ADDED",
      "object": {"kind": "Pod", "apiVersion": "v1", "metadata": {"resourceVersion": "10596", ...}, ...}
    }
    {
      "type": "MODIFIED",
      "object": {"kind": "Pod", "apiVersion": "v1", "metadata": {"resourceVersion": "11020", ...}, ...}
    }
    

    Maybe it's possible to parse each chunk as json? Maybe this needs a custom deserializer? Just making a note of this. Not sure how to parse this yet.

    opened by clux 1
  • support authentication without client certs

    support authentication without client certs

    Make load_kube_config less strict by allowing auth with only client key data and a token (like ones generated from a service account).

    If client certs are missing, we also allow people to set insecure-skip-verify.

    opened by clux 1
  • Allow context, cluster, and user names to be specified

    Allow context, cluster, and user names to be specified

    Allow the desired context name, cluster name, and user name to be specified when loading the Kubernetes configuration.

    Do you prefer an option struct or separate arguments?

    option struct

    #[derive(Default)]
    pub struct ConfigOptions {
        pub context: Option<String>,
        pub cluster: Option<String>,
        pub user: Option<String>,
    }
    
    pub fn load_kube_config_with(options: ConfigOptions)
    

    usage:

    let config_opts = config::ConfigOptions {
        context: "mycontext",
        ..Default::default()
    };
    
    let kubeconfig = config::load_kube_config_with(config_opts)?;
    

    arguments

    pub fn load_kube_config_with(
        context: Option<String>,
        cluster: Option<String>,
        user: Option<String>,
    )
    

    usage:

    let kubeconfig = config::load_kube_config_with(Some("mycontext"), None, None)?;
    opened by svend 0
  • Inclusterconfig, Bearer token, and Basic auth

    Inclusterconfig, Bearer token, and Basic auth

    Overview

    • [x] Add interface for Inclusterconfig from #1.
    • [x] Add optional authorization header from #2.

    Others.

    • [x] Add tests.
    • [x] Add travis ci config.
    • [x] Add docstring
    opened by ynqa 0
  • async/await, 2018 edition, updated deps

    async/await, 2018 edition, updated deps

    This brings the crate up to date with changes in the ecosystem.

    The changes here backwards-incompatible, but allow it to be easily used with recent tokio (std::future based) and k8s-openapi-codegen versions (previously broken by a switch to [email protected]).

    The file system I/O is still done with blocking APIs, as the code looks tricky to migrate. The consumer can schedule that part with spawn_blocking if needed.

    Tests and the list_pod example work. I haven't tested the incluster_config example.

    opened by brigand 1
  • The certificate was not trusted.

    The certificate was not trusted.

    Running the example code:

    #[test]
    fn test_general() {
        let kubeconfig = config::load_kube_config().expect("failed to load kubeconfig");
        let kubeclient = APIClient::new(kubeconfig);
        let (req, _) = api::Pod::list_namespaced_pod("kube-system", Default::default())
            .expect("failed to create a request");
        let list_pod = kubeclient
            .request::<api::PodList>(req)
            .expect("failed to list up pods");
        println!("{:?}", list_pod);
    }
    
    ---- test::test_general stdout ----
    thread 'test::test_general' panicked at 'failed to list up pods: Error(Hyper(Error(Connect, Custom { kind: Other, error: Error { code: -67843, message: "The certificate was not trusted." } })), "https://<uuid>.k8s.ondigitalocean.com/api/v1/namespaces/kube-system/pods?")', src/main.rs:76:24
    
    
    failures:
        test::test_general
    
    test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out
    
    opened by thavlik 0
  • Websocket implementation for connect_core_v1_get_namespaced_pod_exec

    Websocket implementation for connect_core_v1_get_namespaced_pod_exec

    Currently there doesn't appear to be a websocket implementation for connect_core_v1_get_namespaced_pod_exec. It would be great to have one. The python k8s client has an implementation here. The ws crate could be used for the implementation. Thanks!

    opened by benwbooth 1
  • dealing with CRDs?

    dealing with CRDs?

    The API for CRDs is generated by kube as soon as the CRD is posted. Thus these structs are not normally available in the openapi bindings or something else (the crd might not even have a schema in older versions of kube). This is usually not a problem, because if you're using rust, you might have a more precise struct for this anyway, but it would be nice to have an API wrapper for this call somehow maybe?

    The go toolchain does some awkward codegeneration that they force people to do more-or-less manually, but that shouldn't be necessary when you have serde and rust on your side. Still, not sure what's the best way to tackle this.

    Currently, am just calling the api the easy way: https://github.com/Babylonpartners/shipcat/blob/8e1fd9c1e0bfef1a9f642f9d7d64b1b938f00ae2/raftcat/src/kube.rs#L13-L19 (and thus avoiding the openapi bindings entirely because that's all i need atm) but wondered if you/someone had thoughts on this.

    opened by clux 5
  • error handling when kube returns an error struct missing

    error handling when kube returns an error struct missing

    One thing I noticed is that data returned from the kube api is assumed to be parseable into the struct you give it: https://github.com/ynqa/kubernetes-rust/blob/9c5f29f1f70d31042371db8ed6782486a41c8e3b/src/client/mod.rs#L37

    however, we have no real information on what went wrong if kube returns an error struct. We simply get a json parsing failed (usually "unexpected EOF" via serde) because the string is attempted to be coerced into a different struct to the one that contains the error.

    This happens if you query for information about your own custom resources and you've failed to add the necessary rbac rules for it, but i'm sure there are many other cases.

    There's currently got a fork to help me deal with this issue in my account (and to get some debug back when it's failed for now). I might be looking to submit a pr back if I stumble across a good solution to it. In the mean time, just thought this ought to be raised.

    At any rate, thanks for this crate! It's allowed me to write a kube app with rust with only minor tweaks!

    opened by clux 3
Owner
Software Engineer
null
Acts as an IRC server and a nostr client. Connect with your IRC client using your nostr private key as the password.

nostr-irc Acts as an IRC server and a nostr client. Connect with your IRC client using your nostr private key as the password. Experimental code, use

null 11 Dec 26, 2022
FTP client for Rust

rust-ftp FTP client for Rust Documentation rust-ftp Installation Usage License Contribution Development environment Installation FTPS support is achie

Matt McCoy 155 Nov 12, 2022
NNTP client for Rust

rust-nntp NNTP Client for Rust Usage extern crate nntp; use nntp::{Article, NNTPStream}; fn main() { let mut nntp_stream = match NNTPStream::connec

Matt McCoy 13 Jan 22, 2022
POP3 client for Rust

rust-pop3 POP3 Client for Rust This client has SSL support. SSL is configured using an SSLContext that is passed into the connect method of a POP3Stre

Matt McCoy 26 Dec 19, 2022
A STOMP client in Rust. Compatible with RabbitMQ, ActiveMQ.

stomp-rs stomp-rs provides a full STOMP 1.2 client implementation for the Rust programming language. This allows programs written in Rust to interact

Zack Slayton 84 Dec 4, 2022
Rust client for NATS, the cloud native messaging system.

A Rust client for the NATS messaging system. Status Motivation Rust may be the most interesting new language the NATS ecosystem has seen. We believe t

NATS - The Cloud Native Messaging System 651 Jan 3, 2023
rqbit - bittorrent client in Rust

rqbit - bittorrent client in Rust

Igor Katson 177 Jan 2, 2023
Simple project to test grpc between ruby (client) and rust (server)

grpc-example Simple project to test grpc between ruby (client) and rust (server). Usage To simplify a lot this project uses docker and docker compose

Bruno Arueira 2 Oct 14, 2021
A rust client and structures to interact with the Clever-Cloud API.

Clever-Cloud Software Development Kit - Rust edition This crate provides structures and client to interact with the Clever-Cloud API. Status This crat

Clever Cloud 6 Jun 3, 2022
Third party Google DNS client for rust.

google-dns-rs Documentation Install Add the following line to your Cargo.toml file: google-dns-rs = "0.3.0" Usage use google_dns_rs::api::{Dns, DoH, R

Eduardo Stuart 2 Nov 13, 2021
A ddns client written in Rust.

ddns-rs ready for use with one cloudflare A/AAAA record ?? A ddns client written in Rust. Features get public ip cloudflare (A or AAAA record) toml co

Ric Li 1 Oct 25, 2022
Rust client for apache iotdb.

Apache IoTDB Apache IoTDB (Database for Internet of Things) is an IoT native database with high performance for data management and analysis, deployab

Mark Liu 7 Aug 4, 2022
A Rust based DNS client, server, and resolver

Trust-DNS A Rust based DNS client, server, and Resolver, built to be safe and secure from the ground up. This repo consists of multiple crates: Librar

Benjamin Fry 2.7k Dec 30, 2022
An online version of the popular game four in a row, written in Rust on the server side and Flutter + Dart on the client.

Four in a Row - Server An online version of the popular game four in a row, written in Rust on the server side and Flutter + Dart on the client. Downl

Filippo OrrĂ¹ 8 Sep 16, 2022
A minimalist socket-based client/server in Rust to illustrate a tutorial

The basics of unix sockets This repository serves as a reference for this tutorial blogpost How to run Install Rust and Cargo, and then do: cargo run

Emmanuel Bosquet 4 Dec 4, 2022
Rust Verbio SpeechCenter Client

The CLI client allows you to launch a single file to the server. It also allows you to use either a grammar or a language model.

Verbio Technologies 3 Sep 16, 2022
Fast Discord RPC Client written in Rust

Discord RPC Client Examples Big image, small image, details and one button discordrpc -c 942151169185316874 -d 'untypeable nickname' --button-1-text '

Oskar 10 Jan 1, 2023
Rust client for Apache Kafka

Kafka Rust Client Project Status This project is starting to be maintained by John Ward, the current status is that I am bringing the project up to da

Kafka Rust 900 Dec 26, 2022
This is a UPnP client library for Rust.

UPnP Client This is a UPNP client library for Rust. Usage Add this to your Cargo.toml: [dependencies] upnp-client = "0.1" Example This example will pr

Tsiry Sandratraina 7 Feb 20, 2023