Skip to content

Commit

Permalink
testcase: Improves the init test client and using dingTalk to cleanup…
Browse files Browse the repository at this point in the history
… some instances before some specific testcases
  • Loading branch information
xiaozhu36 committed Dec 9, 2024
1 parent 95700f8 commit aea6aec
Show file tree
Hide file tree
Showing 3 changed files with 173 additions and 3 deletions.
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
}

0 comments on commit aea6aec

Please sign in to comment.