// Copyright (c) 2021. Huawei Technologies Co., Ltd. All rights reserved.

// Package common define common utils
package common

import (
"context"
"fmt"
"os"
"sync"
"time"

v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
"volcano.sh/apis/pkg/client/clientset/versioned"

"huawei.com/npu-exporter/hwlog"
"huawei.com/npu-exporter/utils"
)

const (
maxLen = 200

// PVCVolumeName the volume name of storage pvc
PVCVolumeName = "platform"
// StoragePVCName the PVC name of storage
StoragePVCName = "storage-pvc"
// PublicPVCName the PVC name of public dir
PublicPVCName = "storage-pvc-public"
)

var (
k8sClientOnce sync.Once
vcClientOnce sync.Once
kubeClientSet *kubernetes.Clientset
vcClientSet *versioned.Clientset
// Kubeconfig the k8s master config file
Kubeconfig string
)

// K8sBaseClient base k8s client for other component to extend
type K8sBaseClient struct {
Clientset *kubernetes.Clientset
VcClientSet *versioned.Clientset
NameSpace string
}

// K8SController is a controller for k8s client
type K8SController struct {
KubeClientSet kubernetes.Interface
}

// K8sClient Get the internal k8s client of the cluster
func K8sClient(kubeconfig string) (*kubernetes.Clientset, error) {
k8sClientOnce.Do(func() {
if kubeconfig == "" {
configPath := os.Getenv("KUBECONFIG")
if len(configPath) > maxLen {
hwlog.RunLog.Fatal("the path is too long")
}
kubeconfig = configPath
}
cfgPath, err := utils.CheckPath(kubeconfig)
if err != nil {
hwlog.RunLog.Fatal(err)
}
config, err := clientcmd.BuildConfigFromFlags("", cfgPath)
if err != nil {
hwlog.RunLog.Fatal(err)
}
// Create a new k8sClientSet based on the specified config using the current context
kubeClientSet, err = kubernetes.NewForConfig(config)
if err != nil {
hwlog.RunLog.Fatal(err)
}
})

return kubeClientSet, nil
}

// NewK8sController init k8s controller client
func NewK8sController(kc *kubernetes.Clientset) *K8SController {
return &K8SController{
KubeClientSet: kc,
}
}

// VcClient Get the internal volcano client of the cluster
func VcClient(vcConfig string) (*versioned.Clientset, error) {
vcClientOnce.Do(func() {
if vcConfig == "" {
configPath := os.Getenv("KUBECONFIG")
if len(configPath) > maxLen {
hwlog.RunLog.Fatal("the path is too long")
}
vcConfig = configPath
}
cfgPath, err := utils.CheckPath(vcConfig)
if err != nil {
hwlog.RunLog.Fatal(err)
}
config, err := clientcmd.BuildConfigFromFlags("", cfgPath)
if err != nil {
hwlog.RunLog.Fatal(err)
}
// Create a new vcClientSet based on the specified config using the current context
vcClientSet, err = versioned.NewForConfig(config)
if err != nil {
hwlog.RunLog.Fatal(err)
}
})

return vcClientSet, nil
}

// GetDBConnectionPath get db connection path
func (handler *K8sBaseClient) GetDBConnectionPath(retryCount, timeInterval int,
secretName, namespace string) (string, error) {
for {
if retryCount < 0 {
return "", fmt.Errorf("the secret of db information with name(%s) cannot be find in namespace(%s)",
secretName, namespace)
}

secret, err := handler.GetDBSecret(secretName, namespace)
if err != nil {
retryCount--
hwlog.RunLog.Error(err)
time.Sleep(time.Duration(timeInterval) * time.Second)
continue
}

return fmt.Sprintf("%s", secret.Data[DBSecretConnectionPathKey]), nil
}
}

func (handler *K8sBaseClient) getDBSecret(name, namespace string) (*v1.Secret, error) {
secret, err := handler.Clientset.CoreV1().Secrets(namespace).Get(context.TODO(),
name, metav1.GetOptions{})

return secret, err
}

// GetDBSecret get db secret
func (handler *K8sBaseClient) GetDBSecret(name, namespace string) (*v1.Secret, error) {
secret, err := handler.getDBSecret(name, namespace)
if err != nil {
return nil, err
}

if err = handler.validDBSecret(secret); err != nil {
return nil, err
}

return secret, nil
}

func (handler *K8sBaseClient) validDBSecret(secret *v1.Secret) error {
var err error
if secret.Data == nil {
err = fmt.Errorf("the secret data for connect to database is empty")
return err
}

if _, ok := secret.Data[DBSecretConnectionPathKey]; !ok {
err = fmt.Errorf("the %s field for connecting to the database in the secret is incorrect",
DBSecretConnectionPathKey)
return err
}

return nil
}

最新文章

  1. Atitit.图片木马的原理与防范&#160;attilax&#160;总结
  2. 关于String对象的比较
  3. SVN中的常见错误(长期更新)
  4. mybatis的$存在安全问题,为什么又不得不用?
  5. Android(java)学习笔记200:Android中View动画之 XML实现 和 代码实现
  6. codeforces 672 D
  7. OC中NSString 的常用方法
  8. 使用iframe设置frameset的高度
  9. java提高篇(七)-----详解内部类
  10. php rsa 加密、解密、签名、验签
  11. 最近一段OI学习计划
  12. 通过字典给类的实体属性赋值生成url字符串
  13. SQLSERVER异机备份
  14. docker入门实战笔记
  15. 当谈 SQL 优化时谈些什么?
  16. springboot集成mybatis(一)
  17. Uva - 230 - Borrowers
  18. JAVA之旅(十六)——String类,String常用方法,获取,判断,转换,替换,切割,子串,大小写转换,去除空格,比较
  19. [Swift]LeetCode494. 目标和 | Target Sum
  20. NEST 中的日期数学表达式

热门文章

  1. luogu [ZJOI2007] 矩阵游戏
  2. Macos下用pycharm运行django项目死活安装不上mysqlclient怎么办!!??
  3. Java Socket底层实现浅析
  4. .NET 实现启动时重定向程序运行路径及 Windows 服务运行模式部署
  5. 使用 Elastic 技术栈构建 K8S 全栈监控 -4: 使用 Elastic APM 实时监控应用性能
  6. Elasticsearch 快照生命周期管理 (SLM) 实战指南
  7. PAT (Basic Level) Practice 1003 我要通过!分数 20
  8. 编写一个应用程序,在主类Test1类中,创建两个链表List&lt;E&gt;对象,分别存储通过键盘输入的字符串内容
  9. .NET下数据库的负载均衡(有趣实验)(续)
  10. 洛谷P4304 TJOI2013 攻击装置 (二分图匹配)