华为云CDN刷新与查询余量的Go实现及在Jenkins中的部署

引言

在华为云上,对CDN缓存内容进行刷新是一个常见的需求,以确保最新的内容能尽快被用户访问到。通过使用Go语言,我们可以开发一个自动化的工具来实现这一需求,并将其集成到Jenkins中以实现持续部署。下面我们将分步骤讲解如何实现。

1. 实现CDN的刷新

要用Go实现华为云CDN的刷新工作,我们需要首先安装go-sdk,这是华为云为Go开发者提供的SDK,包含了操作华为云服务的API接口。

步骤1.1 安装华为云官方Go SDK

我们可以使用go get命令来安装SDK:

go get -u github.com/huaweicloud/huaweicloud-sdk-go-v3

步骤1.2 创建CDN刷新任务

使用华为云apiexplorer查看一下cdn的实例代码:
image.png
创建刷新缓存任务实例,有V1 V2版本区别,但是看了一眼,目测代码没有什么区别,这里就继续使用v1版本了:

package main

import (
	"fmt"
	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/global"
    cdn "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/cdn/v1"
	"github.com/huaweicloud/huaweicloud-sdk-go-v3/services/cdn/v1/model"
    region "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/cdn/v1/region"
)

func main() {
    // The AK and SK used for authentication are hard-coded or stored in plaintext, which has great security risks. It is recommended that the AK and SK be stored in ciphertext in configuration files or environment variables and decrypted during use to ensure security.
    // In this example, AK and SK are stored in environment variables for authentication. Before running this example, set environment variables CLOUD_SDK_AK and CLOUD_SDK_SK in the local environment
    ak := os.Getenv("CLOUD_SDK_AK")
    sk := os.Getenv("CLOUD_SDK_SK")

    auth := global.NewCredentialsBuilder().
        WithAk(ak).
        WithSk(sk).
        Build()

    client := cdn.NewCdnClient(
        cdn.CdnClientBuilder().
            WithRegion(region.ValueOf("cn-north-1")).
            WithCredential(auth).
            Build())

    request := &model.CreateRefreshTasksRequest{}
	request.Body = &model.RefreshTaskRequest{
	}
	response, err := client.CreateRefreshTasks(request)
	if err == nil {
        fmt.Printf("%+v\n", response)
    } else {
        fmt.Println(err)
    }
}

根据上面的代码做一个简单的实例,演示如何使用华为云Go SDK创建CDN刷新任务:
域名使用 传入的方式,这里就直接使用了os.Args,传递参数:

package main

import (
	"fmt"
	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/global"
	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/config"
	cdn "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/cdn/v1"
	"github.com/huaweicloud/huaweicloud-sdk-go-v3/services/cdn/v1/model"
	"github.com/huaweicloud/huaweicloud-sdk-go-v3/services/cdn/v1/region"
	"os"
)

func main() {
	if len(os.Args) < 2 {
		fmt.Println("Usage: go run main.go <your-cdn-url>")
		return
	}

	cdnUrl := os.Args[1]

	ak := "YOUR_ACCESS_KEY"
	sk := "YOUR_SECRET_KEY"
	auth := global.NewCredentialsBuilder().
		WithAk(ak).
		WithSk(sk).
		Build()

	hcClient := cdn.NewCdnClient(
		cdn.CdnClientBuilder().
			WithRegion(region.ValueOf("cn-north-1")).
			WithCredential(auth).
			WithHttpConfig(config.DefaultHttpConfig()).
			Build())
	// Create CDN refresh task
	createRefreshTask(hcClient, cdnUrl)
}

