Skip to content

Commit 7fcb43b

Browse files
committed
Overhaul implementation for new API and Swift 6 concurrency support
1 parent f878597 commit 7fcb43b

File tree

8 files changed

+320
-280
lines changed

8 files changed

+320
-280
lines changed

Package.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ let package = Package(
1515
],
1616
dependencies: [
1717
.package(url: "https://github.com/swiftkube/client.git", from: "0.21.0"),
18-
.package(url: "https://github.com/apple/swift-service-discovery.git", from: "1.3.0"),
19-
.package(url: "https://github.com/apple/swift-log.git", .upToNextMajor(from: "1.6.2")),
18+
.package(url: "https://github.com/apple/swift-service-discovery.git", from: "1.4.0"),
19+
.package(url: "https://github.com/apple/swift-log.git", from: "1.6.2"),
2020
],
2121
targets: [
2222
.target(

README.md

Lines changed: 81 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,47 @@
11
# Swiftkube:ServiceDiscovery
22

33
<p align="center">
4-
<img src="https://img.shields.io/badge/Swift-5.2-orange.svg" />
5-
<a href="https://v1-18.docs.kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/">
6-
<img src="https://img.shields.io/badge/Kubernetes-1.19.8-blue.svg" alt="Kubernetes 1.19.8"/>
4+
<a href="https://swiftpackageindex.com/swiftkube/client">
5+
<img src="https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fswiftkube%2Fservicediscovery%2Fbadge%3Ftype%3Dswift-versions"/>
76
</a>
8-
<img src="https://img.shields.io/badge/SwiftkubeClient-0.9.0-blue.svg" />
7+
<a href="https://swiftpackageindex.com/swiftkube/client">
8+
<img src="https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fswiftkube%2Fservicediscovery%2Fbadge%3Ftype%3Dplatforms"/>
9+
</a>
10+
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.32/">
11+
<img src="https://img.shields.io/badge/Kubernetes-1.32.0-blue.svg" alt="Kubernetes 1.32.0"/>
12+
</a>
13+
<img src="https://img.shields.io/badge/SwiftkubeClient-0.21.0-blue.svg" />
914
<a href="https://swift.org/package-manager">
1015
<img src="https://img.shields.io/badge/swiftpm-compatible-brightgreen.svg?style=flat" alt="Swift Package Manager" />
1116
</a>
12-
<img src="https://img.shields.io/badge/platforms-mac+linux-brightgreen.svg?style=flat" alt="Mac + Linux" />
1317
<a href="https://github.com/swiftkube/servicediscovery/actions">
1418
<img src="https://github.com/swiftkube/servicediscovery/workflows/swiftkube-servicediscovery-ci/badge.svg" alt="CI Status">
1519
</a>
1620
</p>
1721

18-
An implementation of the [Swift Service Discovery API](https://github.com/apple/swift-service-discovery) for Kubernetes based on [SwiftkubeClient](https://github.com/swiftkube/client).
22+
An implementation of the [Swift Service Discovery API](https://github.com/apple/swift-service-discovery) for
23+
Kubernetes based on [SwiftkubeClient](https://github.com/swiftkube/client).
1924

2025
## Table of contents
2126

2227
* [Overview](#overview)
2328
* [Usage](#usage)
29+
* [Creating a service discovery](#creating-a-service-discovery)
30+
* [Configuration](#Configuration)
31+
* [Lookup resources](#lookup-resources)
32+
* [Subscribtions](#subscriptions)
33+
* [Custom Resources](#custom-resources)
34+
* [Strict Concurrency](#strict-concurrency)
2435
* [RBAC](#rbac)
2536
* [Installation](#installation)
2637
* [License](#license)
2738

2839
#Overview
2940

3041
- [x] Auto-configuration for different environments
31-
- [x] Support for all K8s `ListOptions`
42+
- [x] Support for all Kubernetes `ListOptions`
43+
- [x] Discovery for any listable Kubernetes resource
3244
- [x] Support for reconnect and retry
33-
- [x] Discovery for K8s Pod objects
34-
- [ ] Discovery for K8s Service objects
3545
- [ ] Complete documentation
3646
- [ ] End-to-end tests
3747

@@ -41,28 +51,50 @@ An implementation of the [Swift Service Discovery API](https://github.com/apple/
4151

4252
To use this service discovery import `SwiftkubeServiceDiscovery` and init an instance.
4353

54+
`SwiftkubeServiceDiscovery` is generic. Thus, instances must be specialized and are therefore bound to
55+
a specific `KubernetesResouce` type and its `GroupVersionResource`.
56+
4457
```swift
4558
import SwiftkubeServiceDiscovery
4659

47-
let discovery = KubernetesServiceDiscovery()
60+
let podDiscovery = SwiftkubeServiceDiscovery<core.v1.Pod>()
61+
let serviceDiscovery = SwiftkubeServiceDiscovery<core.v1.Service>()
4862
```
4963

50-
Underneath, `SwiftkubeServiceDiscovery` uses `SwiftkubeClient` for all Kubernets communication, which configures itself automatically for the environement it runs in.
64+
Underneath, `SwiftkubeServiceDiscovery` uses `SwiftkubeClient` for all Kubernetes communication, which configures
65+
itself automatically for the environment it runs in.
5166

52-
You can also pass an existing client instance to the service discovery:
67+
However, you can also pass an existing client instance to the service discovery:
5368

5469
```swift
55-
let client = KubernetesClient()
56-
let discovery = KubernetesServiceDiscovery(client: client)
70+
let config = KubernetesClientConfig(
71+
masterURL: "https://kubernetesmaster",
72+
namespace: "default",
73+
authentication: authentication,
74+
trustRoots: NIOSSLTrustRoots.certificates(caCert),
75+
insecureSkipTLSVerify: false,
76+
timeout: HTTPClient.Configuration.Timeout.init(connect: .seconds(1), read: .seconds(10)),
77+
redirectConfiguration: HTTPClient.Configuration.RedirectConfiguration.follow(max: 5, allowCycles: false)
78+
)
79+
let client = KubernetesClient(config: config)
80+
81+
let discovery = SwiftkubeServiceDiscovery<core.v1.Service>(client: client)
5782
```
5883

59-
You should shut down the `SwiftkubeServiceDiscovery ` instance, which in turn shuts down the underlying `SwiftkubeClient`. You can shutdown either in a synchronius way or asynchronously by providing a `DispatchQueue` for the completion callback.
84+
You should shut down the `SwiftkubeServiceDiscovery` instance when you're done using it, which in turn shuts down the
85+
underlying `SwiftkubeClient`. Thus, you shouldn't call `discovery.shutdown()` before all requests have finished.
86+
87+
You can also shut down the client asynchronously in an async/await context or by providing a `DispatchQueue` for the
88+
completion callback.
6089

6190
```swift
6291
// when finished close the client
6392
try discovery.syncShutdown()
6493

65-
// or asynchronously
94+
// async/await
95+
try await discovery.shutdown()
96+
97+
// DispatchQueue
6698
let queue: DispatchQueue = ...
6799
discovery.shutdown(queue: queue) { (error: Error?) in
68100
print(error)
@@ -71,11 +103,12 @@ discovery.shutdown(queue: queue) { (error: Error?) in
71103

72104
### Configuration
73105

74-
You can configure the service discovery by passing a `Configuration` instance.
106+
You can configure the service discovery by passing a `SwiftkubeDiscoveryConfiguration` instance.
75107

76-
`SwiftkubeServiceDiscovery` supports the following configuration options:
108+
Currently, the following configuration options are supported:
77109

78-
- `RetryStrategy`: A retry strategy to control the reconnect behaviour for the underlying client in case of non-recoverable errors when serving service discovery subsriptions.
110+
- `RetryStrategy`: A retry strategy to control the reconnect-behaviour for the underlying client in case of
111+
non-recoverable errors when serving service discovery subscriptions.
79112

80113
```swift
81114
let strategy = RetryStrategy(
@@ -86,17 +119,19 @@ let strategy = RetryStrategy(
86119
)
87120

88121
let config = Configuration(retryStrategy: strategy)
89-
90-
let discovery = KubernetesServiceDiscovery(config: config)
122+
let discovery = SwiftkubeServiceDiscovery<core.v1.Service>(config: config)
91123
```
92124

93-
### Service lookup
125+
### Lookup resources
94126

95-
To lookup Kubernetes "services" you have to pass an instance of `LookupObject`. You can specify the namespaces to search and provide a list of selectors to filter the desired objects.
127+
To lookup Kubernetes resources you have to pass an instance of `LookupObject`. You can specify the namespaces to
128+
search and provide a list of selectors to filter the desired objects.
96129

97-
`SwiftkubeServiceDiscovery` lookups return a list of `KubernetesPods` describing all of the matching pod objects that have an IP assigned.
130+
`SwiftkubeServiceDiscovery` lookups return a list of resources of the type specified by the generic specialization:
98131

99132
```swift
133+
let podDiscovery = SwiftkubeServiceDiscovery<core.v1.Pod>()
134+
100135
let object = LookupObject(
101136
namespace: .allNamespaces,
102137
options: [
@@ -110,25 +145,26 @@ discovery.lookup(object) { result in
110145
switch result {
111146
case let .success(pods):
112147
pods.forEach { pod in
113-
print("\(pod.name), \(pod.namespace): \(pod.ip)")
148+
print("\(pod.name), \(pod.namespace): \(pod.status?.podIP)")
114149
}
115150
case let .failure(error):
116151
// handle error
117152
}
118153
}
119154
```
120155

121-
### Service subsription
156+
### Subscribtions
122157

123158
You can subscribe to service lookups the same way, by providing a `LookupObject`:
124159

125-
126160
```swift
161+
let serviceDiscovery = SwiftkubeServiceDiscovery<core.v1.Service>()
162+
127163
let token = discovery.subscribe(to: object) { result in
128164
switch result {
129-
case let .success(pods):
165+
case let .success(service):
130166
pods.forEach {
131-
print("\(pod.name), \(pod.namespace): \(pod.ip)")
167+
print("\(service.name), \(service.namespace): \(service.spec?.ports)")
132168
}
133169
case let .failure(error):
134170
print(error)
@@ -140,18 +176,27 @@ let token = discovery.subscribe(to: object) { result in
140176
token.cancel()
141177
```
142178

143-
The client will try to reconnect to the API server according to the configured `RetryStrategy` and will serve updates until the subsription token is cancelled.
179+
The client will try to reconnect to the API server according to the configured `RetryStrategy` and will serve updates
180+
until the subscription token is cancelled.
181+
182+
### Custom Resources
183+
184+
TBD
185+
186+
## Strict Concurrency
187+
188+
TBD
144189

145190
## RBAC
146191

147192
TBD
148193

149194
## Installation
150195

151-
To use the `SwiftkubeModel` in a SwiftPM project, add the following line to the dependencies in your `Package.swift` file:
196+
To use the `SwiftkubeServiceDiscovery` in a SwiftPM project, add the following line to the dependencies in your `Package.swift` file:
152197

153198
```swift
154-
.package(name: "SwiftkubeServiceDiscovery", url: "https://github.com/swiftkube/servicediscovery.git", from: "0.1.0"),
199+
.package(name: "SwiftkubeServiceDiscovery", url: "https://github.com/swiftkube/servicediscovery.git", from: "0.3.0")
155200
```
156201

157202
then include it as a dependency in your target:
@@ -162,11 +207,11 @@ import PackageDescription
162207
let package = Package(
163208
// ...
164209
dependencies: [
165-
.package(name: "SwiftkubeServiceDiscovery", url: "https://github.com/swiftkube/servicediscovery.git", from: "0.1.0")
210+
.package(name: "SwiftkubeServiceDiscovery", url: "https://github.com/swiftkube/servicediscovery.git", from: "0.3.0")
166211
],
167212
targets: [
168213
.target(name: "<your-target>", dependencies: [
169-
.product(name: "SwiftkubeServiceDiscovery", package: "SwiftkubeServiceDiscovery"),
214+
.product(name: "SwiftkubeServiceDiscovery", package: "servicediscovery"),
170215
])
171216
]
172217
)
@@ -176,4 +221,5 @@ Then run `swift build`.
176221

177222
## License
178223

179-
Swiftkube project is licensed under version 2.0 of the [Apache License](https://www.apache.org/licenses/LICENSE-2.0). See [LICENSE](./LICENSE) for more details.
224+
Swiftkube project is licensed under version 2.0 of the [Apache License](https://www.apache.org/licenses/LICENSE-2.0).
225+
See [LICENSE](./LICENSE) for more details.
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//
2-
// Copyright 2020 Swiftkube Project
2+
// Copyright 2025 Swiftkube Project
33
//
44
// Licensed under the Apache License, Version 2.0 (the "License");
55
// you may not use this file except in compliance with the License.
@@ -14,26 +14,30 @@
1414
// limitations under the License.
1515
//
1616

17-
import Foundation
18-
import ServiceDiscovery
19-
import SwiftkubeClient
2017
import SwiftkubeModel
18+
import SwiftkubeClient
2119

22-
// MARK: - ServiceDiscoveryBox
20+
// MARK: - LookupObject
2321

24-
public extension ServiceDiscoveryBox where Service == LookupObject, Instance == KubernetesPod {
22+
/// Specifies the objects to lookup in the cluster.
23+
public struct LookupObject: Hashable, Sendable {
2524

26-
func shutdown(queue: DispatchQueue, _ callback: @escaping (Error?) -> Void) {
27-
guard let serviceDiscovery = try? unwrapAs(KubernetesServiceDiscovery.self) else {
28-
return
29-
}
30-
serviceDiscovery.shutdown(queue: queue, callback)
31-
}
25+
/// The target GroupVersionResource
26+
public let gvr: GroupVersionResource?
27+
28+
/// The namespace to search for objects.
29+
public let namespace: NamespaceSelector?
30+
31+
/// List options to filter the desired objects.
32+
public let options: [ListOption]?
3233

33-
func syncShutdown() throws {
34-
guard let serviceDiscovery = try? unwrapAs(KubernetesServiceDiscovery.self) else {
35-
return
36-
}
37-
try serviceDiscovery.syncShutdown()
34+
public init(
35+
gvr: GroupVersionResource? = nil,
36+
namespace: NamespaceSelector? = nil,
37+
options: [ListOption]? = nil
38+
) {
39+
self.gvr = gvr
40+
self.namespace = namespace
41+
self.options = options
3842
}
3943
}

Sources/SwiftkubeServiceDiscovery/ServiceDiscoveryDelegate.swift

Lines changed: 0 additions & 62 deletions
This file was deleted.

0 commit comments

Comments
 (0)