Golang 删除Helm的yaml文件中的Nginx Location部分

该脚本需求旨在批量删除Gitlab仓库中的前端项目,这些项目通过ConfigMap来暴露服务。通过检查文件是否以特定格式开头、是否为YAML文件、是否包含特定配置等条件,确定文件是否需要处理。然后对满足条件的文件进行分割操作,特别是对location部分进行处理,以实现删除指定前端服务的目的。
摘要由CSDN通过智能技术生成

一 最终版本 split

脚本需求

  • 批量删除Gitlab仓库中的前端项目使用configmap暴露服务

源文件内容

app: fe-freight-admin
appType: nginx
replicaCount: 2
ingress:
  enabled: true
  class: alb
  internal:
    enabled: false
  internet:
    enabled: true
    tlsEnabled: true
    host: xxxx.xxxx.cn
service:
  type: ClusterIP
  port: 80
configs:
  enabled: true
  type: file
  path: /etc/nginx/conf.d
  data:
    default.conf: |-
      server {
          listen  80;
          server_name  localhost;

          resolver kube-dns.kube-system.svc.cluster.local valid=30s;
          resolver_timeout 3s;

          root /opt/dist;
          index index.html;

          location ^~ /oms {
             set $URL http://fe-freight-oms-admin.fe-freight-oms-admin.svc.cluster.local;
             rewrite ^/oms(.*) /$1 break;
             proxy_set_header X-real-ip $remote_addr;
             proxy_pass  $URL;
          }

          location ^~ /tms {
             set $URL http://fe-freight-tms-admin.fe-freight-tms-admin.svc.cluster.local;
             rewrite ^/tms(.*) /$1 break;
             proxy_set_header X-real-ip $remote_addr;
             proxy_pass  $URL;
          }

          location ^~ /bms {
             set $URL http://fe-freight-bms-admin.fe-freight-bms-admin.svc.cluster.local;
             rewrite ^/bms(.*) /$1 break;
             proxy_set_header X-real-ip $remote_addr;
             proxy_pass  $URL;
          }

          location ^~ /base {
             set $URL http://fe-freight-base-admin.fe-freight-base-admin.svc.cluster.local;
             rewrite ^/base(.*) /$1 break;
             proxy_set_header X-real-ip $remote_addr;
             proxy_pass  $URL;
          }

          location ^~ /v1 {
             set $URL http://fe-freight-v1-admin.fe-freight-v1-admin.svc.cluster.local;
             rewrite ^/v1(.*) /$1 break;
             proxy_set_header X-real-ip $remote_addr;
             proxy_pass  $URL;
          }

          location ^~/hope-saas-auth-web/ {
              set $URL http://hope-saas-auth-web.hope-saas-auth-web.svc.cluster.local:8080;
              rewrite ^/hope-saas-auth-web/(.*) /$1 break;
              proxy_set_header X-real-ip $remote_addr;
              proxy_pass  $URL;
          }

          location ^~ /hope-saas-tms-web/ {
             set $URL http://hope-saas-tms-web.hope-saas-tms-web.svc.cluster.local:8080;
             rewrite ^/hope-saas-tms-web/(.*) /$1 break;
             proxy_set_header X-real-ip $remote_addr;
             proxy_pass  $URL;
          }

          location ^~ /tms_plus_waybill/ {
             set $URL http://otms-web-plus.otms-web-plus.svc.cluster.local:8080;
             rewrite ^/tms_plus_waybill/(.*) /$1 break;
             proxy_set_header X-real-ip $remote_addr;
             proxy_pass  $URL;
          }


          location ^~ /hope-saas-tcs-web/ {
             set $URL http://hope-saas-tcs-web.hope-saas-tcs-web.svc.cluster.local:8080;
             rewrite ^/hope-saas-tcs-web/(.*) /$1 break;
             proxy_set_header X-real-ip $remote_addr;
             proxy_pass  $URL;
          }

          location ^~ /tms_plus {
             set $URL http://otms-web-plus.otms-web-plus.svc.cluster.local:8080;
             proxy_set_header X-real-ip $remote_addr;
             proxy_pass  $URL;
          }


          location = /index.html {
              add_header Cache-Control "no-store";
          }

          location / {
              expires -1;
          }
          location ~ \.(jpg|png|jpeg|gif)$  {
              expires 30d;
          }

          location ~ \.(js|css)$  {
              expires 2h;
          }

          location ^~ /.git {
              deny all;
          }
      }
