Skip to content

Commit

Permalink
Add optional previous & timestamps flags to log requests (#35)
Browse files Browse the repository at this point in the history
* add `previous` & `timestamps` flags to log requests

* add tests for `previous` & `timestamps` flags on log requests

* add forgotten doc comments
  • Loading branch information
ewilken authored Sep 11, 2023
1 parent 34744d2 commit adca31d
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 12 deletions.
10 changes: 7 additions & 3 deletions Sources/SwiftkubeClient/Client/GenericKubernetesClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -257,13 +257,15 @@ internal extension GenericKubernetesClient {
/// - namespace: The namespace for this API request.
/// - name: The name of the pod.
/// - container: The name of the container.
/// - previous: Whether to request the logs of the previous instance of the container.
/// - timestamps: Whether to include timestamps on the log lines.
///
/// - Returns: The container logs as a single String.
/// - Throws: An error of type ``SwiftkubeClientError``.
func logs(in namespace: NamespaceSelector, name: String, container: String?) async throws -> String {
func logs(in namespace: NamespaceSelector, name: String, container: String?, previous: Bool = false, timestamps: Bool = false) async throws -> String {
let request = try makeRequest()
.in(namespace)
.toLogs(pod: name, container: container)
.toLogs(pod: name, container: container, previous: previous, timestamps: timestamps)
.subResource(.log)
.build()

Expand Down Expand Up @@ -421,16 +423,18 @@ public extension GenericKubernetesClient {
/// - namespace: The namespace for this API request.
/// - name: The name of the Pod.
/// - container: The name of the container.
/// - timestamps: Whether to include timestamps on the log lines.
/// - retryStrategy: An instance of a ``RetryStrategy`` configuration to use.
///
/// - Returns: A ``SwiftkubeClientTask`` instance, representing a streaming connection to the API server.
func follow(
in namespace: NamespaceSelector,
name: String,
container: String?,
timestamps: Bool = false,
retryStrategy: RetryStrategy = RetryStrategy.never
) throws -> SwiftkubeClientTask<String> {
let request = try makeRequest().in(namespace).toFollow(pod: name, container: container).build()
let request = try makeRequest().in(namespace).toFollow(pod: name, container: container, timestamps: timestamps).build()

return SwiftkubeClientTask(
client: httpClient,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,19 +63,22 @@ public extension NamespacedGenericKubernetesClient where Resource == core.v1.Pod
/// - namespace: The namespace for this API request.
/// - name: The name of the Pod.
/// - container: The name of the container.
/// - timestamps: Whether to include timestamps on the log lines.
/// - retryStrategy: An instance of a ``RetryStrategy`` configuration to use.
///
/// - Returns: A ``SwiftkubeClientTask`` instance, representing a streaming connection to the API server.
func follow(
in namespace: NamespaceSelector? = nil,
name: String,
container: String? = nil,
timestamps: Bool = false,
retryStrategy: RetryStrategy = RetryStrategy.never
) throws -> SwiftkubeClientTask<String> {
try super.follow(
in: namespace ?? .namespace(config.namespace),
name: name,
container: container,
timestamps: timestamps,
retryStrategy: retryStrategy
)
}
Expand All @@ -88,18 +91,24 @@ public extension NamespacedGenericKubernetesClient where Resource == core.v1.Pod
/// - namespace: The namespace for this API request.
/// - name: The name of the pod.
/// - container: The name of the container.
/// - previous: Whether to request the logs of the previous instance of the container.
/// - timestamps: Whether to include timestamps on the log lines.
///
/// - Returns: The container logs as a single String.
/// - Throws: An error of type ``SwiftkubeClientError``.
func logs(
in namespace: NamespaceSelector? = nil,
name: String,
container: String? = nil
container: String? = nil,
previous: Bool = false,
timestamps: Bool = false
) async throws -> String {
try await super.logs(
in: namespace ?? .namespace(config.namespace),
name: name,
container: container
container: container,
previous: previous,
timestamps: timestamps
)
}
}
21 changes: 17 additions & 4 deletions Sources/SwiftkubeClient/Client/RequestBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,11 @@ internal protocol NamespaceStep {
internal protocol MethodStep {
func toGet() -> GetStep
func toWatch() -> GetStep
func toFollow(pod: String, container: String?) -> GetStep
func toFollow(pod: String, container: String?, timestamps: Bool) -> GetStep
func toPost() -> PostStep
func toPut() -> PutStep
func toDelete() -> DeleteStep
func toLogs(pod: String, container: String?) -> GetStep
func toLogs(pod: String, container: String?, previous: Bool, timestamps: Bool) -> GetStep
}

// MARK: - GetStep
Expand Down Expand Up @@ -131,6 +131,8 @@ internal class RequestBuilder {
var deleteOptions: meta.v1.DeleteOptions?
var watchFlag = false
var followFlag = false
var previousFlag = false
var timestampsFlag = false

init(config: KubernetesClientConfig, gvr: GroupVersionResource) {
self.config = config
Expand Down Expand Up @@ -194,20 +196,23 @@ extension RequestBuilder: MethodStep {

/// Set request method to GET and notice the pod and container to follow for the pending request
/// - Returns:The builder instance as GetStep
func toFollow(pod: String, container: String?) -> GetStep {
func toFollow(pod: String, container: String?, timestamps: Bool = false) -> GetStep {
method = .GET
resourceName = pod
containerName = container
subResourceType = .log
followFlag = true
timestampsFlag = timestamps
return self as GetStep
}

func toLogs(pod: String, container: String?) -> GetStep {
func toLogs(pod: String, container: String?, previous: Bool = false, timestamps: Bool = false) -> GetStep {
method = .GET
resourceName = pod
containerName = container
subResourceType = .log
previousFlag = previous
timestampsFlag = timestamps
return self as GetStep
}
}
Expand Down Expand Up @@ -343,6 +348,14 @@ internal extension RequestBuilder {
add(queryItem: URLQueryItem(name: "follow", value: "true"))
}

if previousFlag {
add(queryItem: URLQueryItem(name: "previous", value: "true"))
}

if timestampsFlag {
add(queryItem: URLQueryItem(name: "timestamps", value: "true"))
}

if let container = containerName {
add(queryItem: URLQueryItem(name: "container", value: container))
}
Expand Down
30 changes: 27 additions & 3 deletions Tests/SwiftkubeClientTests/RequestBuilderTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,28 +76,52 @@ final class RequestBuilderTests: XCTestCase {

func testFollowInNamespace() {
let builder = RequestBuilder(config: config, gvr: gvr)
let request = try? builder.in(.system).toFollow(pod: "pod", container: "container").build()
let request = try? builder.in(.system).toFollow(pod: "pod", container: "container", timestamps: false).build()

XCTAssertEqual(request?.url, URL(string: "https://kubernetesmaster/api/v1/namespaces/kube-system/pods/pod/log?follow=true&container=container")!)
XCTAssertEqual(request?.method, HTTPMethod.GET)
}

func testFollowWithTimestampsInNamespace() {
let builder = RequestBuilder(config: config, gvr: gvr)
let request = try? builder.in(.system).toFollow(pod: "pod", container: "container", timestamps: true).build()

XCTAssertEqual(request?.url, URL(string: "https://kubernetesmaster/api/v1/namespaces/kube-system/pods/pod/log?follow=true&timestamps=true&container=container")!)
XCTAssertEqual(request?.method, HTTPMethod.GET)
}

func testLogsInNamespace() {
let builder = RequestBuilder(config: config, gvr: gvr)
let request = try? builder.in(.system).toLogs(pod: "pod", container: nil).build()
let request = try? builder.in(.system).toLogs(pod: "pod", container: nil, previous: false, timestamps: false).build()

XCTAssertEqual(request?.url, URL(string: "https://kubernetesmaster/api/v1/namespaces/kube-system/pods/pod/log")!)
XCTAssertEqual(request?.method, HTTPMethod.GET)
}

func testLogsWithContainerInNamespace() {
let builder = RequestBuilder(config: config, gvr: gvr)
let request = try? builder.in(.system).toLogs(pod: "pod", container: "container").build()
let request = try? builder.in(.system).toLogs(pod: "pod", container: "container", previous: false, timestamps: false).build()

XCTAssertEqual(request?.url, URL(string: "https://kubernetesmaster/api/v1/namespaces/kube-system/pods/pod/log?container=container")!)
XCTAssertEqual(request?.method, HTTPMethod.GET)
}

func testLogsWithPreviousInNamespace() {
let builder = RequestBuilder(config: config, gvr: gvr)
let request = try? builder.in(.system).toLogs(pod: "pod", container: nil, previous: true, timestamps: false).build()

XCTAssertEqual(request?.url, URL(string: "https://kubernetesmaster/api/v1/namespaces/kube-system/pods/pod/log?previous=true")!)
XCTAssertEqual(request?.method, HTTPMethod.GET)
}

func testLogsWithTimestampsInNamespace() {
let builder = RequestBuilder(config: config, gvr: gvr)
let request = try? builder.in(.system).toLogs(pod: "pod", container: nil, previous: false, timestamps: true).build()

XCTAssertEqual(request?.url, URL(string: "https://kubernetesmaster/api/v1/namespaces/kube-system/pods/pod/log?timestamps=true")!)
XCTAssertEqual(request?.method, HTTPMethod.GET)
}

func testGetWithListOptions_Eq() {
let builder = RequestBuilder(config: config, gvr: gvr)
let request = try? builder.in(.default).toGet().with(options: [
Expand Down

0 comments on commit adca31d

Please sign in to comment.