package tls

import (
	"crypto/x509"
	"encoding/json"
	"encoding/pem"
	"errors"
	"github.com/astaxie/beego"
	"k8s-console/dto"
	"k8s-console/dto/tls"
	"k8s-console/utils"
	"k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"os"
	"path"
	"regexp"
	"strconv"
	"strings"
	"time"
)

const PUBLICKEY_CERTIFICATE_FIRSTLINE = "-----BEGIN CERTIFICATE-----"
const PUBLICKEY_CERTIFICATE_LASTLINE = "-----END CERTIFICATE-----"
const PRIVATEKEY_CERTIFICATE_FIRSTLINE = "-----BEGIN RSA PRIVATE KEY-----"
const PRIVATEKEY_CERTIFICATE_LASTLINE = "-----END RSA PRIVATE KEY-----"

var (
	infoLogger  = utils.InfoLogger
	errorLogger = utils.ErrorLogger
)

// TlsController operations for harborImage
type TlsController struct {
	beego.Controller
}

// URLMapping ...
func (c *TlsController) URLMapping() {
	c.Mapping("getTlsList", c.GetTlsList)
}

// Post ...
// @Title GetTlsList
// @Description get TlsList
// @Param	lang		query 	string	true	"api result language type"
// @Param	body		body 	tls.GetTlsListRequestDto	true	""
// @Success 200
// @Failure 300 {object} dto.BaseResponseDto
// @router /getTlsList [post]
func (c *TlsController) GetTlsList() {
	lang := c.GetString("lang")
	infoLogger.Println("语言: ", lang)
	var requestDto tls.GetTlsListRequestDto
	var errorResponseDto = dto.BaseResponseDto{300, utils.GetI18nLang(lang, "sysError")}
	var successResponseDto = dto.GetPageListBaseResponseDto{}
	successResponseDto.Status = 200
	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &requestDto); err != nil {
		errorLogger.Println(err.Error())
		errorResponseDto.Message = utils.GetI18nLang(lang, "requestParamIncorrectFormat")
		c.Data["json"] = errorResponseDto
		c.ServeJSON()
		return
	}
	infoLogger.Println("证书管理列表查询接口请求参数: ", requestDto)

	pageIndex := requestDto.PageIndex
	pageSize := requestDto.PageSize
	if pageIndex < 0 {
		errorResponseDto.Message = utils.GetI18nLang(lang, "pageIndexRange")
		c.Data["json"] = errorResponseDto
		c.ServeJSON()
		return
	}
	if pageSize <= 0 {
		errorResponseDto.Message = utils.GetI18nLang(lang, "pageSizeRange")
		c.Data["json"] = errorResponseDto
		c.ServeJSON()
		return
	}
	nameSpace := requestDto.NameSpace

	// 获取k8s客户端
	k8sClient := utils.GetK8sClient()
	if k8sClient == nil {
		errorResponseDto.Message = utils.GetI18nLang(lang, "createK8sConFail")
		c.Data["json"] = errorResponseDto
		c.ServeJSON()
		return
	}
	//查询集群所有命名空间信息
	nameSpaceList, err := k8sClient.CoreV1().Namespaces().List(metav1.ListOptions{})
	if err != nil {
		errorLogger.Printf("查询集群所有命名空间失败: %s", err.Error())
		errorResponseDto.Message = utils.GetI18nLang(lang, "getClusterAllNamespacesFail")
		c.Data["json"] = errorResponseDto
		c.ServeJSON()
		return
	}
	allNameSpaceList := []string{}
	for _, item := range nameSpaceList.Items {
		infoLogger.Println(item.Name)
		allNameSpaceList = append(allNameSpaceList, item.Name)
	}

	if len(allNameSpaceList) > 0 && !utils.IsContains(allNameSpaceList, nameSpace) {
		errorLogger.Println("集群不存在此命名空间")
		errorResponseDto.Message = utils.GetI18nLang(lang, "theNameSpaceNotExistInCluster")
		c.Data["json"] = errorResponseDto
		c.ServeJSON()
		return
	}

	//查询命名空间下所有type为kubernetes.io/tls的secrets证书信息
	tlsList, err := k8sClient.CoreV1().Secrets(nameSpace).List(metav1.ListOptions{FieldSelector: "type=kubernetes.io/tls"})
	if err != nil {
		errorLogger.Printf("查询集群%s空间下所有type为kubernetes.io/tls的secrets证书信息失败: %s", nameSpace, err.Error())
		errorResponseDto.Message = utils.GetI18nLang(lang, "getTlsListByNameSpaceFail")
		c.Data["json"] = errorResponseDto
		c.ServeJSON()
		return
	}

	itemList := tlsList.Items

	totalRecords := len(itemList)
	totalPages := 0

	result := []tls.GetTlsListResultDataResponseDto{}
	for _, item := range tlsList.Items {
		creationTimestamp, err := utils.ParseDateToString(lang, item.CreationTimestamp.Time)
		if err != nil {
			errorLogger.Printf("时间格式转换失败: %s", err.Error())
		}

		certDomain := "<none>"
		certExpire := "<none>"
		tlsCrt, ok := item.Data["tls.crt"]
		if ok {
			//获取证书信息 -----BEGIN CERTIFICATE-----   -----END CERTIFICATE-----
			//这里返回的第二个值是证书中剩余的block, 一般是rsa私钥 也就是 -----BEGIN RSA PRIVATE KEY 部分
			//一般证书的有效期，组织信息等都在第一个部分里
			certDERBlock, _ := pem.Decode(tlsCrt)
			if certDERBlock != nil {
				//证书解析，转换成Certificate结构体获取证书域名、过期时间等数据信息
				x509Cert, err := x509.ParseCertificate(certDERBlock.Bytes)
				if err != nil {
					errorLogger.Printf("集群%s空间的tls证书%s解析失败：%s", nameSpace, item.Name, err.Error())
				} else {
					certDomain = x509Cert.Issuer.CommonName                      // 证书域名
					certExpire = x509Cert.NotAfter.Format("2006-01-02 15:04:05") // 证书过期时间
				}
			} else {
				errorLogger.Println(utils.GetI18nLang(lang, "certificatePemDecodeError"))
			}
		} else {
			errorLogger.Printf("集群%s空间的tls证书%s没有证书体tls.crt数据，解析失败", nameSpace, item.Name)
		}

		tlsDto := tls.GetTlsListResultDataResponseDto{
			TlsName:     item.Name,
			TlsDomain:   certDomain,
			Expire:      certExpire,
			CreatedTime: creationTimestamp,
		}

		result = append(result, tlsDto)
	}

	resultList := []tls.GetTlsListResultDataResponseDto{}
	if totalRecords > 0 {
		totalPages = totalRecords/pageSize + 1
		if totalRecords%pageSize == 0 {
			totalPages = totalRecords / pageSize
		}
		if totalRecords <= pageIndex*pageSize {
			errorResponseDto.Message = utils.GetI18nLang(lang, "pageIndexOutRange")
			c.Data["json"] = errorResponseDto
			c.ServeJSON()
			return
		}
		resultList = result[pageIndex*pageSize:]
		if len(result)-pageIndex*pageSize >= pageSize {
			resultList = result[pageIndex*pageSize : (pageIndex+1)*pageSize]
		}
	} else {
		if totalRecords < pageIndex*pageSize {
			errorResponseDto.Message = utils.GetI18nLang(lang, "pageIndexOutRange")
			c.Data["json"] = errorResponseDto
			c.ServeJSON()
			return
		}
	}

	successResponseDto.Result = resultList
	successResponseDto.PageInfo = dto.PageInfoBaseResponseDto{
		TotalRecords: totalRecords,
		TotalPages:   totalPages,
	}
	c.Data["json"] = successResponseDto
	c.ServeJSON()
}

