jenkins Job华为云EIP变更带宽

引言:

在数字化时代,云服务资源的弹性管理是企业降低运营成本、提高效率的关键手段。通过弹性公网IP(EIP)服务,企业可以实现按需计费,优化网络支出。然而,根据业务流量的不同阶段调整计费模式,则是提升成本效益的进阶策略。本人腾讯云快十年老用户乘机吐槽一下腾讯云(由于我在大有所为的某云上面已经简单实现了更改流程):
习惯了使用apiexplorer这样的工具生成代码进行修改,参考一下友商的:
image.png
然后我的腾讯云弹性公网IP ?EIP 对吧?
image.png
这是什么样的体验?完全搜索不到?关键词EIP **弹性公网 **完全搜索不到…
image.png
image.png
最后我在这里找到了:
绑定弹性公网IP
image.png
你可以归于私有网络?是不是应该好歹独立一下…
image.png
吐槽完毕,本文将详细介绍如何使用华为云Go SDK在流量高峰时自动调整EIP带宽设置,并在峰值过后恢复原计费模式。

业务背景:

考虑到一家在线互动应用提供商,主要架构是websockt 长链接,其流量在晚高峰时段飙升,观众涌入平台进行抢红包等互动活动。活动时常大概在一个小时。在流量高峰时,固定带宽的使用能保证用户的观看体验,且相对于按流量计费,成本更为可控。因此,我们面临一个机遇,通过智能化工具调整EIP的带宽计费模式,在需要时提供稳定的网络资源和更优的财务开支。

技术方案:

服务器场景搭建在华为云上,使用了cce kubernetes服务。绑定了应用型负载均衡(负载均衡有本身的EIP公网IP),为了实现这一目标,我们选择华为云的Elastic IP服务,它提供了一系列API,允许程序化管理EIP资源。通过Go语言编写的定时任务,我们可以精确控制带宽的调整时机和规模。在本方案中,使用华为云提供的SDK,我们将编写一个Go应用程序,当业务流量达到高峰时,自动将EIP的计费模式从按流量计费调整为按带宽计费,并固定带宽大小。一小时后,系统自动将设置恢复为按流量计费,以节省成本。

代码实现:

参照以下代码实例:UpdateBandwidth 更新带宽方法:
image.png

package mainimport ("fmt""github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/basic"eip "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/eip/v2""github.com/huaweicloud/huaweicloud-sdk-go-v3/services/eip/v2/model"region "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/eip/v2/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 environmentak := os.Getenv("CLOUD_SDK_AK")sk := os.Getenv("CLOUD_SDK_SK")auth := basic.NewCredentialsBuilder().WithAk(ak).WithSk(sk).Build()client := eip.NewEipClient(eip.EipClientBuilder().WithRegion(region.ValueOf("cn-east-3")).WithCredential(auth).Build())request := &model.UpdatePublicipRequest{}request.Body = &model.UpdatePublicipsRequestBody{}response, err := client.UpdatePublicip(request)if err == nil {fmt.Printf("%+v\n", response)} else {fmt.Println(err)}
}

最终实现代码如下:

package mainimport ("fmt""time""github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/basic""github.com/huaweicloud/huaweicloud-sdk-go-v3/core/config"eip "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/eip/v2""github.com/huaweicloud/huaweicloud-sdk-go-v3/services/eip/v2/model"region "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/eip/v2/region"
)func main() {// Replace with your own AK/SK, Region, and Project ID.ak := "xxxxx"sk := "xxxxx"projectID := "xxxxx"// Authenticate using your Access Key and Secret Key.auth := basic.NewCredentialsBuilder().WithAk(ak).WithSk(sk).WithProjectId(projectID).Build()// Create EIP client configuration.eipClient := eip.NewEipClient(eip.EipClientBuilder().WithRegion(region.ValueOf("cn-east-3")).WithCredential(auth).WithHttpConfig(config.DefaultHttpConfig()).Build(),)// Replace the bandwidthId with your actual bandwidth ID.sizeBandwidth := int32(xxx)sizeTraefikBandwidth := int32(xxxx)// Update bandwidth to 10 Mbps and set to bandwidth billing mode.if err := updateBandwidth(eipClient, bandwidthId, "", sizeBandwidth, model.GetUpdateBandwidthOptionChargeModeEnum().BANDWIDTH); err != nil {fmt.Printf("Error updating bandwidth: %s\n", err)return}// Set a timer to switch back to traffic billing mode after 1 hour.time.AfterFunc(1*time.Hour, func() {if err := updateBandwidth(eipClient, bandwidthId, "", sizeTraefikBandwidth, model.GetUpdateBandwidthOptionChargeModeEnum().TRAFFIC); err != nil {fmt.Printf("Error reverting bandwidth: %s\n", err)return}})// Block the main goroutine to not exit immediately.select {}
}// Function to update the bandwidth of an EIP.
func updateBandwidth(client *eip.EipClient, bandwidthId, name string, size int32, chargeMode model.UpdateBandwidthOptionChargeMode) error {request := &model.UpdateBandwidthRequest{BandwidthId: bandwidthId,Body: &model.UpdateBandwidthRequestBody{Bandwidth: &model.UpdateBandwidthOption{Name:       &name,Size:       &size,ChargeMode: &chargeMode,},},}response, err := client.UpdateBandwidth(request)if err != nil {return err}fmt.Printf("Update response: %+v\n", response)return nil
}

