Swift client for Kubernetes

Overview

Kubernetes 1.18.13 Swift Package Manager macOS + iOS Linux CI Status

Table of contents

Overview

Swift client for talking to a Kubernetes cluster via a fluent DSL based on SwiftNIO and the AysncHTTPClient.

  • Covers all Kubernetes API Groups in v1.19.8
  • Automatic configuration discovery
  • DSL style API
    • For all API Groups/Versions
  • Generic client support
  • Swift-Logging support
  • Loading resources from external sources
    • from files
    • from URLs
  • Read Options
  • List Options
  • Delete Options
  • PATCH API
  • /scale API
  • /status API
  • Resource watch support
  • Follow pod logs support
  • Discovery API
  • CRD support
  • Controller/Informer support
  • Swift Metrics
  • Complete documentation
  • End-to-end tests

Compatibility Matrix

<1.18.9 1.18.9 - 1.18.13 1.19.8
SwiftkubeClient 0.6.x - -
SwiftkubeClient 0.7.x - -
SwiftkubeClient 0.8.x - -
SwiftkubeClient 0.9.x - -
  • Exact match of API objects in both client and the Kubernetes version.
  • - API objects mismatches either due to the removal of old API or the addition of new API. However, everything the client and Kubernetes have in common will work.

Examples

Concrete examples for using the Swiftkube tooling reside in the Swiftkube:Examples repository.

Usage

Creating a client

To create a client just import SwiftkubeClient and init an instance.

import SwiftkubeClient

let client = try KubernetesClient()

You should shut down the KubernetesClient instance, which in turn shuts down the underlying HTTPClient. Thus you shouldn't call client.syncShutdown() before all requests have finished. Alternatively, you can close the client asynchronously by providing a DispatchQueue for the completion callback.

// when finished close the client
 try client.syncShutdown()
 
// or asynchronously
let queue: DispatchQueue = ...
client.shutdown(queue: queue) { (error: Error?) in 
    print(error)
}

Configuring the client

The client tries to resolve a kube config automatically from different sources in the following order:

  • Kube config file in the user's $HOME/.kube/config directory
  • ServiceAccount token located at /var/run/secrets/kubernetes.io/serviceaccount/token and a mounted CA certificate, if it's running in Kubernetes.

Alternatively it can be configured manually, for example:

let caCert = try NIOSSLCertificate.fromPEMFile(caFile)
let authentication = KubernetesClientAuthentication.basicAuth(
    username: "admin", 
    password: "admin"
)

let config = KubernetesClientConfig(
    masterURL: "https://kubernetesmaster",
    namespace: "default",
    authentication: authentication,
    trustRoots: NIOSSLTrustRoots.certificates(caCert),
    insecureSkipTLSVerify: false
)

let client = KubernetesClient(config: config)

Client authentication

The following authentication schemes are supported:

  • Basic Auth: .basicAuth(username: String, password: String)
  • Bearer Token: .bearer(token: String)
  • Client certificate: .x509(clientCertificate: NIOSSLCertificate, clientKey: NIOSSLPrivateKey)

Client DSL

SwiftkubeClient defines convenience API to work with Kubernetes resources. Using this DSL is the same for all resources.

The examples use the blocking wait() for brevity. API calls return EventLoopFutures that can be composed and acted upon in an asynchronous way.

Currently only a subset of all API groups are accessible via the DSL. See Advanced usage for mor details.

List resources

let namespaces = try client.namespaces.list().wait()
let deployments = try client.appsV1.deployments.list(in: .allNamespaces).wait()
let roles = try client.rbacV1.roles.list(in: .namespace("ns")).wait()

You can filter the listed resources or limit the returned list size via the ListOptions:

let deployments = try client.appsV1.deployments.list(in: .allNamespaces, options: [
	.labelSelector(.eq(["app": "nginx"])),
	.labelSelector(.notIn(["env": ["dev", "staging"]])),
	.labelSelector(.exists(["app", "env"])),
	.fieldSelector(.eq(["status.phase": "Running"])),
	.resourceVersion("9001"),
	.limit(20),
	.timeoutSeconds(10)
]).wait()

Get a resource