// Post ...
// @Title RemoveTls
// @Description remove tls
// @Param	lang		query 	string	true	"api result language type"
// @Param	body		body 	tls.TlsRequestDto	 true	""
// @Success 200 {object} dto.BaseResponseDto
// @Failure 300 {object} dto.BaseResponseDto
// @router /removeTls [post]
func (c *TlsController) RemoveTls() {
	lang := c.GetString("lang")
	infoLogger.Println("语言: ", lang)
	var requestDto tls.TlsRequestDto
	var responseDto = dto.BaseResponseDto{300, utils.GetI18nLang(lang, "sysError")}
	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &requestDto); err != nil {
		errorLogger.Println(err.Error())
		responseDto.Message = utils.GetI18nLang(lang, "requestParamIncorrectFormat")
		c.Data["json"] = responseDto
		c.ServeJSON()
		return
	}
	infoLogger.Println("删除证书接口请求参数: ", requestDto)

	nameSpace := requestDto.NameSpace
	tlsName := requestDto.TlsName
	if strings.TrimSpace(nameSpace) == "" {
		errorLogger.Println("命名空间不能为空")
		responseDto.Message = utils.GetI18nLang(lang, "requestParamIncorrectFormat")
		c.Data["json"] = responseDto
		c.ServeJSON()
		return
	}
	if strings.TrimSpace(tlsName) == "" {
		errorLogger.Println("证书名称不能为空")
		responseDto.Message = utils.GetI18nLang(lang, "requestParamIncorrectFormat")
		c.Data["json"] = responseDto
		c.ServeJSON()
		return
	}
	if strings.TrimSpace(tlsName) == "k2-tls" {
		responseDto.Message = utils.GetI18nLang(lang, "removeTlsFailByK2Tls")
		c.Data["json"] = responseDto
		c.ServeJSON()
		return
	}
	//查询集群所有命名空间信息
	allNameSpaceList, err := utils.GetClusterAllNameSpaces(lang)
	infoLogger.Println(allNameSpaceList)
	if err != nil {
		errorLogger.Printf("查询集群所有命名空间失败: %s", err.Error())
		responseDto.Message = utils.GetI18nLang(lang, "getClusterAllNamespacesFail")
		c.Data["json"] = responseDto
		c.ServeJSON()
		return
	}
	if len(allNameSpaceList) > 0 && !utils.IsContains(allNameSpaceList, nameSpace) {
		errorLogger.Println("集群不存在此命名空间")
		responseDto.Message = utils.GetI18nLang(lang, "theNameSpaceNotExistInCluster")
		c.Data["json"] = responseDto
		c.ServeJSON()
		return
	}

	// 获取k8s客户端
	k8sClient := utils.GetK8sClient()
	if k8sClient == nil {
		responseDto.Message = utils.GetI18nLang(lang, "createK8sConFail")
		c.Data["json"] = responseDto
		c.ServeJSON()
		return
	}

	//查询tls证书是否存在
	if _, err := k8sClient.CoreV1().Secrets(nameSpace).Get(tlsName, metav1.GetOptions{}); err != nil {
		errorLogger.Printf("查询获取集群%s空间%s的TLS证书详情失败: %s", nameSpace, tlsName, err.Error())
		responseDto.Message = utils.GetI18nLang(lang, "getTheTlsInfoFail")
		c.Data["json"] = responseDto
		c.ServeJSON()
		return
	}

	if err := k8sClient.CoreV1().Secrets(nameSpace).Delete(tlsName, &metav1.DeleteOptions{}); err != nil {
		errorLogger.Printf("移除%s空间TLS证书: %s失败，错误信息: %s", nameSpace, tlsName, err.Error())
		responseDto.Message = utils.GetI18nLang(lang, "removeTlsFail")
		c.Data["json"] = responseDto
		c.ServeJSON()
		return
	}

	responseDto.Status = 200
	responseDto.Message = utils.GetI18nLang(lang, "success")
	c.Data["json"] = responseDto
	c.ServeJSON()
}