初始化EIP客户端

首先,需设置客户端认证,这涉及到基础的Access Key(AK)和Secret Key(SK)配置:

ak := "REPLACE_WITH_YOUR_AK"
sk := "REPLACE_WITH_YOUR_SK"
projectID := "REPLACE_WITH_YOUR_PROJECT_ID"auth := basic.NewCredentialsBuilder().WithAk(ak).WithSk(sk).Build()client := eip.NewEipClient(eip.EipClientBuilder().WithRegion(region.ValueOf("cn-east-3")).WithCredential(auth).Build())
...

务必保障这些敏感信息在环境变量或加密存储中,避免硬编码在应用程序中。

更新带宽函数

updateBandwidth 函数对EIP带宽大小和计费模式进行修改。

func updateBandwidth(client *eip.EipClient, bandwidthId, name string, size int32, chargeMode model.UpdateBandwidthOptionChargeMode) error {request := &model.UpdateBandwidthRequest{BandwidthId: bandwidthId,Body: &model.UpdateBandwidthRequestBody{Bandwidth: &model.UpdateBandwidthOption{Name:       &name,Size:       &size,ChargeMode: &chargeMode,},},}response, err := client.UpdateBandwidth(request)if err != nil {return err}fmt.Printf("Update response: %+v\n", response)return nil
}

这个函数构造了更新带宽的API请求,并处理响应或可能出现的错误。

使用协程和定时器

Go的并发模型让我们能够用协程(goroutines)和定时器轻松实现这个需求。

	go func() {if err := updateBandwidth(eipClient, bandwidthId, "xxxxx", sizeBandwidth, model.GetUpdateBandwidthOptionChargeModeEnum().BANDWIDTH); err != nil {fmt.Printf("更新带宽时出错: %s\n", err)return}// 设置计时器在10分钟后切换回流量计费模式。timer := time.NewTimer(1 * time.Minute)<-timer.Cif err := updateBandwidth(eipClient, bandwidthId, "xxxxxx", sizeTrafficBandwidth, model.GetUpdateBandwidthOptionChargeModeEnum().TRAFFIC); err != nil {fmt.Printf("恢复带宽时出错: %s\n", err)return}}()// 使用通道阻塞主 goroutine 无限期。避免在空的 select 语句中旋转,这是不必要的。done := make(chan struct{})<-done
}

第一版代码

完整代码如下:

package mainimport ("fmt""time""github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/basic""github.com/huaweicloud/huaweicloud-sdk-go-v3/core/config"eip "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/eip/v2""github.com/huaweicloud/huaweicloud-sdk-go-v3/services/eip/v2/model"region "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/eip/v2/region"
)func main() {// Replace with your own AK/SK, Region, and Project ID.ak := "xxxxxx"sk := "xxxxxx"projectID := "xxxxxx"// Authenticate using your Access Key and Secret Key.auth := basic.NewCredentialsBuilder().WithAk(ak).WithSk(sk).WithProjectId(projectID).Build()// Create EIP client configuration.eipClient := eip.NewEipClient(eip.EipClientBuilder().WithRegion(region.ValueOf("cn-east-3")).WithCredential(auth).WithHttpConfig(config.DefaultHttpConfig()).Build(),)// Replace the bandwidthId with your actual bandwidth ID.bandwidthId := "xxxx"sizeBandwidth := int32(xxx)sizeTrafficBandwidth := int32(xxx)// Update bandwidth to 10 Mbps and set to bandwidth billing mode.if err := updateBandwidth(eipClient, bandwidthId, "xxxx", sizeBandwidth, model.GetUpdateBandwidthOptionChargeModeEnum().BANDWIDTH); err != nil {fmt.Printf("Error updating bandwidth: %s\n", err)return}// Set a timer to switch back to traffic billing mode after 1 hour.time.AfterFunc(1*time.Hour, func() {if err := updateBandwidth(eipClient, bandwidthId, "xxxxx", sizeBandwidth, model.GetUpdateBandwidthOptionChargeModeEnum().TRAFFIC); err != nil {fmt.Printf("Error reverting bandwidth: %s\n", err)return}})// Block the main goroutine to not exit immediately.select {}
}// Function to update the bandwidth of an EIP.
func updateBandwidth(client *eip.EipClient, bandwidthId, name string, size int32, chargeMode model.UpdateBandwidthOptionChargeMode) error {request := &model.UpdateBandwidthRequest{BandwidthId: bandwidthId,Body: &model.UpdateBandwidthRequestBody{Bandwidth: &model.UpdateBandwidthOption{Name:       &name,Size:       &size,ChargeMode: &chargeMode,},},}response, err := client.UpdateBandwidth(request)if err != nil {return err}fmt.Printf("Update response: %+v\n", response)return nil
}

