yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/aliyun/utils.go (about) 1 // Copyright 2019 Yunion 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package aliyun 16 17 import ( 18 "fmt" 19 "reflect" 20 21 "yunion.io/x/jsonutils" 22 "yunion.io/x/log" 23 ) 24 25 type jsonRequestFunc func(action string, params map[string]string) (jsonutils.JSONObject, error) 26 27 func unmarshalResult(resp jsonutils.JSONObject, respErr error, resultKey []string, result interface{}) error { 28 if respErr != nil { 29 return respErr 30 } 31 32 if result == nil { 33 return nil 34 } 35 36 if resultKey != nil && len(resultKey) > 0 { 37 respErr = resp.Unmarshal(result, resultKey...) 38 } else { 39 respErr = resp.Unmarshal(result) 40 } 41 42 if respErr != nil { 43 log.Errorf("unmarshal json error %s", respErr) 44 } 45 46 return nil 47 } 48 49 func doListPart(client jsonRequestFunc, action string, limit int, offset int, params map[string]string, resultKey []string, result interface{}) (int, int, error) { 50 params["PageSize"] = fmt.Sprintf("%d", limit) 51 params["PageNumber"] = fmt.Sprintf("%d", (offset/limit)+1) 52 53 ret, err := client(action, params) 54 if err != nil { 55 return 0, 0, err 56 } 57 58 total, _ := ret.Int("TotalCount") 59 60 var lst []jsonutils.JSONObject 61 lst, err = ret.GetArray(resultKey...) 62 if err != nil { 63 return 0, 0, nil 64 } 65 66 resultValue := reflect.Indirect(reflect.ValueOf(result)) 67 elemType := resultValue.Type().Elem() 68 for i := range lst { 69 elemPtr := reflect.New(elemType) 70 err = lst[i].Unmarshal(elemPtr.Interface()) 71 if err != nil { 72 return 0, 0, err 73 } 74 resultValue.Set(reflect.Append(resultValue, elemPtr.Elem())) 75 } 76 return int(total), len(lst), nil 77 } 78 79 // 执行操作 80 func DoAction(client jsonRequestFunc, action string, params map[string]string, resultKey []string, result interface{}) error { 81 resp, err := client(action, params) 82 return unmarshalResult(resp, err, resultKey, result) 83 } 84 85 // 遍历所有结果 86 func DoListAll(client jsonRequestFunc, action string, params map[string]string, resultKey []string, result interface{}) error { 87 pageLimit := 50 88 offset := 0 89 90 resultValue := reflect.Indirect(reflect.ValueOf(result)) 91 for { 92 total, part, err := doListPart(client, action, pageLimit, offset, params, resultKey, result) 93 if err != nil { 94 return err 95 } 96 97 // total 大于零的情况下通过total字段判断列表是否遍历完成。total不存在或者为0的情况下,通过返回列表的长度判断是否遍历完成 98 if (total > 0 && resultValue.Len() >= total) || (total == 0 && pageLimit > part) { 99 break 100 } 101 102 offset = resultValue.Len() 103 } 104 105 return nil 106 }