Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion tools/cli/internal/cli/sunset/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package sunset
import (
"encoding/json"
"fmt"
"sort"
"strings"
"time"

Expand Down Expand Up @@ -52,6 +53,14 @@ func (o *ListOpts) Run() error {
return err
}

// order sunset elements per Path,Operation in ascending order
sort.Slice(sunsets, func(i, j int) bool {
if sunsets[i].Path != sunsets[j].Path {
return sunsets[i].Path < sunsets[j].Path
}
return sunsets[i].Operation < sunsets[j].Operation
})

bytes, err := o.newSunsetListBytes(sunsets)
if err != nil {
return err
Expand Down Expand Up @@ -170,6 +179,5 @@ func ListBuilder() *cobra.Command {
cmd.Flags().StringVarP(&opts.format, flag.Format, flag.FormatShort, "json", usage.Format)

_ = cmd.MarkFlagRequired(flag.Spec)

return cmd
}
99 changes: 99 additions & 0 deletions tools/cli/internal/cli/sunset/list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@
package sunset

import (
"encoding/json"
"reflect"
"testing"

"github.com/mongodb/openapi/tools/cli/internal/openapi/sunset"
"github.com/spf13/afero"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand All @@ -28,10 +31,106 @@ func TestList_Run(t *testing.T) {
basePath: "../../../test/data/base_spec.json",
outputPath: "foas.json",
fs: fs,
format: "json",
from: "2024-09-22",
to: "2026-09-22",
}

require.NoError(t, opts.Run())
b, err := afero.ReadFile(fs, opts.outputPath)
require.NoError(t, err)
assert.NotEmpty(t, b)
var results []*sunset.Sunset
require.NoError(t, json.Unmarshal(b, &results))
if !reflect.DeepEqual(results, expectedResults) {
gotPretty, _ := json.MarshalIndent(results, "", " ")
wantPretty, _ := json.MarshalIndent(expectedResults, "", " ")
t.Errorf("mismatch:\nGot:\n%s\nWant:\n%s", string(gotPretty), string(wantPretty))
}
}

var expectedResults = []*sunset.Sunset{
{Operation: "GET", Path: "/api/atlas/v2/example/info", SunsetDate: "2025-06-01", Team: "APIx",
Version: "2023-01-01"},
{Operation: "GET",
Path: "/api/atlas/v2/federationSettings/{federationSettingsId}/identityProviders/{identityProviderId}",
SunsetDate: "2025-01-01", Team: "IAM", Version: "2023-01-01"},
{Operation: "PATCH",
Path: "/api/atlas/v2/federationSettings/{federationSettingsId}/identityProviders/{identityProviderId}",
SunsetDate: "2025-01-01", Team: "IAM", Version: "2023-01-01"},
{Operation: "PATCH", Path: "/api/atlas/v2/groups/{groupId}/alerts/{alertId}", SunsetDate: "2025-05-30",
Team: "CAP", Version: "2023-01-01"},
{Operation: "GET", Path: "/api/atlas/v2/groups/{groupId}/backup/exportBuckets", SunsetDate: "2025-05-30",
Team: "Backup - Atlas", Version: "2023-01-01"},
{Operation: "POST", Path: "/api/atlas/v2/groups/{groupId}/backup/exportBuckets",
SunsetDate: "2025-05-30", Team: "Backup - Atlas", Version: "2023-01-01"},
{Operation: "GET", Path: "/api/atlas/v2/groups/{groupId}/backup/exportBuckets/{exportBucketId}",
SunsetDate: "2025-05-30", Team: "Backup - Atlas", Version: "2023-01-01"},
{Operation: "GET", Path: "/api/atlas/v2/groups/{groupId}/backupCompliancePolicy",
SunsetDate: "2024-10-01", Team: "Backup - Atlas", Version: "2023-01-01"},
{Operation: "PUT", Path: "/api/atlas/v2/groups/{groupId}/backupCompliancePolicy",
SunsetDate: "2024-10-01", Team: "Backup - Atlas", Version: "2023-01-01"},
{Operation: "POST", Path: "/api/atlas/v2/groups/{groupId}/clusters",
SunsetDate: "2025-06-01", Team: "Atlas Dedicated", Version: "2023-01-01"},
{Operation: "DELETE", Path: "/api/atlas/v2/groups/{groupId}/clusters/{clusterName}",
SunsetDate: "2025-06-01", Team: "Atlas Dedicated", Version: "2023-01-01"},
{Operation: "GET", Path: "/api/atlas/v2/groups/{groupId}/clusters/{clusterName}",
SunsetDate: "2025-06-01", Team: "Atlas Dedicated", Version: "2023-01-01"},
{Operation: "PATCH", Path: "/api/atlas/v2/groups/{groupId}/clusters/{clusterName}",
SunsetDate: "2025-06-01", Team: "Atlas Dedicated", Version: "2023-01-01"},
{Operation: "POST", Path: "/api/atlas/v2/groups/{groupId}/clusters/{clusterName}/fts/indexes",
SunsetDate: "2025-06-01", Team: "Search Web Platform", Version: "2023-01-01"},
{Operation: "GET",
Path: "/api/atlas/v2/groups/{groupId}/clusters/{clusterName}/fts/indexes/{databaseName}/{collectionName}",
SunsetDate: "2025-06-01", Team: "Search Web Platform", Version: "2023-01-01"},
{Operation: "DELETE",
Path: "/api/atlas/v2/groups/{groupId}/clusters/{clusterName}/fts/indexes/{indexId}",
SunsetDate: "2025-06-01", Team: "Search Web Platform", Version: "2023-01-01"},
{Operation: "GET",
Path: "/api/atlas/v2/groups/{groupId}/clusters/{clusterName}/fts/indexes/{indexId}",
SunsetDate: "2025-06-01", Team: "Search Web Platform", Version: "2023-01-01"},
{Operation: "PATCH", Path: "/api/atlas/v2/groups/{groupId}/clusters/{clusterName}/fts/indexes/{indexId}",
SunsetDate: "2025-06-01", Team: "Search Web Platform", Version: "2023-01-01"},
{Operation: "GET", Path: "/api/atlas/v2/groups/{groupId}/clusters/{clusterName}/globalWrites",
SunsetDate: "2025-06-01", Team: "Atlas Dedicated", Version: "2023-01-01"},
{Operation: "DELETE", Path: "/api/atlas/v2/groups/{groupId}/clusters/{clusterName}/globalWrites/customZoneMapping",
SunsetDate: "2025-06-01", Team: "Atlas Dedicated", Version: "2023-01-01"},
{Operation: "POST", Path: "/api/atlas/v2/groups/{groupId}/clusters/{clusterName}/globalWrites/customZoneMapping",
SunsetDate: "2025-06-01", Team: "Atlas Dedicated", Version: "2023-01-01"},
{Operation: "DELETE", Path: "/api/atlas/v2/groups/{groupId}/clusters/{clusterName}/globalWrites/managedNamespaces",
SunsetDate: "2025-06-01", Team: "Atlas Dedicated", Version: "2023-01-01"},
{Operation: "POST", Path: "/api/atlas/v2/groups/{groupId}/clusters/{clusterName}/globalWrites/managedNamespaces",
SunsetDate: "2025-06-01", Team: "Atlas Dedicated", Version: "2023-01-01"},
{Operation: "GET", Path: "/api/atlas/v2/groups/{groupId}/clusters/{clusterName}/processArgs",
SunsetDate: "2025-06-01", Team: "Atlas", Version: "2023-01-01"},
{Operation: "PATCH", Path: "/api/atlas/v2/groups/{groupId}/clusters/{clusterName}/processArgs",
SunsetDate: "2025-06-01", Team: "Atlas", Version: "2023-01-01"},
{Operation: "POST", Path: "/api/atlas/v2/groups/{groupId}/clusters/{clusterName}/restartPrimaries",
SunsetDate: "2025-06-01", Team: "Atlas Dedicated", Version: "2023-01-01"},
{Operation: "DELETE", Path: "/api/atlas/v2/groups/{groupId}/clusters/{clusterName}/search/deployment",
SunsetDate: "2026-03-01", Team: "Search Web Platform", Version: "2023-01-01"},
{Operation: "GET", Path: "/api/atlas/v2/groups/{groupId}/clusters/{clusterName}/search/deployment",
SunsetDate: "2026-03-01", Team: "Search Web Platform", Version: "2023-01-01"},
{Operation: "PATCH", Path: "/api/atlas/v2/groups/{groupId}/clusters/{clusterName}/search/deployment",
SunsetDate: "2026-03-01", Team: "Search Web Platform", Version: "2023-01-01"},
{Operation: "POST", Path: "/api/atlas/v2/groups/{groupId}/clusters/{clusterName}/search/deployment",
SunsetDate: "2026-03-01", Team: "Search Web Platform", Version: "2023-01-01"},
{Operation: "GET", Path: "/api/atlas/v2/groups/{groupId}/clusters/{hostName}/logs/{logName}.gz",
SunsetDate: "2025-06-01", Team: "Atlas Dedicated", Version: "2023-01-01"},
{Operation: "GET", Path: "/api/atlas/v2/groups/{groupId}/invites", SunsetDate: "2024-10-04", Team: "IAM",
Version: "2023-01-01"},
{Operation: "PATCH", Path: "/api/atlas/v2/groups/{groupId}/invites",
SunsetDate: "2024-10-04", Team: "IAM", Version: "2023-01-01"},
{Operation: "POST", Path: "/api/atlas/v2/groups/{groupId}/invites", SunsetDate: "2024-10-04", Team: "IAM",
Version: "2023-01-01"},
{Operation: "DELETE", Path: "/api/atlas/v2/groups/{groupId}/invites/{invitationId}", SunsetDate: "2024-10-04",
Team: "IAM", Version: "2023-01-01"},
{Operation: "GET", Path: "/api/atlas/v2/groups/{groupId}/invites/{invitationId}", SunsetDate: "2024-10-04",
Team: "IAM", Version: "2023-01-01"},
{Operation: "PATCH", Path: "/api/atlas/v2/groups/{groupId}/invites/{invitationId}", SunsetDate: "2024-10-04",
Team: "IAM", Version: "2023-01-01"},
{Operation: "POST", Path: "/api/atlas/v2/groups/{groupId}/liveMigrations", SunsetDate: "2025-05-30",
Team: "Atlas Migrations", Version: "2023-01-01"},
{Operation: "POST", Path: "/api/atlas/v2/groups/{groupId}/liveMigrations/validate", SunsetDate: "2025-05-30",
Team: "Atlas Migrations", Version: "2023-01-01"},
}
26 changes: 22 additions & 4 deletions tools/cli/internal/openapi/sunset/sunset.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@
package sunset

import (
"maps"
"regexp"
"slices"
"sort"

"github.com/getkin/kin-openapi/openapi3"
"github.com/tufin/oasdiff/load"
)
Expand Down Expand Up @@ -95,8 +100,21 @@ func successResponseExtensions(responsesMap map[string]*openapi3.ResponseRef) ma
}

func contentExtensions(content openapi3.Content) map[string]any {
for _, v := range content {
return v.Extensions
}
return nil
keysContent := slices.Collect(maps.Keys(content))
// Regex to find a date in YYYY-MM-DD format.
dateRegex := regexp.MustCompile(`\d{4}-\d{2}-\d{2}`)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

q: What about upcoming and preview?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

upcoming will sunset with the related stable api so we will get the sunset date from the stable api.

Regarding preview is a bit tricky, I need to think about how to add support for it and if it makes sense 🤔

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will create a follow up ticket for preview

// we need the content of the API version with the older date.
sort.Slice(keysContent, func(i, j int) bool {
dateI := dateRegex.FindString(keysContent[i])
dateJ := dateRegex.FindString(keysContent[j])

// If both have dates, compare them as strings.
if dateI != "" && dateJ != "" {
return dateI < dateJ
}
// Strings with dates should come before those without.
return dateI != ""
})

return content[keysContent[0]].Extensions
}
Loading