diff --git a/service/dataselector.go b/service/dataselector.go deleted file mode 100644 index d603907..0000000 --- a/service/dataselector.go +++ /dev/null @@ -1,161 +0,0 @@ -package service - -import ( - appsv1 "k8s.io/api/apps/v1" //引入K8s的APPSv1的包.定义别名为appsv1 - corev1 "k8s.io/api/core/v1" //引入K8s的corev1的包.定义别名为corev1 - nwv1 "k8s.io/api/networking/v1" - "sort" - "strings" - "time" -) - -//定义结构体:dataSelector,用于封装排序、过滤、分页的数据类型 -type dataSelector struct { //包内调用,首字母小写 - GenericDataList []DataCell - DataSelect *DataSelectQuery -} - -// DataCell DataCell接口用于各种资源List类型的转换,转换后可以使用dataSelector的排序、过滤、分页方法 -type DataCell interface { - GetCreation() time.Time - GetName() string -} - -// DataSelectQuery 定义过滤和分页结构体,过滤使用Name过滤,分页使用Limit和page -//Limit 是单页的数据条数 -//Page是第几页 -type DataSelectQuery struct { - Filter *FilterQuery - Paginate *PaginateQuery -} - -type FilterQuery struct { - Name string -} - -type PaginateQuery struct { - Limit int - Page int -} - -// Len 实现自定义结构体的排序,需要重写Len、Swap、Less方法 -//Len方法用于获取数组的长度 -func (d *dataSelector) Len() int { - return len(d.GenericDataList) -} - -// Swap 方法用于数据比较大小之后的位置变更 -func (d *dataSelector) Swap(i, j int) { - //临时变量对调 i,j ==> j.i - d.GenericDataList[i], d.GenericDataList[j] = d.GenericDataList[j], d.GenericDataList[i] -} - -// Less 方法用于比较大小 -func (d *dataSelector) Less(i, j int) bool { - a := d.GenericDataList[i].GetCreation() - b := d.GenericDataList[j].GetCreation() - //比较B的时间是否在A之前,触发位置调换 - return b.Before(a) -} - -//重写以上三个方法,使用sort.Sort进行排序 -func (d *dataSelector) Sort() *dataSelector { - sort.Sort(d) - return d -} - -// Filter 方法用于过滤数据,比较数据的Name属性,如果包含则返回 -func (d *dataSelector) Filter() *dataSelector { - //判断入参是否为空,如果为空则返回所有数据 - if d.DataSelect.Filter.Name == "" { - return d - } - //如果不为空,则按照入参Name进行过滤 - //声明一个新的数组。若Name包含,则把数据放进数组,返回出去 - filtered := []DataCell{} - for _, value := range d.GenericDataList { - //定义是否匹配的标签变量,然后默认是匹配 - matches := true - objName := value.GetName() - if strings.Contains(objName, d.DataSelect.Filter.Name) { - matches = false - continue //跳过当前循环,执行下一次循环 - } - if matches { - filtered = append(filtered, value) - } - } - - d.GenericDataList = filtered - return d -} - -// Paginate 方法用于数组的分页,根据Limit和Page的传参,取一定范围内的数据,返回 -func (d *dataSelector) Paginate() *dataSelector { - //根据Limit和Page的入参,定义快捷变量 - limit := d.DataSelect.Paginate.Limit - page := d.DataSelect.Paginate.Page - - //检验参数的合法性 - if limit <= 0 || page <= 0 { - return d - } - - //定义取数范围需要的starIndex和endIndex - startIndex := limit * (page - 1) - endIndex := limit*page - 1 - - //出来endIndex - if endIndex > len(d.GenericDataList) { - endIndex = len(d.GenericDataList) - } - - d.GenericDataList = d.GenericDataList[startIndex:endIndex] - - return d -} - -// 定义podCell类型,重写GetCreateion和GetName方法后,可进行数据转换 -//corev1.Pod --> podCell --> DataCell -//appsv1.Deployment --> deployCell --> DataCell -type podCell corev1.Pod - -// GetCreation 重写DataCell接口的两个方法 -func (p podCell) GetCreation() time.Time { - return p.CreationTimestamp.Time -} - -func (p podCell) GetName() string { - return p.Name -} - -type deploymentCell appsv1.Deployment - -func (d deploymentCell) GetCreation() time.Time { - return d.CreationTimestamp.Time -} - -func (d deploymentCell) GetName() string { - return d.Name -} - -type serviceCell corev1.Service - -func (s serviceCell) GetCreation() time.Time { - return s.CreationTimestamp.Time -} - -func (s serviceCell) GetName() string { - return s.Name -} - -//追加ingress DataCell接口相关代码 -type ingressCell nwv1.Ingress - -func (i ingressCell) GetCreation() time.Time { - return i.CreationTimestamp.Time -} - -func (i ingressCell) GetName() string { - return i.Name -} diff --git a/service/deployment.go b/service/deployment.go deleted file mode 100644 index acc1992..0000000 --- a/service/deployment.go +++ /dev/null @@ -1,307 +0,0 @@ -package service - -import ( - "context" - "encoding/json" - "errors" - "github.com/wonderivan/logger" - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/resource" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/intstr" - "strconv" - "time" -) - -var Deployment deployment - -type deployment struct{} - -//定义列表的返回内容,Items是deployment元素列表,Total为deployment元素数量 -type DeploymentsResp struct { - Items []appsv1.Deployment `json:"items"` - Total int `json:"total"` -} - -//定义DeployCreate结构体,用于创建deployment需要的参数属性的定义 -type DeployCreate struct { - Name string `json:"name"` - Namespace string `json:"namespace"` - Replicas int32 `json:"replicas"` - Image string `json:"image"` - Label map[string]string `json:"label"` - Cpu string `json:"cpu"` - Memory string `json:"memory"` - ContainerPort int32 `json:"container_port"` - HealthCheck bool `json:"health_check"` - HealthPath string `json:"health_path"` -} - -//定义DeploysNp类型,用于返回namespace中deployment的数量 -type DeploysNp struct { - Namespace string `json:"namespace"` - DeployNum int `json:"deployment_num"` -} - -//获取deployment列表,支持过滤、排序、分页 -func (d *deployment) GetDeployments(filterName, namespace string, limit, page int) (deploymentsResp *DeploymentsResp, err error) { - //获取deploymentList类型的deployment列表 - deploymentList, err := K8s.ClientSet.AppsV1().Deployments(namespace).List(context.TODO(), metav1.ListOptions{}) - if err != nil { - logger.Error(errors.New("获取Deployment列表失败, " + err.Error())) - return nil, errors.New("获取Deployment列表失败, " + err.Error()) - } - //将deploymentList中的deployment列表(Items),放进dataselector对象中,进行排序 - selectableData := &dataSelector{ - GenericDataList: d.toCells(deploymentList.Items), - DataSelect: &DataSelectQuery{ - Filter: &FilterQuery{Name: filterName}, - Paginate: &PaginateQuery{ - Limit: limit, - Page: page, - }, - }, - } - - filtered := selectableData.Filter() - total := len(filtered.GenericDataList) - data := filtered.Sort().Paginate() - - //将[]DataCell类型的deployment列表转为appsv1.deployment列表 - deployments := d.fromCells(data.GenericDataList) - - return &DeploymentsResp{ - Items: deployments, - Total: total, - }, nil -} - -//获取deployment详情 -func (d *deployment) GetDeploymentDetail(deploymentName, namespace string) (deployment *appsv1.Deployment, err error) { - deployment, err = K8s.ClientSet.AppsV1().Deployments(namespace).Get(context.TODO(), deploymentName, metav1.GetOptions{}) - if err != nil { - logger.Error(errors.New("获取Deployment详情失败, " + err.Error())) - return nil, errors.New("获取Deployment详情失败, " + err.Error()) - } - - return deployment, nil -} - -//设置deployment副本数 -func (d *deployment) ScaleDeployment(deploymentName, namespace string, scaleNum int) (replica int32, err error) { - //获取autoscalingv1.Scale类型的对象,能点出当前的副本数 - scale, err := K8s.ClientSet.AppsV1().Deployments(namespace).GetScale(context.TODO(), deploymentName, metav1.GetOptions{}) - if err != nil { - logger.Error(errors.New("获取Deployment副本数信息失败, " + err.Error())) - return 0, errors.New("获取Deployment副本数信息失败, " + err.Error()) - } - //修改副本数 - scale.Spec.Replicas = int32(scaleNum) - //更新副本数,传入scale对象 - newScale, err := K8s.ClientSet.AppsV1().Deployments(namespace).UpdateScale(context.TODO(), deploymentName, scale, metav1.UpdateOptions{}) - if err != nil { - logger.Error(errors.New("更新Deployment副本数信息失败, " + err.Error())) - return 0, errors.New("更新Deployment副本数信息失败, " + err.Error()) - } - - return newScale.Spec.Replicas, nil -} - -//创建deployment,接收DeployCreate对象 -func (d *deployment) CreateDeployment(data *DeployCreate) (err error) { - //初始化appsv1.Deployment类型的对象,并将入参的data数据放进去 - deployment := &appsv1.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: data.Name, - Namespace: data.Namespace, - Labels: data.Label, - }, - Spec: appsv1.DeploymentSpec{ - Replicas: &data.Replicas, - Selector: &metav1.LabelSelector{ - MatchLabels: data.Label, - }, - Template: corev1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Name: data.Name, - Labels: data.Label, - }, - Spec: corev1.PodSpec{ - Containers: []corev1.Container{ - { - Name: data.Name, - Image: data.Image, - Ports: []corev1.ContainerPort{ - { - Name: "http", - Protocol: corev1.ProtocolTCP, - ContainerPort: data.ContainerPort, - }, - }, - }, - }, - }, - }, - }, - Status: appsv1.DeploymentStatus{}, - } - //判断健康检查功能是否打开,若打开,则增加健康检查功能 - if data.HealthCheck { - deployment.Spec.Template.Spec.Containers[0].ReadinessProbe = &corev1.Probe{ - ProbeHandler: corev1.ProbeHandler{ - HTTPGet: &corev1.HTTPGetAction{ - Path: data.HealthPath, - Port: intstr.IntOrString{ - Type: 0, - IntVal: data.ContainerPort, - }, - }, - }, - InitialDelaySeconds: 5, - TimeoutSeconds: 5, - PeriodSeconds: 5, - } - deployment.Spec.Template.Spec.Containers[0].LivenessProbe = &corev1.Probe{ - ProbeHandler: corev1.ProbeHandler{ - HTTPGet: &corev1.HTTPGetAction{ - Path: data.HealthPath, - Port: intstr.IntOrString{ - Type: 0, - IntVal: data.ContainerPort, - }, - }, - }, - InitialDelaySeconds: 15, - TimeoutSeconds: 5, - PeriodSeconds: 5, - } - } - //定义容器的limit和request资源 - deployment.Spec.Template.Spec.Containers[0].Resources.Limits = map[corev1.ResourceName]resource.Quantity{ - corev1.ResourceCPU: resource.MustParse(data.Cpu), - corev1.ResourceMemory: resource.MustParse(data.Memory), - } - deployment.Spec.Template.Spec.Containers[0].Resources.Requests = map[corev1.ResourceName]resource.Quantity{ - corev1.ResourceCPU: resource.MustParse(data.Cpu), - corev1.ResourceMemory: resource.MustParse(data.Memory), - } - - //调用sdk创建deployment - _, err = K8s.ClientSet.AppsV1().Deployments(data.Namespace). - Create(context.TODO(), deployment, metav1.CreateOptions{}) - if err != nil { - logger.Error(errors.New("创建Deployment失败, " + err.Error())) - return errors.New("创建Deployment失败, " + err.Error()) - } - - return nil -} - -//删除deployment -func (d *deployment) DeleteDeployment(deploymentName, namespace string) (err error) { - err = K8s.ClientSet.AppsV1().Deployments(namespace).Delete(context.TODO(), deploymentName, metav1.DeleteOptions{}) - if err != nil { - logger.Error(errors.New("删除Deployment失败, " + err.Error())) - return errors.New("删除Deployment失败, " + err.Error()) - } - - return nil -} - -//重启deployment -func (d *deployment) RestartDeployment(deploymentName, namespace string) (err error) { - //此功能等同于一下kubectl命令 - //kubectl deployment ${service} -p \ - //'{"spec":{"template":{"spec":{"containers":[{"name":"'"${service}"'","env":[{"name":"RESTART_","value":"'$(date +%s)'"}]}]}}}}' - - //使用patchData Map组装数据 - patchData := map[string]interface{}{ - "spec": map[string]interface{}{ - "template": map[string]interface{}{ - "spec": map[string]interface{}{ - "containers": []map[string]interface{}{ - {"name": deploymentName, - "env": []map[string]string{{ - "name": "RESTART_", - "value": strconv.FormatInt(time.Now().Unix(), 10), - }}, - }, - }, - }, - }, - }, - } - //序列化为字节,因为patch方法只接收字节类型参数 - patchByte, err := json.Marshal(patchData) - if err != nil { - logger.Error(errors.New("json序列化失败, " + err.Error())) - return errors.New("json序列化失败, " + err.Error()) - } - //调用patch方法更新deployment - _, err = K8s.ClientSet.AppsV1().Deployments(namespace).Patch(context.TODO(), deploymentName, "application/strategic-merge-patch+json", patchByte, metav1.PatchOptions{}) - if err != nil { - logger.Error(errors.New("重启Deployment失败, " + err.Error())) - return errors.New("重启Deployment失败, " + err.Error()) - } - - return nil -} - -//更新deployment -func (d *deployment) UpdateDeployment(namespace, content string) (err error) { - var deploy = &appsv1.Deployment{} - - err = json.Unmarshal([]byte(content), deploy) - if err != nil { - logger.Error(errors.New("反序列化失败, " + err.Error())) - return errors.New("反序列化失败, " + err.Error()) - } - - _, err = K8s.ClientSet.AppsV1().Deployments(namespace).Update(context.TODO(), deploy, metav1.UpdateOptions{}) - if err != nil { - logger.Error(errors.New("更新Deployment失败, " + err.Error())) - return errors.New("更新Deployment失败, " + err.Error()) - } - return nil -} - -//获取每个namespace的deployment数量 -func (d *deployment) GetDeployNumPerNp() (deploysNps []*DeploysNp, err error) { - namespaceList, err := K8s.ClientSet.CoreV1().Namespaces().List(context.TODO(), metav1.ListOptions{}) - if err != nil { - return nil, err - } - for _, namespace := range namespaceList.Items { - deploymentList, err := K8s.ClientSet.AppsV1().Deployments(namespace.Name).List(context.TODO(), metav1.ListOptions{}) - if err != nil { - return nil, err - } - - deploysNp := &DeploysNp{ - Namespace: namespace.Name, - DeployNum: len(deploymentList.Items), - } - - deploysNps = append(deploysNps, deploysNp) - } - return deploysNps, nil -} - -//类型转换 -func (d *deployment) toCells(deployments []appsv1.Deployment) []DataCell { - cells := make([]DataCell, len(deployments)) - for i := range deployments { - cells[i] = deploymentCell(deployments[i]) - } - return cells -} - -func (d *deployment) fromCells(cells []DataCell) []appsv1.Deployment { - deployments := make([]appsv1.Deployment, len(cells)) - for i := range cells { - //cells[i].(podCell)是将DataCell类型转成podCell - deployments[i] = appsv1.Deployment(cells[i].(deploymentCell)) - } - return deployments -} diff --git a/service/ingress.go b/service/ingress.go deleted file mode 100644 index aca9a2e..0000000 --- a/service/ingress.go +++ /dev/null @@ -1,183 +0,0 @@ -package service - -import ( - "context" - "encoding/json" - "errors" - "github.com/wonderivan/logger" - nwv1 "k8s.io/api/networking/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -var Ingress ingress - -type ingress struct{} - -type IngressesResp struct { - Items []nwv1.Ingress `json:"items"` - Total int `json:"total"` -} - -//定义ServiceCreate结构体,用于创建service需要的参数属性的定义 -type IngressCreate struct { - Name string `json:"name"` - Namespace string `json:"namespace"` - Label map[string]string `json:"label"` - Hosts map[string][]*HttpPath `json:"hosts"` -} - -//定义ingress的path结构体 -type HttpPath struct { - Path string `json:"path"` - PathType nwv1.PathType `json:"path_type"` - ServiceName string `json:"service_name"` - ServicePort int32 `json:"service_port"` -} - -//获取ingress列表,支持过滤、排序、分页 -func (i *ingress) GetIngresses(filterName, namespace string, limit, page int) (ingressesResp *IngressesResp, err error) { - //获取ingressList类型的ingress列表 - ingressList, err := K8s.ClientSet.NetworkingV1().Ingresses(namespace).List(context.TODO(), metav1.ListOptions{}) - if err != nil { - logger.Error(errors.New("获取Ingress列表失败, " + err.Error())) - return nil, errors.New("获取Ingress列表失败, " + err.Error()) - } - //将ingressList中的ingress列表(Items),放进dataselector对象中,进行排序 - selectableData := &dataSelector{ - GenericDataList: i.toCells(ingressList.Items), - DataSelect: &DataSelectQuery{ - Filter: &FilterQuery{Name: filterName}, - Paginate: &PaginateQuery{ - Limit: limit, - Page: page, - }, - }, - } - - filtered := selectableData.Filter() - total := len(filtered.GenericDataList) - data := filtered.Sort().Paginate() - - //将[]DataCell类型的ingress列表转为v1.ingress列表 - ingresss := i.fromCells(data.GenericDataList) - - return &IngressesResp{ - Items: ingresss, - Total: total, - }, nil -} - -//获取ingress详情 -func (i *ingress) GetIngresstDetail(ingressName, namespace string) (ingress *nwv1.Ingress, err error) { - ingress, err = K8s.ClientSet.NetworkingV1().Ingresses(namespace).Get(context.TODO(), ingressName, metav1.GetOptions{}) - if err != nil { - logger.Error(errors.New("获取Ingress详情失败, " + err.Error())) - return nil, errors.New("获取Ingress详情失败, " + err.Error()) - } - - return ingress, nil -} - -//创建ingress -func (i *ingress) CreateIngress(data *IngressCreate) (err error) { - //声明nwv1.IngressRule和nwv1.HTTPIngressPath变量,后面组装数据于鏊用到 - var ingressRules []nwv1.IngressRule - var httpIngressPATHs []nwv1.HTTPIngressPath - //将data中的数据组装成nwv1.Ingress对象 - ingress := &nwv1.Ingress{ - ObjectMeta: metav1.ObjectMeta{ - Name: data.Name, - Namespace: data.Namespace, - Labels: data.Label, - }, - Status: nwv1.IngressStatus{}, - } - //第一层for循环是将host组装成nwv1.IngressRule类型的对象 - // 一个host对应一个ingressrule,每个ingressrule中包含一个host和多个path - for key, value := range data.Hosts { - ir := nwv1.IngressRule{ - Host: key, - //这里现将nwv1.HTTPIngressRuleValue类型中的Paths置为空,后面组装好数据再赋值 - IngressRuleValue: nwv1.IngressRuleValue{ - HTTP: &nwv1.HTTPIngressRuleValue{Paths: nil}, - }, - } - //第二层for循环是将path组装成nwv1.HTTPIngressPath类型的对象 - for _, httpPath := range value { - hip := nwv1.HTTPIngressPath{ - Path: httpPath.Path, - PathType: &httpPath.PathType, - Backend: nwv1.IngressBackend{ - Service: &nwv1.IngressServiceBackend{ - Name: httpPath.ServiceName, - Port: nwv1.ServiceBackendPort{ - Number: httpPath.ServicePort, - }, - }, - }, - } - //将每个hip对象组装成数组 - httpIngressPATHs = append(httpIngressPATHs, hip) - } - //给Paths赋值,前面置为空了 - ir.IngressRuleValue.HTTP.Paths = httpIngressPATHs - //将每个ir对象组装成数组,这个ir对象就是IngressRule,每个元素是一个host和多个path - ingressRules = append(ingressRules, ir) - } - //将ingressRules对象加入到ingress的规则中 - ingress.Spec.Rules = ingressRules - //创建ingress - _, err = K8s.ClientSet.NetworkingV1().Ingresses(data.Namespace).Create(context.TODO(), ingress, metav1.CreateOptions{}) - if err != nil { - logger.Error(errors.New("创建Ingress失败, " + err.Error())) - return errors.New("创建Ingress失败, " + err.Error()) - } - - return nil -} - -//删除ingress -func (i *ingress) DeleteIngress(ingressName, namespace string) (err error) { - err = K8s.ClientSet.NetworkingV1().Ingresses(namespace).Delete(context.TODO(), ingressName, metav1.DeleteOptions{}) - if err != nil { - logger.Error(errors.New("删除Ingress失败, " + err.Error())) - return errors.New("删除Ingress失败, " + err.Error()) - } - - return nil -} - -//更新ingress -func (i *ingress) UpdateIngress(namespace, content string) (err error) { - var ingress = &nwv1.Ingress{} - - err = json.Unmarshal([]byte(content), ingress) - if err != nil { - logger.Error(errors.New("反序列化失败, " + err.Error())) - return errors.New("反序列化失败, " + err.Error()) - } - - _, err = K8s.ClientSet.NetworkingV1().Ingresses(namespace).Update(context.TODO(), ingress, metav1.UpdateOptions{}) - if err != nil { - logger.Error(errors.New("更新ingress失败, " + err.Error())) - return errors.New("更新ingress失败, " + err.Error()) - } - return nil -} - -func (i *ingress) toCells(std []nwv1.Ingress) []DataCell { - cells := make([]DataCell, len(std)) - for i := range std { - cells[i] = ingressCell(std[i]) - } - return cells -} - -func (i *ingress) fromCells(cells []DataCell) []nwv1.Ingress { - ingresss := make([]nwv1.Ingress, len(cells)) - for i := range cells { - ingresss[i] = nwv1.Ingress(cells[i].(ingressCell)) - } - - return ingresss -} diff --git a/service/init.go b/service/init.go deleted file mode 100644 index c5c0aac..0000000 --- a/service/init.go +++ /dev/null @@ -1,32 +0,0 @@ -package service - -import ( - "dkube/config" - "github.com/wonderivan/logger" - "k8s.io/client-go/kubernetes" - "k8s.io/client-go/tools/clientcmd" -) - -//用于初始化k8s clientset -var K8s k8s - -type k8s struct { - ClientSet *kubernetes.Clientset -} - -//初始化方法 -func (k *k8s) Init() { - conf, err := clientcmd.BuildConfigFromFlags("", config.Kubeconfig) - if err != nil { - panic("获取k8s clinet配置失败," + err.Error()) - } - - clientset, err := kubernetes.NewForConfig(conf) - if err != nil { - panic("创建k8s clinet失败," + err.Error()) - } else { - logger.Info("k8s client 初始化成功") - } - - k.ClientSet = clientset -} diff --git a/service/pod.go b/service/pod.go deleted file mode 100644 index 3567115..0000000 --- a/service/pod.go +++ /dev/null @@ -1,190 +0,0 @@ -package service - -import ( - "bytes" - "context" - "dkube/config" - "encoding/json" - "errors" - "github.com/wonderivan/logger" - "io" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -var Pod pod - -type pod struct{} - -// PodsResp 定义列表的返回内容,Items是Pod的元素列表,Total是元素数量 -type PodsResp struct { - Total int `json:"total"` - Items []corev1.Pod `json:"items"` -} - -//声明类型 -type PodsNp struct { - Namespace string - PodNum int -} - -// GetPods 获取Pod列表,支持过滤、排序、分页 -//context.TODD()用于声明一个空的context上下文,用于List方法内设置这个请求的超时(源码),这里是常用用法 -//metav1.ListOptions{}用于过滤List数据,如使用label,field等 -func (p *pod) GetPods(filterName, namespace string, limit, page int) (podsResp *PodsResp, err error) { - podList, err := K8s.ClientSet.CoreV1().Pods(namespace).List(context.TODO(), metav1.ListOptions{}) - if err != nil { - //打印日志,排错 - logger.Info("获取Pod列表失败," + err.Error()) - //返回给上一层,最终返回给前端,前端打印出该error - return nil, errors.New("获取Pod列表失败," + err.Error()) - } - - //实例化dataSelector结构体,组装数据 - selectableData := &dataSelector{ - GenericDataList: p.toCells(podList.Items), - DataSelect: &DataSelectQuery{ - Filter: &FilterQuery{Name: filterName}, - Paginate: &PaginateQuery{ - Limit: limit, - Page: page, - }, - }, - } - - //先过滤 - filtered := selectableData.Filter() - total := len(filtered.GenericDataList) - //排序和分页 - data := filtered.Sort().Paginate() - - //将DataCell类型转换成Pod - pods := p.fromCells(data.GenericDataList) - - return &PodsResp{ - Total: total, - Items: pods, - }, nil - -} - -//获取Pod详情 -func (p *pod) GetPodDetail(podName, namespace string) (pod *corev1.Pod, err error) { - pod, err = K8s.ClientSet.CoreV1().Pods(namespace).Get(context.TODO(), podName, metav1.GetOptions{}) - if err != nil { - logger.Error("获取Pod详情失败," + err.Error()) - return nil, errors.New("获取Pod详情失败," + err.Error()) - } - return pod, nil -} - -//删除Pod -func (p *pod) DeletePod(podName, namespace string) (err error) { - err = K8s.ClientSet.CoreV1().Pods(namespace).Delete(context.TODO(), podName, metav1.DeleteOptions{}) - if err != nil { - logger.Error("删除Pod失败," + err.Error()) - return errors.New("删除Pod失败," + err.Error()) - } - return nil -} - -//更新Pod -func (p *pod) UpdatePod(namespace, content string) (err error) { - pod := &corev1.Pod{} - //将json反序列化为pod类型 - err = json.Unmarshal([]byte(content), pod) - if err != nil { - logger.Error("反序列化失败," + err.Error()) - return errors.New("反序列化失败," + err.Error()) - } - _, err = K8s.ClientSet.CoreV1().Pods(namespace).Update(context.TODO(), pod, metav1.UpdateOptions{}) - if err != nil { - logger.Error("更新Pod失败," + err.Error()) - return errors.New("更新Pod失败," + err.Error()) - } - return nil -} - -//获取Pod容器名列表 -func (p *pod) GetPodContainer(podName, namespace string) (containers []string, err error) { - //获取Pod详情 - pod, err := p.GetPodDetail(podName, namespace) - if err != nil { - return nil, err - } - //从Pod对象中拿到容器名 - for _, container := range pod.Spec.Containers { - containers = append(containers, container.Name) - } - return containers, nil -} - -//获取Pod内容器日志 -func (p *pod) GetPodLog(containerName, podName, namespace string) (log string, err error) { - //设置日志的配置,容器名、获取内容的配置 - lineLimit := int64(config.PodLogTailLine) - option := &corev1.PodLogOptions{ - Container: containerName, - TailLines: &lineLimit, - } - //获取request实例 - req := K8s.ClientSet.CoreV1().Pods(namespace).GetLogs(podName, option) - //发起request请求,返回一个io.ReadCloser类型(等同于response.body) - podLogs, err := req.Stream(context.TODO()) - if err != nil { - logger.Error(errors.New("获取PodLogs失败," + err.Error())) - return "", errors.New("获取PodLogs失败," + err.Error()) - } - defer podLogs.Close() //处理完关闭 - //将response body写入到缓冲区,目的是为了转成string返回 - buf := new(bytes.Buffer) - _, err = io.Copy(buf, podLogs) - if err != nil { - logger.Error(errors.New("获取PodLogs失败," + err.Error())) - return "", errors.New("获取PodLogs失败," + err.Error()) - } - - return buf.String(), nil -} - -//获取每个namespace的pod数量 -func (p *pod) GetPodNumPerNp() (podsNps []*PodsNp, err error) { - //获取namespace列表 - namespaceList, err := K8s.ClientSet.CoreV1().Namespaces().List(context.TODO(), metav1.ListOptions{}) - if err != nil { - return nil, err - } - for _, namespace := range namespaceList.Items { - //获取pod列表 - podList, err := K8s.ClientSet.CoreV1().Pods(namespace.Name).List(context.TODO(), metav1.ListOptions{}) - if err != nil { - return nil, err - } - //组装数据 - podsNp := &PodsNp{ - Namespace: namespace.Name, - PodNum: len(podList.Items), - } - //添加到podsNps数组中 - podsNps = append(podsNps, podsNp) - } - return podsNps, nil -} - -//类型转换的方法 corev1.Pod -> DataCell, DataCell --> corev1.Pod -func (p *pod) toCells(pods []corev1.Pod) []DataCell { - cells := make([]DataCell, len(pods)) - for i := range pods { - cells[i] = podCell(pods[i]) - } - return cells -} - -func (p *pod) fromCells(cells []DataCell) []corev1.Pod { - pods := make([]corev1.Pod, len(cells)) - for i := range cells { - //cells[i].(podCell)是将DataCell类型转成podCell类型 - pods[i] = corev1.Pod(cells[i].(podCell)) - } - return pods -} diff --git a/service/service.go b/service/service.go deleted file mode 100644 index 4c35b0a..0000000 --- a/service/service.go +++ /dev/null @@ -1,161 +0,0 @@ -package service - -import ( - "context" - "encoding/json" - "errors" - "github.com/wonderivan/logger" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/intstr" -) - -var Servicev1 servicev1 - -type servicev1 struct{} - -type ServicesResp struct { - Items []corev1.Service `json:"items"` - Total int `json:"total"` -} - -type ServiceCreate struct { - Name string `json:"name"` - Namespace string `json:"namespace"` - Type string `json:"type"` - ContainerPort int32 `json:"container_port"` - Port int32 `json:"port"` - NodePort int32 `json:"node_port"` - Label map[string]string `json:"label"` -} - -//获取service列表,支持过滤、排序、分页 -func (s *servicev1) GetServices(filterName, namespace string, limit, page int) (servicesResp *ServicesResp, err error) { - //获取serviceList类型的service列表 - serviceList, err := K8s.ClientSet.CoreV1().Services(namespace).List(context.TODO(), metav1.ListOptions{}) - if err != nil { - logger.Error(errors.New("获取Service列表失败, " + err.Error())) - return nil, errors.New("获取Service列表失败, " + err.Error()) - } - //将serviceList中的service列表(Items),放进dataselector对象中,进行排序 - selectableData := &dataSelector{ - GenericDataList: s.toCells(serviceList.Items), - DataSelect: &DataSelectQuery{ - Filter: &FilterQuery{Name: filterName}, - Paginate: &PaginateQuery{ - Limit: limit, - Page: page, - }, - }, - } - - filtered := selectableData.Filter() - total := len(filtered.GenericDataList) - data := filtered.Sort().Paginate() - - //将[]DataCell类型的service列表转为v1.service列表 - services := s.fromCells(data.GenericDataList) - - return &ServicesResp{ - Items: services, - Total: total, - }, nil -} - -//获取service详情 -func (s *servicev1) GetServicetDetail(serviceName, namespace string) (service *corev1.Service, err error) { - service, err = K8s.ClientSet.CoreV1().Services(namespace).Get(context.TODO(), serviceName, metav1.GetOptions{}) - if err != nil { - logger.Error(errors.New("获取Service详情失败, " + err.Error())) - return nil, errors.New("获取Service详情失败, " + err.Error()) - } - - return service, nil -} - -//创建service,,接收ServiceCreate对象 -func (s *servicev1) CreateService(data *ServiceCreate) (err error) { - //将data中的数据组装成corev1.Service对象 - service := &corev1.Service{ - //ObjectMeta中定义资源名、命名空间以及标签 - ObjectMeta: metav1.ObjectMeta{ - Name: data.Name, - Namespace: data.Namespace, - Labels: data.Label, - }, - //Spec中定义类型,端口,选择器 - Spec: corev1.ServiceSpec{ - Type: corev1.ServiceType(data.Type), - Ports: []corev1.ServicePort{ - { - Name: "http", - Port: data.Port, - Protocol: "TCP", - TargetPort: intstr.IntOrString{ - Type: 0, - IntVal: data.ContainerPort, - }, - }, - }, - Selector: data.Label, - }, - } - //默认ClusterIP,这里是判断NodePort,添加配置 - if data.NodePort != 0 && data.Type == "NodePort" { - service.Spec.Ports[0].NodePort = data.NodePort - } - //创建Service - _, err = K8s.ClientSet.CoreV1().Services(data.Namespace).Create(context.TODO(), service, metav1.CreateOptions{}) - if err != nil { - logger.Error(errors.New("创建Service失败, " + err.Error())) - return errors.New("创建Service失败, " + err.Error()) - } - - return nil -} - -//删除service -func (s *servicev1) DeleteService(serviceName, namespace string) (err error) { - err = K8s.ClientSet.CoreV1().Services(namespace).Delete(context.TODO(), serviceName, metav1.DeleteOptions{}) - if err != nil { - logger.Error(errors.New("删除Service失败, " + err.Error())) - return errors.New("删除Service失败, " + err.Error()) - } - - return nil -} - -//更新service -func (s *servicev1) UpdateService(namespace, content string) (err error) { - var service = &corev1.Service{} - - err = json.Unmarshal([]byte(content), service) - if err != nil { - logger.Error(errors.New("反序列化失败, " + err.Error())) - return errors.New("反序列化失败, " + err.Error()) - } - - _, err = K8s.ClientSet.CoreV1().Services(namespace).Update(context.TODO(), service, metav1.UpdateOptions{}) - if err != nil { - logger.Error(errors.New("更新service失败, " + err.Error())) - return errors.New("更新service失败, " + err.Error()) - } - return nil -} - -func (s *servicev1) toCells(std []corev1.Service) []DataCell { - cells := make([]DataCell, len(std)) - for i := range std { - cells[i] = serviceCell(std[i]) - } - return cells -} - -func (s *servicev1) fromCells(cells []DataCell) []corev1.Service { - services := make([]corev1.Service, len(cells)) - for i := range cells { - services[i] = corev1.Service(cells[i].(serviceCell)) - } - - return services -}