67 lines
1.7 KiB
Go
67 lines
1.7 KiB
Go
// Copyright 2021-2023 the Pinniped contributors. All Rights Reserved.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package clusterhost
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/client-go/kubernetes"
|
|
)
|
|
|
|
const (
|
|
labelNodeRolePrefix = "node-role.kubernetes.io/"
|
|
nodeLabelRole = "kubernetes.io/node-role"
|
|
controlPlaneNodeRole = "control-plane"
|
|
// This role was deprecated by Kubernetes 1.20.
|
|
// https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.20.md#urgent-upgrade-notes
|
|
// This role will be removed in Kubernetes 1.24
|
|
// https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.24.md#urgent-upgrade-notes
|
|
masterNodeRole = "master"
|
|
)
|
|
|
|
type ClusterHost struct {
|
|
client kubernetes.Interface
|
|
}
|
|
|
|
func New(client kubernetes.Interface) *ClusterHost {
|
|
return &ClusterHost{client: client}
|
|
}
|
|
|
|
func (c *ClusterHost) HasControlPlaneNodes(ctx context.Context) (bool, error) {
|
|
nodes, err := c.client.CoreV1().Nodes().List(ctx, metav1.ListOptions{})
|
|
if err != nil {
|
|
return false, fmt.Errorf("error fetching nodes: %v", err)
|
|
}
|
|
if len(nodes.Items) == 0 {
|
|
return false, fmt.Errorf("no nodes found")
|
|
}
|
|
for _, node := range nodes.Items {
|
|
for k, v := range node.Labels {
|
|
if isControlPlaneNodeRole(k, v) {
|
|
return true, nil
|
|
}
|
|
}
|
|
}
|
|
|
|
return false, nil
|
|
}
|
|
|
|
func isControlPlaneNodeRole(k string, v string) bool {
|
|
if k == labelNodeRolePrefix+controlPlaneNodeRole {
|
|
return true
|
|
}
|
|
if k == labelNodeRolePrefix+masterNodeRole {
|
|
return true
|
|
}
|
|
if k == nodeLabelRole && v == controlPlaneNodeRole {
|
|
return true
|
|
}
|
|
if k == nodeLabelRole && v == masterNodeRole {
|
|
return true
|
|
}
|
|
return false
|
|
}
|