From db26b9c0db72240072ef5f075a098c0c6153b6bc Mon Sep 17 00:00:00 2001 From: CloudQuery Bot <102256036+cq-bot@users.noreply.github.com> Date: Wed, 15 Nov 2023 17:20:02 +0200 Subject: [PATCH 1/3] fix: Generate CloudQuery Go API Client from `spec.json` (#73) This PR was created by a scheduled workflow to generate the CloudQuery Go API Client from `spec.json` --- client.gen.go | 185 ++++++++++++++++++++++++++++++++++++++++++++++++++ models.gen.go | 25 +++++++ spec.json | 90 ++++++++++++++++++++++++ 3 files changed, 300 insertions(+) diff --git a/client.gen.go b/client.gen.go index 8813281..1e63336 100644 --- a/client.gen.go +++ b/client.gen.go @@ -219,6 +219,9 @@ type ClientInterface interface { UpdateTeam(ctx context.Context, teamName TeamName, body UpdateTeamJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + // ListAddonOrdersByTeam request + ListAddonOrdersByTeam(ctx context.Context, teamName TeamName, params *ListAddonOrdersByTeamParams, reqEditors ...RequestEditorFn) (*http.Response, error) + // DeleteAddonsByTeam request DeleteAddonsByTeam(ctx context.Context, teamName TeamName, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -894,6 +897,18 @@ func (c *Client) UpdateTeam(ctx context.Context, teamName TeamName, body UpdateT return c.Client.Do(req) } +func (c *Client) ListAddonOrdersByTeam(ctx context.Context, teamName TeamName, params *ListAddonOrdersByTeamParams, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewListAddonOrdersByTeamRequest(c.Server, teamName, params) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + func (c *Client) DeleteAddonsByTeam(ctx context.Context, teamName TeamName, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewDeleteAddonsByTeamRequest(c.Server, teamName) if err != nil { @@ -3485,6 +3500,78 @@ func NewUpdateTeamRequestWithBody(server string, teamName TeamName, contentType return req, nil } +// NewListAddonOrdersByTeamRequest generates requests for ListAddonOrdersByTeam +func NewListAddonOrdersByTeamRequest(server string, teamName TeamName, params *ListAddonOrdersByTeamParams) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "team_name", runtime.ParamLocationPath, teamName) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/teams/%s/addon-orders", pathParam0) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + if params != nil { + queryValues := queryURL.Query() + + if params.Page != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "page", runtime.ParamLocationQuery, *params.Page); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + + if params.PerPage != nil { + + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "per_page", runtime.ParamLocationQuery, *params.PerPage); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } + + } + + queryURL.RawQuery = queryValues.Encode() + } + + req, err := http.NewRequest("GET", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + // NewDeleteAddonsByTeamRequest generates requests for DeleteAddonsByTeam func NewDeleteAddonsByTeamRequest(server string, teamName TeamName) (*http.Request, error) { var err error @@ -5269,6 +5356,9 @@ type ClientWithResponsesInterface interface { UpdateTeamWithResponse(ctx context.Context, teamName TeamName, body UpdateTeamJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateTeamResponse, error) + // ListAddonOrdersByTeamWithResponse request + ListAddonOrdersByTeamWithResponse(ctx context.Context, teamName TeamName, params *ListAddonOrdersByTeamParams, reqEditors ...RequestEditorFn) (*ListAddonOrdersByTeamResponse, error) + // DeleteAddonsByTeamWithResponse request DeleteAddonsByTeamWithResponse(ctx context.Context, teamName TeamName, reqEditors ...RequestEditorFn) (*DeleteAddonsByTeamResponse, error) @@ -6275,6 +6365,35 @@ func (r UpdateTeamResponse) StatusCode() int { return 0 } +type ListAddonOrdersByTeamResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *struct { + Items []AddonOrder `json:"items"` + Metadata ListMetadata `json:"metadata"` + } + JSON401 *RequiresAuthentication + JSON403 *Forbidden + JSON404 *NotFound + JSON500 *InternalError +} + +// Status returns HTTPResponse.Status +func (r ListAddonOrdersByTeamResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r ListAddonOrdersByTeamResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + type DeleteAddonsByTeamResponse struct { Body []byte HTTPResponse *http.Response @@ -7442,6 +7561,15 @@ func (c *ClientWithResponses) UpdateTeamWithResponse(ctx context.Context, teamNa return ParseUpdateTeamResponse(rsp) } +// ListAddonOrdersByTeamWithResponse request returning *ListAddonOrdersByTeamResponse +func (c *ClientWithResponses) ListAddonOrdersByTeamWithResponse(ctx context.Context, teamName TeamName, params *ListAddonOrdersByTeamParams, reqEditors ...RequestEditorFn) (*ListAddonOrdersByTeamResponse, error) { + rsp, err := c.ListAddonOrdersByTeam(ctx, teamName, params, reqEditors...) + if err != nil { + return nil, err + } + return ParseListAddonOrdersByTeamResponse(rsp) +} + // DeleteAddonsByTeamWithResponse request returning *DeleteAddonsByTeamResponse func (c *ClientWithResponses) DeleteAddonsByTeamWithResponse(ctx context.Context, teamName TeamName, reqEditors ...RequestEditorFn) (*DeleteAddonsByTeamResponse, error) { rsp, err := c.DeleteAddonsByTeam(ctx, teamName, reqEditors...) @@ -9594,6 +9722,63 @@ func ParseUpdateTeamResponse(rsp *http.Response) (*UpdateTeamResponse, error) { return response, nil } +// ParseListAddonOrdersByTeamResponse parses an HTTP response from a ListAddonOrdersByTeamWithResponse call +func ParseListAddonOrdersByTeamResponse(rsp *http.Response) (*ListAddonOrdersByTeamResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &ListAddonOrdersByTeamResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest struct { + Items []AddonOrder `json:"items"` + Metadata ListMetadata `json:"metadata"` + } + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 401: + var dest RequiresAuthentication + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON401 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 403: + var dest Forbidden + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON403 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 404: + var dest NotFound + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON404 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 500: + var dest InternalError + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON500 = &dest + + } + + return response, nil +} + // ParseDeleteAddonsByTeamResponse parses an HTTP response from a DeleteAddonsByTeamWithResponse call func ParseDeleteAddonsByTeamResponse(rsp *http.Response) (*DeleteAddonsByTeamResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) diff --git a/models.gen.go b/models.gen.go index bdf53ca..dc7f1ff 100644 --- a/models.gen.go +++ b/models.gen.go @@ -265,6 +265,22 @@ type AddonFormat string // AddonName The unique name for the addon. type AddonName = string +// AddonOrder CloudQuery Addon Order +type AddonOrder struct { + // AddonName The unique name for the addon. + AddonName AddonName `json:"addon_name"` + + // AddonTeam The unique name for the team. + AddonTeam TeamName `json:"addon_team"` + + // AddonType Supported types for addons + AddonType AddonType `json:"addon_type"` + PurchaseDate time.Time `json:"purchase_date"` + + // TeamName The unique name for the team. + TeamName TeamName `json:"team_name"` +} + // AddonTier Supported tiers for addons type AddonTier string @@ -1201,6 +1217,15 @@ type UpdateTeamJSONBody struct { DisplayName *string `json:"display_name,omitempty"` } +// ListAddonOrdersByTeamParams defines parameters for ListAddonOrdersByTeam. +type ListAddonOrdersByTeamParams struct { + // Page Page number of the results to fetch + Page *Page `form:"page,omitempty" json:"page,omitempty"` + + // PerPage The number of results per page (max 1000). + PerPage *PerPage `form:"per_page,omitempty" json:"per_page,omitempty"` +} + // ListAddonsByTeamParams defines parameters for ListAddonsByTeam. type ListAddonsByTeamParams struct { // Page Page number of the results to fetch diff --git a/spec.json b/spec.json index 4387f32..062ac91 100644 --- a/spec.json +++ b/spec.json @@ -2283,6 +2283,64 @@ ] } }, + "/teams/{team_name}/addon-orders": { + "get": { + "description": "List all addon orders for the team.", + "operationId": "ListAddonOrdersByTeam", + "parameters": [ + { + "$ref": "#/components/parameters/team_name" + }, + { + "$ref": "#/components/parameters/page" + }, + { + "$ref": "#/components/parameters/per_page" + } + ], + "responses": { + "200": { + "description": "Response", + "content": { + "application/json": { + "schema": { + "required": [ + "items", + "metadata" + ], + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/AddonOrder" + }, + "type": "array" + }, + "metadata": { + "$ref": "#/components/schemas/ListMetadata" + } + } + } + } + } + }, + "401": { + "$ref": "#/components/responses/RequiresAuthentication" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "404": { + "$ref": "#/components/responses/NotFound" + }, + "500": { + "$ref": "#/components/responses/InternalError" + } + }, + "tags": [ + "addons" + ] + } + }, "/teams/{team_name}/memberships": { "get": { "description": "Get memberships to the team.", @@ -4743,6 +4801,38 @@ "title": "Team", "type": "object" }, + "AddonOrder": { + "additionalProperties": false, + "description": "CloudQuery Addon Order", + "properties": { + "team_name": { + "$ref": "#/components/schemas/TeamName" + }, + "addon_team": { + "$ref": "#/components/schemas/TeamName" + }, + "addon_type": { + "$ref": "#/components/schemas/AddonType" + }, + "addon_name": { + "$ref": "#/components/schemas/AddonName" + }, + "purchase_date": { + "type": "string", + "format": "date-time", + "example": "2017-07-14T16:53:42Z" + } + }, + "required": [ + "team_name", + "addon_team", + "addon_type", + "addon_name", + "purchase_date" + ], + "title": "CloudQuery Addon", + "type": "object" + }, "Email": { "type": "string", "example": "user@cloudquery.io", From e07af9f5d7ff20cee004d497a30a50427ee31790 Mon Sep 17 00:00:00 2001 From: Martin Norbury Date: Thu, 16 Nov 2023 13:26:43 +0000 Subject: [PATCH 2/3] feat: Add method to return token type (#75) Whilst the token itself now contains the token type, it is useful to be able to determine the type of tokens the token client will return without fetching a token first. An example user of this functionality will be the usage client, which needs to determine if an API call is needed to fetch the team name when the authentication is using an API key. Refs: https://github.com/cloudquery/cloudquery-issues/issues/893 --- auth/token.go | 12 ++++++++++-- auth/token_test.go | 15 +++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/auth/token.go b/auth/token.go index e0f8b04..aadab9a 100644 --- a/auth/token.go +++ b/auth/token.go @@ -66,8 +66,8 @@ func NewTokenClient() *TokenClient { // GetToken returns the ID token // If CLOUDQUERY_API_KEY is set, it returns that value, otherwise it returns an ID token generated from the refresh token. func (tc *TokenClient) GetToken() (Token, error) { - if token := os.Getenv(EnvVarCloudQueryAPIKey); token != "" { - return Token{Type: APIKey, Value: token}, nil + if tc.GetTokenType() == APIKey { + return Token{Type: APIKey, Value: os.Getenv(EnvVarCloudQueryAPIKey)}, nil } // If the token is not expired, return it @@ -98,6 +98,14 @@ func (tc *TokenClient) GetToken() (Token, error) { return Token{Type: BearerToken, Value: tc.idToken}, nil } +// GetTokenType returns the type of token that will be returned by GetToken +func (tc *TokenClient) GetTokenType() TokenType { + if token := os.Getenv(EnvVarCloudQueryAPIKey); token != "" { + return APIKey + } + return BearerToken +} + func (tc *TokenClient) generateToken(refreshToken string) (*tokenResponse, error) { data := url.Values{} data.Set("grant_type", "refresh_token") diff --git a/auth/token_test.go b/auth/token_test.go index 799683d..dbc8e56 100644 --- a/auth/token_test.go +++ b/auth/token_test.go @@ -9,6 +9,7 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -103,6 +104,20 @@ func TestTokenClient_GetToken_LongExpiry(t *testing.T) { require.Equal(t, Token{Type: BearerToken, Value: "my_id_token_0"}, token, "expected to reuse token") } +func TestTokenClient_BearerTokenType(t *testing.T) { + tc := NewTokenClient() + + assert.Equal(t, BearerToken, tc.GetTokenType()) +} + +func TestTokenClient_APIKeyTokenType(t *testing.T) { + t.Setenv(EnvVarCloudQueryAPIKey, "my_token") + + tc := NewTokenClient() + + assert.Equal(t, APIKey, tc.GetTokenType()) +} + func overrideEnvironmentVariable(t *testing.T, key, value string) func() { originalValue := os.Getenv(key) resetFn := func() { From 816ca83b907c7a0a31cfc27bb991bc307338eca3 Mon Sep 17 00:00:00 2001 From: CloudQuery Bot <102256036+cq-bot@users.noreply.github.com> Date: Thu, 16 Nov 2023 15:52:39 +0200 Subject: [PATCH 3/3] chore(main): Release v1.6.0 (#74) :robot: I have created a release *beep* *boop* --- ## [1.6.0](https://github.com/cloudquery/cloudquery-api-go/compare/v1.5.1...v1.6.0) (2023-11-16) ### Features * Add method to return token type ([#75](https://github.com/cloudquery/cloudquery-api-go/issues/75)) ([e07af9f](https://github.com/cloudquery/cloudquery-api-go/commit/e07af9f5d7ff20cee004d497a30a50427ee31790)) ### Bug Fixes * Generate CloudQuery Go API Client from `spec.json` ([#73](https://github.com/cloudquery/cloudquery-api-go/issues/73)) ([db26b9c](https://github.com/cloudquery/cloudquery-api-go/commit/db26b9c0db72240072ef5f075a098c0c6153b6bc)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index dc62eaf..4889e39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## [1.6.0](https://github.com/cloudquery/cloudquery-api-go/compare/v1.5.1...v1.6.0) (2023-11-16) + + +### Features + +* Add method to return token type ([#75](https://github.com/cloudquery/cloudquery-api-go/issues/75)) ([e07af9f](https://github.com/cloudquery/cloudquery-api-go/commit/e07af9f5d7ff20cee004d497a30a50427ee31790)) + + +### Bug Fixes + +* Generate CloudQuery Go API Client from `spec.json` ([#73](https://github.com/cloudquery/cloudquery-api-go/issues/73)) ([db26b9c](https://github.com/cloudquery/cloudquery-api-go/commit/db26b9c0db72240072ef5f075a098c0c6153b6bc)) + ## [1.5.1](https://github.com/cloudquery/cloudquery-api-go/compare/v1.5.0...v1.5.1) (2023-11-15)