运行main.go
xreUAjVvck.png
可以在控制台查看代码操作,控制台对应实例生效!

继续完善代码:

上面的代码是用户传入bandwidthId,这关键一般用户不知道bandwidthId 阿?控制台用户来说一般能知道的是公网IP
image.png
我这里想到的是使用ListPublicips-查询弹性公网IP列表获取bandwidth_name bandwidth_id。 创建两个函数:getBandwidthIdByPublicIP getBandwidthNameByPublicIP

// 这里假设有一个通过公网IP获取带宽ID的函数
func getBandwidthIdByPublicIP(client *eip.EipClient, publicIP string) (string, error) {// 首先构造查询请求request := &model.ListPublicipsRequest{// 根据需要设置查询参数}// 调用SDK方法查询EIP详情response, err := client.ListPublicips(request)if err != nil {return "", err}// 遍历响应中的公共IP地址for _, publicip := range *response.Publicips { // 假设返回的是指针指向的切片// 检查 PublicIpAddress 是否为nil,并解引用来比较值if publicip.PublicIpAddress != nil && *publicip.PublicIpAddress == publicIP {// 检查 BandwidthId 是否为nil,并解引用来返回值if publicip.BandwidthId != nil {return *publicip.BandwidthId, nil}break // 如果 BandwidthId 为nil,则结束循环}}// 如果没有找到匹配的公共IP地址或带宽ID是nil,则返回错误return "", errors.New("public IP not found or bandwidth ID is nil")
}
func getBandwidthNameByPublicIP(client *eip.EipClient, publicIP string) (string, error) {// 首先构造查询请求request := &model.ListPublicipsRequest{// 根据需要设置查询参数}// 调用SDK方法查询EIP详情response, err := client.ListPublicips(request)if err != nil {return "", err}// 遍历响应中的公共IP地址for _, publicip := range *response.Publicips { // 假设返回的是指针指向的切片// 检查 PublicIpAddress 是否为nil,并解引用来比较值if publicip.PublicIpAddress != nil && *publicip.PublicIpAddress == publicIP {// 检查 BandwidthId 是否为nil,并解引用来返回值if publicip.BandwidthName != nil {return *publicip.BandwidthName, nil}break // 如果 BandwidthId 为nil,则结束循环}}// 如果没有找到匹配的公共IP地址或带宽ID是nil,则返回错误return "", errors.New("public IP not found or bandwidth ID is nil")
}

继续完善一下,通过运行main.go传入公网IP,固定带宽恢复按量计费后的带宽大小,以及修改为固定带宽的持续时间 。

