yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/apsara/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 apsara
    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  }