let namespace = try client.namespaces.get(name: "ns").wait()
let deployment = try client.appsV1.deployments.get(in: .namespace("ns"), name: "nginx").wait()
let roles = try client.rbacV1.roles.get(in: .namespace("ns"), name: "role").wait()

You can also provide the following ReadOptions:

let deployments = try client.appsV1.deployments.get(in: .allNamespaces, options: [
	.pretty(true),
	.exact(false),
	.export(true)
]).wait()

Delete a resource

try.client.namespaces.delete(name: "ns").wait()
try client.appsV1.deployments.delete(in: .namespace("ns"), name: "nginx").wait()
try client.rbacV1.roles.delete(in: .namespace("ns"), name: "role").wait()

You can pass an instance of meta.v1.DeleteOptions to control the behaviour of the delete operation:

let deletOptions = meta.v1.DeleteOptions(
	gracePeriodSeconds: 10,
	propagationPolicy: "Foreground"
)
try client.pods.delete(in: .namespace("ns"), name: "nginx", options: deleteOptions).wait()

Create and update a resource

Resources can be created/updated directly or via the convenience builders defined in SwiftkubeModel

// Create a resouce instance and post it
let configMap = core.v1.ConfigMap(
	metadata: meta.v1.Metadata(name: "test"),
	data: ["foo": "bar"]
}
try cm = try client.configMaps.create(inNamespace: .default, configMap).wait()


// Or inline via a builder
let pod = try client.pods.create(inNamespace: .default) {
        sk.pod {
            $0.metadata = sk.metadata(name: "nginx")
            $0.spec = sk.podSpec {
                $0.containers = [
                    sk.container(name: "nginx") {
                        $0.image = "nginx"
                    }
                ]
            }
        }
    }
    .wait()

Watch a resource

You can watch for Kubernetes events about specific objects via the watch API.

Watching resources opens a persistent connection to the API server. The connection is represented by a SwiftkubeClientTask instance, that acts as an active "subscription" to the events stream.

The task can be cancelled any time to stop the watch.

let task: SwiftkubeClientTask = client.pods.watch(in: .allNamespaces) { (event, pod) in
    print("\(event): \(pod)")
}

task.cancel()

You can also pass ListOptions to filter, i.e. select the required objects:

let options = [
    .labelSelector(.eq(["app": "nginx"])),
    .labelSelector(.exists(["env"]))
]

let task = client.pods.watch(in: .default, options: options) { (event, pod) in
    print("\(event): \(pod)")
}

The client reconnects automatically and restarts the watch upon encountering non-recoverable errors. The reconnect behaviour can be controlled by passing an instance of RetryStrategy.

The default strategy is 10 retry attempts with a fixed 5 seconds delay between each attempt. The initial delay is one second. A jitter of 0.2 seconds is applied.

Passing RetryStrategy.never disables any reconnection attempts.

let strategy = RetryStrategy(
    policy: .maxAttemtps(20),
    backoff: .exponentiaBackoff(maxDelay: 60, multiplier: 2.0),
    initialDelay = 5.0,
    jitter = 0.2
)
let task = client.pods.watch(in: .default, retryStrategy: strategy) { (event, pod) in
    print(pod)
}

To handle events you can pass a ResourceWatcherCallback.EventHandler closure, which is used as a callback for new events. The clients sends each event paired with the corresponding resource as a pair to this eventHandler.

If you require more control or stateful logic, then you can implement the ResourceWatcherDelegate protocol and pass it to the watch call:

class MyDelegate: ResourceWatcherDelegate {
   typealias Resource = core.v1.Pod
   
    func onEvent(event: EventType, resource: core.v1.Pod) {
      // handle events
    }

    func onError(error: SwiftkubeClientError) {
	  // handle errors
    }
}

let task = client.pods.watch(in: .default, delegate: MyDelegate())

Follow logs

The follow API resembles the watch. The difference being the closure/delegate signature:

⚠️ The client does not reconnect on errors in follow mode.

let task = client.pods.follow(in: .default, name: "nginx", container: "app") { (line) in
    print(line)
}

// The task can be cancelled later to stop following logs
task.cancel()

Discovery

The client provides a discovery interface for the API server, which can be used to retrieve the server version, the API groups and the API resources for a specific group version