go run main.go publicIP  sizeBandwidth sizeTrafficBandwidth timerMinutes
package mainimport ("errors""fmt""os""strconv""time""github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/basic""github.com/huaweicloud/huaweicloud-sdk-go-v3/core/config"eip "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/eip/v2""github.com/huaweicloud/huaweicloud-sdk-go-v3/services/eip/v2/model"region "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/eip/v2/region"
)func main() {// Replace with your own AK/SK, Region, and Project ID.ak := "xxxxxx"sk := "xxxxxx"projectID := "xxxxxx"if len(os.Args) != 5 {fmt.Println("Usage: go run main.go <publicIP> <sizeBandwidth> <sizeTrafficBandwidth> <timerMinutes>")return}publicIP := os.Args[1]sizeBandwidth, err := strconv.Atoi(os.Args[2])if err != nil {fmt.Println("Invalid sizeBandwidth:", err)return}sizeTrafficBandwidth, err := strconv.Atoi(os.Args[3])if err != nil {fmt.Println("Invalid sizeTrafficBandwidth:", err)return}timerMinutes, err := strconv.Atoi(os.Args[4])if err != nil {fmt.Println("Invalid timerMinutes:", err)return}// Authenticate using your Access Key and Secret Key.auth := basic.NewCredentialsBuilder().WithAk(ak).WithSk(sk).WithProjectId(projectID).Build()// Create EIP client configuration.eipClient := eip.NewEipClient(eip.EipClientBuilder().WithRegion(region.ValueOf("cn-east-3")).WithCredential(auth).WithHttpConfig(config.DefaultHttpConfig()).Build(),)bandwidthId, err := getBandwidthIdByPublicIP(eipClient, publicIP)if err != nil {fmt.Println(err)return}bandwidthName, err := getBandwidthNameByPublicIP(eipClient, publicIP)if err != nil {fmt.Println(err)return}go func() {if err := updateBandwidth(eipClient, bandwidthId, bandwidthName, int32(sizeBandwidth), model.GetUpdateBandwidthOptionChargeModeEnum().BANDWIDTH); err != nil {fmt.Printf("更新带宽时出错: %s\n", err)return}// 设置计时器在10分钟后切换回流量计费模式。timer := time.NewTimer(time.Duration(timerMinutes) * time.Minute)<-timer.Cif err := updateBandwidth(eipClient, bandwidthId, bandwidthName, int32(sizeTrafficBandwidth), model.GetUpdateBandwidthOptionChargeModeEnum().TRAFFIC); err != nil {fmt.Printf("恢复带宽时出错: %s\n", err)return}}()// 使用通道阻塞主 goroutine 无限期。避免在空的 select 语句中旋转,这是不必要的。done := make(chan struct{})<-done
}// 这里假设有一个通过公网IP获取带宽ID的函数
func getBandwidthIdByPublicIP(client *eip.EipClient, publicIP string) (string, error) {// 首先构造查询请求request := &model.ListPublicipsRequest{// 根据需要设置查询参数}// 调用SDK方法查询EIP详情response, err := client.ListPublicips(request)if err != nil {return "", err}// 遍历响应中的公共IP地址for _, publicip := range *response.Publicips { // 假设返回的是指针指向的切片// 检查 PublicIpAddress 是否为nil,并解引用来比较值if publicip.PublicIpAddress != nil && *publicip.PublicIpAddress == publicIP {// 检查 BandwidthId 是否为nil,并解引用来返回值if publicip.BandwidthId != nil {return *publicip.BandwidthId, nil}break // 如果 BandwidthId 为nil,则结束循环}}// 如果没有找到匹配的公共IP地址或带宽ID是nil,则返回错误return "", errors.New("public IP not found or bandwidth ID is nil")
}
func getBandwidthNameByPublicIP(client *eip.EipClient, publicIP string) (string, error) {// 首先构造查询请求request := &model.ListPublicipsRequest{// 根据需要设置查询参数}// 调用SDK方法查询EIP详情response, err := client.ListPublicips(request)if err != nil {return "", err}// 遍历响应中的公共IP地址for _, publicip := range *response.Publicips { // 假设返回的是指针指向的切片// 检查 PublicIpAddress 是否为nil,并解引用来比较值if publicip.PublicIpAddress != nil && *publicip.PublicIpAddress == publicIP {// 检查 BandwidthId 是否为nil,并解引用来返回值if publicip.BandwidthName != nil {return *publicip.BandwidthName, nil}break // 如果 BandwidthId 为nil,则结束循环}}// 如果没有找到匹配的公共IP地址或带宽ID是nil,则返回错误return "", errors.New("public IP not found or bandwidth ID is nil")
}// Function to update the bandwidth of an EIP.
func updateBandwidth(client *eip.EipClient, bandwidthId, name string, size int32, chargeMode model.UpdateBandwidthOptionChargeMode) error {request := &model.UpdateBandwidthRequest{BandwidthId: bandwidthId,Body: &model.UpdateBandwidthRequestBody{Bandwidth: &model.UpdateBandwidthOption{Name:       &name,Size:       &size,ChargeMode: &chargeMode,},},}response, err := client.UpdateBandwidth(request)if err != nil {return err}fmt.Printf("Update response: %+v\n", response)return nil
}

jenkins运行以上代码实例

最终我需要在jenkins中运行这个更改流量的任务,我将引用ak,sk引用jenkins凭据的方式:
参照之前刷新cdn时候引用凭据的方式:
image.png
最终代码如下:

