【k8s多集群管理平台开发实践】十、client-go实现读取pvc列表、pv列表、storageclass列表

文章目录

        • 简介
      • 一.k8s读取pvc列表
        • 1.1.controllers控制器代码
        • 1.2.models模型代码
      • 二.k8s读取pv列表
        • 2.1.controllers控制器代码
        • 2.2.models模分代码
      • 三.k8s读取storageclass列表
        • 3.1.controllers控制器代码
        • 3.2.models模型代码
      • 四.路由设置
        • 4.1.路由设置
      • 五.前端代码
        • 5.1.pvc列表的html代码
        • 5.2.pv列表的html代码
        • 5.3.storageclass列表的html代码
      • 六.完整代码
        • 6.1.控制器storage.go的完整代码
        • 6.2.模型storageModel.go的完整代码
      • 七.效果图

简介

本章节主要讲解通过client-go实现读取pvc的列表、pv的列表、storageclass的列表,并通过前端html页面进行展示,其中包含控制器这部分的代码,模型这部分代码,以及前端的html代码。

一.k8s读取pvc列表

1.1.controllers控制器代码

通过传递集群id、命名空间、pvc名称、标签来进行过滤,并调用模型代码中PersistentVolumeClaimList函数来读取列表

func (this *StorageController) PvcList() {clusterId := this.GetString("clusterId")nameSpace := this.GetString("nameSpace")pvcName := this.GetString("pvcName")    //pvc名称labels := this.GetString("labels")labelsKV := strings.Split(labels, ":")var labelsKey, labelsValue stringif len(labelsKV) == 2 {labelsKey = labelsKV[0]labelsValue = labelsKV[1]}//读取pvc列表pvcList, err := m.PersistentVolumeClaimList(clusterId, nameSpace, pvcName, labelsKey, labelsValue)msg := "success"code := 0count := len(pvcList)if err != nil {log.Println(err)msg = err.Error()code = -1}this.Data["json"] = &map[string]interface{}{"code": code, "msg": msg, "count": count, "data": &pvcList}this.ServeJSON()
}
1.2.models模型代码

先定义一个结构体PersistentVolumeClaim,然后定义一个结构体数组var bbb = make([]PersistentVolumeClaim, 0),并循环读取Items中的数据并赋值到结构体,然后再追加到数组中bbb中。

