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.rhkb.cn/news/224603.html

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

相关文章

STM32实现流水灯

led.c #include"led.h"void Led_Init(void) {GPIO_InitTypeDef GPIO_VALUE; //???RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//???GPIO_VALUE.GPIO_ModeGPIO_Mode_Out_PP;//???? ????GPIO_VALUE.GPIO_PinGPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_…

Android---Kotlin 学习009

继承 在 java 里如果一个类没有被 final 关键字修饰&#xff0c;那么它都是可以被继承的。而在 kotlin 中&#xff0c;类默认都是封闭的&#xff0c;要让某个类开放继承&#xff0c;必须使用 open 关键字修饰它&#xff0c;否则会编译报错。此外在子类中&#xff0c;如果要复写…

基于电商场景的高并发RocketMQ实战-Commitlog基于内存的高并发写入优化、基于JVM offheap的内存读写分离机制

&#x1f308;&#x1f308;&#x1f308;&#x1f308;&#x1f308;&#x1f308;&#x1f308;&#x1f308; 【11来了】文章导读地址&#xff1a;点击查看文章导读&#xff01; &#x1f341;&#x1f341;&#x1f341;&#x1f341;&#x1f341;&#x1f341;&#x1f3…

HBase基础知识(五):HBase 对接 Hadoop 的 MapReduce

通过 HBase 的相关 JavaAPI&#xff0c;我们可以实现伴随 HBase 操作的 MapReduce 过程&#xff0c;比如使用 MapReduce 将数据从本地文件系统导入到 HBase 的表中&#xff0c;比如我们从 HBase 中读取一些原 始数据后使用 MapReduce 做数据分析。 1 官方 HBase-MapReduce 1&am…

AI数字人可以用在哪些行业,对这些行业有什么好处

引言&#xff1a; 在科技日新月异的今天&#xff0c;人工智能&#xff08;AI&#xff09;的发展已经深入到各个领域&#xff0c;尤其在旅游业、政务党建、城市园区、品牌宣传和乡村振兴等领域&#xff0c;AI数字人的应用正逐步改变我们的生活方式。 一.AI数字人在旅游业中的应…

Android 11.0 系统默认打开OEM解锁开关功能实现

1.前言 在11.0的系统rom定制化开发中,在9.0系统以后为了设备的安装,系统开始启用oem机制,所以在adb push文件就需要先oem解锁,然后才可以 进行相关操作,所以就需要默认打开oem解锁的开关,来方便oem解锁功能的实现 如图: 2.系统默认打开OEM解锁开关功能实现的核心类 pac…

微短剧,会成为长视频的“救命稻草”吗?

职场社畜秒变霸道总裁&#xff0c;普通女孩穿越成为艳丽皇妃.......这样“狗血”的微短剧&#xff0c;最近不仅在国内各大视频平台上异常火爆&#xff0c;而且还直接火出了国外。 所谓微短剧&#xff0c;就是单集时长从几十秒到十几分钟的剧集&#xff0c;有着相对明确的主题和…

redis—String字符串

目录 前言 1.字符串数据类型 2.常见命令 3.典型应用场景 前言 字符串类型是Redis最基础的数据类型&#xff0c;关于字符串需要特别注意: 1)首先Redis中所有的键的类型都是字符串类型&#xff0c;而且其他几种数据结构也都是在字符串类似基础.上构建的&#xff0c;例如列表…

JavaEE:CAS详解

一.什么是CAS CAS: 全称 Compare and swap &#xff0c;字面意思 :” 比较并交换 “ &#xff0c;一个 CAS 涉及到以下操作&#xff1a; 我们假设内存中的原数据V&#xff0c;旧的预期值A&#xff0c;需要修改的新值B。 我们来进行操作&#xff1a; 1. 比较 V 和 A 是否相等。…

vue3 全局配置Axios实例

目录 前言 配置Axios实例 页面使用 总结 前言 Axios 是一个基于 Promise 的 HTTP 客户端&#xff0c;用于浏览器和 Node.js 环境。它提供了一种简单、一致的 API 来处理HTTP请求&#xff0c;支持请求和响应的拦截、转换、取消请求等功能。关于它的作用&#xff1a; 发起 HTTP …