package mainimport ("errors""fmt""os""strconv""time""github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/basic""github.com/huaweicloud/huaweicloud-sdk-go-v3/core/config"eip "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/eip/v2""github.com/huaweicloud/huaweicloud-sdk-go-v3/services/eip/v2/model"region "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/eip/v2/region"
)func main() {// Replace with your own AK/SK, Region, and Project ID.// 尝试从环境变量中获取ak和skcreds := 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]projectID := "xxxxxx"if len(os.Args) != 5 {fmt.Println("Usage: go run main.go <publicIP> <sizeBandwidth> <sizeTrafficBandwidth> <timerMinutes>")return}publicIP := os.Args[1]sizeBandwidth, err := strconv.Atoi(os.Args[2])if err != nil {fmt.Println("Invalid sizeBandwidth:", err)return}sizeTrafficBandwidth, err := strconv.Atoi(os.Args[3])if err != nil {fmt.Println("Invalid sizeTrafficBandwidth:", err)return}timerMinutes, err := strconv.Atoi(os.Args[4])if err != nil {fmt.Println("Invalid timerMinutes:", err)return}// Authenticate using your Access Key and Secret Key.auth := basic.NewCredentialsBuilder().WithAk(ak).WithSk(sk).WithProjectId(projectID).Build()// Create EIP client configuration.eipClient := eip.NewEipClient(eip.EipClientBuilder().WithRegion(region.ValueOf("cn-east-3")).WithCredential(auth).WithHttpConfig(config.DefaultHttpConfig()).Build(),)bandwidthId, err := getBandwidthIdByPublicIP(eipClient, publicIP)if err != nil {fmt.Println(err)return}bandwidthName, err := getBandwidthNameByPublicIP(eipClient, publicIP)if err != nil {fmt.Println(err)return}go func() {if err := updateBandwidth(eipClient, bandwidthId, bandwidthName, int32(sizeBandwidth), model.GetUpdateBandwidthOptionChargeModeEnum().BANDWIDTH); err != nil {fmt.Printf("更新带宽时出错: %s\n", err)return}// 设置计时器在10分钟后切换回流量计费模式。timer := time.NewTimer(time.Duration(timerMinutes) * time.Minute)<-timer.Cif err := updateBandwidth(eipClient, bandwidthId, bandwidthName, int32(sizeTrafficBandwidth), model.GetUpdateBandwidthOptionChargeModeEnum().TRAFFIC); err != nil {fmt.Printf("恢复带宽时出错: %s\n", err)return}}()// 使用通道阻塞主 goroutine 无限期。避免在空的 select 语句中旋转,这是不必要的。done := make(chan struct{})<-done
}// 这里假设有一个通过公网IP获取带宽ID的函数
func getBandwidthIdByPublicIP(client *eip.EipClient, publicIP string) (string, error) {// 首先构造查询请求request := &model.ListPublicipsRequest{// 根据需要设置查询参数}// 调用SDK方法查询EIP详情response, err := client.ListPublicips(request)if err != nil {return "", err}// 遍历响应中的公共IP地址for _, publicip := range *response.Publicips { // 假设返回的是指针指向的切片// 检查 PublicIpAddress 是否为nil,并解引用来比较值if publicip.PublicIpAddress != nil && *publicip.PublicIpAddress == publicIP {// 检查 BandwidthId 是否为nil,并解引用来返回值if publicip.BandwidthId != nil {return *publicip.BandwidthId, nil}break // 如果 BandwidthId 为nil,则结束循环}}// 如果没有找到匹配的公共IP地址或带宽ID是nil,则返回错误return "", errors.New("public IP not found or bandwidth ID is nil")
}
func getBandwidthNameByPublicIP(client *eip.EipClient, publicIP string) (string, error) {// 首先构造查询请求request := &model.ListPublicipsRequest{// 根据需要设置查询参数}// 调用SDK方法查询EIP详情response, err := client.ListPublicips(request)if err != nil {return "", err}// 遍历响应中的公共IP地址for _, publicip := range *response.Publicips { // 假设返回的是指针指向的切片// 检查 PublicIpAddress 是否为nil,并解引用来比较值if publicip.PublicIpAddress != nil && *publicip.PublicIpAddress == publicIP {// 检查 BandwidthId 是否为nil,并解引用来返回值if publicip.BandwidthName != nil {return *publicip.BandwidthName, nil}break // 如果 BandwidthId 为nil,则结束循环}}// 如果没有找到匹配的公共IP地址或带宽ID是nil,则返回错误return "", errors.New("public IP not found or bandwidth ID is nil")
}// Function to update the bandwidth of an EIP.
func updateBandwidth(client *eip.EipClient, bandwidthId, name string, size int32, chargeMode model.UpdateBandwidthOptionChargeMode) error {request := &model.UpdateBandwidthRequest{BandwidthId: bandwidthId,Body: &model.UpdateBandwidthRequestBody{Bandwidth: &model.UpdateBandwidthOption{Name:       &name,Size:       &size,ChargeMode: &chargeMode,},},}response, err := client.UpdateBandwidth(request)if err != nil {return err}fmt.Printf("Update response: %+v\n", response)return nil
}