resources:
  requests:
    cpu: 100m
    memory: 512Mi
  limits:
    cpu: 2000m
    memory: 512Mi

lifecycle:
  preStop:
    enabled: true
    command:
    - /bin/sh
    - -c
    - sleep 15

设计思路

  • 1 首先检测文件是否以backup为开头,如果是,文件为备份文件不需要替换
  • 2 检测文件是否以 yaml或者yml为结尾,如果是yml文件,则进行下一步操作
  • 3 判断文件内容是否包含 appType: nginx,如果包含这个才是前端文件
  • 4 判断文件中是否有我们需要去除的app名字
  • 5 确认文件是我们需要修改的文件后,开始进行split分段操作
  • 6 以default.conf:分段,作为文件中独一无二的部分
  • 7 对location部分split,设置一个切片,最后使用strings.join拼接切片
  • 8 写入修改后的文本内容
package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"regexp"
	"strings"
)

var (
	app string
)

const (
	rule1 = "default.conf:"
)

func checkFile(filename string) {
	//检测文件是否以backup为开头
	if !strings.HasPrefix(filename, "./backup") {
		//检测文件是否以 yaml或者yml为结尾
		if strings.HasSuffix(filename, "ymal") || strings.HasSuffix(filename, "yml") {
			bytes, err := os.ReadFile(filename)
			if err != nil {
				panic(err.Error())
			}
			//判断文件内容是否包含 appType: nginx,如果包含这个才是前端文件
			if regexp.MustCompile(rule1).MatchString(string(bytes)) {
				if regexp.MustCompile(app).MatchString(string(bytes)) {
					updateFile(filename,string(bytes))
				}
			}
		}
	}

}

func addFile(dirName string) []string {
	var ret []string
	fileInfo, err := ioutil.ReadDir(dirName)
	if err != nil {
		fmt.Println(err)
		return ret
	}

	for _, fi := range fileInfo {
		fileName := dirName + "/" + fi.Name()
		//fmt.Printf("%s%s\n", s, fileName)
		if fi.IsDir() {
			tmpRes := addFile(fileName)
			ret = append(ret, tmpRes...)
		} else {
			ret = append(ret, fileName)
		}
	}
	return ret
}



func updateFile(filename,data string)  {
	var result string
	var head []string
	confSplit := strings.Split(data, "default.conf:")
	result =result + confSplit[0] + "default.conf:"

	locationSplit := strings.Split(confSplit[1], "location")
	result = result + locationSplit[0]
	head = []string{""}
	for _,v := range locationSplit[1:]{
		head = append(head, v)
	}
	data = strings.Join(head, "location")


	splits := strings.Split(data, "}")
	rule2 := fmt.Sprintf("location.*/%s-.*{", app)
	rule3 := fmt.Sprintf("location.*/%s.*{", app)
	var ret []string
	for _,v := range splits {
		if regexp.MustCompile(rule3).MatchString(v) {
			if regexp.MustCompile(rule2).MatchString(v){
				ret = append(ret, v)
			}
		} else {
			ret = append(ret, v)
		}
	}
	join := strings.Join(ret, "}")
	result = result + join
	_ = os.Remove(filename)
	file, err := os.OpenFile(filename, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0666)
	if err != nil {
		panic(err.Error())
	}
	file.WriteString(result)
	file.Close()
	fmt.Printf("修改 %s 文件成功\n",filename)
}

func main() {
	flag.StringVar(&app, "app", "", "请输入要替换的location名字")
	flag.Parse()
	if app == "" {
		fmt.Println("请输入要替换的location,并再次执行 ./yunlizhi_change_file --app=你想删除的location名字")
		return
	}
	fileList := addFile(".")
	for _, filename := range fileList {
		checkFile(filename)
	}
	//checkFile("values.yml")
}

第二种思路 使用viper去提取yaml格式

