简介

本章节主要讲解通过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 string
	if len(labelsKV) == 2 {
		labelsKey = labelsKV[0]
		labelsValue = labelsKV[1]
	}
    //读取pvc列表
	pvcList, err := m.PersistentVolumeClaimList(clusterId, nameSpace, pvcName, labelsKey, labelsValue)
	msg := "success"
	code := 0
	count := 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.NamespaceDefault
		namespace = corev1.NamespaceAll
	}

	//设置ListOptions
	var 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 string
		for kk, vv := range pvc.Labels {
			labelsStr += fmt.Sprintf("%s:%s,", kk, vv)
		}
		var annotationsStr string
		for k2, v2 := range pvc.Annotations {
			annotationsStr += fmt.Sprintf("%s:%s,", k2, v2)
		}
		var accessModeStr string
		for _, 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 := 0
	count := 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)
	//循环提取信息并赋值到结构体Items
	for _, pv := range pvList.Items {
		var labelsStr string
		for kk, vv := range pv.Labels {
			labelsStr += fmt.Sprintf("%s:%s,", kk, vv)
		}
		var annotationsStr string
		for k2, v2 := range pv.Annotations {
			annotationsStr += fmt.Sprintf("%s:%s,", k2, v2)
		}
		var accessModeStr string
		for _, 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 := 0
	count := 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 string
		for kk, vv := range sc.Parameters {
			parms += fmt.Sprintf("%s:%s,", kk, vv)
		}

		var labelsStr string
		for kk, vv := range sc.Labels {
			labelsStr += fmt.Sprintf("%s:%s,", kk, vv)
		}
		var annotationsStr string
		for 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中

	//storageclass
	beego.Router("/storage/v1/StorageclassList", &controllers.StorageController{}, "*:StorageclassList")
	//pv
	beego.Router("/storage/v1/PvList", &controllers.StorageController{}, "*:PvList")
	//pvc
	beego.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 controllers

import (
	//"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 := 0
	count := 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 := 0
	count := 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"] = &datas
	this.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 string
	if len(labelsKV) == 2 {
		labelsKey = labelsKV[0]
		labelsValue = labelsKV[1]
	}

	pvcList, err := m.PersistentVolumeClaimList(clusterId, nameSpace, pvcName, labelsKey, labelsValue)
	msg := "success"
	code := 0
	count := 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"] = &datas
	this.ServeJSON()
}

6.2.模型storageModel.go的完整代码

6.2 storageModel.go,放到models下

// storageModel.go
package models

import (
	"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 string
		for kk, vv := range sc.Parameters {
			parms += fmt.Sprintf("%s:%s,", kk, vv)
		}

		var labelsStr string
		for kk, vv := range sc.Labels {
			labelsStr += fmt.Sprintf("%s:%s,", kk, vv)
		}
		var annotationsStr string
		for 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 string
		for kk, vv := range pv.Labels {
			labelsStr += fmt.Sprintf("%s:%s,", kk, vv)
		}
		var annotationsStr string
		for k2, v2 := range pv.Annotations {
			annotationsStr += fmt.Sprintf("%s:%s,", k2, v2)
		}
		var accessModeStr string
		for _, 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.NamespaceDefault
		namespace = corev1.NamespaceAll
	}

	//设置ListOptions
	var 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 string
		for kk, vv := range pvc.Labels {
			labelsStr += fmt.Sprintf("%s:%s,", kk, vv)
		}
		var annotationsStr string
		for k2, v2 := range pvc.Annotations {
			annotationsStr += fmt.Sprintf("%s:%s,", k2, v2)
		}
		var accessModeStr string
		for _, 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
}

七.效果图

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