let version: ResourceOrStatus<Info> = try client.discovery.serverVersion().wait()
let groups: ResourceOrStatus<meta.v1.APIGroupList> = try client.discovery.serverGroups().wait()
let resources: ResourceOrStatus<meta.v1.APIResourceList> = try client.discovery.serverResources(forGroupVersion: "apps/v1").wait()

Advanced usage

Loading from external sources

A resource can be loaded from a file or a URL:

// Load from URL, e.g. a file
let url = URL(fileURLWithPath: "/path/to/manifest.yaml")
let deployment = try apps.v1.Deployment.load(contentsOf: url)

API groups

To access API groups not defined as a DSL, e.g. rbac.v1beta1 a dedicated client can still be intantiated. A client can be either namespace scoped or cluster scoped:

try client.namespaceScoped(for: rbac.v1beta1.RoleBinding.self).list(in: .allNamespaces).wait()
try client.clusterScoped(for: rbac.v1beta1.ClusterRole.self).list().wait()

Type-erased usage

Often when working with Kubernetes the concrete type of the resource is not known or not relevant, e.g. when creating resources from a YAML manifest file. Other times the type or kind of the resource must be derived at runtime given its string representation.

Leveraging SwiftkubeModel's type-erased resource implementations AnyKubernetesAPIResource and its corresponding List-Type AnyKubernetesAPIResourceList it is possible to have a generic client instance, which must be initialized with a GroupVersionKind type:

guard let gvk = try? GroupVersionKind(for: "deployment") else {
   // handle this
}

// Get by name
let resource: AnyKubernetesAPIResource = try client.for(gvk: gvk)
    .get(in: .default , name: "nginx")
    .wait()

// List all
let resources: AnyKubernetesAPIResourceList = try client.for(gvk: gvk)
    .list(in: .allNamespaces)
    .wait()

GroupVersionKind

A GroupVersionKind can be initialized from:

  • KubernetesAPIResource instance
  • KubernetesAPIResource type
  • Full API Group string
  • Lowecassed singular resource kind
  • Lowercased plural resource name
  • lowecased short resource name
let deployment = ..
let gvk = GroupVersionKind(of: deployment)
let gvk = GroupVersionKind(of: apps.v1.Deployment.self)
let gvk = GroupVersionKind(rawValue: "apps/v1/Deployment")
let gvk = GroupVersionKind(for: "deployment")
let gvk = GroupVersionKind(for: "deployments")
let gvk = GroupVersionKind(for: "deploy")

Metrics

KubernetesClient uses SwiftMetrics to collect metric information about the requests count and latencies.

The following metrics are gathered:

  • sk_http_requests_total(counter): the total count of the requests made by the client.
  • sk_http_request_errors_total(counter): the total number of requests made, that returned a http error.
  • sk_request_errors_total(counter): the total number of requests that couldn't be dispatched due to non-http errors.
  • sk_http_request_duration_seconds(timer): the complete request durations.

Collecting the metrics

To collect the metrics you have to bootstrap a metrics backend in your application. For example you can collect the metrics to prometheus via SwiftPrometheus:

import Metrics
import Prometheus

let prom = PrometheusClient()
MetricsSystem.bootstrap(prom)

and expose a /metrics endpoint for scraping:

// if using vapor
app.get("metrics") { request -> EventLoopFuture<String> in
    let promise = request.eventLoop.makePromise(of: String.self)
    try MetricsSystem.prometheus().collect(into: promise)
    return promise.futureResult
}

Installation

To use the SwiftkubeModel in a SwiftPM project, add the following line to the dependencies in your Package.swift file:

.package(name: "SwiftkubeClient", url: "https://github.com/swiftkube/client.git", from: "0.9.0"),

then include it as a dependency in your target:

import PackageDescription

let package = Package(
    // ...
    dependencies: [
        .package(name: "SwiftkubeClient", url: "https://github.com/swiftkube/client.git", from: "0.9.0")
    ],
    targets: [
        .target(name: "<your-target>", dependencies: [
            .product(name: "SwiftkubeClient", package: "SwiftkubeClient"),
        ])
    ]
)

Then run swift build.

License

Swiftkube project is licensed under version 2.0 of the Apache License. See LICENSE for more details.

