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.18.9
- ☑ Automatic configuration discovery
- ☑ DSL style API
- ☑ Highest API version for the most common API Groups
- ☐ Cover 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 - ☐ Better resource watch support
- ☐ Better CRD support
- ☐ Controller/Informer support
- ☐ Swift Metrics
- ☐ Complete documentation
- ☐ End-to-end tests
Compatibility Matrix
K8s <1.18.9 | K8s 1.18.9 - 1.18.13 | |
---|---|---|
SwiftkubeClient 0.3.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()
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 returnEventLoopFutures
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
:warning: Watching a resource opens a persistent connection until the client is closed.
let task: HTTPClient.Task<Void> = client.pods.watch(in: .namespace("default")) { (event, pod) in
print("\(event): \(pod)")
}
// The task can be cancelled later to stop watching
task.cancel()
Follow logs
:warning: Following a pod logs opens a persistent connection until the client is closed.
let task: HTTPClient.Task<Void> = client.pods.follow(in: .namespace("default"), name: "nginx") { (line) in
print(line)
}
// The task can be cancelled later o stop following
task.cancel()
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
instanceKubernetesAPIResource
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")
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.4.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.4.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.
Github
link |
Stars: 39 |
Related Packages
You may find interesting
Releases
SwiftkubeClient v0.4.0 - 2021-01-09T21:21:41
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
andDateFormatters
#4 by @t089
SwiftkubeClient v0.3.2 - 2020-12-28T14:56:17
- Change personal copyright to Swiftkube Project
- Make
KubernetesClientConfig
initializer public #3
SwitkubeClient v0.3.1 - 2020-12-13T11:56:22
- 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.
SwiftkubeClient v0.3.0 - 2020-11-27T23:03:48
New
- Add support for
DeleteOptions
Bug Fixes
- Can not create resources because of "Resource
metadata.name
must be set" error #2
SwiftkubeClient v0.2.0 - 2020-11-27T00:17:15
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>
- from
- Function signature change:
- from
follow(in:name:container:watch:) throws -> HTTPClient.Task<Void>
- to
follow(in:name:container:using:) throws -> HTTPClient.Task<Void>
- from
SwiftkubeClient v0.1.0 - 2020-11-15T18:09:15
Initial release of Swiftkube:Client.
See README for details