替换yaml模板中的变量

"本文介绍了如何使用Golang的text/template包处理YAML文件,包括理解对象和数组结构,以及如何通过模板变量替换生成多实例的PrometheusRule配置。重点讲解了缩进规则和{{-}
摘要由CSDN通过智能技术生成

1. yaml复杂语法

YAML最重要的两个东西,一定要掌握这两种数据和熟悉转换为json是怎么样的

  • 对象:键值对的集合,又称为映射(mapping)/ 哈希(hashes) / 字典(dictionary,yaml整个文件本身就是一个对象。
    下面写一个关于prometheus的resource.yaml文件
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  creationTimestamp: null
  labels:
    prometheus: k8s
    role: alert-rules
  name: prometheus-template-rules
  namespace: monitoring

转换为json对象是:

{
  "apiVersion": "monitoring.coreos.com/v1",
  "kind": "PrometheusRule",
  "metadata": {
    "creationTimestamp": null,
    "labels": {
      "prometheus": "k8s",
      "role": "alert-rules"
    },
    "name": "prometheus-template-rules",
    "namespace": "monitoring"
  }
}

值得注意的是像metadata这样的一个对象里面有多个key,value键值对的情况,一定要熟悉这种缩进代表什么。其实缩进多少空格没所谓,主要是同等位置的东西要对齐,就像creationTimestamp与labels,name,namespace都是matadata里面的键值对,一定要对齐。

  • 数组:一组按次序排列的值,又称为序列(sequence) / 列表(list)
spec:
  groups:
    - name: kkdd
      rule:
        - alert: ingressAlert
          for: 1s
          expr: xioad
          labels:
            nodename: '{{.NodeName}}'
          annotations:
            containerID: label.name
            podName: label.pod
        - alert: egressAlert
          for: 1s
          expr: xxxxadad
          

转为json的结果,结果就是groups是一个list,里面包含了一个对象,而rule也是一个list,但是里面有2个对象。

{
  "spec": {
    "groups": [
    
      {
        "name": "kkdd",
        "rule": [
        
          {
            "alert": "ingressAlert",
            "for": "1s",
            "expr": "xioad",
            "labels": {
              "nodename": "{{.NodeName}}"
            },
            "annotations": {
              "containerID": "label.name",
              "podName": "label.pod"
            }
          },
          
          {
            "alert": "egressAlert",
            "for": "1s",
            "expr": "xxxxadad"
          }
          
        ]
      }
      
    ]
    
  }
  
}

2. 替换模板中的变量

主要是想将带有变量的template.yaml通过够替换变量,生成结果yaml。
方案:golang提供了text/template包,我们可以用它来渲染模板。
第一步:准备模板,我在本目录下创建了一个template.yaml

apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  creationTimestamp: null
  labels:
    prometheus: k8s
    role: alert-rules
  name: prometheus-template-rules
  namespace: monitoring
spec:
  groups:
  {{- range .Resources}} ###这里主要是for循环一个结构体
  - name: {{.NodeName}}-resources-limit-{{.ResourceValue}}unit.rules
    rules:
    - alert: ingressAlert {{"{{.value}} "}} {{"$"}}
      for: 1s      # status from pending to firing for 1s 
      # expr for test         
      expr: max(kube_pod_labels{label_unit="{{.ResourceValue}}"}) by (pod, label_unit)  * on(pod) group_right(label_unit) (sum(rate(container_network_receive_bytes_total{namespace="default",node="{{.NodeName}}"}[5m])) BY (instance, pod) / 128) > 200 * {{.ResourceValue}}
      labels: 
        nodename: "{{.NodeName}}"
      annotations:
        containerID: "{{"{{ $labels.name }}"}}" # notifications sended with the messages
        podName: "{{"{{ $labels.pod }}"}}"
    - alert: egressAlert 
      for: 1s      # status from pending to firing for 1s 
      # expr for test         
      expr: max(kube_pod_labels{label_unit="{{.ResourceValue}}"}) by (pod, label_unit)  * on(pod) group_right(label_unit) (sum(rate(container_network_transmit_bytes_total{namespace="default",node="{{.NodeName}}"}[5m])) BY (instance, pod) / 128) > 200 * {{.ResourceValue}}
      labels: 
        nodename: "{{.NodeName}}"
      annotations:
        containerID: "{{"{{ $labels.name }}"}}" # notifications sended with the messages
        podName: "{{"{{ $labels.pod }} "}}"
  {{- end }}

第二步:写go代码,来替换;Golang的代码
需要循环的部分用到语法{{- range .Resources}},{{- end}}。用它包裹起来的部分可以重复生成,而且是拼接在一份文件中。
Golang的代码:

package main

import (
	"bufio"
	"fmt"
	"io"
	"log"
	"os"
	"strings"
	"text/template"
)
type DeployTemplDatas struct {
	Resources []DeployTemplData
}
type DeployTemplData struct {
	NodeName string
	ResourceValue int
}

//主入口函数
func main() {
	nodeNms := []string{"nodeName1","nodeName2"}
	resourceVals := []int{111,2}
	dd := generateObjects(nodeNms,resourceVals)
	ParseFiles(nodeNms,resourceVals)
}
func ParseFiles(nodeNms []string,resourceVals []int ){
	t := template.New("test")
	t = template.Must(template.ParseFiles("./template.yaml"))
	
	data := generateObjects(nodeNms,resourceVals)
	userFile := "result.yaml"
    fout, err := os.Create(userFile) //create the file in the directory which the present file belongs to 
	if err != nil {
        fmt.Println(userFile, err)
        return
    }
	// 传入一个DeployTemplData结构体切片
	t.Execute(fout, data)

}
// @title    generateObjects
// @description   to generate the objects with the different nodeName and resourceValue
//生成len(nodeNames)*len(resourceVals)个对象
func generateObjects(nodeNames []string,resourceVals []int) DeployTemplDatas{
	datas := make([]DeployTemplData,0,len(nodeNames)*len(resourceVals))
	for i :=0;i<len(nodeNames);i++{
		for j:=0;j<len(resourceVals);j++{
			data := DeployTemplData{
				NodeName: nodeNames[i],
				ResourceValue: resourceVals[j],
			}
			datas = append(datas, data)
		}

	}
	temldatas := DeployTemplDatas{
		Resources: datas,
	}
	return temldatas
}

第三步得到结果:

apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  creationTimestamp: null
  labels:
    prometheus: k8s
    role: alert-rules
  name: prometheus-template-rules
  namespace: monitoring
spec:
  groups:
  - name: nodeName1-resources-limit-1unit.rules
    rules:
    - alert: ingressAlert {{.value}}  $
      for: 1s      # status from pending to firing for 1s 
      # expr for test         
      expr: max(kube_pod_labels{label_unit="1"}) by (pod, label_unit)  * on(pod) group_right(label_unit) (sum(rate(container_network_receive_bytes_total{namespace="default",node="nodeName1"}[5m])) BY (instance, pod) / 128) > 200 * 1
      labels: 
        nodename: "nodeName1"
      annotations:
        containerID: "{{ $labels.name }}" # notifications sended with the messages
        podName: "{{ $labels.pod }}"
    - alert: egressAlert 
      for: 1s      # status from pending to firing for 1s 
      # expr for test         
      expr: max(kube_pod_labels{label_unit="1"}) by (pod, label_unit)  * on(pod) group_right(label_unit) (sum(rate(container_network_transmit_bytes_total{namespace="default",node="nodeName1"}[5m])) BY (instance, pod) / 128) > 200 * 1
      labels: 
        nodename: "nodeName1"
      annotations:
        containerID: "{{ $labels.name }}" # notifications sended with the messages
        podName: "{{ $labels.pod }} "
  - name: nodeName1-resources-limit-2unit.rules
    rules:
    - alert: ingressAlert {{.value}}  $
      for: 1s      # status from pending to firing for 1s 
      # expr for test         
      expr: max(kube_pod_labels{label_unit="2"}) by (pod, label_unit)  * on(pod) group_right(label_unit) (sum(rate(container_network_receive_bytes_total{namespace="default",node="nodeName1"}[5m])) BY (instance, pod) / 128) > 200 * 2
      labels: 
        nodename: "nodeName1"
      annotations:
        containerID: "{{ $labels.name }}" # notifications sended with the messages
        podName: "{{ $labels.pod }}"
    - alert: egressAlert 
      for: 1s      # status from pending to firing for 1s 
      # expr for test         
      expr: max(kube_pod_labels{label_unit="2"}) by (pod, label_unit)  * on(pod) group_right(label_unit) (sum(rate(container_network_transmit_bytes_total{namespace="default",node="nodeName1"}[5m])) BY (instance, pod) / 128) > 200 * 2
      labels: 
        nodename: "nodeName1"
      annotations:
        containerID: "{{ $labels.name }}" # notifications sended with the messages
        podName: "{{ $labels.pod }} "
  - name: nodeName2-resources-limit-1unit.rules
    rules:
    - alert: ingressAlert {{.value}}  $
      for: 1s      # status from pending to firing for 1s 
      # expr for test         
      expr: max(kube_pod_labels{label_unit="1"}) by (pod, label_unit)  * on(pod) group_right(label_unit) (sum(rate(container_network_receive_bytes_total{namespace="default",node="nodeName2"}[5m])) BY (instance, pod) / 128) > 200 * 1
      labels: 
        nodename: "nodeName2"
      annotations:
        containerID: "{{ $labels.name }}" # notifications sended with the messages
        podName: "{{ $labels.pod }}"
    - alert: egressAlert 
      for: 1s      # status from pending to firing for 1s 
      # expr for test         
      expr: max(kube_pod_labels{label_unit="1"}) by (pod, label_unit)  * on(pod) group_right(label_unit) (sum(rate(container_network_transmit_bytes_total{namespace="default",node="nodeName2"}[5m])) BY (instance, pod) / 128) > 200 * 1
      labels: 
        nodename: "nodeName2"
      annotations:
        containerID: "{{ $labels.name }}" # notifications sended with the messages
        podName: "{{ $labels.pod }} "
  - name: nodeName2-resources-limit-2unit.rules
    rules:
    - alert: ingressAlert {{.value}}  $
      for: 1s      # status from pending to firing for 1s 
      # expr for test         
      expr: max(kube_pod_labels{label_unit="2"}) by (pod, label_unit)  * on(pod) group_right(label_unit) (sum(rate(container_network_receive_bytes_total{namespace="default",node="nodeName2"}[5m])) BY (instance, pod) / 128) > 200 * 2
      labels: 
        nodename: "nodeName2"
      annotations:
        containerID: "{{ $labels.name }}" # notifications sended with the messages
        podName: "{{ $labels.pod }}"
    - alert: egressAlert 
      for: 1s      # status from pending to firing for 1s 
      # expr for test         
      expr: max(kube_pod_labels{label_unit="2"}) by (pod, label_unit)  * on(pod) group_right(label_unit) (sum(rate(container_network_transmit_bytes_total{namespace="default",node="nodeName2"}[5m])) BY (instance, pod) / 128) > 200 * 2
      labels: 
        nodename: "nodeName2"
      annotations:
        containerID: "{{ $labels.name }}" # notifications sended with the messages
        podName: "{{ $labels.pod }} "

解析:

  1. 我准备了包含四个对象的切片Resources,然后遍历替换,生成了包含四个na,
  2. {{-}}中的-有何作用?可以除去占用此行的空格,如果不加这个 -,那么range会占用一行,即结果会在range行这里空一行。
  3. Resources是一个数组或者是切片,在循环里面的点"."代表的是当前循环数组中的每一个对象,对象里面的字段就可以用.XXX来表示了。
  4. 如果是想要安全替换,我们并不想{{.value}}被替换,忽略跳过此替换,原样输出{{.value}},方法是:{{" {{.value}} "}};详细可以看上面的例子,美元符号,点都有涉及了。

3. 总结

  • 完成功能关键在于知道Golang的template的循环是使用{{range .xxx}}{{end}}语法;原样输出在模板中怎么写。
  • 拓展,template还可以有其他的表达式,条件判断等等功能,详细点击—>李文周的博客
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值