温馨提示:这篇文章已超过446天没有更新,请注意相关的内容是否还可用!
摘要:本文介绍了在k8s多集群管理平台开发实践中,使用clint-go实现configmap的管理功能。文章详细阐述了实现configmap列表、创建configmap以及yaml配置的编辑过程。通过clint-go工具,开发者能够更方便地管理k8s集群中的configmap资源,提高开发效率和系统管理的便捷性。
文章目录
- 简介
- 一.configmap的列表实现
- 1.1.controllers控制器代码
- 1.2.models模型代码
- 二.界面创建configmap
- 2.1.controllers控制器代码
- 2.2.models模分代码
- 三.读取configmap的yaml配置并更新
- 3.1.controllers控制器代码
- 3.2.models模型代码
- 四.路由设置
- 4.1.路由设置
- 五.前端代码
- 5.1.列表部分html代码
- 5.2.创建表单html代码
- 5.3.显示yaml配置的html代码
- 六.完整代码
- 6.1.控制器完整代码
- 6.2.模型完整代码
- 七.效果图
简介
本章节主要讲解通过client-go实现configmap的列表显示、界面创建configmap,读取yaml配置并更改。功能主要有后端部分:控制器代码、模型部分代码、路由配置。前端部分:configmapList.html的html代码,configmapCreate.html,configmapYaml.html这几部分代码组成。
一.configmap的列表实现
1.1.controllers控制器代码
该列表支持传递集群ID、命名空间、configmap名称来进行过滤查询
func (this *ConfigMapController) List() { clusterId := this.GetString("clusterId") nameSpace := this.GetString("nameSpace") configmapName := this.GetString("configmapName") labels := this.GetString("labels") labelsKV := strings.Split(labels, ":") var labelsKey, labelsValue string if len(labelsKV) == 2 { labelsKey = labelsKV[0] labelsValue = labelsKV[1] } cmList, err := m.CmList(clusterId, nameSpace, configmapName, labelsKey, labelsValue) msg := "success" code := 0 count := len(cmList) if err != nil { log.Println(err) msg = err.Error() code = -1 } this.Data["json"] = &map[string]interface{}{"code": code, "msg": msg, "count": count, "data": &cmList} this.ServeJSON() }
1.2.models模型代码
先定义configmap的实例信息结构体和存储数据的key-value的结构体,并通过传递的集群ID、命名空间、标签等信息过滤,调用clientset.CoreV1().ConfigMaps(namespace).List 函数读取列表,并赋值到Configmap结构体并追加到结构体数组var bbb = make([]Configmap, 0)
//定义configmap中信息的结构体 type Configmap struct { ConfigmapName string `json:"configmapName"` NameSpace string `json:"nameSpace"` Labels string `json:"labels"` CreateTime string `json:"createTime"` Data []Cmkv `json:"data"` } //定义configmap中存储的数据的key-value数据结构体 type Cmkv struct { Key string `json:"key"` Value string `json:"value"` } func CmList(kubeconfig, namespace, configmapName string, labelsKey, labelsValue string) ([]Configmap, 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数据并返回configmap的信息 cmList, err := clientset.CoreV1().ConfigMaps(namespace).List(context.TODO(), listOptions) if err != nil { log.Printf("list deployment error, err:%v\n", err) } //顶一个数组用来存放configmap的信息 var bbb = make([]Configmap, 0) for _, cm := range cmList.Items { //根据configmap的名称来过滤 if configmapName != "" { if !strings.Contains(cm.Name, configmapName) { continue } } var labelsStr string for kk, vv := range cm.ObjectMeta.Labels { labelsStr += fmt.Sprintf("%s:%s,", kk, vv) } if len(labelsStr) > 0 { labelsStr = labelsStr[0 : len(labelsStr)-1] } Items := &Configmap{ ConfigmapName: cm.Name, NameSpace: cm.Namespace, Labels: labelsStr, CreateTime: cm.CreationTimestamp.Format("2006-01-02 15:04:05"), } bbb = append(bbb, *Items) } return bbb, err }
二.界面创建configmap
2.1.controllers控制器代码
接收html中表单传来的数据,并传递给CmCreate函数处理。
func (this *ConfigMapController) Create() { clusterId := this.GetString("clusterId") code := 0 msg := "success" err := m.CmCreate(clusterId, this.Ctx.Input.RequestBody) if err != nil { code = -1 msg = err.Error() log.Printf("[ERROR] configmap Create Fail:%s\n", err) } this.Data["json"] = &map[string]interface{}{"code": code, "msg": msg} this.ServeJSON() }
2.2.models模分代码
接收控制器中Create函数传递过来的body,并进行json解析,先创建一个configmap实例&corev1.ConfigMap,然后将解析出来的值赋值到实例中,然后通过调用clientset.CoreV1().ConfigMaps(nameSpace).Create进行创建。
func CmCreate(kubeconfig string, bodys []byte) error { gp := gjson.ParseBytes(bodys) clusterId := gp.Get("clusterId").String() if kubeconfig == "" { kubeconfig = clusterId } configmapName := gp.Get("configmapName").String() nameSpace := gp.Get("nameSpace").String() var labelsMap = make(map[string]string) labelsMap["app"] = configmapName for _, vv := range gp.Get("lables").Array() { labelsMap[vv.Get("key").Str] = vv.Get("value").Str } var dataMap = make(map[string]string) for _, vv := range gp.Get("configmaps").Array() { dataMap[vv.Get("key").Str] = vv.Get("value").Str } cm := &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: configmapName, Namespace: nameSpace, Labels: labelsMap, }, Data: dataMap, } clientset := common.ClientSet(kubeconfig) _, err := clientset.CoreV1().ConfigMaps(nameSpace).Create(context.TODO(), cm, metav1.CreateOptions{}) if err != nil { return err } return nil }
三.读取configmap的yaml配置并更新
3.1.controllers控制器代码
两个功能:一个是读取yaml配置Yaml(),一个是更新yaml配置ModifyByYaml()。
//读取configmap的yaml配置 func (this *ConfigMapController) Yaml() { clusterId := this.GetString("clusterId") namespace := this.GetString("nameSpace") configmapName := this.GetString("configmapName") yamlStr, _ := m.GetCmYaml(clusterId, namespace, configmapName) this.Ctx.WriteString(yamlStr) } //更新configmap的yaml配置 func (this *ConfigMapController) ModifyByYaml() { clusterId := this.GetString("clusterId") code := 0 msg := "success" bodyByte := []byte(strings.ReplaceAll(string(this.Ctx.Input.RequestBody), "%25", "%")) err := m.CmYamlModify(clusterId, bodyByte) if err != nil { code = -1 msg = err.Error() log.Printf("[ERROR] configmap ModifyByYaml Fail:%s\n", err) } this.Data["json"] = &map[string]interface{}{"code": code, "msg": msg} this.ServeJSON() }
3.2.models模型代码
GetCmYaml通过集群ID、命名空间、configmap的名称获取实例,并进行解构然后进行序列化成yaml配置,CmYamlModify将提交的yaml配置进行反序列化成configmap实例,然后通过调用clientset.CoreV1().ConfigMaps(namespace).Update进行更新
//获取configmapyaml配置 func GetCmYaml(kubeconfig, namespace, configmapName string) (string, error) { cmClient := common.ClientSet(kubeconfig).CoreV1().ConfigMaps(namespace) //读取configmap实例配置 configmap, err := cmClient.Get(context.TODO(), configmapName, metav1.GetOptions{}) //将配置进行解构 cmUnstructured, err := runtime.DefaultUnstructuredConverter.ToUnstructured(configmap) if err != nil { return "", err } //将解构的数据进行序列化成yaml配置 yamlBytes, err := yaml.Marshal(cmUnstructured) if err != nil { return "", err } return string(yamlBytes), nil } //更新configmap的yaml配置 func CmYamlModify(kubeconfig string, yamlData []byte) error { //将yaml配置解析成json data, err := yamlutil.ToJSON(yamlData) if err != nil { return err } //定义configmap实例 configmap := &corev1.ConfigMap{} //将json数据转成结构体configmap的实例上 err = json.Unmarshal(data, configmap) if err != nil { return err } namespace := configmap.ObjectMeta.Namespace confignameName := configmap.ObjectMeta.Name //调用Update函数进行更新 clientset := common.ClientSet(kubeconfig) _, err = clientset.CoreV1().ConfigMaps(namespace).Update(context.TODO(), configmap, metav1.UpdateOptions{}) if err != nil { return err } //fmt.Println(namespace, confignameName) return err }
四.路由设置
4.1.路由设置
将以下路由配置添加到routers/route.go中
//configmap beego.Router("/cm/v1/List", &controllers.ConfigMapController{}, "*:List") beego.Router("/cm/v1/Create", &controllers.ConfigMapController{}, "*:Create") beego.Router("/cm/v1/ModifyByYaml", &controllers.ConfigMapController{}, "*:ModifyByYaml") beego.Router("/cm/v1/Yaml", &controllers.ConfigMapController{}, "*:Yaml")
五.前端代码
5.1.列表部分html代码
5.1 configmapList.html
configmap列表 .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; } {{# if (d.labels != "") { }} {{# layui.each(d.labels.split(','), function(index, item){ }} {{# if(index == 0) { }} {{ item }} {{# }else{ }}
{{ item }} {{# } }} {{# }); }} {{# }else{ }} {{# } }} 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: '/cm/v1/List?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: 'configmapName', width: 250,title: '名称', sort: true}, {field: 'nameSpace', width: 150,title: '命名空间', sort: true}, {field: 'labels', title: '标签', sort: true,templet: '#TagTpl'}, {field: 'createTime', width:180, title: '创建时间'}, {title: '操作', toolbar: '#currentTableBar', align: "center"} ]], //size:'lg', limits: [25, 50, 100], limit: 25, page: true }); table.on('toolbar(currentTableFilter)', function (obj) { if (obj.event === 'create') { // 监听添加操作 var index = layer.open({ title: '创建', type: 2, shade: 0.2, maxmin:true, shadeClose: true, area: ['60%', '90%'], content: '/page/xkube/configmapCreate.html', //end: function(){ // window.parent.location.reload();//关闭open打开的页面时,刷新父页面 //} }); $(window).on("resize", function () { layer.full(index); }); } }); 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: ['45%', '92%'], content: '/page/xkube/configmapYaml.html?clusterId='+clusterId+'&nameSpace='+data.nameSpace+'&configmapName='+data.configmapName, }); $(window).on("resize", function () { layer.full(index); }); return false; } }); });5.2.创建表单html代码
5.2 configmapCreate.html
创建 body { background-color: #ffffff; }
当前集群请选择集群cm名称*命名空间key名称值标签确认保存5.3.显示yaml配置的html代码
5.3 configmapYaml.html
yaml编辑
保存更新 下载六.完整代码
6.1.控制器完整代码
6.1 configmap.go,放到controllers下
// configmap.go package controllers import ( "log" m "myk8s/models" "strings" //"github.com/tidwall/gjson" beego "github.com/beego/beego/v2/server/web" ) type ConfigMapController struct { beego.Controller } func (this *ConfigMapController) List() { clusterId := this.GetString("clusterId") nameSpace := this.GetString("nameSpace") configmapName := this.GetString("configmapName") labels := this.GetString("labels") labelsKV := strings.Split(labels, ":") var labelsKey, labelsValue string if len(labelsKV) == 2 { labelsKey = labelsKV[0] labelsValue = labelsKV[1] } cmList, err := m.CmList(clusterId, nameSpace, configmapName, labelsKey, labelsValue) msg := "success" code := 0 count := len(cmList) if err != nil { log.Println(err) msg = err.Error() code = -1 } this.Data["json"] = &map[string]interface{}{"code": code, "msg": msg, "count": count, "data": &cmList} this.ServeJSON() } func (this *ConfigMapController) Create() { clusterId := this.GetString("clusterId") code := 0 msg := "success" err := m.CmCreate(clusterId, this.Ctx.Input.RequestBody) if err != nil { code = -1 msg = err.Error() log.Printf("[ERROR] configmap Create Fail:%s\n", err) } this.Data["json"] = &map[string]interface{}{"code": code, "msg": msg} this.ServeJSON() } func (this *ConfigMapController) ModifyByYaml() { clusterId := this.GetString("clusterId") code := 0 msg := "success" bodyByte := []byte(strings.ReplaceAll(string(this.Ctx.Input.RequestBody), "%25", "%")) err := m.CmYamlModify(clusterId, bodyByte) if err != nil { code = -1 msg = err.Error() log.Printf("[ERROR] configmap ModifyByYaml Fail:%s\n", err) } this.Data["json"] = &map[string]interface{}{"code": code, "msg": msg} this.ServeJSON() } func (this *ConfigMapController) Yaml() { clusterId := this.GetString("clusterId") namespace := this.GetString("nameSpace") configmapName := this.GetString("configmapName") yamlStr, _ := m.GetCmYaml(clusterId, namespace, configmapName) this.Ctx.WriteString(yamlStr) }
6.2.模型完整代码
6.2 configmapModel.go,放到models下
// configmapModel.go package models import ( "context" "encoding/json" "fmt" "log" "myk8s/common" "strings" "github.com/tidwall/gjson" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" yamlutil "k8s.io/apimachinery/pkg/util/yaml" "sigs.k8s.io/yaml" ) type Configmap struct { ConfigmapName string `json:"configmapName"` NameSpace string `json:"nameSpace"` Labels string `json:"labels"` CreateTime string `json:"createTime"` Data []Cmkv `json:"data"` } type Cmkv struct { Key string `json:"key"` Value string `json:"value"` } func CmList(kubeconfig, namespace, configmapName string, labelsKey, labelsValue string) ([]Configmap, 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), } } cmList, err := clientset.CoreV1().ConfigMaps(namespace).List(context.TODO(), listOptions) if err != nil { log.Printf("list deployment error, err:%v\n", err) } var bbb = make([]Configmap, 0) for _, cm := range cmList.Items { //搜索 if configmapName != "" { if !strings.Contains(cm.Name, configmapName) { continue } } var labelsStr string for kk, vv := range cm.ObjectMeta.Labels { labelsStr += fmt.Sprintf("%s:%s,", kk, vv) } if len(labelsStr) > 0 { labelsStr = labelsStr[0 : len(labelsStr)-1] } Items := &Configmap{ ConfigmapName: cm.Name, NameSpace: cm.Namespace, Labels: labelsStr, CreateTime: cm.CreationTimestamp.Format("2006-01-02 15:04:05"), } bbb = append(bbb, *Items) } return bbb, err } func CmCreate(kubeconfig string, bodys []byte) error { gp := gjson.ParseBytes(bodys) clusterId := gp.Get("clusterId").String() if kubeconfig == "" { kubeconfig = clusterId } configmapName := gp.Get("configmapName").String() nameSpace := gp.Get("nameSpace").String() var labelsMap = make(map[string]string) labelsMap["app"] = configmapName for _, vv := range gp.Get("lables").Array() { labelsMap[vv.Get("key").Str] = vv.Get("value").Str } var dataMap = make(map[string]string) for _, vv := range gp.Get("configmaps").Array() { dataMap[vv.Get("key").Str] = vv.Get("value").Str } cm := &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: configmapName, Namespace: nameSpace, Labels: labelsMap, }, Data: dataMap, } clientset := common.ClientSet(kubeconfig) _, err := clientset.CoreV1().ConfigMaps(nameSpace).Create(context.TODO(), cm, metav1.CreateOptions{}) if err != nil { return err } return nil } func CmYamlModify(kubeconfig string, yamlData []byte) error { data, err := yamlutil.ToJSON(yamlData) if err != nil { return err } configmap := &corev1.ConfigMap{} err = json.Unmarshal(data, configmap) if err != nil { return err } namespace := configmap.ObjectMeta.Namespace confignameName := configmap.ObjectMeta.Name clientset := common.ClientSet(kubeconfig) _, err = clientset.CoreV1().ConfigMaps(namespace).Update(context.TODO(), configmap, metav1.UpdateOptions{}) if err != nil { return err } fmt.Println(namespace, confignameName) return err } func GetCmYaml(kubeconfig, namespace, configmapName string) (string, error) { cmClient := common.ClientSet(kubeconfig).CoreV1().ConfigMaps(namespace) configmap, err := cmClient.Get(context.TODO(), configmapName, metav1.GetOptions{}) cmUnstructured, err := runtime.DefaultUnstructuredConverter.ToUnstructured(configmap) if err != nil { return "", err } yamlBytes, err := yaml.Marshal(cmUnstructured) if err != nil { return "", err } return string(yamlBytes), nil }
七.效果图
还没有评论,来说两句吧...