diff --git a/.generator/schemas/v2/openapi.yaml b/.generator/schemas/v2/openapi.yaml index ea3da24e20a2..6e546e1ae72a 100644 --- a/.generator/schemas/v2/openapi.yaml +++ b/.generator/schemas/v2/openapi.yaml @@ -52263,14 +52263,31 @@ components: TeamSyncAttributes: description: Team sync attributes. properties: + frequency: + $ref: '#/components/schemas/TeamSyncAttributesFrequency' source: $ref: '#/components/schemas/TeamSyncAttributesSource' + sync_membership: + $ref: '#/components/schemas/TeamSyncAttributesSyncMembership' type: $ref: '#/components/schemas/TeamSyncAttributesType' required: - source - type type: object + TeamSyncAttributesFrequency: + description: How often the sync process should be run. Defaults to `once` when + not provided. + enum: + - once + - continuously + - paused + example: once + type: string + x-enum-varnames: + - ONCE + - CONTINUOUSLY + - PAUSED TeamSyncAttributesSource: description: The external source platform for team synchronization. Only "github" is supported. @@ -52280,15 +52297,22 @@ components: type: string x-enum-varnames: - GITHUB + TeamSyncAttributesSyncMembership: + description: Whether to sync members from the external team to the Datadog team. + Defaults to `false` when not provided. + example: true + type: boolean TeamSyncAttributesType: - description: The type of synchronization operation. Only "link" is supported, - which links existing teams by matching names. + description: The type of synchronization operation. "link" connects teams by + matching names. "provision" creates new teams when no match is found. enum: - link + - provision example: link type: string x-enum-varnames: - LINK + - PROVISION TeamSyncBulkType: description: Team sync bulk type. enum: @@ -52298,10 +52322,15 @@ components: x-enum-varnames: - TEAM_SYNC_BULK TeamSyncData: - description: Team sync data. + description: A configuration governing syncing between Datadog teams and teams + from an external system. properties: attributes: $ref: '#/components/schemas/TeamSyncAttributes' + id: + description: The sync's identifier + example: aeadc05e-98a8-11ec-ac2c-da7ad0900001 + type: string type: $ref: '#/components/schemas/TeamSyncBulkType' required: @@ -52322,6 +52351,15 @@ components: required: - data type: object + TeamSyncResponse: + description: Team sync configurations response. + properties: + data: + description: List of team sync configurations + items: + $ref: '#/components/schemas/TeamSyncData' + type: array + type: object TeamTarget: description: Represents a team target for an escalation policy step, including the team's ID and resource type. @@ -81179,6 +81217,52 @@ paths: If you have any feedback, contact [Datadog support](https://docs.datadoghq.com/help/).' /api/v2/team/sync: + get: + description: 'Get all team synchronization configurations. + + Returns a list of configurations used for linking or provisioning teams with + external sources like GitHub.' + operationId: GetTeamSync + parameters: + - description: Filter by the external source platform for team synchronization + in: query + name: filter[source] + required: true + schema: + $ref: '#/components/schemas/TeamSyncAttributesSource' + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/TeamSyncResponse' + description: OK + '403': + $ref: '#/components/responses/ForbiddenResponse' + '404': + content: + application/json: + schema: + $ref: '#/components/schemas/APIErrorResponse' + description: Team sync configurations not found + '429': + $ref: '#/components/responses/TooManyRequestsResponse' + security: + - apiKeyAuth: [] + appKeyAuth: [] + - AuthZ: + - teams_read + summary: Get team sync configurations + tags: + - Teams + x-permission: + operator: OR + permissions: + - teams_read + x-unstable: '**Note**: This endpoint is in Preview. To request access, fill + out this [form](https://www.datadoghq.com/product-preview/github-integration-for-teams/). + + If you have any feedback, contact [Datadog support](https://docs.datadoghq.com/help/).' post: description: 'This endpoint attempts to link your existing Datadog teams with GitHub teams by matching their names. @@ -81205,7 +81289,8 @@ paths: using a normalized exact match; case is ignored and spaces are removed. No modifications are made - to teams in GitHub. This will not create new Teams in Datadog.' + to teams in GitHub. This only creates new teams in Datadog when type is set + to `provision`.' operationId: SyncTeams requestBody: content: diff --git a/features/v2/teams.feature b/features/v2/teams.feature index 5ba9294a164f..bf11bd0316d6 100644 --- a/features/v2/teams.feature +++ b/features/v2/teams.feature @@ -235,6 +235,22 @@ Feature: Teams Then the response status is 200 OK And the response has 3 items + @generated @skip @team:DataDog/aaa-omg + Scenario: Get team sync configurations returns "OK" response + Given operation "GetTeamSync" enabled + And new "GetTeamSync" request + And request contains "filter[source]" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 200 OK + + @generated @skip @team:DataDog/aaa-omg + Scenario: Get team sync configurations returns "Team sync configurations not found" response + Given operation "GetTeamSync" enabled + And new "GetTeamSync" request + And request contains "filter[source]" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 404 Team sync configurations not found + @generated @skip @team:DataDog/aaa-omg Scenario: Get user memberships returns "API error response." response Given new "GetUserMemberships" request diff --git a/features/v2/undo.json b/features/v2/undo.json index d25ca0a4dba2..dba9a5e29d71 100644 --- a/features/v2/undo.json +++ b/features/v2/undo.json @@ -4287,6 +4287,12 @@ "type": "unsafe" } }, + "GetTeamSync": { + "tag": "Teams", + "undo": { + "type": "safe" + } + }, "SyncTeams": { "tag": "Teams", "undo": { diff --git a/private/bdd_runner/src/support/scenarios_model_mapping.ts b/private/bdd_runner/src/support/scenarios_model_mapping.ts index e17570286950..620124ad0974 100644 --- a/private/bdd_runner/src/support/scenarios_model_mapping.ts +++ b/private/bdd_runner/src/support/scenarios_model_mapping.ts @@ -8693,6 +8693,13 @@ export const ScenariosModelMappings: { [key: string]: OperationMapping } = { }, operationResponseType: "TeamResponse", }, + "TeamsApi.V2.GetTeamSync": { + filterSource: { + type: "TeamSyncAttributesSource", + format: "", + }, + operationResponseType: "TeamSyncResponse", + }, "TeamsApi.V2.SyncTeams": { body: { type: "TeamSyncRequest", diff --git a/services/teams/src/v2/TeamsApi.ts b/services/teams/src/v2/TeamsApi.ts index 6b4460d78d21..05f89c95c9e1 100644 --- a/services/teams/src/v2/TeamsApi.ts +++ b/services/teams/src/v2/TeamsApi.ts @@ -38,7 +38,9 @@ import { TeamPermissionSettingUpdateRequest } from "./models/TeamPermissionSetti import { TeamResponse } from "./models/TeamResponse"; import { TeamsField } from "./models/TeamsField"; import { TeamsResponse } from "./models/TeamsResponse"; +import { TeamSyncAttributesSource } from "./models/TeamSyncAttributesSource"; import { TeamSyncRequest } from "./models/TeamSyncRequest"; +import { TeamSyncResponse } from "./models/TeamSyncResponse"; import { TeamUpdateRequest } from "./models/TeamUpdateRequest"; import { UserTeam } from "./models/UserTeam"; import { UserTeamRequest } from "./models/UserTeamRequest"; @@ -702,6 +704,63 @@ export class TeamsApiRequestFactory extends BaseAPIRequestFactory { return requestContext; } + public async getTeamSync( + filterSource: TeamSyncAttributesSource, + _options?: Configuration, + ): Promise { + const _config = _options || this.configuration; + + if (!_config.unstableOperations["TeamsApi.v2.getTeamSync"]) { + throw new Error( + "Unstable operation 'getTeamSync' is disabled. Enable it by setting `configuration.unstableOperations['TeamsApi.v2.getTeamSync'] = true`", + ); + } + + // verify required parameter 'filterSource' is not null or undefined + if (filterSource === null || filterSource === undefined) { + throw new RequiredError("filterSource", "getTeamSync"); + } + + // Path Params + const localVarPath = "/api/v2/team/sync"; + + // Make Request Context + const { server, overrides } = _config.getServerAndOverrides( + "TeamsApi.v2.getTeamSync", + TeamsApi.operationServers, + ); + const requestContext = server.makeRequestContext( + localVarPath, + HttpMethod.GET, + overrides, + ); + requestContext.setHeaderParam("Accept", "application/json"); + requestContext.setHttpConfig(_config.httpConfig); + + // Set User-Agent + if (this.userAgent) { + requestContext.setHeaderParam("User-Agent", this.userAgent); + } + + // Query Params + if (filterSource !== undefined) { + requestContext.setQueryParam( + "filter[source]", + serialize(filterSource, TypingInfo, "TeamSyncAttributesSource", ""), + "", + ); + } + + // Apply auth methods + applySecurityAuthentication(_config, requestContext, [ + "apiKeyAuth", + "appKeyAuth", + "AuthZ", + ]); + + return requestContext; + } + public async getUserMemberships( userUuid: string, _options?: Configuration, @@ -1955,6 +2014,66 @@ export class TeamsApiResponseProcessor { ); } + /** + * Unwraps the actual response sent by the server from the response context and deserializes the response content + * to the expected objects + * + * @params response Response returned by the server for a request to getTeamSync + * @throws ApiException if the response code was not in [200, 299] + */ + public async getTeamSync( + response: ResponseContext, + ): Promise { + const contentType = normalizeMediaType(response.headers["content-type"]); + if (response.httpStatusCode === 200) { + const body: TeamSyncResponse = deserialize( + parse(await response.body.text(), contentType), + TypingInfo, + "TeamSyncResponse", + ) as TeamSyncResponse; + return body; + } + if ( + response.httpStatusCode === 403 || + response.httpStatusCode === 404 || + response.httpStatusCode === 429 + ) { + const bodyText = parse(await response.body.text(), contentType); + let body: APIErrorResponse; + try { + body = deserialize( + bodyText, + TypingInfo, + "APIErrorResponse", + ) as APIErrorResponse; + } catch (error) { + logger.debug(`Got error deserializing error: ${error}`); + throw new ApiException( + response.httpStatusCode, + bodyText, + ); + } + throw new ApiException(response.httpStatusCode, body); + } + + // Work around for missing responses in specification, e.g. for petstore.yaml + if (response.httpStatusCode >= 200 && response.httpStatusCode <= 299) { + const body: TeamSyncResponse = deserialize( + parse(await response.body.text(), contentType), + TypingInfo, + "TeamSyncResponse", + "", + ) as TeamSyncResponse; + return body; + } + + const body = (await response.body.text()) || ""; + throw new ApiException( + response.httpStatusCode, + 'Unknown API Status Code!\nBody: "' + body + '"', + ); + } + /** * Unwraps the actual response sent by the server from the response context and deserializes the response content * to the expected objects @@ -2602,6 +2721,14 @@ export interface TeamsApiGetTeamPermissionSettingsRequest { teamId: string; } +export interface TeamsApiGetTeamSyncRequest { + /** + * Filter by the external source platform for team synchronization + * @type TeamSyncAttributesSource + */ + filterSource: TeamSyncAttributesSource; +} + export interface TeamsApiGetUserMembershipsRequest { /** * None @@ -3081,6 +3208,28 @@ export class TeamsApi { }); } + /** + * Get all team synchronization configurations. + * Returns a list of configurations used for linking or provisioning teams with external sources like GitHub. + * @param param The request object + */ + public getTeamSync( + param: TeamsApiGetTeamSyncRequest, + options?: Configuration, + ): Promise { + const requestContextPromise = this.requestFactory.getTeamSync( + param.filterSource, + options, + ); + return requestContextPromise.then((requestContext) => { + return this.configuration.httpApi + .send(requestContext) + .then((responseContext) => { + return this.responseProcessor.getTeamSync(responseContext); + }); + }); + } + /** * Get a list of memberships for a user * @param param The request object @@ -3271,7 +3420,7 @@ export class TeamsApi { * [A GitHub organization must be connected to your Datadog account](https://docs.datadoghq.com/integrations/github/), * and the GitHub App integrated with Datadog must have the `Members Read` permission. Matching is performed by comparing the Datadog team handle to the GitHub team slug * using a normalized exact match; case is ignored and spaces are removed. No modifications are made - * to teams in GitHub. This will not create new Teams in Datadog. + * to teams in GitHub. This only creates new teams in Datadog when type is set to `provision`. * @param param The request object */ public syncTeams( diff --git a/services/teams/src/v2/index.ts b/services/teams/src/v2/index.ts index c3970a51edb0..81b3b6948c00 100644 --- a/services/teams/src/v2/index.ts +++ b/services/teams/src/v2/index.ts @@ -11,6 +11,7 @@ export { TeamsApiGetTeamLinksRequest, TeamsApiGetTeamMembershipsRequest, TeamsApiGetTeamPermissionSettingsRequest, + TeamsApiGetTeamSyncRequest, TeamsApiGetUserMembershipsRequest, TeamsApiListMemberTeamsRequest, TeamsApiListTeamsRequest, @@ -80,11 +81,13 @@ export { TeamsResponseLinks } from "./models/TeamsResponseLinks"; export { TeamsResponseMeta } from "./models/TeamsResponseMeta"; export { TeamsResponseMetaPagination } from "./models/TeamsResponseMetaPagination"; export { TeamSyncAttributes } from "./models/TeamSyncAttributes"; +export { TeamSyncAttributesFrequency } from "./models/TeamSyncAttributesFrequency"; export { TeamSyncAttributesSource } from "./models/TeamSyncAttributesSource"; export { TeamSyncAttributesType } from "./models/TeamSyncAttributesType"; export { TeamSyncBulkType } from "./models/TeamSyncBulkType"; export { TeamSyncData } from "./models/TeamSyncData"; export { TeamSyncRequest } from "./models/TeamSyncRequest"; +export { TeamSyncResponse } from "./models/TeamSyncResponse"; export { TeamType } from "./models/TeamType"; export { TeamUpdate } from "./models/TeamUpdate"; export { TeamUpdateAttributes } from "./models/TeamUpdateAttributes"; diff --git a/services/teams/src/v2/models/TeamSyncAttributes.ts b/services/teams/src/v2/models/TeamSyncAttributes.ts index 0329de1489ad..ed3d29733306 100644 --- a/services/teams/src/v2/models/TeamSyncAttributes.ts +++ b/services/teams/src/v2/models/TeamSyncAttributes.ts @@ -1,5 +1,6 @@ import { AttributeTypeMap } from "@datadog/datadog-api-client"; +import { TeamSyncAttributesFrequency } from "./TeamSyncAttributesFrequency"; import { TeamSyncAttributesSource } from "./TeamSyncAttributesSource"; import { TeamSyncAttributesType } from "./TeamSyncAttributesType"; @@ -7,12 +8,20 @@ import { TeamSyncAttributesType } from "./TeamSyncAttributesType"; * Team sync attributes. */ export class TeamSyncAttributes { + /** + * How often the sync process should be run. Defaults to `once` when not provided. + */ + "frequency"?: TeamSyncAttributesFrequency; /** * The external source platform for team synchronization. Only "github" is supported. */ "source": TeamSyncAttributesSource; /** - * The type of synchronization operation. Only "link" is supported, which links existing teams by matching names. + * Whether to sync members from the external team to the Datadog team. Defaults to `false` when not provided. + */ + "syncMembership"?: boolean; + /** + * The type of synchronization operation. "link" connects teams by matching names. "provision" creates new teams when no match is found. */ "type": TeamSyncAttributesType; /** @@ -30,11 +39,19 @@ export class TeamSyncAttributes { * @ignore */ static readonly attributeTypeMap: AttributeTypeMap = { + frequency: { + baseName: "frequency", + type: "TeamSyncAttributesFrequency", + }, source: { baseName: "source", type: "TeamSyncAttributesSource", required: true, }, + syncMembership: { + baseName: "sync_membership", + type: "boolean", + }, type: { baseName: "type", type: "TeamSyncAttributesType", diff --git a/services/teams/src/v2/models/TeamSyncAttributesFrequency.ts b/services/teams/src/v2/models/TeamSyncAttributesFrequency.ts new file mode 100644 index 000000000000..a63ddbceb76b --- /dev/null +++ b/services/teams/src/v2/models/TeamSyncAttributesFrequency.ts @@ -0,0 +1,13 @@ +import { UnparsedObject } from "@datadog/datadog-api-client"; + +/** + * How often the sync process should be run. Defaults to `once` when not provided. + */ +export type TeamSyncAttributesFrequency = + | typeof ONCE + | typeof CONTINUOUSLY + | typeof PAUSED + | UnparsedObject; +export const ONCE = "once"; +export const CONTINUOUSLY = "continuously"; +export const PAUSED = "paused"; diff --git a/services/teams/src/v2/models/TeamSyncAttributesType.ts b/services/teams/src/v2/models/TeamSyncAttributesType.ts index 6690b8cd057f..0cdcb9eb19a5 100644 --- a/services/teams/src/v2/models/TeamSyncAttributesType.ts +++ b/services/teams/src/v2/models/TeamSyncAttributesType.ts @@ -1,7 +1,11 @@ import { UnparsedObject } from "@datadog/datadog-api-client"; /** - * The type of synchronization operation. Only "link" is supported, which links existing teams by matching names. + * The type of synchronization operation. "link" connects teams by matching names. "provision" creates new teams when no match is found. */ -export type TeamSyncAttributesType = typeof LINK | UnparsedObject; +export type TeamSyncAttributesType = + | typeof LINK + | typeof PROVISION + | UnparsedObject; export const LINK = "link"; +export const PROVISION = "provision"; diff --git a/services/teams/src/v2/models/TeamSyncData.ts b/services/teams/src/v2/models/TeamSyncData.ts index 11aff6fe384b..42a293f0d8a6 100644 --- a/services/teams/src/v2/models/TeamSyncData.ts +++ b/services/teams/src/v2/models/TeamSyncData.ts @@ -4,13 +4,17 @@ import { TeamSyncAttributes } from "./TeamSyncAttributes"; import { TeamSyncBulkType } from "./TeamSyncBulkType"; /** - * Team sync data. + * A configuration governing syncing between Datadog teams and teams from an external system. */ export class TeamSyncData { /** * Team sync attributes. */ "attributes": TeamSyncAttributes; + /** + * The sync's identifier + */ + "id"?: string; /** * Team sync bulk type. */ @@ -35,6 +39,10 @@ export class TeamSyncData { type: "TeamSyncAttributes", required: true, }, + id: { + baseName: "id", + type: "string", + }, type: { baseName: "type", type: "TeamSyncBulkType", diff --git a/services/teams/src/v2/models/TeamSyncRequest.ts b/services/teams/src/v2/models/TeamSyncRequest.ts index 52ed589352d4..ac798ea2231c 100644 --- a/services/teams/src/v2/models/TeamSyncRequest.ts +++ b/services/teams/src/v2/models/TeamSyncRequest.ts @@ -7,7 +7,7 @@ import { TeamSyncData } from "./TeamSyncData"; */ export class TeamSyncRequest { /** - * Team sync data. + * A configuration governing syncing between Datadog teams and teams from an external system. */ "data": TeamSyncData; /** diff --git a/services/teams/src/v2/models/TeamSyncResponse.ts b/services/teams/src/v2/models/TeamSyncResponse.ts new file mode 100644 index 000000000000..5b2037a989a2 --- /dev/null +++ b/services/teams/src/v2/models/TeamSyncResponse.ts @@ -0,0 +1,46 @@ +import { AttributeTypeMap } from "@datadog/datadog-api-client"; + +import { TeamSyncData } from "./TeamSyncData"; + +/** + * Team sync configurations response. + */ +export class TeamSyncResponse { + /** + * List of team sync configurations + */ + "data"?: Array; + /** + * A container for additional, undeclared properties. + * This is a holder for any undeclared properties as specified with + * the 'additionalProperties' keyword in the OAS document. + */ + "additionalProperties"?: { [key: string]: any }; + /** + * @ignore + */ + "_unparsed"?: boolean; + + /** + * @ignore + */ + static readonly attributeTypeMap: AttributeTypeMap = { + data: { + baseName: "data", + type: "Array", + }, + additionalProperties: { + baseName: "additionalProperties", + type: "{ [key: string]: any; }", + }, + }; + + /** + * @ignore + */ + static getAttributeTypeMap(): AttributeTypeMap { + return TeamSyncResponse.attributeTypeMap; + } + + public constructor() {} +} diff --git a/services/teams/src/v2/models/TypingInfo.ts b/services/teams/src/v2/models/TypingInfo.ts index 8e15310253ce..859d75291396 100644 --- a/services/teams/src/v2/models/TypingInfo.ts +++ b/services/teams/src/v2/models/TypingInfo.ts @@ -43,6 +43,7 @@ import { TeamResponse } from "./TeamResponse"; import { TeamSyncAttributes } from "./TeamSyncAttributes"; import { TeamSyncData } from "./TeamSyncData"; import { TeamSyncRequest } from "./TeamSyncRequest"; +import { TeamSyncResponse } from "./TeamSyncResponse"; import { TeamUpdate } from "./TeamUpdate"; import { TeamUpdateAttributes } from "./TeamUpdateAttributes"; import { TeamUpdateRelationships } from "./TeamUpdateRelationships"; @@ -93,8 +94,9 @@ export const TypingInfo: ModelTypingInfo = { "user_access_manage", "teams_manage", ], + TeamSyncAttributesFrequency: ["once", "continuously", "paused"], TeamSyncAttributesSource: ["github"], - TeamSyncAttributesType: ["link"], + TeamSyncAttributesType: ["link", "provision"], TeamSyncBulkType: ["team_sync_bulk"], TeamType: ["team"], TeamsField: [ @@ -170,6 +172,7 @@ export const TypingInfo: ModelTypingInfo = { TeamSyncAttributes: TeamSyncAttributes, TeamSyncData: TeamSyncData, TeamSyncRequest: TeamSyncRequest, + TeamSyncResponse: TeamSyncResponse, TeamUpdate: TeamUpdate, TeamUpdateAttributes: TeamUpdateAttributes, TeamUpdateRelationships: TeamUpdateRelationships,