// Post ...
// @Title GetTlsInfo
// @Description get tls info
// @Param	lang		query 	string	true	"api result language type"
// @Param	body		body 	tls.TlsRequestDto	true	""
// @Success 200 {object} dto.BaseResultResponseDto
// @Failure 300 {object} dto.BaseResponseDto
// @router /getTlsInfo [post]
func (c *TlsController) GetTlsInfo() {
	lang := c.GetString("lang")
	infoLogger.Println("语言: ", lang)
	var requestDto tls.TlsRequestDto
	var errorResponseDto = dto.BaseResponseDto{300, utils.GetI18nLang(lang, "sysError")}
	var successResponseDto = dto.BaseResultResponseDto{}
	successResponseDto.Status = 200
	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &requestDto); err != nil {
		errorLogger.Println(err.Error())
		errorResponseDto.Message = utils.GetI18nLang(lang, "requestParamIncorrectFormat")
		c.Data["json"] = errorResponseDto
		c.ServeJSON()
		return
	}
	infoLogger.Println("证书详情查询接口请求参数: ", requestDto)

	nameSpace := requestDto.NameSpace
	tlsName := requestDto.TlsName
	if strings.TrimSpace(nameSpace) == "" {
		errorLogger.Println("命名空间不能为空")
		errorResponseDto.Message = utils.GetI18nLang(lang, "requestParamIncorrectFormat")
		c.Data["json"] = errorResponseDto
		c.ServeJSON()
		return
	}
	if strings.TrimSpace(tlsName) == "" {
		errorLogger.Println("证书名称不能为空")
		errorResponseDto.Message = utils.GetI18nLang(lang, "requestParamIncorrectFormat")
		c.Data["json"] = errorResponseDto
		c.ServeJSON()
		return
	}
	//查询集群所有命名空间信息
	allNameSpaceList, err := utils.GetClusterAllNameSpaces(lang)
	infoLogger.Println(allNameSpaceList)
	if err != nil {
		errorLogger.Printf("查询集群所有命名空间失败: %s", err.Error())
		errorResponseDto.Message = utils.GetI18nLang(lang, "getClusterAllNamespacesFail")
		c.Data["json"] = errorResponseDto
		c.ServeJSON()
		return
	}
	if len(allNameSpaceList) > 0 && !utils.IsContains(allNameSpaceList, nameSpace) {
		errorLogger.Println("集群不存在此命名空间")
		errorResponseDto.Message = utils.GetI18nLang(lang, "theNameSpaceNotExistInCluster")
		c.Data["json"] = errorResponseDto
		c.ServeJSON()
		return
	}

	// 获取k8s客户端
	k8sClient := utils.GetK8sClient()
	if k8sClient == nil {
		errorResponseDto.Message = utils.GetI18nLang(lang, "createK8sConFail")
		c.Data["json"] = errorResponseDto
		c.ServeJSON()
		return
	}

	//查询tls详情
	tlsInfo, err := k8sClient.CoreV1().Secrets(nameSpace).Get(tlsName, metav1.GetOptions{})
	if err != nil {
		errorLogger.Printf("查询集群%s空间%s的tls证书详情失败: %s", nameSpace, tlsName, err.Error())
		errorResponseDto.Message = utils.GetI18nLang(lang, "getTheTlsInfoFail")
		c.Data["json"] = errorResponseDto
		c.ServeJSON()
		return
	}

	tls := tls.GetTlsInfoResultDataResponseDto{
		TlsName:               tlsInfo.Name,
		PublicKeyCertificate:  string(tlsInfo.Data["tls.crt"]),
		PrivateKeyCertificate: string(tlsInfo.Data["tls.key"]),
	}
	infoLogger.Println("TLS证书详情：", tls)
	successResponseDto.Result = tls
	c.Data["json"] = successResponseDto
	c.ServeJSON()
}