VMware虚拟机安装Ubuntu系统教程

所使用的文件如下&#xff1a; VMware Workstation 17 Pro ubuntu-22.04.3-desktop-amd64.iso 一、ubuntu 命名规则及各版本一览表 1.ubuntu 命名规则&#xff1a; 例如&#xff1a;ubuntu 16.04 LTS 是长期维护版本&#xff1b;ubuntu 17.04 是新特性版本 前两位数字为发…

使用pytorch神经网络拟合计算模型

一. 内容简介 python调用百度翻译api&#xff0c;将中文论文翻译英文&#xff0c;并保留部分格式 二. 软件环境 2.1vsCode 2.2Anaconda version: conda 22.9.0 2.3数据文件 链接&#xff1a;https://pan.baidu.com/s/1csJOoErGyx77MW_FImVKjg?pwd1234 三.主要流程 3.…

【计数DP】牛客小白月赛19

登录—专业IT笔试面试备考平台_牛客网 题意 思路 首先做法一定是计数 dp 然后状态设计&#xff0c;先设 dp[i] 然后看影响决策的因素&#xff1a;两边的火焰情况&#xff0c;那就 dp[i][0/1][0/1]表示 前 i 个&#xff0c;该位有无火焰&#xff0c;该位右边有无火焰的方案数…

mysql原理--连接查询的成本

1.准备工作 连接查询至少是要有两个表的&#xff0c;只有一个 single_table 表是不够的&#xff0c;所以为了故事的顺利发展&#xff0c;我们直接构造一个和 single_table 表一模一样的 single_table2 表。为了简便起见&#xff0c;我们把 single_table 表称为 s1 表&#xff0…

ES8生产实践——Kibana对接Azure AD实现单点登录

基本概念介绍 什么是单点登录 单点登录&#xff08;Single Sign-On&#xff0c;SSO&#xff09;是一种身份验证和访问控制机制&#xff0c;允许用户使用一组凭据&#xff08;通常是用户名和密码&#xff09;仅需登录一次&#xff0c;即可访问多个应用程序或系统&#xff0c;而…

结构体的对齐规则

1.引入 我们在掌握了结构体的基本使⽤后。 现在我们深⼊讨论⼀个问题&#xff1a;计算结构体的大小。 这也是⼀个特别热门的考点&#xff1a; 结构体内存对齐。 2.具体分析 ⾸先我们得掌握结构体的对⻬规则&#xff1a; 1. 结构体的第⼀个成员对⻬到和结构体变量起始位置偏移量…

一站式指南:第 377 场力扣周赛的终极题解

比赛详情 比赛地址 题目一很简单题目二主要是题目长了点&#xff0c;其实解法很常规(比赛后才意识到)题目三套用Dijkstra算法题目四没时间解答水平还有待提升(其实就是需要灵活组合运用已知的算法&#xff0c;有点类似大模型的Agent) 题解和思路 第一题&#xff1a;最小数字…

CentOS进入单用户模式

一、重启 二、出现内核选项 按“e” 三、编辑这一行 输入 rw init/sysroot/bin/sh 四、进入单用户模式 ctrlx 进入 五、切换目录 chroot /sysroot 六、然后你就操作你的系统了。 修改密码等等

【知识点随笔分享 | 第九篇】常见的限流算法

目录 前言&#xff1a; 1.固定窗口限流&#xff1a; 缺点&#xff1a; 2.滑动窗口限流&#xff1a; 优点&#xff1a; 滴桶限流&#xff1a; 缺点&#xff1a; 令牌桶限流&#xff1a; 优点&#xff1a; 总结: 前言&#xff1a; 当今互联网时代&#xff0c;随着网络…

IP编址,IP地址介绍与子网划分方法

网络层位于数据链路层与传输层之间。网络层中包含了许多协议&#xff0c;其中最为重要的协议就是IP协议。网络层提供了IP路由功能。理解IP路由除了要熟悉IP协议的工作机制之外&#xff0c;还必须理解IP编址以及如何合理地使用IP地址来设计网络。 上层协议类型 以太网帧中的Typ…