Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 19 additions & 50 deletions Sources/SwiftkubeClient/Client/KubernetesClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -104,56 +104,6 @@ public actor KubernetesClient {
}()
#endif

/// Create a new instance of the Kubernetes client.
///
/// The client tries to resolve a `kube config` automatically from different sources in the following order:
///
/// - A Kube config file at path of environment variable `KUBECONFIG` (if set)
/// - A 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.
///
/// Returns `nil` if a configuration can't be found.
///
/// - Parameters:
/// - provider: A ``EventLoopGroupProvider`` to specify how ``EventLoopGroup`` will be created.
/// - logger: The logger to use for this client.
public init?(
provider: HTTPClient.EventLoopGroupProvider = .shared(MultiThreadedEventLoopGroup(numberOfThreads: 1)),
logger: Logger? = nil
) {
let logger = logger ?? SwiftkubeClient.loggingDisabled

guard
let config = KubernetesClientConfig.initialize(logger: logger)
else {
return nil
}

self.init(config: config, provider: provider, logger: logger)
}

/// Create a new instance of the Kubernetes client.
///
/// - Parameters:
/// - url: The url to load the configuration from for this client instance. It can be a local file or remote URL.
/// - provider: A ``EventLoopGroupProvider`` to specify how ``EventLoopGroup`` will be created.
/// - logger: The logger to use for this client.
public init?(
fromURL url: URL,
provider: HTTPClient.EventLoopGroupProvider = .shared(MultiThreadedEventLoopGroup(numberOfThreads: 1)),
logger: Logger? = nil
) {
let logger = logger ?? SwiftkubeClient.loggingDisabled

guard
let config = KubernetesClientConfig.create(fromUrl: url, logger: logger)
else {
return nil
}

self.init(config: config, provider: provider, logger: logger)
}

/// Create a new instance of the Kubernetes client.
///
/// - Parameters:
Expand Down Expand Up @@ -216,6 +166,25 @@ public actor KubernetesClient {
)
}

public static func forContext(
context: String,
provider: HTTPClient.EventLoopGroupProvider = .shared(MultiThreadedEventLoopGroup(numberOfThreads: 1)),
logger: Logger? = nil
) throws -> KubernetesClient? {
try KubeConfig.fromLocalEnvironment()
.flatMap { try KubernetesClientConfig.from(kubeConfig: $0, context: context, logger: logger) }
.map { KubernetesClient(config: $0) }
}

public static func forCurrentContext(
provider: HTTPClient.EventLoopGroupProvider = .shared(MultiThreadedEventLoopGroup(numberOfThreads: 1)),
logger: Logger? = nil
) throws -> KubernetesClient? {
try KubeConfig.fromLocalEnvironment()
.flatMap { try KubernetesClientConfig.from(kubeConfig: $0, logger: logger) }
.map { KubernetesClient(config: $0) }
}

/// Shuts down the client gracefully.
///
/// This function uses a completion instead of an EventLoopFuture, because the underlying event loop will be closed
Expand Down
32 changes: 32 additions & 0 deletions Sources/SwiftkubeClient/Config/KubeConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
//

import Foundation
import Logging
import NIOSSL
import Yams

// MARK: - KubeConfig

Expand Down Expand Up @@ -49,6 +52,35 @@ public struct KubeConfig: Codable, Sendable {
public var currentContext: String?
}

public extension KubeConfig {

static func from(config: String) throws -> KubeConfig {
let decoder = YAMLDecoder()

return try decoder.decode(KubeConfig.self, from: config)
}

static func from(url: URL) throws -> KubeConfig {
let contents = try String(contentsOf: url, encoding: .utf8)

return try from(config: contents)
}

static func fromLocalEnvironment(envVar: String = "KUBECONFIG", logger: Logger? = nil) throws -> KubeConfig? {
let kubeConfigURL: URL? = ProcessInfo.processInfo.environment[envVar].map { URL(fileURLWithPath: $0) } ?? ProcessInfo.processInfo.environment["HOME"].map { URL(fileURLWithPath: $0 + "/.kube/config") }

guard let kubeConfigURL else {
logger?.warning(
"Skipping local kubeconfig loading, neither environment variable KUBECONFIG nor HOME are set."
)
return nil
}
logger?.info("Loading configuration from \(kubeConfigURL)")

return try from(url: kubeConfigURL)
}
}

// MARK: - Cluster

/// Cluster contains information about how to communicate with a kubernetes cluster.
Expand Down
Loading