// UploadTls ...
// @Title Post UploadTls
// @Description upload tls
// @Param	lang			query 	  string	true		"api result language type"
// @Param	certificate		formData  file		true		""
// @Param	caType			formData  string	true		""
// @Success 200 {object} dto.BaseResultResponseDto
// @Failure 300 {object} dto.BaseResponseDto
// @router /uploadTls [post]
func (c *TlsController) UploadTls() {
	lang := c.GetString("lang")
	infoLogger.Println("语言: ", lang)
	var errorResponseDto = dto.BaseResponseDto{300, utils.GetI18nLang(lang, "sysError")}
	var successResponseDto = dto.BaseResultResponseDto{}
	caType := c.Input().Get("caType")
	infoLogger.Println("证书类型: ", caType)
	if !utils.IsContains([]string{"publicKey", "privateKey"}, caType) {
		errorResponseDto.Message = utils.GetI18nLang(lang, "invalidCertificateType")
		c.Data["json"] = errorResponseDto
		c.ServeJSON()
		return
	}

	//获取上传的证书文件
	file, header, err := c.GetFile("certificate")
	if err != nil {
		errorLogger.Println("获取上传的证书文件失败：", err.Error())
		errorResponseDto.Message = utils.GetI18nLang(lang, "certificateUploadFailed")
		c.Data["json"] = errorResponseDto
		c.ServeJSON()
		return
	}
	defer file.Close()
	infoLogger.Println("证书文件大小: ", header.Size)
	infoLogger.Println("证书文件名称: ", header.Filename)

	//校验上传证书大小不能超过200KB
	if header.Size > 200*1024 {
		errorResponseDto.Message = utils.GetI18nLang(lang, "certificateMaxSize")
		c.Data["json"] = errorResponseDto
		c.ServeJSON()
		return
	}
	// 证书文件扩展名
	fileExt := path.Ext(header.Filename)

	// 返给前端页面展示的证书内容
	certificateContent := ""

	// 公钥证书文件校验
	if caType == "publicKey" {
		// 公钥证书扩展名校验
		if fileExt != ".pem" && fileExt != ".crt" {
			errorResponseDto.Message = utils.GetI18nLang(lang, "inValidPublicKeyCertificateExt")
			c.Data["json"] = errorResponseDto
			c.ServeJSON()
			return
		}

		fpath, err := createFile(c, lang, fileExt)
		if err != nil {
			errorLogger.Println("createFile Error：", err.Error())
			errorResponseDto.Message = "createFile Error"
			c.Data["json"] = errorResponseDto
			c.ServeJSON()
			return
		}

		// 公钥证书首、尾行内容校验
		crtArray, err := utils.ReadFile(fpath)
		if err != nil {
			errorLogger.Println("ReadFile Error：", err.Error())
			errorResponseDto.Message = "ReadFile Error"
			c.Data["json"] = errorResponseDto
			c.ServeJSON()
			return
		}
		firstLine := crtArray[0]
		infoLogger.Println("公钥证书文件内容首行: ", firstLine)
		lastLine := crtArray[len(crtArray)-1]
		infoLogger.Println("公钥证书文件内容尾行: ", lastLine)
		if !strings.Contains(firstLine, PUBLICKEY_CERTIFICATE_FIRSTLINE) {
			errorResponseDto.Message = "公钥证书文件首行内容需包含" + PUBLICKEY_CERTIFICATE_FIRSTLINE
			c.Data["json"] = errorResponseDto
			c.ServeJSON()
			return
		}

		if !strings.Contains(lastLine, PUBLICKEY_CERTIFICATE_LASTLINE) {
			errorResponseDto.Message = "公钥证书文件尾行内容需包含" + PUBLICKEY_CERTIFICATE_LASTLINE
			c.Data["json"] = errorResponseDto
			c.ServeJSON()
			return
		}
		for _, v := range crtArray {
			certificateContent += v + "\n"
		}
	}

	// 私钥证书文件校验
	if caType == "privateKey" {
		// 私钥证书扩展名校验
		if fileExt != ".pem" && fileExt != ".key" {
			errorResponseDto.Message = utils.GetI18nLang(lang, "inValidPublicKeyCertificateExt")
			c.Data["json"] = errorResponseDto
			c.ServeJSON()
			return
		}

		fpath, err := createFile(c, lang, fileExt)
		if err != nil {
			errorLogger.Println("createFile Error：", err.Error())
			errorResponseDto.Message = "createFile Error"
			c.Data["json"] = errorResponseDto
			c.ServeJSON()
			return
		}

		// 私钥证书首、尾行内容校验
		crtArray, err := utils.ReadFile(fpath)
		if err != nil {
			errorLogger.Println("ReadFile Error：", err.Error())
			errorResponseDto.Message = "ReadFile Error"
			c.Data["json"] = errorResponseDto
			c.ServeJSON()
			return
		}
		firstLine := crtArray[0]
		infoLogger.Println("私钥证书文件内容首行: ", firstLine)
		lastLine := crtArray[len(crtArray)-1]
		infoLogger.Println("私钥证书文件内容尾行: ", lastLine)
		if !strings.Contains(firstLine, PRIVATEKEY_CERTIFICATE_FIRSTLINE) {
			errorResponseDto.Message = "私钥证书文件首行内容需包含" + PRIVATEKEY_CERTIFICATE_FIRSTLINE
			c.Data["json"] = errorResponseDto
			c.ServeJSON()
			return
		}

		if !strings.Contains(lastLine, PRIVATEKEY_CERTIFICATE_LASTLINE) {
			errorResponseDto.Message = "私钥证书文件尾行内容需包含" + PRIVATEKEY_CERTIFICATE_LASTLINE
			c.Data["json"] = errorResponseDto
			c.ServeJSON()
			return
		}
		for _, v := range crtArray {
			// 拼接换行符"\n"
			certificateContent += v + "\n"
		}
	}

	successResponseDto.Status = 200
	successResponseDto.Result = certificateContent
	c.Data["json"] = successResponseDto
	c.ServeJSON()
}