失败原因提取的yaml未经过格式化,大小写区分错误

package main

import (
	"fmt"
	"github.com/spf13/viper"
	"strings"
)



func main() {
	viper.SetConfigType("yaml")
	viper.SetConfigFile("fe-bms-admin_prod_values.yml")
	//判断文件的前缀	fmt.Println(strings.HasPrefix(a, "go"))
	//判断文件的后缀	fmt.Println(strings.HasSuffix(a, "ng")) //true
	err := viper.ReadInConfig()
	if err != nil {
		panic(err.Error())
	}
	data := viper.GetStringMap("configs.data")
	confData := data["default.conf"].(string)
	splitN := strings.Split(confData, "location")

	//fmt.Println(splitN[0])
	s := strings.Join(splitN,"location")
	fmt.Println(s)
}
package main

import (
	"flag"
	"fmt"
	"github.com/spf13/viper"
	"io/ioutil"
	"os"
	"regexp"
	"strings"
)

var (
	app string
)

const (
	rule1 = "appType: nginx"
)

func checkFile(filename string) {
	//检测文件是否以backup为开头
	if !strings.HasPrefix(filename, "backup") {
		//检测文件是否以 yaml或者yml为结尾
		if strings.HasSuffix(filename, "ymal") || strings.HasSuffix(filename, "yml") {
			bytes, err := os.ReadFile(filename)
			if err != nil {
				panic(err.Error())
			}
			//判断文件内容是否包含 appType: nginx,如果包含这个才是前端文件
			if regexp.MustCompile(rule1).MatchString(string(bytes)) {
				updateFile(filename)
			}
		}
	}

}

func addFile(dirName string) []string {
	var ret []string
	fileInfo, err := ioutil.ReadDir(dirName)
	if err != nil {
		fmt.Println(err)
		return ret
	}

	for _, fi := range fileInfo {
		fileName := dirName + "/" + fi.Name()
		//fmt.Printf("%s%s\n", s, fileName)
		if fi.IsDir() {
			tmpRes := addFile(fileName)
			ret = append(ret, tmpRes...)
		} else {
			ret = append(ret, fileName)
		}
	}
	return ret
}

func replaceStr(filename,old,new string)  {
	bytes, err := os.ReadFile(filename)
	if err != nil {
		panic(err.Error())
	}

	var result string
	for _,v := range bytes{
		result = result + string(v)
	}
	replace := strings.Replace(result, old, new, -1)
	os.Remove(filename)

	//创建新文件
	file, err := os.OpenFile(filename, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0666)
	if err != nil {
		panic(err.Error())
	}
	file.WriteString(replace)
	//fmt.Printf("修改文件 %s 成功========================================\n", filename)
	defer file.Close()
}


func updateFile(filename string)  {
	replaceStr(filename,"default.conf","default-conf")
	viper.SetConfigType("yaml")
	viper.SetConfigFile(filename)
	err := viper.ReadInConfig()
	if err != nil {
		panic(err.Error())
	}
	keys := viper.AllKeys()
	for _,v := range keys{
		if regexp.MustCompile("configs.data.default-conf").MatchString(v){
			data := viper.GetString("configs.data.default-conf")
			locations := strings.Split(data, "}")
			rule2 := fmt.Sprintf("location.*/%s-.*", app)
			rule3 := fmt.Sprintf("location.*/%s", app)

			var ret []string
			for _,v := range locations{
				if regexp.MustCompile(rule3).MatchString(v) {
					if regexp.MustCompile(rule2).MatchString(v){
						ret = append(ret, v)
					}
				} else {
					ret = append(ret,v)
				}
			}
			result := strings.Join(ret, "}")
			fmt.Println(result)
			viper.Set("configs.data.default-conf",result)
			viper.WriteConfig()
			replaceStr(filename,"default-conf","default.conf")
		}
	}

}

func main() {
	flag.StringVar(&app, "app", "", "请输入要替换的location名字")
	flag.Parse()
	//fileList := addFile(".")
	//for _, filename := range fileList {
	//	checkFile(filename)
	//}
	checkFile("fe-application-admin_prod_values.yml")
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值