Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

testcase: Improves the init test client and using dingTalk to cleanup some instances before some specific testcases #7957

Merged
merged 1 commit into from
Dec 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion alicloud/alicloud_sweeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ package alicloud

import (
"fmt"
"github.com/aliyun/credentials-go/credentials"
"log"
"os"
"strings"
"sync"
"testing"

Expand Down Expand Up @@ -52,7 +54,7 @@ var endpoints sync.Map
// sharedClientForRegion returns a common AlicloudClient setup needed for the sweeper
// functions for a give n region
func sharedClientForRegion(region string) (interface{}, error) {
var accessKey, secretKey string
var accessKey, secretKey, securityToken string
if accessKey = os.Getenv("ALICLOUD_ACCESS_KEY"); accessKey == "" {
return nil, fmt.Errorf("empty ALICLOUD_ACCESS_KEY")
}
Expand All @@ -61,6 +63,8 @@ func sharedClientForRegion(region string) (interface{}, error) {
return nil, fmt.Errorf("empty ALICLOUD_SECRET_KEY")
}

securityToken = os.Getenv("ALICLOUD_SECURITY_TOKEN")

conf := connectivity.Config{
Region: connectivity.Region(region),
RegionId: region,
Expand All @@ -69,9 +73,21 @@ func sharedClientForRegion(region string) (interface{}, error) {
Protocol: "HTTPS",
Endpoints: &endpoints,
}
if securityToken != "" {
conf.SecurityToken = securityToken
}
if accountId := os.Getenv("ALICLOUD_ACCOUNT_ID"); accountId != "" {
conf.AccountId = accountId
}
credentialConfig := new(credentials.Config).SetType("access_key").SetAccessKeyId(accessKey).SetAccessKeySecret(secretKey)
if v := strings.TrimSpace(securityToken); v != "" {
credentialConfig.SetType("sts").SetSecurityToken(v)
}
credential, err := credentials.NewCredential(credentialConfig)
if err != nil {
return nil, err
}
conf.Credential = credential

// configures a default client for the region, using the above env vars
client, err := conf.Client()
Expand Down
88 changes: 88 additions & 0 deletions alicloud/provider_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package alicloud

import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"testing"
"time"
Expand Down Expand Up @@ -65,6 +67,55 @@ func testAccPreCheck(t *testing.T) {
}
}

func testAccPreCheckForCleanUpInstances(t *testing.T, instanceRegion, productCode, productType, productCodeIntl, productTypeIntl string) {
rawClient, err := sharedClientForRegion(defaultRegionToTest)
if err != nil {
t.Errorf("error getting AliCloud client: %s", err)
}
client := rawClient.(*connectivity.AliyunClient)
bssOpenApiService := BssOpenApiService{client}
accountId, err := client.AccountId()
if err != nil {
t.Errorf("error getting AliCloud client: %s", err)
}
deadline := time.Now().Add(30 * time.Minute)
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()
for {
select {
case <-ticker.C:
if time.Now().After(deadline) {
fmt.Println("Deadline reached, stopping waiting.")
return
}
instances, err := bssOpenApiService.QueryAvailableInstanceList(instanceRegion, productCode, productType, productCodeIntl, productTypeIntl)
if err != nil {
t.Errorf("error querying available instances: %s", err)
return
}
instanceId := ""
for _, instance := range instances {
v := instance.(map[string]interface{})
if v["Status"].(string) != "Normal" {
continue
}
instanceId = v["InstanceID"].(string)
}
if instanceId == "" {
return
}
sendMessage(fmt.Sprintf(`
[Critical] Please cleaning up instance before running integration test.

AccountId: %s
ProductCode: %s
InstanceId: %s
`, accountId, productCode, instanceId))
time.Sleep(3 * time.Minute)
}
}
}

// currently not all account site type support create PostPaid resources, PayByBandwidth and other limits.
// The setting of account site type can skip some unsupported cases automatically.

Expand Down Expand Up @@ -416,6 +467,43 @@ func testAccPreCheckWithResourceManagerHandshakesSetting(t *testing.T) {
}
}

type DingTalkMessage struct {
MsgType string `json:"msgtype"`
Text struct {
Content string `json:"content"`
} `json:"text"`
}

func sendMessage(msg string) {
// 钉钉机器人的 Webhook 地址
webhookURL := "https://oapi.dingtalk.com/robot/send?access_token=" + os.Getenv("DINGTALK_WEBHOOK_ACCESS_TOKEN")

// 构建消息内容
message := DingTalkMessage{
MsgType: "text",
Text: struct {
Content string `json:"content"`
}{
Content: msg,
},
}

// 将消息内容转换为 JSON 格式
jsonData, err := json.Marshal(message)
if err != nil {
fmt.Println("[ERROR] send dingTalk message failed. Error:", err)
return
}

// 发送 POST 请求
resp, err := http.Post(webhookURL, "application/json", bytes.NewBuffer(jsonData))
if err != nil {
fmt.Println("[ERROR] send dingTalk message failed. Error:", err)
return
}
defer resp.Body.Close()
}

func setStsCredential() {
// 创建OSSClient实例。
client, err := oss.New("https://oss-cn-zhangjiakou.aliyuncs.com", os.Getenv("ALICLOUD_ACCESS_KEY"), os.Getenv("ALICLOUD_SECRET_KEY"))
Expand Down
70 changes: 68 additions & 2 deletions alicloud/service_alicloud_bss_open_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@ func (s *BssOpenApiService) QueryAvailableInstances(id, instanceRegion, productC
}
action := "QueryAvailableInstances"
request := map[string]interface{}{
"InstanceIDs": id,
"ProductCode": productCode,
"ProductType": productType,
}
if id != "" {
request["InstanceIDs"] = id
}
if instanceRegion != "" {
request["Region"] = instanceRegion
}
Expand Down Expand Up @@ -78,7 +80,7 @@ func (s *BssOpenApiService) QueryAvailableInstances(id, instanceRegion, productC
}
if len(v.([]interface{})) < 1 {
return object, WrapErrorf(Error(GetNotFoundMessage(productCode+"Instance", id)), NotFoundWithResponse, response)
} else {
} else if id != "" {
if fmt.Sprint(v.([]interface{})[0].(map[string]interface{})["InstanceID"]) != id {
return object, WrapErrorf(Error(GetNotFoundMessage(productCode+"Instance", id)), NotFoundWithResponse, response)
}
Expand Down Expand Up @@ -320,3 +322,67 @@ func (s *BssOpenApiService) CloudFirewallInstanceOrderDetailStateRefreshFunc(ord
return object, object["PaymentStatus"].(string), nil
}
}

func (s *BssOpenApiService) QueryAvailableInstanceList(instanceRegion, productCode, productType, productCodeIntl, productTypeIntl string) (object []interface{}, err error) {
var response map[string]interface{}
conn, err := s.client.NewBssopenapiClient()
if err != nil {
return nil, WrapError(err)
}
action := "QueryAvailableInstances"
request := map[string]interface{}{
"ProductCode": productCode,
"ProductType": productType,
}
if instanceRegion != "" {
request["Region"] = instanceRegion
}
runtime := util.RuntimeOptions{}
runtime.SetAutoretry(true)
wait := incrementalWait(3*time.Second, 3*time.Second)
err = resource.Retry(5*time.Minute, func() *resource.RetryError {
response, err = conn.DoRequest(StringPointer(action), nil, StringPointer("POST"), StringPointer("2017-12-14"), StringPointer("AK"), nil, request, &runtime)
if err != nil {
if NeedRetry(err) {
wait()
return resource.RetryableError(err)
}
if IsExpectedErrors(err, []string{"NotApplicable", "SignatureDoesNotMatch"}) {
conn.Endpoint = String(connectivity.BssOpenAPIEndpointInternational)
request["ProductCode"] = productCodeIntl
request["ProductType"] = productTypeIntl
return resource.RetryableError(err)
}
return resource.NonRetryableError(err)
}
resp, _ := jsonpath.Get("$.Data.InstanceList", response)
if len(resp.([]interface{})) < 1 {
request["ProductCode"] = productCodeIntl
if productTypeIntl != "" {
request["ProductType"] = productTypeIntl
}
conn.Endpoint = String(connectivity.BssOpenAPIEndpointInternational)
response, err = conn.DoRequest(StringPointer(action), nil, StringPointer("POST"), StringPointer("2017-12-14"), StringPointer("AK"), nil, request, &runtime)
if err != nil {
if NeedRetry(err) {
wait()
return resource.RetryableError(err)
}
return resource.NonRetryableError(err)
}
}
return nil
})
addDebug(action, response, request)
if err != nil {
return object, WrapError(err)
}
if fmt.Sprint(response["Code"]) != "Success" {
return object, WrapError(fmt.Errorf("%s failed, response: %v", action, response))
}
v, err := jsonpath.Get("$.Data.InstanceList", response)
if err != nil {
return object, WrapError(err)
}
return v.([]interface{}), nil
}
Loading