// 将上传的证书创建到指定目录下，并生成文件
func createFile(c *TlsController, lang string, fileExt string) (filePath string, err error) {
	uploadDir := "./upload/tls/" + time.Now().Format("2006/01/02/")
	if err := os.MkdirAll(uploadDir, os.ModePerm); err != nil {
		errorLogger.Println("MkdirAll error：", err.Error())
		return "", err
	}
	filePath = uploadDir + strconv.FormatInt(time.Now().Unix(), 10) + fileExt
	if err := c.SaveToFile("certificate", filePath); err != nil {
		errorLogger.Println("SaveToFile error：", err.Error())
		return "", err
	}
	return filePath, nil
}

// Post ...
// @Title AddOrUpdateTls
// @Description add or update tls
// @Param	lang		query 	string	true	"api result language type"
// @Param	body		body 	tls.AddOrUpdateTlsRequestDto	true	""
// @Success 200 {object} dto.BaseResponseDto
// @Failure 300 {object} dto.BaseResponseDto
// @router /addOrUpdateTls [post]
func (c *TlsController) AddOrUpdateTls() {
	lang := c.GetString("lang")
	infoLogger.Println("语言: ", lang)
	var requestDto tls.AddOrUpdateTlsRequestDto
	var responseDto = dto.BaseResponseDto{300, utils.GetI18nLang(lang, "sysError")}
	infoLogger.Println("证书添加/更新接口转换前的请求参数: ", string(c.Ctx.Input.RequestBody))
	// 替换掉证书内容中所有换行符
	requestBodyStr := string(c.Ctx.Input.RequestBody)
	requestBodyStr = strings.ReplaceAll(requestBodyStr, "\n", "")
	if err := json.Unmarshal([]byte(requestBodyStr), &requestDto); err != nil {
		errorLogger.Println(err.Error())
		responseDto.Message = utils.GetI18nLang(lang, "requestParamIncorrectFormat")
		c.Data["json"] = responseDto
		c.ServeJSON()
		return
	}
	infoLogger.Println("证书添加/更新接口转换后的请求参数: ", requestDto)

	// 校验请求参数
	if err := paramsValid(lang, requestDto); err != nil {
		errorLogger.Printf("证书添加/更新接口参数校验失败: %s", err.Error())
		responseDto.Message = err.Error()
		c.Data["json"] = responseDto
		c.ServeJSON()
		return
	}

	// 获取k8s客户端
	k8sClient := utils.GetK8sClient()
	if k8sClient == nil {
		responseDto.Message = utils.GetI18nLang(lang, "createK8sConFail")
		c.Data["json"] = responseDto
		c.ServeJSON()
		return
	}

	nameSpace := requestDto.NameSpace
	tlsName := requestDto.TlsName
	secretOptions := v1.Secret{}
	secretOptions.Name = tlsName

	// k2-tls名字的证书除了default空间外，不可在其他空间创建
	if nameSpace != "default" && tlsName == "k2-tls" {
		responseDto.Message = utils.GetI18nLang(lang, "k2TlsGlobalUniqueness")
		c.Data["json"] = responseDto
		c.ServeJSON()
		return
	}

	// 添加证书
	if requestDto.OperationType == "add" {
		secretOptions.Kind = "Secret"
		secretOptions.APIVersion = "v1"
		secretOptions.Type = "kubernetes.io/tls"
		secretOptions.Namespace = nameSpace
		dataMap := make(map[string][]byte)
		//publicKeyEncoded := base64.StdEncoding.EncodeToString([]byte(requestDto.PublicKey))
		dataMap["tls.crt"] = []byte(requestDto.PublicKey)
		//privateKeyEncoded := base64.StdEncoding.EncodeToString([]byte(requestDto.PrivateKey))
		dataMap["tls.key"] = []byte(requestDto.PrivateKey)
		secretOptions.Data = dataMap
		_, err := k8sClient.CoreV1().Secrets(nameSpace).Create(&secretOptions)
		if err != nil {
			errorLogger.Printf("创建集群%s空间%s的tls证书secret失败: %s", nameSpace, tlsName, err.Error())
			responseDto.Message = strings.Join([]string{utils.GetI18nLang(lang, "addTlsFail"), err.Error()}, ": ")
			c.Data["json"] = responseDto
			c.ServeJSON()
			return
		}
		infoLogger.Printf("创建集群%s空间%s的tls证书secret成功", nameSpace, tlsName)
	}

	// 更新证书
	if requestDto.OperationType == "update" {
		//先根据证书名称查询tls证书是否存在
		tlsInfo, err := k8sClient.CoreV1().Secrets(nameSpace).Get(tlsName, metav1.GetOptions{})
		if err != nil && strings.Contains(err.Error(), "not found") {
			errorLogger.Printf("查询集群%s空间%s的tls证书详情失败: %s", nameSpace, tlsName, err.Error())
			responseDto.Message = utils.GetI18nLang(lang, "getTheTlsInfoFail")
			c.Data["json"] = responseDto
			c.ServeJSON()
			return
		}
		if _, ok := tlsInfo.Data["tls.crt"]; ok {
			//publicKeyEncoded := base64.StdEncoding.EncodeToString([]byte(requestDto.PublicKey))
			tlsInfo.Data["tls.crt"] = []byte(requestDto.PublicKey)
		}
		if _, ok := tlsInfo.Data["tls.key"]; ok {
			//privateKeyEncoded := base64.StdEncoding.EncodeToString([]byte(requestDto.PrivateKey))
			tlsInfo.Data["tls.key"] = []byte(requestDto.PrivateKey)
		}

		if _, err := k8sClient.CoreV1().Secrets(nameSpace).Update(tlsInfo); err != nil {
			errorLogger.Printf("更新集群%s空间%s的tls证书失败: %s", nameSpace, tlsName, err.Error())
			responseDto.Message = strings.Join([]string{utils.GetI18nLang(lang, "updateTlsFail"), err.Error()}, ": ")
			c.Data["json"] = responseDto
			c.ServeJSON()
			return
		}
		infoLogger.Printf("更新集群%s空间%s的tls证书成功", nameSpace, tlsName)

	}

	responseDto.Status = 200
	responseDto.Message = utils.GetI18nLang(lang, "success")
	c.Data["json"] = responseDto
	c.ServeJSON()

}