go build main.go,编译为可执行程序!将可执行程序放在工作节点上,jenkins 做了一个demo
参数化构建,字符参数
image.png
绑定密钥文件:
image.png
Build Steps 执行shell

cd /home/eip-hw&&./main $publicIP $sizeBandwidth $sizeTrafficBandwidth $timerMinutes

image.png
输入publicIP运行程序:
image.png
程序运行生效,但是进程没有退出:

image.png

最终go相关代码:

继续完善一下代码,当程序运行完成后,退出程序。输出Bandwidth update successful, exiting:

package mainimport ("errors""fmt""os""strconv""time""strings""github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/basic""github.com/huaweicloud/huaweicloud-sdk-go-v3/core/config"eip "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/eip/v2""github.com/huaweicloud/huaweicloud-sdk-go-v3/services/eip/v2/model"region "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/eip/v2/region"
)func main() {// Replace with your own AK/SK, Region, and Project ID.// 尝试从环境变量中获取ak和skcreds := os.Getenv("xxxxxx")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]projectID := "xxxxxx"if len(os.Args) != 5 {fmt.Println("Usage: go run main.go <publicIP> <sizeBandwidth> <sizeTrafficBandwidth> <timerMinutes>")return}publicIP := os.Args[1]sizeBandwidth, err := strconv.Atoi(os.Args[2])if err != nil {fmt.Println("Invalid sizeBandwidth:", err)return}sizeTrafficBandwidth, err := strconv.Atoi(os.Args[3])if err != nil {fmt.Println("Invalid sizeTrafficBandwidth:", err)return}timerMinutes, err := strconv.Atoi(os.Args[4])if err != nil {fmt.Println("Invalid timerMinutes:", err)return}// Authenticate using your Access Key and Secret Key.auth := basic.NewCredentialsBuilder().WithAk(ak).WithSk(sk).WithProjectId(projectID).Build()// Create EIP client configuration.eipClient := eip.NewEipClient(eip.EipClientBuilder().WithRegion(region.ValueOf("cn-east-3")).WithCredential(auth).WithHttpConfig(config.DefaultHttpConfig()).Build(),)bandwidthId, err := getBandwidthIdByPublicIP(eipClient, publicIP)if err != nil {fmt.Println(err)return}bandwidthName, err := getBandwidthNameByPublicIP(eipClient, publicIP)if err != nil {fmt.Println(err)return}go func() {if err := updateBandwidth(eipClient, bandwidthId, bandwidthName, int32(sizeBandwidth), model.GetUpdateBandwidthOptionChargeModeEnum().BANDWIDTH); err != nil {fmt.Printf("更新带宽时出错: %s\n", err)os.Exit(1)return}// 设置计时器在10分钟后切换回流量计费模式。timer := time.NewTimer(time.Duration(timerMinutes) * time.Minute)<-timer.Cif err := updateBandwidth(eipClient, bandwidthId, bandwidthName, int32(sizeTrafficBandwidth), model.GetUpdateBandwidthOptionChargeModeEnum().TRAFFIC); err != nil {fmt.Printf("恢复带宽时出错: %s\n", err)os.Exit(1)return}fmt.Println("Bandwidth update successful, exiting.") // Log success messageos.Exit(0) // Exit the process after success}()// 使用通道阻塞主 goroutine 无限期。避免在空的 select 语句中旋转,这是不必要的。done := make(chan struct{})<-done
}// 这里假设有一个通过公网IP获取带宽ID的函数
func getBandwidthIdByPublicIP(client *eip.EipClient, publicIP string) (string, error) {// 首先构造查询请求request := &model.ListPublicipsRequest{// 根据需要设置查询参数}// 调用SDK方法查询EIP详情response, err := client.ListPublicips(request)if err != nil {return "", err}// 遍历响应中的公共IP地址for _, publicip := range *response.Publicips { // 假设返回的是指针指向的切片// 检查 PublicIpAddress 是否为nil,并解引用来比较值if publicip.PublicIpAddress != nil && *publicip.PublicIpAddress == publicIP {// 检查 BandwidthId 是否为nil,并解引用来返回值if publicip.BandwidthId != nil {return *publicip.BandwidthId, nil}break // 如果 BandwidthId 为nil,则结束循环}}// 如果没有找到匹配的公共IP地址或带宽ID是nil,则返回错误return "", errors.New("public IP not found or bandwidth ID is nil")
}
func getBandwidthNameByPublicIP(client *eip.EipClient, publicIP string) (string, error) {// 首先构造查询请求request := &model.ListPublicipsRequest{// 根据需要设置查询参数}// 调用SDK方法查询EIP详情response, err := client.ListPublicips(request)if err != nil {return "", err}// 遍历响应中的公共IP地址for _, publicip := range *response.Publicips { // 假设返回的是指针指向的切片// 检查 PublicIpAddress 是否为nil,并解引用来比较值if publicip.PublicIpAddress != nil && *publicip.PublicIpAddress == publicIP {// 检查 BandwidthId 是否为nil,并解引用来返回值if publicip.BandwidthName != nil {return *publicip.BandwidthName, nil}break // 如果 BandwidthId 为nil,则结束循环}}// 如果没有找到匹配的公共IP地址或带宽ID是nil,则返回错误return "", errors.New("public IP not found or bandwidth ID is nil")
}// Function to update the bandwidth of an EIP.
func updateBandwidth(client *eip.EipClient, bandwidthId, name string, size int32, chargeMode model.UpdateBandwidthOptionChargeMode) error {request := &model.UpdateBandwidthRequest{BandwidthId: bandwidthId,Body: &model.UpdateBandwidthRequestBody{Bandwidth: &model.UpdateBandwidthOption{Name:       &name,Size:       &size,ChargeMode: &chargeMode,},},}response, err := client.UpdateBandwidth(request)if err != nil {return err}fmt.Printf("Update response: %+v\n", response)return nil
}