Comments
  • Add option to retrieve logs without watching

    Add option to retrieve logs without watching

    This adds a parallel way to get logs other than the current follow logs option. It uses the same path to query the api but without the follow=true option This returns the logs as plane text so a number of functions have been duplicated to handle this

    opened by thomashorrobin 6
  • Add LocalFileConfigLoader

    Add LocalFileConfigLoader

    Hi, I need a function like this so that my application can load user selected files

    • Why not just build the extension in your own app? AuthInfo.authentication and NamedCluster.trustRoots are both private functions

    • Why would anyone need this, it seems like an objectively worse way of loading a client. Issues to do with the Sandbox, mainly. But also, it is useful to be able to open a config directly.

    I don't have a lot of experience with Swift, so I may have done this all wrong. Feel free to set me straight if my approach is wrong.

    opened by thomashorrobin 5
  • fix: typo in property name for storage V1 api group

    fix: typo in property name for storage V1 api group

    Hello 👋

    First of all great work. It's my first time using the lib and i found it with a very amusing interface 😍

    I just found out a typo in the the property to access the storage and i thought i could contribute with this dummy fix and thank you for this.

    So feel free to deny this simple PR, the main idea was to thank you for your work 🙇

    Please let me know if i can help you with something 🙏 I use to be an iOS developer for several years, always enjoying backend and since things like PerfectSwift, Vapor and Kitura(no longer with us) appeared i decide to move back to backend and trying to push the usage of Swift on it, so i'm glad to help in what i can 😊

    Cheers

    opened by portellaa 3
  • Don't use deinit to shutdown http client

    Don't use deinit to shutdown http client

    Shutting down the HTTP client in deinit might be problematic. I think, it is usually better to make this explicit by exposing the shutdown/syncShutdown methods directly on the KubernetesClient.

    For example, if you were using the KubernetesClient in a NIO app and you happened to deinit an instance of the client on an event loop thread, you would be blocking this event loop which is verboten.

    For example:

    let eventLoop = elg.next()
            
    let deployments : EventLoopFuture<apps.v1.DeploymentList> = eventLoop.flatSubmit {
        let client = KubernetesClient(provider: .shared(elg), logger: nil)!
        return client.appsV1.deployments.list()
    }
    
    print(try deployments.wait())
    

    This hits a precondition error because the deinit and thus the syncShutdown of the client instance happens on the event loop thread.

    Fatal error: BUG DETECTED: syncShutdown() must not be called when on an EventLoop.
    Calling syncShutdown() on any EventLoop can lead to deadlocks.
    Current eventLoop: SelectableEventLoop { selector = Selector { descriptor = 3 }, thread = NIOThread(name = NIO-ELT-0-#0) }: file AsyncHTTPClient/HTTPClient.swift, line 138
    2021-01-09 22:32:06.490788+0100 [50257:6763987] Fatal error: BUG DETECTED: syncShutdown() must not be called when on an EventLoop.
    Calling syncShutdown() on any EventLoop can lead to deadlocks.
    Current eventLoop: SelectableEventLoop { selector = Selector { descriptor = 3 }, thread = NIOThread(name = NIO-ELT-0-#0) }: file AsyncHTTPClient/HTTPClient.swift, line 138
    
    enhancement help wanted 
    opened by t089 3
  • Missing support for `continue` token on list operations

    Missing support for `continue` token on list operations

    When doing a list operation the API server may return an opaque continue token in metadata.continue. I couldn't find it, but is there API to the use this token to fetch next batch of results for the list?

    enhancement 
    opened by t089 2
  • KubernetesClient can't create x509 authentication from local kubeconfig's certificate data and key

    KubernetesClient can't create x509 authentication from local kubeconfig's certificate data and key

    I am trying to use this package with a local Kind cluster

    Initially I tried this

    let client = KubernetesClient()
    
    let deployments = try client?.appsV1.deployments.list(in:.allNamespaces).wait()
    deployments?.forEach { print($0) }
    

    I expected to see each deployment printed out. However, there was no output to the console.

    I then tried passing in a Logger..

    import SwiftkubeClient
    import Logging
    
    let logger = Logger(label: "com.example.swift.k8s.demo")
    
    let client = KubernetesClient(logger: logger)
    
    let deployments = try client?.appsV1.deployments.list(in:.allNamespaces).wait()
    deployments?.forEach { print($0) }
    

    With this I get some output

    2020-11-25T21:16:18-0600 warning com.example.swift.k8s.demo : Skipping service account kubeconfig because either KUBERNETES_SERVICE_HOST or KUBERNETES_SERVICE_PORT is not set
    

    I then set those environment variables and get this output

    2020-11-25T21:23:41-0600 warning com.example.swift.k8s.demo : Did not find service account token at /var/run/secrets/kubernetes.io/serviceaccount/token
    

    I guess this is a long winded way of saying, how can I get the KubernetesClient to use my local .kube/config? What am I doing wrong? Has anyone tried using Kind with this project? I think the only way for this to work is to have it run in a pod?

    bug 
    opened by spprichard 2
  • 'No route to host' on iOS16 when connect to lan kube cluster

    'No route to host' on iOS16 when connect to lan kube cluster

    Hey, awesome project!

    'No route to host' on iOS16 when connect to lan kube cluster

    What i miss? I add Privacy - Local Network Usage Description on my info, but already crash at real device.

    BTW, simulator is good.

    opened by buhe 1
  • fixes bug when trying to fetch logs without following

    fixes bug when trying to fetch logs without following

    After some investigation it turns out that sending follow=true in the query of any request to the Kubernetes API changes the behaviour of the response significantly. So it's critical that it is not sent if the request is not intended to stream the result. I've modified the code so we can easily distinguish between a "dump" of the logs and a stream of the logs

    opened by thomashorrobin 1
  • Explicit dependency on NIO

    Explicit dependency on NIO

    Motivation

    When compiling with Swift 5.5 on linux I get the following errors

    $ docker run -it --rm -v (pwd):/app -w /app  swift:5.5.2-focal swift build -c release --static-swift-stdlib
    /app/.build/checkouts/client/Sources/SwiftkubeClient/Client/GenericKubernetesClient.swift:335:14: error: no exact matches in call to initializer 
                    let data = Data(buffer: byteBuffer)
                               ^
    /app/.build/checkouts/client/Sources/SwiftkubeClient/Client/GenericKubernetesClient.swift:335:14: note: found candidate with type '(UnsafeBufferPointer<_>) -> Data'
                    let data = Data(buffer: byteBuffer)
                               ^
    /app/.build/checkouts/client/Sources/SwiftkubeClient/Client/GenericKubernetesClient.swift:335:14: note: found candidate with type '(UnsafeMutableBufferPointer<_>) -> Data'
                    let data = Data(buffer: byteBuffer)
                               ^
    /app/.build/checkouts/client/Sources/SwiftkubeClient/Discovery/KubernetesClient+Discovery.swift:153:14: error: no exact matches in call to initializer 
                    let data = Data(buffer: byteBuffer)
                               ^
    /app/.build/checkouts/client/Sources/SwiftkubeClient/Discovery/KubernetesClient+Discovery.swift:153:14: note: found candidate with type '(UnsafeBufferPointer<_>) -> Data'
                    let data = Data(buffer: byteBuffer)
                               ^
    /app/.build/checkouts/client/Sources/SwiftkubeClient/Discovery/KubernetesClient+Discovery.swift:153:14: note: found candidate with type '(UnsafeMutableBufferPointer<_>) -> Data'
                    let data = Data(buffer: byteBuffer)
                               ^
    /app/.build/checkouts/client/Sources/SwiftkubeClient/Watch/StreamingDelegate.swift:74:31: error: value of type 'ByteBuffer' has no member 'readData'
                            let data = streamingBuffer.readData(length: readableLine + 1)
    

    In StreamingDelegate.swift we are importing and using methods from NIO and we are using API from NIOFoundationCompat without explicitly importing this package.

    Neither NIO, nor NIOFoundationCompat are explicitly declared dependencies in Package.swift. Adding those fixes the compilation.

    Changes

    Add explicit dependency on NIO and NIOFoundationCompat.

    Result

    Compilation completes successfully on linux with Swift 5.5.2.

    I remember vaguely that there was a recent change on how transitive dependencies are handled in Swift but I could not find any reference anymore.

    opened by t089 1
  • Dependency on SwiftkubeModel is too loose

    Dependency on SwiftkubeModel is too loose

    It seems that minor versions of SwiftkubeModel are not backward compatible. For example settings has been removed from SwiftkubeModel 0.4.0, however it's used in SwiftkubeClient 0.9.0. So installing SwiftkubeClient 0.9.0 without manually pinning SwiftkubeModel to 0.3.x in the main project would cause the project failing to compile.

    So, I would recommend updating the dependency on SwiftkubeModel to upToNextMinor in Package.swift.

    bug 
    opened by allenhsu 1
  • Fix massive memory leak by breaking retain cycle

    Fix massive memory leak by breaking retain cycle

    Any instance of the GenericKubernetesClient is never deallocated because there is a retain cycle between the client and its jsonDecoder through the date decoding closure which references self. This causes massive memory leak, since everything the client creates, will never be freed from memory (most notably the underlying HTTPClient).

    My first idea was to use [unowned self] to break the retain cycle. But this is only safe if the decoder will never outlive the client instance. Since the decoder is a package internal property we cannot guarantee it. We could make it private, but then we might as well hide the whole date formatting internals. So, this PR just makes the date formatters owned only by the decoder. This breaks the retain cycle.

    Happy New Year ;)

    bug enhancement 
    opened by t089 1
  • Support yams > 5.0.0 as dependencies

    Support yams > 5.0.0 as dependencies

    In one of our projects we use yams as well as the beautiful swiftkube client, that we do really love. After updating to Yams.git from: "5.0.1" and client.git from: "0.11.0" the following error occur while package resolve

    Computing version for https://github.com/swiftkube/client.git
    error: Dependencies could not be resolved because root depends on 'yams' 5.0.1..<6.0.0 and root depends on 'client' 0.11.0..<1.0.0.
    'client' >= 0.11.0 practically depends on 'yams' 4.0.0..<5.0.0 because no versions of 'client' match the requirement 0.11.1..<1.0.0 and 'client' 0.11.0 depends on 'yams' 4.0.0..<5.0.0.
    

    Is it possible to update swiftkube to support the latest Yams version?

    opened by petershaw 3
  • Add configurable timeout for a HTTPClient

    Add configurable timeout for a HTTPClient

    In some large Kubernetes deployments various techniques may be applied to protect API:

    • throttling -> connection may take longer then default 1 second
    • large deployments -> read may require additional timeout tuning.

    Suggestion:

    • we can accept additional parameter HTTPClient.Configuration.Timeout

    Alternatives considered:

    • Accept full HTTPClient -> will make TLS configuration more complicated
    • Accept full HTTPClient.Configuation -> frankly not many parameters actually can be configured, so better to be focused and just accept Timeout as the most environment specific out of all other HTTPClient.Configuation parameters
    opened by octo47 3
  • adds suspend and unsuspend functions to Cronjob and implements PATCH

    adds suspend and unsuspend functions to Cronjob and implements PATCH

    This PR adds functions to make it easier and more reliable to update corncobs with Swiftkube.

    Using PATCH is important as it enables us to update resources without concern for copying and uploading the entire resource. Which I have found to be error prone and messy. Implementing PATCH makes this much easier

    @iabudiab as always, this may need some further work as I'm not as familiar with Swift as I'd like to be. And I'm not sure my implementation of PATCH is up to the standard it would need to be to be able to merged. So happy to rewrite if you have suggestions

    opened by thomashorrobin 3
  • Support to extend with custom models

    Support to extend with custom models

    I need to list all resources of

    apiVersion: cert-manager.io/v1
    kind: Certificate
    

    it there is any way to implement own Models to support crds? The code looks very extensable at the first look. Feature-Request is to have a documentation how to implement an extension to support cruds on custom resources.

    Will this be possible?

    opened by petershaw 2
Releases(0.11.0)
  • 0.11.0(Jun 13, 2022)

    New

    • Update to Kubernetes model v1.22.7
    • Add option to retrieve logs once without watching / streaming (#14) by @thomashorrobin
    • Add discovery API to load server resources
    • Use SwiftkubeModel v0.5.0
    • Refactor client to use GroupVersionResource instead of GroupVersionKind for resource type resolution
    • Support creating a parametrised generic client given a GroupVersionResource
    • Make GenericKubernetesClient extensions public
    • Update k3s docker image to k3s:v1.22.7-k3s1

    Fixes

    • Typo in property name for storage.v1 API Group (#11) by @portellaa
    • Add explicit dependency on NIO (#12) by @t089
    Source code(tar.gz)
    Source code(zip)
  • 0.10.0(Sep 4, 2021)

    New

    • Update to Kubernetes model v1.20.9
    • Add LocalFileConfigLoader for loading KubeConfigs from a local file given a URL #8 by @thomashorrobin
    • Add support for scale and status API
    • Setup CI with live K3d cluster and add several tests against it

    Bug Fixes

    • Add missing support for continue token in ListOption for retrieving subsequent list results #9
    • Track dependency on SwiftkubeModel up-to-next minor instead of major #10
    Source code(tar.gz)
    Source code(zip)
  • 0.9.0(May 10, 2021)

  • 0.8.0(Apr 11, 2021)

  • 0.7.0(Mar 15, 2021)

  • 0.6.1(Feb 11, 2021)

  • 0.6.0(Feb 11, 2021)

    New

    • Implement asynchronous shutdown
    • Implement reconnect handling for watch and follow API requests
    • Introduce ResourceWatcherDelegate and LogWatcherDelegate protocols

    API Changes

    • Changed signature of watch and follow APIs
    • Replace ResourceWatch and LogWatch with new protocols
    • The follow and watch functions return a cancellable SwiftkubeClientTask instance insteaf of HTTPClient.Task<Void>
    Source code(tar.gz)
    Source code(zip)
  • 0.5.0(Feb 1, 2021)

    New

    • Add metrics support for gathering request latencies and counts
    • Support ListOptions in watch call
    • Add watch and follow API that accept a RecourceWatch or LogWatch instance
    • Add an errorHandler closure to ResourceWatch and LogWatch
    • Make Selectors (NamespaceSelector, LabelSelector etc.) Hashable

    API Changes

    • Replace implicit client shutdown on deinit with explicit syncShutdow
    • Expose ResourceWatch and LogWatch classes for extension
    Source code(tar.gz)
    Source code(zip)
  • 0.4.0(Jan 9, 2021)

    New

    • Add SwiftFormat config and format code base accordingly
    • Add support for ReadOptions

    Bug Fixes

    • Fix massive memory leak by breaking retain cycle between the JSONDecoder and DateFormatters #4 by @t089
    Source code(tar.gz)
    Source code(zip)
  • 0.3.2(Dec 28, 2020)

  • 0.3.1(Dec 13, 2020)

    • Update to Kubernetes model v1.18.13
      • No model changes between 1.18.9 and 1.18.13. This release is to track the update explicitly via a version bump.
    Source code(tar.gz)
    Source code(zip)
  • 0.3.0(Nov 27, 2020)

  • 0.2.0(Nov 27, 2020)

    New

    • Add support for ListOptions
    • Add core.v1.Pod status read and update API

    Bug Fixes

    • KubernetesClient can't create x509 authentication from local kubeconfig's certificate data and key #1

    API Changes

    • Initializers of GenericKubernetesClients are no longer public
    • Function signature change:
      • from watch(in:watch:) throws -> EventLoopFuture<Void>
      • to watch(in:using:) throws -> HTTPClient.Task<Void>
    • Function signature change:
      • fromfollow(in:name:container:watch:) throws -> HTTPClient.Task<Void>
      • to follow(in:name:container:using:) throws -> HTTPClient.Task<Void>
    Source code(tar.gz)
    Source code(zip)
  • 0.1.0(Nov 15, 2020)

Owner
Swiftkube
Swift tooling for Kubernetes
Swiftkube
A Swift client for the OpenAI API.

OpenAI A Swift client for the OpenAI API. Requirements Swift 5.3+ An OpenAI API Key Example Usage Completions import OpenAI

Mattt 161 Dec 26, 2022
A (really) native and powerful macOS Telegram client built using SwiftUI, optimized for moderating large communities and personal use.

Moc A (really) native and powerful macOS Telegram client, optimized for moderating large communities and personal use. This client is currently in dev

GGorAA 84 Jan 2, 2023
Swift implementation of Github REST API v3

GitHubAPI Swift implementation of GitHub REST api v3. Library support Swift 4.2. Work is in progress. Currently supported: Issues API. Activity API(Fe

Serhii Londar 77 Jan 7, 2023
Google Directions API helper for iOS, written in Swift

PXGoogleDirections Google Directions API SDK for iOS, entirely written in Swift. ?? Features Supports all features from the Google Directions API as o

Romain L 268 Aug 18, 2022
👤 Framework to Generate Random Users - An Unofficial Swift SDK for randomuser.me

RandomUserSwift is an easy to use Swift framework that provides the ability to generate random users and their accompanying data for your Swift applic

Wilson Ding 95 Sep 9, 2022
Swift Reddit API Wrapper

reddift reddift is Swift Reddit API Wrapper framework, and includes a browser is developed using the framework. Supports OAuth2(is not supported on tv

sonson 236 Dec 28, 2022
Swifter - A Twitter framework for iOS & OS X written in Swift

Getting Started Installation If you're using Xcode 6 and above, Swifter can be installed by simply dragging the Swifter Xcode project into your own pr

Matt Donnelly 2.4k Dec 26, 2022
Instagram Private API Swift

SwiftyInsta Please notice SwiftyInsta may not be actively maintained at the moment of you reading this note. Refer to #244 for more info. Instagram of

Mahdi Makhdumi 218 Jan 5, 2023
SDK for creating Telegram Bots in Swift.

Chat • Changelog • Prerequisites • Getting started • Creating a new bot • Generating Xcode project • API overview • Debugging notes • Examples • Docum

Rapier 349 Dec 20, 2022
Telegram Bot Framework written in Swift 5.1 with SwiftNIO network framework

Telegrammer is open-source framework for Telegram Bots developers. It was built on top of Apple/SwiftNIO

Pataridze Givi 279 Jan 4, 2023
Swift Bot with Vapor for Telegram Bot Api

Telegram Vapor Bot Please support Swift Telegram Vapor Bot Lib development by giving a ⭐️ Telegram Bot based on Swift Vapor. Swift Server Side Communi

OleG. 104 Jan 6, 2023
Solana + RxSolana This is a open source library on pure swift for Solana protocol

The objective is to create a cross platform, fully functional, highly tested and less depencies as posible. The project is still at initial stage. Lots of changes chan happen to the exposed api.

Arturo Jamaica 138 Dec 15, 2022
Fetch Multiple Rest API using Swift 5.5 Async Await with Task, TaskGroup, Continuation API

Source code for Tutorial on experimenting with Swift Async Await to fetch multiple REST API endpoints and eliminate Pyramid of Doom callback hell to improve code readability and maintanability

Alfian Losari 14 Dec 7, 2022
QuoteKit is a Swift framework to use the free APIs provided by Quotable created by Luke Peavey.

QuoteKit The QuoteKit is a Swift framework to use the free APIs provided by Quotable created by Luke Peavey.

Rudrank Riyam 17 Jun 23, 2022
Swift library for the Twitter API v1 and v2

Swift library for the Twitter API v1 and v2

mironal 96 Dec 30, 2022
Swift iPhone and iPad Client for Polls API, using Hyperdrive API client

Polls Client This is a Swift iPhone and iPad client for the Polls API - a simple application allowing users to view polls and vote in them. Polls is a

Apiary 34 Jul 15, 2022
The Outline Client is a cross-platform VPN or proxy client for Windows, macOS, iOS, Android, and ChromeOS

Outline Client The Outline Client is a cross-platform VPN or proxy client for Windows, macOS, iOS, Android, and ChromeOS. The Outline Client is design

Jigsaw 7.3k Dec 31, 2022
Twitter-Client - A twitter client that allow users to view tweets on their iphone

Project 3 - Twitter Client Name of your app is a basic twitter app to read your

null 0 Feb 7, 2022
Wanikani-swift - Unofficial Swift client for the WaniKani API

WaniKani A Swift library and client for the WaniKani REST API. It currently supp

Aaron Sky 5 Oct 28, 2022
Instagram API client written in Swift

SwiftInstagram is a wrapper for the Instagram API written in Swift. It allows you to authenticate users and request data from Instagram effortlessly.

Ander Goig 580 Nov 25, 2022