// 证书添加、更新接口参数校验
func paramsValid(lang string, requestDto tls.AddOrUpdateTlsRequestDto) error {
	// 证书名称，1-80字符，并且只能包含小写字母、数字、横杆-、小数点，必须以字母或数字开头结尾
	if len([]rune(requestDto.TlsName)) < 1 || len([]rune(requestDto.TlsName)) > 80 {
		return errors.New(utils.GetI18nLang(lang, "requestParamIncorrectFormat") + ": 证书名称长度范围1-80")
	}
	nameMatched, err := regexp.MatchString("^[a-z0-9]+([-\\.]*[a-z0-9]+)*$", requestDto.TlsName)
	if err != nil {
		return errors.New(utils.GetI18nLang(lang, "requestParamIncorrectFormat") + ": 证书名称正则校验异常")
	}
	if !nameMatched {
		return errors.New(utils.GetI18nLang(lang, "requestParamIncorrectFormat") + ": 证书名称正则校验失败")
	}

	if strings.TrimSpace(requestDto.PublicKey) == "" {
		return errors.New(utils.GetI18nLang(lang, "requestParamIncorrectFormat") + ": 公钥证书内容不能为空")
	}

	if !strings.HasPrefix(requestDto.PublicKey, PUBLICKEY_CERTIFICATE_FIRSTLINE) {
		return errors.New(utils.GetI18nLang(lang, "requestParamIncorrectFormat") + ": 公钥证书文件首行内容需包含" + PUBLICKEY_CERTIFICATE_FIRSTLINE)
	}

	if !hasSuffix(requestDto.PublicKey, PUBLICKEY_CERTIFICATE_LASTLINE) {
		return errors.New(utils.GetI18nLang(lang, "requestParamIncorrectFormat") + ": 公钥证书文件尾行内容需包含" + PUBLICKEY_CERTIFICATE_LASTLINE)
	}

	if strings.TrimSpace(requestDto.PrivateKey) == "" {
		return errors.New(utils.GetI18nLang(lang, "requestParamIncorrectFormat") + ": 私钥证书内容不能为空")
	}

	if !strings.HasPrefix(requestDto.PrivateKey, PRIVATEKEY_CERTIFICATE_FIRSTLINE) {
		return errors.New(utils.GetI18nLang(lang, "requestParamIncorrectFormat") + ": 私钥证书文件首行内容需包含" + PRIVATEKEY_CERTIFICATE_FIRSTLINE)
	}

	if !hasSuffix(requestDto.PrivateKey, PRIVATEKEY_CERTIFICATE_LASTLINE) {
		return errors.New(utils.GetI18nLang(lang, "requestParamIncorrectFormat") + ": 私钥证书文件尾行内容需包含" + PRIVATEKEY_CERTIFICATE_LASTLINE)
	}

	if !utils.IsContains([]string{"add", "update"}, requestDto.OperationType) {
		return errors.New(utils.GetI18nLang(lang, "requestParamIncorrectFormat") + ": 操作类型operationType的值只能为添加add和更新update")
	}

	if strings.TrimSpace(requestDto.NameSpace) == "" {
		return errors.New(utils.GetI18nLang(lang, "requestParamIncorrectFormat") + ": 命名空间不能为空")
	}
	//查询集群所有命名空间信息
	allNameSpaceList, err := utils.GetClusterAllNameSpaces(lang)
	infoLogger.Println(allNameSpaceList)
	if err != nil {
		errorLogger.Printf("查询集群所有命名空间失败: %s", err.Error())
		return errors.New(utils.GetI18nLang(lang, "getClusterAllNamespacesFail"))
	}
	if len(allNameSpaceList) > 0 && !utils.IsContains(allNameSpaceList, requestDto.NameSpace) {
		errorLogger.Println("集群不存在此命名空间")
		return errors.New(utils.GetI18nLang(lang, "theNameSpaceNotExistInCluster"))
	}

	return nil
}

// 判断证书尾行是否包含指定内容
func hasSuffix(s, suffix string) bool {
	array := strings.Split(s, "\n")
	return len(s) >= len(suffix) && len(array) > 1 && (array[len(array)-1] == suffix || array[len(array)-2] == suffix)
}
