github.com/kyma-project/kyma-environment-broker@v0.0.1/internal/cis/client_ver_1.go (about)

     1  package cis
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"fmt"
     7  	"io/ioutil"
     8  	"net/http"
     9  	"strconv"
    10  
    11  	"github.com/sirupsen/logrus"
    12  	"golang.org/x/oauth2/clientcredentials"
    13  )
    14  
    15  const (
    16  	eventServicePathVer1 = "%s/public/rest/v2/events"
    17  	eventTypeVer1        = "MASTER_SUBACCOUNT_DELETION"
    18  	defaultPageSizeVer1  = "1000"
    19  )
    20  
    21  type ClientVer1 struct {
    22  	httpClient *http.Client
    23  	config     Config
    24  	log        logrus.FieldLogger
    25  }
    26  
    27  func NewClientVer1(ctx context.Context, config Config, log logrus.FieldLogger) *ClientVer1 {
    28  	cfg := clientcredentials.Config{
    29  		ClientID:     config.ClientID,
    30  		ClientSecret: config.ClientSecret,
    31  		TokenURL:     config.AuthURL,
    32  	}
    33  	httpClientOAuth := cfg.Client(ctx)
    34  
    35  	if config.PageSize == "" {
    36  		config.PageSize = defaultPageSizeVer1
    37  	}
    38  
    39  	return &ClientVer1{
    40  		httpClient: httpClientOAuth,
    41  		config:     config,
    42  		log:        log.WithField("client", "CIS-1.0"),
    43  	}
    44  }
    45  
    46  // SetHttpClient auxiliary method of testing to get rid of oAuth client wrapper
    47  func (c *ClientVer1) SetHttpClient(httpClient *http.Client) {
    48  	c.httpClient = httpClient
    49  }
    50  
    51  type subaccountsVer1 struct {
    52  	total int
    53  	ids   []string
    54  }
    55  
    56  func (c *ClientVer1) FetchSubaccountsToDelete() ([]string, error) {
    57  	subaccounts := subaccountsVer1{}
    58  
    59  	err := c.fetchSubaccountsFromDeleteEvents(&subaccounts, 1)
    60  	if err != nil {
    61  		return []string{}, fmt.Errorf("while fetching subaccounts from delete events: %w", err)
    62  	}
    63  
    64  	c.log.Infof("CIS returned total amount of delete events: %d, client fetched %d subaccounts to delete.",
    65  		subaccounts.total,
    66  		len(subaccounts.ids))
    67  
    68  	return subaccounts.ids, nil
    69  }
    70  
    71  func (c *ClientVer1) fetchSubaccountsFromDeleteEvents(collection *subaccountsVer1, page int) error {
    72  	request, err := c.buildRequest(page)
    73  	if err != nil {
    74  		return fmt.Errorf("while building request for event service: %w", err)
    75  	}
    76  
    77  	response, err := c.httpClient.Do(request)
    78  	if err != nil {
    79  		return fmt.Errorf("while executing request to event service: %w", err)
    80  	}
    81  
    82  	if response.StatusCode != http.StatusOK {
    83  		return fmt.Errorf("while processing response: %s", c.handleWrongStatusCode(response))
    84  	}
    85  
    86  	var cisResponse CisResponseVer1
    87  	err = json.NewDecoder(response.Body).Decode(&cisResponse)
    88  	if err != nil {
    89  		return fmt.Errorf("while decoding CIS response: %w", err)
    90  	}
    91  
    92  	collection.total = cisResponse.Total
    93  	for _, event := range cisResponse.Events {
    94  		if event.Type != eventTypeVer1 {
    95  			c.log.Warnf("event type %s is not equal to %s, skip event", event.Type, eventTypeVer1)
    96  			continue
    97  		}
    98  		collection.ids = append(collection.ids, event.Data.SubAccount)
    99  	}
   100  
   101  	page++
   102  	if page <= cisResponse.TotalPages {
   103  		return c.fetchSubaccountsFromDeleteEvents(collection, page)
   104  	}
   105  
   106  	return nil
   107  }
   108  
   109  func (c *ClientVer1) buildRequest(page int) (*http.Request, error) {
   110  	request, err := http.NewRequest(http.MethodGet, fmt.Sprintf(eventServicePathVer1, c.config.EventServiceURL), nil)
   111  	if err != nil {
   112  		return nil, fmt.Errorf("while creating request: %w", err)
   113  	}
   114  
   115  	q := request.URL.Query()
   116  	q.Add("ts", "1")
   117  	q.Add("type", eventTypeVer1)
   118  	q.Add("resultsPerPage", c.config.PageSize)
   119  	q.Add("page", strconv.Itoa(page))
   120  
   121  	request.URL.RawQuery = q.Encode()
   122  
   123  	return request, nil
   124  }
   125  
   126  func (c *ClientVer1) handleWrongStatusCode(response *http.Response) string {
   127  	body, err := ioutil.ReadAll(response.Body)
   128  	if err != nil {
   129  		return fmt.Sprintf("server returned %d status code, response body is unreadable", response.StatusCode)
   130  	}
   131  
   132  	return fmt.Sprintf("server returned %d status code, body: %q", response.StatusCode, string(body))
   133  }