github.com/kyma-project/kyma-environment-broker@v0.0.1/common/runtime/client.go (about)

     1  package runtime
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"io"
     7  	"io/ioutil"
     8  	"net/http"
     9  	"net/url"
    10  	"strconv"
    11  
    12  	"github.com/kyma-project/kyma-environment-broker/common/pagination"
    13  )
    14  
    15  const defaultPageSize = 100
    16  
    17  // Client is the interface to interact with the KEB /runtimes API as an HTTP client using OIDC ID token in JWT format.
    18  type Client interface {
    19  	ListRuntimes(params ListParameters) (RuntimesPage, error)
    20  }
    21  
    22  type client struct {
    23  	url        string
    24  	httpClient *http.Client
    25  }
    26  
    27  // NewClient constructs and returns new Client for KEB /runtimes API
    28  // It takes the following arguments:
    29  //   - url        : base url of all KEB APIs, e.g. https://kyma-env-broker.kyma.local
    30  //   - httpClient : underlying HTTP client used for API call to KEB
    31  func NewClient(url string, httpClient *http.Client) Client {
    32  	return &client{
    33  		url:        url,
    34  		httpClient: httpClient,
    35  	}
    36  }
    37  
    38  // ListRuntimes fetches the runtimes from KEB according to the given parameters.
    39  // If params.Page or params.PageSize is not set (zero), the client will fetch and return all runtimes.
    40  func (c *client) ListRuntimes(params ListParameters) (RuntimesPage, error) {
    41  	runtimes := RuntimesPage{}
    42  	getAll := false
    43  	fetchedAll := false
    44  	if params.Page == 0 || params.PageSize == 0 {
    45  		getAll = true
    46  		params.Page = 1
    47  		params.PageSize = defaultPageSize
    48  	}
    49  
    50  	for !fetchedAll {
    51  		req, err := http.NewRequest("GET", fmt.Sprintf("%s/runtimes", c.url), nil)
    52  		if err != nil {
    53  			return runtimes, fmt.Errorf("while creating request: %w", err)
    54  		}
    55  		setQuery(req.URL, params)
    56  
    57  		resp, err := c.httpClient.Do(req)
    58  		if err != nil {
    59  			return runtimes, fmt.Errorf("while calling %s: %w", req.URL.String(), err)
    60  		}
    61  
    62  		// Drain response body and close, return error to context if there isn't any.
    63  		defer func() {
    64  			derr := drainResponseBody(resp.Body)
    65  			if err == nil {
    66  				err = derr
    67  			}
    68  			cerr := resp.Body.Close()
    69  			if err == nil {
    70  				err = cerr
    71  			}
    72  		}()
    73  
    74  		if resp.StatusCode != http.StatusOK {
    75  			return runtimes, fmt.Errorf("calling %s returned %d (%s) status", req.URL.String(), resp.StatusCode, resp.Status)
    76  		}
    77  
    78  		var rp RuntimesPage
    79  		decoder := json.NewDecoder(resp.Body)
    80  		err = decoder.Decode(&rp)
    81  		if err != nil {
    82  			return runtimes, fmt.Errorf("while decoding response body: %w", err)
    83  		}
    84  
    85  		runtimes.TotalCount = rp.TotalCount
    86  		runtimes.Count += rp.Count
    87  		runtimes.Data = append(runtimes.Data, rp.Data...)
    88  		if getAll {
    89  			params.Page++
    90  			fetchedAll = runtimes.Count >= runtimes.TotalCount
    91  		} else {
    92  			fetchedAll = true
    93  		}
    94  	}
    95  
    96  	return runtimes, nil
    97  }
    98  
    99  func setQuery(url *url.URL, params ListParameters) {
   100  	query := url.Query()
   101  	query.Add(pagination.PageParam, strconv.Itoa(params.Page))
   102  	query.Add(pagination.PageSizeParam, strconv.Itoa(params.PageSize))
   103  	if params.OperationDetail != "" {
   104  		query.Add(OperationDetailParam, string(params.OperationDetail))
   105  	}
   106  	if params.KymaConfig {
   107  		query.Add(KymaConfigParam, "true")
   108  	}
   109  	if params.ClusterConfig {
   110  		query.Add(ClusterConfigParam, "true")
   111  	}
   112  	if params.Expired {
   113  		query.Add(ExpiredParam, "true")
   114  	}
   115  	setParamList(query, GlobalAccountIDParam, params.GlobalAccountIDs)
   116  	setParamList(query, SubAccountIDParam, params.SubAccountIDs)
   117  	setParamList(query, InstanceIDParam, params.InstanceIDs)
   118  	setParamList(query, RuntimeIDParam, params.RuntimeIDs)
   119  	setParamList(query, RegionParam, params.Regions)
   120  	setParamList(query, ShootParam, params.Shoots)
   121  	setParamList(query, PlanParam, params.Plans)
   122  	for _, s := range params.States {
   123  		query.Add(StateParam, string(s))
   124  	}
   125  	url.RawQuery = query.Encode()
   126  }
   127  
   128  func setParamList(query url.Values, key string, values []string) {
   129  	for _, value := range values {
   130  		query.Add(key, value)
   131  	}
   132  }
   133  
   134  func drainResponseBody(body io.Reader) error {
   135  	if body == nil {
   136  		return nil
   137  	}
   138  	_, err := io.Copy(ioutil.Discard, io.LimitReader(body, 4096))
   139  	return err
   140  }