diff --git a/src/Exceptions/KubeConfigFileNotFound.php b/src/Exceptions/KubeConfigFileNotFound.php deleted file mode 100644 index ba114ef0..00000000 --- a/src/Exceptions/KubeConfigFileNotFound.php +++ /dev/null @@ -1,10 +0,0 @@ - - */ -class KubeConfigFileNotFound extends PhpK8sException -{ -} diff --git a/src/Traits/Cluster/LoadsFromKubeConfig.php b/src/Traits/Cluster/LoadsFromKubeConfig.php index 9a2c0184..d43d72ed 100644 --- a/src/Traits/Cluster/LoadsFromKubeConfig.php +++ b/src/Traits/Cluster/LoadsFromKubeConfig.php @@ -6,10 +6,8 @@ use Illuminate\Support\Arr; use RenokiCo\PhpK8s\Exceptions\KubeConfigClusterNotFound; use RenokiCo\PhpK8s\Exceptions\KubeConfigContextNotFound; -use RenokiCo\PhpK8s\Exceptions\KubeConfigFileNotFound; use RenokiCo\PhpK8s\Exceptions\KubeConfigUserNotFound; use RenokiCo\PhpK8s\Kinds\K8sResource; -use RenokiCo\PhpK8s\KubernetesCluster; trait LoadsFromKubeConfig { @@ -34,56 +32,41 @@ public static function setTempFolder(string $tempFolder) } /** - * Creates a KubernetesCluster instance according to the current environment. + * Loads the configuration fro the KubernetesCluster instance + * according to the current KUBECONFIG environment variable. * - * This method implements the same connection algorithm as kubectl. - * First, it will read the KUBECONFIG environment variable and merge the referenced YAML files. - * If KUBECONFIG isn't set, the method will try to load $HOME/.kube/config. - * - * The current context will be used unless a context name is explicitly passed as parameter of this method. - * - * @see https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/ - * @see https://github.com/kubernetes/client-go/blob/f6ce18ae578c8cca64d14ab9687824d9e1305a67/tools/clientcmd/loader.go#L139 - * - * @return LoadsFromKubeConfig - * @throws KubeConfigClusterNotFound - * @throws KubeConfigContextNotFound - * @throws KubeConfigFileNotFound - * @throws KubeConfigUserNotFound + * @param string|null $context + * @return $this + * @throws \RenokiCo\PhpK8s\Exceptions\KubeConfigClusterNotFound + * @throws \RenokiCo\PhpK8s\Exceptions\KubeConfigContextNotFound + * @throws \RenokiCo\PhpK8s\Exceptions\KubeConfigUserNotFound */ - public static function create(?string $currentContext = null): KubernetesCluster + public function fromKubeConfigVariable(string $context = null) { - if (isset($_SERVER['KUBECONFIG'])) { - $paths = array_unique(explode(':', $_SERVER['KUBECONFIG'])); - } else { - $paths = [($_SERVER['HOME'] ?? '').'/.kube/config']; + if (! isset($_SERVER['KUBECONFIG'])) { + return $this; } + $paths = array_unique(explode(':', $_SERVER['KUBECONFIG'])); $kubeconfig = []; + foreach ($paths as $path) { - if ('' === $path || ! @is_readable($path) || false === $yaml = yaml_parse_file($path)) { + if (! @is_readable($path) || ($yaml = yaml_parse_file($path)) === false) { continue; } - $kubeconfig = self::mergeKubeconfig($kubeconfig, $yaml); + $kubeconfig = static::mergeKubeconfigContents($kubeconfig, $yaml); } - if ([] === $kubeconfig) { - throw new KubeConfigFileNotFound(sprintf('Kubernetes configuration not found (paths: "%s")', implode('", "', $paths))); + if ($kubeconfig === []) { + return $this; } - if (null === $currentContext && isset($kubeconfig['current-context'])) { - $currentContext = $kubeconfig['current-context']; + if (! $context && isset($kubeconfig['current-context'])) { + $context = $kubeconfig['current-context']; } - if (null === $currentContext) { - throw new KubeConfigContextNotFound('Kubernetes context not set.'); - } - - $cluster = new KubernetesCluster(''); - $cluster->loadKubeConfigFromArray($kubeconfig, $currentContext); - - return $cluster; + $this->loadKubeConfigFromArray($kubeconfig, $context); } /** @@ -211,21 +194,29 @@ protected function writeTempFileForContext(string $context, string $fileName, st return $tempFilePath; } - private static function mergeKubeconfig(array $a1, array $a2): array + /** + * Merge the two kubeconfig contents. + * + * @param array $kubeconfig1 + * @param array $kubeconfig2 + * @return array + */ + protected static function mergeKubeconfigContents(array $kubeconfig1, array $kubeconfig2): array { - $a1 += $a2; - foreach ($a1 as $key => $value) { + $kubeconfig1 += $kubeconfig2; + + foreach ($kubeconfig1 as $key => $value) { if ( is_array($value) && - isset($a2[$key]) && - is_array($a2[$key]) && + isset($kubeconfig2[$key]) && + is_array($kubeconfig2[$key]) && ! Arr::isAssoc($value) && - ! Arr::isAssoc($a2[$key]) + ! Arr::isAssoc($kubeconfig2[$key]) ) { - $a1[$key] = array_merge($a1[$key], $a2[$key]); + $kubeconfig1[$key] = array_merge($kubeconfig1[$key], $kubeconfig2[$key]); } } - return $a1; + return $kubeconfig1; } } diff --git a/tests/KubeConfigTest.php b/tests/KubeConfigTest.php index 91db42dc..6988fcf0 100644 --- a/tests/KubeConfigTest.php +++ b/tests/KubeConfigTest.php @@ -4,7 +4,6 @@ use RenokiCo\PhpK8s\Exceptions\KubeConfigClusterNotFound; use RenokiCo\PhpK8s\Exceptions\KubeConfigContextNotFound; -use RenokiCo\PhpK8s\Exceptions\KubeConfigFileNotFound; use RenokiCo\PhpK8s\Exceptions\KubeConfigUserNotFound; use RenokiCo\PhpK8s\Kinds\K8sResource; use RenokiCo\PhpK8s\KubernetesCluster; @@ -200,36 +199,23 @@ public function test_in_cluster_config() } /** - * @dataProvider contextProvider + * @dataProvider environmentVariableContextProvider */ - public function test_from_environment_variable(?string $context, string $domain) + public function test_from_environment_variable(string $context = null, string $expectedDomain) { $_SERVER['KUBECONFIG'] = __DIR__.'/cluster/kubeconfig.yaml::'.__DIR__.'/cluster/kubeconfig-2.yaml'; - $cluster = KubernetesCluster::create($context); - $this->assertSame("https://$domain:8443/?", $cluster->getCallableUrl('/', [])); + $cluster = new KubernetesCluster("https://{$expectedDomain}:8443"); + + $cluster->fromKubeConfigVariable($context); + + $this->assertSame("https://{$expectedDomain}:8443/?", $cluster->getCallableUrl('/', [])); } - public function contextProvider(): iterable + public function environmentVariableContextProvider(): iterable { yield [null, 'minikube']; yield ['minikube-2', 'minikube-2']; yield ['minikube-3', 'minikube-3']; } - - public function test_from_environment_variable_file_not_found() - { - $this->expectException(KubeConfigFileNotFound::class); - - $_SERVER['KUBECONFIG'] = '/notfound'; - KubernetesCluster::create(); - } - - public function test_from_environment_variable_context_not_set() - { - $this->expectException(KubeConfigContextNotFound::class); - - $_SERVER['KUBECONFIG'] = __DIR__.'/cluster/kubeconfig-2.yaml'; - KubernetesCluster::create(); - } }