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

     1  package events
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"io"
     7  	"io/ioutil"
     8  	"net/http"
     9  	"strings"
    10  	"time"
    11  )
    12  
    13  type EventLevel string
    14  
    15  const (
    16  	InfoEventLevel  EventLevel = "info"
    17  	ErrorEventLevel EventLevel = "error"
    18  )
    19  
    20  type EventDTO struct {
    21  	ID          string
    22  	Level       EventLevel
    23  	InstanceID  *string
    24  	OperationID *string
    25  	Message     string
    26  	CreatedAt   time.Time
    27  }
    28  
    29  type EventFilter struct {
    30  	InstanceIDs  []string
    31  	OperationIDs []string
    32  }
    33  
    34  // Client is the interface to interact with the KEB /events API as an HTTP client using OIDC ID token in JWT format.
    35  type Client interface {
    36  	ListEvents(instanceIDs []string) ([]EventDTO, error)
    37  }
    38  
    39  type client struct {
    40  	url        string
    41  	httpClient *http.Client
    42  }
    43  
    44  // NewClient constructs and returns new Client for KEB /events API
    45  // It takes the following arguments:
    46  //   - url        : base url of all KEB APIs, e.g. https://kyma-env-broker.kyma.local
    47  //   - httpClient : underlying HTTP client used for API call to KEB
    48  func NewClient(url string, httpClient *http.Client) Client {
    49  	return &client{
    50  		url:        url,
    51  		httpClient: httpClient,
    52  	}
    53  }
    54  
    55  // ListEvents
    56  func (c *client) ListEvents(instanceIDs []string) ([]EventDTO, error) {
    57  	var events []EventDTO
    58  	req, err := http.NewRequest("GET", fmt.Sprintf("%s/events", c.url), nil)
    59  	if err != nil {
    60  		return events, fmt.Errorf("while creating request: %v", err)
    61  	}
    62  	q := req.URL.Query()
    63  	q.Add("instance_ids", strings.Join(instanceIDs, ","))
    64  	req.URL.RawQuery = q.Encode()
    65  	resp, err := c.httpClient.Do(req)
    66  	if err != nil {
    67  		return events, fmt.Errorf("while calling %s: %v", req.URL.String(), err)
    68  	}
    69  
    70  	// Drain response body and close, return error to context if there isn't any.
    71  	defer func() {
    72  		derr := drainResponseBody(resp.Body)
    73  		if err == nil {
    74  			err = derr
    75  		}
    76  		cerr := resp.Body.Close()
    77  		if err == nil {
    78  			err = cerr
    79  		}
    80  	}()
    81  
    82  	if resp.StatusCode != http.StatusOK {
    83  		return events, fmt.Errorf("calling %s returned %d (%s) status", req.URL.String(), resp.StatusCode, resp.Status)
    84  	}
    85  
    86  	decoder := json.NewDecoder(resp.Body)
    87  	err = decoder.Decode(&events)
    88  	if err != nil {
    89  		return events, fmt.Errorf("while decoding response body: %v", err)
    90  	}
    91  	return events, nil
    92  }
    93  
    94  func drainResponseBody(body io.Reader) error {
    95  	if body == nil {
    96  		return nil
    97  	}
    98  	_, err := io.Copy(ioutil.Discard, io.LimitReader(body, 4096))
    99  	return err
   100  }