func createRefreshTask(hcClient *cdn.CdnClient, cdnUrl string) {
	refreshTaskRequest := &model.CreateRefreshTasksRequest{}
	typeRefreshTask := model.GetRefreshTaskRequestBodyTypeEnum().DIRECTORY
	modeRefreshTask := model.GetRefreshTaskRequestBodyModeEnum().DETECT_MODIFY_REFRESH
	zhUrlEncodeRefreshTask := false
	refreshTaskbody := &model.RefreshTaskRequestBody{
		Type:        &typeRefreshTask,
		Mode:        &modeRefreshTask,
		ZhUrlEncode: &zhUrlEncodeRefreshTask,
		Urls:        []string{cdnUrl},
	}
	refreshTaskRequest.Body = &model.RefreshTaskRequest{
		RefreshTask: refreshTaskbody,
	}
	// Create the refresh task
	response, err := hcClient.CreateRefreshTasks(refreshTaskRequest)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error creating CDN refresh task: %s\n", err)
		os.Exit(2)
	}

	fmt.Printf("CDN refresh task created successfully: %s\n", response)
}

在上述代码中,替换**YOUR_ACCESS_KEY****YOUR_SECRET_KEY**为你的华为云账号的密钥信息。
尝试运行脚本:

go run main.go https://xxx.xxx.com/

