diff --git a/internal/api/api.go b/internal/api/api.go index 4019937553..29648a2ae0 100644 --- a/internal/api/api.go +++ b/internal/api/api.go @@ -18,6 +18,7 @@ import ( "fmt" "net/http" "strings" + "time" ) type GroupedAndSortedCommands []Group @@ -46,6 +47,7 @@ type RequestParameters struct { type Version struct { Version string + Sunset *time.Time RequestContentType string ResponseContentTypes []string } diff --git a/tools/api-generator/convert.go b/tools/api-generator/convert.go index 803a7cbc51..24bd20701b 100644 --- a/tools/api-generator/convert.go +++ b/tools/api-generator/convert.go @@ -79,8 +79,8 @@ func specToCommands(spec *openapi3.T) (api.GroupedAndSortedCommands, error) { return sortedGroups, nil } -func extractSunsetDate(operation *openapi3.Operation) *time.Time { - if sSunset, ok := operation.Extensions["x-sunset"].(string); ok && sSunset != "" { +func extractSunsetDate(extensions map[string]any) *time.Time { + if sSunset, ok := extensions["x-sunset"].(string); ok && sSunset != "" { if sunset, err := time.Parse("2006-01-02", sSunset); err == nil { return &sunset } @@ -119,8 +119,7 @@ func extractExtensionsFromOperation(operation *openapi3.Operation) (bool, string func operationToCommand(path, verb string, operation *openapi3.Operation) (*api.Command, error) { skip, operationID, aliases := extractExtensionsFromOperation(operation) - sunset := extractSunsetDate(operation) - if skip || (sunset != nil && sunset.Before(time.Now())) { + if skip { return nil, nil } @@ -139,6 +138,10 @@ func operationToCommand(path, verb string, operation *openapi3.Operation) (*api. return nil, err } + if len(versions) == 0 { + return nil, nil + } + description, err := buildDescription(operation) if err != nil { return nil, fmt.Errorf("failed to clean description: %w", err) @@ -328,6 +331,13 @@ func buildVersions(operation *openapi3.Operation) ([]api.Version, error) { return nil, err } + // filter sunsetted versions + for key, version := range versionsMap { + if version.Sunset != nil && time.Now().After(*version.Sunset) { + delete(versionsMap, key) + } + } + return sortVersions(versionsMap), nil } @@ -343,8 +353,8 @@ func processResponses(responses *openapi3.Responses, versionsMap map[string]*api continue } - for versionedContentType := range responses.Value.Content { - if err := addContentTypeToVersion(versionedContentType, versionsMap, false); err != nil { + for versionedContentType, mediaType := range responses.Value.Content { + if err := addContentTypeToVersion(versionedContentType, versionsMap, false, extractSunsetDate(mediaType.Extensions)); err != nil { return err } } @@ -358,8 +368,8 @@ func processRequestBody(requestBody *openapi3.RequestBodyRef, versionsMap map[st return nil } - for versionedContentType := range requestBody.Value.Content { - if err := addContentTypeToVersion(versionedContentType, versionsMap, true); err != nil { + for versionedContentType, mediaType := range requestBody.Value.Content { + if err := addContentTypeToVersion(versionedContentType, versionsMap, true, extractSunsetDate(mediaType.Extensions)); err != nil { return err } } @@ -367,7 +377,7 @@ func processRequestBody(requestBody *openapi3.RequestBodyRef, versionsMap map[st } // Helper function to add content type to version map. -func addContentTypeToVersion(versionedContentType string, versionsMap map[string]*api.Version, isRequest bool) error { +func addContentTypeToVersion(versionedContentType string, versionsMap map[string]*api.Version, isRequest bool, sunset *time.Time) error { version, contentType, err := extractVersionAndContentType(versionedContentType) if err != nil { return fmt.Errorf("unsupported version '%s' error: %w", versionedContentType, err) @@ -376,10 +386,17 @@ func addContentTypeToVersion(versionedContentType string, versionsMap map[string if _, ok := versionsMap[version]; !ok { versionsMap[version] = &api.Version{ Version: version, + Sunset: sunset, ResponseContentTypes: []string{}, } } + if sunset != nil { + if versionsMap[version].Sunset == nil || sunset.Before(*versionsMap[version].Sunset) { + versionsMap[version].Sunset = sunset + } + } + if isRequest { if versionsMap[version].RequestContentType != "" { return errors.New("multiple request content types is not supported") diff --git a/tools/api-generator/fixtures/07-sunset.yaml b/tools/api-generator/fixtures/07-sunset.yaml index e0f4129f07..9f81041b3e 100644 --- a/tools/api-generator/fixtures/07-sunset.yaml +++ b/tools/api-generator/fixtures/07-sunset.yaml @@ -76,7 +76,6 @@ paths: post: description: Creates one cluster in the specified project. Clusters contain a group of hosts that maintain the same data set. This resource can create clusters with asymmetrically-sized shards. Each project supports up to 25 database deployments. To use this resource, the requesting API Key must have the Project Owner role. This feature is not available for serverless clusters. operationId: createCluster - x-sunset: "2025-01-01" parameters: - $ref: '#/components/parameters/envelope' - $ref: '#/components/parameters/groupId' @@ -235,6 +234,7 @@ paths: schema: $ref: '#/components/schemas/ClusterDescription20240805' x-xgen-version: '2024-10-23' + x-sunset: "2025-01-01" description: Cluster to create in this project. required: true responses: @@ -243,22 +243,23 @@ paths: application/vnd.atlas.2023-01-01+json: schema: $ref: '#/components/schemas/LegacyAtlasCluster' - x-sunset: '2025-06-01' + x-sunset: '2025-01-01' x-xgen-version: '2023-01-01' application/vnd.atlas.2023-02-01+json: schema: $ref: '#/components/schemas/AdvancedClusterDescription' - x-sunset: '2026-03-01' + x-sunset: '2025-01-01' x-xgen-version: '2023-02-01' application/vnd.atlas.2024-08-05+json: schema: $ref: '#/components/schemas/ClusterDescription20240805' - x-sunset: '2026-03-01' + x-sunset: '2025-01-01' x-xgen-version: '2024-08-05' application/vnd.atlas.2024-10-23+json: schema: $ref: '#/components/schemas/ClusterDescription20240805' x-xgen-version: '2024-10-23' + x-sunset: '2025-01-01' description: Created '400': $ref: '#/components/responses/badRequest'