type PersistentVolumeClaim struct {PvcName      string `json:"pvcName"`NameSpace    string `json:"nameSpace"`Capacity     string `json:"capacity"`     //容量AccessMode   string `json:"accessMode"`   //访问模式StorageClass string `json:"storageClass"` //存储类型Status       string `json:"status"`       //状态VolumeName   string `json:"volumeName"`   //关联存储卷Labels       string `json:"labels"`Annotations  string `json:"annotations"` //注解CreateTime   string `json:"createTime"`
}func PersistentVolumeClaimList(kubeconfig, namespace, pvcName, labelsKey, labelsValue string) ([]PersistentVolumeClaim, error) {clientset := common.ClientSet(kubeconfig)if namespace == "" {//namespace = corev1.NamespaceDefaultnamespace = corev1.NamespaceAll}//设置ListOptionsvar listOptions = metav1.ListOptions{}if labelsKey != "" && labelsValue != "" {listOptions = metav1.ListOptions{LabelSelector: fmt.Sprintf("%s=%s", labelsKey, labelsValue),}}//通过api读取pvc列表pvcList, err := clientset.CoreV1().PersistentVolumeClaims(namespace).List(context.TODO(), listOptions)if err != nil {log.Printf("list deployment error, err:%v\n", err)}var bbb = make([]PersistentVolumeClaim, 0)for _, pvc := range pvcList.Items {//根据pvc名称过滤if pvcName != "" {if !strings.Contains(pvc.Name, pvcName) {continue}}var labelsStr stringfor kk, vv := range pvc.Labels {labelsStr += fmt.Sprintf("%s:%s,", kk, vv)}var annotationsStr stringfor k2, v2 := range pvc.Annotations {annotationsStr += fmt.Sprintf("%s:%s,", k2, v2)}var accessModeStr stringfor _, v3 := range pvc.Spec.AccessModes {accessModeStr += fmt.Sprintf("%s", v3)}//赋值到结构体Items := &PersistentVolumeClaim{PvcName:      pvc.Name,NameSpace:    pvc.Namespace,Capacity:     pvc.Status.Capacity.Storage().String(),AccessMode:   accessModeStr,StorageClass: *pvc.Spec.StorageClassName,Status:       fmt.Sprintf("%s", pvc.Status.Phase),VolumeName:   pvc.Spec.VolumeName,Labels:       labelsStr,Annotations:  annotationsStr,CreateTime:   pvc.CreationTimestamp.Format("2006-01-02 15:04:05"),}//追加到数组bbb = append(bbb, *Items)}return bbb, err
}

二.k8s读取pv列表

2.1.controllers控制器代码

通过传递集群id,并调用模型代码中PvList函数来读取列表

func (this *StorageController) PvList() {clusterId := this.GetString("clusterId")List, err := m.PersistentVolumeList(clusterId)msg := "success"code := 0count := len(List)if err != nil {log.Println(err)msg = err.Error()code = -1}this.Data["json"] = &map[string]interface{}{"code": code, "msg": msg, "count": count, "data": &List}this.ServeJSON()
}
2.2.models模分代码

定义结构体PersistentVolume,在PersistentVolumeList函数中,通过clientset.CoreV1().PersistentVolumes().List读取pv列表,并循环赋值到结构体Items := &PersistentVolume,并追加到结构体数组中var bbb = make([]PersistentVolume, 0)


type PersistentVolume struct {PvName          string `json:"pvName"`  //pv名称Capacity        string `json:"capacity"`        //容量AccessMode      string `json:"accessMode"`      //访问模式PvReclaimPolicy string `json:"pvReclaimPolicy"` //回收策略StorageClass    string `json:"storageClass"`    //存储类型Status          string `json:"status"`          //状态ClaimRef        string `json:"claimRef"`        //绑定存储申明Labels          string `json:"labels"`Annotations     string `json:"annotations"` //注解CreateTime      string `json:"createTime"`
}func PersistentVolumeList(kubeconfig string) ([]PersistentVolume, error) {clientset := common.ClientSet(kubeconfig)//api读取pv列表pvList, err := clientset.CoreV1().PersistentVolumes().List(context.TODO(), metav1.ListOptions{})if err != nil {log.Printf("list deployment error, err:%v\n", err)}var bbb = make([]PersistentVolume, 0)//循环提取信息并赋值到结构体Itemsfor _, pv := range pvList.Items {var labelsStr stringfor kk, vv := range pv.Labels {labelsStr += fmt.Sprintf("%s:%s,", kk, vv)}var annotationsStr stringfor k2, v2 := range pv.Annotations {annotationsStr += fmt.Sprintf("%s:%s,", k2, v2)}var accessModeStr stringfor _, v3 := range pv.Spec.AccessModes {accessModeStr += fmt.Sprintf("%s", v3)}Items := &PersistentVolume{PvName:          pv.Name,Capacity:        pv.Spec.Capacity.Storage().String(),AccessMode:      accessModeStr,PvReclaimPolicy: fmt.Sprintf("%s", pv.Spec.PersistentVolumeReclaimPolicy),StorageClass:    pv.Spec.StorageClassName,Status:          fmt.Sprintf("%s", pv.Status.Phase),ClaimRef:        fmt.Sprintf("命名空间:%s<br>名称:%s", pv.Spec.ClaimRef.Namespace, pv.Spec.ClaimRef.Name),Labels:          labelsStr,Annotations:     annotationsStr,CreateTime:      pv.CreationTimestamp.Format("2006-01-02 15:04:05"),}//追加到数组中bbb = append(bbb, *Items)}return bbb, err
}

三.k8s读取storageclass列表

3.1.controllers控制器代码

通过传递集群id,调用StorageclassList函数来读取存储类storageclass的列表


func (this *StorageController) StorageclassList() {clusterId := this.GetString("clusterId")List, err := m.StorageclassList(clusterId)msg := "success"code := 0count := len(List)if err != nil {log.Println(err)msg = err.Error()code = -1}this.Data["json"] = &map[string]interface{}{"code": code, "msg": msg, "count": count, "data": &List}this.ServeJSON()
}
3.2.models模型代码

先定义结构体Storageclass,将控制器传递过来的集群id读取对应集群存储类数据,然后赋值到结构体,并追加到结构体数组var bbb = make([]Storageclass, 0).

type Storageclass struct {StorageclassName string `json:"storageclassName"`Provisioner      string `json:"provisioner"`   //提供者Parameters       string `json:"parameters"`    //参数ReclaimPolicy    string `json:"reclaimPolicy"` //回收策略Labels           string `json:"labels"` //标签Annotations      string `json:"annotations"` //注解CreateTime       string `json:"createTime"`
}func StorageclassList(kubeconfig string) ([]Storageclass, error) {clientset := common.ClientSet(kubeconfig)storageclassList, err := clientset.StorageV1().StorageClasses().List(context.TODO(), metav1.ListOptions{})if err != nil {log.Printf("list deployment error, err:%v\n", err)}var bbb = make([]Storageclass, 0)for _, sc := range storageclassList.Items {var parms stringfor kk, vv := range sc.Parameters {parms += fmt.Sprintf("%s:%s,", kk, vv)}var labelsStr stringfor kk, vv := range sc.Labels {labelsStr += fmt.Sprintf("%s:%s,", kk, vv)}var annotationsStr stringfor k2, v2 := range sc.Annotations {annotationsStr += fmt.Sprintf("%s:%s,", k2, v2)}Items := &Storageclass{StorageclassName: sc.Name,Provisioner:      sc.Provisioner,Parameters:       parms,ReclaimPolicy:    fmt.Sprintf("%s", *sc.ReclaimPolicy),Labels:           labelsStr,Annotations:      annotationsStr,CreateTime:       sc.CreationTimestamp.Format("2006-01-02 15:04:05"),}bbb = append(bbb, *Items)}return bbb, err
}

四.路由设置

4.1.路由设置

将以下代码放到routers/route.go中

	//storageclassbeego.Router("/storage/v1/StorageclassList", &controllers.StorageController{}, "*:StorageclassList")//pvbeego.Router("/storage/v1/PvList", &controllers.StorageController{}, "*:PvList")//pvcbeego.Router("/storage/v1/PvcList", &controllers.StorageController{}, "*:PvcList")

五.前端代码

5.1.pvc列表的html代码

5.1 pvcList.html,放到views/front/page/xkube下

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>pvc列表</title><meta name="renderer" content="webkit"><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"><link rel="stylesheet" href="/lib/layui-v2.6.3/css/layui.css" media="all"><link rel="stylesheet" href="/css/public.css" media="all"><script type="text/javascript" src="/lib/jquery-3.4.1/jquery-3.4.1.min.js"></script><script src="/lib/layui-v2.6.3/layui.js" charset="utf-8"></script><script src="/js/xkube.js?v=1" charset="utf-8"></script><script src="/js/lay-config.js?v=1.0.4" charset="utf-8"></script><style type="text/css">.layui-table-cell {height: auto;line-height: 22px !important;text-overflow: inherit;overflow: visible;white-space: normal;}.layui-table-cell .layui-table-tool-panel li {word-break: break-word;}
</style>
</head>
<body>
<div class="layuimini-container"><div class="layuimini-main"><table class="layui-table" id="currentTableId" lay-filter="currentTableFilter"></table><script type="text/html" id="currentTableBar"><a class="layui-btn layui-btn-normal layui-btn-sm" lay-event="viewYaml">查看yaml</a></script></div>
</div>
</body>
<script type="text/html" id="tagTpl">{{# if (d.labels != "") { }}{{# layui.each(d.labels.split(','), function(index, item){ }}{{# if(index == 0) { }}<span>{{ item }}</span>{{# }else{ }}<br><span>{{ item }}</span>{{# } }}  {{# });  }}{{# }else{  }}<span></span>{{# } }}
</script>	
<script type="text/html" id="annotationsTpl">{{# if (d.annotations != "") { }}{{# layui.each(d.annotations.split(','), function(index, item){ }}{{# if(index == 0) { }}<span>{{ item }}</span>{{# }else{ }}<br><span>{{ item }}</span>{{# } }}  {{# });  }}{{# }else{  }}<span></span>{{# } }}
</script>	
<script>var clusterId = getQueryString("clusterId");
if (clusterId == null) {clusterId = getCookie("clusterId")
}layui.use(['form', 'table','miniTab'], function () {var $ = layui.jquery,form = layui.form,table = layui.table;miniTab = layui.miniTab,miniTab.listen();table.render({elem: '#currentTableId',url: '/storage/v1/PvcList?clusterId='+clusterId,toolbar: '#toolbarDemo',defaultToolbar: ['filter', 'exports', 'print', {title: '提示',layEvent: 'LAYTABLE_TIPS',icon: 'layui-icon-tips'}],parseData: function(res) { //实现加载全部数据后再分页if(this.page.curr) {result=res.data.slice(this.limit*(this.page.curr-1),this.limit*this.page.curr);}else{result=res.data.slice(0,this.limit);}return {"code": res.code,"msg":'',"count":res.count,"data":result};},cols: [[{field: 'pvcName',title: '名称', sort: true},{field: 'nameSpace',title: '命名空间', sort: true},{field: 'capacity',title: '容量', sort: true},{field: 'accessMode',title: '访问模式', sort: true},{field: 'storageClass',title: '存储类型', sort: true},{field: 'status', title: '状态', sort: true},{field: 'volumeName', title: '关联存储卷', sort: true},{field: 'annotations', title: '注解', sort: true,templet: '#annotationsTpl',hide:true},{field: 'labels', title: '标签', sort: true,templet: '#tagTpl',hide:true},{field: 'createTime',title: '创建时间'},{title: '操作', minWidth:250,  toolbar: '#currentTableBar', align: "center"}]],//size:'lg',limits: [25, 50, 100],limit: 25,page: true});table.on('tool(currentTableFilter)', function (obj) {var data = obj.data;if (obj.event === 'viewYaml') {var index = layer.open({title: 'yaml',type: 2,shade: 0.2,maxmin:true,shadeClose: true,area: ['50%', '92%'],content: '/page/xkube/pvcYaml.html?clusterId='+clusterId+'&nameSpace='+data.nameSpace+'&pvcName='+data.pvcName,});$(window).on("resize", function () {layer.full(index);});return false;}});});
</script>
</html>
5.2.pv列表的html代码

5.2 pvList.html,放到views/front/page/xkube下

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>pv列表</title><meta name="renderer" content="webkit"><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"><link rel="stylesheet" href="/lib/layui-v2.6.3/css/layui.css" media="all"><link rel="stylesheet" href="/css/public.css" media="all"><script type="text/javascript" src="/lib/jquery-3.4.1/jquery-3.4.1.min.js"></script><script src="/lib/layui-v2.6.3/layui.js" charset="utf-8"></script><script src="/js/xkube.js?v=1" charset="utf-8"></script><script src="/js/lay-config.js?v=1.0.4" charset="utf-8"></script>
<style type="text/css">.layui-table-cell {height: auto;line-height: 22px !important;text-overflow: inherit;overflow: visible;white-space: normal;}.layui-table-cell .layui-table-tool-panel li {word-break: break-word;}
</style>
</head>
<body>
<div class="layuimini-container"><div class="layuimini-main"><table class="layui-table" id="currentTableId" lay-filter="currentTableFilter"></table><script type="text/html" id="currentTableBar"><a class="layui-btn layui-btn-normal layui-btn-sm" lay-event="viewYaml">查看yaml</a></script></div>
</div>
</body><script type="text/html" id="tagTpl">{{# if (d.labels != "") { }}{{# layui.each(d.labels.split(','), function(index, item){ }}{{# if(index == 0) { }}<span>{{ item }}</span>{{# }else{ }}<br><span>{{ item }}</span>{{# } }}  {{# });  }}{{# }else{  }}<span></span>{{# } }}
</script>	
<script type="text/html" id="annotationsTpl">{{# if (d.annotations != "") { }}{{# layui.each(d.annotations.split(','), function(index, item){ }}{{# if(index == 0) { }}<span>{{ item }}</span>{{# }else{ }}<br><span>{{ item }}</span>{{# } }}  {{# });  }}{{# }else{  }}<span></span>{{# } }}
</script>	
<script>var clusterId = getQueryString("clusterId");
if (clusterId == null) {clusterId = getCookie("clusterId")
}layui.use(['form', 'table','miniTab'], function () {var $ = layui.jquery,form = layui.form,table = layui.table;miniTab = layui.miniTab,miniTab.listen();table.render({elem: '#currentTableId',url: '/storage/v1/PvList?clusterId='+clusterId,toolbar: '#toolbarDemo',defaultToolbar: ['filter', 'exports', 'print', {title: '提示',layEvent: 'LAYTABLE_TIPS',icon: 'layui-icon-tips'}],parseData: function(res) { //实现加载全部数据后再分页if(this.page.curr) {result=res.data.slice(this.limit*(this.page.curr-1),this.limit*this.page.curr);}else{result=res.data.slice(0,this.limit);}return {"code": res.code,"msg":'',"count":res.count,"data":result};},cols: [[//{type: "checkbox", width: 50},{field: 'pvName',title: '名称', sort: true},{field: 'capacity',title: '容量', sort: true},{field: 'accessMode', title: '访问模式', sort: true},{field: 'pvReclaimPolicy',title: '回收策略', sort: true},{field: 'storageClass', title: '存储类型', sort: true},{field: 'status',title: '状态', sort: true},{field: 'claimRef', title: '存储申明', sort: true},{field: 'annotations', title: '注解', sort: true,templet: '#annotationsTpl',hide:true},{field: 'labels', title: '标签', sort: true,templet: '#tagTpl',hide:true},{field: 'createTime', title: '创建时间'},{title: '操作', minWidth:250, toolbar: '#currentTableBar', align: "center"}]],//size:'lg',limits: [25, 50, 100],limit: 25,page: true});table.on('tool(currentTableFilter)', function (obj) {var data = obj.data;if (obj.event === 'viewYaml') {var index = layer.open({title: 'yaml',type: 2,shade: 0.2,maxmin:true,shadeClose: true,area: ['50%', '92%'],content: '/page/xkube/pvYaml.html?clusterId='+clusterId+'&pvName='+data.pvName,});$(window).on("resize", function () {layer.full(index);});return false;}});});
</script>
</html>
5.3.storageclass列表的html代码

5.3 storageclassList.html,放到views/front/page/xkube下

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>storageclass列表</title><meta name="renderer" content="webkit"><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"><link rel="stylesheet" href="/lib/layui-v2.6.3/css/layui.css" media="all"><link rel="stylesheet" href="/css/public.css" media="all"><script type="text/javascript" src="/lib/jquery-3.4.1/jquery-3.4.1.min.js"></script><script src="/lib/layui-v2.6.3/layui.js" charset="utf-8"></script><script src="/js/xkube.js?v=1" charset="utf-8"></script><script src="/js/lay-config.js?v=1.0.4" charset="utf-8"></script><style type="text/css">.layui-table-cell {height: auto;line-height: 22px !important;text-overflow: inherit;overflow: visible;white-space: normal;}.layui-table-cell .layui-table-tool-panel li {word-break: break-word;}
</style>
</head>
<body>
<div class="layuimini-container"><div class="layuimini-main"><table class="layui-table" id="currentTableId" lay-filter="currentTableFilter"></table><script type="text/html" id="currentTableBar"><a class="layui-btn layui-btn-normal layui-btn-sm" lay-event="viewYaml">查看yaml</a></script></div>
</div>
</body><script type="text/html" id="parmsTpl">{{# if (d.parameters != "") { }}{{# layui.each(d.parameters.split(','), function(index, item){ }}{{# if(index == 0) { }}<span>{{ item }}</span>{{# }else{ }}<br><span>{{ item }}</span>{{# } }}  {{# });  }}{{# }else{  }}<span></span>{{# } }}
</script>	
<script>var clusterId = getQueryString("clusterId");
if (clusterId == null) {clusterId = getCookie("clusterId")
}layui.use(['form', 'table','miniTab'], function () {var $ = layui.jquery,form = layui.form,table = layui.table;miniTab = layui.miniTab,miniTab.listen();table.render({elem: '#currentTableId',url: '/storage/v1/StorageclassList?clusterId='+clusterId,toolbar: '#toolbarDemo',defaultToolbar: ['filter', 'exports', 'print', {title: '提示',layEvent: 'LAYTABLE_TIPS',icon: 'layui-icon-tips'}],parseData: function(res) { //实现加载全部数据后再分页if(this.page.curr) {result=res.data.slice(this.limit*(this.page.curr-1),this.limit*this.page.curr);}else{result=res.data.slice(0,this.limit);}return {"code": res.code,"msg":'',"count":res.count,"data":result};},cols: [[//{type: "checkbox", width: 50},{field: 'storageclassName',title: '名称', sort: true},{field: 'provisioner', title: '提供者', sort: true},{field: 'parameters',title: '参数', sort: true,templet: '#parmsTpl'},{field: 'reclaimPolicy', title: '回收策略', sort: true},{field: 'createTime', title: '创建时间'},{title: '操作', minWidth:250, toolbar: '#currentTableBar', align: "center"}]],//size:'lg',limits: [25, 50, 100],limit: 25,page: true});table.on('tool(currentTableFilter)', function (obj) {var data = obj.data;if (obj.event === 'viewYaml') {var index = layer.open({title: 'yaml',type: 2,shade: 0.2,maxmin:true,shadeClose: true,area: ['50%', '92%'],content: '/page/xkube/storageclassYaml.html?clusterId='+clusterId+'&storageclassName='+data.storageclassName,});$(window).on("resize", function () {layer.full(index);});return false;}});});
</script>
</html>

六.完整代码

6.1.控制器storage.go的完整代码

6.1 storage.go,放到contrillers下

// storage.go
package controllersimport (//"encoding/json""log"//"myk8s/common"m "myk8s/models""strings"beego "github.com/beego/beego/v2/server/web""github.com/tidwall/gjson"
)type StorageController struct {beego.Controller
}func (this *StorageController) StorageclassList() {clusterId := this.GetString("clusterId")List, err := m.StorageclassList(clusterId)msg := "success"code := 0count := len(List)if err != nil {log.Println(err)msg = err.Error()code = -1}this.Data["json"] = &map[string]interface{}{"code": code, "msg": msg, "count": count, "data": &List}this.ServeJSON()
}func (this *StorageController) PvList() {clusterId := this.GetString("clusterId")List, err := m.PersistentVolumeList(clusterId)msg := "success"code := 0count := len(List)if err != nil {log.Println(err)msg = err.Error()code = -1}this.Data["json"] = &map[string]interface{}{"code": code, "msg": msg, "count": count, "data": &List}//this.Data["json"] = &datasthis.ServeJSON()
}func (this *StorageController) PvcList() {clusterId := this.GetString("clusterId")nameSpace := this.GetString("nameSpace")pvcName := this.GetString("pvcName")labels := this.GetString("labels")if this.Ctx.Input.Method() == "POST" {gp := gjson.ParseBytes(this.Ctx.Input.RequestBody)pvcName = gp.Get("pvcName").String()nameSpace = gp.Get("nameSpace").String()}labelsKV := strings.Split(labels, ":")var labelsKey, labelsValue stringif len(labelsKV) == 2 {labelsKey = labelsKV[0]labelsValue = labelsKV[1]}pvcList, err := m.PersistentVolumeClaimList(clusterId, nameSpace, pvcName, labelsKey, labelsValue)msg := "success"code := 0count := len(pvcList)if err != nil {log.Println(err)msg = err.Error()code = -1}this.Data["json"] = &map[string]interface{}{"code": code, "msg": msg, "count": count, "data": &pvcList}//this.Data["json"] = &datasthis.ServeJSON()
}
6.2.模型storageModel.go的完整代码

6.2 storageModel.go,放到models下

// storageModel.go
package modelsimport ("context""fmt""log""myk8s/common""strings"corev1 "k8s.io/api/core/v1"metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"//"k8s.io/apimachinery/pkg/runtime"//"sigs.k8s.io/yaml"
)type Storageclass struct {StorageclassName string `json:"storageclassName"`Provisioner      string `json:"provisioner"`   //提供者Parameters       string `json:"parameters"`    //参数ReclaimPolicy    string `json:"reclaimPolicy"` //回收策略Labels           string `json:"labels"`Annotations      string `json:"annotations"` //注解CreateTime       string `json:"createTime"`
}type PersistentVolume struct {PvName          string `json:"pvName"`Capacity        string `json:"capacity"`        //容量AccessMode      string `json:"accessMode"`      //访问模式PvReclaimPolicy string `json:"pvReclaimPolicy"` //回收策略StorageClass    string `json:"storageClass"`    //存储类型Status          string `json:"status"`          //状态ClaimRef        string `json:"claimRef"`        //绑定存储申明Labels          string `json:"labels"`Annotations     string `json:"annotations"` //注解CreateTime      string `json:"createTime"`
}type PersistentVolumeClaim struct {PvcName      string `json:"pvcName"`NameSpace    string `json:"nameSpace"`Capacity     string `json:"capacity"`     //容量AccessMode   string `json:"accessMode"`   //访问模式StorageClass string `json:"storageClass"` //存储类型Status       string `json:"status"`       //状态VolumeName   string `json:"volumeName"`   //关联存储卷Labels       string `json:"labels"`Annotations  string `json:"annotations"` //注解CreateTime   string `json:"createTime"`
}func StorageclassList(kubeconfig string) ([]Storageclass, error) {clientset := common.ClientSet(kubeconfig)storageclassList, err := clientset.StorageV1().StorageClasses().List(context.TODO(), metav1.ListOptions{})if err != nil {log.Printf("list deployment error, err:%v\n", err)}var bbb = make([]Storageclass, 0)for _, sc := range storageclassList.Items {var parms stringfor kk, vv := range sc.Parameters {parms += fmt.Sprintf("%s:%s,", kk, vv)}var labelsStr stringfor kk, vv := range sc.Labels {labelsStr += fmt.Sprintf("%s:%s,", kk, vv)}var annotationsStr stringfor k2, v2 := range sc.Annotations {annotationsStr += fmt.Sprintf("%s:%s,", k2, v2)}Items := &Storageclass{StorageclassName: sc.Name,Provisioner:      sc.Provisioner,Parameters:       parms,ReclaimPolicy:    fmt.Sprintf("%s", *sc.ReclaimPolicy),Labels:           labelsStr,Annotations:      annotationsStr,CreateTime:       sc.CreationTimestamp.Format("2006-01-02 15:04:05"),}bbb = append(bbb, *Items)}return bbb, err
}func PersistentVolumeList(kubeconfig string) ([]PersistentVolume, error) {clientset := common.ClientSet(kubeconfig)pvList, err := clientset.CoreV1().PersistentVolumes().List(context.TODO(), metav1.ListOptions{})if err != nil {log.Printf("list deployment error, err:%v\n", err)}var bbb = make([]PersistentVolume, 0)for _, pv := range pvList.Items {var labelsStr stringfor kk, vv := range pv.Labels {labelsStr += fmt.Sprintf("%s:%s,", kk, vv)}var annotationsStr stringfor k2, v2 := range pv.Annotations {annotationsStr += fmt.Sprintf("%s:%s,", k2, v2)}var accessModeStr stringfor _, v3 := range pv.Spec.AccessModes {accessModeStr += fmt.Sprintf("%s", v3)}Items := &PersistentVolume{PvName:          pv.Name,Capacity:        pv.Spec.Capacity.Storage().String(),AccessMode:      accessModeStr,PvReclaimPolicy: fmt.Sprintf("%s", pv.Spec.PersistentVolumeReclaimPolicy),StorageClass:    pv.Spec.StorageClassName,Status:          fmt.Sprintf("%s", pv.Status.Phase),ClaimRef:        fmt.Sprintf("命名空间:%s<br>名称:%s", pv.Spec.ClaimRef.Namespace, pv.Spec.ClaimRef.Name),Labels:          labelsStr,Annotations:     annotationsStr,CreateTime:      pv.CreationTimestamp.Format("2006-01-02 15:04:05"),}bbb = append(bbb, *Items)}return bbb, err
}func PersistentVolumeClaimList(kubeconfig, namespace, pvcName, labelsKey, labelsValue string) ([]PersistentVolumeClaim, error) {clientset := common.ClientSet(kubeconfig)if namespace == "" {//namespace = corev1.NamespaceDefaultnamespace = corev1.NamespaceAll}//设置ListOptionsvar listOptions = metav1.ListOptions{}if labelsKey != "" && labelsValue != "" {listOptions = metav1.ListOptions{LabelSelector: fmt.Sprintf("%s=%s", labelsKey, labelsValue),}}pvcList, err := clientset.CoreV1().PersistentVolumeClaims(namespace).List(context.TODO(), listOptions)if err != nil {log.Printf("list deployment error, err:%v\n", err)}var bbb = make([]PersistentVolumeClaim, 0)for _, pvc := range pvcList.Items {//搜索if pvcName != "" {if !strings.Contains(pvc.Name, pvcName) {continue}}var labelsStr stringfor kk, vv := range pvc.Labels {labelsStr += fmt.Sprintf("%s:%s,", kk, vv)}var annotationsStr stringfor k2, v2 := range pvc.Annotations {annotationsStr += fmt.Sprintf("%s:%s,", k2, v2)}var accessModeStr stringfor _, v3 := range pvc.Spec.AccessModes {accessModeStr += fmt.Sprintf("%s", v3)}Items := &PersistentVolumeClaim{PvcName:      pvc.Name,NameSpace:    pvc.Namespace,Capacity:     pvc.Status.Capacity.Storage().String(),AccessMode:   accessModeStr,StorageClass: *pvc.Spec.StorageClassName,Status:       fmt.Sprintf("%s", pvc.Status.Phase),VolumeName:   pvc.Spec.VolumeName,Labels:       labelsStr,Annotations:  annotationsStr,CreateTime:   pvc.CreationTimestamp.Format("2006-01-02 15:04:05"),}bbb = append(bbb, *Items)}return bbb, err
}

七.效果图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3018946.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

内网穿透使用教程

什么是内网穿透 内网穿透&#xff0c;即NAT穿透&#xff0c;网络连接时术语&#xff0c;计算机是局域网内时&#xff0c;外网与内网的计算机节点需要连接通信&#xff0c;有时就会出现不支持内网穿透。就是说映射端口&#xff0c;能让外网的电脑找到处于内网的电脑&#xff0c…

算法学习008-登山爬石梯 c++动态规划/递归算法实现 中小学算法思维学习 信奥算法解析

目录 C登山爬石梯 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序编写 四、程序说明 五、运行结果 六、考点分析 七、推荐资料 C登山爬石梯 一、题目要求 1、编程实现 小明周末和朋友约好了一起去爬山&#xff0c;来到山下&#xff0c;发现登山道是…

医疗器械软件如何生成符合FDA要求的SBOM文件?

在当今这个高度互联的世界&#xff0c;医疗器械的安全性和可靠性对于保障公众健康至关重要。FDA作为美国食品和药物的主要监管机构&#xff0c;长期以来一直致力于确保医疗器械的安全性和有效性。 2023年9月27日&#xff0c;美国食品和药品监督管理局&#xff08;后续简称FDA&…

Activity工作流基本知识点

1.概念 工作流(Workflow)&#xff0c;就是“业务过程的部分或整体在计算机应用环境下的自动化”&#xff0c;它主要解决的是“使在多个参与者之间按照某种预定义的规则传递文档、信息或任务的过程自动进行&#xff0c;从而实现某个预期的业务目标&#xff0c;或者促使此目标的…

行业新应用:电机驱动将成为机器人的动力核心

电机已经遍布当今社会人们生活的方方面面&#xff0c;不仅应用范围越来越广&#xff0c;更新换代的速度也日益加快。按照工作电源分类&#xff0c;可以将它划分为直流电机和交流电机两大类型。直流电机中&#xff0c;按照线圈类型分类&#xff0c;又可以分为有铁芯的电机、空心…

如何查看近50年的历史影像?

天地图最近上线了2024版&#xff0c;全面更新了覆盖全国的在线地图服务。 本次更新首次开放多时相卫星影像&#xff0c;可查看32个省级节点近半个世纪的历史影像。 2024版天地图有哪些更新&#xff1f; 2024版天地图的更新优化主要包括&#xff1a; 1、新增上海市黄浦区、徐…

中国护照照片尺寸分辨率要求及居家自拍制作教程

经常出国的小伙伴都知道&#xff0c;护照照片作为出国旅行的重要身份证明文件&#xff0c;其规格和质量要求非常严格。本文将详细介绍中国护照照片的具体要求&#xff0c;并提供一些实用的居家自拍技巧&#xff0c;帮助您轻松拍出符合规定的护照照片&#xff08;手机和相机居家…

.Net Core/.Net6/.Net8 实现前端控制台输出

.Net Core/.Net6/.Net8 实现前端控制台输出 场景描述实现思路 代码添加/入队读取列表前端效果 场景描述 公司会接一些小项目开发&#xff0c;部署到客户方后&#xff0c;不方便进行debug 项目以webapi服务为主 实现思路 通过静态类和队列将最近发生的一些内容缓存起来 通过接口…

公众号旧主体执照注销了,账号冻结怎么迁移?

公众号迁移有什么作用&#xff1f;只能变更主体吗&#xff1f;最近有几个学校里面的学生找我咨询“说他们学校的公众号是之前一个学长用自己的身份信息注册的&#xff0c;每次换届的时候&#xff0c;就要麻烦学长重新绑定新的运营者&#xff0c;就想问问有没有办法可以把他的公…

英文文本标点恢复

文章目录 一、安装 rpunct二、使用三、下载模型时报错1、报错详情2、报错原因3、解决方案 四、程序运行时报错1、报错详情2、报错原因3、解决方案 五、修改默认缓存路径 一、安装 rpunct pip install rpunct 相关依赖包信息&#xff1a; langdetect1.0.9 pandas1.2.4 simpletr…

创造极致体验!5个让用户爱不释手的APP按钮设计秘诀

完美的应用程序设计离不开完美的应用程序按钮设计。应用程序按钮是UI界面不可缺少的UI组件之一。一个好的应用程序按钮可以使用户更容易与界面交互&#xff0c;从而提高应用程序应用程序的转换率。本文将围绕应用程序按钮进行解释&#xff0c;以帮助您创建一个具有良好用户体验…

【易错题】第六章-业务数据分析 #CDA Level 1

目录 一. 指标作用与理解 二. 基本指标 1&#xff09;求和类&#xff08;常规求和、累计求和&#xff09; 2&#xff09;*比较类&#xff08;均比、同比、环比、定基比、标准比&#xff09; 三. 场景指标 1&#xff09;*流量相关指标&#xff08;访客数UV、浏览量PV、访问…

【贪心算法】最小生成树Kruskal算法Python实现

文章目录 [toc]问题描述最小生成树的性质证明 Kruskal算法Python实现时间复杂性 问题描述 设 G ( V , E ) G (V , E) G(V,E)是无向连通带权图&#xff0c; E E E中每条边 ( v , w ) (v , w) (v,w)的权为 c [ v ] [ w ] c[v][w] c[v][w]如果 G G G的一个子图 G ′ G^{} G′是…

accelerator入门

一、目录 1 定义 2. DP、DPP的区别 3 实现 4. 测试比较 二、实现 定义 accelerator 是由大名鼎鼎的huggingface发布的&#xff0c;专门适用于Pytorch的分布式训练框架,是torchrun 的封装。 GitHub: https://github.com/huggingface/accelerate 官网教程&#xff1a;https://…

WPF之多种视图切换

1&#xff0c;View切换&#xff0c;效果呈现 视图1 视图2 视图3 2&#xff0c;在Xaml中添加Listview控件&#xff0c;Combobox控件。 <Grid ><Grid.RowDefinitions><RowDefinition Height"143*"/><RowDefinition Height"30"/>&l…

【Linux】常用基本指令

目录 食用说明 用户管理 whoami/who clear tree 目录结构和路径 pwd ls 文件 隐藏文件 常用选项 cd 家目录、根目录、绝对路径和相对路径 touch 常用选项 mkdir rmdir/rm man cp mv cat nano echo 输出重定向 > 输入重定向 < more/less head/…

pycharm code行太长显示波浪线取消

实际操作如下&#xff1a;个人比较合适的位置为160,180时有点多 效果&#xff1a;

前端开发攻略---使用Sass调整颜色亮度,实现Element组件库同款按钮

目录 1、演示 2、实现原理 3、实现代码 1、演示 2、实现原理 改变颜色亮度的原理是通过调整颜色的 RGB 值中的亮度部分来实现的。在 Sass 中&#xff0c;可以使用颜色函数来操作颜色的 RGB 值&#xff0c;从而实现亮度的调整。 具体来说&#xff0c;亮度调整函数通常会改变颜…

Python实战点云并行化处理

LAS 及其压缩版本 LAZ 是用于存储点云信息的流行文件格式&#xff0c;通常由 LiDAR 技术生成。 LiDAR&#xff08;即光探测和测距&#xff09;是一种遥感技术&#xff0c;用于测量距离并创建物体和景观的高精度 3D 地图。存储的点云信息主要包括X、Y、Z坐标、强度、颜色、特征分…

博睿数据将出席ClickHouse Hangzhou User Group第1届 Meetup

2024年5月18日&#xff0c;博睿数据数智能力中心负责人李骅宸将受邀参加ClickHouse Hangzhou User Group第1届 Meetup活动&#xff0c;分享《ClickHouse在可观测性的应用实践和优化》的主题演讲。 在当前数字化浪潮下&#xff0c;数据的规模和复杂性不断攀升&#xff0c;如何高…