From 61a43689de092332b7118c15723495a93c41abef Mon Sep 17 00:00:00 2001 From: Andrea Angiolillo Date: Fri, 8 Mar 2024 15:44:43 +0000 Subject: [PATCH] CLOUDP-236398: Adding merge command skeleton (#6) --- tools/cli/go.mod | 6 ++- tools/cli/go.sum | 8 ++++ tools/cli/internal/cli/flag/flag.go | 24 +++++++++++ tools/cli/internal/cli/merge/merge.go | 44 ++++++++++++++++++--- tools/cli/internal/cli/merge/merge_test.go | 30 ++++++++++++++ tools/cli/internal/cli/usage/usage.go | 21 ++++++++++ tools/cli/internal/cli/validator/command.go | 41 +++++++++++++++++++ 7 files changed, 167 insertions(+), 7 deletions(-) create mode 100644 tools/cli/internal/cli/flag/flag.go create mode 100644 tools/cli/internal/cli/merge/merge_test.go create mode 100644 tools/cli/internal/cli/usage/usage.go create mode 100644 tools/cli/internal/cli/validator/command.go diff --git a/tools/cli/go.mod b/tools/cli/go.mod index 6ff94b0..6bf47df 100644 --- a/tools/cli/go.mod +++ b/tools/cli/go.mod @@ -3,12 +3,15 @@ module mongodb/openapi/tools/cli go 1.22.1 require ( + github.com/getkin/kin-openapi v0.120.0 github.com/spf13/cobra v1.8.0 + github.com/stretchr/testify v1.8.4 github.com/tufin/oasdiff v1.9.5 ) require ( - github.com/getkin/kin-openapi v0.120.0 // indirect + cloud.google.com/go v0.110.10 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/go-openapi/jsonpointer v0.20.0 // indirect github.com/go-openapi/swag v0.22.4 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect @@ -17,6 +20,7 @@ require ( github.com/mailru/easyjson v0.7.7 // indirect github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect github.com/perimeterx/marshmallow v1.1.5 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/yargevad/filepathx v1.0.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/tools/cli/go.sum b/tools/cli/go.sum index d89a2c1..3fcc8a5 100644 --- a/tools/cli/go.sum +++ b/tools/cli/go.sum @@ -1,3 +1,7 @@ +cloud.google.com/go v0.110.10 h1:LXy9GEO+timppncPIAZoOj3l58LIU9k+kn48AN7IO3Y= +cloud.google.com/go v0.110.10/go.mod h1:v1OoFqYxiBkUrruItNM3eT4lLByNjxmJSV/xDKJNnic= +github.com/TwiN/go-color v1.4.1 h1:mqG0P/KBgHKVqmtL5ye7K0/Gr4l6hTksPgTgMk3mUzc= +github.com/TwiN/go-color v1.4.1/go.mod h1:WcPf/jtiW95WBIsEeY1Lc/b8aaWoiqQpu5cf8WFxu+s= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -9,6 +13,8 @@ github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogB github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM= github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/invopop/yaml v0.2.0 h1:7zky/qH+O0DwAyoobXUqvVBwgBFRxKoQ/3FjcVpjTMY= @@ -42,6 +48,8 @@ github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0 github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= github.com/yargevad/filepathx v1.0.0 h1:SYcT+N3tYGi+NvazubCNlvgIPbzAk7i7y2dwg3I5FYc= github.com/yargevad/filepathx v1.0.0/go.mod h1:BprfX/gpYNJHJfc35GjRRpVcwWXS89gGulUIU5tK3tA= +golang.org/x/exp v0.0.0-20231108232855-2478ac86f678 h1:mchzmB1XO2pMaKFRqk/+MV3mgGG96aqaPXaMifQU47w= +golang.org/x/exp v0.0.0-20231108232855-2478ac86f678/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/tools/cli/internal/cli/flag/flag.go b/tools/cli/internal/cli/flag/flag.go new file mode 100644 index 0000000..9c9039d --- /dev/null +++ b/tools/cli/internal/cli/flag/flag.go @@ -0,0 +1,24 @@ +// Copyright 2024 MongoDB Inc +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package flag + +const ( + Base = "base" + BaseShort = "b" + External = "external" + ExternalShort = "e" + Output = "output" + OutputShort = "o" +) diff --git a/tools/cli/internal/cli/merge/merge.go b/tools/cli/internal/cli/merge/merge.go index 1aee19b..4f48bdc 100644 --- a/tools/cli/internal/cli/merge/merge.go +++ b/tools/cli/internal/cli/merge/merge.go @@ -15,31 +15,60 @@ package merge import ( + "fmt" + "log" + "mongodb/openapi/tools/cli/internal/cli/flag" + "mongodb/openapi/tools/cli/internal/cli/usage" + "os" + "github.com/spf13/cobra" - "github.com/tufin/oasdiff/load" +) + +const ( + DefaultOutputFileName = "FOAS.json" ) type Opts struct { - Base *load.SpecInfo + basePath string + outputPath string + externalPaths []string } func (o *Opts) Run(_ []string) error { // To add in follow up PR: CLOUDP-225849 - return nil + return o.saveFile([]byte("test")) } func (o *Opts) PreRunE(_ []string) error { - // To Add in follow up PR: CLOUDP-225849 + if o.basePath == "" { + return fmt.Errorf("no base OAS detected. Please, use the flag %s to include the base OAS", flag.Base) + } + + if o.externalPaths == nil { + return fmt.Errorf("no external OAS detected. Please, use the flag %s to include at least one OAS", flag.External) + } + + return nil +} + +func (o *Opts) saveFile(data []byte) error { + if err := os.WriteFile(o.outputPath, data, 0o600); err != nil { + return err + } + + log.Printf("\nMerged spec was saved in '%s'.\n\n", o.outputPath) return nil } +// Builder builds the merge command with the following signature: +// merge -b base-oas -e external-oas-1 -e external-oas-2 func Builder() *cobra.Command { opts := &Opts{} cmd := &cobra.Command{ - Use: "merge [base-spec] [spec-1] [spec-2] [spec-3] ... [spec-n]", + Use: "merge -b base-spec [-e spec]...", Short: "Merge Open API specifications into a base spec.", - Args: cobra.MinimumNArgs(2), + Args: cobra.NoArgs, PreRunE: func(_ *cobra.Command, args []string) error { return opts.PreRunE(args) }, @@ -48,5 +77,8 @@ func Builder() *cobra.Command { }, } + cmd.Flags().StringVarP(&opts.basePath, flag.Base, flag.BaseShort, "", usage.Base) + cmd.Flags().StringArrayVarP(&opts.externalPaths, flag.External, flag.ExternalShort, nil, usage.External) + cmd.Flags().StringVarP(&opts.outputPath, flag.Output, flag.OutputShort, DefaultOutputFileName, usage.Output) return cmd } diff --git a/tools/cli/internal/cli/merge/merge_test.go b/tools/cli/internal/cli/merge/merge_test.go new file mode 100644 index 0000000..c53a7c9 --- /dev/null +++ b/tools/cli/internal/cli/merge/merge_test.go @@ -0,0 +1,30 @@ +// Copyright 2024 MongoDB Inc +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package merge + +import ( + "mongodb/openapi/tools/cli/internal/cli/flag" + "mongodb/openapi/tools/cli/internal/cli/validator" + "testing" +) + +func TestCreateBuilder(t *testing.T) { + validator.ValidateSubCommandsAndFlags( + t, + Builder(), + 0, + []string{flag.Base, flag.External, flag.Output}, + ) +} diff --git a/tools/cli/internal/cli/usage/usage.go b/tools/cli/internal/cli/usage/usage.go new file mode 100644 index 0000000..10bef7e --- /dev/null +++ b/tools/cli/internal/cli/usage/usage.go @@ -0,0 +1,21 @@ +// Copyright 2024 MongoDB Inc +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package usage + +const ( + Base = "Base OAS. The command will merge other OASes into it." + External = "OASes that will be merged into the base OAS." + Output = "File name where the command will store the output." +) diff --git a/tools/cli/internal/cli/validator/command.go b/tools/cli/internal/cli/validator/command.go new file mode 100644 index 0000000..f1eba14 --- /dev/null +++ b/tools/cli/internal/cli/validator/command.go @@ -0,0 +1,41 @@ +// Copyright 2024 MongoDB Inc +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package validator + +import ( + "testing" + + "github.com/spf13/cobra" + "github.com/stretchr/testify/assert" +) + +// ValidateSubCommandsAndFlags validates a cobra.Command, verifying the number of sub commands +// and the flags that are being defined for it. +func ValidateSubCommandsAndFlags(t *testing.T, subject *cobra.Command, nSubCommands int, flags []string) { + t.Helper() + a := assert.New(t) + if len(subject.Commands()) != nSubCommands { + t.Errorf("Sub command count mismatch. Expected %d, got %d. "+ + "Check the CmdValidator for your command.\n", nSubCommands, len(subject.Commands())) + } + if len(flags) == 0 { + a.False(subject.HasAvailableFlags(), "expected command to not have flags but it does") + return + } + a.True(subject.HasAvailableFlags(), "expected command to have flag but has none") + for _, f := range flags { + a.NotNilf(subject.Flags().Lookup(f), "command has no flag: %s", f) + } +}