Skip to content

Commit 04361db

Browse files
add support for public preview api to 'foasclo version' command
1 parent 4cc8dec commit 04361db

File tree

5 files changed

+78
-27
lines changed

5 files changed

+78
-27
lines changed

tools/cli/internal/apiversion/version.go

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
14+
1415
package apiversion
1516

1617
import (
@@ -23,15 +24,18 @@ import (
2324
)
2425

2526
type APIVersion struct {
26-
version string
27-
versionDate time.Time
27+
version string
28+
stabilityVersion string
29+
versionDate time.Time
2830
}
2931

3032
const (
31-
dateFormat = "2006-01-02"
33+
dateFormat = "2006-01-02"
34+
StableStabilityLevel = "STABLE"
35+
PreviewStabilityLevel = "PREVIEW"
3236
)
3337

34-
var ContentPattern = regexp.MustCompile(`application/vnd\.atlas\.(\d{4})-(\d{2})-(\d{2})\+(.+)`)
38+
var ContentPattern = regexp.MustCompile(`application/vnd\.atlas\.((\d{4})-(\d{2})-(\d{2})|preview)\+(.+)`)
3539

3640
// Option is a function that sets a value on the APIVersion.
3741
type Option func(v *APIVersion) error
@@ -66,10 +70,31 @@ func WithDate(date time.Time) Option {
6670
return func(v *APIVersion) error {
6771
v.version = date.Format(dateFormat)
6872
v.versionDate = date
73+
v.stabilityVersion = StableStabilityLevel
74+
return nil
75+
}
76+
}
77+
78+
// WithStabilityLevel sets the version and stability level on the APIVersion.
79+
func WithStabilityLevel(version, stabilityLevel string) Option {
80+
return func(v *APIVersion) error {
81+
v.stabilityVersion = stabilityLevel
82+
v.version = version
83+
if stabilityLevel != StableStabilityLevel {
84+
return nil
85+
}
86+
87+
versionDate, err := DateFromVersion(version)
88+
if err != nil {
89+
return err
90+
}
91+
92+
v.versionDate = versionDate
6993
return nil
7094
}
7195
}
7296

97+
// WithContent returns an Option to generate a new APIVersion given the contentType.
7398
func WithContent(contentType string) Option {
7499
return func(v *APIVersion) error {
75100
version, err := Parse(contentType)
@@ -78,6 +103,12 @@ func WithContent(contentType string) Option {
78103
}
79104

80105
v.version = version
106+
v.stabilityVersion = StableStabilityLevel
107+
if version == PreviewStabilityLevel {
108+
v.stabilityVersion = PreviewStabilityLevel
109+
return nil
110+
}
111+
81112
v.versionDate, err = DateFromVersion(version)
82113
if err != nil {
83114
return err
@@ -124,7 +155,12 @@ func Parse(contentType string) (string, error) {
124155
if matches == nil {
125156
return "", fmt.Errorf("invalid content type: %s", contentType)
126157
}
127-
return fmt.Sprintf("%s-%s-%s", matches[1], matches[2], matches[3]), nil
158+
159+
if len(matches) == 3 {
160+
return fmt.Sprintf("%s-%s-%s", matches[1], matches[2], matches[3]), nil
161+
}
162+
163+
return matches[1], nil
128164
}
129165

130166
// FindLatestContentVersionMatched finds the latest content version that matches the requested version.

tools/cli/internal/cli/flag/flag.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,6 @@ const (
4747
ChannelIDShort = "c"
4848
From = "from"
4949
To = "to"
50+
StabilityLevel = "stability-level"
51+
StabilityLevelShort = "sl"
5052
)

tools/cli/internal/cli/usage/usage.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,5 @@ const (
3737
SlackChannelID = "Slack Channel ID."
3838
From = "Date in the format YYYY-MM-DD that indicates the start of a date range"
3939
To = "Date in the format YYYY-MM-DD that indicates the end of a date range"
40+
StabilityLevel = "Stability level related to the API Version. Valid values: [STABLE, PREVIEW]"
4041
)

tools/cli/internal/cli/versions/versions.go

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package versions
1717
import (
1818
"encoding/json"
1919
"fmt"
20+
"github.com/mongodb/openapi/tools/cli/internal/apiversion"
2021
"strings"
2122

2223
"github.com/mongodb/openapi/tools/cli/internal/cli/flag"
@@ -28,11 +29,12 @@ import (
2829
)
2930

3031
type Opts struct {
31-
fs afero.Fs
32-
basePath string
33-
outputPath string
34-
format string
35-
env string
32+
fs afero.Fs
33+
basePath string
34+
outputPath string
35+
format string
36+
env string
37+
stabilityLevel string
3638
}
3739

3840
func (o *Opts) Run() error {
@@ -43,11 +45,7 @@ func (o *Opts) Run() error {
4345
}
4446

4547
var versions []string
46-
if o.env == "" {
47-
versions, err = openapi.ExtractVersions(specInfo.Spec)
48-
} else {
49-
versions, err = openapi.ExtractVersionsWithEnv(specInfo.Spec, o.env)
50-
}
48+
versions, err = openapi.ExtractVersionsWithEnv(specInfo.Spec, o.env)
5149

5250
if err != nil {
5351
return err
@@ -57,7 +55,7 @@ func (o *Opts) Run() error {
5755
return fmt.Errorf("no versions found in the OpenAPI specification")
5856
}
5957

60-
bytes, err := o.getVersionBytes(versions)
58+
bytes, err := o.versionsAsBytes(versions)
6159
if err != nil {
6260
return err
6361
}
@@ -70,7 +68,7 @@ func (o *Opts) Run() error {
7068
return nil
7169
}
7270

73-
func (o *Opts) getVersionBytes(versions []string) ([]byte, error) {
71+
func (o *Opts) versionsAsBytes(versions []string) ([]byte, error) {
7472
data, err := json.MarshalIndent(versions, "", " ")
7573
if err != nil {
7674
return nil, err
@@ -94,16 +92,21 @@ func (o *Opts) getVersionBytes(versions []string) ([]byte, error) {
9492
}
9593

9694
func (o *Opts) PreRunE(_ []string) error {
95+
o.stabilityLevel = strings.ToUpper(o.stabilityLevel)
96+
if o.stabilityLevel != "" && o.stabilityLevel != apiversion.PreviewStabilityLevel && o.stabilityLevel != apiversion.StableStabilityLevel {
97+
return fmt.Errorf("stability level must be %q or %q, got %q", apiversion.PreviewStabilityLevel, apiversion.StableStabilityLevel, o.stabilityLevel)
98+
}
99+
97100
if o.basePath == "" {
98-
return fmt.Errorf("no OAS detected. Please, use the flag %s to include the base OAS", flag.Base)
101+
return fmt.Errorf("no OAS detected. Please, use the flag %q to include the base OAS", flag.Base)
99102
}
100103

101104
if o.outputPath != "" && !strings.Contains(o.outputPath, ".json") && !strings.Contains(o.outputPath, ".yaml") {
102-
return fmt.Errorf("output file must be either a JSON or YAML file, got %s", o.outputPath)
105+
return fmt.Errorf("output file must be either a JSON or YAML file, got %q", o.outputPath)
103106
}
104107

105108
if o.format != "json" && o.format != "yaml" {
106-
return fmt.Errorf("output format must be either 'json' or 'yaml', got %s", o.format)
109+
return fmt.Errorf("output format must be either 'json' or 'yaml', got %q", o.format)
107110
}
108111

109112
return nil
@@ -117,9 +120,10 @@ func Builder() *cobra.Command {
117120
}
118121

119122
cmd := &cobra.Command{
120-
Use: "versions -s spec ",
121-
Short: "Get a list of versions from an OpenAPI specification.",
122-
Args: cobra.NoArgs,
123+
Use: "versions -s spec ",
124+
Aliases: []string{"versions list", "versions ls"},
125+
Short: "Get a list of versions from an OpenAPI specification.",
126+
Args: cobra.NoArgs,
123127
PreRunE: func(_ *cobra.Command, args []string) error {
124128
return opts.PreRunE(args)
125129
},
@@ -130,7 +134,9 @@ func Builder() *cobra.Command {
130134

131135
cmd.Flags().StringVarP(&opts.basePath, flag.Spec, flag.SpecShort, "", usage.Spec)
132136
cmd.Flags().StringVar(&opts.env, flag.Environment, "", usage.Environment)
137+
cmd.Flags().StringVarP(&opts.stabilityLevel, flag.StabilityLevel, flag.StabilityLevelShort, "", usage.StabilityLevel)
133138
cmd.Flags().StringVarP(&opts.outputPath, flag.Output, flag.OutputShort, "", usage.Output)
134139
cmd.Flags().StringVarP(&opts.format, flag.Format, flag.FormatShort, "json", usage.Format)
140+
135141
return cmd
136142
}

tools/cli/internal/openapi/versions.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,24 @@ import (
2222
"github.com/mongodb/openapi/tools/cli/internal/openapi/filter"
2323
)
2424

25+
// ExtractVersionsWithEnv extracts API version Content Type strings from the given OpenAPI specification and environment.
26+
// When env is not set, the function returns the API Versions from all the environments.
2527
func ExtractVersionsWithEnv(oas *openapi3.T, env string) ([]string, error) {
28+
if env == "" {
29+
return extractVersions(oas)
30+
}
31+
2632
// We need to remove the version that are hidden for the given environment
2733
doc, err := filter.ApplyFilters(oas, filter.NewMetadata(nil, env), filter.FiltersToGetVersions)
2834
if err != nil {
29-
return nil, nil
35+
return nil, err
3036
}
3137

32-
return ExtractVersions(doc)
38+
return extractVersions(doc)
3339
}
3440

35-
// ExtractVersions extracts version strings from an OpenAPI specification.
36-
func ExtractVersions(oas *openapi3.T) ([]string, error) {
41+
// extractVersions extracts version strings from an OpenAPI specification.
42+
func extractVersions(oas *openapi3.T) ([]string, error) {
3743
versions := make(map[string]struct{})
3844
for _, pathItem := range oas.Paths.Map() {
3945
if pathItem == nil {

0 commit comments

Comments
 (0)