image.png
ok这样就简单实现了!
注:以上代码chatgpt生成,个人进行了更改整理.

其他想到的

  1. 修改一下程序,检测流量计费,当带宽到xxx的时候自动切换带宽?
  2. 支持一下更多类型的切换方式?比如固定带宽的直接10变更 5 20,不恢复流量计费?

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

批量归一化

目录 一、BN层介绍 1、深层神经网络存在的问题 2、批量归一化的解决方案 3、BN层作用位置 4、BN层在做什么 5、总结 二、批量归一化从零实现 1、实现批量归一化操作 2、创建BN层 3、对LeNet加入批量归一化 4、开始训练 三、简明实现 1、对LeNet加入批量归一化 2…

Latex如何转成Word

将 LaTeX 文档转换成 Word 文档有几种方法&#xff0c;每种方法都有其优缺点。下面是一些常用的方法&#xff1a; 1. Pandoc Pandoc 是一个文档转换工具&#xff0c;可以将 LaTeX 转换成多种格式&#xff0c;包括 Word。 安装 Pandoc。使用以下命令转换 LaTeX 文件到 Word&a…

【性能优化】EFCore性能优化(一)-IEnumerable和IQueryable

阅读本文你的收获 了解EF Core在使用上应该要注意的地方学习EF Core的优化技术&#xff0c;如禁用跟踪、IQueryable接口等 一、问题描述 Entity Framework Core&#xff08;以下简称EF&#xff09;是微软自家出品的大型O/RM框架&#xff0c;使用EF Core&#xff0c;我们可以在…

【SD】IP-Adapter 进阶 - 垫图 【画风重绘-必看】

目录 关于SD1.5的画风迁移 修改动作-方法一&#xff1a;提示词 修改动作-方法二&#xff1a;openpose 关于SD1.5的画风迁移 1.5测试模型&#xff1a;flat2DAnimerge_v30_2.safetensors [b2c93e7a89] 测试图&#xff1a; 文生图&#xff1a;best quality,masterpiece, co…

20231225在WIN10下使用SSH连接Ubuntu20.04.6

20231225在WIN10下使用SSH连接Ubuntu20.04.6 2023/12/25 23:03 https://jingyan.baidu.com/article/5552ef479e1856108ffbc9e3.html Win10怎么开启SSH功能 Win10怎么开启SSH功能,下面就一起来看看吧! 工具/原料 华硕天选4 Windows10 方法/步骤 点击左下角的开始菜单,打开Wind…

Redis过期删除策略和内存淘汰策略

1、设置Redis键过期时间 Redis提供了四个命令来设置过期时间&#xff08;生存时间&#xff09;。 EXPIRE <key> <ttl> &#xff1a;表示将键 key 的生存时间设置为 ttl 秒。 PEXPIRE <key> <ttl> &#xff1a;表示将键 key 的生存时间设置为 ttl 毫秒。…

flutter怎么对ReorderableListView中的用于排序的控制手柄进行显示或隐藏

我在使用ReorderableListView创建可排序列表的时候&#xff0c;需要在编辑的时候才显示右侧的控制排序的手柄。研究了半天&#xff0c;配合搜索引擎&#xff0c;才找到正确的方案。 答案很简单&#xff0c;就是在它的属性当中有一个叫做&#xff1a;buildDefaultDragHandles的…

SICP : The Elements of Programming

好的计算机编程语言应具备的三个特性 基础单元表达式&#xff0c;计算机编程语言最最最基础单元&#xff0c;理应具备的表达式组合的能力&#xff0c;能够通过基础单元表达式组合成更复杂的元素抽象的能力&#xff0c;能通过复杂的元素抽象成更高层的单元 基础单元表达式 加 …