image.png
末尾以**/**单斜线结尾!
注:以上代码以刷新目录为例,且只刷新变更资源!具体参数或者其他需求可以参考:https://console.huaweicloud.com/apiexplorer/#/openapi/CDN/doc?version=v1&api=CreateRefreshTasks,文档中参数!

2. 查询file URL余量

在创建刷新任务后,我们可能还需要查询当前账户下的URL刷新余量,以确保后续操作不会受到次数限制的影响。

步骤2.1 查询CDN file URL余量

可以在上面的Go程序中继续添加以下查询余量的代码片段:
参照:https://console.huaweicloud.com/apiexplorer/#/openapi/CDN/debug?version=v1&api=ShowQuota
image.png
尝试调试,查看返回值数据结构,编写代码如下:

// 查询URL 目录余量
func queryCdnQuota(hcClient *cdn.CdnClient) {
	request := &model.ShowQuotaRequest{}
	response, err := hcClient.ShowQuota(request)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error querying CDN quota: %s\n", err)
		os.Exit(2)
	}

	// 请确保 response.Quotas 不是nil,否则可能会导致空指针异常
	if response.Quotas == nil {
		fmt.Fprintln(os.Stderr, "Error: received nil Quotas in response")
		os.Exit(2)
	}

	// 自定义类型名称的映射
	typeNameMap := map[string]string{
		"file_refresh": "缓存刷新剩余Url条数",
		"dir_refresh":  "缓存刷新剩余目录数",
	}

	// Print out the customized quota information
	fmt.Println("CDN quota information:")
	for _, quota := range *response.Quotas {
		// 检查quota.Type是否为我们关心的类型之一
		if customName, ok := typeNameMap[*quota.Type]; ok {
			remaining := *quota.QuotaLimit - *quota.Used
			fmt.Printf("- %s: %d\n", customName, remaining)
		}
	}
}

在main函数中增加一下代码:

	queryCdnQuota(hcClient)

此片段會在创建CDN刷新任务之后调用ShowQuota接口,查询并打印出当前账户的URL以及目录刷新余量信息。typeNameMap部分是我想自定义一下输出打印的名称,增加可读性!
完成代码如下:

package main

import (
	"fmt"
	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/global"
	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/config"
	cdn "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/cdn/v1"
	"github.com/huaweicloud/huaweicloud-sdk-go-v3/services/cdn/v1/model"
	"github.com/huaweicloud/huaweicloud-sdk-go-v3/services/cdn/v1/region"
	"os"
)

func main() {
	if len(os.Args) < 2 {
		fmt.Println("Usage: go run main.go <your-cdn-url>")
		return
	}

	cdnUrl := os.Args[1]

	ak := "YOUR_ACCESS_KEY"
	sk := "YOUR_SECRET_KEY"
	auth := global.NewCredentialsBuilder().
		WithAk(ak).
		WithSk(sk).
		Build()

	hcClient := cdn.NewCdnClient(
		cdn.CdnClientBuilder().
			WithRegion(region.ValueOf("cn-north-1")).
			WithCredential(auth).
			WithHttpConfig(config.DefaultHttpConfig()).
			Build())
	// Create CDN refresh task
	createRefreshTask(hcClient, cdnUrl)
}

func createRefreshTask(hcClient *cdn.CdnClient, cdnUrl string) {
	refreshTaskRequest := &model.CreateRefreshTasksRequest{}
	typeRefreshTask := model.GetRefreshTaskRequestBodyTypeEnum().DIRECTORY
	modeRefreshTask := model.GetRefreshTaskRequestBodyModeEnum().DETECT_MODIFY_REFRESH
	zhUrlEncodeRefreshTask := false
	refreshTaskbody := &model.RefreshTaskRequestBody{
		Type:        &typeRefreshTask,
		Mode:        &modeRefreshTask,
		ZhUrlEncode: &zhUrlEncodeRefreshTask,
		Urls:        []string{cdnUrl},
	}
	refreshTaskRequest.Body = &model.RefreshTaskRequest{
		RefreshTask: refreshTaskbody,
	}
	// Create the refresh task
	response, err := hcClient.CreateRefreshTasks(refreshTaskRequest)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error creating CDN refresh task: %s\n", err)
		os.Exit(2)
	}

	fmt.Printf("CDN refresh task created successfully: %s\n", response)
}

运行代码返回数据格式如下:

go run main.go https://xxx.xxx.com/

image.png

3. 在Jenkins节点上运行程序

一旦我们的Go程序可以正确执行CDN刷新和查询余量的操作,接下来的步骤就是在Jenkins中配置该程序的运行环境。

步骤3.1 创建一个新的Jenkins任务

在Jenkins中创建一个Freestyle项目或者Pipeline项目,此部分取决于你的工作流。为了简便说明,我们这里以Freestyle项目为例。

步骤3.2 配置构建步骤

首先添加一个参数化构建过程,传入参数:
image.png
限制一下可运行的节点:
image.png

在你的Jenkins任务配置页中,添加一个构建步骤,选择“Execute shell”(对于Linux系统)或“Execute Windows batch command”(对于Windows系统),并填入以下内容:
image.png

# 假设你的Go程序名为`main`,且已经编译到Jenkins的工作空间中
cd /home/flush-hw&&./main $dir

确保构建环境中已经安装了Go运行时,并且环境变量已经配置,这样main程序才可以在Jenkins节点上运行没有问题。
注:main要有可执行权限,复制过来要记得chmod +x main .

4. 使用Jenkins Credentials管理AK/SK密钥

为了避免在代码中硬编码敏感信息,如Access Key和Secret Key,推荐使用Jenkins的Credentials插件来管理这些密钥。

步骤4.1 添加Credentials

在Jenkins中进入Credentials管理页面,添加一个新的Credentials,选择“Secret text”,其中**Secret**字段填入AK:SK的格式。记住这里的**ID,**接下来绑定的时候会用到
image.png
image.png

步骤4.2 修改Go程序以获取Credentials

之后,你需要修改Go程序,让其从环境变量中读取AK和SK。例如:

package main

import (
	"fmt"
	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/global"
	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/config"
	cdn "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/cdn/v1"
	"github.com/huaweicloud/huaweicloud-sdk-go-v3/services/cdn/v1/model"
	"github.com/huaweicloud/huaweicloud-sdk-go-v3/services/cdn/v1/region"
	"os"
	"strings"
)

func main() {
	if len(os.Args) < 2 {
		fmt.Println("Usage: go run main.go <your-cdn-url>")
		return
	}

	cdnUrl := os.Args[1]

	// 尝试从环境变量中获取ak和sk
	creds := os.Getenv("huaweiyun-hn-cdn")
	if creds == "" {
		fmt.Fprintln(os.Stderr, "Error: Credentials environment variable is not set.")
		os.Exit(1)
	}

	parts := strings.SplitN(creds, ":", 2)
	if len(parts) != 2 {
		fmt.Fprintln(os.Stderr, "Error: Invalid credential format. Expected 'AK:SK'.")
		os.Exit(1)
	}

	ak, sk := parts[0], parts[1]
	auth := global.NewCredentialsBuilder().
		WithAk(ak).
		WithSk(sk).
		Build()

	hcClient := cdn.NewCdnClient(
		cdn.CdnClientBuilder().
			WithRegion(region.ValueOf("cn-north-1")).
			WithCredential(auth).
			WithHttpConfig(config.DefaultHttpConfig()).
			Build())
	// Create CDN refresh task
	createRefreshTask(hcClient, cdnUrl)

	// Query remaining refresh and preload quota
	queryCdnQuota(hcClient)
}

func createRefreshTask(hcClient *cdn.CdnClient, cdnUrl string) {
	refreshTaskRequest := &model.CreateRefreshTasksRequest{}
	typeRefreshTask := model.GetRefreshTaskRequestBodyTypeEnum().DIRECTORY
	modeRefreshTask := model.GetRefreshTaskRequestBodyModeEnum().DETECT_MODIFY_REFRESH
	zhUrlEncodeRefreshTask := false
	refreshTaskbody := &model.RefreshTaskRequestBody{
		Type:        &typeRefreshTask,
		Mode:        &modeRefreshTask,
		ZhUrlEncode: &zhUrlEncodeRefreshTask,
		Urls:        []string{cdnUrl},
	}
	refreshTaskRequest.Body = &model.RefreshTaskRequest{
		RefreshTask: refreshTaskbody,
	}
	// Create the refresh task
	response, err := hcClient.CreateRefreshTasks(refreshTaskRequest)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error creating CDN refresh task: %s\n", err)
		os.Exit(2)
	}

	fmt.Printf("CDN refresh task created successfully: %s\n", response)
}
func queryCdnQuota(hcClient *cdn.CdnClient) {
	request := &model.ShowQuotaRequest{}
	response, err := hcClient.ShowQuota(request)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error querying CDN quota: %s\n", err)
		os.Exit(2)
	}

	// 请确保 response.Quotas 不是nil,否则可能会导致空指针异常
	if response.Quotas == nil {
		fmt.Fprintln(os.Stderr, "Error: received nil Quotas in response")
		os.Exit(2)
	}

	// 自定义类型名称的映射
	typeNameMap := map[string]string{
		"file_refresh": "缓存刷新剩余Url条数",
		"dir_refresh":  "缓存刷新剩余目录数",
	}

	// Print out the customized quota information
	fmt.Println("CDN quota information:")
	for _, quota := range *response.Quotas {
		// 检查quota.Type是否为我们关心的类型之一
		if customName, ok := typeNameMap[*quota.Type]; ok {
			remaining := *quota.QuotaLimit - *quota.Used
			fmt.Printf("- %s: %d\n", customName, remaining)
		}
	}
}

步骤4.3 配置Jenkins任务以传递Credentials

在Jenkins任务的构建环境配置中,使用Credentials Binding插件将新添加的Credentials绑定到相应的环境变量中。在“Build Environment”选择“Use secret text(s) or file(s)”,命名为xxx并绑定AK/SK到指定凭据:
image.png

步骤4.4 测试运行

最后,在Jenkins中运行配置好的任务,检查输出以确保CDN刷新和余量查询均运行顺利。
image.png
image.png

5. 其他的需求

1. 经常输入域名的时候忘记/单斜线,是否可以自动补全?

2. 设置改阈值?剩余量到20可以自动报警?邮件or短信

3. 优雅的pipeline?

结语

通过上述步骤,我们成功地实现了通过Go语言操作华为云CDN刷新服务的功能,并将其集成到Jenkins任务中,同时安全地管理了敏感的AK/SK凭证。这样的自动化工具对于管理大量的CDN资源来说非常有用,可以大大提高工作效率。
注:以上大纲chatgpt生成代码结构也是,代码基本也是chatgpt生成,貌似中间就有几个&指针数据格式有问题修改了一下

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MySQL递归查询:洞悉数据的层层关联

在处理关系型数据库时&#xff0c;我们经常会遇到这样的情况&#xff1a;某些数据之间存在层级关系&#xff0c;例如目录、组织结构、评论等。在这些场景下&#xff0c;我们需要一种灵活的查询技术来处理这种层级关系。今天我们就来探讨MySQL中的递归查询&#xff0c;体验其独特…

ThinkPHP6学生选课管理系统

有需要请加文章底部Q哦 可远程调试 ThinkPHP6学生选课管理系统 一 介绍 此学生选课管理系统基于ThinkPHP6框架开发&#xff0c;数据库mysql8&#xff0c;前端bootstrap。系统角色分为学生&#xff0c;教师和管理员。学生登录后可进行选课&#xff0c;教师登录后可查看选课情况…

Android : 获取、添加、手机联系人-ContentResolver简单应用

示例图&#xff1a; MainActivity.java package com.example.mygetdata;import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat;import android.Mani…

图书管理系统源码,图书管理系统开发,图书借阅系统源码四TuShuManager应用程序MVC视图View

Asp.net web应用程序MVC之View视图 .ASP.NET MVC页面也就是要说的视图基本被放在Views文件夹下&#xff1b; 2.利用APS.NET MVC模板生成框架&#xff0c;Views文件夹下的默认页面为.cshtml页面&#xff1b; 3.ASP.NET MVC默认页面为Razor格式的页面&#xff0c;因此默认页面为.…

三、Lua变量

文章目录 一、变量分类二、变量赋值三、索引 一、变量分类 lua变量分为全局变量&#xff0c;局部变量。 全局变量&#xff1a;默认&#xff0c;全局有效。 局部变量&#xff1a;从作用范围开始到作用范围结束&#xff0c;需加local 修饰。 a1function ff()local b1 endprint(a…

spring boot的redis连接数过多导致redis服务器压力过大的一次问题排查

一、背景 在今天上午的时候&#xff0c;突然收到大量的sentry报错&#xff0c;都是关于redis连接超时的警告。 首先想到的是去查看redis的监控&#xff0c;发现那个时间段&#xff0c;redis的请求数剧增&#xff0c;cpu使用率和带宽都陡增双倍。 下面的是redis监控的cpu情况 …

Module build failed: Error: ENOENT: no such file or directory

前言 这个错误通常发生在Node.js 和 vue,js项目中&#xff0c;当你试图访问一个不存在的文件或目录时。在大多数情况下&#xff0c;这是因为你的代码试图打开一个不存在的文件&#xff0c;或者你的构建系统&#xff08;例如Webpack&#xff09;需要一个配置文件&#xff0c;但找…

程序员为什么要一直坚持写博客

shigen日更文章的博客写手&#xff0c;擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。记录成长&#xff0c;分享认知&#xff0c;留住感动。 今天的文章其实说和技术有关系也没有什么问题&#xff0c;算起来我日更文章已经快四个月了&#xff0c;从最初的…

四、Lua循环

文章目录 一、while(循环条件)二、for&#xff08;一&#xff09;数值for&#xff08;二&#xff09;泛型for&#xff08;三&#xff09;repeat util 既然同为编程语言&#xff0c;那么控制逻辑里的循环就不能缺少&#xff0c;它可以帮助我们实现有规律的重复操作&#xff0c;而…

洗地机应该怎么选?希亦、必胜、米博、添可、小米洗地机实测推荐

作为一个常年测评智能家居的博主&#xff0c;关于洗地机的测评使用这些年也积累了不少的体验感受。以至于常被周边的朋友问到&#xff0c;洗地机到底是不是真的好用&#xff1f;洗地机有什么优点吗&#xff1f;选购的时候应该怎么选呢&#xff1f;洗地机什么牌子比较好呢&#…

.NET6实现破解Modbus poll点表配置文件

📢欢迎点赞 :👍 收藏 ⭐留言 📝 如有错误敬请指正,赐人玫瑰,手留余香!📢本文作者:由webmote 原创📢作者格言:新的征程,我们面对的不仅仅是技术还有人心,人心不可测,海水不可量,唯有技术,才是深沉黑夜中的一座闪烁的灯塔 !序言 Modbus 协议是工控领域常见…

Elasticsearch:什么是非结构化数据?

非结构化数据定义 非结构化数据是指未按照设计的模型或结构组织的数据。 非结构化数据通常被归类为定性数据&#xff0c;可以是人类或机器生成的。 非结构化数据是最丰富的可用数据类型&#xff0c;经过分析后&#xff0c;可用于指导业务决策并在许多其他用例中实现业务目标。…

2015年五一杯数学建模B题空气污染问题研究解题全过程文档及程序

2015年五一杯数学建模 B题 空气污染问题研究 原题再现 近十年来&#xff0c;我国 GDP 持续快速增长&#xff0c;但经济增长模式相对传统落后&#xff0c;对生态平衡和自然环境造成一定的破坏&#xff0c;空气污染的弊病日益突出&#xff0c;特别是日益加重的雾霾天气已经干扰…

Node.js入门指南(五)

目录 MongoDB 介绍 下载与启动 命令行交互 Mongoose 代码模块化 图形化管理工具 hello&#xff0c;大家好&#xff01;上一篇文章我们介绍了express框架&#xff0c;这一篇文字主要介绍MongoDB。来对数据进行存储以及操作。 MongoDB 介绍 各位小伙伴应该多多少少都有接…

JMeter---BeanShell实现接口前置和后置操作

在JMeter中&#xff0c;可以使用BeanShell脚本来实现接口的前置和后置操作。 下面是使用BeanShell脚本实现接口前置和后置操作的步骤&#xff1a; 1、在测试计划中添加一个BeanShell前置处理器或后置处理器。 右键点击需要添加前置或后置操作的接口请求&#xff0c;选择&quo…

使用com组件编辑word

一个普通的窗体应用&#xff0c;6个button using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; u…

西南科技大学电路分析基础实验A1(元件伏安特性测试 )

目录 一、实验目的 二、实验设备 三、预习内容(如:基本原理、电路图、计算值等) 1、测定线性电阻的伏安特性 2、二极管伏安特性测试 3、测定实际电压源的伏安特性 四、实验数据及结果分析(预习写必要实验步骤和表格) 1、测定线性电阻的伏安特性 2、二极管伏安特性测…

RT-DETR改进 | 2023 | InnerEIoU、InnerSIoU、InnerWIoU、InnerDIoU等二十余种损失函数

论文地址&#xff1a;官方Inner-IoU论文地址点击即可跳转 官方代码地址&#xff1a;官方代码地址-官方只放出了两种结合方式CIoU、SIoU 本位改进地址&#xff1a; 文末提供完整代码块-包括InnerEIoU、InnerCIoU、InnerDIoU等七种结合方式和其AlphaIoU变种结合起来可以达到二十…

JAVA进阶之路JVM-1:jvm基本组成、java程序执行过程、java程序的跨平台、静态编译器、jvm执行方式

JVM基本组成 当线上系统突然宕机&#xff0c;系统无法访问&#xff0c;甚至直接OOM&#xff1b; 线上系统响应速度太慢&#xff0c;优化系统性能过程中发现CPU占用过高&#xff0c;原因也许是因为JVM的GC次数过于频繁 因此&#xff0c;新项目上线&#xff0c;需要设置JVM的各…