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 }