计算机硬件 4.2显卡

第二节 显卡 一、基本概念 1.定义&#xff1a;是主机与显示器之间的接口电路&#xff0c;也成为显示适配器&#xff0c;决定显示系统的优劣。 2.作用&#xff1a;处理和存储图形数据&#xff0c;向显示器提供信号、控制显示器显示的重要设备。 3.分类&#xff1a;核芯显卡、…

lvgl 双物理显示器的驱动实现

目录 一、背景 1. 要实现的功能2. lvgl 版本 二、简单粗暴的方式 理论上可以这样实现缺陷&#xff1a; 三、lvgl 自身机制支持 3.1 实现思路3.2 初始化缓冲区和注册显示驱动 3.2.1 复制lv_port_disp → lv_port_disp_23.2.2 修改 lv_port_disp_2 文件3.2.3 在应用层调用显示器…

什么是SLAM中的回环检测,如果没有回环检测会怎样

目录 什么是回环检测 如果没有回环检测 SLAM&#xff08;Simultaneous Localization and Mapping&#xff0c;即同时定位与地图构建&#xff09;是一种使机器人或自动驾驶汽车能够在未知环境中建立地图的同时定位自身位置的技术。回环检测&#xff08;Loop Closure Detectio…

快速入门学习定时任务框架-xxljob

定时任务框架-xxljob 简介 主要用于分布式任务调度&#xff0c;可以将任务调度和执行分布在多个节点上。它提供了一个集中式的管理平台&#xff0c;支持动态添加、修改、删除任务&#xff0c;以及任务的分片执行&#xff0c;确保任务在分布式环境中的高可用性的一个框架 spr…

C语言中函数调用和嵌套

函数是C语言的基本组成元素 函数调用 根据函数在程序中出现的位置有下列三种函数调用方式&#xff1a; 将函数作为表达式调用 将函数作为表达式调用时&#xff0c;函数的返回值参与表达式的运算&#xff0c;此时要求函数必须有返回值 int retmax(100,150); 将函数作为语句…

k8s学习 — (DevOps实践)第十四章 微服务 DevOps 实战 【Kubesphere DevOps】

k8s学习 — &#xff08;DevOps实践&#xff09;第十四章 微服务 DevOps 实战 【Kubesphere DevOps】 1 开启 DevOps2 集成 SonarQube3 更新 settings.xml4 部署项目4.1 Spring Boot 项目4.1.1 项目4.1.2 配置文件 4.2 微服务项目4.2.1 项目4.2.2 配置文件 5 DevOps 项目5.1 Sp…

大数据Doris(四十一):物化视图简单介绍

文章目录 物化视图简单介绍 一、适用场景

Windows系统配置pytorch环境,Jupyter notebook编辑器安装使用(深度学习本地篇)

如今现在好一点的笔记本都自带英伟达独立显卡&#xff0c;对于一些简单的深度学习项目&#xff0c;是不需要连接服务器的&#xff0c;甚至数据量不大的话&#xff0c;cpu也足够进行训练学习。我把电脑上一些以前的笔记整理一下&#xff0c;记录起来&#xff0c;方便自己35岁事业…

在Android中使用Flow获取网络连接信息

在Android中使用Flow获取网络连接信息 如果你是一名Android开发者&#xff0c;你可能会对这个主题感到有趣。考虑到几乎每个应用程序都需要数据交换&#xff0c;例如刷新动态或上传/下载内容。而互联网连接对此至关重要。但是&#xff0c;当用户的设备离线时&#xff0c;数据如…

Python之__enter__和__exit__

1. 概述 这两个函数与with as语句语句紧密相连&#xff0c;即 class Test():def __enter__(self):print("Enter!")passdef __exit__(self, type, value, trace):print("Exit!")passwith Test() as f: # 执行with as语句时&#xff0c;Test类中的_…

git中的smart checkout和force checkout

切换分支时出现了这个问题&#xff1a; 这是因为shiyan01分支修改了代码,但是没有commit, 所以在切换到test分支的时候弹出这个窗口 一、smart checkout(智能签出) 会把shiyan01分支的改动内容带到test分支。合并处理后的内容就变成了test分支的内容,而shiyan01分支的改动会被…

【Qt-编码】

Qt编程指南 ■ 编码■ ASCII■ ANSI■ GB2312■ GBK■ GB18030 编码■ Unicode■ UTF-8&#xff1a; ■ Qt接收注射泵GBK编码后显示乱码■■ ■ 编码 ■ ASCII &#xff08;American Standard Code for Information Interchange&#xff0c;美国信息交换标准代码&#xff09;…