diff --git a/Sources/SwiftkubeClient/Config/KubernetesClientConfig.swift b/Sources/SwiftkubeClient/Config/KubernetesClientConfig.swift index 73b1fa1..cbd0a41 100644 --- a/Sources/SwiftkubeClient/Config/KubernetesClientConfig.swift +++ b/Sources/SwiftkubeClient/Config/KubernetesClientConfig.swift @@ -114,6 +114,30 @@ public extension KubernetesClientConfig { return try? URLConfigLoader(url: url).load(timeout: timeout, redirectConfiguration: redirectConfiguration, logger: logger) } + + /// Initializes a client configuration from a given String. + /// + /// It is also possible to override the default values for the underlying `HTTPClient` timeout and redirect config. + /// + /// - Parameters: + /// - string: The string to load the configuration from. + /// - timeout: The desired timeout configuration to apply. If not provided, then `connect` timeout will + /// default to 10 seconds. + /// - redirectConfiguration: Specifies redirect processing settings. If not provided, then it will default + /// to a maximum of 5 follows w/o cycles. + /// - logger: The logger to use for the underlying configuration loaders. + /// - Returns: An instance of KubernetesClientConfig for the Swiftkube KubernetesClient + static func createFromString( + fromString string: String, + timeout: HTTPClient.Configuration.Timeout? = nil, + redirectConfiguration: HTTPClient.Configuration.RedirectConfiguration? = nil, + logger: Logger = SwiftkubeClient.loggingDisabled + ) -> KubernetesClientConfig? { + let timeout = timeout ?? .init() + let redirectConfiguration = redirectConfiguration ?? .follow(max: 5, allowCycles: false) + + return try? StringConfigLoader(contents: string).load(timeout: timeout, redirectConfiguration: redirectConfiguration, logger: logger) + } } // MARK: - KubernetesClientConfigLoader @@ -133,6 +157,59 @@ extension KubernetesClientConfigLoader { } } +// MARK: - StringConfigLoader + +internal struct StringConfigLoader: KubernetesClientConfigLoader { + + let contents: String + + internal func load( + timeout: HTTPClient.Configuration.Timeout, + redirectConfiguration: HTTPClient.Configuration.RedirectConfiguration, + logger: Logger? + ) throws -> KubernetesClientConfig? { + let decoder = YAMLDecoder() + + guard let kubeConfig = try? decoder.decode(KubeConfig.self, from: contents) else { + return nil + } + + guard let currentContext = kubeConfig.currentContext else { + return nil + } + + guard let context = kubeConfig.contexts?.filter({ $0.name == currentContext }).map(\.context).first else { + return nil + } + + guard let cluster = kubeConfig.clusters?.filter({ $0.name == context.cluster }).map(\.cluster).first else { + return nil + } + + guard let masterURL = URL(string: cluster.server) else { + return nil + } + + guard let authInfo = kubeConfig.users?.filter({ $0.name == context.user }).map(\.authInfo).first else { + return nil + } + + guard let authentication = authInfo.authentication(logger: logger) else { + return nil + } + + return KubernetesClientConfig( + masterURL: masterURL, + namespace: context.namespace ?? "default", + authentication: authentication, + trustRoots: cluster.trustRoots(logger: logger), + insecureSkipTLSVerify: cluster.insecureSkipTLSVerify ?? true, + timeout: timeout, + redirectConfiguration: redirectConfiguration + ) + } +} + // MARK: - URLConfigLoader internal struct URLConfigLoader: KubernetesClientConfigLoader {